Fixed: Reimplemented Voicemeeter integration (based on official examples) to fix stuttering issues.

This commit is contained in:
jthedering committed 2022-05-15 18:27:24 +00:00
1 parent da3341ed42
commit 93af3de251
5 files changed
+331 -142

No files matched your search

+178 -122
View File
@@ -1,6 +1,6 @@
/* /*
This file is part of Equalizer APO, a system-wide equalizer. This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering Copyright (C) 2022 Jonas Thedering
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -18,7 +18,7 @@
*/ */
#include "stdafx.h" #include "stdafx.h"
#include <string>
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <shellapi.h> #include <shellapi.h>
@@ -29,15 +29,21 @@
#define voicemeeterKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}" #define voicemeeterKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}"
#define voicemeeterWowKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}" #define voicemeeterWowKeyPath L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VB:Voicemeeter {17359A74-1236-5467}"
#define uninstallStringValueName L"UninstallString" #define uninstallStringValueName L"UninstallString"
#ifdef _WIN64
#define voicemeeterRemoteFileName L"VoicemeeterRemote64.dll"
#else
#define voicemeeterRemoteFileName L"VoicemeeterRemote.dll"
#endif
#define IDM_RESTART 200
using namespace std; using namespace std;
long __stdcall callback(void* lpUser, long nCommand, void* lpData, long nnn); static long __stdcall callback(void* lpUser, long nCommand, void* lpData, long nnn);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance, _In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine, _In_ LPWSTR lpCmdLine,
_In_ int nCmdShow) _In_ int nShowCmd)
{ {
vector<wstring> outputs; vector<wstring> outputs;
if (lpCmdLine[0] != 0) if (lpCmdLine[0] != 0)
@@ -49,30 +55,17 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
LocalFree(argv); LocalFree(argv);
} }
VoicemeeterClient* client = new VoicemeeterClient(outputs); try
MSG msg;
msg.wParam = 0;
bool loop = client->restart;
while (loop)
{ {
client->start(); VoicemeeterClient client(outputs);
client->restart = false; client.run();
return 0;
while (GetMessage(&msg, NULL, 0, 0)) }
{ catch (InitError e)
TranslateMessage(&msg); {
DispatchMessage(&msg); MessageBoxW(NULL, e.getMessage().c_str(), L"Init Error", MB_APPLMODAL | MB_OK | MB_ICONERROR);
} return -1;
loop = client->restart;
client->stop();
} }
delete client;
return (int)msg.wParam;
} }
VoicemeeterClient::VoicemeeterClient(const vector<wstring>& outputs) VoicemeeterClient::VoicemeeterClient(const vector<wstring>& outputs)
@@ -87,108 +80,72 @@ VoicemeeterClient::VoicemeeterClient(const vector<wstring>& outputs)
voicemeeterDirectory = RegistryHelper::readValue(voicemeeterWowKeyPath, uninstallStringValueName); voicemeeterDirectory = RegistryHelper::readValue(voicemeeterWowKeyPath, uninstallStringValueName);
size_t index = voicemeeterDirectory.find_last_of(L'\\'); size_t index = voicemeeterDirectory.find_last_of(L'\\');
HMODULE voicemeeterModule = NULL;
if (index != wstring::npos) if (index != wstring::npos)
{
wstring setupFilename = voicemeeterDirectory.substr(index + 1);
voicemeeterType = 1;
if (setupFilename == L"VoicemeeterProSetup.exe")
voicemeeterType = 2;// banana
else if (setupFilename == L"Voicemeeter8Setup.exe")
voicemeeterType = 3;// potato
voicemeeterDirectory = voicemeeterDirectory.substr(0, index); voicemeeterDirectory = voicemeeterDirectory.substr(0, index);
else
throw InitError(L"Voicemeeter is not installed");
#ifdef _WIN64 HMODULE module = NULL;
voicemeeterModule = LoadLibraryW((voicemeeterDirectory + L"\\VoicemeeterRemote64.dll").c_str()); module = LoadLibraryW((voicemeeterDirectory + L"\\" voicemeeterRemoteFileName).c_str());
#else if (module == NULL)
voicemeeterModule = LoadLibraryW((voicemeeterDirectory + L"\\VoicemeeterRemote.dll").c_str()); throw InitError(L"Failed to load " voicemeeterRemoteFileName);
#endif
}
memset(&vmr, 0, sizeof(T_VBVMR_INTERFACE)); memset(&vmr, 0, sizeof(T_VBVMR_INTERFACE));
#define LOAD_PROC(proc) vmr.proc = (T_ ## proc)GetProcAddress(voicemeeterModule, # proc)
if (voicemeeterModule != NULL)
{
LOAD_PROC(VBVMR_Login);
LOAD_PROC(VBVMR_Logout);
LOAD_PROC(VBVMR_AudioCallbackRegister);
LOAD_PROC(VBVMR_AudioCallbackStart);
LOAD_PROC(VBVMR_AudioCallbackStop);
LOAD_PROC(VBVMR_AudioCallbackUnregister);
LOAD_PROC(VBVMR_GetVoicemeeterType);
restart = true; #define LOAD_PROC(proc) vmr.proc = (T_ ## proc)GetProcAddress(module, # proc);if (vmr.proc == NULL) throw InitError(L"Did not find function \"" # proc L"\" in " voicemeeterRemoteFileName)
} LOAD_PROC(VBVMR_Login);
LOAD_PROC(VBVMR_Logout);
LOAD_PROC(VBVMR_GetVoicemeeterType);
LOAD_PROC(VBVMR_IsParametersDirty);
LOAD_PROC(VBVMR_AudioCallbackRegister);
LOAD_PROC(VBVMR_AudioCallbackStart);
LOAD_PROC(VBVMR_AudioCallbackStop);
LOAD_PROC(VBVMR_AudioCallbackUnregister);
initSoftware();
} }
VoicemeeterClient::~VoicemeeterClient() VoicemeeterClient::~VoicemeeterClient()
{ {
if (loggedIn) if (wTimer != 0)
{ {
vmr.VBVMR_Logout(); KillTimer(NULL, wTimer);
loggedIn = false; wTimer = 0;
} }
endSoftware();
} }
void VoicemeeterClient::start() void VoicemeeterClient::run()
{ {
if (!loggedIn) wTimer = SetTimer(NULL, 0, 500, NULL);
loggedIn = (vmr.VBVMR_Login() == 0); PostThreadMessage(mainThreadId, WM_COMMAND, IDM_RESTART, 0);
if (loggedIn) MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{ {
long type; switch (msg.message)
if (vmr.VBVMR_GetVoicemeeterType(&type) == 0)
voicemeeterType = type;
}
unsigned outputCount;
if (voicemeeterType == 3)
outputCount = 5;
else if (voicemeeterType == 2)
outputCount = 3;
else
outputCount = 1;
for (unsigned i = 0; i < outputCount; i++)
{
wstringstream sstream;
sstream << "Output A" << (i + 1);
wstring output = sstream.str();
if (find(outputs.begin(), outputs.end(), output) != outputs.end())
{ {
FilterEngine* engine = new FilterEngine(); case WM_COMMAND:
engine->setDeviceInfo(false, true, L"Voicemeeter", output, L"", L"Voicemeeter " + output); handleCommand(msg.wParam, msg.lParam);
engines.push_back(engine); break;
case WM_TIMER:
if (msg.wParam == wTimer)
{
// check if Voicemeeter type has changed
if (vmr.VBVMR_IsParametersDirty() >= 0)
{
if (!connected)
detectVoicemeeterType();
}
else
{
// Voicemeeter has been shut down
connected = false;
}
}
break;
} }
else
{
engines.push_back(NULL);
}
idleSampleCounts.push_back(0);
} }
if (vmr.VBVMR_AudioCallbackRegister(VBVMR_AUDIOCALLBACK_OUT, callback, this, "Equalizer APO") != 0)
{
PostThreadMessage(mainThreadId, WM_QUIT, 0, 0);
return;
}
vmr.VBVMR_AudioCallbackStart();
}
void VoicemeeterClient::stop()
{
vmr.VBVMR_AudioCallbackStop();
vmr.VBVMR_AudioCallbackUnregister();
idleSampleCounts.clear();
for (FilterEngine* engine : engines)
if (engine != NULL)
delete engine;
engines.clear();
} }
void VoicemeeterClient::handle(long nCommand, void* lpData, long nnn) void VoicemeeterClient::handle(long nCommand, void* lpData, long nnn)
@@ -198,26 +155,18 @@ void VoicemeeterClient::handle(long nCommand, void* lpData, long nnn)
case VBVMR_CBCOMMAND_STARTING: case VBVMR_CBCOMMAND_STARTING:
{ {
VBVMR_LPT_AUDIOINFO audioInfo = (VBVMR_LPT_AUDIOINFO)lpData; VBVMR_LPT_AUDIOINFO audioInfo = (VBVMR_LPT_AUDIOINFO)lpData;
sampleRate = (float)audioInfo->samplerate;
maxFrameCount = audioInfo->nbSamplePerFrame;
for (FilterEngine* engine : engines) for (FilterEngine* engine : engines)
if (engine != NULL) if (engine != NULL)
engine->initialize((float)audioInfo->samplerate, 8, 8, 8, 0, audioInfo->nbSamplePerFrame); engine->initialize(sampleRate, 8, 8, 8, 0, maxFrameCount);
VoicemeeterAPOInfo::saveVoicemeeterSampleRate((unsigned)audioInfo->samplerate); VoicemeeterAPOInfo::saveVoicemeeterSampleRate((unsigned)audioInfo->samplerate);
} }
break; break;
case VBVMR_CBCOMMAND_ENDING: case VBVMR_CBCOMMAND_ENDING:
{
restart = true;
PostThreadMessage(mainThreadId, WM_QUIT, 0, 0);
}
break; break;
case VBVMR_CBCOMMAND_CHANGE: case VBVMR_CBCOMMAND_CHANGE:
{ PostThreadMessage(mainThreadId, WM_COMMAND, IDM_RESTART, 0);
VBVMR_LPT_AUDIOINFO audioInfo = (VBVMR_LPT_AUDIOINFO)lpData;
for (FilterEngine* engine : engines)
if (engine != NULL)
engine->initialize((float)audioInfo->samplerate, 8, 8, 8, 0, audioInfo->nbSamplePerFrame);
VoicemeeterAPOInfo::saveVoicemeeterSampleRate((unsigned)audioInfo->samplerate);
}
break; break;
case VBVMR_CBCOMMAND_BUFFER_OUT: case VBVMR_CBCOMMAND_BUFFER_OUT:
{ {
@@ -262,6 +211,113 @@ void VoicemeeterClient::handle(long nCommand, void* lpData, long nnn)
} }
} }
void VoicemeeterClient::initSoftware()
{
long rep = vmr.VBVMR_Login();
if (rep < 0)
throw InitError(L"Failed To Login");
if (vmr.VBVMR_IsParametersDirty() == 0)
detectVoicemeeterType();
else
connected = false;
unsigned tries = 30;
bool loop = true;
while (loop)
{
loop = false;
char clientName[64] = "Equalizer APO";
rep = vmr.VBVMR_AudioCallbackRegister(VBVMR_AUDIOCALLBACK_OUT, callback, this, clientName);
if (rep == 1)
{
wchar_t message[512];
wsprintf(message, L"Voicemeeter Output Insert already in use by:\n%S", clientName);
throw InitError(message);
}
else if (rep != 0)
{
if (tries > 1)
{
// sometimes fails temporarily after restarting VoicemeeterClient
Sleep(100);
tries--;
loop = true;
}
else
{
throw InitError(L"Failed to register audio callback");
}
}
}
}
void VoicemeeterClient::detectVoicemeeterType()
{
long vmType;
long rep = vmr.VBVMR_GetVoicemeeterType(&vmType);
if (rep == 0)
{
connected = true;
unsigned outputCount;
if (vmType == 3)
outputCount = 5;
else if (vmType == 2)
outputCount = 3;
else
outputCount = 1;
if (outputCount != engines.size())
{
idleSampleCounts.clear();
for (FilterEngine* engine : engines)
if (engine != NULL)
delete engine;
engines.clear();
for (unsigned i = 0; i < outputCount; i++)
{
wstringstream sstream;
sstream << "Output A" << (i + 1);
wstring output = sstream.str();
if (find(outputs.begin(), outputs.end(), output) != outputs.end())
{
FilterEngine* engine = new FilterEngine();
engine->setDeviceInfo(false, true, L"Voicemeeter", output, L"", L"Voicemeeter " + output);
if (sampleRate != 0.0f && maxFrameCount != 0)
engine->initialize(sampleRate, 8, 8, 8, 0, maxFrameCount);
engines.push_back(engine);
}
else
{
engines.push_back(NULL);
}
idleSampleCounts.push_back(0);
}
}
}
}
void VoicemeeterClient::endSoftware()
{
if (vmr.VBVMR_Logout != NULL)
vmr.VBVMR_Logout();
if (vmr.VBVMR_AudioCallbackUnregister != NULL)
vmr.VBVMR_AudioCallbackUnregister();
}
void VoicemeeterClient::handleCommand(WPARAM wparam, LPARAM lparam)
{
switch (LOWORD(wparam))
{
case IDM_RESTART:
Sleep(50);
if (vmr.VBVMR_AudioCallbackStart != NULL)
vmr.VBVMR_AudioCallbackStart();
break;
}
}
bool VoicemeeterClient::isBufferSilent(float** sampleData, long sampleCount) bool VoicemeeterClient::isBufferSilent(float** sampleData, long sampleCount)
{ {
bool silent = true; bool silent = true;
@@ -282,7 +338,7 @@ bool VoicemeeterClient::isBufferSilent(float** sampleData, long sampleCount)
return silent; return silent;
} }
long __stdcall callback(void* lpUser, long nCommand, void* lpData, long nnn) static long __stdcall callback(void* lpUser, long nCommand, void* lpData, long nnn)
{ {
VoicemeeterClient* client = (VoicemeeterClient*)lpUser; VoicemeeterClient* client = (VoicemeeterClient*)lpUser;
client->handle(nCommand, lpData, nnn); client->handle(nCommand, lpData, nnn);
+29 -8
View File
@@ -1,6 +1,6 @@
/* /*
This file is part of Equalizer APO, a system-wide equalizer. This file is part of Equalizer APO, a system-wide equalizer.
Copyright (C) 2017 Jonas Thedering Copyright (C) 2022 Jonas Thedering
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -29,20 +29,41 @@ class VoicemeeterClient
public: public:
VoicemeeterClient(const std::vector<std::wstring>& outputs); VoicemeeterClient(const std::vector<std::wstring>& outputs);
~VoicemeeterClient(); ~VoicemeeterClient();
void start(); void run();
void stop();
void handle(long nCommand, void* lpData, long nnn); void handle(long nCommand, void* lpData, long nnn);
bool restart = false;
private: private:
void initSoftware();
void detectVoicemeeterType();
void endSoftware();
void handleCommand(WPARAM wparam, LPARAM lparam);
bool isBufferSilent(float** sampleData, long sampleCount); bool isBufferSilent(float** sampleData, long sampleCount);
std::vector<std::wstring> outputs;
unsigned long mainThreadId; unsigned long mainThreadId;
T_VBVMR_INTERFACE vmr; T_VBVMR_INTERFACE vmr;
size_t wTimer = 0;
bool connected = true;
float sampleRate = 0.0f;
unsigned maxFrameCount = 0;
std::vector<FilterEngine*> engines; std::vector<FilterEngine*> engines;
std::vector<int> idleSampleCounts; std::vector<int> idleSampleCounts;
bool loggedIn = false; };
long voicemeeterType = 1;
std::vector<std::wstring> outputs; class InitError
{
public:
InitError(const std::wstring& message)
: message(message)
{
}
std::wstring getMessage()
{
return message;
}
private:
std::wstring message;
}; };
Binary file not shown.
+123 -11
View File
@@ -1,22 +1,20 @@
/******************************************************************************/ /******************************************************************************/
/* Voicemeeter Remote API. V.Burel©2015 */ /* Voicemeeter Remote API. V.Burel©2015-2021 */
/******************************************************************************/ /******************************************************************************/
/* This Library allows communication with Voicemeeter Applications */ /* This Library allows communication with Voicemeeter applications */
/* 4 Client Applications can be connected to remote Voicemeeter. */ /* 4 Client Applications can be connected to remote Voicemeeter. */
/* it also allows communication with MacroButtons application. */
/******************************************************************************/ /******************************************************************************/
/* */ /* */
/* OFFICIAL LINK : WWW.VOICEMEETER.COM */ /* OFFICIAL LINK : WWW.VOICEMEETER.COM */
/* */ /* */
/******************************************************************************/ /******************************************************************************/
/* COPYRIGHT: Vincent Burel(c)2015 All Rights Reserved */ /* COPYRIGHT: Vincent Burel(c)2015-2021 All Rights Reserved */
/******************************************************************************/ /******************************************************************************/
/* LICENSING: This header file and VoicemeeterRemote.dll are made available */
/* for evaluation and testing purpose only (to make demo and proof */
/* of concept). */
/* */ /* */
/* for any commercial exploitation or to get specific support, */ /* LICENSING: VoicemeeterRemote.dll usage is driven by a license agreement */
/* a commercial license needs to be purchased. thanks to contact */ /* given in VoicemeeterRemoteAPI.pdf or readme.txt */
/* us by e-mail (get our contact on www.vb-audio.com). */ /* */
/******************************************************************************/ /******************************************************************************/
/* long = 32 bit integer */ /* long = 32 bit integer */
/******************************************************************************/ /******************************************************************************/
@@ -61,9 +59,10 @@ long __stdcall VBVMR_Logout(void);
/** /**
@brief Run Voicemeeter Application (get installation directory and run Voicemeeter Application). @brief Run Voicemeeter Application (get installation directory and run Voicemeeter Application).
@param vType : Voicemeeter type (1 = Voicemeeter, 2= Voicemeeter Banana). @param vType : Voicemeeter type (1 = Voicemeeter, 2= Voicemeeter Banana, 3= Voicemeeter Potato, 6 = Potato x64 bits).
@return : 0: Ok. @return : 0: Ok.
-1: not installed -1: not installed (UninstallString not found in registry).
-2: unknown vType number
*/ */
long __stdcall VBVMR_RunVoicemeeter(long vType); long __stdcall VBVMR_RunVoicemeeter(long vType);
@@ -106,6 +105,11 @@ long __stdcall VBVMR_RunVoicemeeter(long vType);
+---------+---------+---------+-------------+-----------+------+------+------+------+------+ +---------+---------+---------+-------------+-----------+------+------+------+------+------+
| 0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 | 4 | | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 | 4 |
VOICEMEETER POTATO STRIP/BUS INDEX ASSIGNMENT
| Strip 1 | Strip 2 | Strip 2 | Strip 2 | Strip 2 |Virtual Input|Virtual AUX| VAIO3 |BUS A1|BUS A2|BUS A3|BUS A4|BUS A5|BUS B1|BUS B2|BUS B3|
+---------+---------+---------+---------+---------+-------------+-----------+-----------+------+------+------+------+------+------+------+------+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
@return : 0: OK (no error). @return : 0: OK (no error).
@@ -255,6 +259,20 @@ long __stdcall VBVMR_GetParameterStringW(char * szParamName, unsigned short * ws
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
VOICEMEETER POTATO CHANNEL ASSIGNMENT
| Strip 1 | Strip 2 | Strip 3 | Strip 4 | Strip 5 | Virtual Input | Virtual Input AUX | VAIO3 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
| Output A1 | Output A2 | Output A3 | Output A4 | Output A5 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
| Virtual Output B1 | Virtual Output B2 | Virtual Output B3 |
+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
| 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
@return : 0: OK (no error). @return : 0: OK (no error).
-1: error -1: error
@@ -681,6 +699,66 @@ long __stdcall VBVMR_AudioCallbackUnregister(void);
/******************************************************************************/
/* */
/* Macro Buttons */
/* */
/******************************************************************************/
/** @name Macro Buttons functions
* @{ */
/**
@brief Check if Macro Buttons states changed.
Call this function periodically (typically every 50 or 500ms) to know if something happen on MacroButton states .
(this function must be called from one thread only)
@return: 0: no new status.
>0: last nu logical button status changed.
-1: error (unexpected)
-2: no server.
*/
long __stdcall VBVMR_MacroButton_IsDirty(void);
/**
@brief get current status of a given button.
@param nuLogicalButton : button index: 0 to 79)
@param pValue : Pointer on float (32bit float by reference) receiving the wanted value (0.0 = OFF / 1.0 = ON).
@param bitmode: define what kind of value you want to read (see MACROBUTTON_MODE below)
@return : 0: OK (no error).
-1: error
-2: no server.
-3: unknown parameter
-5: structure mismatch
*/
long __stdcall VBVMR_MacroButton_GetStatus(long nuLogicalButton, float * pValue, long bitmode);
/**
@brief set current button value.
@param nuLogicalButton : button index: 0 to 79)
@param fValue : float 32 bit value giving the status (0.0 = OFF / 1.0 = ON).
@param bitmode: define what kind of value you want to write/modify (see MACROBUTTON_MODE below)
@return : 0: OK (no error).
-1: error
-2: no server.
-3: unknown parameter
-5: structure mismatch
*/
long __stdcall VBVMR_MacroButton_SetStatus(long nuLogicalButton, float fValue, long bitmode);
#define VBVMR_MACROBUTTON_MODE_DEFAULT 0x00000000 //PUSH or RELEASE button
#define VBVMR_MACROBUTTON_MODE_STATEONLY 0x00000002 //change Displayed State only
#define VBVMR_MACROBUTTON_MODE_TRIGGER 0x00000003 //change Trigger State
/** @} */
@@ -725,6 +803,11 @@ typedef long (__stdcall *T_VBVMR_AudioCallbackStart)(void);
typedef long (__stdcall *T_VBVMR_AudioCallbackStop)(void); typedef long (__stdcall *T_VBVMR_AudioCallbackStop)(void);
typedef long (__stdcall *T_VBVMR_AudioCallbackUnregister)(void); typedef long (__stdcall *T_VBVMR_AudioCallbackUnregister)(void);
typedef long (__stdcall *T_VBVMR_MacroButton_IsDirty)(void);
typedef long (__stdcall *T_VBVMR_MacroButton_GetStatus)(long nuLogicalButton, float * pValue, long bitmode);
typedef long (__stdcall *T_VBVMR_MacroButton_SetStatus)(long nuLogicalButton, float fValue, long bitmode);
typedef struct tagVBVMR_INTERFACE typedef struct tagVBVMR_INTERFACE
{ {
@@ -759,6 +842,10 @@ typedef struct tagVBVMR_INTERFACE
T_VBVMR_AudioCallbackStop VBVMR_AudioCallbackStop; T_VBVMR_AudioCallbackStop VBVMR_AudioCallbackStop;
T_VBVMR_AudioCallbackUnregister VBVMR_AudioCallbackUnregister; T_VBVMR_AudioCallbackUnregister VBVMR_AudioCallbackUnregister;
T_VBVMR_MacroButton_IsDirty VBVMR_MacroButton_IsDirty;
T_VBVMR_MacroButton_GetStatus VBVMR_MacroButton_GetStatus;
T_VBVMR_MacroButton_SetStatus VBVMR_MacroButton_SetStatus;
} T_VBVMR_INTERFACE, *PT_VBVMR_INTERFACE, *LPT_VBVMR_INTERFACE; } T_VBVMR_INTERFACE, *PT_VBVMR_INTERFACE, *LPT_VBVMR_INTERFACE;
#ifdef VBUSE_LOCALLIB #ifdef VBUSE_LOCALLIB
@@ -766,6 +853,31 @@ typedef struct tagVBVMR_INTERFACE
void __stdcall VBVMR_SetHinstance(HINSTANCE hinst); void __stdcall VBVMR_SetHinstance(HINSTANCE hinst);
#endif #endif
/******************************************************************************/
/* LOCAL FUNCTIONS */
/******************************************************************************/
long VBVMR_LocalInit(void);
long VBVMR_LocalEnd(void);
void * VBVMR_GetRequestVB0STREAMPTR(void);
long VBVMR_SetParametersWEx(unsigned short * szParamScript, long fCopyToClient);
long VBVMR_LoginEx(long properties);
long VBVMR_MB_PushSettings(void * lpParam);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
+1 -1
View File
@@ -25,7 +25,7 @@
class PrecisionTimer class PrecisionTimer
{ {
LARGE_INTEGER freq; LARGE_INTEGER freq;
LARGE_INTEGER startCount; LARGE_INTEGER startCount{};
public: public:
PrecisionTimer() PrecisionTimer()