From ee75dcc7e6b23f811b5cc6eb366b1b26657d782b Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 7 Mar 2020 22:29:21 +0100 Subject: [PATCH] Add specific logging functions for all the events --- src/common/logging.cpp | 334 +++++++++++++++++++++++++++++++++++++ src/common/logging.h | 20 ++- src/plugin/host-bridge.cpp | 17 +- src/plugin/host-bridge.h | 2 +- 4 files changed, 361 insertions(+), 12 deletions(-) diff --git a/src/common/logging.cpp b/src/common/logging.cpp index 4514bdf8..ec93a769 100644 --- a/src/common/logging.cpp +++ b/src/common/logging.cpp @@ -11,6 +11,8 @@ #endif #include +#include "vestige/aeffect.h" + /** * The environment variable indicating whether to log to a file. Will log to * STDERR if not specified. @@ -25,6 +27,8 @@ constexpr char logging_file_environment_variable[] = "YABRIDGE_DEBUG_FILE"; constexpr char logging_verbosity_environment_variable[] = "YABRIDGE_DEBUG_VERBOSITY"; +std::optional opcode_to_string(int opcode, bool dispatch); + Logger::Logger(std::shared_ptr stream, Verbosity verbosity_level, std::string prefix) @@ -79,3 +83,333 @@ void Logger::log(const std::string& message) { *stream << formatted_message.str() << std::flush; } + +void Logger::log_get_parameter(int32_t index) { + if (verbosity >= Verbosity::events) { + std::ostringstream message; + message << "> getParameter() " << index; + + log(message.str()); + } +} + +void Logger::log_get_parameter_response(int32_t index, float value) { + if (verbosity >= Verbosity::events) { + std::ostringstream message; + message << "< getParameter() " << index << " == " << value; + + log(message.str()); + } +} + +void Logger::log_set_parameter(int32_t index, float value) { + if (verbosity >= Verbosity::events) { + std::ostringstream message; + message << "> setParameter() " << index << " = " << value; + + log(message.str()); + } +} + +void Logger::log_set_parameter_response(int32_t index) { + if (verbosity >= Verbosity::events) { + std::ostringstream message; + message << "< setParameter() " << index << " OK"; + + log(message.str()); + } +} + +void Logger::log_event(bool dispatch, + int32_t opcode, + int32_t index, + intptr_t value, + std::optional data, + float option) { + if (verbosity >= Verbosity::events) { + std::ostringstream message; + if (dispatch) { + message << "> dispatch() "; + } else { + message << "> audioMasterCallback() "; + } + + message + << opcode_to_string(opcode, dispatch).value_or(""); + message << "(index = " << index << ", value = " << value + << ", option = " << option << ", data = "; + + if (!data.has_value()) { + message << ""; + } else if (data->empty()) { + message << ""; + } else { + // Might print binary data, maybe check for this? + message << data.value(); + } + + message << ")"; + + log(message.str()); + } +} + +void Logger::log_event_response(bool dispatch, + intptr_t return_value, + std::optional data) { + if (verbosity >= Verbosity::events) { + std::ostringstream message; + if (dispatch) { + message << "< dispatch() "; + } else { + message << "< audioMasterCallback() "; + } + + message << " " << return_value; + if (data.has_value()) { + message << ", " << data.value(); + } + } +} + +/** + * Convert an event opcode to a human readable string for debugging purposes. + * See `src/include/vestige/aeffect.h` for a complete list of these opcodes. + * + * @param opcode The opcode of the event. + * @param dispatch Whether to use opcodes for the `dispatch` function. Will use + * the names from the host callback function if set to false. + * + * @return Either the name from `aeffect.h`, or a nullopt if it was not listed + * there. + */ +std::optional opcode_to_string(int opcode, bool dispatch) { + if (dispatch) { + // Opcodes for a plugin's dispatch function + switch (opcode) { + case effOpen: + return "effOpen"; + break; + case effClose: + return "effClose"; + break; + case effSetProgram: + return "effSetProgram"; + break; + case effGetProgram: + return "effGetProgram"; + break; + case effGetProgramName: + return "effGetProgramName"; + break; + case effGetParamName: + return "effGetParamName"; + break; + case effSetSampleRate: + return "effSetSampleRate"; + break; + case effSetBlockSize: + return "effSetBlockSize"; + break; + case effMainsChanged: + return "effMainsChanged"; + break; + case effEditGetRect: + return "effEditGetRect"; + break; + case effEditOpen: + return "effEditOpen"; + break; + case effEditClose: + return "effEditClose"; + break; + case effEditIdle: + return "effEditIdle"; + break; + case effEditTop: + return "effEditTop"; + break; + case effSetChunk: + return "effSetChunk"; + break; + case effProcessEvents: + return "effProcessEvents"; + break; + case effGetEffectName: + return "effGetEffectName"; + break; + case effGetVendorString: + return "effGetVendorString"; + break; + case effGetProductString: + return "effGetProductString"; + break; + case effGetVendorVersion: + return "effGetVendorVersion"; + break; + case effCanDo: + return "effCanDo"; + break; + case effGetVstVersion: + return "effGetVstVersion"; + break; + default: + return std::nullopt; + break; + } + } else { + // Opcodes for the host callback + switch (opcode) { + case audioMasterAutomate: + return "audioMasterAutomate"; + break; + case audioMasterVersion: + return "audioMasterVersion"; + break; + case audioMasterCurrentId: + return "audioMasterCurrentId"; + break; + case audioMasterIdle: + return "audioMasterIdle"; + break; + case audioMasterPinConnected: + return "audioMasterPinConnected"; + break; + case audioMasterWantMidi: + return "audioMasterWantMidi"; + break; + case audioMasterGetTime: + return "audioMasterGetTime"; + break; + case audioMasterProcessEvents: + return "audioMasterProcessEvents"; + break; + case audioMasterSetTime: + return "audioMasterSetTime"; + break; + case audioMasterTempoAt: + return "audioMasterTempoAt"; + break; + case audioMasterGetNumAutomatableParameters: + return "audioMasterGetNumAutomatableParameters"; + break; + case audioMasterGetParameterQuantization: + return "audioMasterGetParameterQuantization"; + break; + case audioMasterIOChanged: + return "audioMasterIOChanged"; + break; + case audioMasterNeedIdle: + return "audioMasterNeedIdle"; + break; + case audioMasterSizeWindow: + return "audioMasterSizeWindow"; + break; + case audioMasterGetSampleRate: + return "audioMasterGetSampleRate"; + break; + case audioMasterGetBlockSize: + return "audioMasterGetBlockSize"; + break; + case audioMasterGetInputLatency: + return "audioMasterGetInputLatency"; + break; + case audioMasterGetOutputLatency: + return "audioMasterGetOutputLatency"; + break; + case audioMasterGetPreviousPlug: + return "audioMasterGetPreviousPlug"; + break; + case audioMasterGetNextPlug: + return "audioMasterGetNextPlug"; + break; + case audioMasterWillReplaceOrAccumulate: + return "audioMasterWillReplaceOrAccumulate"; + break; + case audioMasterGetCurrentProcessLevel: + return "audioMasterGetCurrentProcessLevel"; + break; + case audioMasterGetAutomationState: + return "audioMasterGetAutomationState"; + break; + case audioMasterOfflineStart: + return "audioMasterOfflineStart"; + break; + case audioMasterOfflineRead: + return "audioMasterOfflineRead"; + break; + case audioMasterOfflineWrite: + return "audioMasterOfflineWrite"; + break; + case audioMasterOfflineGetCurrentPass: + return "audioMasterOfflineGetCurrentPass"; + break; + case audioMasterOfflineGetCurrentMetaPass: + return "audioMasterOfflineGetCurrentMetaPass"; + break; + case audioMasterSetOutputSampleRate: + return "audioMasterSetOutputSampleRate"; + break; + case audioMasterGetSpeakerArrangement: + return "audioMasterGetSpeakerArrangement"; + break; + case audioMasterGetVendorString: + return "audioMasterGetVendorString"; + break; + case audioMasterGetProductString: + return "audioMasterGetProductString"; + break; + case audioMasterGetVendorVersion: + return "audioMasterGetVendorVersion"; + break; + case audioMasterVendorSpecific: + return "audioMasterVendorSpecific"; + break; + case audioMasterSetIcon: + return "audioMasterSetIcon"; + break; + case audioMasterCanDo: + return "audioMasterCanDo"; + break; + case audioMasterGetLanguage: + return "audioMasterGetLanguage"; + break; + case audioMasterOpenWindow: + return "audioMasterOpenWindow"; + break; + case audioMasterCloseWindow: + return "audioMasterCloseWindow"; + break; + case audioMasterGetDirectory: + return "audioMasterGetDirectory"; + break; + case audioMasterUpdateDisplay: + return "audioMasterUpdateDisplay"; + break; + case audioMasterBeginEdit: + return "audioMasterBeginEdit"; + break; + case audioMasterEndEdit: + return "audioMasterEndEdit"; + break; + case audioMasterOpenFileSelector: + return "audioMasterOpenFileSelector"; + break; + case audioMasterCloseFileSelector: + return "audioMasterCloseFileSelector"; + break; + case audioMasterEditFile: + return "audioMasterEditFile"; + break; + case audioMasterGetChunkFile: + return "audioMasterGetChunkFile"; + break; + case audioMasterGetInputSpeakerArrangement: + return "audioMasterGetInputSpeakerArrangement"; + break; + default: + return std::nullopt; + break; + } + } +} diff --git a/src/common/logging.h b/src/common/logging.h index ac1e6d7e..e5f37eb1 100644 --- a/src/common/logging.h +++ b/src/common/logging.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include /** @@ -85,8 +86,23 @@ class Logger { */ void log(const std::string& message); - // TODO: Add dedicated logging functions for events and the Wine process's - // STDOUT and STDERR + // The following functions are for logging specific events, they are only + // enabled for verbosity levels higher than 1 (i.e. `Verbosity::events`) + void log_get_parameter(int32_t index); + void log_get_parameter_response(int32_t index, float vlaue); + void log_set_parameter(int32_t index, float value); + void log_set_parameter_response(int32_t index); + // If dispatch is true, then use opcode names from the plugin's dispatch + // function. Otherwise use names for the host callback function opcodes. + void log_event(bool dispatch, + int32_t opcode, + int32_t index, + intptr_t value, + std::optional data, + float option); + void log_event_response(bool dispatch, + intptr_t return_value, + std::optional data); private: /** diff --git a/src/plugin/host-bridge.cpp b/src/plugin/host-bridge.cpp index 7af5948b..3713441b 100644 --- a/src/plugin/host-bridge.cpp +++ b/src/plugin/host-bridge.cpp @@ -123,7 +123,6 @@ HostBridge::HostBridge(audioMasterCallback host_callback) host_callback_function); } }); - wine_io_handler = std::thread([&]() { io_context.run(); }); // Print the Wine host's STDOUT and STDERR streams to the log file @@ -199,6 +198,14 @@ void HostBridge::process_replacing(AEffect* /*plugin*/, } } +float HostBridge::get_parameter(AEffect* /*plugin*/, int32_t index) { + const Parameter request{index, std::nullopt}; + write_object(host_vst_parameters, request); + + const auto response = read_object(host_vst_parameters); + return response.value.value(); +} + void HostBridge::set_parameter(AEffect* /*plugin*/, int32_t index, float value) { @@ -210,14 +217,6 @@ void HostBridge::set_parameter(AEffect* /*plugin*/, assert(!response.value.has_value()); } -float HostBridge::get_parameter(AEffect* /*plugin*/, int32_t index) { - const Parameter request{index, std::nullopt}; - write_object(host_vst_parameters, request); - - const auto response = read_object(host_vst_parameters); - return response.value.value(); -} - void HostBridge::async_log_pipe_lines(bp::async_pipe& pipe, boost::asio::streambuf& buffer, std::string prefix) { diff --git a/src/plugin/host-bridge.h b/src/plugin/host-bridge.h index 6ade645d..387975bc 100644 --- a/src/plugin/host-bridge.h +++ b/src/plugin/host-bridge.h @@ -68,8 +68,8 @@ class HostBridge { float** inputs, float** outputs, int sample_frames); - void set_parameter(AEffect* plugin, int32_t index, float value); float get_parameter(AEffect* plugin, int32_t index); + void set_parameter(AEffect* plugin, int32_t index, float value); /** * The path to `yabridge-host.exe`.