/*************************************************************************
**
**    This file is part of the 'forwords' educational programm.
**    Copyright (C) 2024  Alexander Fomin
**
**    This program is free software: you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation, either version 3 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program.  If not, see <https://www.gnu.org/licenses/>.
**
**    Contact: fomin_alex@yahoo.com
**
**************************************************************************/

#include "tts.h"
#include "common.h"

tts::tts()
{
    //+++++++ check engines +++++++
    lEngines = new QStringList();
    *lEngines << "espeak-ng"<<"espeak";
    QString s;
    for (int i = lEngines->count()-1; i >= 0; --i)
    {
        lib.setFileName(lEngines->at(i));
        if(!lib.load())
            lEngines->removeAt(i);
    }
    vCurrentEngine = "";
}

const QStringList *tts::getVoiceList()
{
    //+++++++ espeak ++++++++++++++
    if(vCurrentEngine == "")
        return nullptr;
    const espeak_VOICE **voiceList = fListVoices(NULL);
    QStringList lvoices;
    const espeak_VOICE *voice;
    const char *name;
    while (*voiceList!=NULL)
    {
        voice = *voiceList;
        name = voice->name;
        lvoices.append(QString(name));
        ++voiceList;
    }
    if(lvoices.isEmpty())
        return nullptr;
    lVoices = new QStringList(lvoices);
    return lVoices;
}

bool tts::setVoice(QString voice)
{
    if(voice == "")
        return false;
    if(fSetVoice(voice.toStdString().data()) != EE_OK)
        return false;
    return true;
}

void tts::speakOut(QString text)
{
    //+++++++ espeak ++++++++++++++
    vSpeechBuffer.clear();
    vSpeechBuffer = text.toUtf8();
    int baLenght = vSpeechBuffer.size();
    fSynth(vSpeechBuffer.data(),baLenght,0,POS_CHARACTER,0,espeakCHARS_UTF8,NULL,NULL);
}

const QStringList *tts::getEngines()
{
    if(lEngines->isEmpty())
        return nullptr;
    return lEngines;
}

bool tts::setEngine(QString engine)
{
    if(engine == vCurrentEngine)
        return true;
    if(engine == "")
        return false;
    lib.setFileName(engine);
    if(lib.load())
    {
        fTTSinit = (ttsInit) lib.resolve("espeak_Initialize");
        if (!fTTSinit)
        {
            fShowMsg(engine + " resolve Initialize failed");
            return false;
        }
        if(!fTTSinit(AUDIO_OUTPUT_SYNCH_PLAYBACK,0,NULL,0))
        {
            fShowMsg(engine + " init failed");
            return false;
        }
        if(!(fListVoices = (ListVoices) lib.resolve("espeak_ListVoices")))
        {
            fShowMsg(engine + " resolve ListVoices failed");
            return false;
        }
        if(!(fSetVoice = (SetVoiceByName) lib.resolve("espeak_SetVoiceByName")))
        {
            fShowMsg(engine + " resolve SetVoiceByName failed");
            return false;
        }
        if(!(fSynth = (Synth) lib.resolve("espeak_Synth")))
        {
            fShowMsg(engine + " resolve Synth failed");
            return false;
        }
        vCurrentEngine = engine;
    }
    else
        return false;
    return true;
}

void tts::SpeachCancel()
{
    fEspeakCancel();
}

