aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/grpc/generated/voice_agent.pb.dart70
-rw-r--r--lib/grpc/generated/voice_agent.pbenum.dart30
-rw-r--r--lib/grpc/generated/voice_agent.pbgrpc.dart176
-rw-r--r--lib/grpc/generated/voice_agent.pbjson.dart74
-rw-r--r--lib/main.dart3
-rw-r--r--lib/models/app_state.dart2
-rw-r--r--lib/protos/voice_agent.proto14
-rw-r--r--lib/screens/home_screen.dart380
-rw-r--r--lib/screens/loading_screen.dart81
-rw-r--r--lib/widgets/assistant_mode_choice.dart8
-rw-r--r--lib/widgets/nlu_engine_choice.dart6
-rw-r--r--lib/widgets/online_mode_choice.dart148
-rw-r--r--lib/widgets/stt_model_choice.dart148
13 files changed, 926 insertions, 214 deletions
diff --git a/lib/grpc/generated/voice_agent.pb.dart b/lib/grpc/generated/voice_agent.pb.dart
index 2c0f9fa..892b95e 100644
--- a/lib/grpc/generated/voice_agent.pb.dart
+++ b/lib/grpc/generated/voice_agent.pb.dart
@@ -9,6 +9,7 @@
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
+import 'dart:async' as $async;
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
@@ -274,6 +275,7 @@ class S_RecognizeVoiceControl extends $pb.GeneratedMessage {
VoiceAudio? audioStream,
NLUModel? nluModel,
$core.String? streamId,
+ STTFramework? sttFramework,
}) {
final $result = create();
if (audioStream != null) {
@@ -285,6 +287,9 @@ class S_RecognizeVoiceControl extends $pb.GeneratedMessage {
if (streamId != null) {
$result.streamId = streamId;
}
+ if (sttFramework != null) {
+ $result.sttFramework = sttFramework;
+ }
return $result;
}
S_RecognizeVoiceControl._() : super();
@@ -295,6 +300,7 @@ class S_RecognizeVoiceControl extends $pb.GeneratedMessage {
..aOM<VoiceAudio>(1, _omitFieldNames ? '' : 'audioStream', subBuilder: VoiceAudio.create)
..e<NLUModel>(2, _omitFieldNames ? '' : 'nluModel', $pb.PbFieldType.OE, defaultOrMaker: NLUModel.SNIPS, valueOf: NLUModel.valueOf, enumValues: NLUModel.values)
..aOS(3, _omitFieldNames ? '' : 'streamId')
+ ..e<STTFramework>(4, _omitFieldNames ? '' : 'sttFramework', $pb.PbFieldType.OE, defaultOrMaker: STTFramework.VOSK, valueOf: STTFramework.valueOf, enumValues: STTFramework.values)
..hasRequiredFields = false
;
@@ -347,6 +353,15 @@ class S_RecognizeVoiceControl extends $pb.GeneratedMessage {
$core.bool hasStreamId() => $_has(2);
@$pb.TagNumber(3)
void clearStreamId() => clearField(3);
+
+ @$pb.TagNumber(4)
+ STTFramework get sttFramework => $_getN(3);
+ @$pb.TagNumber(4)
+ set sttFramework(STTFramework v) { setField(4, v); }
+ @$pb.TagNumber(4)
+ $core.bool hasSttFramework() => $_has(3);
+ @$pb.TagNumber(4)
+ void clearSttFramework() => clearField(4);
}
class RecognizeVoiceControl extends $pb.GeneratedMessage {
@@ -355,6 +370,8 @@ class RecognizeVoiceControl extends $pb.GeneratedMessage {
NLUModel? nluModel,
RecordMode? recordMode,
$core.String? streamId,
+ STTFramework? sttFramework,
+ OnlineMode? onlineMode,
}) {
final $result = create();
if (action != null) {
@@ -369,6 +386,12 @@ class RecognizeVoiceControl extends $pb.GeneratedMessage {
if (streamId != null) {
$result.streamId = streamId;
}
+ if (sttFramework != null) {
+ $result.sttFramework = sttFramework;
+ }
+ if (onlineMode != null) {
+ $result.onlineMode = onlineMode;
+ }
return $result;
}
RecognizeVoiceControl._() : super();
@@ -380,6 +403,8 @@ class RecognizeVoiceControl extends $pb.GeneratedMessage {
..e<NLUModel>(2, _omitFieldNames ? '' : 'nluModel', $pb.PbFieldType.OE, defaultOrMaker: NLUModel.SNIPS, valueOf: NLUModel.valueOf, enumValues: NLUModel.values)
..e<RecordMode>(3, _omitFieldNames ? '' : 'recordMode', $pb.PbFieldType.OE, defaultOrMaker: RecordMode.MANUAL, valueOf: RecordMode.valueOf, enumValues: RecordMode.values)
..aOS(4, _omitFieldNames ? '' : 'streamId')
+ ..e<STTFramework>(5, _omitFieldNames ? '' : 'sttFramework', $pb.PbFieldType.OE, defaultOrMaker: STTFramework.VOSK, valueOf: STTFramework.valueOf, enumValues: STTFramework.values)
+ ..e<OnlineMode>(6, _omitFieldNames ? '' : 'onlineMode', $pb.PbFieldType.OE, defaultOrMaker: OnlineMode.ONLINE, valueOf: OnlineMode.valueOf, enumValues: OnlineMode.values)
..hasRequiredFields = false
;
@@ -439,6 +464,24 @@ class RecognizeVoiceControl extends $pb.GeneratedMessage {
$core.bool hasStreamId() => $_has(3);
@$pb.TagNumber(4)
void clearStreamId() => clearField(4);
+
+ @$pb.TagNumber(5)
+ STTFramework get sttFramework => $_getN(4);
+ @$pb.TagNumber(5)
+ set sttFramework(STTFramework v) { setField(5, v); }
+ @$pb.TagNumber(5)
+ $core.bool hasSttFramework() => $_has(4);
+ @$pb.TagNumber(5)
+ void clearSttFramework() => clearField(5);
+
+ @$pb.TagNumber(6)
+ OnlineMode get onlineMode => $_getN(5);
+ @$pb.TagNumber(6)
+ set onlineMode(OnlineMode v) { setField(6, v); }
+ @$pb.TagNumber(6)
+ $core.bool hasOnlineMode() => $_has(5);
+ @$pb.TagNumber(6)
+ void clearOnlineMode() => clearField(6);
}
class RecognizeTextControl extends $pb.GeneratedMessage {
@@ -791,6 +834,33 @@ class ExecuteResult extends $pb.GeneratedMessage {
void clearStatus() => clearField(2);
}
+class VoiceAgentServiceApi {
+ $pb.RpcClient _client;
+ VoiceAgentServiceApi(this._client);
+
+ $async.Future<ServiceStatus> checkServiceStatus($pb.ClientContext? ctx, Empty request) =>
+ _client.invoke<ServiceStatus>(ctx, 'VoiceAgentService', 'CheckServiceStatus', request, ServiceStatus())
+ ;
+ $async.Future<WakeWordStatus> s_DetectWakeWord($pb.ClientContext? ctx, VoiceAudio request) =>
+ _client.invoke<WakeWordStatus>(ctx, 'VoiceAgentService', 'S_DetectWakeWord', request, WakeWordStatus())
+ ;
+ $async.Future<WakeWordStatus> detectWakeWord($pb.ClientContext? ctx, Empty request) =>
+ _client.invoke<WakeWordStatus>(ctx, 'VoiceAgentService', 'DetectWakeWord', request, WakeWordStatus())
+ ;
+ $async.Future<RecognizeResult> s_RecognizeVoiceCommand($pb.ClientContext? ctx, S_RecognizeVoiceControl request) =>
+ _client.invoke<RecognizeResult>(ctx, 'VoiceAgentService', 'S_RecognizeVoiceCommand', request, RecognizeResult())
+ ;
+ $async.Future<RecognizeResult> recognizeVoiceCommand($pb.ClientContext? ctx, RecognizeVoiceControl request) =>
+ _client.invoke<RecognizeResult>(ctx, 'VoiceAgentService', 'RecognizeVoiceCommand', request, RecognizeResult())
+ ;
+ $async.Future<RecognizeResult> recognizeTextCommand($pb.ClientContext? ctx, RecognizeTextControl request) =>
+ _client.invoke<RecognizeResult>(ctx, 'VoiceAgentService', 'RecognizeTextCommand', request, RecognizeResult())
+ ;
+ $async.Future<ExecuteResult> executeCommand($pb.ClientContext? ctx, ExecuteInput request) =>
+ _client.invoke<ExecuteResult>(ctx, 'VoiceAgentService', 'ExecuteCommand', request, ExecuteResult())
+ ;
+}
+
const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names');
const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names');
diff --git a/lib/grpc/generated/voice_agent.pbenum.dart b/lib/grpc/generated/voice_agent.pbenum.dart
index 78da13f..51e7427 100644
--- a/lib/grpc/generated/voice_agent.pbenum.dart
+++ b/lib/grpc/generated/voice_agent.pbenum.dart
@@ -13,6 +13,36 @@ import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
+class STTFramework extends $pb.ProtobufEnum {
+ static const STTFramework VOSK = STTFramework._(0, _omitEnumNames ? '' : 'VOSK');
+ static const STTFramework WHISPER = STTFramework._(1, _omitEnumNames ? '' : 'WHISPER');
+
+ static const $core.List<STTFramework> values = <STTFramework> [
+ VOSK,
+ WHISPER,
+ ];
+
+ static final $core.Map<$core.int, STTFramework> _byValue = $pb.ProtobufEnum.initByValue(values);
+ static STTFramework? valueOf($core.int value) => _byValue[value];
+
+ const STTFramework._($core.int v, $core.String n) : super(v, n);
+}
+
+class OnlineMode extends $pb.ProtobufEnum {
+ static const OnlineMode ONLINE = OnlineMode._(0, _omitEnumNames ? '' : 'ONLINE');
+ static const OnlineMode OFFLINE = OnlineMode._(1, _omitEnumNames ? '' : 'OFFLINE');
+
+ static const $core.List<OnlineMode> values = <OnlineMode> [
+ ONLINE,
+ OFFLINE,
+ ];
+
+ static final $core.Map<$core.int, OnlineMode> _byValue = $pb.ProtobufEnum.initByValue(values);
+ static OnlineMode? valueOf($core.int value) => _byValue[value];
+
+ const OnlineMode._($core.int v, $core.String n) : super(v, n);
+}
+
class RecordAction extends $pb.ProtobufEnum {
static const RecordAction START = RecordAction._(0, _omitEnumNames ? '' : 'START');
static const RecordAction STOP = RecordAction._(1, _omitEnumNames ? '' : 'STOP');
diff --git a/lib/grpc/generated/voice_agent.pbgrpc.dart b/lib/grpc/generated/voice_agent.pbgrpc.dart
index 502c797..5b31b44 100644
--- a/lib/grpc/generated/voice_agent.pbgrpc.dart
+++ b/lib/grpc/generated/voice_agent.pbgrpc.dart
@@ -21,92 +21,66 @@ export 'voice_agent.pb.dart';
// @$pb.GrpcServiceName('VoiceAgentService')
class VoiceAgentServiceClient extends $grpc.Client {
- static final _$checkServiceStatus =
- $grpc.ClientMethod<$0.Empty, $0.ServiceStatus>(
- '/VoiceAgentService/CheckServiceStatus',
- ($0.Empty value) => value.writeToBuffer(),
- ($core.List<$core.int> value) => $0.ServiceStatus.fromBuffer(value));
- static final _$s_DetectWakeWord =
- $grpc.ClientMethod<$0.VoiceAudio, $0.WakeWordStatus>(
- '/VoiceAgentService/S_DetectWakeWord',
- ($0.VoiceAudio value) => value.writeToBuffer(),
- ($core.List<$core.int> value) => $0.WakeWordStatus.fromBuffer(value));
- static final _$detectWakeWord =
- $grpc.ClientMethod<$0.Empty, $0.WakeWordStatus>(
- '/VoiceAgentService/DetectWakeWord',
- ($0.Empty value) => value.writeToBuffer(),
- ($core.List<$core.int> value) => $0.WakeWordStatus.fromBuffer(value));
- static final _$s_RecognizeVoiceCommand =
- $grpc.ClientMethod<$0.S_RecognizeVoiceControl, $0.RecognizeResult>(
- '/VoiceAgentService/S_RecognizeVoiceCommand',
- ($0.S_RecognizeVoiceControl value) => value.writeToBuffer(),
- ($core.List<$core.int> value) =>
- $0.RecognizeResult.fromBuffer(value));
- static final _$recognizeVoiceCommand =
- $grpc.ClientMethod<$0.RecognizeVoiceControl, $0.RecognizeResult>(
- '/VoiceAgentService/RecognizeVoiceCommand',
- ($0.RecognizeVoiceControl value) => value.writeToBuffer(),
- ($core.List<$core.int> value) =>
- $0.RecognizeResult.fromBuffer(value));
- static final _$recognizeTextCommand =
- $grpc.ClientMethod<$0.RecognizeTextControl, $0.RecognizeResult>(
- '/VoiceAgentService/RecognizeTextCommand',
- ($0.RecognizeTextControl value) => value.writeToBuffer(),
- ($core.List<$core.int> value) =>
- $0.RecognizeResult.fromBuffer(value));
- static final _$executeCommand =
- $grpc.ClientMethod<$0.ExecuteInput, $0.ExecuteResult>(
- '/VoiceAgentService/ExecuteCommand',
- ($0.ExecuteInput value) => value.writeToBuffer(),
- ($core.List<$core.int> value) => $0.ExecuteResult.fromBuffer(value));
+ static final _$checkServiceStatus = $grpc.ClientMethod<$0.Empty, $0.ServiceStatus>(
+ '/VoiceAgentService/CheckServiceStatus',
+ ($0.Empty value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.ServiceStatus.fromBuffer(value));
+ static final _$s_DetectWakeWord = $grpc.ClientMethod<$0.VoiceAudio, $0.WakeWordStatus>(
+ '/VoiceAgentService/S_DetectWakeWord',
+ ($0.VoiceAudio value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.WakeWordStatus.fromBuffer(value));
+ static final _$detectWakeWord = $grpc.ClientMethod<$0.Empty, $0.WakeWordStatus>(
+ '/VoiceAgentService/DetectWakeWord',
+ ($0.Empty value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.WakeWordStatus.fromBuffer(value));
+ static final _$s_RecognizeVoiceCommand = $grpc.ClientMethod<$0.S_RecognizeVoiceControl, $0.RecognizeResult>(
+ '/VoiceAgentService/S_RecognizeVoiceCommand',
+ ($0.S_RecognizeVoiceControl value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.RecognizeResult.fromBuffer(value));
+ static final _$recognizeVoiceCommand = $grpc.ClientMethod<$0.RecognizeVoiceControl, $0.RecognizeResult>(
+ '/VoiceAgentService/RecognizeVoiceCommand',
+ ($0.RecognizeVoiceControl value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.RecognizeResult.fromBuffer(value));
+ static final _$recognizeTextCommand = $grpc.ClientMethod<$0.RecognizeTextControl, $0.RecognizeResult>(
+ '/VoiceAgentService/RecognizeTextCommand',
+ ($0.RecognizeTextControl value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.RecognizeResult.fromBuffer(value));
+ static final _$executeCommand = $grpc.ClientMethod<$0.ExecuteInput, $0.ExecuteResult>(
+ '/VoiceAgentService/ExecuteCommand',
+ ($0.ExecuteInput value) => value.writeToBuffer(),
+ ($core.List<$core.int> value) => $0.ExecuteResult.fromBuffer(value));
VoiceAgentServiceClient($grpc.ClientChannel channel,
{$grpc.CallOptions? options,
$core.Iterable<$grpc.ClientInterceptor>? interceptors})
- : super(channel, options: options, interceptors: interceptors);
+ : super(channel, options: options,
+ interceptors: interceptors);
- $grpc.ResponseFuture<$0.ServiceStatus> checkServiceStatus($0.Empty request,
- {$grpc.CallOptions? options}) {
+ $grpc.ResponseFuture<$0.ServiceStatus> checkServiceStatus($0.Empty request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$checkServiceStatus, request, options: options);
}
- $grpc.ResponseStream<$0.WakeWordStatus> s_DetectWakeWord(
- $async.Stream<$0.VoiceAudio> request,
- {$grpc.CallOptions? options}) {
+ $grpc.ResponseStream<$0.WakeWordStatus> s_DetectWakeWord($async.Stream<$0.VoiceAudio> request, {$grpc.CallOptions? options}) {
return $createStreamingCall(_$s_DetectWakeWord, request, options: options);
}
- $grpc.ResponseStream<$0.WakeWordStatus> detectWakeWord($0.Empty request,
- {$grpc.CallOptions? options}) {
- return $createStreamingCall(
- _$detectWakeWord, $async.Stream.fromIterable([request]),
- options: options);
+ $grpc.ResponseStream<$0.WakeWordStatus> detectWakeWord($0.Empty request, {$grpc.CallOptions? options}) {
+ return $createStreamingCall(_$detectWakeWord, $async.Stream.fromIterable([request]), options: options);
}
- $grpc.ResponseFuture<$0.RecognizeResult> s_RecognizeVoiceCommand(
- $async.Stream<$0.S_RecognizeVoiceControl> request,
- {$grpc.CallOptions? options}) {
- return $createStreamingCall(_$s_RecognizeVoiceCommand, request,
- options: options)
- .single;
+ $grpc.ResponseFuture<$0.RecognizeResult> s_RecognizeVoiceCommand($async.Stream<$0.S_RecognizeVoiceControl> request, {$grpc.CallOptions? options}) {
+ return $createStreamingCall(_$s_RecognizeVoiceCommand, request, options: options).single;
}
- $grpc.ResponseFuture<$0.RecognizeResult> recognizeVoiceCommand(
- $async.Stream<$0.RecognizeVoiceControl> request,
- {$grpc.CallOptions? options}) {
- return $createStreamingCall(_$recognizeVoiceCommand, request,
- options: options)
- .single;
+ $grpc.ResponseFuture<$0.RecognizeResult> recognizeVoiceCommand($async.Stream<$0.RecognizeVoiceControl> request, {$grpc.CallOptions? options}) {
+ return $createStreamingCall(_$recognizeVoiceCommand, request, options: options).single;
}
- $grpc.ResponseFuture<$0.RecognizeResult> recognizeTextCommand(
- $0.RecognizeTextControl request,
- {$grpc.CallOptions? options}) {
+ $grpc.ResponseFuture<$0.RecognizeResult> recognizeTextCommand($0.RecognizeTextControl request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$recognizeTextCommand, request, options: options);
}
- $grpc.ResponseFuture<$0.ExecuteResult> executeCommand($0.ExecuteInput request,
- {$grpc.CallOptions? options}) {
+ $grpc.ResponseFuture<$0.ExecuteResult> executeCommand($0.ExecuteInput request, {$grpc.CallOptions? options}) {
return $createUnaryCall(_$executeCommand, request, options: options);
}
}
@@ -137,31 +111,26 @@ abstract class VoiceAgentServiceBase extends $grpc.Service {
true,
($core.List<$core.int> value) => $0.Empty.fromBuffer(value),
($0.WakeWordStatus value) => value.writeToBuffer()));
- $addMethod(
- $grpc.ServiceMethod<$0.S_RecognizeVoiceControl, $0.RecognizeResult>(
- 'S_RecognizeVoiceCommand',
- s_RecognizeVoiceCommand,
- true,
- false,
- ($core.List<$core.int> value) =>
- $0.S_RecognizeVoiceControl.fromBuffer(value),
- ($0.RecognizeResult value) => value.writeToBuffer()));
- $addMethod(
- $grpc.ServiceMethod<$0.RecognizeVoiceControl, $0.RecognizeResult>(
- 'RecognizeVoiceCommand',
- recognizeVoiceCommand,
- true,
- false,
- ($core.List<$core.int> value) =>
- $0.RecognizeVoiceControl.fromBuffer(value),
- ($0.RecognizeResult value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.S_RecognizeVoiceControl, $0.RecognizeResult>(
+ 'S_RecognizeVoiceCommand',
+ s_RecognizeVoiceCommand,
+ true,
+ false,
+ ($core.List<$core.int> value) => $0.S_RecognizeVoiceControl.fromBuffer(value),
+ ($0.RecognizeResult value) => value.writeToBuffer()));
+ $addMethod($grpc.ServiceMethod<$0.RecognizeVoiceControl, $0.RecognizeResult>(
+ 'RecognizeVoiceCommand',
+ recognizeVoiceCommand,
+ true,
+ false,
+ ($core.List<$core.int> value) => $0.RecognizeVoiceControl.fromBuffer(value),
+ ($0.RecognizeResult value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$0.RecognizeTextControl, $0.RecognizeResult>(
'RecognizeTextCommand',
recognizeTextCommand_Pre,
false,
false,
- ($core.List<$core.int> value) =>
- $0.RecognizeTextControl.fromBuffer(value),
+ ($core.List<$core.int> value) => $0.RecognizeTextControl.fromBuffer(value),
($0.RecognizeResult value) => value.writeToBuffer()));
$addMethod($grpc.ServiceMethod<$0.ExecuteInput, $0.ExecuteResult>(
'ExecuteCommand',
@@ -172,40 +141,27 @@ abstract class VoiceAgentServiceBase extends $grpc.Service {
($0.ExecuteResult value) => value.writeToBuffer()));
}
- $async.Future<$0.ServiceStatus> checkServiceStatus_Pre(
- $grpc.ServiceCall call, $async.Future<$0.Empty> request) async {
+ $async.Future<$0.ServiceStatus> checkServiceStatus_Pre($grpc.ServiceCall call, $async.Future<$0.Empty> request) async {
return checkServiceStatus(call, await request);
}
- $async.Stream<$0.WakeWordStatus> detectWakeWord_Pre(
- $grpc.ServiceCall call, $async.Future<$0.Empty> request) async* {
+ $async.Stream<$0.WakeWordStatus> detectWakeWord_Pre($grpc.ServiceCall call, $async.Future<$0.Empty> request) async* {
yield* detectWakeWord(call, await request);
}
- $async.Future<$0.RecognizeResult> recognizeTextCommand_Pre(
- $grpc.ServiceCall call,
- $async.Future<$0.RecognizeTextControl> request) async {
+ $async.Future<$0.RecognizeResult> recognizeTextCommand_Pre($grpc.ServiceCall call, $async.Future<$0.RecognizeTextControl> request) async {
return recognizeTextCommand(call, await request);
}
- $async.Future<$0.ExecuteResult> executeCommand_Pre(
- $grpc.ServiceCall call, $async.Future<$0.ExecuteInput> request) async {
+ $async.Future<$0.ExecuteResult> executeCommand_Pre($grpc.ServiceCall call, $async.Future<$0.ExecuteInput> request) async {
return executeCommand(call, await request);
}
- $async.Future<$0.ServiceStatus> checkServiceStatus(
- $grpc.ServiceCall call, $0.Empty request);
- $async.Stream<$0.WakeWordStatus> s_DetectWakeWord(
- $grpc.ServiceCall call, $async.Stream<$0.VoiceAudio> request);
- $async.Stream<$0.WakeWordStatus> detectWakeWord(
- $grpc.ServiceCall call, $0.Empty request);
- $async.Future<$0.RecognizeResult> s_RecognizeVoiceCommand(
- $grpc.ServiceCall call,
- $async.Stream<$0.S_RecognizeVoiceControl> request);
- $async.Future<$0.RecognizeResult> recognizeVoiceCommand(
- $grpc.ServiceCall call, $async.Stream<$0.RecognizeVoiceControl> request);
- $async.Future<$0.RecognizeResult> recognizeTextCommand(
- $grpc.ServiceCall call, $0.RecognizeTextControl request);
- $async.Future<$0.ExecuteResult> executeCommand(
- $grpc.ServiceCall call, $0.ExecuteInput request);
+ $async.Future<$0.ServiceStatus> checkServiceStatus($grpc.ServiceCall call, $0.Empty request);
+ $async.Stream<$0.WakeWordStatus> s_DetectWakeWord($grpc.ServiceCall call, $async.Stream<$0.VoiceAudio> request);
+ $async.Stream<$0.WakeWordStatus> detectWakeWord($grpc.ServiceCall call, $0.Empty request);
+ $async.Future<$0.RecognizeResult> s_RecognizeVoiceCommand($grpc.ServiceCall call, $async.Stream<$0.S_RecognizeVoiceControl> request);
+ $async.Future<$0.RecognizeResult> recognizeVoiceCommand($grpc.ServiceCall call, $async.Stream<$0.RecognizeVoiceControl> request);
+ $async.Future<$0.RecognizeResult> recognizeTextCommand($grpc.ServiceCall call, $0.RecognizeTextControl request);
+ $async.Future<$0.ExecuteResult> executeCommand($grpc.ServiceCall call, $0.ExecuteInput request);
}
diff --git a/lib/grpc/generated/voice_agent.pbjson.dart b/lib/grpc/generated/voice_agent.pbjson.dart
index 6fa9502..1b8365d 100644
--- a/lib/grpc/generated/voice_agent.pbjson.dart
+++ b/lib/grpc/generated/voice_agent.pbjson.dart
@@ -13,6 +13,32 @@ import 'dart:convert' as $convert;
import 'dart:core' as $core;
import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use sTTFrameworkDescriptor instead')
+const STTFramework$json = {
+ '1': 'STTFramework',
+ '2': [
+ {'1': 'VOSK', '2': 0},
+ {'1': 'WHISPER', '2': 1},
+ ],
+};
+
+/// Descriptor for `STTFramework`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List sTTFrameworkDescriptor = $convert.base64Decode(
+ 'CgxTVFRGcmFtZXdvcmsSCAoEVk9TSxAAEgsKB1dISVNQRVIQAQ==');
+
+@$core.Deprecated('Use onlineModeDescriptor instead')
+const OnlineMode$json = {
+ '1': 'OnlineMode',
+ '2': [
+ {'1': 'ONLINE', '2': 0},
+ {'1': 'OFFLINE', '2': 1},
+ ],
+};
+
+/// Descriptor for `OnlineMode`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List onlineModeDescriptor = $convert.base64Decode(
+ 'CgpPbmxpbmVNb2RlEgoKBk9OTElORRAAEgsKB09GRkxJTkUQAQ==');
+
@$core.Deprecated('Use recordActionDescriptor instead')
const RecordAction$json = {
'1': 'RecordAction',
@@ -151,6 +177,7 @@ const S_RecognizeVoiceControl$json = {
{'1': 'audio_stream', '3': 1, '4': 1, '5': 11, '6': '.VoiceAudio', '10': 'audioStream'},
{'1': 'nlu_model', '3': 2, '4': 1, '5': 14, '6': '.NLUModel', '10': 'nluModel'},
{'1': 'stream_id', '3': 3, '4': 1, '5': 9, '10': 'streamId'},
+ {'1': 'stt_framework', '3': 4, '4': 1, '5': 14, '6': '.STTFramework', '10': 'sttFramework'},
],
};
@@ -158,7 +185,8 @@ const S_RecognizeVoiceControl$json = {
final $typed_data.Uint8List s_RecognizeVoiceControlDescriptor = $convert.base64Decode(
'ChdTX1JlY29nbml6ZVZvaWNlQ29udHJvbBIuCgxhdWRpb19zdHJlYW0YASABKAsyCy5Wb2ljZU'
'F1ZGlvUgthdWRpb1N0cmVhbRImCglubHVfbW9kZWwYAiABKA4yCS5OTFVNb2RlbFIIbmx1TW9k'
- 'ZWwSGwoJc3RyZWFtX2lkGAMgASgJUghzdHJlYW1JZA==');
+ 'ZWwSGwoJc3RyZWFtX2lkGAMgASgJUghzdHJlYW1JZBIyCg1zdHRfZnJhbWV3b3JrGAQgASgOMg'
+ '0uU1RURnJhbWV3b3JrUgxzdHRGcmFtZXdvcms=');
@$core.Deprecated('Use recognizeVoiceControlDescriptor instead')
const RecognizeVoiceControl$json = {
@@ -168,6 +196,8 @@ const RecognizeVoiceControl$json = {
{'1': 'nlu_model', '3': 2, '4': 1, '5': 14, '6': '.NLUModel', '10': 'nluModel'},
{'1': 'record_mode', '3': 3, '4': 1, '5': 14, '6': '.RecordMode', '10': 'recordMode'},
{'1': 'stream_id', '3': 4, '4': 1, '5': 9, '10': 'streamId'},
+ {'1': 'stt_framework', '3': 5, '4': 1, '5': 14, '6': '.STTFramework', '10': 'sttFramework'},
+ {'1': 'online_mode', '3': 6, '4': 1, '5': 14, '6': '.OnlineMode', '10': 'onlineMode'},
],
};
@@ -176,7 +206,8 @@ final $typed_data.Uint8List recognizeVoiceControlDescriptor = $convert.base64Dec
'ChVSZWNvZ25pemVWb2ljZUNvbnRyb2wSJQoGYWN0aW9uGAEgASgOMg0uUmVjb3JkQWN0aW9uUg'
'ZhY3Rpb24SJgoJbmx1X21vZGVsGAIgASgOMgkuTkxVTW9kZWxSCG5sdU1vZGVsEiwKC3JlY29y'
'ZF9tb2RlGAMgASgOMgsuUmVjb3JkTW9kZVIKcmVjb3JkTW9kZRIbCglzdHJlYW1faWQYBCABKA'
- 'lSCHN0cmVhbUlk');
+ 'lSCHN0cmVhbUlkEjIKDXN0dF9mcmFtZXdvcmsYBSABKA4yDS5TVFRGcmFtZXdvcmtSDHN0dEZy'
+ 'YW1ld29yaxIsCgtvbmxpbmVfbW9kZRgGIAEoDjILLk9ubGluZU1vZGVSCm9ubGluZU1vZGU=');
@$core.Deprecated('Use recognizeTextControlDescriptor instead')
const RecognizeTextControl$json = {
@@ -252,3 +283,42 @@ final $typed_data.Uint8List executeResultDescriptor = $convert.base64Decode(
'Cg1FeGVjdXRlUmVzdWx0EhoKCHJlc3BvbnNlGAEgASgJUghyZXNwb25zZRIqCgZzdGF0dXMYAi'
'ABKA4yEi5FeGVjdXRlU3RhdHVzVHlwZVIGc3RhdHVz');
+const $core.Map<$core.String, $core.dynamic> VoiceAgentServiceBase$json = {
+ '1': 'VoiceAgentService',
+ '2': [
+ {'1': 'CheckServiceStatus', '2': '.Empty', '3': '.ServiceStatus'},
+ {'1': 'S_DetectWakeWord', '2': '.VoiceAudio', '3': '.WakeWordStatus', '5': true, '6': true},
+ {'1': 'DetectWakeWord', '2': '.Empty', '3': '.WakeWordStatus', '6': true},
+ {'1': 'S_RecognizeVoiceCommand', '2': '.S_RecognizeVoiceControl', '3': '.RecognizeResult', '5': true},
+ {'1': 'RecognizeVoiceCommand', '2': '.RecognizeVoiceControl', '3': '.RecognizeResult', '5': true},
+ {'1': 'RecognizeTextCommand', '2': '.RecognizeTextControl', '3': '.RecognizeResult'},
+ {'1': 'ExecuteCommand', '2': '.ExecuteInput', '3': '.ExecuteResult'},
+ ],
+};
+
+@$core.Deprecated('Use voiceAgentServiceDescriptor instead')
+const $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> VoiceAgentServiceBase$messageJson = {
+ '.Empty': Empty$json,
+ '.ServiceStatus': ServiceStatus$json,
+ '.VoiceAudio': VoiceAudio$json,
+ '.WakeWordStatus': WakeWordStatus$json,
+ '.S_RecognizeVoiceControl': S_RecognizeVoiceControl$json,
+ '.RecognizeResult': RecognizeResult$json,
+ '.IntentSlot': IntentSlot$json,
+ '.RecognizeVoiceControl': RecognizeVoiceControl$json,
+ '.RecognizeTextControl': RecognizeTextControl$json,
+ '.ExecuteInput': ExecuteInput$json,
+ '.ExecuteResult': ExecuteResult$json,
+};
+
+/// Descriptor for `VoiceAgentService`. Decode as a `google.protobuf.ServiceDescriptorProto`.
+final $typed_data.Uint8List voiceAgentServiceDescriptor = $convert.base64Decode(
+ 'ChFWb2ljZUFnZW50U2VydmljZRIsChJDaGVja1NlcnZpY2VTdGF0dXMSBi5FbXB0eRoOLlNlcn'
+ 'ZpY2VTdGF0dXMSNAoQU19EZXRlY3RXYWtlV29yZBILLlZvaWNlQXVkaW8aDy5XYWtlV29yZFN0'
+ 'YXR1cygBMAESKwoORGV0ZWN0V2FrZVdvcmQSBi5FbXB0eRoPLldha2VXb3JkU3RhdHVzMAESRw'
+ 'oXU19SZWNvZ25pemVWb2ljZUNvbW1hbmQSGC5TX1JlY29nbml6ZVZvaWNlQ29udHJvbBoQLlJl'
+ 'Y29nbml6ZVJlc3VsdCgBEkMKFVJlY29nbml6ZVZvaWNlQ29tbWFuZBIWLlJlY29nbml6ZVZvaW'
+ 'NlQ29udHJvbBoQLlJlY29nbml6ZVJlc3VsdCgBEj8KFFJlY29nbml6ZVRleHRDb21tYW5kEhUu'
+ 'UmVjb2duaXplVGV4dENvbnRyb2waEC5SZWNvZ25pemVSZXN1bHQSLwoORXhlY3V0ZUNvbW1hbm'
+ 'QSDS5FeGVjdXRlSW5wdXQaDi5FeGVjdXRlUmVzdWx0');
+
diff --git a/lib/main.dart b/lib/main.dart
index 9dfbd54..6349d8d 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'package:flutter_voiceassistant/screens/loading_screen.dart';
import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'models/app_state.dart';
@@ -103,7 +104,7 @@ class App extends StatelessWidget {
Consumer<ServiceStatusProvider>(
builder: (context, provider, child) {
return provider.isServiceOnline
- ? HomePage(config: config, wakeWord: provider.wakeWord)
+ ? Loading(config: config, wakeWord: provider.wakeWord)
: ErrorScreen(
onRetry: onRetry,
);
diff --git a/lib/models/app_state.dart b/lib/models/app_state.dart
index 709b445..8325b50 100644
--- a/lib/models/app_state.dart
+++ b/lib/models/app_state.dart
@@ -7,4 +7,6 @@ class AppState extends ChangeNotifier {
String streamId = "";
bool isCommandProcessing = false;
String commandProcessingText = "Processing...";
+ String sttFramework = "vosk";
+ bool onlineMode = false;
}
diff --git a/lib/protos/voice_agent.proto b/lib/protos/voice_agent.proto
index 40dfe6a..09b9461 100644
--- a/lib/protos/voice_agent.proto
+++ b/lib/protos/voice_agent.proto
@@ -11,6 +11,15 @@ service VoiceAgentService {
rpc ExecuteCommand(ExecuteInput) returns (ExecuteResult);
}
+enum STTFramework {
+ VOSK = 0;
+ WHISPER = 1;
+}
+
+enum OnlineMode {
+ ONLINE = 0;
+ OFFLINE = 1;
+}
enum RecordAction {
START = 0;
@@ -50,7 +59,7 @@ message Empty {}
message ServiceStatus {
string version = 1;
- bool status = 2;
+ bool status = 2;
string wake_word = 3;
}
@@ -69,6 +78,7 @@ message S_RecognizeVoiceControl {
VoiceAudio audio_stream = 1;
NLUModel nlu_model = 2;
string stream_id = 3;
+ STTFramework stt_framework = 4;
}
message RecognizeVoiceControl {
@@ -76,6 +86,8 @@ message RecognizeVoiceControl {
NLUModel nlu_model = 2;
RecordMode record_mode = 3;
string stream_id = 4;
+ STTFramework stt_framework = 5;
+ OnlineMode online_mode = 6;
}
message RecognizeTextControl {
diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart
index a9d567b..4c2407f 100644
--- a/lib/screens/home_screen.dart
+++ b/lib/screens/home_screen.dart
@@ -1,8 +1,10 @@
import 'dart:ui';
import 'package:flutter/material.dart';
+import 'package:flutter_voiceassistant/widgets/online_mode_choice.dart';
import 'package:flutter_voiceassistant/widgets/try_commands.dart';
import 'package:provider/provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
import 'dart:async';
import '../models/app_state.dart';
import '../widgets/nlu_engine_choice.dart';
@@ -13,6 +15,7 @@ import '../widgets/chat_section.dart';
import '../grpc/generated/voice_agent.pbgrpc.dart';
import '../grpc/voice_agent_client.dart';
import '../utils/app_config.dart';
+import '../widgets/stt_model_choice.dart';
class HomePage extends StatefulWidget {
final AppConfig config;
@@ -36,18 +39,30 @@ class HomePageState extends State<HomePage> {
super.initState();
_config = widget.config; // Initialize _config in the initState
_wakeWord = widget.wakeWord; // Initialize _wakeWord in the initState
- addChatMessage(
- "Assistant in Manual mode. You can send commands directly by pressing the record button.");
+ final appState = context.read<AppState>();
+ if(appState.isWakeWordMode){
+ addChatMessage(
+ 'Switched to Wake Word mode. I\'ll listen for the wake word "$_wakeWord" before responding.');
+ _startWakeWordDetection(context);
+ }
+ else{
+ addChatMessage(
+ "Assistant in Manual mode. You can send commands directly by pressing the record button.");
+ }
+
}
- void changeAssistantMode(BuildContext context, AssistantMode newMode) {
+ Future<void> changeAssistantMode(BuildContext context, AssistantMode newMode) async {
final appState = context.read<AppState>();
clearChatMessages();
appState.streamId = "";
appState.isWakeWordDetected = false;
appState.isCommandProcessing = false;
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+
if (newMode == AssistantMode.wakeWord) {
+ await prefs.setBool('isWakeWordMode', true);
addChatMessage(
'Switched to Wake Word mode. I\'ll listen for the wake word "$_wakeWord" before responding.');
@@ -62,6 +77,7 @@ class HomePageState extends State<HomePage> {
toggleWakeWordDetection(context, true);
}
} else if (newMode == AssistantMode.manual) {
+ prefs.setBool('isWakeWordMode', false);
addChatMessage(
'Switched to Manual mode. You can send commands directly by pressing record button.');
@@ -74,15 +90,17 @@ class HomePageState extends State<HomePage> {
setState(() {}); // Trigger a rebuild
}
- void changeIntentEngine(BuildContext context, NLUEngine newEngine) {
+ Future<void> changeIntentEngine(BuildContext context, NLUEngine newEngine) async {
final appState = context.read<AppState>();
-
+ SharedPreferences prefs = await SharedPreferences.getInstance();
if (newEngine == NLUEngine.snips) {
appState.intentEngine = "snips";
+ await prefs.setString("intentEngine","snips");
addChatMessage(
'Switched to 🚀 Snips engine. Lets be precise and accurate.');
} else if (newEngine == NLUEngine.rasa) {
appState.intentEngine = "rasa";
+ await prefs.setString("intentEngine","rasa");
addChatMessage(
'Switched to 🤖 RASA engine. Conversations just got smarter!');
}
@@ -90,6 +108,42 @@ class HomePageState extends State<HomePage> {
setState(() {}); // Trigger a rebuild
}
+ Future<void> changeSTTFramework(BuildContext context, STTModel newModel) async {
+ final appState = context.read<AppState>();
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ if (newModel == STTModel.vosk) {
+ appState.sttFramework = "vosk";
+ await prefs.setString("sttFramework", "vosk");
+ // vosk is fast and efficient
+ addChatMessage(
+ 'Switched to 🚀 Vosk framework. Lets be quick and efficient.');
+ } else if (newModel == STTModel.whisper) {
+ appState.sttFramework = "whisper";
+ await prefs.setString("sttFramework", "whisper");
+ addChatMessage(
+ 'Switched to 🤖 Whisper framework. Conversations just got smarter!');
+ }
+ print(appState.sttFramework);
+ setState(() {}); // Trigger a rebuild
+ }
+
+ Future<void> toggleOnlineMode(BuildContext context, OnlineModeEnum mode) async {
+ final appState = context.read<AppState>();
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ if (mode == OnlineModeEnum.enabled) {
+ appState.onlineMode = true;
+ await prefs.setBool('onlineMode', true);
+ addChatMessage(
+ 'Switched to Online mode. I\'ll be connected to the internet for better results.');
+ } else {
+ appState.onlineMode = false;
+ await prefs.setBool('onlineMode', false);
+ addChatMessage(
+ 'Switched to Offline mode. I\'ll be disconnected from the internet.');
+ }
+ setState(() {}); // Trigger a rebuild
+ }
+
void addChatMessage(String text, {bool isUserMessage = false}) {
final newMessage = ChatMessage(text: text, isUserMessage: isUserMessage);
setState(() {
@@ -123,7 +177,7 @@ class HomePageState extends State<HomePage> {
setState(
() {}); // Trigger a rebuild to ensure the loading indicator is shown, tis a bad practice though but deosn't heavily affect the performance
final response =
- await stopRecording(appState.streamId, appState.intentEngine);
+ await stopRecording(appState.streamId, appState.intentEngine,appState.sttFramework,appState.onlineMode);
// Process and store the result
if (response.status == RecognizeStatusType.REC_SUCCESS) {
appState.commandProcessingText = "Executing command...";
@@ -204,19 +258,31 @@ class HomePageState extends State<HomePage> {
}
Future<RecognizeResult> stopRecording(
- String streamId, String nluModel) async {
+ String streamId, String nluModel, String stt,bool isOnlineMode) async {
+
try {
NLUModel model = NLUModel.RASA;
if (nluModel == "snips") {
model = NLUModel.SNIPS;
}
+ STTFramework sttFramework = STTFramework.VOSK;
+ if (stt == "whisper") {
+ sttFramework = STTFramework.WHISPER;
+ }
+ OnlineMode onlineMode = OnlineMode.OFFLINE;
+ if (isOnlineMode) {
+ onlineMode = OnlineMode.ONLINE;
+ }
// Create a RecognizeControl message to stop recording
final controlMessage = RecognizeVoiceControl()
..action = RecordAction.STOP
..nluModel = model
..streamId =
streamId // Use the same stream ID as when starting recording
- ..recordMode = RecordMode.MANUAL;
+ ..recordMode = RecordMode.MANUAL
+ ..sttFramework = sttFramework
+ ..onlineMode = onlineMode;
+
// Create a Stream with the control message
final controlStream = Stream.fromIterable([controlMessage]);
@@ -375,116 +441,234 @@ class HomePageState extends State<HomePage> {
style: TextStyle(fontSize: 26, fontWeight: FontWeight.bold),
),
SizedBox(height: 15),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
+ Column(
children: [
- Flexible(
- flex: 1,
- child: ClipRect(
- child: BackdropFilter(
- filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
- child: Card(
- color: _config.theme == "textured-dark" ||
- _config.theme == "textured-light"
- ? Colors.transparent
- : null,
- elevation: 4, // Add elevation for shadow
- shadowColor: _config.theme == "textured-dark" ||
- _config.theme == "textured-light"
- ? Colors.transparent
- : null,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(12),
- ),
- child: Padding(
- padding: EdgeInsets.all(16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- 'Assistant Mode',
- style: TextStyle(
- fontSize: 18,
- fontWeight: FontWeight.bold,
- ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Flexible(
+ flex: 1,
+ child: ClipRect(
+ child: BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
+ child: Card(
+ color: _config.theme == "textured-dark" ||
+ _config.theme == "textured-light"
+ ? Colors.transparent
+ : null,
+ elevation: 4, // Add elevation for shadow
+ shadowColor: _config.theme == "textured-dark" ||
+ _config.theme == "textured-light"
+ ? Colors.transparent
+ : null,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Assistant Mode',
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ SizedBox(height: 16), // Add spacing if needed
+ Center(
+ child: Consumer<AppState>(
+ builder: (context, appState, _) {
+ return AssistantModeChoice(
+ onModeChanged: (newMode) {
+ changeAssistantMode(
+ context, newMode);
+ print(newMode);
+ },
+ theme: _config.theme,
+ );
+ },
+ ),
+ ),
+ ],
),
- SizedBox(height: 16), // Add spacing if needed
- Center(
- child: Consumer<AppState>(
- builder: (context, appState, _) {
- return AssistantModeChoice(
- onModeChanged: (newMode) {
- changeAssistantMode(
- context, newMode);
- print(newMode);
+ ),
+ ),
+ ),
+ ),
+ ),
+
+ SizedBox(width: 20), // Add spacing between buttons
+
+ Flexible(
+ flex: 1,
+ child: ClipRect(
+ child: BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
+ child: Card(
+ color: _config.theme == "textured-dark" ||
+ _config.theme == "textured-light"
+ ? Colors.transparent
+ : null,
+ elevation: 4, // Add elevation for shadow
+ shadowColor: _config.theme == "textured-dark" ||
+ _config.theme == "textured-light"
+ ? Colors.transparent
+ : null,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Intent Engine',
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ SizedBox(height: 16), // Add spacing if needed
+ Center(
+ child: Consumer<AppState>(
+ builder: (context, appState, _) {
+ return NLUEngineChoice(
+ onEngineChanged: (newEngine) {
+ changeIntentEngine(
+ context, newEngine);
+ print(newEngine);
+ },
+ theme: _config.theme,
+ );
},
- theme: _config.theme,
- );
- },
- ),
+ ),
+ ),
+ ],
),
- ],
+ ),
),
),
),
),
- ),
+ ],
),
- SizedBox(width: 20), // Add spacing between buttons
-
- Flexible(
- flex: 1,
- child: ClipRect(
- child: BackdropFilter(
- filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
- child: Card(
- color: _config.theme == "textured-dark" ||
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Flexible(
+ flex: 1,
+ child: ClipRect(
+ child: BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
+ child: Card(
+ color: _config.theme == "textured-dark" ||
_config.theme == "textured-light"
- ? Colors.transparent
- : null,
- elevation: 4, // Add elevation for shadow
- shadowColor: _config.theme == "textured-dark" ||
+ ? Colors.transparent
+ : null,
+ elevation: 4, // Add elevation for shadow
+ shadowColor: _config.theme == "textured-dark" ||
_config.theme == "textured-light"
- ? Colors.transparent
- : null,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(12),
- ),
- child: Padding(
- padding: EdgeInsets.all(16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- 'Intent Engine',
- style: TextStyle(
- fontSize: 18,
- fontWeight: FontWeight.bold,
- ),
+ ? Colors.transparent
+ : null,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Speech-to-Text Model',
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ SizedBox(height: 16), // Add spacing if needed
+ Center(
+ child: Consumer<AppState>(
+ builder: (context, appState, _) {
+ return STTModelChoice(
+ onModelChanged: (newModel) {
+ changeSTTFramework(
+ context, newModel);
+ print(newModel);
+ },
+ theme: _config.theme,
+ );
+ },
+ ),
+ ),
+ ],
),
- SizedBox(height: 16), // Add spacing if needed
- Center(
- child: Consumer<AppState>(
- builder: (context, appState, _) {
- return NLUEngineChoice(
- onEngineChanged: (newEngine) {
- changeIntentEngine(
- context, newEngine);
- print(newEngine);
+ ),
+ ),
+ ),
+ ),
+ ),
+
+ SizedBox(width: 20), // Add spacing between buttons
+
+ Flexible(
+ flex: 1,
+ child: ClipRect(
+ child: BackdropFilter(
+ filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
+ child: Card(
+ color: _config.theme == "textured-dark" ||
+ _config.theme == "textured-light"
+ ? Colors.transparent
+ : null,
+ elevation: 4, // Add elevation for shadow
+ shadowColor: _config.theme == "textured-dark" ||
+ _config.theme == "textured-light"
+ ? Colors.transparent
+ : null,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Padding(
+ padding: EdgeInsets.all(16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Online Mode',
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ SizedBox(height: 16), // Add spacing if needed
+ Center(
+ child: Consumer<AppState>(
+ builder: (context, appState, _) {
+ return OnlineModeChoice(
+ onModeChanged: (mode) {
+ toggleOnlineMode(context, mode);
+ print(mode);
+ },
+ theme: _config.theme,
+ );
},
- theme: _config.theme,
- );
- },
- ),
+ ),
+ ),
+ ],
),
- ],
+ ),
),
),
),
),
- ),
+ ],
),
+
+
],
),
SizedBox(height: 15),
diff --git a/lib/screens/loading_screen.dart b/lib/screens/loading_screen.dart
new file mode 100644
index 0000000..f4d6c6d
--- /dev/null
+++ b/lib/screens/loading_screen.dart
@@ -0,0 +1,81 @@
+import 'dart:async';
+
+import 'package:flutter/cupertino.dart';
+import 'package:flutter_voiceassistant/screens/home_screen.dart';
+import 'package:provider/provider.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+import '../models/app_state.dart';
+import '../utils/app_config.dart';
+
+class Loading extends StatelessWidget {
+ final AppConfig config;
+ final String wakeWord;
+ Loading({required this.config, required this.wakeWord});
+
+ Future<void> initialize(BuildContext context) async {
+ // Initialize the app
+ final appState = context.read<AppState>();
+ bool isWakeWordMode = false;
+ String intentEngine = "snips";
+ String streamId = "";
+ bool isCommandProcessing = false;
+ String commandProcessingText = "Processing...";
+ String sttFramework = "vosk";
+ bool onlineMode = false;
+
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ prefs.reload();
+ if(prefs.containsKey('isWakeWordMode')) {
+ isWakeWordMode = await prefs.getBool('isWakeWordMode')!;
+ }
+ if(prefs.containsKey('intentEngine')) {
+ intentEngine = await prefs.getString('intentEngine')!;
+ }
+ if(prefs.containsKey('streamId')) {
+ streamId = await prefs.getString('streamId')!;
+ }
+ if(prefs.containsKey('isCommandProcessing')) {
+ isCommandProcessing = await prefs.getBool('isCommandProcessing')!;
+ }
+ if(prefs.containsKey('commandProcessingText')) {
+ commandProcessingText = await prefs.getString('commandProcessingText')!;
+ }
+ if(prefs.containsKey('sttFramework')) {
+ sttFramework = await prefs.getString('sttFramework')!;
+ }
+ if(prefs.containsKey('onlineMode')) {
+ onlineMode = await prefs.getBool('onlineMode')!;
+ }
+
+ appState.isWakeWordMode = isWakeWordMode;
+ appState.intentEngine = intentEngine;
+ appState.streamId = streamId;
+ appState.isCommandProcessing = isCommandProcessing;
+ appState.commandProcessingText = commandProcessingText;
+ appState.sttFramework = sttFramework;
+ appState.onlineMode = onlineMode;
+
+ print('isWakeWordMode: $isWakeWordMode');
+ print('intentEngine: $intentEngine');
+ print('streamId: $streamId');
+ print('isCommandProcessing: $isCommandProcessing');
+ print('commandProcessingText: $commandProcessingText');
+ print('sttFramework: $sttFramework');
+ print('onlineMode: $onlineMode');
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return FutureBuilder(
+ future: initialize(context),
+ builder: (context, snapshot) {
+ if (snapshot.connectionState == ConnectionState.done) {
+ return HomePage(config: config, wakeWord: wakeWord);
+ } else {
+ return CupertinoActivityIndicator();
+ }
+ },
+ );
+ }
+}
diff --git a/lib/widgets/assistant_mode_choice.dart b/lib/widgets/assistant_mode_choice.dart
index c2afe5b..2c776df 100644
--- a/lib/widgets/assistant_mode_choice.dart
+++ b/lib/widgets/assistant_mode_choice.dart
@@ -70,6 +70,9 @@
// }
import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../models/app_state.dart';
enum AssistantMode { wakeWord, manual }
@@ -92,7 +95,10 @@ class AssistantModeChoiceState extends State<AssistantModeChoice> {
@override
void initState() {
super.initState();
- _selectedMode = AssistantMode.manual; // Initialize the selection
+ final appState = context.read<AppState>();
+ _selectedMode = appState.isWakeWordMode
+ ? AssistantMode.wakeWord
+ : AssistantMode.manual; // Initialize the selection
_theme = widget.theme;
print(widget.theme);
}
diff --git a/lib/widgets/nlu_engine_choice.dart b/lib/widgets/nlu_engine_choice.dart
index 32db7dd..53a4aaa 100644
--- a/lib/widgets/nlu_engine_choice.dart
+++ b/lib/widgets/nlu_engine_choice.dart
@@ -68,6 +68,9 @@
// }
import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../models/app_state.dart';
enum NLUEngine { snips, rasa }
@@ -90,7 +93,8 @@ class _NLUEngineChoiceState extends State<NLUEngineChoice> {
@override
void initState() {
super.initState();
- _selectedEngine = NLUEngine.snips; // Initialize the selection
+ final appState = context.read<AppState>();
+ _selectedEngine = appState.intentEngine == "snips" ? NLUEngine.snips : NLUEngine.rasa;
_theme = widget.theme;
}
diff --git a/lib/widgets/online_mode_choice.dart b/lib/widgets/online_mode_choice.dart
new file mode 100644
index 0000000..3146d15
--- /dev/null
+++ b/lib/widgets/online_mode_choice.dart
@@ -0,0 +1,148 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../models/app_state.dart';
+
+enum OnlineModeEnum{
+ enabled,
+ disabled
+}
+
+class OnlineModeChoice extends StatefulWidget {
+ final Function(OnlineModeEnum) onModeChanged;
+ final String theme;
+
+ const OnlineModeChoice({
+ Key? key,
+ required this.onModeChanged,
+ required this.theme
+ }) : super(key: key);
+
+ @override
+ State<OnlineModeChoice> createState() => _OnlineModeChoiceState();
+}
+
+class _OnlineModeChoiceState extends State<OnlineModeChoice> {
+ late OnlineModeEnum _selectedMode;
+ late String _theme;
+
+ @override
+ void initState() {
+ super.initState();
+ final appState = context.read<AppState>();
+ _selectedMode = appState.onlineMode ? OnlineModeEnum.enabled : OnlineModeEnum.disabled;
+ _theme = widget.theme;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ InkWell(
+ onTap: () => _onModelChanged(OnlineModeEnum.disabled),
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ color: _selectedMode == OnlineModeEnum.disabled
+ ? Colors.green
+ : _theme == "dark" || _theme == "textured-dark"
+ ? Colors.black
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedMode == OnlineModeEnum.disabled
+ ? Icons.check
+ : Icons.cloud_off_outlined,
+ color: _selectedMode == OnlineModeEnum.disabled
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'Disabled',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 17,
+ color: _selectedMode == OnlineModeEnum.disabled
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ InkWell(
+ onTap: () => _onModelChanged(OnlineModeEnum.enabled),
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ color: _selectedMode == OnlineModeEnum.enabled
+ ? Colors.green
+ : _theme == "dark" || _theme == "textured-dark"
+ ? Colors.black
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedMode == OnlineModeEnum.enabled
+ ? Icons.check
+ : Icons.cloud_done_outlined,
+ color: _selectedMode == OnlineModeEnum.enabled
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'Enabled',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 17,
+ color: _selectedMode == OnlineModeEnum.enabled
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+
+ void _onModelChanged(OnlineModeEnum newMode) {
+ setState(() {
+ _selectedMode = newMode;
+ });
+
+ // Call the callback function to notify the engine change
+ widget.onModeChanged(newMode);
+ }
+} \ No newline at end of file
diff --git a/lib/widgets/stt_model_choice.dart b/lib/widgets/stt_model_choice.dart
new file mode 100644
index 0000000..fc0e099
--- /dev/null
+++ b/lib/widgets/stt_model_choice.dart
@@ -0,0 +1,148 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import '../models/app_state.dart';
+
+enum STTModel{
+ vosk,
+ whisper
+}
+
+class STTModelChoice extends StatefulWidget {
+ final Function(STTModel) onModelChanged;
+ final String theme;
+
+ const STTModelChoice({
+ Key? key,
+ required this.onModelChanged,
+ required this.theme
+ }) : super(key: key);
+
+ @override
+ State<STTModelChoice> createState() => _STTModelChoiceState();
+}
+
+class _STTModelChoiceState extends State<STTModelChoice> {
+ late STTModel _selectedModel;
+ late String _theme;
+
+ @override
+ void initState() {
+ super.initState();
+ final appState = context.read<AppState>();
+ _selectedModel = appState.sttFramework == "vosk" ? STTModel.vosk : STTModel.whisper;
+ _theme = widget.theme;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ InkWell(
+ onTap: () => _onModelChanged(STTModel.vosk),
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ color: _selectedModel == STTModel.vosk
+ ? Colors.green
+ : _theme == "dark" || _theme == "textured-dark"
+ ? Colors.black
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedModel == STTModel.vosk
+ ? Icons.check
+ : Icons.transcribe_sharp,
+ color: _selectedModel == STTModel.vosk
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'Vosk',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 17,
+ color: _selectedModel == STTModel.vosk
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ InkWell(
+ onTap: () => _onModelChanged(STTModel.whisper),
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ color: _selectedModel == STTModel.whisper
+ ? Colors.green
+ : _theme == "dark" || _theme == "textured-dark"
+ ? Colors.black
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedModel == STTModel.whisper
+ ? Icons.check
+ : Icons.transcribe_sharp,
+ color: _selectedModel == STTModel.whisper
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'Whisper',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 17,
+ color: _selectedModel == STTModel.whisper
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+
+ void _onModelChanged(STTModel newModel) {
+ setState(() {
+ _selectedModel = newModel;
+ });
+
+ // Call the callback function to notify the engine change
+ widget.onModelChanged(newModel);
+ }
+} \ No newline at end of file