Added an initial WASAPI output plugin implementation. Down with waveout!

(maybe).
This commit is contained in:
casey langen 2016-12-04 18:43:11 -08:00
parent 25506a009d
commit a797d4db9d
9 changed files with 905 additions and 0 deletions

View File

@ -6,6 +6,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "musikbox", "src\musikbox\mu
ProjectSection(ProjectDependencies) = postProject
{68AA481E-3CCE-440F-8CCE-69F1B371C89D} = {68AA481E-3CCE-440F-8CCE-69F1B371C89D}
{3E30064E-B9C4-4690-8AC2-2C694176A319} = {3E30064E-B9C4-4690-8AC2-2C694176A319}
{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304} = {EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}
{54764854-5A73-4329-9BAD-9AF22C72D9E2} = {54764854-5A73-4329-9BAD-9AF22C72D9E2}
{465EF178-91C1-4068-BE1D-F9616ECCB6DE} = {465EF178-91C1-4068-BE1D-F9616ECCB6DE}
{4F10C17A-8AF7-4FAC-A4E2-087AE6E8F9D8} = {4F10C17A-8AF7-4FAC-A4E2-087AE6E8F9D8}
@ -37,6 +38,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32globalhotkeys", "src\c
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "win32gdivis", "src\contrib\win32gdivis\GdiVis-musikcube.vcxproj", "{68AA481E-3CCE-440F-8CCE-69F1B371C89D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wasapiout", "src\contrib\wasapiout\wasapiout.vcxproj", "{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -91,6 +94,10 @@ Global
{68AA481E-3CCE-440F-8CCE-69F1B371C89D}.Debug|Win32.Build.0 = Debug|Win32
{68AA481E-3CCE-440F-8CCE-69F1B371C89D}.Release|Win32.ActiveCfg = Release|Win32
{68AA481E-3CCE-440F-8CCE-69F1B371C89D}.Release|Win32.Build.0 = Release|Win32
{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}.Debug|Win32.ActiveCfg = Debug|Win32
{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}.Debug|Win32.Build.0 = Debug|Win32
{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}.Release|Win32.ActiveCfg = Release|Win32
{EBD2E652-AA1B-4B8B-8D03-CCECB9BF3304}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,316 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include "WasapiOut.h"
#include <AudioSessionTypes.h>
#include <iostream>
#include <chrono>
#include <thread>
#define MAX_BUFFERS_PER_OUTPUT 32
/* NOTE! device init and deinit logic was stolen and modified from
QMMP's WASABI output plugin! http://qmmp.ylsoftware.com/ */
#ifndef AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM
#define AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
#endif
using Lock = std::unique_lock<std::recursive_mutex>;
WasapiOut::WasapiOut()
: enumerator(nullptr)
, device(nullptr)
, audioClient(nullptr)
, renderClient(nullptr)
, simpleAudioVolume(nullptr)
, outputBufferSize(0)
, state(Stopped) {
memset(&waveFormat, 0, sizeof(WAVEFORMATEXTENSIBLE));
}
WasapiOut::~WasapiOut() {
}
void WasapiOut::Destroy() {
this->Reset();
delete this;
}
void WasapiOut::Pause() {
Lock lock(this->stateMutex);
if (this->audioClient) {
this->state = Paused;
this->audioClient->Stop();
}
}
void WasapiOut::Resume() {
Lock lock(this->stateMutex);
if (this->audioClient) {
this->state = Playing;
this->audioClient->Start();
}
}
void WasapiOut::SetVolume(double volume) {
Lock lock(this->stateMutex);
if (this->simpleAudioVolume) {
simpleAudioVolume->SetMasterVolume((float) volume, 0);
}
}
void WasapiOut::Stop() {
{
Lock lock(this->stateMutex);
if (this->audioClient) {
this->audioClient->Stop();
this->audioClient->Reset();
this->audioClient->Start();
}
}
std::deque<std::shared_ptr<BufferContext>> toRelease;
{
Lock lock(this->bufferQueueMutex);
std::swap(this->pendingQueue, toRelease);
}
auto it = toRelease.begin();
while (it != toRelease.end()) {
(*it)->provider->OnBufferProcessed((*it)->buffer);
++it;
}
}
bool WasapiOut::Play(IBuffer *buffer, IBufferProvider *provider) {
{
Lock lock(this->stateMutex);
if (!this->Configure(buffer)) {
this->Reset();
return false;
}
this->state = Playing;
UINT32 availableFrames;
UINT32 frameOffset = 0;
UINT32 samples = (UINT32)buffer->Samples();
UINT32 framesToWrite = samples / (UINT32)buffer->Channels();
int channels = buffer->Channels();
do {
this->audioClient->GetCurrentPadding(&frameOffset);
availableFrames = (this->outputBufferSize - frameOffset);
if (availableFrames < framesToWrite) {
UINT32 delta = framesToWrite - availableFrames;
REFERENCE_TIME sleepTime = (delta * 1000 * 1000) / buffer->SampleRate();
std::this_thread::sleep_for(std::chrono::microseconds(sleepTime));
}
} while (this->state == Playing && availableFrames < framesToWrite);
if (state != Playing) {
return false;
}
if (availableFrames >= framesToWrite) {
BYTE *data = 0;
HRESULT result = this->renderClient->GetBuffer(framesToWrite, &data);
if (result != S_OK) {
return false;
}
memcpy(data, buffer->BufferPointer(), sizeof(float) * samples);
this->renderClient->ReleaseBuffer(framesToWrite, 0);
}
}
{
Lock lock(this->bufferQueueMutex);
std::shared_ptr<BufferContext> context(new BufferContext());
context->buffer = buffer;
context->provider = provider;
pendingQueue.push_back(context);
if (pendingQueue.size() >= MAX_BUFFERS_PER_OUTPUT) {
context = pendingQueue.front();
pendingQueue.pop_front();
context->provider->OnBufferProcessed(context->buffer);
}
}
return true;
}
void WasapiOut::Reset() {
if (this->audioClient) {
this->audioClient->Stop();
this->audioClient->Release();
this->audioClient = nullptr;
}
if (this->enumerator) {
this->enumerator->Release();
this->enumerator = nullptr;
}
if (this->device) {
this->device->Release();
this->device = 0;
}
if (this->renderClient) {
this->renderClient->Release();
this->renderClient = nullptr;
}
if (this->simpleAudioVolume) {
this->simpleAudioVolume->Release();
this->simpleAudioVolume = nullptr;
}
}
bool WasapiOut::Configure(IBuffer *buffer) {
HRESULT result;
if (!this->audioClient) {
CoInitialize(nullptr);
result = CoCreateInstance(
__uuidof(MMDeviceEnumerator),
NULL,
CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**) &this->enumerator);
if (result != S_OK) {
std::cerr << "WasapiOut: CoCreateInstance failed, error code = " << result << "\n";
return false;
}
if ((result = this->enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &this->device)) != S_OK) {
std::cerr << "WasapiOut: IMMDeviceEnumerator::GetDefaultAudioEndpoint failed, error code = " << result << "\n";
return false;
}
if ((result = this->device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**) &this->audioClient)) != S_OK) {
std::cerr << "WasapiOut: IMMDevice::Activate failed, error code = " << result << "\n";
return false;
}
}
if (waveFormat.Format.nChannels == buffer->Channels() &&
waveFormat.Format.nSamplesPerSec == buffer->SampleRate())
{
return true;
}
DWORD speakerConfig = 0;
switch (buffer->Channels()) {
case 1:
speakerConfig = KSAUDIO_SPEAKER_MONO;
break;
case 2:
speakerConfig = KSAUDIO_SPEAKER_STEREO;
break;
case 4:
speakerConfig = KSAUDIO_SPEAKER_QUAD;
break;
case 5:
speakerConfig = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT);
break;
case 6:
speakerConfig = KSAUDIO_SPEAKER_5POINT1;
break;
}
WAVEFORMATEXTENSIBLE &wf = this->waveFormat;
wf.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE);
wf.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
wf.Format.nChannels = (WORD) buffer->Channels();
wf.Format.wBitsPerSample = 8 * sizeof(float);
wf.Format.nSamplesPerSec = (DWORD) buffer->SampleRate();
wf.Samples.wValidBitsPerSample = 8 * sizeof(float);
wf.Format.nBlockAlign = (wf.Format.wBitsPerSample / 8) * wf.Format.nChannels;
wf.Format.nAvgBytesPerSec = wf.Format.nSamplesPerSec * wf.Format.nBlockAlign;
wf.dwChannelMask = speakerConfig;
wf.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
DWORD streamFlags = 0;
if (this->audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX *) &wf, 0) != S_OK) {
streamFlags |= AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM;
std::cerr << "WasapiOut: format is not supported, using converter\n";
}
long totalMillis = (long) round((buffer->Samples() * 1000) / buffer->SampleRate()) * MAX_BUFFERS_PER_OUTPUT;
REFERENCE_TIME hundredNanos = totalMillis * 1000 * 10;
if ((result = this->audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, streamFlags, hundredNanos, 0, (WAVEFORMATEX *) &wf, NULL)) != S_OK) {
std::cerr << "WasapiOut: IAudioClient::Initialize failed, error code = " << result << "\n";
return false;
}
if ((result = this->audioClient->GetBufferSize(&this->outputBufferSize)) != S_OK) {
std::cerr << "WasapiOut: IAudioClient::GetBufferSize failed, error code = " << result << "\n";
return false;
}
if ((result = this->audioClient->GetService(__uuidof(IAudioRenderClient), (void**) &this->renderClient)) != S_OK) {
std::cerr << "WasapiOut: IAudioClient::GetService failed, error code = " << result << "\n";
return false;
}
if ((result = this->audioClient->GetService(__uuidof(ISimpleAudioVolume), (void**) &this->simpleAudioVolume)) != S_OK) {
std::cerr << "WasapiOut: IAudioClient::GetService failed, error code = " << result << "\n";
return false;
}
if ((result = this->audioClient->Start()) != S_OK) {
std::cerr << "WasapiOut: IAudioClient::Start failed, error code = " << result << "\n";
return false;
}
return true;
}

