Skip to content

Commit fd8b7d5

Browse files
authored
[flutter_tts] Fix bug and support setting speech volume (#263)
* Fix bug in setLanguage * Support setVolume * Minor cleanups
1 parent b952bdf commit fd8b7d5

File tree

10 files changed

+119
-19
lines changed

10 files changed

+119
-19
lines changed

packages/flutter_tts/CHANGELOG.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@
88

99
## 1.1.0
1010

11-
* All APIs now return valid values.(0 or 1, empty list, etc.)
11+
* All APIs now return valid values(0 or 1, empty list, etc.).
1212

1313
## 1.1.1
1414

15-
* Fix calling onCancel in a successful situation and refactor native implementations
15+
* Fix calling onCancel in a successful situation and refactor native implementations.
16+
17+
## 1.2.0
18+
19+
* Fix a bug where `setLanguage()` wasn't invoked due to typo in "setLanguage".
20+
* Update flutter_tts to 3.2.2 and update the example app.
21+
* Support `setVolume()`.
22+
* Minor cleanups.

packages/flutter_tts/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ This package is not an _endorsed_ implementation of `flutter_tts`. Therefore, yo
88

99
```yaml
1010
dependencies:
11-
flutter_tts: ^3.0.0
12-
flutter_tts_tizen: ^1.1.1
11+
flutter_tts: ^3.2.2
12+
flutter_tts_tizen: ^1.2.0
1313
```
1414
1515
Then you can import `flutter_tts` in your Dart code:
@@ -29,3 +29,4 @@ The features supported by Tizen are as follows. Other features are not supported
2929
- [x] get languages
3030
- [x] set language
3131
- [x] set speech rate
32+
- [x] set speech volume (requires privilege `http://tizen.org/privilege/volume.set` in `tizen_manifest.xml`)

packages/flutter_tts/example/lib/main.dart

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ enum TtsState { playing, stopped, paused, continued }
1717
class _MyAppState extends State<MyApp> {
1818
late FlutterTts flutterTts;
1919
String? language;
20+
double volume = 0.5;
2021
double pitch = 1.0;
2122
double rate = 0.5;
2223
String? _newVoiceText;
@@ -82,6 +83,7 @@ class _MyAppState extends State<MyApp> {
8283
Future<dynamic> _getLanguages() => flutterTts.getLanguages;
8384

8485
Future _speak() async {
86+
await flutterTts.setVolume(volume);
8587
await flutterTts.setSpeechRate(rate);
8688

8789
if (_newVoiceText != null) {
@@ -216,10 +218,22 @@ class _MyAppState extends State<MyApp> {
216218

217219
Widget _buildSliders() {
218220
return Column(
219-
children: [_rate()],
221+
children: [_volume(), _rate()],
220222
);
221223
}
222224

225+
Widget _volume() {
226+
return Slider(
227+
value: volume,
228+
onChanged: (newVolume) {
229+
setState(() => volume = newVolume);
230+
},
231+
min: 0.0,
232+
max: 1.0,
233+
divisions: 10,
234+
label: "Volume: $volume");
235+
}
236+
223237
Widget _rate() {
224238
return Slider(
225239
value: rate,

packages/flutter_tts/example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ publish_to: "none"
55
dependencies:
66
flutter:
77
sdk: flutter
8-
flutter_tts: ^3.0.0
8+
flutter_tts: ^3.2.2
99
flutter_tts_tizen:
1010
path: ../
1111

packages/flutter_tts/example/tizen/Runner.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Tizen.NET.Sdk/1.1.5">
1+
<Project Sdk="Tizen.NET.Sdk/1.1.6">
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest package="org.tizen.flutter_tts_tizen_example" version="1.0.0" api-version="4.0" xmlns="http://tizen.org/ns/packages">
33
<profile name="common"/>
4-
<ui-application appid="org.tizen.flutter_tts_tizen_example" exec="Runner.dll" type="dotnet" multiple="false" taskmanage="true" nodisplay="false" api-version="4" launch_mode="single">
4+
<ui-application appid="org.tizen.flutter_tts_tizen_example" exec="Runner.dll" type="dotnet" multiple="false" taskmanage="true" nodisplay="false" api-version="4">
55
<label>flutter_tts_tizen_example</label>
66
<icon>ic_launcher.png</icon>
77
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true"/>
88
<metadata key="http://tizen.org/metadata/direct-launch" value="yes"/>
99
</ui-application>
1010
<feature name="http://tizen.org/feature/screen.size.all"/>
11+
<privileges>
12+
<privilege>http://tizen.org/privilege/volume.set</privilege>
13+
</privileges>
1114
</manifest>

packages/flutter_tts/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: flutter_tts_tizen
22
description: The tizen implementation of flutter_tts plugin.
33
homepage: https://github.com/flutter-tizen/plugins
44
repository: https://github.com/flutter-tizen/plugins/tree/master/packages/flutter_tts
5-
version: 1.1.1
5+
version: 1.2.0
66

77
dependencies:
88
flutter:

packages/flutter_tts/tizen/src/flutter_tts_tizen_plugin.cc

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,12 @@ class FlutterTtsTizenPlugin : public flutter::Plugin {
7373
const flutter::MethodCall<flutter::EncodableValue> &method_call,
7474
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
7575
// Keep in sync with the return values implemented in:
76-
// https://github.com/dlutton/flutter_tts/blob/master/android/src/main/java/com/tundralabs/fluttertts/FlutterTtsPlugin.java
77-
// The API specification is vague, and there is no detailed description of
78-
// the return value, so I mimic the Android implementation.
76+
// https://github.com/dlutton/flutter_tts/blob/master/android/src/main/java/com/tundralabs/fluttertts/FlutterTtsPlugin.java.
77+
// In principle, MethodResult was designed to call MethodResult.Error() to
78+
// notify the dart code of any method call failures from the host platform.
79+
// However, in the case of flutter_tts, it expects a return value 0 on
80+
// failure(and value 1 on success). Therefore in the scope of this plugin,
81+
// we call result->Success(flutter::EncodableValue(0)) to notify errors.
7982

8083
const auto method_name = method_call.method_name();
8184
const auto &arguments = *method_call.arguments();
@@ -137,7 +140,6 @@ class FlutterTtsTizenPlugin : public flutter::Plugin {
137140
map.insert(std::pair<flutter::EncodableValue, flutter::EncodableValue>(
138141
"platform", "tizen"));
139142
result->Success(flutter::EncodableValue(std::move(map)));
140-
return;
141143
} else if (method_name.compare("setSpeechRate") == 0) {
142144
if (std::holds_alternative<double>(arguments)) {
143145
int speed = (int)std::get<double>(arguments);
@@ -146,7 +148,7 @@ class FlutterTtsTizenPlugin : public flutter::Plugin {
146148
return;
147149
}
148150
result->Success(flutter::EncodableValue(0));
149-
} else if (method_name.compare("setLanguages") == 0) {
151+
} else if (method_name.compare("setLanguage") == 0) {
150152
if (std::holds_alternative<std::string>(arguments)) {
151153
std::string language = std::move(std::get<std::string>(arguments));
152154
tts_->SetDefaultLanguage(language);
@@ -160,9 +162,17 @@ class FlutterTtsTizenPlugin : public flutter::Plugin {
160162
list.push_back(flutter::EncodableValue(language));
161163
}
162164
result->Success(flutter::EncodableValue(list));
165+
} else if (method_name.compare("setVolume") == 0) {
166+
if (std::holds_alternative<double>(arguments)) {
167+
double rate = std::get<double>(arguments);
168+
if (tts_->SetVolume(rate)) {
169+
result->Success(flutter::EncodableValue(1));
170+
return;
171+
}
172+
}
173+
result->Success(flutter::EncodableValue(0));
163174
} else {
164175
result->Error("-1", "Not supported method");
165-
return;
166176
}
167177
}
168178

packages/flutter_tts/tizen/src/text_to_speech.cc

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include "text_to_speech.h"
66

7+
#include <sound_manager.h>
8+
79
#include "log.h"
810

911
namespace {
@@ -52,6 +54,13 @@ void TextToSpeech::Prepare() {
5254
default_voice_type_ = voice_type;
5355
free(language);
5456
}
57+
ret = sound_manager_get_max_volume(SOUND_TYPE_VOICE, &system_max_volume_);
58+
if (ret != SOUND_MANAGER_ERROR_NONE) {
59+
LOG_ERROR("[SOUNDMANAGER] sound_manager_get_max_volume failed: %s",
60+
get_error_message(ret));
61+
}
62+
system_volume_ = GetSpeechVolumeInternal();
63+
tts_volume_ = system_volume_;
5564

5665
ret = tts_prepare(tts_);
5766
if (ret != TTS_ERROR_NONE) {
@@ -72,6 +81,7 @@ void TextToSpeech::UnregisterTtsCallback() {
7281
}
7382

7483
void TextToSpeech::OnStateChanged(tts_state_e previous, tts_state_e current) {
84+
SwitchVolumeOnStateChange(previous, current);
7585
on_state_changed_(previous, current);
7686
}
7787

@@ -145,11 +155,58 @@ bool TextToSpeech::Pause() {
145155
return true;
146156
}
147157

148-
bool TextToSpeech::GetSpeedRange(int *min, int *nomal, int *max) {
149-
int ret = tts_get_speed_range(tts_, min, nomal, max);
158+
bool TextToSpeech::SetVolume(double volume_rate) {
159+
tts_volume_ = static_cast<int>(system_max_volume_ * volume_rate);
160+
// Change volume instantly when tts is playing.
161+
if (GetState() == TTS_STATE_PLAYING) {
162+
if (!SetSpeechVolumeInternal(tts_volume_)) {
163+
return false;
164+
}
165+
}
166+
return true;
167+
}
168+
169+
bool TextToSpeech::GetSpeedRange(int *min, int *normal, int *max) {
170+
int ret = tts_get_speed_range(tts_, min, normal, max);
150171
if (ret != TTS_ERROR_NONE) {
151172
LOG_ERROR("[TTS] tts_get_speed_range failed: %s", get_error_message(ret));
152173
return false;
153174
}
154175
return true;
155176
}
177+
178+
void TextToSpeech::SwitchVolumeOnStateChange(tts_state_e previous,
179+
tts_state_e current) {
180+
if (previous == TTS_STATE_PLAYING) {
181+
// When playback is finished, save the tts_volume that might've changed
182+
// from hardware key, then restore the system volume.
183+
tts_volume_ = GetSpeechVolumeInternal();
184+
SetSpeechVolumeInternal(system_volume_);
185+
} else if (current == TTS_STATE_PLAYING) {
186+
// Before playback starts, save the system volume to restore when playback
187+
// is finished, then set the tts volume.
188+
system_volume_ = GetSpeechVolumeInternal();
189+
SetSpeechVolumeInternal(tts_volume_);
190+
}
191+
}
192+
193+
int TextToSpeech::GetSpeechVolumeInternal() {
194+
int volume;
195+
int ret = sound_manager_get_volume(SOUND_TYPE_VOICE, &volume);
196+
if (ret != SOUND_MANAGER_ERROR_NONE) {
197+
LOG_ERROR("[SOUNDMANAGER] sound_manager_get_volume failed: %s",
198+
get_error_message(ret));
199+
volume = 0;
200+
}
201+
return volume;
202+
}
203+
204+
bool TextToSpeech::SetSpeechVolumeInternal(int volume) {
205+
int ret = sound_manager_set_volume(SOUND_TYPE_VOICE, volume);
206+
if (ret != SOUND_MANAGER_ERROR_NONE) {
207+
LOG_ERROR("[SOUNDMANAGER] sound_manager_set_volume failed: %s",
208+
get_error_message(ret));
209+
return false;
210+
}
211+
return true;
212+
}

packages/flutter_tts/tizen/src/text_to_speech.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ class TextToSpeech {
7272

7373
bool Pause();
7474

75-
bool GetSpeedRange(int *min, int *nomal, int *max);
75+
bool SetVolume(double volume_rate);
76+
77+
bool GetSpeedRange(int *min, int *normal, int *max);
7678

7779
void SetTtsSpeed(int speed) { tts_speed_ = speed; }
7880

@@ -87,12 +89,18 @@ class TextToSpeech {
8789
void HandleAwaitSpeakCompletion(tts_state_e previous, tts_state_e current);
8890
void ClearUttId() { utt_id_ = 0; }
8991

92+
void SwitchVolumeOnStateChange(tts_state_e previous, tts_state_e current);
93+
bool SetSpeechVolumeInternal(int volume);
94+
int GetSpeechVolumeInternal();
95+
9096
tts_h tts_ = nullptr;
91-
tts_state_e state_ = TTS_STATE_CREATED;
9297
std::string default_language_;
9398
int default_voice_type_ = TTS_VOICE_TYPE_AUTO;
9499
int tts_speed_ = TTS_SPEED_AUTO;
95100
int utt_id_ = 0;
101+
int tts_volume_ = 0;
102+
int system_volume_ = 0;
103+
int system_max_volume_ = 0;
96104
std::vector<std::string> supported_lanaguages_;
97105

98106
OnStateChangedCallback on_state_changed_;

0 commit comments

Comments
 (0)