Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make SAPI4 voices use WASAPI #17718

Merged
merged 23 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8152934
Make SAPI4 voices use WASAPI
gexgd0419 Feb 20, 2025
36d183e
Pre-commit auto-fix
pre-commit-ci[bot] Feb 21, 2025
ad95fea
Add type hints & doc strings
gexgd0419 Feb 21, 2025
302968a
Change log level in `cancel` to debugWarning, because error 0x8001000…
gexgd0419 Feb 21, 2025
df66a52
Reset `_startTime` on start
gexgd0419 Feb 22, 2025
d57d6c4
Implement LevelGet/Set
gexgd0419 Feb 22, 2025
2cc4a3e
Merge branch 'master' into sapi4-wasapi
gexgd0419 Feb 22, 2025
793a2be
Add changelog entry
gexgd0419 Feb 22, 2025
858ff5e
Change implementation, add docstring
gexgd0419 Feb 23, 2025
03ce810
Pre-commit auto-fix
pre-commit-ci[bot] Feb 23, 2025
a06d3f4
Stop the player when unclaiming with empty buffer
gexgd0419 Feb 24, 2025
edfca3e
Remove WinMM-related stuff
gexgd0419 Feb 24, 2025
024e528
Apply suggestions from code review
gexgd0419 Feb 25, 2025
2d0e7d3
Move TypeAlias definitions
gexgd0419 Feb 25, 2025
a23e5dc
Merge branch 'master' into sapi4-wasapi
gexgd0419 Feb 25, 2025
79016ec
Check if `_ttsAudio` is null before termination
gexgd0419 Feb 25, 2025
9603d31
Make AUDERR codes an enum
gexgd0419 Feb 25, 2025
8694ae4
Add comment and type hint
gexgd0419 Feb 25, 2025
e99c940
Release notifySink when terminated
gexgd0419 Feb 25, 2025
968261c
Remove SAPI 4 deprecation messages
gexgd0419 Feb 25, 2025
648b391
Add SAPI 4 links in projectDocs
gexgd0419 Feb 25, 2025
0ac0402
Apply suggestions from code review
seanbudd Feb 25, 2025
041bf7f
Update source/synthDrivers/sapi4.py
seanbudd Feb 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 82 additions & 15 deletions source/synthDrivers/_sapi4.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
sizeof,
Structure,
)
from ctypes.wintypes import BYTE, DWORD, LPCWSTR, WORD
from enum import IntEnum
from comtypes import GUID, IUnknown, STDMETHOD
from ctypes.wintypes import BOOL, BYTE, DWORD, FILETIME, LPCWSTR, WORD
from comtypes import GUID, IUnknown, STDMETHOD, COMMETHOD

import winKernel

Expand All @@ -43,6 +42,27 @@
TTSFEATURE_PITCH = 8
TTSFEATURE_FIXEDAUDIO = 1024

# Audio related error codes
AUDERR_BADDEVICEID = -2147220735
AUDERR_NEEDWAVEFORMAT = -2147220734
AUDERR_NOTSUPPORTED = -2147467263 # E_NOTIMPL
AUDERR_NOTENOUGHDATA = -2147220991
AUDERR_NOTPLAYING = -2147220730
AUDERR_WAVEFORMATNOTSUPPORTED = -2147220990
AUDERR_WAVEDEVICEBUSY = -2147220989
AUDERR_WAVEDEVNOTSUPPORTED = -2147220718
AUDERR_NOTRECORDING = -2147220717
AUDERR_INVALIDFLAG = -2147220988
AUDERR_NODRIVER = -2147220713
AUDERR_HANDLEBUSY = -2147220712
AUDERR_INVALIDNOTIFYSINK = -2147220711
AUDERR_WAVENOTENABLED = -2147220710
AUDERR_ALREADYCLAIMED = -2147220707
AUDERR_NOTCLAIMED = -2147220706
AUDERR_STILLPLAYING = -2147220705
AUDERR_ALREADYSTARTED = -2147220704
AUDERR_SYNCNOTALLOWED = -2147220703

