Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flatpak/com.mikeasoft.pied.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ finish-args:
- --device=dri
- --socket=pulseaudio
- --share=network
- --filesystem=home
- --filesystem=xdg-config/speech-dispathcer:create
- --talk-name=org.freedesktop.Flatpak
modules:
- name: Pied
Expand Down
137 changes: 91 additions & 46 deletions lib/voice_buttons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,60 +48,95 @@ class _VoiceButtonsState extends State<VoiceButtons> {
}
}

void setSDConfig() async {
Future<void> setSDConfig() async {
Directory confDir =
Directory(path.join(getHome()!, ".config/speech-dispatcher"));
Directory? originalConfigDir;
if (confDir.existsSync()) {
File sdConfig = File(path.join(confDir.path, "speechd.conf"));
if (sdConfig.existsSync()) {
if (sdConfig
.readAsStringSync()
.contains("THIS CONFIG WAS GENERATED BY PIED")) {
return;
}
}
DateTime now = DateTime.now();
Directory newDir;
if (isSnap()) {
Directory origDir =
Directory(path.join(getHome()!, ".config/speech-dispatcher.orig"));
if (!origDir.existsSync()) {
origDir.createSync();
}
newDir = Directory(
"${confDir.path}.orig/${now.year}-${now.month}-${now.day}");
} else {
newDir = Directory(
"${confDir.path}.orig.${now.year}-${now.month}-${now.day}");

// Ensure the main config directory and subdirectories exist
if (!confDir.existsSync()) {
confDir.createSync(recursive: true);
}
Directory modulesDir = Directory(path.join(confDir.path, "modules"));
if (!modulesDir.existsSync()) {
modulesDir.createSync(recursive: true);
}
Directory clientsDir = Directory(path.join(confDir.path, "clients"));
if (!clientsDir.existsSync()) {
clientsDir.createSync(recursive: true);
}

File sdConfig = File(path.join(confDir.path, "speechd.conf"));
File piperConfig = File(path.join(modulesDir.path, "piper.conf"));

DateTime now = DateTime.now();
String timestamp =
"${now.year}-${now.month}-${now.day}-${now.hour}-${now.minute}-${now.second}";

File? sdBackup;
File? piperBackup;
bool sdChanged = false;

// Check/Backup speechd.conf
// If it exists and DOES NOT contain our signature, back it up.
if (sdConfig.existsSync()) {
if (!sdConfig.readAsStringSync().contains("THIS CONFIG WAS GENERATED BY PIED")) {
sdBackup = File("${sdConfig.path}.bak-$timestamp");
sdConfig.renameSync(sdBackup.path);

// We only create new config if we moved the old one or it didn't exist
sdConfig.createSync();
sdConfig.writeAsString(sdConfigTemplate);
sdChanged = true;
}
if (newDir.existsSync()) {
newDir.deleteSync(recursive: true);
} else {
// Create fresh if didn't exist
sdConfig.createSync();
sdConfig.writeAsString(sdConfigTemplate);
sdChanged = true;
}

// if not generated by pied -> back up
if (piperConfig.existsSync()) {
if (!piperConfig.readAsStringSync().contains("THIS CONFIG WAS GENERATED BY PIED")) {
piperBackup = File("${piperConfig.path}.bak-$timestamp");
piperConfig.renameSync(piperBackup.path);
}
confDir.renameSync(newDir.path);
originalConfigDir = newDir;
}
confDir.createSync();
Directory(path.join(confDir.path, "clients")).create();
Directory(path.join(confDir.path, "modules")).create();
File sdConfig = File(path.join(confDir.path, "speechd.conf"));
sdConfig.createSync();
sdConfig.writeAsString(sdConfigTemplate);
restartSD();
Timer(const Duration(seconds: 2), () {
confirmConfigChange(originalConfigDir);
});

// if changed config -> ask for confirmation
if (sdChanged) {
restartSD();
Timer(const Duration(seconds: 2), () {
confirmConfigChange(sdBackup, piperBackup);
});
}
}

Future<void> revertConfig(Directory? originalConfigDir) async {
Future<void> revertConfig(File? sdBackup, File? piperBackup) async {
Directory confDir =
Directory(path.join(getHome()!, ".config/speech-dispatcher"));
confDir.deleteSync(recursive: true);
if (originalConfigDir != null) {
originalConfigDir.rename(confDir.path);
File sdConfig = File(path.join(confDir.path, "speechd.conf"));
File piperConfig = File(path.join(confDir.path, "modules/piper.conf"));

// undo the Pied configuration
if (sdConfig.existsSync()) {
sdConfig.deleteSync();
}
if (piperConfig.existsSync()) {
piperConfig.deleteSync();
}

// restore backups
if (sdBackup != null && sdBackup.existsSync()) {
sdBackup.renameSync(sdConfig.path);
}
if (piperBackup != null && piperBackup.existsSync()) {
piperBackup.renameSync(piperConfig.path);
}

widget.onCurrentVoiceChanged("");
restartSD();

Timer(const Duration(seconds: 2), () {
showDialog<void>(
context: context,
Expand Down Expand Up @@ -136,13 +171,13 @@ class _VoiceButtonsState extends State<VoiceButtons> {
});
}

Future<void> confirmConfigChange(Directory? originalConfigDir) async {
Future<void> confirmConfigChange(File? sdBackup, File? piperBackup) async {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return ConfirmationDialog(onRevert: () {
revertConfig(originalConfigDir);
revertConfig(sdBackup, piperBackup);
});
});
}
Expand All @@ -161,12 +196,14 @@ class _VoiceButtonsState extends State<VoiceButtons> {
enabled: true,
child: ElevatedButton(
onPressed: () async {
setSDConfig();
await setSDConfig();

final Directory appDir = await getDataDir();
Directory modelDir =
Directory(path.join(appDir.path, "models"));
File modelConf = File(path.join(getHome()!,
".config/speech-dispatcher/modules/piper.conf"));

String configString = modelTemplate;
configString = configString.replaceAll("PIPER_PATH",
path.join(appDir.path, "piper", "piper"));
Expand All @@ -178,7 +215,15 @@ class _VoiceButtonsState extends State<VoiceButtons> {
"LANGUAGE", widget.voiceData[1]);
configString = configString.replaceAll(
"SUBVOICE", widget.selectedSubVoice.toString());
modelConf.writeAsString(configString);

String header = "# THIS CONFIG WAS GENERATED BY PIED\n";

if (!modelConf.parent.existsSync()) {
modelConf.parent.createSync(recursive: true);
}

// add pied signature to piper.conf
modelConf.writeAsString(header + configString);
restartSD();
widget.onCurrentVoiceChanged(widget.voiceData[4]);
widget.onCurrentSubVoiceChanged(
Expand Down