View File

@ -0,0 +1,89 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include "pch.h"
#include <deque>
#include <memory>
#include <mutex>
#include <mmdeviceapi.h>
#include <Audioclient.h>
#include <core/sdk/IOutput.h>
using namespace musik::core::sdk;
class WasapiOut : public IOutput {
public:
WasapiOut();
~WasapiOut();
virtual void Destroy();
virtual void Pause();
virtual void Resume();
virtual void SetVolume(double volume);
virtual void Stop();
virtual bool Play(IBuffer *buffer, IBufferProvider *provider);
private:
enum State {
Stopped,
Playing,
Paused
};
struct BufferContext {
IBuffer *buffer;
IBufferProvider *provider;
};
bool Configure(IBuffer *buffer);
void Reset();
IMMDeviceEnumerator *enumerator;
IMMDevice *device;
IAudioClient *audioClient;
IAudioRenderClient *renderClient;
ISimpleAudioVolume *simpleAudioVolume;
WAVEFORMATEXTENSIBLE waveFormat;
UINT32 outputBufferSize;
UINT64 totalSamplesWritten;
State state;
std::recursive_mutex bufferQueueMutex;
std::recursive_mutex stateMutex;
std::deque<std::shared_ptr<BufferContext>> pendingQueue;
};

View File