LANGID = WORD
QWORD = c_ulonglong

Expand Down Expand Up @@ -224,21 +244,68 @@ class ITTSNotifySinkW(IUnknown):

ITTSNotifySink = ITTSNotifySinkW

CLSID_MMAudioDest = GUID("{CB96B400-C743-11cd-80E5-00AA003E4B50}")
CLSID_TTSEnumerator = GUID("{D67C0280-C743-11cd-80E5-00AA003E4B50}")

class IAudio(IUnknown):
_iid_ = GUID("{F546B340-C743-11cd-80E5-00AA003E4B50}")

# Defined in mmsyscom.h
MMSYSERR_NOERROR = 0

IAudio._methods_ = [
COMMETHOD([], HRESULT, "Flush"),
COMMETHOD([], HRESULT, "LevelGet", (["out"], POINTER(DWORD), "pdwLevel")),
COMMETHOD([], HRESULT, "LevelSet", (["in"], DWORD, "dwLevel")),
COMMETHOD(
[],
HRESULT,
"PassNotify",
(["in"], c_void_p, "pNotifyInterface"),
(["in"], GUID, "IIDNotifyInterface"),
),
COMMETHOD([], HRESULT, "PosnGet", (["out"], POINTER(QWORD), "pqwTimeStamp")),
COMMETHOD([], HRESULT, "Claim"),
COMMETHOD([], HRESULT, "UnClaim"),
COMMETHOD([], HRESULT, "Start"),
COMMETHOD([], HRESULT, "Stop"),
COMMETHOD([], HRESULT, "TotalGet", (["out"], POINTER(QWORD), "pqWord")),
COMMETHOD(
[],
HRESULT,
"ToFileTime",
(["in"], POINTER(QWORD), "pqWord"),
(["out"], POINTER(FILETIME), "pFT"),
),
COMMETHOD([], HRESULT, "WaveFormatGet", (["out"], POINTER(SDATA), "pdWFEX")),
COMMETHOD([], HRESULT, "WaveFormatSet", (["in"], SDATA, "dWFEX")),
]


class DriverMessage(IntEnum):
"""WaveOutMessage message codes
Defined in mmddk.h
"""
class IAudioDest(IUnknown):
_iid_ = GUID("{2EC34DA0-C743-11cd-80E5-00AA003E4B50}")

QUERY_INSTANCE_ID = 2065
"""DRV_QUERYFUNCTIONINSTANCEID """

QUERY_INSTANCE_ID_SIZE = 2066
"""DRV_QUERYFUNCTIONINSTANCEIDSIZE """
IAudioDest._methods_ = [
COMMETHOD(
[],
HRESULT,
"FreeSpace",
(["out"], POINTER(DWORD), "pdwBytes"),
(["out"], POINTER(BOOL), "pfEOF"),
),
COMMETHOD([], HRESULT, "DataSet", (["in"], c_void_p, "pBuffer"), (["in"], DWORD, "dwSize")),
COMMETHOD([], HRESULT, "BookMark", (["in"], DWORD, "dwMarkID")),
]


class IAudioDestNotifySink(IUnknown):
_iid_ = GUID("{ACB08C00-C743-11cd-80E5-00AA003E4B50}")


IAudioDestNotifySink._methods_ = [
STDMETHOD(HRESULT, "AudioStop", [WORD]),
STDMETHOD(HRESULT, "AudioStart"),
STDMETHOD(HRESULT, "FreeSpace", [DWORD, BOOL]),
STDMETHOD(HRESULT, "BookMark", [DWORD, BOOL]),
]


CLSID_MMAudioDest = GUID("{CB96B400-C743-11cd-80E5-00AA003E4B50}")
CLSID_TTSEnumerator = GUID("{D67C0280-C743-11cd-80E5-00AA003E4B50}")
Loading