diff --git a/src/common/logging/vst3.cpp b/src/common/logging/vst3.cpp index 76b6e327..00ad16e2 100644 --- a/src/common/logging/vst3.cpp +++ b/src/common/logging/vst3.cpp @@ -471,6 +471,17 @@ bool Vst3Logger::log_request(bool is_host_vst, }); } +bool Vst3Logger::log_request(bool is_host_vst, + const YaUnitInfo::GetProgramInfo& request) { + return log_request_base(is_host_vst, [&](auto& message) { + message << request.instance_id + << ": IUnitInfo::getProgramInfo(listId = " << request.list_id + << ", programIndex = " << request.program_index + << ", attributeId = " << request.attribute_id + << ", &attributeValue)"; + }); +} + bool Vst3Logger::log_request( bool is_host_vst, const YaAudioProcessor::SetBusArrangements& request) { @@ -904,6 +915,19 @@ void Vst3Logger::log_response( }); } +void Vst3Logger::log_response( + bool is_host_vst, + const YaUnitInfo::GetProgramInfoResponse& response) { + log_response_base(is_host_vst, [&](auto& message) { + message << response.result.string(); + if (response.result == Steinberg::kResultOk) { + message << ", \"" + << VST3::StringConvert::convert(response.attribute_value) + << "\""; + } + }); +} + void Vst3Logger::log_response( bool is_host_vst, const YaAudioProcessor::GetBusArrangementResponse& response) { diff --git a/src/common/logging/vst3.h b/src/common/logging/vst3.h index cf60d46c..c80c3f8a 100644 --- a/src/common/logging/vst3.h +++ b/src/common/logging/vst3.h @@ -113,6 +113,7 @@ class Vst3Logger { bool log_request(bool is_host_vst, const YaUnitInfo::GetProgramListCount&); bool log_request(bool is_host_vst, const YaUnitInfo::GetProgramListInfo&); bool log_request(bool is_host_vst, const YaUnitInfo::GetProgramName&); + bool log_request(bool is_host_vst, const YaUnitInfo::GetProgramInfo&); bool log_request(bool is_host_vst, const YaAudioProcessor::SetBusArrangements&); @@ -171,6 +172,8 @@ class Vst3Logger { const YaUnitInfo::GetProgramListInfoResponse&); void log_response(bool is_host_vst, const YaUnitInfo::GetProgramNameResponse&); + void log_response(bool is_host_vst, + const YaUnitInfo::GetProgramInfoResponse&); void log_response(bool is_host_vst, const YaAudioProcessor::GetBusArrangementResponse&); diff --git a/src/common/serialization/vst3.h b/src/common/serialization/vst3.h index 233e4534..f27b5299 100644 --- a/src/common/serialization/vst3.h +++ b/src/common/serialization/vst3.h @@ -104,7 +104,8 @@ using ControlRequest = std::variant; + YaUnitInfo::GetProgramName, + YaUnitInfo::GetProgramInfo>; template void serialize(S& s, ControlRequest& payload) { diff --git a/src/common/serialization/vst3/plugin/unit-info.h b/src/common/serialization/vst3/plugin/unit-info.h index 6ff6f454..57265d22 100644 --- a/src/common/serialization/vst3/plugin/unit-info.h +++ b/src/common/serialization/vst3/plugin/unit-info.h @@ -210,6 +210,45 @@ class YaUnitInfo : public Steinberg::Vst::IUnitInfo { getProgramName(Steinberg::Vst::ProgramListID listId, int32 programIndex, Steinberg::Vst::String128 name /*out*/) override = 0; + + /** + * The response code and returned name for a call to + * `IUnitInfo::getPrograminfo(list_id, program_index, attribute_name, + * &attribute_value)`. + */ + struct GetProgramInfoResponse { + UniversalTResult result; + std::u16string attribute_value; + + template + void serialize(S& s) { + s.object(result); + s.text2b(attribute_value, std::extent_v); + } + }; + + /** + * Message to pass through a call to `IUnitInfo::getProgramInfo(list_id, + * program_index, attribute_id, &attribute_value)` to the Wine plugin host. + */ + struct GetProgramInfo { + using Response = GetProgramInfoResponse; + + native_size_t instance_id; + + Steinberg::Vst::ProgramListID list_id; + int32 program_index; + std::string attribute_id; + + template + void serialize(S& s) { + s.value8b(instance_id); + s.value4b(list_id); + s.value4b(program_index); + s.text1b(attribute_id, 256); + } + }; + virtual tresult PLUGIN_API getProgramInfo( Steinberg::Vst::ProgramListID listId, int32 programIndex, diff --git a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp index 01ce3d98..7319faf2 100644 --- a/src/plugin/bridges/vst3-impls/plugin-proxy.cpp +++ b/src/plugin/bridges/vst3-impls/plugin-proxy.cpp @@ -494,9 +494,19 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getProgramInfo( int32 programIndex, Steinberg::Vst::CString attributeId /*in*/, Steinberg::Vst::String128 attributeValue /*out*/) { - // TODO: Implement - bridge.logger.log("TODO: IUnitInfo::getProgramInfo()"); - return Steinberg::kNotImplemented; + assert(attributeId); + + const GetProgramInfoResponse response = bridge.send_message( + YaUnitInfo::GetProgramInfo{.instance_id = instance_id(), + .list_id = listId, + .program_index = programIndex, + .attribute_id = attributeId}); + + std::copy(response.attribute_value.begin(), response.attribute_value.end(), + attributeValue); + attributeValue[response.attribute_value.size()] = 0; + + return response.result; } tresult PLUGIN_API diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index cc561337..b84ce2e7 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -607,6 +607,20 @@ void Vst3Bridge::run() { return YaUnitInfo::GetProgramNameResponse{ .result = result, .name = tchar_pointer_to_u16string(name)}; }, + [&](const YaUnitInfo::GetProgramInfo& request) + -> YaUnitInfo::GetProgramInfo::Response { + Steinberg::Vst::String128 attribute_value{0}; + const tresult result = + object_instances[request.instance_id] + .unit_info->getProgramInfo( + request.list_id, request.program_index, + request.attribute_id.c_str(), attribute_value); + + return YaUnitInfo::GetProgramInfoResponse{ + .result = result, + .attribute_value = + tchar_pointer_to_u16string(attribute_value)}; + }, }); }