Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next2 #235

Closed
wants to merge 7 commits into from
Closed

Next2 #235

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/pullreq.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ jobs:
with:
submodules: recursive

- name: Apt Update
if: ${{ matrix.run_aptget }}
run: sudo apt-get update

- name: Get Deps
if: ${{ matrix.run_aptget }}
run: sudo apt-get install -y alsa alsa-tools libasound2-dev libjack-dev libgtk-3-dev
Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ option(CLAP_WRAPPER_WINDOWS_SINGLE_FILE "Build a single fine (rather than folder

project(clap-wrapper
LANGUAGES C CXX
VERSION 0.7.1
VERSION 0.7.3
DESCRIPTION "CLAP-as-X wrappers"
)
set(CLAP_WRAPPER_VERSION "${CMAKE_PROJECT_VERSION}" CACHE STRING "Version of the wrapper project")

if (APPLE)
enable_language(OBJC)
Expand Down
2 changes: 1 addition & 1 deletion cmake/shared_prologue.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ endif()
add_library(clap-wrapper-compile-options INTERFACE)
add_library(clap-wrapper-sanitizer-options INTERFACE)

target_compile_options(clap-wrapper-compile-options INTERFACE -D${CLAP_WRAPPER_PLATFORM}=1)
target_compile_options(clap-wrapper-compile-options INTERFACE -D${CLAP_WRAPPER_PLATFORM}=1 -DCLAP_WRAPPER_VERSION="${CLAP_WRAPPER_VERSION}")
if (APPLE)
target_link_libraries(clap-wrapper-compile-options INTERFACE macos_filesystem_support)
endif()
Expand Down
11 changes: 7 additions & 4 deletions include/clapwrapper/vst3.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
#endif

// the factory extension
static const CLAP_CONSTEXPR char CLAP_PLUGIN_FACTORY_INFO_VST3[] =
"clap.plugin-factory-info-as-vst3.draft0";
static const CLAP_CONSTEXPR char CLAP_PLUGIN_FACTORY_INFO_VST3[] = "clap.plugin-factory-info-as-vst3/0";

// the plugin extension
static const CLAP_CONSTEXPR char CLAP_PLUGIN_AS_VST3[] = "clap.plugin-info-as-vst3.draft0";
static const CLAP_CONSTEXPR char CLAP_PLUGIN_AS_VST3[] = "clap.plugin-info-as-vst3/0";

typedef uint8_t array_of_16_bytes[16];

Expand Down Expand Up @@ -77,6 +76,8 @@ typedef uint8_t array_of_16_bytes[16];

all members are optional when set to nullptr
if not provided, the wrapper code will use/generate appropriate values

this struct is being returned by the plugin in clap_plugin_factory_as_vst3_t::get_vst3_info()
*/

typedef struct clap_plugin_info_as_vst3
Expand All @@ -92,7 +93,7 @@ typedef struct clap_plugin_info_as_vst3
all members are optional and can be set to nullptr
if not provided, the wrapper code will use/generate appropriate values

retrieved when asking for factory CLAP_PLUGIN_FACTORY_INFO_VST3
retrieved when asking for factory CLAP_PLUGIN_FACTORY_INFO_VST3 by clap_entry::get_factory()
*/

typedef struct clap_plugin_factory_as_vst3
Expand Down Expand Up @@ -125,6 +126,8 @@ enum clap_supported_note_expressions
/*
retrieve additional information for the plugin itself, if note expressions are being supported and if there
is a limit in MIDI channels (to reduce the offered controllers etc. in the VST3 host)

This extension is optionally returned by the plugin when asked for extension CLAP_PLUGIN_AS_VST3
*/
typedef struct clap_plugin_as_vst3
{
Expand Down
2 changes: 1 addition & 1 deletion src/clap_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Plugin::Plugin(IHost* host)
host->host_get_name(),
"defiant nerd",
"https://www.defiantnerd.com",
"0.0.1",
CLAP_WRAPPER_VERSION,
Plugin::clapExtension,
Plugin::clapRequestRestart,
Plugin::clapRequestProcess,
Expand Down
8 changes: 5 additions & 3 deletions src/detail/vst3/parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,14 +160,16 @@ Vst3Parameter* Vst3Parameter::create(uint8_t bus, uint8_t channel, uint8_t cc, V
str8ToStr16(v.title, fullname.c_str(), str16BufferSize(v.title));
// TODO: string shrink algorithm shortening the string a bit
str8ToStr16(v.shortTitle, name, str16BufferSize(v.shortTitle));
v.units[0] = 0; // unfortunately, CLAP has no unit for parameter values
v.unitId = channel + 1;

v.units[0] = 0; // nothing in the "unit" field
// the unit will not be set here, but outside
// v.unitId = channel + 1;

v.defaultNormalizedValue = 0;
v.flags = Vst::ParameterInfo::kNoFlags;
if (cc == Vst::ControllerNumbers::kCtrlProgramChange)
{
v.flags |= Vst::ParameterInfo::kIsProgramChange;
v.flags |= Vst::ParameterInfo::kIsProgramChange | Vst::ParameterInfo::kCanAutomate;
v.stepCount = 128;
}

Expand Down
7 changes: 6 additions & 1 deletion src/detail/vst3/parameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,15 @@ class Vst3Parameter : public Steinberg::Vst::Parameter

inline double asClapValue(double vst3value) const
{
return vst3value * (max_value - min_value) + min_value;
return (vst3value * (max_value - min_value)) + min_value;
}
inline double asVst3Value(double clapvalue) const
{
auto& info = this->getInfo();
if (info.stepCount > 0)
{
return (clapvalue - min_value) / float(info.stepCount);
}
return (clapvalue - min_value) / (max_value - min_value);
}
static Vst3Parameter* create(const clap_param_info_t* info,
Expand Down
8 changes: 8 additions & 0 deletions src/detail/vst3/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,14 @@ void ProcessAdapter::process(Steinberg::Vst::ProcessData& data)
n.midi.data[2] = (val >> 7) & 0x7F; // MSB
}
break;
case Vst::ControllerNumbers::kCtrlProgramChange:
{
auto val = (uint16_t)param->asClapValue(value);
n.midi.data[0] = 0xC0 | param->channel; // $Cc
n.midi.data[1] = (val & 0x7F); // only one byte
n.midi.data[2] = 0;
}
break;
default:
n.midi.data[0] = 0xB0 | param->channel;
n.midi.data[1] = param->controller;
Expand Down
2 changes: 1 addition & 1 deletion src/wrapasauv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ OSStatus WrapAsAUV2::Render(AudioUnitRenderActionFlags& inFlags, const AudioTime
auto userd = _midioutput_hostcallback.userData;
auto pktlist = i->getMIDIPacketList();
auto fn = _midioutput_hostcallback.midiOutputCallback;
OSStatus result = (*fn)(userd, &inTimeStamp, i->_auport, pktlist);
[[maybe_unused]] OSStatus result = (*fn)(userd, &inTimeStamp, i->_auport, pktlist);
assert(result == noErr);
}
}
Expand Down
90 changes: 81 additions & 9 deletions src/wrapasvst3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ tresult PLUGIN_API ClapAsVst3::process(Vst::ProcessData& data)
}

auto thisFn = _plugin->AlwaysAudioThread();

this->_processAdapter->process(data);
return kResultOk;
}
Expand Down Expand Up @@ -261,6 +262,14 @@ tresult PLUGIN_API ClapAsVst3::getParamStringByValue(Vst::ParamID id, Vst::Param
auto param = (Vst3Parameter*)this->getParameterObject(id);
auto val = param->asClapValue(valueNormalized);

if (param->getInfo().flags & Vst::ParameterInfo::kIsProgramChange)
{
UString wrapper(&string[0], str16BufferSize(Steinberg::Vst::String128));

wrapper.assign("Program", 8);
return kResultOk;
}

char outbuf[128];
memset(outbuf, 0, sizeof(outbuf));
if (this->_plugin->_ext._params->value_to_text(_plugin->_plugin, param->id, val, outbuf, 127))
Expand Down Expand Up @@ -304,8 +313,11 @@ tresult PLUGIN_API ClapAsVst3::getMidiControllerAssignment(int32 busIndex, int16
// for my first Event bus and for MIDI channel 0 and for MIDI CC Volume only
if (busIndex == 0) // && channel == 0) // && midiControllerNumber == Vst::kCtrlVolume)
{
id = _IMidiMappingIDs[channel][midiControllerNumber];
return kResultTrue;
if (midiControllerNumber < Vst::kCountCtrlNumber) // with program change
{
id = _IMidiMappingIDs[channel][midiControllerNumber];
return kResultTrue;
}
}
return kResultFalse;
}
Expand Down Expand Up @@ -353,12 +365,22 @@ tresult ClapAsVst3::getNoteExpressionValueByString(int32 /*busIndex*/, int16 /*c

#endif

////-----------------------------------------------------------------------------
//tresult PLUGIN_API ClapAsVst3::queryInterface(const TUID iid, void** obj)
//{
// DEF_INTERFACE(IMidiMapping)
// return SingleComponentEffect::queryInterface(iid, obj);
//}
tresult ClapAsVst3::getUnitByBus(Vst::MediaType type, Vst::BusDirection dir, int32 busIndex,
int32 channel, Vst::UnitID& unitId /*out*/)
{
if (type == Vst::MediaTypes::kEvent && dir == Vst::BusDirections::kInput)
{
if (busIndex == 0)
{
if ((channel >= 0) && (channel < (Steinberg::int32)_MIDIUnits.size()))
{
unitId = _MIDIUnits[channel];
return kResultTrue;
}
}
}
return kResultFalse;
}

static Vst::SpeakerArrangement speakerArrFromPortType(const char* port_type)
{
Expand Down Expand Up @@ -636,9 +658,21 @@ void ClapAsVst3::setupParameters(const clap_plugin_t* plugin, const clap_plugin_
// find free tags for IMidiMapping
Vst::ParamID x = 0xb00000;
_IMidiMappingEasy = true;
_MIDIUnits.clear();

for (uint8_t channel = 0; channel < _numMidiChannels; channel++)
{
// the unit for that channel
Vst::UnitInfo midiUnitInfo;

midiUnitInfo.id = (decltype(midiUnitInfo.id))units.size();
midiUnitInfo.parentUnitId = 0; // parented in the root unit
midiUnitInfo.programListId = Vst::kNoProgramListId;

auto name = fmt::format("MIDI Channel {}", channel + 1);

VST3::StringConvert::convert(name, midiUnitInfo.name);

for (int i = 0; i < Vst::ControllerNumbers::kCountCtrlNumber; ++i)
{
while (parameters.getParameter(x))
Expand All @@ -649,9 +683,46 @@ void ClapAsVst3::setupParameters(const clap_plugin_t* plugin, const clap_plugin_
x++;
}
auto p = Vst3Parameter::create(0, channel, i, x);
p->setUnitID(midiUnitInfo.id);
parameters.addParameter(p);
_IMidiMappingIDs[channel][i] = x++;
}
// if (false)
{
// program change parameter
while (parameters.getParameter(x))
{
// if this happens there is a index clash between the parameter ids
// and the ones reserved for the IMidiMapping
_IMidiMappingEasy = false;
x++;
}
auto p = Vst3Parameter::create(0, channel, Vst::ControllerNumbers::kCtrlProgramChange, x);

p->setUnitID(midiUnitInfo.id);
_MIDIUnits.emplace_back(midiUnitInfo.id);

parameters.addParameter(p);

auto programlist = new Steinberg::Vst::ProgramList(STR16("Program Changes"), x, midiUnitInfo.id);
for (int pc = 0; pc < 128; ++pc)
{
auto programname = fmt::format("Program {}", pc + 1);

programlist->addProgram(VST3::StringConvert::convert(programname).c_str());
}
this->addProgramList(programlist);

auto newUnit = new Vst::Unit(midiUnitInfo);

addUnit(newUnit);

// the programlist ID is actually the parameter ID
newUnit->setProgramListID(x);

//_IMidiMappingIDs[channel][Vst::ControllerNumbers::kCtrlProgramChange] = x++;
x++;
}
}
}

Expand Down Expand Up @@ -903,7 +974,8 @@ void ClapAsVst3::onIdle()
Clap::ProcessAdapter pa;
pa.setupProcessing(_plugin->_plugin, _plugin->_ext._params, audioInputs, audioOutputs, 0, 0, 0,
this->parameters, componentHandler, nullptr, false, false);
auto thisFn = _plugin->AlwaysMainThread();
auto thisFn = _plugin->AlwaysMainThread(); // just to pacify the clap-helper

pa.flush();
}
}
Expand Down
24 changes: 23 additions & 1 deletion src/wrapasvst3.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,25 @@ class ClapAsVst3 : public Steinberg::Vst::SingleComponentEffect,
int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, const Vst::TChar* string /*in*/,
Vst::NoteExpressionValue& valueNormalized /*out*/) override;

