API de voz de Windows en Qt. Funciona en main (), pero muchos errores cuando está en clase
Frecuentes
Visto 1,412 veces
1
So I first tried to make a short example just to get text-to-speech working in main function. This worked and no problems. Code looks like this:
principal.cpp:
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include <QDebug>
#include <sapi.h>
#include <windows.h>
#include <atlbase.h>
#include "sphelper.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/GC/main.qml"));
viewer.showExpanded();
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
ISpVoice * pVoice = NULL;
ULONG count = 0;
if (FAILED(::CoInitialize(NULL)))
return FALSE;
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
if(SUCCEEDED(hr))
{
//Enumerate voices.
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
}
else
{
qDebug() << "Failed to initialize SAPI5";
}
if(SUCCEEDED(hr))
{
//Get number of voices.
hr = cpEnum->GetCount(&count);
qDebug() << "TTS voices found: " + QString::number(count);
}
else
{
qDebug() << "Failed to enumerate voices. Using default.";
hr = S_OK;
}
if(SUCCEEDED(hr))
{
cpVoiceToken.Release();
cpEnum->Item(4, &cpVoiceToken);
pVoice->SetVoice(cpVoiceToken);
hr = pVoice->Speak(L"Hello! How are you?", 0, NULL);
pVoice->Release();
pVoice = NULL;
}
::CoUninitialize();
qDebug() << "End";
return app.exec();
}
This outputs the number of voices I have installed on my computer and says the text: "Hello! How are you?".
When I now move this code to a class:
tts.h:
#ifndef TTS_H
#define TTS_H
#include <sapi.h>
#include <windows.h>
#include <atlbase.h>
#include "sphelper.h"
class Tts
{
public:
Tts();
bool Initialize();
HRESULT Speak(char * text, ISpVoice * pVoice);
private:
};
#endif // TTS_H
tts.cpp:
#include "tts.h"
#include <QDebug>
#include <sapi.h>
#include <windows.h>
#include <atlbase.h>
#include "sphelper.h"
Tts::Tts()
{
}
bool Tts::Initialize()
{
CComPtr<ISpObjectToken> cpVoiceToken;
CComPtr<IEnumSpObjectTokens> cpEnum;
ISpVoice * pVoice = NULL;
ULONG count = 0;
if (FAILED(::CoInitialize(NULL)))
return false;
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
if(SUCCEEDED(hr))
{
//Enumerate voices.
hr = SpEnumTokens(SPCAT_VOICES, NULL, NULL, &cpEnum);
}
else
{
qDebug() << "Failed to initialize SAPI5";
}
if(SUCCEEDED(hr))
{
//Get number of voices.
hr = cpEnum->GetCount(&count);
qDebug() << "TTS voices found: " + QString::number(count);
}
else
{
qDebug() << "Failed to enumerate voices. Using default.";
hr = S_OK;
}
if(SUCCEEDED(hr))
{
cpVoiceToken.Release();
cpEnum->Item(4, &cpVoiceToken);
pVoice->SetVoice(cpVoiceToken);
Speak("Some text here", pVoice);
pVoice->Release();
pVoice = NULL;
}
::CoUninitialize();
return true;
}
HRESULT Tts::Speak(char * text, ISpVoice * pVoice)
{
HRESULT hr;
hr = pVoice->Speak(L"Hello! How are you?", 0, NULL);
return hr;
}
Nueva principal.cpp:
#include <QtCore>
#include <QtGui/QGuiApplication>
#include <QtQuick>
#include "qtquick2applicationviewer.h"
#include <QDebug>
#include "tts.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
viewer.setMainQmlFile(QStringLiteral("qml/GC/main.qml"));
viewer.showExpanded();
viewer.showMaximized();
return app.exec();
}
I have just included the tts.h header file and get a lot of errors. I have tried rebuilding, cleaning and deleting the files in the build folder, but no luck. When building without the tts.h header file included in main the program runs as normal.
I don't understand why this happens when I move it to a class file. Here is the .pro file and errors:
.Pro:
# Add more folders to ship with the application, here
folder_01.source = qml/GC
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01
# Additional import path used to resolve QML modules in Creator's code model
QML_IMPORT_PATH =
# If your application uses the Qt Mobility libraries, uncomment the following
# lines and add the respective components to the MOBILITY variable.
# CONFIG += mobility
# MOBILITY +=
# The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp \
simkeyevent.cpp \
serialthread.cpp \
serial.cpp \
tts.cpp
# Installation path
# target.path =
# Please do not modify the following two lines. Required for deployment.
include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
qtcAddDeployment()
#Manually added:
QT += core gui serialport
HEADERS += \
simkeyevent.h \
serialthread.h \
serial.h \
tts.h
Errores:
1 Respuestas
1
I would refactor your tts.h
to forward-declare the ISpVoice interface, and remove all the dependencies; this would also reduce compilation time considerably.
#ifndef TTS_H
#define TTS_H
interface ISpVoice; // or struct ISpVoice, if GCC hates interface decls.
class Tts
{
public:
Tts();
bool Initialize();
HRESULT Speak(char * text, ISpVoice * pVoice);
private:
};
#endif // TTS_H
Alternatively, your #include order is a bit odd; you're #including sapi.h
antes windows.h
, and there are some dependencies between the two. Try reversing them.
You left the line numbers off the error listing, but it looks like the initial error is on this line in sapi.h:
typedef interface ISpNotifySource ISpNotifySource;
So I suspect that GCC is having some problems with the interface
keyword, and that some other header file is masking this.
respondido 28 nov., 13:01
I did as you said and used "struct ISpVoice" (it did not have the interface keyword) and removed the dependencies. This worked. I would really like to know why and what caused this problem. Could you say a few sentences about that? - nombre único aquí
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ qt sapi or haz tu propia pregunta.
Does sapi.h have include guards? The redefinition error suggests it doesn't and you include sapi.h multiple times. Try removing the includes from the .cpp (or the header, if they aren't needed there), so they are included only once in your code. - Frank Osterfeld
Yes sapi.h does. I tried as you said anyways, but still the same. - uniquenamehere