@ -0,0 +1,35 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.h"

View File

@ -0,0 +1,38 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <core/config.h>

View File

@ -0,0 +1,217 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="wasapiout"
ProjectGUID="{ebd2e652-aa1b-4b8b-8d03-ccecb9bf3304}"
RootNamespace="wasapiout"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)/bin/$(ConfigurationName)/plugins"
IntermediateDirectory="./obj/$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../..;../../3rdparty/include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib "
LinkIncremental="2"
AdditionalLibraryDirectories="../../3rdparty/lib"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)/bin/$(ConfigurationName)/plugins"
IntermediateDirectory="./obj/$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../..;../../3rdparty/include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib "
AdditionalLibraryDirectories="../../3rdparty/lib"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
LinkTimeCodeGeneration="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="plugin"
Filter="h;hpp;hxx;hm;inl;inc;xsd;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\pch.cpp"
>
</File>
<File
RelativePath=".\pch.h"
>
</File>
<File
RelativePath=".\WaveOut.cpp"
>
</File>
<File
RelativePath=".\WaveOut.h"
>
</File>
<File
RelativePath=".\waveout_plugin.cpp"
>
</File>
<File
RelativePath=".\WaveOutBuffer.cpp"
>
</File>
<File
RelativePath=".\WaveOutBuffer.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{ebd2e652-aa1b-4b8b-8d03-ccecb9bf3304}</ProjectGuid>
<RootNamespace>wasapiout</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)/bin/$(Configuration)/plugins\</OutDir>
<IntDir>./obj/$(Configuration)\</IntDir>
<LinkIncremental>true</LinkIncremental>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)/bin/$(Configuration)/plugins\</OutDir>
<IntDir>./obj/$(Configuration)\</IntDir>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../..;../../3rdparty/include;../../../../boost_1_60_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../3rdparty/lib;../../../../boost_1_60_0/lib32-msvc-14.0;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../..;../../3rdparty/include;../../../../boost_1_60_0;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat />
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../3rdparty/lib;../../../../boost_1_60_0/lib32-msvc-14.0;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<TargetMachine>MachineX86</TargetMachine>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="pch.cpp" />
<ClCompile Include="WasapiOut.cpp" />
<ClCompile Include="wasapiout_plugin.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="WasapiOut.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="plugin">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<Filter>plugin</Filter>
</ClCompile>
<ClCompile Include="wasapiout_plugin.cpp">
<Filter>plugin</Filter>
</ClCompile>
<ClCompile Include="WasapiOut.cpp">
<Filter>plugin</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>plugin</Filter>
</ClInclude>
<ClInclude Include="WasapiOut.h">
<Filter>plugin</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,57 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2016 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#include <core/sdk/IPlugin.h>
#include "WasapiOut.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
return true;
}
class WasapiOutPlugin : public musik::core::sdk::IPlugin {
void Destroy() { delete this; };
const char* Name() { return "WASAPI IOutput"; };
const char* Version() { return "0.1"; };
const char* Author() { return "clangen"; };
};
extern "C" __declspec(dllexport) musik::core::sdk::IPlugin* GetPlugin() {
return new WasapiOutPlugin();
}
extern "C" __declspec(dllexport) musik::core::sdk::IOutput* GetAudioOutput() {
return new WasapiOut();
}