Compare commits
No commits in common. "sapi4" and "master" have entirely different histories.
|
@ -1,44 +0,0 @@
|
||||||
BasedOnStyle: Google
|
|
||||||
|
|
||||||
# force T* or T&
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
PointerAlignment: Left
|
|
||||||
|
|
||||||
TabWidth: 4
|
|
||||||
IndentWidth: 4
|
|
||||||
UseTab: Always
|
|
||||||
IndentPPDirectives: BeforeHash
|
|
||||||
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
|
||||||
AllowShortBlocksOnASingleLine: false
|
|
||||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
|
||||||
|
|
||||||
BinPackArguments: true
|
|
||||||
BinPackParameters: true
|
|
||||||
BreakConstructorInitializers: BeforeColon
|
|
||||||
BreakStringLiterals: false
|
|
||||||
|
|
||||||
ColumnLimit: 150
|
|
||||||
CompactNamespaces: false
|
|
||||||
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|
||||||
ContinuationIndentWidth: 0
|
|
||||||
|
|
||||||
# turning this on causes major issues with initializer lists
|
|
||||||
Cpp11BracedListStyle: false
|
|
||||||
SpaceBeforeCpp11BracedList: true
|
|
||||||
|
|
||||||
FixNamespaceComments: true
|
|
||||||
|
|
||||||
NamespaceIndentation: All
|
|
||||||
ReflowComments: true
|
|
||||||
|
|
||||||
SortIncludes: CaseInsensitive
|
|
||||||
SortUsingDeclarations: true
|
|
||||||
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
SpaceBeforeParens: Never
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
|
@ -1,11 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
indent_style = tab
|
|
||||||
indent_size = 4
|
|
||||||
|
|
||||||
# specifically for YAML
|
|
||||||
[{yml, yaml}]
|
|
||||||
indent_style = space
|
|
370
.gitignore
vendored
370
.gitignore
vendored
|
@ -1,11 +1,363 @@
|
||||||
# ccls/clangd
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
.cache/
|
## files generated by popular Visual Studio add-ons.
|
||||||
**/bin/
|
##
|
||||||
**/obj/
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
# on your own machine, please.
|
# User-specific files
|
||||||
/speech2/build
|
*.rsuser
|
||||||
/speech2/build-debug
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
# cmake tools is viciously unaware of subdirectories
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
/build
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
201
.gitmodules
vendored
201
.gitmodules
vendored
|
@ -1,201 +0,0 @@
|
||||||
[submodule "speech2/third_party/boost/algorithm"]
|
|
||||||
path = speech2/third_party/boost/algorithm
|
|
||||||
url = https://github.com/boostorg/algorithm.git
|
|
||||||
[submodule "speech2/third_party/boost/align"]
|
|
||||||
path = speech2/third_party/boost/align
|
|
||||||
url = https://github.com/boostorg/align.git
|
|
||||||
[submodule "speech2/third_party/boost/array"]
|
|
||||||
path = speech2/third_party/boost/array
|
|
||||||
url = https://github.com/boostorg/array.git
|
|
||||||
[submodule "speech2/third_party/boost/assert"]
|
|
||||||
path = speech2/third_party/boost/assert
|
|
||||||
url = https://github.com/boostorg/assert.git
|
|
||||||
[submodule "speech2/third_party/boost/atomic"]
|
|
||||||
path = speech2/third_party/boost/atomic
|
|
||||||
url = https://github.com/boostorg/atomic.git
|
|
||||||
[submodule "speech2/third_party/boost/bind"]
|
|
||||||
path = speech2/third_party/boost/bind
|
|
||||||
url = https://github.com/boostorg/bind.git
|
|
||||||
[submodule "speech2/third_party/boost/charconv"]
|
|
||||||
path = speech2/third_party/boost/charconv
|
|
||||||
url = https://github.com/boostorg/charconv.git
|
|
||||||
[submodule "speech2/third_party/boost/chrono"]
|
|
||||||
path = speech2/third_party/boost/chrono
|
|
||||||
url = https://github.com/boostorg/chrono.git
|
|
||||||
[submodule "speech2/third_party/boost/circular_buffer"]
|
|
||||||
path = speech2/third_party/boost/circular_buffer
|
|
||||||
url = https://github.com/boostorg/circular_buffer.git
|
|
||||||
[submodule "speech2/third_party/boost/concept_check"]
|
|
||||||
path = speech2/third_party/boost/concept_check
|
|
||||||
url = https://github.com/boostorg/concept_check.git
|
|
||||||
[submodule "speech2/third_party/boost/config"]
|
|
||||||
path = speech2/third_party/boost/config
|
|
||||||
url = https://github.com/boostorg/config.git
|
|
||||||
[submodule "speech2/third_party/boost/container"]
|
|
||||||
path = speech2/third_party/boost/container
|
|
||||||
url = https://github.com/boostorg/container.git
|
|
||||||
[submodule "speech2/third_party/boost/container_hash"]
|
|
||||||
path = speech2/third_party/boost/container_hash
|
|
||||||
url = https://github.com/boostorg/container_hash.git
|
|
||||||
[submodule "speech2/third_party/boost/context"]
|
|
||||||
path = speech2/third_party/boost/context
|
|
||||||
url = https://github.com/boostorg/context.git
|
|
||||||
[submodule "speech2/third_party/boost/conversion"]
|
|
||||||
path = speech2/third_party/boost/conversion
|
|
||||||
url = https://github.com/boostorg/conversion.git
|
|
||||||
[submodule "speech2/third_party/boost/core"]
|
|
||||||
path = speech2/third_party/boost/core
|
|
||||||
url = https://github.com/boostorg/core.git
|
|
||||||
[submodule "speech2/third_party/boost/coroutine"]
|
|
||||||
path = speech2/third_party/boost/coroutine
|
|
||||||
url = https://github.com/boostorg/coroutine.git
|
|
||||||
[submodule "speech2/third_party/boost/date_time"]
|
|
||||||
path = speech2/third_party/boost/date_time
|
|
||||||
url = https://github.com/boostorg/date_time.git
|
|
||||||
[submodule "speech2/third_party/boost/describe"]
|
|
||||||
path = speech2/third_party/boost/describe
|
|
||||||
url = https://github.com/boostorg/describe.git
|
|
||||||
[submodule "speech2/third_party/boost/detail"]
|
|
||||||
path = speech2/third_party/boost/detail
|
|
||||||
url = https://github.com/boostorg/detail.git
|
|
||||||
[submodule "speech2/third_party/boost/endian"]
|
|
||||||
path = speech2/third_party/boost/endian
|
|
||||||
url = https://github.com/boostorg/endian.git
|
|
||||||
[submodule "speech2/third_party/boost/exception"]
|
|
||||||
path = speech2/third_party/boost/exception
|
|
||||||
url = https://github.com/boostorg/exception.git
|
|
||||||
[submodule "speech2/third_party/boost/filesystem"]
|
|
||||||
path = speech2/third_party/boost/filesystem
|
|
||||||
url = https://github.com/boostorg/filesystem.git
|
|
||||||
[submodule "speech2/third_party/boost/function"]
|
|
||||||
path = speech2/third_party/boost/function
|
|
||||||
url = https://github.com/boostorg/function.git
|
|
||||||
[submodule "speech2/third_party/boost/functional"]
|
|
||||||
path = speech2/third_party/boost/functional
|
|
||||||
url = https://github.com/boostorg/functional.git
|
|
||||||
[submodule "speech2/third_party/boost/function_types"]
|
|
||||||
path = speech2/third_party/boost/function_types
|
|
||||||
url = https://github.com/boostorg/function_types.git
|
|
||||||
[submodule "speech2/third_party/boost/fusion"]
|
|
||||||
path = speech2/third_party/boost/fusion
|
|
||||||
url = https://github.com/boostorg/fusion.git
|
|
||||||
[submodule "speech2/third_party/boost/integer"]
|
|
||||||
path = speech2/third_party/boost/integer
|
|
||||||
url = https://github.com/boostorg/integer.git
|
|
||||||
[submodule "speech2/third_party/boost/intrusive"]
|
|
||||||
path = speech2/third_party/boost/intrusive
|
|
||||||
url = https://github.com/boostorg/intrusive.git
|
|
||||||
[submodule "speech2/third_party/boost/io"]
|
|
||||||
path = speech2/third_party/boost/io
|
|
||||||
url = https://github.com/boostorg/io.git
|
|
||||||
[submodule "speech2/third_party/boost/iterator"]
|
|
||||||
path = speech2/third_party/boost/iterator
|
|
||||||
url = https://github.com/boostorg/iterator.git
|
|
||||||
[submodule "speech2/third_party/boost/json"]
|
|
||||||
path = speech2/third_party/boost/json
|
|
||||||
url = https://github.com/boostorg/json.git
|
|
||||||
[submodule "speech2/third_party/boost/leaf"]
|
|
||||||
path = speech2/third_party/boost/leaf
|
|
||||||
url = https://github.com/boostorg/leaf.git
|
|
||||||
[submodule "speech2/third_party/boost/lexical_cast"]
|
|
||||||
path = speech2/third_party/boost/lexical_cast
|
|
||||||
url = https://github.com/boostorg/lexical_cast.git
|
|
||||||
[submodule "speech2/third_party/boost/lockfree"]
|
|
||||||
path = speech2/third_party/boost/lockfree
|
|
||||||
url = https://github.com/boostorg/lockfree.git
|
|
||||||
[submodule "speech2/third_party/boost/logic"]
|
|
||||||
path = speech2/third_party/boost/logic
|
|
||||||
url = https://github.com/boostorg/logic.git
|
|
||||||
[submodule "speech2/third_party/boost/move"]
|
|
||||||
path = speech2/third_party/boost/move
|
|
||||||
url = https://github.com/boostorg/move.git
|
|
||||||
[submodule "speech2/third_party/boost/mp11"]
|
|
||||||
path = speech2/third_party/boost/mp11
|
|
||||||
url = https://github.com/boostorg/mp11.git
|
|
||||||
[submodule "speech2/third_party/boost/mpl"]
|
|
||||||
path = speech2/third_party/boost/mpl
|
|
||||||
url = https://github.com/boostorg/mpl.git
|
|
||||||
[submodule "speech2/third_party/boost/numeric_conversion"]
|
|
||||||
path = speech2/third_party/boost/numeric_conversion
|
|
||||||
url = https://github.com/boostorg/numeric_conversion.git
|
|
||||||
[submodule "speech2/third_party/boost/optional"]
|
|
||||||
path = speech2/third_party/boost/optional
|
|
||||||
url = https://github.com/boostorg/optional.git
|
|
||||||
[submodule "speech2/third_party/boost/parameter"]
|
|
||||||
path = speech2/third_party/boost/parameter
|
|
||||||
url = https://github.com/boostorg/parameter.git
|
|
||||||
[submodule "speech2/third_party/boost/pool"]
|
|
||||||
path = speech2/third_party/boost/pool
|
|
||||||
url = https://github.com/boostorg/pool.git
|
|
||||||
[submodule "speech2/third_party/boost/predef"]
|
|
||||||
path = speech2/third_party/boost/predef
|
|
||||||
url = https://github.com/boostorg/predef.git
|
|
||||||
[submodule "speech2/third_party/boost/preprocessor"]
|
|
||||||
path = speech2/third_party/boost/preprocessor
|
|
||||||
url = https://github.com/boostorg/preprocessor.git
|
|
||||||
[submodule "speech2/third_party/boost/range"]
|
|
||||||
path = speech2/third_party/boost/range
|
|
||||||
url = https://github.com/boostorg/range.git
|
|
||||||
[submodule "speech2/third_party/boost/ratio"]
|
|
||||||
path = speech2/third_party/boost/ratio
|
|
||||||
url = https://github.com/boostorg/ratio.git
|
|
||||||
[submodule "speech2/third_party/boost/rational"]
|
|
||||||
path = speech2/third_party/boost/rational
|
|
||||||
url = https://github.com/boostorg/rational.git
|
|
||||||
[submodule "speech2/third_party/boost/regex"]
|
|
||||||
path = speech2/third_party/boost/regex
|
|
||||||
url = https://github.com/boostorg/regex.git
|
|
||||||
[submodule "speech2/third_party/boost/scope"]
|
|
||||||
path = speech2/third_party/boost/scope
|
|
||||||
url = https://github.com/boostorg/scope.git
|
|
||||||
[submodule "speech2/third_party/boost/smart_ptr"]
|
|
||||||
path = speech2/third_party/boost/smart_ptr
|
|
||||||
url = https://github.com/boostorg/smart_ptr.git
|
|
||||||
[submodule "speech2/third_party/boost/static_assert"]
|
|
||||||
path = speech2/third_party/boost/static_assert
|
|
||||||
url = https://github.com/boostorg/static_assert.git
|
|
||||||
[submodule "speech2/third_party/boost/static_string"]
|
|
||||||
path = speech2/third_party/boost/static_string
|
|
||||||
url = https://github.com/boostorg/static_string.git
|
|
||||||
[submodule "speech2/third_party/boost/system"]
|
|
||||||
path = speech2/third_party/boost/system
|
|
||||||
url = https://github.com/boostorg/system.git
|
|
||||||
[submodule "speech2/third_party/boost/throw_exception"]
|
|
||||||
path = speech2/third_party/boost/throw_exception
|
|
||||||
url = https://github.com/boostorg/throw_exception.git
|
|
||||||
[submodule "speech2/third_party/boost/tokenizer"]
|
|
||||||
path = speech2/third_party/boost/tokenizer
|
|
||||||
url = https://github.com/boostorg/tokenizer.git
|
|
||||||
[submodule "speech2/third_party/boost/tuple"]
|
|
||||||
path = speech2/third_party/boost/tuple
|
|
||||||
url = https://github.com/boostorg/tuple.git
|
|
||||||
[submodule "speech2/third_party/boost/type_index"]
|
|
||||||
path = speech2/third_party/boost/type_index
|
|
||||||
url = https://github.com/boostorg/type_index.git
|
|
||||||
[submodule "speech2/third_party/boost/typeof"]
|
|
||||||
path = speech2/third_party/boost/typeof
|
|
||||||
url = https://github.com/boostorg/typeof.git
|
|
||||||
[submodule "speech2/third_party/boost/type_traits"]
|
|
||||||
path = speech2/third_party/boost/type_traits
|
|
||||||
url = https://github.com/boostorg/type_traits.git
|
|
||||||
[submodule "speech2/third_party/boost/unordered"]
|
|
||||||
path = speech2/third_party/boost/unordered
|
|
||||||
url = https://github.com/boostorg/unordered.git
|
|
||||||
[submodule "speech2/third_party/boost/url"]
|
|
||||||
path = speech2/third_party/boost/url
|
|
||||||
url = https://github.com/boostorg/url.git
|
|
||||||
[submodule "speech2/third_party/boost/utility"]
|
|
||||||
path = speech2/third_party/boost/utility
|
|
||||||
url = https://github.com/boostorg/utility.git
|
|
||||||
[submodule "speech2/third_party/boost/variant2"]
|
|
||||||
path = speech2/third_party/boost/variant2
|
|
||||||
url = https://github.com/boostorg/variant2.git
|
|
||||||
[submodule "speech2/third_party/boost/winapi"]
|
|
||||||
path = speech2/third_party/boost/winapi
|
|
||||||
url = https://github.com/boostorg/winapi.git
|
|
||||||
[submodule "speech2/third_party/boost/asio"]
|
|
||||||
path = speech2/third_party/boost/asio
|
|
||||||
url = https://github.com/boostorg/asio.git
|
|
||||||
[submodule "speech2/third_party/boost/beast"]
|
|
||||||
path = speech2/third_party/boost/beast
|
|
||||||
url = https://github.com/boostorg/beast.git
|
|
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"cmake.sourceDirectory": "${workspaceFolder}/speech2",
|
|
||||||
"cmake.configureArgs": [
|
|
||||||
"--toolchain cmake/clangcl-winxp.cmake"
|
|
||||||
],
|
|
||||||
"cmake.configureEnvironment": {
|
|
||||||
"VCDIR": "${env:HOME}/vs2022"
|
|
||||||
},
|
|
||||||
"cmake.ignoreCMakeListsMissing": true,
|
|
||||||
}
|
|
11
Justfile
11
Justfile
|
@ -1,11 +0,0 @@
|
||||||
build:
|
|
||||||
cd speech2; cmake --toolchain cmake/clangcl-winxp.cmake -GNinja -Bbuild; cd ..
|
|
||||||
cd speech2; cd build; ninja; cd ..; cd ..;
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf SAPIServer/bin SAPIServer/obj
|
|
||||||
make -C speech2 clean
|
|
||||||
|
|
||||||
|
|
||||||
format:
|
|
||||||
cd SAPIServer; for f in *.cs; do clang-format -i $f; done; cd ..;
|
|
13
README.md
13
README.md
|
@ -2,17 +2,6 @@
|
||||||
|
|
||||||
Simple HTTP frontend API for Microsoft Speech API
|
Simple HTTP frontend API for Microsoft Speech API
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
- .NET SDK
|
|
||||||
- VS2022 lib pack (TODO: link)
|
|
||||||
- LLVM toolchain
|
|
||||||
|
|
||||||
You'll also need to chattr +F (or mount the whole thing with `ciopfs` and rename the headers to lowercase, if not on ext4 or you don't want to tune2fs) the windows sdk header directories so the build works.
|
|
||||||
|
|
||||||
`just` should do the trick.
|
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -38,4 +27,4 @@ Content-Type: application/json
|
||||||
{"text":"Lorem ipsum doler sit amet...","voice":"Microsoft Sam"}
|
{"text":"Lorem ipsum doler sit amet...","voice":"Microsoft Sam"}
|
||||||
```
|
```
|
||||||
|
|
||||||
Returns synthesized TTS audio as a wave-form file.
|
Returns synthesized TTS audio as a wave-form file.
|
|
@ -3,103 +3,112 @@ using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace SAPIServer {
|
namespace SAPIServer
|
||||||
/// <summary>
|
{
|
||||||
/// Simple routing HTTP server for .NET Framework
|
/// <summary>
|
||||||
/// </summary>
|
/// Simple routing HTTP server for .NET Framework
|
||||||
class HTTPServer {
|
/// </summary>
|
||||||
private bool listening = false;
|
class HTTPServer
|
||||||
private HttpListener listener;
|
{
|
||||||
private Dictionary<string, Func<HttpListenerContext, byte[]>> GETListeners;
|
private bool listening = false;
|
||||||
private Dictionary<string, Func<HttpListenerContext, byte[]>> POSTListeners;
|
private HttpListener listener;
|
||||||
|
private Dictionary<string, Func<HttpListenerContext, byte[]>> GETListeners;
|
||||||
|
private Dictionary<string, Func<HttpListenerContext, byte[]>> POSTListeners;
|
||||||
|
|
||||||
public HTTPServer() {
|
public HTTPServer()
|
||||||
listener = new HttpListener();
|
{
|
||||||
this.GETListeners = new Dictionary<string, Func<HttpListenerContext, byte[]>>();
|
listener = new HttpListener();
|
||||||
this.POSTListeners = new Dictionary<string, Func<HttpListenerContext, byte[]>>();
|
this.GETListeners = new Dictionary<string, Func<HttpListenerContext, byte[]>>();
|
||||||
}
|
this.POSTListeners = new Dictionary<string, Func<HttpListenerContext, byte[]>>();
|
||||||
|
}
|
||||||
|
|
||||||
public void Get(string uri, Func<HttpListenerContext, byte[]> handler) {
|
public void Get(string uri, Func<HttpListenerContext, byte[]> handler)
|
||||||
if(GETListeners.ContainsKey(uri))
|
{
|
||||||
throw new InvalidOperationException("A handler by that URI already exists.");
|
if (GETListeners.ContainsKey(uri)) throw new InvalidOperationException("A handler by that URI already exists.");
|
||||||
if(!uri.StartsWith("/"))
|
if (!uri.StartsWith("/")) throw new ArgumentException("URIs must start with /");
|
||||||
throw new ArgumentException("URIs must start with /");
|
this.GETListeners.Add(uri, handler);
|
||||||
this.GETListeners.Add(uri, handler);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void Post(string uri, Func<HttpListenerContext, byte[]> handler) {
|
public void Post(string uri, Func<HttpListenerContext, byte[]> handler)
|
||||||
if(POSTListeners.ContainsKey(uri))
|
{
|
||||||
throw new InvalidOperationException("A handler by that URI already exists.");
|
if (POSTListeners.ContainsKey(uri)) throw new InvalidOperationException("A handler by that URI already exists.");
|
||||||
if(!uri.StartsWith("/"))
|
if (!uri.StartsWith("/")) throw new ArgumentException("URIs must start with /");
|
||||||
throw new ArgumentException("URIs must start with /");
|
this.POSTListeners.Add(uri, handler);
|
||||||
this.POSTListeners.Add(uri, handler);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void Listen(ushort port) {
|
public void Listen(ushort port)
|
||||||
if(listening)
|
{
|
||||||
throw new InvalidOperationException("This HTTPServer is already listening.");
|
if (listening) throw new InvalidOperationException("This HTTPServer is already listening.");
|
||||||
listening = true;
|
listening = true;
|
||||||
listener.Prefixes.Add(string.Format("http://*:{0}/", port));
|
listener.Prefixes.Add(string.Format("http://*:{0}/", port));
|
||||||
listener.Start();
|
listener.Start();
|
||||||
|
while (listener.IsListening)
|
||||||
|
{
|
||||||
|
var context = listener.GetContext();
|
||||||
|
ThreadPool.QueueUserWorkItem(_ =>
|
||||||
|
{
|
||||||
|
var uri = context.Request.RawUrl.Split('?')[0];
|
||||||
|
var ip = context.Request.RemoteEndPoint.Address;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dictionary<string, Func<HttpListenerContext, byte[]>> handlerDict;
|
||||||
|
// TODO: Make query params parsable
|
||||||
|
byte[] response;
|
||||||
|
switch (context.Request.HttpMethod)
|
||||||
|
{
|
||||||
|
case "GET":
|
||||||
|
{
|
||||||
|
handlerDict = GETListeners;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "POST":
|
||||||
|
{
|
||||||
|
handlerDict = POSTListeners;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
response = Encoding.UTF8.GetBytes($"Method not allowed: {context.Request.HttpMethod}");
|
||||||
|
context.Response.StatusCode = 405;
|
||||||
|
context.Response.ContentType = "text/plain";
|
||||||
|
context.Response.ContentLength64 = response.Length;
|
||||||
|
context.Response.OutputStream.Write(response, 0, response.Length);
|
||||||
|
context.Response.OutputStream.Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!handlerDict.TryGetValue(uri, out var handler))
|
||||||
|
{
|
||||||
|
response = Encoding.UTF8.GetBytes($"No route defined for {uri}");
|
||||||
|
context.Response.StatusCode = 404;
|
||||||
|
context.Response.ContentType = "text/plain";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
response = handler(context);
|
||||||
|
} catch (Exception e)
|
||||||
|
{
|
||||||
|
response = Encoding.UTF8.GetBytes("Internal Server Error");
|
||||||
|
context.Response.StatusCode = 500;
|
||||||
|
context.Response.ContentType = "text/plain";
|
||||||
|
Console.Error.WriteLine($"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Handler Failed: {e.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(listener.IsListening) {
|
context.Response.ContentLength64 = response.Length;
|
||||||
var context = listener.GetContext();
|
context.Response.OutputStream.Write(response, 0, response.Length);
|
||||||
ThreadPool.QueueUserWorkItem(
|
context.Response.OutputStream.Close();
|
||||||
_ => {
|
Console.WriteLine($"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - {context.Response.StatusCode}");
|
||||||
var uri = context.Request.RawUrl.Split('?')[0];
|
} catch (Exception e)
|
||||||
var ip = context.Request.RemoteEndPoint.Address;
|
{
|
||||||
try {
|
Console.Error.WriteLine($"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Exception: {e.Message}");
|
||||||
Dictionary<string, Func<HttpListenerContext, byte[]>> handlerDict;
|
}
|
||||||
// TODO: Make query params parsable
|
|
||||||
byte[] response;
|
|
||||||
switch(context.Request.HttpMethod) {
|
|
||||||
case "GET": {
|
|
||||||
handlerDict = GETListeners;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "POST": {
|
|
||||||
handlerDict = POSTListeners;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
response = Encoding.UTF8.GetBytes($"Method not allowed: {context.Request.HttpMethod}");
|
|
||||||
context.Response.StatusCode = 405;
|
|
||||||
context.Response.ContentType = "text/plain";
|
|
||||||
context.Response.ContentLength64 = response.Length;
|
|
||||||
context.Response.OutputStream.Write(response, 0, response.Length);
|
|
||||||
context.Response.OutputStream.Close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!handlerDict.TryGetValue(uri, out var handler)) {
|
|
||||||
response = Encoding.UTF8.GetBytes($"No route defined for {uri}");
|
|
||||||
context.Response.StatusCode = 404;
|
|
||||||
context.Response.ContentType = "text/plain";
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
response = handler(context);
|
|
||||||
} catch(Exception e) {
|
|
||||||
response = Encoding.UTF8.GetBytes("Internal Server Error");
|
|
||||||
context.Response.StatusCode = 500;
|
|
||||||
context.Response.ContentType = "text/plain";
|
|
||||||
Console.Error.WriteLine(
|
|
||||||
$"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Handler Failed: {e.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Response.ContentLength64 = response.Length;
|
});
|
||||||
context.Response.OutputStream.Write(response, 0, response.Length);
|
}
|
||||||
context.Response.OutputStream.Close();
|
}
|
||||||
Console.WriteLine(
|
}
|
||||||
$"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - {context.Response.StatusCode}");
|
|
||||||
} catch(Exception e) {
|
|
||||||
Console.Error.WriteLine(
|
|
||||||
$"[{DateTime.Now:u}] {ip} - {context.Request.HttpMethod} {context.Request.RawUrl} - Exception: {e.Message}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,80 +6,69 @@ using System.Speech.Synthesis;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace SAPIServer {
|
namespace SAPIServer
|
||||||
|
{
|
||||||
class SpeechServer {
|
class Program
|
||||||
private Dictionary<string, SpeechAPI> apis = new();
|
{
|
||||||
private HTTPServer httpServer = new();
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
public SpeechServer() {
|
if (args.Length < 1 || !ushort.TryParse(args[0], out var port))
|
||||||
// Test out creating a speech2 api object
|
{
|
||||||
apis["sapi4"] = new SpeechAPI(EngineType.ET_SAPI4);
|
Console.Error.WriteLine("Usage: SAPIServer.exe <port>");
|
||||||
#if true
|
Environment.Exit(1);
|
||||||
foreach(var voice in apis["sapi4"].GetVoices()) {
|
return;
|
||||||
Console.WriteLine($"ggg {voice.name}");
|
}
|
||||||
}
|
var http = new HTTPServer();
|
||||||
#endif
|
http.Get("/api/voices", ctx =>
|
||||||
|
{
|
||||||
httpServer.Get("/api/voices", ctx => {
|
using (var synth = new SpeechSynthesizer())
|
||||||
/*
|
{
|
||||||
using(var synth = new SpeechSynthesizer()) {
|
ctx.Response.ContentType = "application/json";
|
||||||
ctx.Response.ContentType = "application/json";
|
return Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new VoicesResponse
|
||||||
return Encoding.UTF8.GetBytes(
|
{
|
||||||
JsonConvert.SerializeObject(new VoicesResponse { voices = synth.GetInstalledVoices().Select(v => v.VoiceInfo.Name).ToArray() }));
|
voices = synth.GetInstalledVoices().Select(v => v.VoiceInfo.Name).ToArray()
|
||||||
}*/
|
}));
|
||||||
|
}
|
||||||
return new byte[]{0};
|
});
|
||||||
});
|
http.Post("/api/synthesize", ctx =>
|
||||||
|
{
|
||||||
httpServer.Post("/api/synthesize", ctx => {
|
SynthesizePayload body;
|
||||||
SynthesizePayload body;
|
try
|
||||||
try {
|
{
|
||||||
string bodyraw;
|
string bodyraw;
|
||||||
using(var reader = new StreamReader(ctx.Request.InputStream)) {
|
using (var reader = new StreamReader(ctx.Request.InputStream))
|
||||||
bodyraw = reader.ReadToEnd();
|
{
|
||||||
}
|
bodyraw = reader.ReadToEnd();
|
||||||
body = JsonConvert.DeserializeObject<SynthesizePayload>(bodyraw);
|
}
|
||||||
} catch(Exception) {
|
body = JsonConvert.DeserializeObject<SynthesizePayload>(bodyraw);
|
||||||
ctx.Response.StatusCode = 400;
|
}
|
||||||
return Encoding.UTF8.GetBytes("Bad payload");
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
if(body == null || body.text == null || body.voice == null) {
|
ctx.Response.StatusCode = 400;
|
||||||
ctx.Response.StatusCode = 400;
|
return Encoding.UTF8.GetBytes("Bad payload");
|
||||||
return Encoding.UTF8.GetBytes("Bad payload");
|
}
|
||||||
}
|
if (body == null || body.text == null || body.voice == null)
|
||||||
using(var ms = new MemoryStream()) {
|
{
|
||||||
using(var synth = new SpeechSynthesizer()) {
|
ctx.Response.StatusCode = 400;
|
||||||
if(!synth.GetInstalledVoices().Any(v => v.VoiceInfo.Name == body.voice)) {
|
return Encoding.UTF8.GetBytes("Bad payload");
|
||||||
ctx.Response.StatusCode = 400;
|
}
|
||||||
return Encoding.UTF8.GetBytes("Voice not found");
|
using (var ms = new MemoryStream())
|
||||||
}
|
using (var synth = new SpeechSynthesizer())
|
||||||
synth.SelectVoice(body.voice);
|
{
|
||||||
synth.SetOutputToWaveStream(ms);
|
if (!synth.GetInstalledVoices().Any(v => v.VoiceInfo.Name == body.voice))
|
||||||
synth.Speak(body.text);
|
{
|
||||||
ctx.Response.ContentType = "audio/wav";
|
ctx.Response.StatusCode = 400;
|
||||||
return ms.ToArray();
|
return Encoding.UTF8.GetBytes("Voice not found");
|
||||||
}
|
}
|
||||||
}
|
synth.SelectVoice(body.voice);
|
||||||
});
|
synth.SetOutputToWaveStream(ms);
|
||||||
}
|
synth.Speak(body.text);
|
||||||
|
ctx.Response.ContentType = "audio/wav";
|
||||||
public void Start(ushort port) {
|
return ms.ToArray();
|
||||||
Console.WriteLine($"[{DateTime.Now:u}] Starting HTTP server on port {port}");
|
}
|
||||||
httpServer.Listen(port);
|
});
|
||||||
}
|
Console.WriteLine($"[{ DateTime.Now:u}] Starting HTTP server on port {port}");
|
||||||
}
|
http.Listen(port);
|
||||||
|
}
|
||||||
class Program {
|
}
|
||||||
static void Main(string[] args) {
|
|
||||||
if(args.Length < 1 || !ushort.TryParse(args[0], out var port)) {
|
|
||||||
Console.Error.WriteLine("Usage: SAPIServer.exe <port>");
|
|
||||||
Environment.Exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var server = new SpeechServer();
|
|
||||||
server.Start(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,58 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Older VS generated one for us; we're just using that one.
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
Unless we wanna use the generated one?? -->
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<ProjectGuid>{BF824074-4C4E-4DE1-8DCA-F022682B00E1}</ProjectGuid>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>net40</TargetFrameworks>
|
<RootNamespace>SAPIServer</RootNamespace>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AssemblyName>SAPIServer</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RuntimeIdentifier>windows-x86</RuntimeIdentifier>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<!-- N.B: This is only to gain support for some compiler-supported nicities, like new(). -->
|
|
||||||
<LangVersion>9.0</LangVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
<ItemGroup>
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||||
<!--<PackageReference Include="Microsoft.Bcl.Async" Version="1.0.168" />-->
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Speech" />
|
<Reference Include="System.Speech" />
|
||||||
|
@ -27,5 +62,23 @@
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
</Project>
|
<Compile Include="HTTPServer.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="SynthesizePayload.cs" />
|
||||||
|
<Compile Include="VoicesResponse.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.manifest" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
|
@ -1,85 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security;
|
|
||||||
|
|
||||||
namespace SAPIServer {
|
|
||||||
|
|
||||||
// Sync with C++ code.
|
|
||||||
public enum EngineType : int { ET_SAPI4, ET_SAPI5, ET_DECTALK }
|
|
||||||
|
|
||||||
public class VoiceDef {
|
|
||||||
public Guid guid;
|
|
||||||
public string name;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
||||||
internal struct VoiceDefInternal {
|
|
||||||
Guid guid;
|
|
||||||
|
|
||||||
[MarshalAs(UnmanagedType.LPStr)]
|
|
||||||
string name;
|
|
||||||
|
|
||||||
public VoiceDef Voicify() {
|
|
||||||
Console.WriteLine($"FUCK ${name}");
|
|
||||||
//var str = Marshal.PtrToStringAnsi(name);
|
|
||||||
VoiceDef def = new();
|
|
||||||
|
|
||||||
def.guid = guid;
|
|
||||||
def.name = name;
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Speech2 DLL API. Sync with c++ code.
|
|
||||||
internal class SpeechDLL {
|
|
||||||
private const string Speech2DLL = "speech2.dll";
|
|
||||||
|
|
||||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
|
||||||
public static extern IntPtr speech2_create_api(EngineType type);
|
|
||||||
|
|
||||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
|
||||||
public static extern void speech2_destroy_api(IntPtr pAPI);
|
|
||||||
|
|
||||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
|
||||||
public static extern int speech2_api_get_voiceinfo_count(IntPtr pAPI);
|
|
||||||
|
|
||||||
[DllImport(Speech2DLL, CallingConvention = CallingConvention.StdCall)]
|
|
||||||
public static extern IntPtr speech2_api_get_voiceinfo_index(IntPtr pAPI, int index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A speech API. This is generic for all speech2 supported speech APIs, so
|
|
||||||
// we can use the same code for everything. Cool, huh?
|
|
||||||
public class SpeechAPI : IDisposable {
|
|
||||||
private IntPtr handle = IntPtr.Zero;
|
|
||||||
|
|
||||||
public SpeechAPI(EngineType type) {
|
|
||||||
handle = SpeechDLL.speech2_create_api(type);
|
|
||||||
if(handle == IntPtr.Zero)
|
|
||||||
throw new InvalidOperationException("Failed to create speech API");
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<VoiceDef> GetVoices() {
|
|
||||||
Console.WriteLine("SpeechAPI.GetVoices()");
|
|
||||||
|
|
||||||
var count = SpeechDLL.speech2_api_get_voiceinfo_count(handle);
|
|
||||||
Console.WriteLine($"count {count}");
|
|
||||||
var list = new List<VoiceDef>();
|
|
||||||
for(var i = 0; i < count; ++i) {
|
|
||||||
var ptr = SpeechDLL.speech2_api_get_voiceinfo_index(handle, i);
|
|
||||||
var obj = (VoiceDefInternal)Marshal.PtrToStructure(ptr, typeof(VoiceDefInternal));
|
|
||||||
list.Add(obj.Voicify());
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IDisposable.Dispose() {
|
|
||||||
if(handle != IntPtr.Zero)
|
|
||||||
SpeechDLL.speech2_destroy_api(handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +1,8 @@
|
||||||
namespace SAPIServer {
|
namespace SAPIServer
|
||||||
class SynthesizePayload {
|
{
|
||||||
public string voice { get; set; }
|
class SynthesizePayload
|
||||||
public string text { get; set; }
|
{
|
||||||
}
|
public string voice { get; set; }
|
||||||
|
public string text { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
namespace SAPIServer {
|
namespace SAPIServer
|
||||||
class VoicesResponse {
|
{
|
||||||
public string[] voices { get; set; }
|
class VoicesResponse
|
||||||
}
|
{
|
||||||
|
public string[] voices { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.15)
|
|
||||||
|
|
||||||
project(speech2)
|
|
||||||
|
|
||||||
|
|
||||||
xp_init()
|
|
||||||
|
|
||||||
|
|
||||||
enable_language(ASM)
|
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
|
||||||
|
|
||||||
include(Policies)
|
|
||||||
include(ProjectFuncs)
|
|
||||||
|
|
||||||
add_subdirectory(third_party/boost)
|
|
||||||
add_subdirectory(src)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# speech2
|
|
||||||
|
|
||||||
speech dll thing
|
|
|
@ -1,22 +0,0 @@
|
||||||
# CMake policy configuration
|
|
||||||
|
|
||||||
# Macro to enable new CMake policy.
|
|
||||||
# Makes this file a *LOT* shorter.
|
|
||||||
macro (_new_cmake_policy policy)
|
|
||||||
if(POLICY ${policy})
|
|
||||||
#message(STATUS "Enabling new policy ${policy}")
|
|
||||||
cmake_policy(SET ${policy} NEW)
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
_new_cmake_policy(CMP0026) # CMake 3.0: Disallow use of the LOCATION property for build targets.
|
|
||||||
_new_cmake_policy(CMP0042) # CMake 3.0+ (2.8.12): MacOS "@rpath" in target's install name
|
|
||||||
_new_cmake_policy(CMP0046) # warn about non-existent dependencies
|
|
||||||
_new_cmake_policy(CMP0048) # CMake 3.0+: project() command now maintains VERSION
|
|
||||||
_new_cmake_policy(CMP0054) # CMake 3.1: Only interpret if() arguments as variables or keywords when unquoted.
|
|
||||||
_new_cmake_policy(CMP0056) # try_compile() linker flags
|
|
||||||
_new_cmake_policy(CMP0066) # CMake 3.7: try_compile(): use per-config flags, like CMAKE_CXX_FLAGS_RELEASE
|
|
||||||
_new_cmake_policy(CMP0067) # CMake 3.8: try_compile(): honor language standard variables (like C++11)
|
|
||||||
_new_cmake_policy(CMP0068) # CMake 3.9+: `RPATH` settings on macOS do not affect `install_name`.
|
|
||||||
_new_cmake_policy(CMP0075) # CMake 3.12+: Include file check macros honor `CMAKE_REQUIRED_LIBRARIES`
|
|
||||||
_new_cmake_policy(CMP0077) # CMake 3.13+: option() honors normal variables.
|
|
|
@ -1,14 +0,0 @@
|
||||||
function(speech2_target target)
|
|
||||||
target_compile_definitions(${target} PRIVATE "$<$<CONFIG:DEBUG>:SPEECH2_DEBUG>")
|
|
||||||
target_compile_features(${target} PRIVATE cxx_std_20)
|
|
||||||
target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/third_party ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
# use the static multithreaded C library
|
|
||||||
set_property(TARGET ${target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
|
||||||
|
|
||||||
# TODO option for this.
|
|
||||||
target_link_options(${target} PRIVATE
|
|
||||||
-Wl,/safeseh:no
|
|
||||||
-Xlinker /subsystem:console,${CMAKE_SYSTEM_VERSION}
|
|
||||||
)
|
|
||||||
endfunction()
|
|
|
@ -1,78 +0,0 @@
|
||||||
# Windows XP
|
|
||||||
|
|
||||||
set(CMAKE_SYSTEM_NAME Windows)
|
|
||||||
set(CMAKE_SYSTEM_VERSION 5.1)
|
|
||||||
set(CMAKE_SYSTEM_PROCESSOR x86)
|
|
||||||
|
|
||||||
set(TARGET_VERSION_MAJOR 5)
|
|
||||||
set(TARGET_VERSION_MINOR)
|
|
||||||
|
|
||||||
set(_MSVC_TRIPLET "i686-pc-windows-msvc")
|
|
||||||
|
|
||||||
# CXXRTDIR = $(VCDIR)/crt
|
|
||||||
# UCRTDIR = $(VCDIR)/ucrt
|
|
||||||
# PSDKDIR = $(VCDIR)/winsdk
|
|
||||||
|
|
||||||
if("$ENV{VCDIR}" STREQUAL "")
|
|
||||||
message(FATAL_ERROR "Please set VCDIR in your environment to an appropiate path.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_CRTDIR "$ENV{VCDIR}/crt")
|
|
||||||
#-isystem ${_CRTDIR}/include
|
|
||||||
set(_UCRTDIR "$ENV{VCDIR}/ucrt")
|
|
||||||
set(_PSDKDIR "$ENV{VCDIR}/winsdk")
|
|
||||||
|
|
||||||
set(_CLANG_BASEFLAGS "-target ${_MSVC_TRIPLET} -fms-extensions -fms-compatibility -fms-compatibility-version=19 -isystem $ENV{VCDIR}/libcxx/include/c++ -isystem ${_UCRTDIR}/include -isystem $ENV{VCDIR}/libcxx/include -isystem ${_PSDKDIR}/include/shared -isystem ${_PSDKDIR}/include/um ")
|
|
||||||
set(_CLANG_ARCHFLAGS "-march=pentium4 -D_WIN32_WINNT=0x0501")
|
|
||||||
|
|
||||||
set(CMAKE_C_COMPILER "clang" CACHE FILEPATH "")
|
|
||||||
set(CMAKE_CXX_COMPILER "clang++" CACHE FILEPATH "")
|
|
||||||
set(CMAKE_LINKER "lld-link" CACHE FILEPATH "")
|
|
||||||
|
|
||||||
set(CMAKE_ASM_FLAGS_INIT "${_CLANG_BASEFLAGS} ${_CLANG_ARCHFLAGS}")
|
|
||||||
set(CMAKE_C_FLAGS_INIT "${_CLANG_BASEFLAGS} ${_CLANG_ARCHFLAGS}")
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_INIT} -fomit-frame-pointer")
|
|
||||||
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}")
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE_INIT "${CMAKE_C_FLAGS_RELEASE_INIT} ${CMAKE_CXX_FLAGS_INIT}")
|
|
||||||
|
|
||||||
# Set base linker library paths
|
|
||||||
foreach(type EXE MODULE SHARED)
|
|
||||||
# -Xlinker /nodefaultlib:libcpmt -Xlinker /nodefaultlib:libcpmtd
|
|
||||||
set(CMAKE_${type}_LINKER_FLAGS "-Xlinker /libpath:${_CRTDIR}/lib/x86 -Xlinker /libpath:${_UCRTDIR}/lib -Xlinker /libpath:${_PSDKDIR}/lib")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Remove fluff libraries; projects should specify them
|
|
||||||
set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
|
||||||
|
|
||||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
|
||||||
set(CMAKE_CXX_STANDARD_LIBRARIES "-Xlinker /libpath:$ENV{VCDIR}/libcxx/lib -Xlinker libcpmtd.lib -Xlinker libc++d.lib -Xlinker winpthreadsd.lib" CACHE STRING "" FORCE)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_STANDARD_LIBRARIES "-Xlinker /libpath:$ENV{VCDIR}/libcxx/lib -Xlinker libcpmt.lib -Xlinker libc++.lib -Xlinker winpthreads.lib" CACHE STRING "" FORCE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Run this once after you call project() to replace broken
|
|
||||||
macro(xp_init)
|
|
||||||
foreach(lang C CXX)
|
|
||||||
# have to patch the link commands to replace /MANIFEST:EMBED with /MANIFEST:NO
|
|
||||||
# because ....
|
|
||||||
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
|
|
||||||
"<CMAKE_${lang}_COMPILER> -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:${CMAKE_SYSTEM_VERSION} <OBJECTS> <LINK_LIBRARIES> <MANIFESTS>" CACHE STRING "" FORCE)
|
|
||||||
set(CMAKE_${lang}_CREATE_SHARED_MODULE ${CMAKE_${lang}_CREATE_SHARED_LIBRARY} CACHE STRING "" FORCE)
|
|
||||||
set(CMAKE_${lang}_LINK_EXECUTABLE
|
|
||||||
"<CMAKE_${lang}_COMPILER> -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /MANIFEST:NO -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:${CMAKE_SYSTEM_VERSION} ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES> <MANIFESTS>" CACHE STRING "" FORCE)
|
|
||||||
|
|
||||||
# also patch these so we can set the subsytem version
|
|
||||||
set(CMAKE_${lang}_CREATE_WIN32_EXE "-Xlinker /subsystem:windows,${CMAKE_SYSTEM_VERSION}" CACHE STRING "" FORCE)
|
|
||||||
set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console,${CMAKE_SYSTEM_VERSION}" CACHE STRING "" FORCE)
|
|
||||||
endforeach()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
# Use the static multithreaded C library
|
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
|
||||||
|
|
||||||
|
|
||||||
# dummy
|
|
||||||
|
|
||||||
set(CMAKE_ASM_MASM_COMPILE_OBJECT "${CMAKE_ASM_COMPILE_OBJECT}")
|
|
||||||
|
|
||||||
xp_init()
|
|
|
@ -1,39 +0,0 @@
|
||||||
add_subdirectory(base)
|
|
||||||
add_subdirectory(impl)
|
|
||||||
add_subdirectory(sapi4)
|
|
||||||
|
|
||||||
|
|
||||||
add_executable(sapiserver
|
|
||||||
main.cpp
|
|
||||||
|
|
||||||
winxp_compat_fwd.S
|
|
||||||
winxp_compat.cpp
|
|
||||||
winxp_compat_threadsafe_static.c
|
|
||||||
)
|
|
||||||
|
|
||||||
speech2_target(sapiserver)
|
|
||||||
|
|
||||||
target_compile_definitions(sapiserver PRIVATE
|
|
||||||
# Need to force this on, since I think clang's msvc compatibility
|
|
||||||
# is deciding to set a wrong __cplusplus (like MSVC, so it's not *exactly* clang's fault).
|
|
||||||
# The best way to fix it would probably involve using clang-cl frontend and passing the option (I think.)
|
|
||||||
# (nevermind, it's just broken.)
|
|
||||||
-DBOOST_ASIO_HAS_STD_INVOKE_RESULT=1
|
|
||||||
|
|
||||||
# Disable the "helpful" auto-link Boost.Config tries to do. CMake already has a functional
|
|
||||||
# dependency graph based on our input, so we don't need it.
|
|
||||||
-DBOOST_ALL_NO_LIB=1
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(sapiserver PRIVATE
|
|
||||||
#libc++
|
|
||||||
|
|
||||||
# subprojects
|
|
||||||
speech2::base
|
|
||||||
speech2::impl
|
|
||||||
speech2::api_sapi4
|
|
||||||
|
|
||||||
# SDK libraries
|
|
||||||
uuid.lib
|
|
||||||
ole32.lib
|
|
||||||
)
|
|
|
@ -1,14 +0,0 @@
|
||||||
add_library(speech2_base STATIC
|
|
||||||
|
|
||||||
Thread.cpp
|
|
||||||
|
|
||||||
# Logging system
|
|
||||||
Logger.cpp
|
|
||||||
Logger_priv.cpp
|
|
||||||
StdoutSink.cpp
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
speech2_target(speech2_base)
|
|
||||||
|
|
||||||
add_library(speech2::base ALIAS speech2_base)
|
|
|
@ -1,41 +0,0 @@
|
||||||
#include "Logger.hpp"
|
|
||||||
|
|
||||||
#include <base/Logger_priv.hpp>
|
|
||||||
#include <base/Thread.hpp>
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
inline auto& GlobalState() {
|
|
||||||
return logger_impl::LoggerGlobalState::The();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggerAttachSink(LoggerSink& sink) {
|
|
||||||
GlobalState().AttachSink(sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageSeverity GetLogLevel() {
|
|
||||||
return GlobalState().GetLogLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetLogLevel(MessageSeverity newLevel) {
|
|
||||||
GlobalState().SetLogLevel(newLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger& Logger::Get(std::string_view key) {
|
|
||||||
return logger_impl::GetOrRegister(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger::Logger(ChannelId id)
|
|
||||||
: channelId(id) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::VOut(MessageSeverity severity, std::string_view format, std::format_args args) {
|
|
||||||
logger_impl::MessageData data {
|
|
||||||
.time = std::chrono::system_clock::now(), .severity = severity, .channelId = channelId, .message = std::vformat(format, args)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Push data into logger thread.
|
|
||||||
logger_impl::PushMessage(std::move(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace common
|
|
|
@ -1,75 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <base/Types.hpp>
|
|
||||||
|
|
||||||
#include <format>
|
|
||||||
#include <string_view>
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
/// A logger sink. Outputs messages to some device (a TTY), a file,
|
|
||||||
/// anything. A interface for the logger to spit stuff out.
|
|
||||||
///
|
|
||||||
/// # Notes
|
|
||||||
/// Sinks *do not* run on the main application thread. Instead, they run on a
|
|
||||||
/// single internal thread shared with the logging system.
|
|
||||||
/// Sinks should *not* block for large periods of time.
|
|
||||||
struct LoggerSink {
|
|
||||||
virtual void OutputMessage(std::string_view message) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MessageSeverity { Debug, Info, Warning, Error, Fatal };
|
|
||||||
|
|
||||||
/// A channel ID. `enum class`es are used to avoid confusion with a normal u32,
|
|
||||||
/// and to also add addional interface type safety.
|
|
||||||
/// These are opaque, and only exposed here because it would be annoying to move elsewhere.
|
|
||||||
enum class ChannelId : u32 {};
|
|
||||||
|
|
||||||
/// Attach a sink to all Support loggers; allowing it to output logger messages.
|
|
||||||
void LoggerAttachSink(LoggerSink& sink);
|
|
||||||
|
|
||||||
MessageSeverity GetLogLevel();
|
|
||||||
|
|
||||||
void SetLogLevel(MessageSeverity newLevel);
|
|
||||||
|
|
||||||
/// An (asynchronous) logger.
|
|
||||||
struct Logger {
|
|
||||||
/// Gets or creates a logger for the specified channel.
|
|
||||||
static Logger& Get(std::string_view channel);
|
|
||||||
|
|
||||||
explicit Logger(ChannelId channel);
|
|
||||||
|
|
||||||
Logger(const Logger&) = delete;
|
|
||||||
Logger(Logger&&) = delete;
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
inline void Debug(std::string_view fmt, Args&&... args) {
|
|
||||||
VOut(MessageSeverity::Debug, fmt, std::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
inline void Info(std::string_view fmt, Args&&... args) {
|
|
||||||
VOut(MessageSeverity::Info, fmt, std::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
inline void Warning(std::string_view fmt, Args&&... args) {
|
|
||||||
VOut(MessageSeverity::Warning, fmt, std::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
inline void Error(std::string_view fmt, Args&&... args) {
|
|
||||||
VOut(MessageSeverity::Error, fmt, std::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class... Args>
|
|
||||||
inline void Fatal(std::string_view fmt, Args&&... args) {
|
|
||||||
VOut(MessageSeverity::Fatal, fmt, std::make_format_args(args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void VOut(MessageSeverity severity, std::string_view format, std::format_args args);
|
|
||||||
|
|
||||||
ChannelId channelId;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace collabvm
|
|
|
@ -1,170 +0,0 @@
|
||||||
#include <base/Logger_priv.hpp>
|
|
||||||
#include <base/Thread.hpp>
|
|
||||||
#include <chrono>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <deque>
|
|
||||||
#include <mutex>
|
|
||||||
#include <queue>
|
|
||||||
#include <string_view>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace base::logger_impl {
|
|
||||||
|
|
||||||
static constexpr std::string_view SeverityToString(MessageSeverity sev) {
|
|
||||||
// This must match order of MessageSeverity.
|
|
||||||
const char* MessageSeverityStringTable[] = { "Debug", "Info", "Warn", "Error", "Fatal" };
|
|
||||||
return MessageSeverityStringTable[static_cast<std::size_t>(sev)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hash algorithm for channel IDs. In this case it's PJW-ELF.
|
|
||||||
/// I might switch to murmur or something if collisions are a problem,
|
|
||||||
/// but I don't think it's a problem.
|
|
||||||
ChannelId ChannelIDHash(const char* in) {
|
|
||||||
u32 hash = 0;
|
|
||||||
u32 high = 0;
|
|
||||||
|
|
||||||
while(*in) {
|
|
||||||
hash = (hash << 4) + *in++;
|
|
||||||
|
|
||||||
if((high = hash & 0xf0000000))
|
|
||||||
hash ^= high >> 23;
|
|
||||||
|
|
||||||
hash &= ~high;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<ChannelId>(hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view ChannelToString(ChannelId id) {
|
|
||||||
auto& gs = LoggerGlobalState::The();
|
|
||||||
std::unique_lock lk(gs.loggerMapLock);
|
|
||||||
return gs.loggerMap[id].channelName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// comparator for [std::priority_queue]
|
|
||||||
struct LogMessageComparator {
|
|
||||||
constexpr bool operator()(const MessageData& mdLeft, const MessageData& mdRight) { return mdLeft.time > mdRight.time; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LoggerThreadData {
|
|
||||||
// Logger thread stuff
|
|
||||||
std::thread loggerThread;
|
|
||||||
std::mutex logQueueMutex;
|
|
||||||
std::condition_variable logQueueCv;
|
|
||||||
|
|
||||||
std::priority_queue<MessageData, std::deque<MessageData>, LogMessageComparator> logQueue;
|
|
||||||
|
|
||||||
// could be an atomic_bool
|
|
||||||
bool logThreadShutdown = false;
|
|
||||||
|
|
||||||
bool ShouldUnblock() {
|
|
||||||
// N.B: ALL calls of this hold the lock.
|
|
||||||
|
|
||||||
// Always unblock if the logger thread needs to be shut down.
|
|
||||||
if(logThreadShutdown)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return !logQueue.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushMessage(MessageData&& md) {
|
|
||||||
{
|
|
||||||
std::unique_lock lk(logQueueMutex);
|
|
||||||
logQueue.push(std::move(md));
|
|
||||||
}
|
|
||||||
logQueueCv.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This thread drives the logging system.
|
|
||||||
static void LoggerThread(LoggerThreadData* self) {
|
|
||||||
// Fancy thread names.
|
|
||||||
SetThreadName("AsyncLogger");
|
|
||||||
|
|
||||||
auto& state = LoggerGlobalState::The();
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
// Shutdown if requested.
|
|
||||||
if(self->logThreadShutdown)
|
|
||||||
break;
|
|
||||||
|
|
||||||
{
|
|
||||||
std::unique_lock lk(self->logQueueMutex);
|
|
||||||
if(self->logQueue.empty()) {
|
|
||||||
// Await for messages.
|
|
||||||
self->logQueueCv.wait(lk, [self]() { return self->ShouldUnblock(); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::unique_lock lk(self->logQueueMutex);
|
|
||||||
// Flush the logger queue until there are no more messages.
|
|
||||||
while(!self->logQueue.empty()) {
|
|
||||||
const auto& msg = self->logQueue.top();
|
|
||||||
state.OutputMessage(msg);
|
|
||||||
self->logQueue.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Unique<LoggerThreadData> threadData;
|
|
||||||
|
|
||||||
LoggerGlobalState& LoggerGlobalState::The() {
|
|
||||||
static LoggerGlobalState storage;
|
|
||||||
return storage;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerGlobalState::LoggerGlobalState() {
|
|
||||||
// Spawn the logger thread
|
|
||||||
threadData = std::make_unique<LoggerThreadData>();
|
|
||||||
threadData->loggerThread = std::thread(&LoggerThreadData::LoggerThread, threadData.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
LoggerGlobalState::~LoggerGlobalState() {
|
|
||||||
// Shut down the logger thread
|
|
||||||
threadData->logThreadShutdown = true;
|
|
||||||
threadData->logQueueCv.notify_all();
|
|
||||||
threadData->loggerThread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggerGlobalState::AttachSink(LoggerSink& sink) {
|
|
||||||
sinks.push_back(&sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggerGlobalState::OutputMessage(const MessageData& data) {
|
|
||||||
// give up early if no sinks are attached
|
|
||||||
if(sinks.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(data.severity < logLevel)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto formattedLoggerMessage = std::format("[{:%F %H:%M:%S}|{}|{}] {}", std::chrono::floor<std::chrono::milliseconds>(data.time),
|
|
||||||
SeverityToString(data.severity), ChannelToString(data.channelId), data.message);
|
|
||||||
|
|
||||||
for(auto sink : sinks)
|
|
||||||
sink->OutputMessage(formattedLoggerMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger& GetOrRegister(std::string_view component) {
|
|
||||||
auto& gs = LoggerGlobalState::The();
|
|
||||||
|
|
||||||
std::unique_lock lk(gs.loggerMapLock);
|
|
||||||
|
|
||||||
auto hash = ChannelIDHash(component.data());
|
|
||||||
|
|
||||||
if(!gs.loggerMap.contains(hash)) {
|
|
||||||
// Insert a new entry into the logger map.
|
|
||||||
gs.loggerMap.insert_or_assign(hash, BoltedLoggerData { component, std::make_unique<Logger>(hash) });
|
|
||||||
}
|
|
||||||
|
|
||||||
return *gs.loggerMap[hash].logger.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PushMessage(MessageData&& md) {
|
|
||||||
if(threadData)
|
|
||||||
threadData->PushMessage(std::move(md));
|
|
||||||
}
|
|
||||||
} // namespace base::logger_impl
|
|
|
@ -1,59 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <base/Logger.hpp>
|
|
||||||
#include <chrono>
|
|
||||||
#include <mutex>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace base::logger_impl {
|
|
||||||
|
|
||||||
/// Message data. This is only used by logger sinks.
|
|
||||||
struct MessageData {
|
|
||||||
std::chrono::system_clock::time_point time;
|
|
||||||
MessageSeverity severity;
|
|
||||||
|
|
||||||
ChannelId channelId; // the channel ID.
|
|
||||||
|
|
||||||
std::string message; // DO NOT SET THIS, IT WILL BE OVERWRITTEN AND I WILL BE VERY SAD -lily
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BoltedLoggerData {
|
|
||||||
std::string_view channelName;
|
|
||||||
Unique<Logger> logger;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Shared global state all loggers use.
|
|
||||||
struct LoggerGlobalState {
|
|
||||||
static LoggerGlobalState& The();
|
|
||||||
|
|
||||||
void AttachSink(LoggerSink& sink);
|
|
||||||
|
|
||||||
void OutputMessage(const MessageData& data);
|
|
||||||
|
|
||||||
/// Get the current log level.
|
|
||||||
MessageSeverity GetLogLevel() const { return logLevel; }
|
|
||||||
|
|
||||||
/// Set the current log level.
|
|
||||||
void SetLogLevel(MessageSeverity newLogLevel) { logLevel = newLogLevel; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
LoggerGlobalState();
|
|
||||||
~LoggerGlobalState();
|
|
||||||
|
|
||||||
public:
|
|
||||||
std::vector<LoggerSink*> sinks;
|
|
||||||
MessageSeverity logLevel { MessageSeverity::Info };
|
|
||||||
|
|
||||||
std::unordered_map<ChannelId, BoltedLoggerData> loggerMap;
|
|
||||||
std::mutex loggerMapLock;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Gets or registers a new logger. This routine is threadsafe, and can be called
|
|
||||||
/// on any thread, like (most) parts of the logging system.
|
|
||||||
Logger& GetOrRegister(std::string_view component);
|
|
||||||
|
|
||||||
/// Push a logger message into the queue.
|
|
||||||
void PushMessage(MessageData&& md);
|
|
||||||
|
|
||||||
} // namespace base::logger_impl
|
|
|
@ -1,6 +0,0 @@
|
||||||
// Sane windows.h
|
|
||||||
#pragma once
|
|
||||||
#define _WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
|
||||||
#include <commctrl.h>
|
|
||||||
#undef _WIN32_LEAN_AND_MEAN
|
|
|
@ -1,20 +0,0 @@
|
||||||
#include <base/StdoutSink.hpp>
|
|
||||||
|
|
||||||
#include "Logger.hpp"
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
StdoutLoggerSink& StdoutLoggerSink::The() {
|
|
||||||
static StdoutLoggerSink sink;
|
|
||||||
return sink;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StdoutLoggerSink::OutputMessage(std::string_view message) {
|
|
||||||
fputs(message.data(), stdout);
|
|
||||||
fputc('\n', stdout);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoggerAttachStdout() {
|
|
||||||
LoggerAttachSink(StdoutLoggerSink::The());
|
|
||||||
}
|
|
||||||
} // namespace base
|
|
|
@ -1,17 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <base/Logger.hpp>
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
/// A logger sink implementation that prints to standard output.
|
|
||||||
struct StdoutLoggerSink : public LoggerSink {
|
|
||||||
static StdoutLoggerSink& The();
|
|
||||||
|
|
||||||
void OutputMessage(std::string_view message) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Attach the stdout logger sink to the global Lucore logger.
|
|
||||||
void LoggerAttachStdout();
|
|
||||||
|
|
||||||
} // namespace base
|
|
|
@ -1,11 +0,0 @@
|
||||||
#include <pthread.h>
|
|
||||||
#include <base/Thread.hpp>
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
void SetThreadNameImpl(const char* name, usize len) {
|
|
||||||
//COMMON_ASSERT(len <= 15, "name will overflow pthread_setname_np() buffer");
|
|
||||||
pthread_setname_np(pthread_self(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <base/Types.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
void SetThreadNameImpl(const char* name, usize len);
|
|
||||||
|
|
||||||
/// Sets the name of the current thread. Mainly for portability.
|
|
||||||
inline void SetThreadName(const std::string& name) {
|
|
||||||
SetThreadNameImpl(name.data(), name.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace collabvm
|
|
|
@ -1,52 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
using u8 = std::uint8_t;
|
|
||||||
using i8 = std::int8_t;
|
|
||||||
using u16 = std::uint16_t;
|
|
||||||
using i16 = std::int16_t;
|
|
||||||
using u32 = std::uint32_t;
|
|
||||||
using i32 = std::int32_t;
|
|
||||||
using u64 = std::uint64_t;
|
|
||||||
using i64 = std::int64_t;
|
|
||||||
using usize = std::size_t;
|
|
||||||
using isize = std::intptr_t;
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
/// A little ergonomic wrapper over
|
|
||||||
/// std::unique_ptr<T[]>, for a "kinda-vector"
|
|
||||||
/// that lives on the heap and is statically sized
|
|
||||||
template <class T>
|
|
||||||
struct UniqueArray final {
|
|
||||||
explicit UniqueArray(usize size)
|
|
||||||
: array(std::make_unique<T[]>(size)),
|
|
||||||
size(size) {
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueArray(UniqueArray&& move) {
|
|
||||||
array = std::move(move.array);
|
|
||||||
size = move.size;
|
|
||||||
|
|
||||||
// invalidate
|
|
||||||
move.array = nullptr;
|
|
||||||
move.size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator[](usize index) { return Get()[index]; }
|
|
||||||
const T& operator[](usize index) const { return Get()[index]; }
|
|
||||||
|
|
||||||
T* Get() { return array.get(); }
|
|
||||||
const T* Get() const { return array.get(); }
|
|
||||||
usize Size() const { return size; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<T[]> array {};
|
|
||||||
usize size {};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
using Unique = std::unique_ptr<T>;
|
|
||||||
|
|
||||||
} // namespace common
|
|
|
@ -1,71 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <base/SaneWin.hpp>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
|
|
||||||
// A relatively sane (non-intrinsic) COM smart pointer
|
|
||||||
// TODO: Allow downcasting to ComPtr<IUnknown, IID_IUnknown> (all COM objects implement this anyways)
|
|
||||||
//
|
|
||||||
template <class T = IUnknown, const IID* iid = &IID_IUnknown>
|
|
||||||
struct ComPtr {
|
|
||||||
//constexpr ComPtr() = default;
|
|
||||||
|
|
||||||
//explicit ComPtr(T* t) : interface_ptr(t) {}
|
|
||||||
constexpr ComPtr() : interface_ptr(nullptr) {}
|
|
||||||
|
|
||||||
// Assignment won't require AddRef() because most COM interfaces
|
|
||||||
// will automatically AddRef() upon querying them.
|
|
||||||
ComPtr& operator=(T* interface_) {
|
|
||||||
// Release an existing interface.
|
|
||||||
if(interface_ptr) {
|
|
||||||
printf("ComPtr<T>::operator= releasing %p (guid %08x)\n", interface_ptr, *iid);
|
|
||||||
interface_ptr->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface_ptr = interface_;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComPtr(const ComPtr& copy) {
|
|
||||||
if(interface_ptr) {
|
|
||||||
interface_ptr->AddRef();
|
|
||||||
interface_ptr = copy.interface_ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~ComPtr() {
|
|
||||||
if(interface_ptr) {
|
|
||||||
printf("ComPtr<T>::~ComPtr releasing %p (guid %08x)\n", interface_ptr, *iid);
|
|
||||||
interface_ptr->Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper to CoCreateInstance() on this pointer
|
|
||||||
HRESULT CreateInstance(REFCLSID clsid, DWORD ctx) {
|
|
||||||
return CoCreateInstance(clsid, nullptr, CLSCTX_ALL, *iid, reinterpret_cast<void**>(&interface_ptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// smart pointer overrides
|
|
||||||
|
|
||||||
constexpr T** operator&() { return &interface_ptr; }
|
|
||||||
constexpr T* operator->() { return interface_ptr; }
|
|
||||||
constexpr operator T*() const { return interface_ptr; }
|
|
||||||
|
|
||||||
T* Get() { return interface_ptr; }
|
|
||||||
const T* Get() const { return interface_ptr; }
|
|
||||||
|
|
||||||
// release pointer - you need to manage it yourself or put it
|
|
||||||
// into another ComSmartPtr then
|
|
||||||
T* ReleasePtr() {
|
|
||||||
auto old = interface_ptr;
|
|
||||||
interface_ptr = nullptr;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
T* interface_ptr { nullptr };
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace base
|
|
|
@ -1,35 +0,0 @@
|
||||||
add_library(speech2_impl
|
|
||||||
asio_src.cpp
|
|
||||||
beast_src.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
speech2_target(speech2_impl)
|
|
||||||
|
|
||||||
target_compile_definitions(speech2_impl PUBLIC
|
|
||||||
# Need to force this on, since I think clang's msvc compatibility
|
|
||||||
# is deciding to set a wrong __cplusplus (like MSVC, so it's not *exactly* clang's fault).
|
|
||||||
# The best way to fix it would probably involve using clang-cl frontend and passing the option (I think.)
|
|
||||||
# (nevermind, it's just broken.)
|
|
||||||
-DBOOST_ASIO_HAS_STD_INVOKE_RESULT=1
|
|
||||||
|
|
||||||
# We compile all of these header-only libraries in separate .cpp source files
|
|
||||||
# to decrease build churn
|
|
||||||
-DBOOST_ASIO_SEPARATE_COMPILATION=1
|
|
||||||
-DBOOST_BEAST_SEPARATE_COMPILATION=1
|
|
||||||
|
|
||||||
# Disable deprecated functionality and some things which add additional dependencies or are
|
|
||||||
# simply baggage we aren't ever going to use
|
|
||||||
-DBOOST_ASIO_NO_DEPRECATED=1
|
|
||||||
-DBOOST_ASIO_DISABLE_BOOST_ARRAY=1
|
|
||||||
-DBOOST_ASIO_DISABLE_BOOST_BIND=1
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(speech2_impl PUBLIC
|
|
||||||
Boost::asio
|
|
||||||
Boost::beast
|
|
||||||
|
|
||||||
Boost::coroutine
|
|
||||||
Boost::context
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(speech2::impl ALIAS speech2_impl)
|
|
|
@ -1,5 +0,0 @@
|
||||||
// Since we're using (BOOST_)ASIO_SEPARATE_COMPILATION, we need
|
|
||||||
// to include the <(boost/)asio/impl/src.hpp> header in some TU.
|
|
||||||
// We use this one to explicitly do so.
|
|
||||||
|
|
||||||
#include <boost/asio/impl/src.hpp>
|
|
|
@ -1 +0,0 @@
|
||||||
#include <boost/beast/src.hpp>
|
|
|
@ -1,163 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <boost/asio/detached.hpp>
|
|
||||||
#include <boost/asio/io_context.hpp>
|
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
|
||||||
#include <boost/asio/spawn.hpp>
|
|
||||||
#include <boost/asio/steady_timer.hpp>
|
|
||||||
#include <boost/asio/write.hpp>
|
|
||||||
#include <boost/beast/core/basic_stream.hpp>
|
|
||||||
#include <boost/beast/core/flat_buffer.hpp>
|
|
||||||
#include <boost/beast/http.hpp>
|
|
||||||
#include <boost/beast/http/message_generator.hpp>
|
|
||||||
#include <boost/beast/http/read.hpp>
|
|
||||||
#include <boost/beast/http/string_body.hpp>
|
|
||||||
#include <boost/beast/http/write.hpp>
|
|
||||||
#include <format>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "base/Logger.hpp"
|
|
||||||
#include "base/StdoutSink.hpp"
|
|
||||||
#include "speechapi.hpp"
|
|
||||||
|
|
||||||
namespace net = boost::asio;
|
|
||||||
namespace beast = boost::beast;
|
|
||||||
namespace bhttp = beast::http;
|
|
||||||
|
|
||||||
using net::ip::tcp;
|
|
||||||
|
|
||||||
auto coresv_to_cxx(boost::core::string_view sv) {
|
|
||||||
return std::string_view { sv.data(), sv.length() };
|
|
||||||
}
|
|
||||||
|
|
||||||
// A test coro
|
|
||||||
void test_out_of_line_coro(net::any_io_executor ioc,net::yield_context yc) {
|
|
||||||
net::steady_timer t{ioc};
|
|
||||||
|
|
||||||
t.expires_after(std::chrono::seconds(5));
|
|
||||||
t.async_wait(yc);
|
|
||||||
}
|
|
||||||
|
|
||||||
class session : public std::enable_shared_from_this<session> {
|
|
||||||
public:
|
|
||||||
explicit session(net::io_context& io_context, beast::basic_stream<net::ip::tcp> socket)
|
|
||||||
: socket_(std::move(socket)), strand_(io_context.get_executor()) {}
|
|
||||||
|
|
||||||
void go() {
|
|
||||||
auto self(shared_from_this());
|
|
||||||
|
|
||||||
net::spawn(
|
|
||||||
strand_,
|
|
||||||
[this, self](net::yield_context yield) {
|
|
||||||
try {
|
|
||||||
auto& logger = base::Logger::Get("HTTPSession");
|
|
||||||
|
|
||||||
bhttp::request<bhttp::string_body> req {};
|
|
||||||
beast::flat_buffer buffer {};
|
|
||||||
|
|
||||||
logger.Info("Wait test");
|
|
||||||
|
|
||||||
// mostly just to test if I can yield stuff from another member function.
|
|
||||||
// This seems to work, so /shrug
|
|
||||||
test_out_of_line_coro(socket_.get_executor(), yield);
|
|
||||||
|
|
||||||
logger.Info("Wait completed");
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
socket_.expires_after(std::chrono::seconds(10));
|
|
||||||
bhttp::async_read(socket_, buffer, req, yield);
|
|
||||||
|
|
||||||
auto const routeTest = [&]() -> bhttp::message_generator {
|
|
||||||
bhttp::response<bhttp::string_body> resp { bhttp::status::bad_request, req.version() };
|
|
||||||
resp.set(bhttp::field::server, "Fucker Google/1.0");
|
|
||||||
resp.set(bhttp::field::content_type, "text/plain");
|
|
||||||
resp.keep_alive(false);
|
|
||||||
resp.body() = std::format("You requested \"{} {}\"", coresv_to_cxx(req.method_string()), coresv_to_cxx(req.target()));
|
|
||||||
resp.prepare_payload();
|
|
||||||
return resp;
|
|
||||||
};
|
|
||||||
|
|
||||||
logger.Info("HTTP request to {}", coresv_to_cxx(req.target()));
|
|
||||||
|
|
||||||
auto res = routeTest();
|
|
||||||
|
|
||||||
socket_.expires_after(std::chrono::seconds(10));
|
|
||||||
beast::async_write(socket_, std::move(res), yield);
|
|
||||||
|
|
||||||
if(!req.keep_alive()) {
|
|
||||||
socket_.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(std::exception& e) {
|
|
||||||
socket_.close();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
net::detached);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
beast::basic_stream<net::ip::tcp> socket_;
|
|
||||||
net::strand<net::io_context::executor_type> strand_;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
// CoInitialize(nullptr);
|
|
||||||
|
|
||||||
base::LoggerAttachStdout();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(argc != 2) {
|
|
||||||
std::cerr << "Usage: echo_server <port>\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
net::io_context io_context;
|
|
||||||
|
|
||||||
net::spawn(
|
|
||||||
io_context,
|
|
||||||
[&](net::yield_context yield) {
|
|
||||||
tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), std::atoi(argv[1])));
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
boost::system::error_code ec;
|
|
||||||
tcp::socket socket(io_context);
|
|
||||||
|
|
||||||
acceptor.async_accept(socket, yield[ec]);
|
|
||||||
if(!ec) {
|
|
||||||
auto stream = beast::basic_stream<net::ip::tcp>(std::move(socket));
|
|
||||||
std::make_shared<session>(io_context, std::move(stream))->go();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[](std::exception_ptr e) {
|
|
||||||
if(e)
|
|
||||||
std::rethrow_exception(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
io_context.run();
|
|
||||||
} catch(std::exception& e) {
|
|
||||||
std::cerr << "Exception: " << e.what() << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 // test spech shit
|
|
||||||
auto api = std::unique_ptr<ISpeechAPI>(ISpeechAPI::CreateSapi4());
|
|
||||||
|
|
||||||
if(auto hr = api->Initialize(); FAILED(hr)) {
|
|
||||||
printf("Failed to initialize speech API\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(auto hr = api->SelectVoice("Sam"); FAILED(hr)) {
|
|
||||||
printf("Failed to select voice\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Selected voice\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// CoUninitialize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
# SAPI4 layer for speech2
|
|
||||||
|
|
||||||
add_library(speech2_sapi4
|
|
||||||
api_sapi4.cpp
|
|
||||||
guid_sapi4.cpp
|
|
||||||
audio_buffer.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
speech2_target(speech2_sapi4)
|
|
||||||
|
|
||||||
add_library(speech2::api_sapi4 ALIAS speech2_sapi4)
|
|
|
@ -1,97 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <base/comptr.hpp>
|
|
||||||
|
|
||||||
#include "sapi4/audio_buffer.hpp"
|
|
||||||
#include "sapi4/include/speech.h"
|
|
||||||
#include "speechapi.hpp"
|
|
||||||
|
|
||||||
struct SpeechAPI_SAPI4 : public ISpeechAPI {
|
|
||||||
virtual ~SpeechAPI_SAPI4() {
|
|
||||||
printf("~SpeechAPI_SAPI4\n");
|
|
||||||
// if(pAudioOut)
|
|
||||||
// pAudioOut->AddRef();
|
|
||||||
|
|
||||||
if(pCentral)
|
|
||||||
pCentral->Release();
|
|
||||||
};
|
|
||||||
|
|
||||||
HRESULT Initialize() override {
|
|
||||||
HRESULT hRes{};
|
|
||||||
|
|
||||||
printf("speech2: SpeechAPI_Sapi4::Initalize() begin: %p\n", this);
|
|
||||||
|
|
||||||
hRes = pEnum.CreateInstance(CLSID_TTSEnumerator, CLSCTX_INPROC);
|
|
||||||
if(FAILED(hRes))
|
|
||||||
return hRes;
|
|
||||||
|
|
||||||
|
|
||||||
pEnum->Reset();
|
|
||||||
|
|
||||||
// Fill out voices
|
|
||||||
EnumVoices();
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnumVoices() {
|
|
||||||
TTSMODEINFO found{};
|
|
||||||
|
|
||||||
while(!pEnum->Next(1, &found, nullptr)) {
|
|
||||||
voices.push_back({found.gModeID, found.szModeName});
|
|
||||||
}
|
|
||||||
|
|
||||||
pEnum->Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<VoiceInfo>& GetVoices() override {
|
|
||||||
return voices;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT SelectVoiceImpl(const GUID& guid) {
|
|
||||||
pAudioOut = new AudioOutBuffer();
|
|
||||||
pAudioOut->AddRef();
|
|
||||||
|
|
||||||
if(pCentral)
|
|
||||||
pCentral->Release();
|
|
||||||
|
|
||||||
ITTSCentral* central;
|
|
||||||
if(auto hr = pEnum->Select(guid, ¢ral, static_cast<IUnknown*>(pAudioOut)); FAILED(hr))
|
|
||||||
return hr;
|
|
||||||
|
|
||||||
pCentral = central;
|
|
||||||
|
|
||||||
// From Microsoft Speech SDK 4.0 documentation:
|
|
||||||
// The engine will AddRef the interface, and release the interface when the engine is destroyed.
|
|
||||||
// Because of this the application will need to call Release on the audio object after the select call or audio objects will be leaked.
|
|
||||||
pAudioOut->Release();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT SelectVoice(std::string_view voiceName) override {
|
|
||||||
TTSMODEINFO found {};
|
|
||||||
|
|
||||||
while(!pEnum->Next(1, &found, nullptr)) {
|
|
||||||
if(voiceName == found.szModeName) {
|
|
||||||
return SelectVoiceImpl(found.gModeID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pEnum->Reset();
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
base::ComPtr<ITTSEnum, &IID_ITTSEnum> pEnum;
|
|
||||||
ITTSCentral* pCentral { nullptr };
|
|
||||||
|
|
||||||
// The above comment is also why this isn't a ComPtr.
|
|
||||||
AudioOutBuffer* pAudioOut { nullptr };
|
|
||||||
|
|
||||||
std::vector<VoiceInfo> voices{};
|
|
||||||
};
|
|
||||||
|
|
||||||
ISpeechAPI* ISpeechAPI::CreateSapi4() {
|
|
||||||
return new SpeechAPI_SAPI4();
|
|
||||||
}
|
|
|
@ -1,185 +0,0 @@
|
||||||
#include "audio_buffer.hpp"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <winerror.h>
|
|
||||||
|
|
||||||
// Implements IAudioDest.
|
|
||||||
struct AudioOutBuffer::Dest : public IAudioDest {
|
|
||||||
Dest(AudioOutBuffer* pOut) : pOut(pOut) {}
|
|
||||||
~Dest() = default;
|
|
||||||
|
|
||||||
// IUnknown
|
|
||||||
STDMETHODIMP QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept override { return pOut->QueryInterface(riid, ppvObj); }
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) AddRef() noexcept override {
|
|
||||||
m_iRefCount++;
|
|
||||||
return pOut->AddRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) Release() noexcept override {
|
|
||||||
m_iRefCount--;
|
|
||||||
return pOut->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// IAudioDest
|
|
||||||
|
|
||||||
STDMETHODIMP FreeSpace(DWORD* pFree, BOOL* pEOF) noexcept override { return E_NOTIMPL; }
|
|
||||||
|
|
||||||
STDMETHODIMP DataSet(PVOID pBuffer, DWORD dwSize) noexcept override {
|
|
||||||
// TODO
|
|
||||||
printf("AudioOutBuffer::Dest::DataSet()\n");
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP BookMark(DWORD pos) noexcept override {
|
|
||||||
// Ignored
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
AudioOutBuffer* pOut;
|
|
||||||
ULONG m_iRefCount{};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Implements IAudio.
|
|
||||||
struct AudioOutBuffer::Audio : public IAudio {
|
|
||||||
Audio(AudioOutBuffer* pOut) : pOut(pOut) {}
|
|
||||||
~Audio() {
|
|
||||||
};
|
|
||||||
|
|
||||||
// IUnknown
|
|
||||||
STDMETHODIMP QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept override { return pOut->QueryInterface(riid, ppvObj); }
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) AddRef() noexcept override {
|
|
||||||
m_iRefCount++;
|
|
||||||
return pOut->AddRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) Release() noexcept override {
|
|
||||||
m_iRefCount--;
|
|
||||||
return pOut->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
// IAudio
|
|
||||||
|
|
||||||
STDMETHODIMP Flush() noexcept override { return S_OK; }
|
|
||||||
|
|
||||||
STDMETHODIMP LevelGet(DWORD* pLevel) noexcept override { return E_NOTIMPL; }
|
|
||||||
|
|
||||||
STDMETHODIMP LevelSet(DWORD level) noexcept override { return E_NOTIMPL; }
|
|
||||||
|
|
||||||
STDMETHODIMP PassNotify(PVOID pSink, IID iid) noexcept override {
|
|
||||||
printf("AudioOutBuffer::Audio::PassNotify() %p\n", pSink);
|
|
||||||
if(pSink == nullptr) {
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(iid != IID_IAudioDestNotifySink)
|
|
||||||
return AUDERR_INVALIDNOTIFYSINK;
|
|
||||||
|
|
||||||
pOut->m_pDestNotifySink = static_cast<IAudioDestNotifySink*>(pSink);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP PosnGet(PQWORD pos) noexcept override {
|
|
||||||
if(!pos)
|
|
||||||
return E_POINTER;
|
|
||||||
*pos = pOut->m_BufferWritten;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP Claim() noexcept override { return S_OK; }
|
|
||||||
|
|
||||||
STDMETHODIMP UnClaim() noexcept override { return S_OK; }
|
|
||||||
|
|
||||||
STDMETHODIMP Start() noexcept override {
|
|
||||||
// TODO
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP Stop() noexcept override {
|
|
||||||
// TODO
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP TotalGet(PQWORD total) noexcept override { return PosnGet(total); }
|
|
||||||
|
|
||||||
STDMETHODIMP ToFileTime(PQWORD time, FILETIME* out) noexcept override { return E_NOTIMPL; }
|
|
||||||
|
|
||||||
STDMETHODIMP WaveFormatGet(SDATA* pOut) noexcept override {
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
//IMalloc* pMalloc { nullptr };
|
|
||||||
//if(auto hr = CoGetMalloc(1, &pMalloc); FAILED(hr))
|
|
||||||
// return hr;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP WaveFormatSet(SDATA data) noexcept override {
|
|
||||||
if(!data.pData)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
AudioOutBuffer* pOut;
|
|
||||||
|
|
||||||
ULONG m_iRefCount{};
|
|
||||||
};
|
|
||||||
|
|
||||||
AudioOutBuffer::AudioOutBuffer() {
|
|
||||||
printf("AudioOutBuffer() %p\n", this);
|
|
||||||
m_Audio = new AudioOutBuffer::Audio(this);
|
|
||||||
m_AudioDestBuffer = new AudioOutBuffer::Dest(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioOutBuffer::~AudioOutBuffer() {
|
|
||||||
printf("~AudioOutBuffer() %p\n", this);
|
|
||||||
if(m_AudioDestBuffer)
|
|
||||||
delete m_AudioDestBuffer;
|
|
||||||
|
|
||||||
if(m_Audio)
|
|
||||||
delete m_Audio;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IUnknown
|
|
||||||
STDMETHODIMP AudioOutBuffer::QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept {
|
|
||||||
if(!ppvObj)
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
|
|
||||||
*ppvObj = nullptr;
|
|
||||||
|
|
||||||
// This object only directly implements IUnknown, and proxies
|
|
||||||
// to other implementation objects for other interfaces.
|
|
||||||
if(riid == IID_IUnknown) {
|
|
||||||
*ppvObj = static_cast<void*>(this);
|
|
||||||
AddRef();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return implementations
|
|
||||||
if(riid == IID_IAudio) {
|
|
||||||
*ppvObj = static_cast<void*>(m_Audio);
|
|
||||||
//m_Audio->AddRef();
|
|
||||||
return S_OK;
|
|
||||||
} else if(riid == IID_IAudioDest) {
|
|
||||||
*ppvObj = static_cast<void*>(m_AudioDestBuffer);
|
|
||||||
//m_AudioDestBuffer->AddRef();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) AudioOutBuffer::AddRef() {
|
|
||||||
return InterlockedIncrement(&m_iRefCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP_(ULONG) AudioOutBuffer::Release() {
|
|
||||||
auto ulRefCount = InterlockedDecrement(&m_iRefCount);
|
|
||||||
if(ulRefCount == 0) {
|
|
||||||
printf("Deleting release AudioOutBuffer\n");
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
return ulRefCount;
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include <windows.h>
|
|
||||||
#include "base/comptr.hpp"
|
|
||||||
#include "sapi4/include/speech.h"
|
|
||||||
|
|
||||||
// Implementation of SAPI 4 IAudio(Dest) to spit out wave format data to a buffer
|
|
||||||
// TODO: out-line definition so other components can call methods they need
|
|
||||||
struct AudioOutBuffer : public IUnknown {
|
|
||||||
|
|
||||||
// Implements IAudioDest.
|
|
||||||
struct Dest;
|
|
||||||
struct Audio;
|
|
||||||
|
|
||||||
AudioOutBuffer();
|
|
||||||
virtual ~AudioOutBuffer();
|
|
||||||
|
|
||||||
AudioOutBuffer(const AudioOutBuffer&) = delete;
|
|
||||||
AudioOutBuffer(AudioOutBuffer&&) = delete;
|
|
||||||
|
|
||||||
// IUnknown
|
|
||||||
STDMETHODIMP QueryInterface(const IID& riid, LPVOID* ppvObj) noexcept override;
|
|
||||||
STDMETHODIMP_(ULONG) AddRef() override;
|
|
||||||
STDMETHODIMP_(ULONG) Release() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
ULONG m_iRefCount{};
|
|
||||||
|
|
||||||
Dest* m_AudioDestBuffer{};
|
|
||||||
Audio* m_Audio{};
|
|
||||||
|
|
||||||
enum class State {
|
|
||||||
Clear,
|
|
||||||
WroteHeader,
|
|
||||||
WritingWaveData,
|
|
||||||
Done
|
|
||||||
};
|
|
||||||
|
|
||||||
//base::ComPtr<IAudioDestNotifySink, &IID_IAudioDestNotifySink> m_pDestNotifySink{};
|
|
||||||
IAudioDestNotifySink* m_pDestNotifySink{nullptr};
|
|
||||||
|
|
||||||
QWORD m_BufferWritten{};
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,6 +0,0 @@
|
||||||
// This file declares all the SAPI 4.0 GUID's.
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
|
|
||||||
#include "sapi4/include/speech.h"
|
|
|
@ -1,30 +0,0 @@
|
||||||
#include <windows.h>
|
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/// base class for access to text-to-speech APIs.
|
|
||||||
struct ISpeechAPI {
|
|
||||||
|
|
||||||
struct VoiceInfo {
|
|
||||||
GUID guid{}; // Optional. May not be filled out if the API doesn't do guids
|
|
||||||
std::string voiceName;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ~ISpeechAPI() = default;
|
|
||||||
|
|
||||||
/// Creates a implementation of SpeechAPI for SAPI 4.
|
|
||||||
/// COM must be initalized before calling this function.
|
|
||||||
static ISpeechAPI* CreateSapi4();
|
|
||||||
|
|
||||||
/// Performs the bare level of initalization required to use the speech API
|
|
||||||
virtual HRESULT Initialize() = 0;
|
|
||||||
|
|
||||||
virtual const std::vector<VoiceInfo>& GetVoices() = 0;
|
|
||||||
|
|
||||||
/// Selects a voice.
|
|
||||||
virtual HRESULT SelectVoice(std::string_view voiceName) = 0;
|
|
||||||
|
|
||||||
|
|
||||||
//virtual HRESULT Speak(LPCSTR text, char** pOutputBuffer, size_t* pOutSize) = 0;
|
|
||||||
};
|
|
|
@ -1,34 +0,0 @@
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
typedef BOOL(WINAPI* PFN_INITIALIZECRITICALSECTIONEX)(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags);
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
PFN_INITIALIZECRITICALSECTIONEX pfnInitalizeCriticalSectionEx = nullptr;
|
|
||||||
|
|
||||||
BOOL WINAPI _InitalizeCriticalSectionEx_xp(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags) {
|
|
||||||
// We ignore dwFlags, but pass dwSpinCount to InitializeCriticalSectionAndSpinCount,
|
|
||||||
// which DOES exist on XP.
|
|
||||||
static_cast<void>(dwFlags);
|
|
||||||
return InitializeCriticalSectionAndSpinCount(lpCriticalSection, dwSpinCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL WINAPI LibInitalizeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD dwFlags) {
|
|
||||||
if(!pfnInitalizeCriticalSectionEx) {
|
|
||||||
pfnInitalizeCriticalSectionEx =
|
|
||||||
reinterpret_cast<PFN_INITIALIZECRITICALSECTIONEX>(GetProcAddress(GetModuleHandle("kernel32.dll"), "InitializeCriticalSectionEx"));
|
|
||||||
|
|
||||||
// Compatibilty.
|
|
||||||
if(!pfnInitalizeCriticalSectionEx)
|
|
||||||
pfnInitalizeCriticalSectionEx = _InitalizeCriticalSectionEx_xp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pfnInitalizeCriticalSectionEx(lpCriticalSection, dwSpinCount, dwFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WINAPI LibGetSystemTimePreciseAsFileTime(LPFILETIME lpSystemTimeAsFileTime) {
|
|
||||||
// TODO: Above
|
|
||||||
return GetSystemTimeAsFileTime(lpSystemTimeAsFileTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
// This file declares forwarders for Windows imports which the newer VS 2022 CRT requires.
|
|
||||||
|
|
||||||
.globl "__imp__InitializeCriticalSectionEx@12"
|
|
||||||
"__imp__InitializeCriticalSectionEx@12":
|
|
||||||
.long "_LibInitalizeCriticalSectionEx@12"
|
|
||||||
|
|
||||||
.globl "__imp__GetSystemTimePreciseAsFileTime@4"
|
|
||||||
"__imp__GetSystemTimePreciseAsFileTime@4":
|
|
||||||
.long "_LibGetSystemTimePreciseAsFileTime@4"
|
|
|
@ -1,104 +0,0 @@
|
||||||
/* This file provides routines used for thread-safe initialisation of static
|
|
||||||
* variables when /Zc:threadSafeInit is used (enabled by default).
|
|
||||||
*
|
|
||||||
* This is intended to override the default implementations from the Microsoft
|
|
||||||
* C++ Runtime which are compiled to target Windows Vista or later.
|
|
||||||
*
|
|
||||||
* Modeled on the reference implementation in thread_safe_statics.cpp in the
|
|
||||||
* Microsoft C++ Runtime.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
static const int UNINITIALIZED = 0;
|
|
||||||
static const int INITIALIZING = -1;
|
|
||||||
|
|
||||||
static const int EPOCH_BASE = INT_MIN;
|
|
||||||
|
|
||||||
/* Exposed as a public symbol in the reference implementation, so exposed it
|
|
||||||
* has to stay here too...
|
|
||||||
*/
|
|
||||||
int _Init_global_epoch = EPOCH_BASE;
|
|
||||||
__declspec(thread) int _Init_thread_epoch = EPOCH_BASE;
|
|
||||||
|
|
||||||
static pthread_mutex_t _Init_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
static pthread_cond_t _Init_thread_cond = PTHREAD_COND_INITIALIZER;
|
|
||||||
|
|
||||||
void __cdecl _Init_thread_lock()
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&_Init_thread_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl _Init_thread_unlock()
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&_Init_thread_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl _Init_thread_wait_v2()
|
|
||||||
{
|
|
||||||
pthread_cond_wait(&_Init_thread_cond, &_Init_thread_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl _Init_thread_notify()
|
|
||||||
{
|
|
||||||
pthread_cond_broadcast(&_Init_thread_cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl _Init_thread_header(int* const pOnce)
|
|
||||||
{
|
|
||||||
_Init_thread_lock();
|
|
||||||
|
|
||||||
if (*pOnce == UNINITIALIZED)
|
|
||||||
{
|
|
||||||
*pOnce = INITIALIZING;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (*pOnce == INITIALIZING)
|
|
||||||
{
|
|
||||||
_Init_thread_wait_v2();
|
|
||||||
|
|
||||||
if (*pOnce == UNINITIALIZED)
|
|
||||||
{
|
|
||||||
*pOnce = INITIALIZING;
|
|
||||||
_Init_thread_unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_Init_thread_epoch = _Init_global_epoch;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Init_thread_unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl _Init_thread_abort(int* const pOnce)
|
|
||||||
{
|
|
||||||
_Init_thread_lock();
|
|
||||||
|
|
||||||
*pOnce = UNINITIALIZED;
|
|
||||||
|
|
||||||
_Init_thread_unlock();
|
|
||||||
_Init_thread_notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl _Init_thread_footer(int* const pOnce)
|
|
||||||
{
|
|
||||||
_Init_thread_lock();
|
|
||||||
|
|
||||||
++_Init_global_epoch;
|
|
||||||
|
|
||||||
/* Probably unlikely condition... you would need to construct ~2 billion
|
|
||||||
* static objects before the "epoch" would roll up to the "INITIALIZING"
|
|
||||||
* constant and cause weird behaviour... the official implementation
|
|
||||||
* technically has this bug too.
|
|
||||||
*/
|
|
||||||
assert(_Init_global_epoch < INITIALIZING);
|
|
||||||
|
|
||||||
*pOnce = _Init_global_epoch;
|
|
||||||
_Init_thread_epoch = _Init_global_epoch;
|
|
||||||
|
|
||||||
_Init_thread_unlock();
|
|
||||||
_Init_thread_notify();
|
|
||||||
}
|
|
4
speech2/third_party/README.md
vendored
4
speech2/third_party/README.md
vendored
|
@ -1,4 +0,0 @@
|
||||||
Files in this directory are the intellectual property of:
|
|
||||||
|
|
||||||
- sapi4: Microsoft Speech SDK 4.0.4.2512
|
|
||||||
- sapi5: Microsoft Speech SDK 5.1
|
|
13
speech2/third_party/boost/CMakeLists.txt
vendored
13
speech2/third_party/boost/CMakeLists.txt
vendored
|
@ -1,13 +0,0 @@
|
||||||
# Hack but it works :)
|
|
||||||
set(BOOST_SUPERPROJECT_VERSION 1.85.0)
|
|
||||||
|
|
||||||
# Boost Context Have Sucks
|
|
||||||
set(BOOST_CONTEXT_ASSEMBLER clang_gas CACHE STRING "")
|
|
||||||
set(BOOST_CONTEXT_ASM_SUFFIX .S CACHE STRING "")
|
|
||||||
|
|
||||||
# Populate library list
|
|
||||||
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/list _COLLABVM3_BOOST_LIBRARY_LIST)
|
|
||||||
foreach(lib ${_COLLABVM3_BOOST_LIBRARY_LIST})
|
|
||||||
message(STATUS "Adding boost module ${lib}")
|
|
||||||
add_subdirectory(${lib})
|
|
||||||
endforeach()
|
|
11
speech2/third_party/boost/README.md
vendored
11
speech2/third_party/boost/README.md
vendored
|
@ -1,11 +0,0 @@
|
||||||
# Welcome to hell
|
|
||||||
|
|
||||||
This is where all the boost libraries used by the server live
|
|
||||||
|
|
||||||
see ./list for them
|
|
||||||
|
|
||||||
# Reinitalizing
|
|
||||||
|
|
||||||
The following bash one liner was used to initalize this repo
|
|
||||||
|
|
||||||
`for f in $(cat list); do git submodule add https://github.com/boostorg/$f.git $f; cd $f; git checkout boost-1.82.0; cd ..; done`
|
|
10
speech2/third_party/boost/add.sh
vendored
10
speech2/third_party/boost/add.sh
vendored
|
@ -1,10 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# note that this doesn't add the library to ./list
|
|
||||||
# you will need to do that yourself
|
|
||||||
# (it could be added but bleh)
|
|
||||||
|
|
||||||
lib=$1
|
|
||||||
git submodule add https://github.com/boostorg/$lib.git $lib
|
|
||||||
# remember to bump the version afterwards
|
|
||||||
|
|
1
speech2/third_party/boost/algorithm
vendored
1
speech2/third_party/boost/algorithm
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 32c5a6327cfdca5d41ce0f1d8849b811886daa2f
|
|
1
speech2/third_party/boost/align
vendored
1
speech2/third_party/boost/align
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 5ad7df63cd792fbdb801d600b93cad1a432f0151
|
|
1
speech2/third_party/boost/array
vendored
1
speech2/third_party/boost/array
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 23f6b27c0d9916b9932baac898ae3009817a9153
|
|
1
speech2/third_party/boost/asio
vendored
1
speech2/third_party/boost/asio
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit e65367991cb5fbdb8a7cf218ae38f69ca9a0a9f5
|
|
1
speech2/third_party/boost/assert
vendored
1
speech2/third_party/boost/assert
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 447e0b3a331930f8708ade0e42683d12de9dfbc3
|
|
1
speech2/third_party/boost/atomic
vendored
1
speech2/third_party/boost/atomic
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 5bbcce0f6e855dc4009e2e6977c62e0520c39573
|
|
1
speech2/third_party/boost/beast
vendored
1
speech2/third_party/boost/beast
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 98b8be489fa7a74753a724d8d0772d90bcbed0fc
|
|
1
speech2/third_party/boost/bind
vendored
1
speech2/third_party/boost/bind
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 9fbfdcb3577e9427815d4f8cc25b3a25d5b9696b
|
|
10
speech2/third_party/boost/bump_version.sh
vendored
10
speech2/third_party/boost/bump_version.sh
vendored
|
@ -1,10 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# bump all the repositories
|
|
||||||
for library in $(cat $PWD/list); do
|
|
||||||
pushd $library >/dev/null 2>&1
|
|
||||||
git checkout develop
|
|
||||||
git pull
|
|
||||||
git checkout $1
|
|
||||||
popd >/dev/null 2>&1
|
|
||||||
done
|
|
1
speech2/third_party/boost/charconv
vendored
1
speech2/third_party/boost/charconv
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit ecdca0865d4d8fcfbf8e5b48914f2b5711c418ad
|
|
1
speech2/third_party/boost/chrono
vendored
1
speech2/third_party/boost/chrono
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit ee0d6d543a37d9b7243682549e9ae359eb89daa9
|
|
1
speech2/third_party/boost/circular_buffer
vendored
1
speech2/third_party/boost/circular_buffer
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit a08a5b55ee82e0c2487523471379ac53a23935dc
|
|
1
speech2/third_party/boost/concept_check
vendored
1
speech2/third_party/boost/concept_check
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 37c9bddf0bdefaaae0ca5852c1a153d9fc43f278
|
|
1
speech2/third_party/boost/config
vendored
1
speech2/third_party/boost/config
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 11385ec21012926e15a612e3bf9f9a71403c1e5b
|
|
1
speech2/third_party/boost/container
vendored
1
speech2/third_party/boost/container
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 6e697d796897b32b471b4f0740dcaa03d8ee57cc
|
|
1
speech2/third_party/boost/container_hash
vendored
1
speech2/third_party/boost/container_hash
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 6d214eb776456bf17fbee20780a034a23438084f
|
|
1
speech2/third_party/boost/context
vendored
1
speech2/third_party/boost/context
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 1bde50e400547e29336afe7ea0cd693d8c884fb6
|
|
1
speech2/third_party/boost/conversion
vendored
1
speech2/third_party/boost/conversion
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 9f285ef0c43c101e49b37bf5e6085e8d635887dc
|
|
1
speech2/third_party/boost/core
vendored
1
speech2/third_party/boost/core
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 083b41c17e34f1fc9b43ab796b40d0d8bece685c
|
|
1
speech2/third_party/boost/coroutine
vendored
1
speech2/third_party/boost/coroutine
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 1e1347c0b1910b9310ec1719edad8b0bf2fd03c8
|
|
1
speech2/third_party/boost/date_time
vendored
1
speech2/third_party/boost/date_time
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 85e637cb325208c2af9af791c3a1948b4888c6cd
|
|
1
speech2/third_party/boost/describe
vendored
1
speech2/third_party/boost/describe
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 50719b212349f3d1268285c586331584d3dbfeb5
|
|
1
speech2/third_party/boost/detail
vendored
1
speech2/third_party/boost/detail
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 9c3a0022b25d3e483f9100cc363bc93a72fd900a
|
|
1
speech2/third_party/boost/endian
vendored
1
speech2/third_party/boost/endian
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit c9b436e5dfce85e8ae365e5aabbb872dd35c29eb
|
|
1
speech2/third_party/boost/exception
vendored
1
speech2/third_party/boost/exception
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit b9170a02f102250b308c9f94ed6593c5f30eab39
|
|
1
speech2/third_party/boost/filesystem
vendored
1
speech2/third_party/boost/filesystem
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit a0c8edba38a4d31b449fcf7b7ada455977342596
|
|
1
speech2/third_party/boost/function
vendored
1
speech2/third_party/boost/function
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 28b88d07bb4807445462c3f5dab0efde6f532d32
|
|
1
speech2/third_party/boost/function_types
vendored
1
speech2/third_party/boost/function_types
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 895335874d67987ada0d8bf6ca1725e70642ed49
|
|
1
speech2/third_party/boost/functional
vendored
1
speech2/third_party/boost/functional
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 6a573e4b8333ee63ee62ce95558c3667348db233
|
|
1
speech2/third_party/boost/fusion
vendored
1
speech2/third_party/boost/fusion
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7d4c03fa032299f2d46149b7b3136c9fd43e4f81
|
|
1
speech2/third_party/boost/integer
vendored
1
speech2/third_party/boost/integer
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit dea8e3445dc3ca29201498260307138b9460a70c
|
|
1
speech2/third_party/boost/intrusive
vendored
1
speech2/third_party/boost/intrusive
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 07ba0e376177409c396c109807c13b7181a98ebe
|
|
1
speech2/third_party/boost/io
vendored
1
speech2/third_party/boost/io
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 342e4c6d10d586058818daa84201a2d301357a53
|
|
1
speech2/third_party/boost/iterator
vendored
1
speech2/third_party/boost/iterator
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 4f7219965a399051bb0d8088ea4ab3929b1ac3f2
|
|
1
speech2/third_party/boost/json
vendored
1
speech2/third_party/boost/json
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 9f85ed6d62ff91c6dc4fc30e3a20e9049ec67585
|
|
1
speech2/third_party/boost/leaf
vendored
1
speech2/third_party/boost/leaf
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit ed8f9cd32f4fde695d497502f696f6f861b68559
|
|
1
speech2/third_party/boost/lexical_cast
vendored
1
speech2/third_party/boost/lexical_cast
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 02e5821ab32c45fad719829e9644e5d681c9ba0b
|
|
67
speech2/third_party/boost/list
vendored
67
speech2/third_party/boost/list
vendored
|
@ -1,67 +0,0 @@
|
||||||
algorithm
|
|
||||||
align
|
|
||||||
array
|
|
||||||
assert
|
|
||||||
atomic
|
|
||||||
bind
|
|
||||||
charconv
|
|
||||||
chrono
|
|
||||||
circular_buffer
|
|
||||||
concept_check
|
|
||||||
config
|
|
||||||
container
|
|
||||||
container_hash
|
|
||||||
context
|
|
||||||
conversion
|
|
||||||
core
|
|
||||||
coroutine
|
|
||||||
date_time
|
|
||||||
describe
|
|
||||||
detail
|
|
||||||
endian
|
|
||||||
exception
|
|
||||||
filesystem
|
|
||||||
function
|
|
||||||
functional
|
|
||||||
function_types
|
|
||||||
fusion
|
|
||||||
integer
|
|
||||||
intrusive
|
|
||||||
io
|
|
||||||
iterator
|
|
||||||
json
|
|
||||||
leaf
|
|
||||||
lexical_cast
|
|
||||||
lockfree
|
|
||||||
logic
|
|
||||||
move
|
|
||||||
mp11
|
|
||||||
mpl
|
|
||||||
numeric_conversion
|
|
||||||
optional
|
|
||||||
parameter
|
|
||||||
pool
|
|
||||||
predef
|
|
||||||
preprocessor
|
|
||||||
range
|
|
||||||
ratio
|
|
||||||
rational
|
|
||||||
regex
|
|
||||||
scope
|
|
||||||
smart_ptr
|
|
||||||
static_assert
|
|
||||||
static_string
|
|
||||||
system
|
|
||||||
throw_exception
|
|
||||||
tokenizer
|
|
||||||
tuple
|
|
||||||
type_index
|
|
||||||
typeof
|
|
||||||
type_traits
|
|
||||||
unordered
|
|
||||||
url
|
|
||||||
utility
|
|
||||||
variant2
|
|
||||||
winapi
|
|
||||||
asio
|
|
||||||
beast
|
|
1
speech2/third_party/boost/lockfree
vendored
1
speech2/third_party/boost/lockfree
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit fdd4d0632dd0904f6e9c656c45397fe8ef985bc9
|
|
1
speech2/third_party/boost/logic
vendored
1
speech2/third_party/boost/logic
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 145778490c2d332c1411df6a5274a4b53ec3e091
|
|
1
speech2/third_party/boost/move
vendored
1
speech2/third_party/boost/move
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7c01072629d83a7b54c99de70ef535d699ebd200
|
|
1
speech2/third_party/boost/mp11
vendored
1
speech2/third_party/boost/mp11
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 863d8b8d2b20f2acd0b5870f23e553df9ce90e6c
|
|
1
speech2/third_party/boost/mpl
vendored
1
speech2/third_party/boost/mpl
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit b440c45c2810acbddc917db057f2e5194da1a199
|
|
1
speech2/third_party/boost/numeric_conversion
vendored
1
speech2/third_party/boost/numeric_conversion
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 50a1eae942effb0a9b90724323ef8f2a67e7984a
|
|
1
speech2/third_party/boost/optional
vendored
1
speech2/third_party/boost/optional
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit c60db27762ff9cc16529e069c3c15f2fa898f994
|
|
1
speech2/third_party/boost/parameter
vendored
1
speech2/third_party/boost/parameter
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit c07f2b8d37ded87f6f9d5bac867550f6e61282c1
|
|
1
speech2/third_party/boost/pool
vendored
1
speech2/third_party/boost/pool
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit ec7da07ed13e0c61e50d945b574a12ae7ec83cf4
|
|
1
speech2/third_party/boost/predef
vendored
1
speech2/third_party/boost/predef
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 0fdfb49c3a6789e50169a44e88a07cc889001106
|
|
1
speech2/third_party/boost/preprocessor
vendored
1
speech2/third_party/boost/preprocessor
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit c4ea7e40d365ba28faecef8917d5c3f1e0121bf9
|
|
1
speech2/third_party/boost/range
vendored
1
speech2/third_party/boost/range
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 2bb6b636796f7b008196888613f51f5bb347c77d
|
|
1
speech2/third_party/boost/ratio
vendored
1
speech2/third_party/boost/ratio
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit d5b33caa7d564be9be6d962b18659b7741d764ac
|
|
1
speech2/third_party/boost/rational
vendored
1
speech2/third_party/boost/rational
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 564623136417068916495e2b24737054d607347c
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue