Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
ee8c8f65
Commit
ee8c8f65
authored
Jul 13, 2023
by
Shaun Ren
Committed by
Alexandre Julliard
Jul 21, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sapi: Implement ISpTTSEngineSite::GetActions/Rate/Volume.
parent
0d09ab37
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
87 additions
and
8 deletions
+87
-8
tts.c
dlls/sapi/tests/tts.c
+42
-2
tts.c
dlls/sapi/tts.c
+45
-6
No files found.
dlls/sapi/tests/tts.c
View file @
ee8c8f65
...
...
@@ -112,6 +112,8 @@ struct test_engine
DWORD
flags
;
GUID
fmtid
;
SPVTEXTFRAG
*
frag_list
;
LONG
rate
;
USHORT
volume
;
};
static
void
copy_frag_list
(
const
SPVTEXTFRAG
*
frag_list
,
SPVTEXTFRAG
**
ret_frag_list
)
...
...
@@ -154,6 +156,8 @@ static void reset_engine_params(struct test_engine *engine)
engine
->
speak_called
=
FALSE
;
engine
->
flags
=
0xdeadbeef
;
memset
(
&
engine
->
fmtid
,
0xde
,
sizeof
(
engine
->
fmtid
));
engine
->
rate
=
0xdeadbeef
;
engine
->
volume
=
0xbeef
;
for
(
frag
=
engine
->
frag_list
;
frag
;
frag
=
next
)
{
...
...
@@ -206,6 +210,7 @@ static HRESULT WINAPI test_engine_Speak(ISpTTSEngine *iface, DWORD flags, REFGUI
ISpTTSEngineSite
*
site
)
{
struct
test_engine
*
engine
=
impl_from_ISpTTSEngine
(
iface
);
DWORD
actions
;
char
*
buf
;
int
i
;
HRESULT
hr
;
...
...
@@ -215,11 +220,26 @@ static HRESULT WINAPI test_engine_Speak(ISpTTSEngine *iface, DWORD flags, REFGUI
copy_frag_list
(
frag_list
,
&
engine
->
frag_list
);
engine
->
speak_called
=
TRUE
;
actions
=
ISpTTSEngineSite_GetActions
(
site
);
ok
(
actions
==
(
SPVES_CONTINUE
|
SPVES_RATE
|
SPVES_VOLUME
),
"got %#lx.
\n
"
,
actions
);
hr
=
ISpTTSEngineSite_GetRate
(
site
,
&
engine
->
rate
);
ok
(
hr
==
S_OK
,
"got %#lx.
\n
"
,
hr
);
actions
=
ISpTTSEngineSite_GetActions
(
site
);
ok
(
actions
==
(
SPVES_CONTINUE
|
SPVES_VOLUME
),
"got %#lx.
\n
"
,
actions
);
hr
=
ISpTTSEngineSite_GetVolume
(
site
,
&
engine
->
volume
);
ok
(
hr
==
S_OK
,
"got %#lx.
\n
"
,
hr
);
actions
=
ISpTTSEngineSite_GetActions
(
site
);
ok
(
actions
==
SPVES_CONTINUE
,
"got %#lx.
\n
"
,
actions
);
buf
=
calloc
(
1
,
22050
*
2
/
5
);
for
(
i
=
0
;
i
<
5
;
i
++
)
{
if
(
ISpTTSEngineSite_GetActions
(
site
)
&
SPVES_ABORT
)
break
;
hr
=
ISpTTSEngineSite_Write
(
site
,
buf
,
22050
*
2
/
5
,
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx.
\n
"
,
hr
);
ok
(
hr
==
S_OK
||
hr
==
SP_AUDIO_STOPPED
,
"got %#lx.
\n
"
,
hr
);
Sleep
(
100
);
}
free
(
buf
);
...
...
@@ -507,7 +527,10 @@ static void test_spvoice(void)
ok
(
hr
==
S_OK
,
"got %#lx.
\n
"
,
hr
);
ok
(
stream_num
==
0xdeadbeef
,
"got %lu.
\n
"
,
stream_num
);
test_engine
.
speak_called
=
FALSE
;
ISpVoice_SetRate
(
voice
,
0
);
ISpVoice_SetVolume
(
voice
,
100
);
reset_engine_params
(
&
test_engine
);
stream_num
=
0xdeadbeef
;
start
=
GetTickCount
();
hr
=
ISpVoice_Speak
(
voice
,
test_text
,
SPF_DEFAULT
,
&
stream_num
);
...
...
@@ -520,6 +543,8 @@ static void test_spvoice(void)
ok
(
test_engine
.
frag_list
->
ulTextLen
==
wcslen
(
test_text
),
"got %lu.
\n
"
,
test_engine
.
frag_list
->
ulTextLen
);
ok
(
!
wcsncmp
(
test_text
,
test_engine
.
frag_list
->
pTextStart
,
wcslen
(
test_text
)),
"got %s.
\n
"
,
wine_dbgstr_w
(
test_engine
.
frag_list
->
pTextStart
));
ok
(
test_engine
.
rate
==
0
,
"got %ld.
\n
"
,
test_engine
.
rate
);
ok
(
test_engine
.
volume
==
100
,
"got %d.
\n
"
,
test_engine
.
volume
);
ok
(
stream_num
==
1
,
"got %lu.
\n
"
,
stream_num
);
ok
(
duration
>
800
&&
duration
<
3000
,
"took %lu ms.
\n
"
,
duration
);
...
...
@@ -540,6 +565,21 @@ static void test_spvoice(void)
ok
(
test_engine
.
frag_list
->
ulTextLen
==
wcslen
(
test_text
),
"got %lu.
\n
"
,
test_engine
.
frag_list
->
ulTextLen
);
ok
(
!
wcsncmp
(
test_text
,
test_engine
.
frag_list
->
pTextStart
,
wcslen
(
test_text
)),
"got %s.
\n
"
,
wine_dbgstr_w
(
test_engine
.
frag_list
->
pTextStart
));
ok
(
test_engine
.
rate
==
0
,
"got %ld.
\n
"
,
test_engine
.
rate
);
ok
(
test_engine
.
volume
==
100
,
"got %d.
\n
"
,
test_engine
.
volume
);
Sleep
(
2000
);
reset_engine_params
(
&
test_engine
);
hr
=
ISpVoice_Speak
(
voice
,
test_text
,
SPF_DEFAULT
|
SPF_ASYNC
,
NULL
);
ok
(
hr
==
S_OK
,
"got %#lx.
\n
"
,
hr
);
Sleep
(
200
);
start
=
GetTickCount
();
hr
=
ISpVoice_Speak
(
voice
,
NULL
,
SPF_PURGEBEFORESPEAK
,
NULL
);
duration
=
GetTickCount
()
-
start
;
ok
(
hr
==
S_OK
,
"got %#lx.
\n
"
,
hr
);
ok
(
duration
<
300
,
"took %lu ms.
\n
"
,
duration
);
done:
reset_engine_params
(
&
test_engine
);
...
...
dlls/sapi/tts.c
View file @
ee8c8f65
...
...
@@ -45,6 +45,7 @@ struct speech_voice
ISpStreamFormat
*
output
;
ISpTTSEngine
*
engine
;
LONG
cur_stream_num
;
DWORD
actions
;
USHORT
volume
;
LONG
rate
;
struct
async_queue
queue
;
...
...
@@ -777,6 +778,13 @@ static void speak_proc(struct async_task *task)
EnterCriticalSection
(
&
This
->
cs
);
if
(
This
->
actions
&
SPVES_ABORT
)
{
LeaveCriticalSection
(
&
This
->
cs
);
hr
=
S_OK
;
goto
done
;
}
if
(
FAILED
(
hr
=
set_output_format
(
This
->
output
,
This
->
engine
,
&
fmtid
,
&
wfx
)))
{
LeaveCriticalSection
(
&
This
->
cs
);
...
...
@@ -789,6 +797,8 @@ static void speak_proc(struct async_task *task)
if
(
SUCCEEDED
(
ISpStreamFormat_QueryInterface
(
This
->
output
,
&
IID_ISpAudio
,
(
void
**
)
&
audio
)))
ISpAudio_SetState
(
audio
,
SPAS_RUN
,
0
);
This
->
actions
=
SPVES_RATE
|
SPVES_VOLUME
;
LeaveCriticalSection
(
&
This
->
cs
);
hr
=
ISpTTSEngine_Speak
(
engine
,
speak_task
->
flags
,
&
fmtid
,
wfx
,
speak_task
->
frag_list
,
speak_task
->
site
);
...
...
@@ -847,6 +857,7 @@ static HRESULT WINAPI spvoice_Speak(ISpVoice *iface, const WCHAR *contents, DWOR
EnterCriticalSection
(
&
This
->
cs
);
This
->
actions
=
SPVES_ABORT
;
if
(
This
->
output
&&
SUCCEEDED
(
ISpStreamFormat_QueryInterface
(
This
->
output
,
&
IID_ISpAudio
,
(
void
**
)
&
audio
)))
{
ISpAudio_SetState
(
audio
,
SPAS_CLOSED
,
0
);
...
...
@@ -857,6 +868,10 @@ static HRESULT WINAPI spvoice_Speak(ISpVoice *iface, const WCHAR *contents, DWOR
async_empty_queue
(
&
This
->
queue
);
EnterCriticalSection
(
&
This
->
cs
);
This
->
actions
=
SPVES_CONTINUE
;
LeaveCriticalSection
(
&
This
->
cs
);
if
(
!
contents
||
!*
contents
)
return
S_OK
;
}
...
...
@@ -1007,6 +1022,7 @@ static HRESULT WINAPI spvoice_SetRate(ISpVoice *iface, LONG rate)
EnterCriticalSection
(
&
This
->
cs
);
This
->
rate
=
rate
;
This
->
actions
|=
SPVES_RATE
;
LeaveCriticalSection
(
&
This
->
cs
);
return
S_OK
;
...
...
@@ -1036,6 +1052,7 @@ static HRESULT WINAPI spvoice_SetVolume(ISpVoice *iface, USHORT volume)
EnterCriticalSection
(
&
This
->
cs
);
This
->
volume
=
volume
;
This
->
actions
|=
SPVES_VOLUME
;
LeaveCriticalSection
(
&
This
->
cs
);
return
S_OK
;
...
...
@@ -1205,9 +1222,16 @@ static HRESULT WINAPI ttsenginesite_GetEventInterest(ISpTTSEngineSite *iface, UL
static
DWORD
WINAPI
ttsenginesite_GetActions
(
ISpTTSEngineSite
*
iface
)
{
FIXME
(
"(%p): stub.
\n
"
,
iface
);
struct
tts_engine_site
*
This
=
impl_from_ISpTTSEngineSite
(
iface
);
DWORD
actions
;
TRACE
(
"(%p).
\n
"
,
iface
);
EnterCriticalSection
(
&
This
->
voice
->
cs
);
actions
=
This
->
voice
->
actions
;
LeaveCriticalSection
(
&
This
->
voice
->
cs
);
return
SPVES_CONTINUE
;
return
actions
;
}
static
HRESULT
WINAPI
ttsenginesite_Write
(
ISpTTSEngineSite
*
iface
,
const
void
*
buf
,
ULONG
cb
,
ULONG
*
cb_written
)
...
...
@@ -1224,16 +1248,30 @@ static HRESULT WINAPI ttsenginesite_Write(ISpTTSEngineSite *iface, const void *b
static
HRESULT
WINAPI
ttsenginesite_GetRate
(
ISpTTSEngineSite
*
iface
,
LONG
*
rate
)
{
FIXME
(
"(%p, %p): stub.
\n
"
,
iface
,
rat
e
);
struct
tts_engine_site
*
This
=
impl_from_ISpTTSEngineSite
(
ifac
e
);
return
E_NOTIMPL
;
TRACE
(
"(%p, %p).
\n
"
,
iface
,
rate
);
EnterCriticalSection
(
&
This
->
voice
->
cs
);
*
rate
=
This
->
voice
->
rate
;
This
->
voice
->
actions
&=
~
SPVES_RATE
;
LeaveCriticalSection
(
&
This
->
voice
->
cs
);
return
S_OK
;
}
static
HRESULT
WINAPI
ttsenginesite_GetVolume
(
ISpTTSEngineSite
*
iface
,
USHORT
*
volume
)
{
FIXME
(
"(%p, %p): stub.
\n
"
,
iface
,
volum
e
);
struct
tts_engine_site
*
This
=
impl_from_ISpTTSEngineSite
(
ifac
e
);
return
E_NOTIMPL
;
TRACE
(
"(%p, %p).
\n
"
,
iface
,
volume
);
EnterCriticalSection
(
&
This
->
voice
->
cs
);
*
volume
=
This
->
voice
->
volume
;
This
->
voice
->
actions
&=
~
SPVES_VOLUME
;
LeaveCriticalSection
(
&
This
->
voice
->
cs
);
return
S_OK
;
}
static
HRESULT
WINAPI
ttsenginesite_GetSkipInfo
(
ISpTTSEngineSite
*
iface
,
SPVSKIPTYPE
*
type
,
LONG
*
skip_count
)
...
...
@@ -1351,6 +1389,7 @@ HRESULT speech_voice_create(IUnknown *outer, REFIID iid, void **obj)
This
->
output
=
NULL
;
This
->
engine
=
NULL
;
This
->
cur_stream_num
=
0
;
This
->
actions
=
SPVES_CONTINUE
;
This
->
volume
=
100
;
This
->
rate
=
0
;
memset
(
&
This
->
queue
,
0
,
sizeof
(
This
->
queue
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment