mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-11-03 22:26:48 +00:00
Create a skeleton SAPI TtsEngine COM object.
This commit is contained in:
@@ -16,19 +16,68 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#define INITGUID
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
HRESULT __stdcall DllGetClassObject(REFCLSID classId, REFIID iface, void **pObject)
|
||||
{
|
||||
if (!pObject)
|
||||
return E_POINTER;
|
||||
// {61D23633-CE59-4101-8158-569FC6B51B49}
|
||||
DEFINE_GUID(CLSID_TtsEngine, 0x61d23633, 0xce59, 0x4101, 0x81, 0x58, 0x56, 0x9f, 0xc6, 0xb5, 0x1b, 0x49);
|
||||
|
||||
*pObject = NULL;
|
||||
extern HRESULT __stdcall TtsEngine_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **object);
|
||||
|
||||
ULONG ObjectCount = 0;
|
||||
static ULONG LockCount = 0;
|
||||
|
||||
static ULONG __stdcall ClassFactory_AddRef(IClassFactory *iface)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ULONG __stdcall ClassFactory_Release(IClassFactory *iface)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HRESULT __stdcall ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **object)
|
||||
{
|
||||
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory)) {
|
||||
*object = iface;
|
||||
iface->lpVtbl->AddRef(iface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static HRESULT __stdcall ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
|
||||
{
|
||||
if (lock)
|
||||
InterlockedIncrement(&LockCount);
|
||||
else
|
||||
InterlockedDecrement(&LockCount);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IClassFactoryVtbl TtsEngine_ClassFactoryVtbl = {
|
||||
ClassFactory_QueryInterface,
|
||||
ClassFactory_AddRef,
|
||||
ClassFactory_Release,
|
||||
TtsEngine_CreateInstance,
|
||||
ClassFactory_LockServer
|
||||
};
|
||||
static IClassFactory TtsEngine_ClassFactory = { &TtsEngine_ClassFactoryVtbl };
|
||||
|
||||
HRESULT __stdcall DllGetClassObject(REFCLSID classId, REFIID iid, void **object)
|
||||
{
|
||||
if (IsEqualCLSID(classId, &CLSID_TtsEngine))
|
||||
return ClassFactory_QueryInterface(&TtsEngine_ClassFactory, iid, object);
|
||||
|
||||
*object = NULL;
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
HRESULT __stdcall DllCanUnloadNow(void)
|
||||
{
|
||||
return S_OK;
|
||||
return (ObjectCount == 0 && LockCount == 0) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Reece H. Dunn
|
||||
*
|
||||
* 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: <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <sapiddk.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
extern "C" ULONG ObjectCount;
|
||||
|
||||
struct TtsEngine
|
||||
: public ISpObjectWithToken
|
||||
, public ISpTTSEngine
|
||||
{
|
||||
TtsEngine();
|
||||
~TtsEngine();
|
||||
|
||||
// IUnknown
|
||||
|
||||
ULONG __stdcall AddRef();
|
||||
ULONG __stdcall Release();
|
||||
|
||||
HRESULT __stdcall QueryInterface(REFIID iid, void **object);
|
||||
|
||||
// ISpObjectWithToken
|
||||
|
||||
HRESULT __stdcall GetObjectToken(ISpObjectToken **token);
|
||||
HRESULT __stdcall SetObjectToken(ISpObjectToken *token);
|
||||
|
||||
// ISpTTSEngine
|
||||
|
||||
HRESULT __stdcall
|
||||
Speak(DWORD flags,
|
||||
REFGUID formatId,
|
||||
const WAVEFORMATEX *format,
|
||||
const SPVTEXTFRAG *textFragList,
|
||||
ISpTTSEngineSite *site);
|
||||
|
||||
HRESULT __stdcall
|
||||
GetOutputFormat(const GUID *targetFormatId,
|
||||
const WAVEFORMATEX *targetFormat,
|
||||
GUID *formatId,
|
||||
WAVEFORMATEX **format);
|
||||
private:
|
||||
ULONG refCount;
|
||||
};
|
||||
|
||||
TtsEngine::TtsEngine()
|
||||
: refCount(1)
|
||||
{
|
||||
InterlockedIncrement(&ObjectCount);
|
||||
}
|
||||
|
||||
TtsEngine::~TtsEngine()
|
||||
{
|
||||
InterlockedDecrement(&ObjectCount);
|
||||
}
|
||||
|
||||
ULONG __stdcall TtsEngine::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&refCount);
|
||||
}
|
||||
|
||||
ULONG __stdcall TtsEngine::Release()
|
||||
{
|
||||
ULONG ret = InterlockedDecrement(&refCount);
|
||||
if (ret == 0)
|
||||
delete this;
|
||||
return ret;
|
||||
}
|
||||
|
||||
HRESULT __stdcall TtsEngine::QueryInterface(REFIID iid, void **object)
|
||||
{
|
||||
*object = NULL;
|
||||
if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_ISpTTSEngine))
|
||||
*object = (ISpTTSEngine *)this;
|
||||
else if (IsEqualIID(iid, IID_ISpObjectWithToken))
|
||||
*object = (ISpObjectWithToken *)this;
|
||||
else
|
||||
return E_NOINTERFACE;
|
||||
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT __stdcall TtsEngine::GetObjectToken(ISpObjectToken **token)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT __stdcall TtsEngine::SetObjectToken(ISpObjectToken *token)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT __stdcall
|
||||
TtsEngine::Speak(DWORD flags,
|
||||
REFGUID formatId,
|
||||
const WAVEFORMATEX *format,
|
||||
const SPVTEXTFRAG *textFragList,
|
||||
ISpTTSEngineSite *site)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT __stdcall
|
||||
TtsEngine::GetOutputFormat(const GUID *targetFormatId,
|
||||
const WAVEFORMATEX *targetFormat,
|
||||
GUID *formatId,
|
||||
WAVEFORMATEX **format)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
extern "C" HRESULT __stdcall TtsEngine_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **object)
|
||||
{
|
||||
if (outer != NULL)
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
|
||||
TtsEngine *engine = new (std::nothrow) TtsEngine();
|
||||
if (!engine)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
HRESULT ret = engine->QueryInterface(iid, object);
|
||||
engine->Release();
|
||||
return ret;
|
||||
}
|
||||
@@ -178,6 +178,7 @@
|
||||
<ClCompile Include="..\libespeak-ng\voices.c" />
|
||||
<ClCompile Include="..\libespeak-ng\wavegen.c" />
|
||||
<ClCompile Include="com\comentrypoints.c" />
|
||||
<ClCompile Include="com\ttsengine.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\espeak-ng\espeak_ng.h" />
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
<ClCompile Include="com\comentrypoints.c">
|
||||
<Filter>Source Files\com</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="com\ttsengine.cpp">
|
||||
<Filter>Source Files\com</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="config.h">
|
||||
|
||||
Reference in New Issue
Block a user