//---IUnitInfo--------------------------------------------------------------------------

tresult PLUGIN_API getUnitByBus(Vst::MediaType /*type*/, Vst::BusDirection /*dir*/, int32 /*busIndex*/,
int32 /*channel*/, Vst::UnitID& /*unitId*/ /*out*/) SMTG_OVERRIDE;

#if 0
// units selection --------------------
Vst::UnitID PLUGIN_API getSelectedUnit () SMTG_OVERRIDE { return selectedUnit; }
tresult PLUGIN_API selectUnit (Vst::UnitID unitId) SMTG_OVERRIDE
{
selectedUnit = unitId;
return kResultTrue;
}
#endif

//---Interface--------------------------------------------------------------------------
OBJ_METHODS(ClapAsVst3, SingleComponentEffect)
DEFINE_INTERFACES
// since the macro above opens a local function, this code is being executed during QueryInterface() :)
// dynamic interfaces
if (::Steinberg::FUnknownPrivate::iidEqual(iid, IMidiMapping::iid))
{
// when queried for the IMididMapping interface, check if the CLAP supports MIDI dialect on the MIDI Input busses and only return IMidiMapping then
Expand All @@ -176,6 +191,12 @@ class ClapAsVst3 : public Steinberg::Vst::SingleComponentEffect,
DEF_INTERFACE(IMidiMapping)
}
}
// add any other interfaces here:
//if (::Steinberg::FUnknownPrivate::iidEqual(iid, IExampleSomething::iid))
//{
// DEF_INTERFACE(IExampleSomething)
//}

DEF_INTERFACE(INoteExpressionController)
// tresult PLUGIN_API queryInterface(const TUID iid, void** obj) override;
END_DEFINE_INTERFACES(SingleComponentEffect)
Expand Down Expand Up @@ -324,4 +345,5 @@ class ClapAsVst3 : public Steinberg::Vst::SingleComponentEffect,
#else
clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_PRESSURE;
#endif
std::vector<Vst::UnitID> _MIDIUnits;
};
Loading