FS#13977 - rbutil: fix SAPI5 TTS test output and playback (Alessio Lenzi)

rockbox-gerrit-noreply--- via rockbox-cvs <[email protected]>
Newsgroups gmane.comp.systems.archos.rockbox.cvs
Message-ID <[email protected]>
commit 21e95258f2d3f7c8c62cd01872afe9926301bf8d
Author: Solomon Peachy <[email protected]>
Date:   Sun Aug 9 08:00:50 2026 -0400

    FS#13977 - rbutil: fix SAPI5 TTS test output and playback (Alessio Lenzi)
    
    After the SAPI5 error handling added for FS#13972, the Test TTS button
    can fail with SAPI error 5 even though the engine and voice are
    configured correctly. The test also destroys its QSoundEffect and
    temporary file before asynchronous playback can complete.
    
    Config::testTts() used a QTemporaryFile with no .wav extension.
    TTSSapi::voice() removes the requested output before synthesis so that a
    stale file cannot be mistaken for successful output. SAPI SpFileStream
    was therefore asked to create an extensionless output file and returned
    error 5 (invalid procedure call or argument).
    
    After successful synthesis, QSoundEffect was allocated on the stack, its
    loop count was set to zero, and the temporary file was removed when
    testTts() returned. This does not allow asynchronous playback to
    complete reliably.
    
     * create a temporary directory and requests an initially
       nonexistent tts-test.wav inside it;
     * keep the directory and generated wave file alive for playback;
     * keep QSoundEffect alive until playback finishes or fails;
     * request one playback and clean up all temporary data afterward.
    
    Change-Id: I8e482ab846e6445889118e121025ec48d3776d6b

diff --git a/utils/rbutilqt/configure.cpp b/utils/rbutilqt/configure.cpp
index 7b6d634c3f..d8a2a5a4c2 100644
--- a/utils/rbutilqt/configure.cpp
+++ b/utils/rbutilqt/configure.cpp
@@ -939,17 +939,20 @@ void Config::testTts()
     }
 
     QString filename;
-    QTemporaryFile file(this);
+    QTemporaryDir* tempDir = nullptr;
     // keep filename empty if the TTS can do speaking for itself.
     if(!(tts->capabilities() & TTSBase::CanSpeak)) {
-        file.open();
-        filename = file.fileName();
-        file.close();
+        // SAPI's SpFileStream requires a filename with a wave extension.
+        // Give the engine a path that does not exist yet, matching normal
+        // voice-file generation, and keep its directory until playback ends.
+        tempDir = new QTemporaryDir();
+        filename = tempDir->filePath("tts-test.wav");
     }
 
     if(tts->voice(tr("Rockbox Utility Voice Test"),filename,&errstr) == FatalError)
     {
         tts->stop();
+        delete tempDir;
         QMessageBox::warning(this,tr("Could not voice test string."),
                 tr("Could not voice test string.\n") + errstr
                 + tr("\nPlease configure TTS engine."));
@@ -957,17 +960,28 @@ void Config::testTts()
         return;
     }
     tts->stop();
-    if(!filename.isEmpty()) {
-        QSoundEffect effect;
-        effect.setSource(QUrl::fromLocalFile(filename));
-        effect.setLoopCount(0);
-        effect.setVolume(1.0f);
-        effect.play();
-    }
     ui.testTTS->setEnabled(true);
     delete tts; /* Config objects are never deleted (in fact, they are
                    leaked..), so we can't rely on QObject, since that would
                    delete the TTSBase instance on application exit */
+    if(tempDir != nullptr) {
+        QSoundEffect* effect = new QSoundEffect(this);
+        connect(effect, &QObject::destroyed, [tempDir]() {
+            delete tempDir;
+        });
+        connect(effect, &QSoundEffect::playingChanged, effect, [effect]() {
+            if(!effect->isPlaying())
+                effect->deleteLater();
+        });
+        connect(effect, &QSoundEffect::statusChanged, effect, [effect]() {
+            if(effect->status() == QSoundEffect::Error)
+                effect->deleteLater();
+        });
+        effect->setSource(QUrl::fromLocalFile(filename));
+        effect->setLoopCount(1);
+        effect->setVolume(1.0f);
+        effect->play();
+    }
 #endif
 }
 
-- 
rockbox-cvs mailing list
[email protected]
https://lists.haxx.se/mailman/listinfo/rockbox-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.