blob: d4724bbb61c5c635637d273c2d59a39733102e69 [file] [edit]
/*
* BRLTTY - A background process providing access to the console screen (when in
* text mode) for a blind person using a refreshable braille display.
*
* Copyright (C) 1995-2023 by The BRLTTY Developers.
*
* BRLTTY comes with ABSOLUTELY NO WARRANTY.
*
* This is free software, placed under the terms of the
* GNU Lesser General Public License, as published by the Free Software
* Foundation; either version 2.1 of the License, or (at your option) any
* later version. Please see the file LICENSE-LGPL for details.
*
* Web Page: http://brltty.app/
*
* This software is maintained by Dave Mielke <dave@mielke.cc>.
*/
/* Swift/speech.c - Speech library
* For the Swift text to speech package
* Maintained by Dave Mielke <dave@mielke.cc>
*/
#include "prologue.h"
#include <stdio.h>
#include "log.h"
typedef enum {
PARM_NAME
} DriverParameter;
#define SPKPARMS "name"
#include "spk_driver.h"
#include <swift.h>
static swift_engine *swiftEngine = NULL;
static swift_port *swiftPort = NULL;
static void
speechError (swift_result_t result, const char *action) {
logMessage(LOG_ERR, "Swift %s error: %s", action, swift_strerror(result));
}
static int
setPortParameter (const char *name, swift_val *value) {
swift_result_t result = swift_port_set_param(swiftPort, name, value, SWIFT_ASYNC_NONE);
if (result == SWIFT_SUCCESS) return 1;
speechError(result, "parameter set");
return 0;
}
static int
setStringParameter (const char *name, const char *value) {
logMessage(LOG_DEBUG, "setting swift string parameter: %s=%s", name, value);
if (setPortParameter(name, swift_val_string(value))) return 1;
logMessage(LOG_WARNING, "Couldn't set %s=%s", name, value);
return 0;
}
static int
setIntegerParameter (const char *name, int value) {
logMessage(LOG_DEBUG, "setting swift integer parameter: %s=%d", name, value);
if (setPortParameter(name, swift_val_int(value))) return 1;
logMessage(LOG_WARNING, "Couldn't set %s=%d", name, value);
return 0;
}
static int
setVolume (int percentage) {
return setIntegerParameter("audio/volume", percentage);
}
static int
setRate (int wordsPerMinute) {
return setIntegerParameter("speech/rate", wordsPerMinute);
}
static int
setEnvironmentVariable (const char *name, const char *value) {
logMessage(LOG_DEBUG, "setting swift environment variable: %s=%s", name, value);
if (setenv(name, value, 1) != -1) return 1;
logSystemError("environment variable set");
return 0;
}
static void
spk_say (SpeechSynthesizer *spk, const unsigned char *buffer, size_t length, size_t count, const unsigned char *attributes) {
swift_result_t result;
swift_background_t job;
if ((result = swift_port_speak_text(swiftPort, buffer, length, NULL, &job, NULL)) != SWIFT_SUCCESS) {
speechError(result, "port speak");
}
}
static void
spk_mute (SpeechSynthesizer *spk) {
swift_result_t result;
if ((result = swift_port_stop(swiftPort, SWIFT_ASYNC_CURRENT, SWIFT_EVENT_NOW)) != SWIFT_SUCCESS) {
//speechError(result, "port stop");
}
}
static void
spk_setVolume (SpeechSynthesizer *spk, unsigned char setting) {
setVolume(getIntegerSpeechVolume(setting, 100));
}
static void
spk_setRate (SpeechSynthesizer *spk, unsigned char setting) {
setRate((int)(getFloatSpeechRate(setting) * 170.0));
}
static int
spk_construct (SpeechSynthesizer *spk, char **parameters) {
swift_result_t result;
spk->setVolume = spk_setVolume;
spk->setRate = spk_setRate;
if (setEnvironmentVariable("SWIFT_HOME", SWIFT_ROOT)) {
swift_params *engineParameters;
if ((engineParameters = swift_params_new(NULL))) {
if ((swiftEngine = swift_engine_open(engineParameters))) {
if ((swiftPort = swift_port_open(swiftEngine, NULL))) {
{
const char *name = parameters[PARM_NAME];
if (name && *name) {
swift_voice *voice;
if (*name == '/') {
logMessage(LOG_DEBUG, "setting swift voice directory: %s", name);
voice = swift_port_set_voice_from_dir(swiftPort, name);
} else {
logMessage(LOG_DEBUG, "setting swift voice name: %s", name);
voice = swift_port_set_voice_by_name(swiftPort, name);
}
if (!voice) {
logMessage(LOG_WARNING, "Swift voice set error: %s", name);
}
}
}
setStringParameter("tts/content-type", "text/plain");
logMessage(LOG_INFO, "Swift Engine: %s for %s, version %s, %s",
swift_engine_name, swift_platform, swift_version, swift_date);
return 1;
} else {
logMessage(LOG_ERR, "Swift port open error.");
}
if ((result = swift_engine_close(swiftEngine)) != SWIFT_SUCCESS) {
speechError(result, "engine close");
}
swiftEngine = NULL;
} else {
logMessage(LOG_ERR, "Swift engine open error.");
}
} else {
logMessage(LOG_ERR, "Swift engine parameters allocation error.");
}
}
return 0;
}
static void
spk_destruct (SpeechSynthesizer *spk) {
swift_result_t result;
if (swiftPort) {
if ((result = swift_port_close(swiftPort)) != SWIFT_SUCCESS) {
speechError(result, "port close");
}
swiftPort = NULL;
}
if (swiftEngine) {
if ((result = swift_engine_close(swiftEngine)) != SWIFT_SUCCESS) {
speechError(result, "engine close");
}
swiftEngine = NULL;
}
}