/* Copyright (C) 2008, All rights reserved.
*
* Author: Chaoji Li<lichaoji@gmail.com>
* Date: May 27, 2008
*
* http://www.litchie.net
*/
#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <ctype.h>
#include <sapi.h>
#define MAX_WORD 4096
void usage()
{
printf("speak -l list all available voices\n");
printf("speak -q -l list all voices quietly\n");
printf("speak <sentence> speak the sentence out loud\n");
printf("speak -<digit> <sentence> speak the sentence using <digit>th voice\n");
printf("speak -h print this message\n");
printf("speak -f <file> speak the content of file\n");
}
int main(int argc, char* argv[])
{
HRESULT hr = S_OK;
ISpObjectToken* cpVoiceToken = 0;
IEnumSpObjectTokens* cpEnum = 0;
ISpVoice* cpVoice = 0;
ULONG ulCount = 0;
ISpObjectTokenCategory *cpCategory = 0;
wchar_t person[32] = L"";
wchar_t word[MAX_WORD];
int opt_list = 0;
int opt_index = 0;
int opt_quiet = 0;
if (argc < 2)
{
usage();
wcscpy(word, L"Give me your word.");
}
else
{
int i = 1;
int j = 0;
for (; i < argc; i++)
{
char *p = argv[i];
if (strcmp(p, "-l")==0)
{
opt_list = 1;
}
else if (strcmp(p, "-h") == 0)
{
usage();
wcscpy(word, L"Isn't it simple?");
}
else if (strcmp(p, "-f")==0)
{
if (++i == argc)
{
fprintf(stderr, "-f: missing a file argument\n");
goto Error;
}
else
{
char *filename = argv[i];
FILE *fp = fopen(filename, "r");
if (fp != NULL)
{
char buf[MAX_WORD];
int nread = 0;
nread = fread(buf, 1, MAX_WORD-1, fp);
buf[nread] = '\0';
int nconv = MultiByteToWideChar(
CP_ACP,
0,
buf,
strlen(buf),
&word[0],
MAX_WORD - 1
);
word[nconv] = 0;
fclose(fp);
}
break;
}
}
else if (strcmp(p, "-q")==0)
{
opt_quiet = 1;
}
else if (p[0] == '-' && isdigit(p[1]))
{
opt_index = p[1] - '0';
}
else
{
int n = MultiByteToWideChar(
CP_ACP,
0,
p,
strlen(p),
&word[j],
MAX_WORD - j - 2
);
j += n;
word[j++] = L' ';
word[j] = 0;
}
}
}
hr = CoInitialize(NULL);
if (FAILED(hr))
{
fprintf(stderr, "speak: cannot initialize COM\n");
goto Error;
}
hr = CoCreateInstance(
CLSID_SpVoice,
NULL,
CLSCTX_ALL,
IID_ISpVoice,
(void **)&cpVoice);
if (FAILED(hr))
{
fprintf(stderr, "speak: no voice\n");
goto Error;
}
hr = CoCreateInstance(
CLSID_SpObjectTokenCategory,
NULL,
CLSCTX_ALL,
IID_ISpObjectTokenCategory,
(void**)&cpCategory);
if (FAILED(hr) && opt_list)
{
fprintf(stderr, "speak: cannot enumerate voices\n");
goto Error;
}
else
{
cpCategory->SetId(SPCAT_VOICES, 0);
cpCategory->EnumTokens(NULL,NULL, &cpEnum);
if (cpEnum != 0)
{
hr = cpEnum->GetCount(&ulCount);
}
}
int index = 0;
while (cpEnum != 0 && ulCount--)
{
index++;
if (cpVoiceToken!=0)
{
cpVoiceToken->Release();
cpVoiceToken = 0;
}
hr = cpEnum->Next(1, &cpVoiceToken, NULL);
if (FAILED(hr))
{
break;
}
wchar_t * desc = 0;
cpVoiceToken->GetStringValue(NULL, &desc);
if (opt_list && desc != 0)
{
wsprintf(word, L"Hello, I am %s", desc);
wprintf(L"%d: %s\n", index, desc);
hr = cpVoice->SetVoice(cpVoiceToken);
if (SUCCEEDED (hr) && !opt_quiet)
{
hr = cpVoice->Speak(word, SPF_DEFAULT, NULL );
}
}
else if (opt_index == index)
{
hr = cpVoice->SetVoice(cpVoiceToken);
break;
}
}
if (opt_index > 0 && opt_index != index)
{
fprintf(stderr, "can't use %dth voice, use default voice\n", opt_index);
}
if (!opt_list && cpVoice != 0)
{
cpVoice->Speak(word, SPF_DEFAULT, NULL);
}
Error:
if (cpCategory != 0)
{
cpCategory->Release();
}
if (cpEnum != 0)
{
cpEnum->Release();
}
if (cpVoice != 0)
{
cpVoice->Release();
}
if (cpVoiceToken != 0)
{
cpVoiceToken->Release();
}
CoUninitialize();
return (SUCCEEDED(hr) ? 0 : -1);
}