mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
Pass through host provided IBStream objects
So if the host supports IStreamAttributes, we can also provide objects that support the same itnerface to the plugin.
This commit is contained in:
@@ -113,9 +113,9 @@ bool Vst3Logger::log_request(bool is_host_vst,
|
|||||||
bool Vst3Logger::log_request(bool is_host_vst,
|
bool Vst3Logger::log_request(bool is_host_vst,
|
||||||
const Vst3PluginProxy::GetState& request) {
|
const Vst3PluginProxy::GetState& request) {
|
||||||
return log_request_base(is_host_vst, [&](auto& message) {
|
return log_request_base(is_host_vst, [&](auto& message) {
|
||||||
message
|
message << request.instance_id
|
||||||
<< request.instance_id
|
<< ": {IComponent,IEditController}::getState(state = "
|
||||||
<< ": {IComponent,IEditController}::getState(state = <IBStream*>)";
|
<< format_bstream(request.state) << ")";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,7 +618,8 @@ bool Vst3Logger::log_request(bool is_host_vst,
|
|||||||
return log_request_base(is_host_vst, [&](auto& message) {
|
return log_request_base(is_host_vst, [&](auto& message) {
|
||||||
message << "IProgramListData::getProgramData(listId = "
|
message << "IProgramListData::getProgramData(listId = "
|
||||||
<< request.list_id
|
<< request.list_id
|
||||||
<< ", programIndex = " << request.program_index << ", &data)";
|
<< ", programIndex = " << request.program_index
|
||||||
|
<< ", data = " << format_bstream(request.data) << ")";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,7 +644,7 @@ bool Vst3Logger::log_request(bool is_host_vst,
|
|||||||
const YaUnitData::GetUnitData& request) {
|
const YaUnitData::GetUnitData& request) {
|
||||||
return log_request_base(is_host_vst, [&](auto& message) {
|
return log_request_base(is_host_vst, [&](auto& message) {
|
||||||
message << "IUnitData::getUnitData(listId = " << request.unit_id
|
message << "IUnitData::getUnitData(listId = " << request.unit_id
|
||||||
<< ", &data)";
|
<< ", data = " << format_bstream(request.data) << ")";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,7 +775,8 @@ bool Vst3Logger::log_request(
|
|||||||
<< ": "
|
<< ": "
|
||||||
"IXmlRepresentationController::getXmlRepresentationStream("
|
"IXmlRepresentationController::getXmlRepresentationStream("
|
||||||
"info = <RepresentationInfo for \""
|
"info = <RepresentationInfo for \""
|
||||||
<< request.info.name << "\">, stream = <IBstream*>)";
|
<< request.info.name
|
||||||
|
<< "\">, stream = " << format_bstream(request.stream) << ")";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1213,7 +1215,7 @@ void Vst3Logger::log_response(
|
|||||||
log_response_base(is_host_vst, [&](auto& message) {
|
log_response_base(is_host_vst, [&](auto& message) {
|
||||||
message << response.result.string();
|
message << response.result.string();
|
||||||
if (response.result == Steinberg::kResultOk) {
|
if (response.result == Steinberg::kResultOk) {
|
||||||
message << ", " << format_bstream(response.updated_state);
|
message << ", " << format_bstream(response.state);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,25 +30,25 @@ YaBStream::YaBStream(Steinberg::IBStream* stream) {
|
|||||||
throw std::runtime_error("Null pointer passed to YaBStream()");
|
throw std::runtime_error("Null pointer passed to YaBStream()");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->seek(0, Steinberg::IBStream::IStreamSeekMode::kIBSeekEnd) !=
|
// Copy any existing contents, used for `IComponent::setState` and similar
|
||||||
|
// methods
|
||||||
|
if (stream->seek(0, Steinberg::IBStream::IStreamSeekMode::kIBSeekEnd) ==
|
||||||
Steinberg::kResultOk) {
|
Steinberg::kResultOk) {
|
||||||
throw std::runtime_error(
|
// Now that we're at the end of the stream we know how large the buffer
|
||||||
"IBStream passed to YaBStream() does not suport seeking to end");
|
// should be
|
||||||
|
int64 size;
|
||||||
|
assert(stream->tell(&size) == Steinberg::kResultOk);
|
||||||
|
|
||||||
|
int32 num_bytes_read = 0;
|
||||||
|
buffer.resize(size);
|
||||||
|
assert(
|
||||||
|
stream->seek(0, Steinberg::IBStream::IStreamSeekMode::kIBSeekSet) ==
|
||||||
|
Steinberg::kResultOk);
|
||||||
|
assert(stream->read(buffer.data(), size, &num_bytes_read) ==
|
||||||
|
Steinberg::kResultOk);
|
||||||
|
assert(num_bytes_read == 0 || num_bytes_read == size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we're at the end of the stream we know how large the buffer
|
|
||||||
// should be
|
|
||||||
int64 size;
|
|
||||||
assert(stream->tell(&size) == Steinberg::kResultOk);
|
|
||||||
|
|
||||||
int32 num_bytes_read = 0;
|
|
||||||
buffer.resize(size);
|
|
||||||
assert(stream->seek(0, Steinberg::IBStream::IStreamSeekMode::kIBSeekSet) ==
|
|
||||||
Steinberg::kResultOk);
|
|
||||||
assert(stream->read(buffer.data(), size, &num_bytes_read) ==
|
|
||||||
Steinberg::kResultOk);
|
|
||||||
assert(num_bytes_read == 0 || num_bytes_read == size);
|
|
||||||
|
|
||||||
// Starting at VST 3.6.0 streams provided by the host may contain context
|
// Starting at VST 3.6.0 streams provided by the host may contain context
|
||||||
// based meta data
|
// based meta data
|
||||||
if (Steinberg::FUnknownPtr<Steinberg::Vst::IStreamAttributes>
|
if (Steinberg::FUnknownPtr<Steinberg::Vst::IStreamAttributes>
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ class YaBStream : public Steinberg::IBStream,
|
|||||||
public Steinberg::ISizeableStream,
|
public Steinberg::ISizeableStream,
|
||||||
public Steinberg::Vst::IStreamAttributes {
|
public Steinberg::Vst::IStreamAttributes {
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* This constructor should only be used by bitsery for serialization. The
|
||||||
|
* other constructor will check whether the `IBstream*` provided by the host
|
||||||
|
* supports stream attributes and configures the object accordingly.
|
||||||
|
*/
|
||||||
YaBStream();
|
YaBStream();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -225,31 +225,34 @@ class Vst3PluginProxy : public YaAudioPresentationLatency,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The response code and written state for a call to
|
* The response code and written state for a call to
|
||||||
* `{IComponent,IEditController}::getState(state)`.
|
* `{IComponent,IEditController}::getState(&state)`.
|
||||||
*/
|
*/
|
||||||
struct GetStateResponse {
|
struct GetStateResponse {
|
||||||
UniversalTResult result;
|
UniversalTResult result;
|
||||||
YaBStream updated_state;
|
YaBStream state;
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void serialize(S& s) {
|
void serialize(S& s) {
|
||||||
s.object(result);
|
s.object(result);
|
||||||
s.object(updated_state);
|
s.object(state);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Message to pass through a call to
|
* Message to pass through a call to
|
||||||
* `{IComponent,IEditController}::getState(state)` to the Wine plugin host.
|
* `{IComponent,IEditController}::getState(&state)` to the Wine plugin host.
|
||||||
*/
|
*/
|
||||||
struct GetState {
|
struct GetState {
|
||||||
using Response = GetStateResponse;
|
using Response = GetStateResponse;
|
||||||
|
|
||||||
native_size_t instance_id;
|
native_size_t instance_id;
|
||||||
|
|
||||||
|
YaBStream state;
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void serialize(S& s) {
|
void serialize(S& s) {
|
||||||
s.value8b(instance_id);
|
s.value8b(instance_id);
|
||||||
|
s.object(state);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -111,12 +111,14 @@ class YaProgramListData : public Steinberg::Vst::IProgramListData {
|
|||||||
|
|
||||||
Steinberg::Vst::ProgramListID list_id;
|
Steinberg::Vst::ProgramListID list_id;
|
||||||
int32 program_index;
|
int32 program_index;
|
||||||
|
YaBStream data;
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void serialize(S& s) {
|
void serialize(S& s) {
|
||||||
s.value8b(instance_id);
|
s.value8b(instance_id);
|
||||||
s.value4b(list_id);
|
s.value4b(list_id);
|
||||||
s.value4b(program_index);
|
s.value4b(program_index);
|
||||||
|
s.object(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -108,11 +108,13 @@ class YaUnitData : public Steinberg::Vst::IUnitData {
|
|||||||
native_size_t instance_id;
|
native_size_t instance_id;
|
||||||
|
|
||||||
Steinberg::Vst::UnitID unit_id;
|
Steinberg::Vst::UnitID unit_id;
|
||||||
|
YaBStream data;
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void serialize(S& s) {
|
void serialize(S& s) {
|
||||||
s.value8b(instance_id);
|
s.value8b(instance_id);
|
||||||
s.value4b(unit_id);
|
s.value4b(unit_id);
|
||||||
|
s.object(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -96,11 +96,13 @@ class YaXmlRepresentationController
|
|||||||
native_size_t instance_id;
|
native_size_t instance_id;
|
||||||
|
|
||||||
Steinberg::Vst::RepresentationInfo info;
|
Steinberg::Vst::RepresentationInfo info;
|
||||||
|
YaBStream stream;
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void serialize(S& s) {
|
void serialize(S& s) {
|
||||||
s.value8b(instance_id);
|
s.value8b(instance_id);
|
||||||
s.object(info);
|
s.object(info);
|
||||||
|
s.object(stream);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -253,11 +253,11 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getState(Steinberg::IBStream* state) {
|
|||||||
if (state) {
|
if (state) {
|
||||||
// Since both interfaces contain this function, this is used for both
|
// Since both interfaces contain this function, this is used for both
|
||||||
// `IComponent::getState()` as well as `IEditController::getState()`
|
// `IComponent::getState()` as well as `IEditController::getState()`
|
||||||
const GetStateResponse response = bridge.send_message(
|
const GetStateResponse response =
|
||||||
Vst3PluginProxy::GetState{.instance_id = instance_id()});
|
bridge.send_message(Vst3PluginProxy::GetState{
|
||||||
|
.instance_id = instance_id(), .state = state});
|
||||||
|
|
||||||
assert(response.updated_state.write_back(state) ==
|
assert(response.state.write_back(state) == Steinberg::kResultOk);
|
||||||
Steinberg::kResultOk);
|
|
||||||
|
|
||||||
return response.result;
|
return response.result;
|
||||||
} else {
|
} else {
|
||||||
@@ -681,7 +681,8 @@ Vst3PluginProxyImpl::getProgramData(Steinberg::Vst::ProgramListID listId,
|
|||||||
const GetProgramDataResponse response = bridge.send_message(
|
const GetProgramDataResponse response = bridge.send_message(
|
||||||
YaProgramListData::GetProgramData{.instance_id = instance_id(),
|
YaProgramListData::GetProgramData{.instance_id = instance_id(),
|
||||||
.list_id = listId,
|
.list_id = listId,
|
||||||
.program_index = programIndex});
|
.program_index = programIndex,
|
||||||
|
.data = data});
|
||||||
|
|
||||||
assert(response.data.write_back(data) == Steinberg::kResultOk);
|
assert(response.data.write_back(data) == Steinberg::kResultOk);
|
||||||
|
|
||||||
@@ -724,7 +725,7 @@ Vst3PluginProxyImpl::getUnitData(Steinberg::Vst::UnitID unitId,
|
|||||||
if (data) {
|
if (data) {
|
||||||
const GetUnitDataResponse response =
|
const GetUnitDataResponse response =
|
||||||
bridge.send_message(YaUnitData::GetUnitData{
|
bridge.send_message(YaUnitData::GetUnitData{
|
||||||
.instance_id = instance_id(), .unit_id = unitId});
|
.instance_id = instance_id(), .unit_id = unitId, .data = data});
|
||||||
|
|
||||||
assert(response.data.write_back(data) == Steinberg::kResultOk);
|
assert(response.data.write_back(data) == Steinberg::kResultOk);
|
||||||
|
|
||||||
@@ -914,7 +915,7 @@ tresult PLUGIN_API Vst3PluginProxyImpl::getXmlRepresentationStream(
|
|||||||
if (stream) {
|
if (stream) {
|
||||||
const GetXmlRepresentationStreamResponse response = bridge.send_message(
|
const GetXmlRepresentationStreamResponse response = bridge.send_message(
|
||||||
YaXmlRepresentationController::GetXmlRepresentationStream{
|
YaXmlRepresentationController::GetXmlRepresentationStream{
|
||||||
.instance_id = instance_id(), .info = info});
|
.instance_id = instance_id(), .info = info, .stream = stream});
|
||||||
|
|
||||||
response.stream.write_back(stream);
|
response.stream.write_back(stream);
|
||||||
|
|
||||||
|
|||||||
@@ -172,21 +172,20 @@ void Vst3Bridge::run() {
|
|||||||
},
|
},
|
||||||
[&](Vst3PluginProxy::GetState& request)
|
[&](Vst3PluginProxy::GetState& request)
|
||||||
-> Vst3PluginProxy::GetState::Response {
|
-> Vst3PluginProxy::GetState::Response {
|
||||||
YaBStream stream{};
|
|
||||||
tresult result;
|
tresult result;
|
||||||
|
|
||||||
// This same function is defined in both `IComponent` and
|
// This same function is defined in both `IComponent` and
|
||||||
// `IEditController`, so the host is calling one or the other
|
// `IEditController`, so the host is calling one or the other
|
||||||
if (object_instances[request.instance_id].component) {
|
if (object_instances[request.instance_id].component) {
|
||||||
result = object_instances[request.instance_id]
|
result = object_instances[request.instance_id]
|
||||||
.component->getState(&stream);
|
.component->getState(&request.state);
|
||||||
} else {
|
} else {
|
||||||
result = object_instances[request.instance_id]
|
result = object_instances[request.instance_id]
|
||||||
.edit_controller->getState(&stream);
|
.edit_controller->getState(&request.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Vst3PluginProxy::GetStateResponse{
|
return Vst3PluginProxy::GetStateResponse{
|
||||||
.result = result, .updated_state = std::move(stream)};
|
.result = result, .state = std::move(request.state)};
|
||||||
},
|
},
|
||||||
[&](YaAudioPresentationLatency::SetAudioPresentationLatencySamples&
|
[&](YaAudioPresentationLatency::SetAudioPresentationLatencySamples&
|
||||||
request)
|
request)
|
||||||
@@ -739,16 +738,16 @@ void Vst3Bridge::run() {
|
|||||||
return object_instances[request.instance_id]
|
return object_instances[request.instance_id]
|
||||||
.program_list_data->programDataSupported(request.list_id);
|
.program_list_data->programDataSupported(request.list_id);
|
||||||
},
|
},
|
||||||
[&](const YaProgramListData::GetProgramData& request)
|
[&](YaProgramListData::GetProgramData& request)
|
||||||
-> YaProgramListData::GetProgramData::Response {
|
-> YaProgramListData::GetProgramData::Response {
|
||||||
YaBStream data{};
|
|
||||||
const tresult result =
|
const tresult result =
|
||||||
object_instances[request.instance_id]
|
object_instances[request.instance_id]
|
||||||
.program_list_data->getProgramData(
|
.program_list_data->getProgramData(
|
||||||
request.list_id, request.program_index, &data);
|
request.list_id, request.program_index,
|
||||||
|
&request.data);
|
||||||
|
|
||||||
return YaProgramListData::GetProgramDataResponse{
|
return YaProgramListData::GetProgramDataResponse{
|
||||||
.result = result, .data = std::move(data)};
|
.result = result, .data = std::move(request.data)};
|
||||||
},
|
},
|
||||||
[&](YaProgramListData::SetProgramData& request)
|
[&](YaProgramListData::SetProgramData& request)
|
||||||
-> YaProgramListData::SetProgramData::Response {
|
-> YaProgramListData::SetProgramData::Response {
|
||||||
@@ -761,15 +760,14 @@ void Vst3Bridge::run() {
|
|||||||
return object_instances[request.instance_id]
|
return object_instances[request.instance_id]
|
||||||
.unit_data->unitDataSupported(request.unit_id);
|
.unit_data->unitDataSupported(request.unit_id);
|
||||||
},
|
},
|
||||||
[&](const YaUnitData::GetUnitData& request)
|
[&](YaUnitData::GetUnitData& request)
|
||||||
-> YaUnitData::GetUnitData::Response {
|
-> YaUnitData::GetUnitData::Response {
|
||||||
YaBStream data{};
|
|
||||||
const tresult result =
|
const tresult result =
|
||||||
object_instances[request.instance_id]
|
object_instances[request.instance_id]
|
||||||
.unit_data->getUnitData(request.unit_id, &data);
|
.unit_data->getUnitData(request.unit_id, &request.data);
|
||||||
|
|
||||||
return YaUnitData::GetUnitDataResponse{.result = result,
|
return YaUnitData::GetUnitDataResponse{
|
||||||
.data = std::move(data)};
|
.result = result, .data = std::move(request.data)};
|
||||||
},
|
},
|
||||||
[&](YaUnitData::SetUnitData& request)
|
[&](YaUnitData::SetUnitData& request)
|
||||||
-> YaUnitData::SetUnitData::Response {
|
-> YaUnitData::SetUnitData::Response {
|
||||||
@@ -898,17 +896,17 @@ void Vst3Bridge::run() {
|
|||||||
[&](YaXmlRepresentationController::GetXmlRepresentationStream&
|
[&](YaXmlRepresentationController::GetXmlRepresentationStream&
|
||||||
request) -> YaXmlRepresentationController::
|
request) -> YaXmlRepresentationController::
|
||||||
GetXmlRepresentationStream::Response {
|
GetXmlRepresentationStream::Response {
|
||||||
YaBStream stream{};
|
|
||||||
const tresult result =
|
const tresult result =
|
||||||
object_instances[request.instance_id]
|
object_instances[request.instance_id]
|
||||||
.xml_representation_controller
|
.xml_representation_controller
|
||||||
->getXmlRepresentationStream(
|
->getXmlRepresentationStream(
|
||||||
request.info, &stream);
|
request.info, &request.stream);
|
||||||
|
|
||||||
return YaXmlRepresentationController::
|
return YaXmlRepresentationController::
|
||||||
GetXmlRepresentationStreamResponse{
|
GetXmlRepresentationStreamResponse{
|
||||||
.result = result,
|
.result = result,
|
||||||
.stream = std::move(stream)};
|
.stream =
|
||||||
|
std::move(request.stream)};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user