diff -Nru fst-0.120.0/debian/changelog fst-0.122.0/debian/changelog --- fst-0.120.0/debian/changelog 2021-09-01 15:06:03.000000000 +0000 +++ fst-0.122.0/debian/changelog 2022-08-19 13:44:14.000000000 +0000 @@ -1,3 +1,12 @@ +fst (0.122.0-1) unstable; urgency=medium + + * New upstream version 0.122.0 + * Refresh dates in d/copyright + * Regenerate d/copyright_hints + * Bump standards version to 4.6.1 + + -- IOhannes m zmölnig (Debian/GNU) Fri, 19 Aug 2022 15:44:14 +0200 + fst (0.120.0-1) unstable; urgency=medium * New upstream version 0.120.0 diff -Nru fst-0.120.0/debian/control fst-0.122.0/debian/control --- fst-0.120.0/debian/control 2021-09-01 15:06:03.000000000 +0000 +++ fst-0.122.0/debian/control 2022-08-19 13:44:14.000000000 +0000 @@ -6,7 +6,7 @@ Priority: optional Build-Depends: debhelper-compat (= 13), -Standards-Version: 4.6.0 +Standards-Version: 4.6.1 Rules-Requires-Root: no Vcs-Browser: https://salsa.debian.org/multimedia-team/fst Vcs-Git: https://salsa.debian.org/multimedia-team/fst.git diff -Nru fst-0.120.0/debian/copyright fst-0.122.0/debian/copyright --- fst-0.120.0/debian/copyright 2021-09-01 15:06:03.000000000 +0000 +++ fst-0.122.0/debian/copyright 2022-08-19 13:44:14.000000000 +0000 @@ -4,11 +4,11 @@ Source: https://git.iem.at/zmoelnig/FST/ Files: * -Copyright: 2019-2021, IOhannes m zmölnig, IEM +Copyright: 2019-2022, IOhannes m zmölnig, IEM License: GPL-3+ Files: debian/* -Copyright: 2019, IOhannes m zmölnig +Copyright: 2019-2022, IOhannes m zmölnig License: GPL-3+ License: GPL-3+ diff -Nru fst-0.120.0/debian/copyright_hints fst-0.122.0/debian/copyright_hints --- fst-0.120.0/debian/copyright_hints 2021-09-01 15:06:03.000000000 +0000 +++ fst-0.122.0/debian/copyright_hints 2022-08-19 13:44:14.000000000 +0000 @@ -4,8 +4,7 @@ Source: FIXME Disclaimer: Autogenerated by licensecheck -Files: ./debian/changelog - ./debian/control +Files: ./debian/control ./debian/fst-dev.docs ./debian/fst-dev.install ./debian/fst-dev.postinst @@ -62,15 +61,15 @@ License: GPL-3 FIXME -Files: ./README.md -Copyright: NONE +Files: ./debian/copyright +Copyright: 2019, IOhannes m zmölnig + 2019-2021, IOhannes m zmölnig, IEM License: GPL-3+ FIXME -Files: ./debian/copyright -Copyright: 2019, IOhannes m zmölnig - 2019, IOhannes m zmölnig, IEM -License: GPL-3+ +Files: ./debian/changelog +Copyright: Bump copyright dates +License: UNKNOWN FIXME Files: ./LICENSE @@ -78,3 +77,9 @@ License: UNKNOWN FIXME +Files: ./README.md +Copyright: terms or + terms. +License: UNKNOWN + FIXME + diff -Nru fst-0.120.0/docs/opcodes.org fst-0.122.0/docs/opcodes.org --- fst-0.120.0/docs/opcodes.org 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/docs/opcodes.org 2022-08-19 12:48:20.000000000 +0000 @@ -3,157 +3,156 @@ ** host -| opcode | value | notes | -|--------+----------------------------------------+------------------------------------------------------------------------------| -| 0 | audioMasterAutomate | | -| 1 | audioMasterVersion | :JUCE returns 2400 | -| 2 | audioMasterCurrentId? | :REAPER returns 0xDEAD | -| 2 | ? | :REAPER-plugins call this in the ctor | -| 6 | ? | :called as response to effCode:12 with ivalue=1 | -| 6 | ? | :REAPER returns 1 | -| 7 | audioMasterGetTime | :called by hypercyclic/tonespace as response to effCode:12 with ivalue=65024 | -| 7 | audioMasterGetTime | :REAPER returns an address | -| 8 | audioMasterProcessEvents | :REAPER returns 1 | -| | | :REAPER crashes with tained VstEvents-data | -| 10 | audioMasterTempoAt | | -| 11 | ? | :REAPER returns 0x10000 (65536) | -| 12 | ? | :REAPER returns 1 | -| 13 | ? | :called with 0-args in Protoverb:main and hypercyclic:eff:12 | -| 13? | ? | :Protoverb calls in main (and as response to effcode:30514?) | -| 16 | audioMasterGetSampleRate | | -| 17 | audioMasterGetBlockSize | | -| 19 | ? | :REAPER returns 0x2800, 0x33FF, 0x2FFF, 0x3400, 0x3000 when called... | -| | | :...repeatedly while handling effCode:25 (args are ignored) | -| 23 | ? | :called by JUCE-plugins with 0-args as response to effCode:12 | -| 32 | audioMasterGetVendorString | | -| 33 | audioMasterGetProductString | | -| 34 | audioMasterGetVendorVersion | :JUCE returns 0x0101 (257) | -| 37 | audioMasterCanDo | | -| 42 | ? | :Protoverb calls as response to effSetProgramName | -| 43 | ? | :called by JUCE-plugins with index of a GUI-changed parameter (no more args) | -| 44 | ? | :called by JUCE-plugins with index of a GUI-changed parameter (no more args) | -| 48 | audioMasterGetDirectory? | :REAPER returns filename of reaper-project file (.RPP) | -|--------+----------------------------------------+------------------------------------------------------------------------------| -| | audioMasterWantMidi | | -| | audioMasterCanDo | | -| | audioMasterCurrentId? | | -| | audioMasterGetDirectory? | | -| | audioMasterBeginEdit | | -| | audioMasterEndEdit | | -| | audioMasterSizeWindow | | -| | audioMasterUpdateDisplay | | -| | audioMasterGetCurrentProcessLevel | | -| | audioMasterGetAutomationState | | -| | audioMasterGetNumAutomatableParameters | | -| | audioMasterIdle | | -| | audioMasterIOChanged | | -| | audioMasterNeedIdle | | -| | audioMasterPinConnected | | -| | audioMasterSetOutputSampleRate | | -|--------+----------------------------------------+------------------------------------------------------------------------------| -| | audioMasterGetLanguage | JUCE-ignore | -| | audioMasterGetOutputSpeakerArrangement | JUCE-ignore | -| | audioMasterGetParameterQuantization | JUCE-ignore | -| | audioMasterGetPreviousPlug | JUCE-ignore | -| | audioMasterGetNextPlug | JUCE-ignore | -| | audioMasterSetTime | JUCE-ignore | -| | audioMasterWillReplaceOrAccumulate | JUCE-ignore | -| | audioMasterGetInputLatency | JUCE-ignore | -| | audioMasterGetOutputLatency | JUCE-ignore | -| | audioMasterOpenWindow | JUCE-ignore | -| | audioMasterCloseWindow | JUCE-ignore | -| | audioMasterSetIcon | JUCE-ignore | -| | audioMasterOfflineGetCurrentMetaPass | JUCE-ignore | -| | audioMasterOfflineGetCurrentPass | JUCE-ignore | -| | audioMasterOfflineRead | JUCE-ignore | -| | audioMasterOfflineStart | JUCE-ignore | -| | audioMasterOfflineWrite | JUCE-ignore | -| | audioMasterVendorSpecific | JUCE-ignore | -| | | | +| opcode | value | notes | +|--------+----------------------------------------+-----------------------------------------------------------------------------------| +| 0 | audioMasterAutomate | | +| 1 | audioMasterVersion | :JUCE returns 2400 | +| 2 | audioMasterCurrentId? | :REAPER returns 0xDEAD | +| | | :REAPER-plugins call this in the ctor | +| 6 | audioMasterWantMidi | :called as response to effMainsChanged with ivalue=1 | +| | | :REAPER returns 1 | +| 7 | audioMasterGetTime | :called by hypercyclic/tonespace as response to effMainsChanged with ivalue=65024 | +| | | :REAPER returns an address | +| 8 | audioMasterProcessEvents | :REAPER returns 1 | +| | | :REAPER crashes with tained VstEvents-data | +| 10 | audioMasterTempoAt | | +| 11 | ? | :REAPER returns 0x10000 (65536) | +| 12 | ? | :REAPER returns 1 | +| 13 | ? | :called with 0-args in Protoverb:main and hypercyclic:eff:12 | +| 13? | ? | :Protoverb calls in main (and as response to effcode:30514?) | +| 14 | ? | :Renoise_Redux calls this (without args) in main | +| | | :REAPER returns 0 | +| 15 | audioMasterSizeWindow | | +| 16 | audioMasterGetSampleRate | | +| 17 | audioMasterGetBlockSize | | +| 19 | ? | :REAPER returns 0x2800, 0x33FF, 0x2FFF, 0x3400, 0x3000 when called... | +| | | :...repeatedly while handling effProcessEvents (args are ignored) | +| 23 | audioMasterGetCurrentProcessLevel | :called by JUCE-plugins with 0-args as response to effMainsChanged | +| 32 | audioMasterGetVendorString | | +| 33 | audioMasterGetProductString | | +| 34 | audioMasterGetVendorVersion | :JUCE returns 0x0101 (257) | +| 37 | audioMasterCanDo | | +| 42 | ? | :Protoverb calls as response to effSetProgramName | +| 43 | audioMasterBeginEdit | :called by JUCE-plugins with index of a GUI-changed parameter (no more args) | +| 44 | audioMasterEndEdit | :called by JUCE-plugins with index of a GUI-changed parameter (no more args) | +| 48 | audioMasterGetDirectory? | :REAPER returns filename of reaper-project file (.RPP) | +|--------+----------------------------------------+-----------------------------------------------------------------------------------| +| | audioMasterCurrentId? | | +| | audioMasterGetDirectory? | | +| | audioMasterUpdateDisplay | | +| | audioMasterGetAutomationState | | +| | audioMasterGetNumAutomatableParameters | | +| | audioMasterIdle | | +| | audioMasterIOChanged | | +| | audioMasterNeedIdle | | +| | audioMasterPinConnected | | +| | audioMasterSetOutputSampleRate | | +|--------+----------------------------------------+-----------------------------------------------------------------------------------| +| | audioMasterGetLanguage | JUCE-ignore | +| | audioMasterGetOutputSpeakerArrangement | JUCE-ignore | +| | audioMasterGetParameterQuantization | JUCE-ignore | +| | audioMasterGetPreviousPlug | JUCE-ignore | +| | audioMasterGetNextPlug | JUCE-ignore | +| | audioMasterSetTime | JUCE-ignore | +| | audioMasterWillReplaceOrAccumulate | JUCE-ignore | +| | audioMasterGetInputLatency | JUCE-ignore | +| | audioMasterGetOutputLatency | JUCE-ignore | +| | audioMasterOpenWindow | JUCE-ignore | +| | audioMasterCloseWindow | JUCE-ignore | +| | audioMasterSetIcon | JUCE-ignore | +| | audioMasterOfflineGetCurrentMetaPass | JUCE-ignore | +| | audioMasterOfflineGetCurrentPass | JUCE-ignore | +| | audioMasterOfflineRead | JUCE-ignore | +| | audioMasterOfflineStart | JUCE-ignore | +| | audioMasterOfflineWrite | JUCE-ignore | +| | audioMasterVendorSpecific | JUCE-ignore | +| | | | ** plugin -| opcode | value | notes | -|------------+-----------------------------+--------------------------------------------------------------------| -| 0 | effOpen | :REAPER calls with 0 (at the very beginning) | -| 1 | effClose | :CRASH | -| | | :REAPER calls with 0 (at the very end) | -| 2 | effSetProgram | set program# via ivalue | -| 3 | effGetProgram | returns current program# | -| 4 | effSetProgramName | :needs a valid ptr, Protoverb calls hostCode:42 | -| 5 | effGetProgramName | writes current program name into ptr | -| 6 | effGetParamLabel | unit (e.g. "dB") | -| 7 | effGetParamDisplay | string representation of current value (e.g. "-23") | -| 8 | effGetParamName | human readable name (e.g. "Gain") | -| 9 | | | -| 10 | effSetSampleRate | :Protoverb prints "AM_AudioMan::reset()" | -| 11 | effSetBlockSize | | -| 12 | effMainsChanged | :Protoverb does resume/reset and calls hostCode:6 | -| | | :Digits calls hostCode:6 | -| | | :BowEcho/Danaides calls hostCode:23+6 | -| | | :hypercyclic/tonespace calls hostCode:23+7+6 | -| | | :REAPER calls with ivalue=1/0 | -| 13 | effEditGetRect | :Protoverb prints "AM_VST_Editor::getRect" and CRASH | -| 14 | effEditOpen | :Protoverb prints "AM_VST_Editor::open" and EXIT | -| 15 | effEditClose | :Protoverb prints "closed editor." | -| 22 | effIdentify | :Protoverv returns 0x4E764566 | -| 23 | effGetChunk | :Protoverb returns 0x317 (or 0x307) and writes an address into ptr | -| 24 | effSetChunk | :Protoverb returns 1 | -| 25 | effProcessEvents | :Protoverb returns 1 | -| 26 | | :Protoverb returns 1 | -| 29 | effGetProgramNameIndexed | :Protoverb returns 1 and ptr:"initialize" | -| 33 | effGetInputProperties | :Protoverb returns 1 and ptr:"Protoverb-In0" | -| 34 | effGetOutputProperties | :Protoverb returns 1 and ptr:"Protoverb-Out0" | -| 35 | effGetPlugCategory | :JUCE RETURNS VstPlugCategory | -| 35 | | :REAPER calls with 0 | -| | | :InstaLooper returns 0 | -| | | :Protoverb/BowEcho/Danaides/reacom.vst returns 1 | -| | | :Digits/hypercyclic/tonespace returns 2 | -| 41 | | :crashes when called with (0,0,"name41",0) | -| 45 | effGetEffectName | :Protoverb returns 1 and ptr:"Protoverb" | -| 47 | effGetVendorString | :Protoverb returns 1 and ptr:"u-he"; prints getVendorString() | -| 48 | effGetProductString | :Protoverb returns 1 and ptr:"Protoverb 1.0.0" | -| 49 | effGetVendorVersion | :Protoverb returns 0x10000 | -| 50 | effVendorSpecific | :REAPER only calls this is 'hasCockosExtensions' is supported | -| 51 | effCanDo | :Protoverb returns 0xFFFFFFFFFFFFFFFF (with ptr:"") | -| 56 | | :REAPER calls with ptr to zeroed memory | -| | | :all return 0 | -| 58 | effGetVstVersion | :Protoverb returns 2400 (0x960) | -| 59 | effKeysRequired? | :Protoverb prints "u-he plugin doesn't use key" | -| 63 | | :Protoverb returns 0xFFFFFFFFFFFFFFFF (with ptr:"") | -| 71 | | :REAPER calls with 0 | -| | | :Protoverb returns 1, rest returns 0 | -| 72 | | :REAPER calls with 0 | -| 77 | effSetProcessPrecision | :REAPER calls with 1 | -| | | :Protoverb returns 1, rest returns 0 | -| 30514 | | :Protoverb calls hostCode:13 | -| 0xdeadbeef | | :REAPER ask for function? | -|------------+-----------------------------+--------------------------------------------------------------------| -| | effGetTailSize | | -| | effGetCurrentMidiProgram | | -| | effGetSpeakerArrangement | | -| | effGetNumMidiInputChannels | | -| | effGetNumMidiOutputChannels | | -| | | | -| | effCanBeAutomated | :takes index | -| | effString2Parameter | | -| | effSetSpeakerArrangement | | -| | effSetBypass | | -| | effSetTotalSampleToProcess | | -| | effConnectInput | | -| | effConnectOutput | | -| | effIdle | | -| | effShellGetNextPlugin | | -| | effStartProcess | | -| | effStopProcess | | -| | effEditDraw | | -| | effEditMouse | | -| | effEditSleep | | -| | effEditTop | | -| | effEditIdle | | +| opcode | value | notes | +|------------+-----------------------------+---------------------------------------------------------------------------------------------------------| +| 0 | effOpen | :REAPER calls with 0 (at the very beginning) | +| 1 | effClose | :CRASH | +| | | :REAPER calls with 0 (at the very end) | +| 2 | effSetProgram | set program# via ivalue | +| 3 | effGetProgram | returns current program# | +| 4 | effSetProgramName | :needs a valid ptr, Protoverb calls hostCode:42 | +| 5 | effGetProgramName | writes current program name into ptr | +| 6 | effGetParamLabel | unit (e.g. "dB") | +| 7 | effGetParamDisplay | string representation of current value (e.g. "-23") | +| 8 | effGetParamName | human readable name (e.g. "Gain") | +| 9 | | | +| 10 | effSetSampleRate | :Protoverb prints "AM_AudioMan::reset()" | +| 11 | effSetBlockSize | | +| 12 | effMainsChanged | :Protoverb does resume/reset and calls audioMasterWantMidi | +| | | :Digits calls audioMasterWantMidi | +| | | :BowEcho/Danaides calls audioMasterWantMidi, audioMasterGetCurrentProcessLevel | +| | | :hypercyclic/tonespace calls audioMasterWantMidi, audioMasterGetTime, audioMasterGetCurrentProcessLevel | +| | | :REAPER calls with ivalue=1/0 | +| 13 | effEditGetRect | :Protoverb prints "AM_VST_Editor::getRect" and CRASH | +| 14 | effEditOpen | :Protoverb prints "AM_VST_Editor::open" and EXIT | +| 15 | effEditClose | :Protoverb prints "closed editor." | +| 19 | effEditIdle | :REAPER calls repeatedly every 50ms | +| | | :JUCE (>=7?) requires polling for GUI | +| 22 | effIdentify | :Protoverv returns 0x4E764566 | +| 23 | effGetChunk | :Protoverb returns 0x317 (or 0x307) and writes an address into ptr | +| 24 | effSetChunk | :Protoverb returns 1 | +| 25 | effProcessEvents | :Protoverb returns 1 | +| 26 | | :Protoverb returns 1 | +| 29 | effGetProgramNameIndexed | :Protoverb returns 1 and ptr:"initialize" | +| 33 | effGetInputProperties | :Protoverb returns 1 and ptr:"Protoverb-In0" | +| 34 | effGetOutputProperties | :Protoverb returns 1 and ptr:"Protoverb-Out0" | +| 35 | effGetPlugCategory | :JUCE RETURNS VstPlugCategory | +| 35 | | :REAPER calls with 0 | +| | | :InstaLooper returns 0 | +| | | :Protoverb/BowEcho/Danaides/reacom.vst returns 1 | +| | | :Digits/hypercyclic/tonespace returns 2 | +| 41 | | :crashes when called with (0,0,"name41",0) | +| 45 | effGetEffectName | :Protoverb returns 1 and ptr:"Protoverb" | +| 47 | effGetVendorString | :Protoverb returns 1 and ptr:"u-he"; prints getVendorString() | +| 48 | effGetProductString | :Protoverb returns 1 and ptr:"Protoverb 1.0.0" | +| 49 | effGetVendorVersion | :Protoverb returns 0x10000 | +| 50 | effVendorSpecific | :REAPER only calls this if 'hasCockosExtensions' is supported | +| 51 | effCanDo | :Protoverb returns 0xFFFFFFFFFFFFFFFF (with ptr:"") | +| 53 | | :REAPER calls repeatedly every 50ms | +| 56 | | :REAPER calls with ptr to zeroed memory | +| | | :all return 0 | +| 58 | effGetVstVersion | :Protoverb returns 2400 (0x960) | +| 59 | effKeysRequired? | :Protoverb prints "u-he plugin doesn't use key" | +| 63 | | :Protoverb returns 0xFFFFFFFFFFFFFFFF (with ptr:"") | +| 71 | | :REAPER calls with 0 | +| | | :Protoverb returns 1, rest returns 0 | +| 72 | | :REAPER calls with 0 | +| 77 | effSetProcessPrecision | :REAPER calls with 1 | +| | | :Protoverb returns 1, rest returns 0 | +| 30514 | | :Protoverb calls hostCode:13 | +| 0xDEADBEEF | | :REAPER ask for function? | +|------------+-----------------------------+---------------------------------------------------------------------------------------------------------| +| | effGetTailSize | | +| | effGetCurrentMidiProgram | | +| | effGetSpeakerArrangement | | +| | effGetNumMidiInputChannels | | +| | effGetNumMidiOutputChannels | | +| | | | +| | effCanBeAutomated | :takes index | +| | effString2Parameter | | +| | effSetSpeakerArrangement | | +| | effSetBypass | | +| | effSetTotalSampleToProcess | | +| | effConnectInput | | +| | effConnectOutput | | +| | effIdle | | +| | effShellGetNextPlugin | | +| | effStartProcess | | +| | effStopProcess | | +| | effEditDraw | | +| | effEditMouse | | +| | effEditSleep | | +| | effEditTop | | ** flags diff -Nru fst-0.120.0/docs/REVERSE_ENGINEERING.md fst-0.122.0/docs/REVERSE_ENGINEERING.md --- fst-0.120.0/docs/REVERSE_ENGINEERING.md 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/docs/REVERSE_ENGINEERING.md 2022-08-19 12:48:20.000000000 +0000 @@ -26,6 +26,7 @@ - JUCE-5.4.1: https://d30pueezughrda.cloudfront.net/juce/juce-5.4.1-linux.zip - JUCE-6.0.7: https://github.com/juce-framework/JUCE/releases/download/6.0.7/juce-6.0.7-linux.zip (accessed 2021-02-03) +- JUCE-7.0.2: https://github.com/juce-framework/JUCE/releases/download/7.0.2/juce-7.0.2-linux.zip (accessed 2022-08-17) ### Plugins @@ -39,6 +40,11 @@ - Tonespace: http://www.mucoder.net/en/tonespace/ - GVST: https://www.gvst.co.uk/index.htm +- ArpeggiatorTutorial: https://docs.juce.com/master/tutorial_plugin_examples.html (accessed 2022-08-17) +- NoiseGateTutorial: https://docs.juce.com/master/tutorial_plugin_examples.html (accessed 2022-08-17) +- SurroundTutorial: https://docs.juce.com/master/tutorial_plugin_examples.html (accessed 2022-08-17) +- MultiOutSynthTutorial: https://docs.juce.com/master/tutorial_plugin_examples.html (accessed 2022-08-17) + ### Hosts - Reaper: https://www.reaper.fm/download.php (reaper5965_linux_x86_64.tar.xz) @@ -365,6 +371,17 @@ } AEffect; ~~~ +#### the AEffect struct tag +As of JUCE-7.0.2, the `typedef struct AEffect_ AEffect` fails to compile, +as it uses `struct AEffect` as an argument (that is: it uses the struct-tag `AEffect` +rather than the typedef `AEffect`). +Since I don't know of any way to alias a struct-tag, we really must use `struct AEffect` as in: + +~~~C +typedef struct AEffect { +/* ... */ +} AEffect; +~~~ ### VstPinProperties this is also a type rather than an enum. @@ -615,7 +632,7 @@ ## fake values to make our live a bit easier, we want to make sure to be able to differentiate between -real opcodes (the values we somehow detected from our reverse engineering effords) and +real opcodes (the values we somehow detected from our reverse engineering efforts) and fake opcodes (those where we only know the name, but have no clue about their actual value). The simplest way is to just assign values to the fake opcodes that we are pretty sure are wrong @@ -872,7 +889,7 @@ This looks bad enough. Not all looks bad though: `magic` has a value of `1450406992`, which really is `0x56737450` in hex, which happens to be the magic number `VstP`. -The rest however is absymal: negative version numbers, unique IDs that are `0` (how unique can you get), +The rest however is abysmal: negative version numbers, unique IDs that are `0` (how unique can you get), a function pointer (to `processReplacing`) that is `0x31` which is definitely invalid. So let's take a closer look at the actual data. @@ -1028,7 +1045,7 @@ will also print something about a 16samples delay to the stderr). ~~~C -typedef struct AEffect_ { +typedef struct AEffect { t_fstInt32 magic; /* @0 0x56737450, aka 'VstP' */ char _pad1[4]; // always 0 AEffectDispatcherProc* dispatcher; // ??? @@ -1080,7 +1097,7 @@ Using `pointer sized int` instead of `int32` helps a bit: ~~~ -typedef struct AEffect_ { +typedef struct AEffect { VstIntPtr magic; AEffectDispatcherProc* dispatcher; //?? AEffectProcessProc* process; //? @@ -1705,7 +1722,7 @@ So let's play with those, and just revert the order of the two functions: ~~~C -typedef struct AEffect_ { +typedef struct AEffect { t_fstInt32 magic; AEffectDispatcherProc* dispatcher; AEffectProcessProc* process; @@ -2369,7 +2386,7 @@ Some columns have very reasonable values (e.g. columns 1, 2, 4, 5, 6, 7 and 8), while others are out of bounds (9, 10, 11 and 12). -The reasonable values indicate that we used the corret type to decode the bytes. +The reasonable values indicate that we used the correct type to decode the bytes. A value like "8.48798e-314" is hardly useful in the context of audio processing, so most likely these bytes just don't represent double values. Note that there's a clear divide between reasonable values to the left (the first 8 numbers; aka 64 bytes) @@ -2432,7 +2449,7 @@ The number `-559038737` has a (little endian) hex representation of 0xDEADBEEF and is a typical magic number. -We should also havea look at the bytes @10-18, which - so far - made most sense when decoded as double. +We should also have a look at the bytes @10-18, which - so far - made most sense when decoded as double. Because the numbers are so high (*1.48147e+14*) we divide them by 10^9. This results in the display of a number (e.g. `152197`) that increments by 1 every second. @@ -2540,7 +2557,7 @@ - the 3rd and 13th bits are set when looping - the 4th bit is set when recording -If we skim through the list of contants for values that might be related to the transport state, +If we skim through the list of constants for values that might be related to the transport state, we find 4 constants starting with `kVstTransport*`, that map neatly to the observed bits: | flag | value | @@ -2950,7 +2967,7 @@ # Part: AudioPluginHost With many opcodes working, we can start testing on a larger scale. -A good start is by compiling some slighly larger application ourself, e.g. the *AudioPluginHost* that comes with JUCE. +A good start is by compiling some slightly larger application ourself, e.g. the *AudioPluginHost* that comes with JUCE. Once started we can load the *Protoverb* plugin, to see that a number of yet unknown opcodes are called in both directions: @@ -3459,7 +3476,7 @@ Loading the above plugin in a fake host, we get immediate segfaults when trying to write vendor string, using our estimate of `kVstMaxVendorStrLen` (197782). Gradually lowering the maximum length of the vendor string, the first value where it doesn't crash is `130`. -This is a much more reasonable length thatn *197782*, although `128` would be even more plausible. +This is a much more reasonable length than *197782*, although `128` would be even more plausible. Lets used that last value for `kVstMaxVendorStrLen` (and `kVstMaxProductStrLen` as well). ## effString2Parameter @@ -3590,7 +3607,7 @@ We can easily test this assumption: since `VstSpeakerProperties` is at least 4 bytes large (assuming that it's `type` member is a 32bit `int` like all other types we have seen so far), and REAPER can handle up to 64 channels, we can force the full size of `speakers[]` to 256 bytes -(64 * 4), which is way beyong the 88 bytes of position @58. +(64 * 4), which is way beyond the 88 bytes of position @58. Printing the first 512 bytes a 64channel plugin receives with the `effSetSpeakerArrangement` opcode, gives: @@ -3686,7 +3703,7 @@ | 64 | alternating `01`/`02` from @58 to @1be8, every 0x70 bytes | after @1f88 | | 3 | `01`@58, `02`@c8, `03`@138 | after @4da | -After a certain point the data is densly filled with non-null bytes, which probably really is "uninitialized memory" (aka "garbage"). +After a certain point the data is densely filled with non-null bytes, which probably really is "uninitialized memory" (aka "garbage"). The important part to notice is that the position difference between the first lonely byte @58 and the last one (@c8, @138, @1be8) is always `112 * (numChannels-1)`. @@ -3819,14 +3836,14 @@ | unchecked (OFF) | 2 | `kVstProcessLevelRealtime` | | checked (ON) | 4 | `kVstProcessLevelOffline` | -REAPER also reports a a process-level of `1`, but only at the beginning (e.g. while the host calls the plugin with `effMainsChanged`). +REAPER also reports a process-level of `1`, but only at the beginning (e.g. while the host calls the plugin with `effMainsChanged`). | name | value | note | |----------------------------|-------|---------------------------------------------| | ?? | 0 | returned by JUCE is in realtime mode | | ?? | 1 | returned by REAPER during `effMainsChanged` | | `kVstProcessLevelRealtime` | 2 | returned by REAPER during normal rendering | -| ?? | 3 | (inbetween) | +| ?? | 3 | (in between) | | `kVstProcessLevelOffline` | 4 | returned by REAPER when offline-rendering; returned by JUCE if NOT in realtime mode | | `kVstProcessLevelUnknown` | ?? | used by MrsWatson | @@ -3933,7 +3950,7 @@ So Apple also uses the `k` prefix for constants. -Anyhow, only the `kVstMaxParamStrLen` constant appear to be truely VST2-related. +Anyhow, only the `kVstMaxParamStrLen` constant appear to be truly VST2-related. Checking the JUCE sources for a bit of context, we learn: > length should technically be `kVstMaxParamStrLen`, which is 8, but hosts will normally allow a bit more @@ -3948,6 +3965,73 @@ +# JUCE-7.0.2 + +Time has passed again. +Recently (at the middle of 2022) I checked compiling `JstHost` and `JstPlugin` +against JUCE-7.0.2. And it miserably failed, with unknown symbols (again). + +## AudioMasterOpcodesX + +This time it was only one, namely a type `AudioMasterOpcodesX` (within the +`Vst2::` namespace, but that is added by JUCE). +We also notice that this type is used with the `audioMasterIOChanged` opcode. +Which makes us think that the `AudioMasterOpcodesX` is simply a typedef for our +host opcode enumeration. + +Note: The trailing `X` in the type name most likely indicates that it is defined +in the `aeffectx.h` header. +It's likely, that there is also an `AudioMasterOpcodes` enum type, and they +contain different enumerations. +We ignore this for now and simply wrap all our host opcodes into an enumeration +that is typedefed to `AudioMasterOpcodesX`. + +## struct AEffect + +JUCE-7.0.2 now explicitly uses the [`AEffect` struct tag](#the-aeffect-struct-tag). + + +## effEditIdle +JUCE-7.0.2 now issues `effEditIdle` in the host's `VSTPluginInstance::handleIdle()` +(at least if the plugin is currently being shown). +On Linux, JUCE-7.0.2 plugins react on the `effEditIdle` by processing any pending events. + +These pending events appear to be responsible for updating the GUI, +at least the GUI now shows nothing if I compile a JUCE-plugin (e.g. the +*ArpeggiatorTutorial* plugin from the JUCE Plugin examples) +and load it into REAPER: +"nothing" being a rectangle that is not being updated at all. +I'm sure it did show something in older versions of JUCE. + +As we want our GUI to be updated continuously, we need to check for a (yet unknown) opcode +that is sent periodically to our plugin. +With REAPER, this gives us two potential candidates: `opcode:19` and `opcode:53`. +Both are called about every 50ms with only `0` as arguments. + +We also notice that both are only called when we open the *FX* window in REAPER. +However, while `opcode:53` is always polled as soon as the *FX* window is open, +`opcode:19` is only polled if we enable the built-in GUI. +As soon as we switch to the generic GUI, only `opcode:53` remains. + +It's hard to tell which one we should pick, but +*19* is close to the range of already known `effEdit*` opcodes (e.g. `effEditClose` is 15), +whereas *53* is somewhere near `effCanDo`. + +So let's go for: + +| opcode | | +|-------------|----| +| effEditIdle | 19 | + +Maybe `opcode:53` is for `effIdle` (as it also gets continuously called), +but why does it only get polled if the *FX* window is open? + +NOTE: while this makes the *ArpeggiatorTutorial* and friends work, +they still crash when opening a second JUCE plugin. hmmm... + + + + # Summary So far we have discovered quite a few opcodes (and constants): @@ -3968,8 +4052,8 @@ | `audioMasterSetOutputSampleRate` | | `audioMasterUpdateDisplay` | |------------------------------------------| -| `effConnectInput`/ `effConnectOutput` | -| `effEdit(Draw,Idle,Mouse,Sleep,Top)` | +| `effConnect(In,Out)put` | +| `effEdit(Draw,Mouse,Sleep,Top)` | | `effGetNumMidi(In,Out)putChannels` | | `effGetTailSize` | | `effIdle` | @@ -3994,9 +4078,9 @@ |------------|-------| | audioHost* | 3 | | audioHost* | 13 | +| audioHost* | 14 | | audioHost* | 42 | |------------|-------| -| eff* | 19 | | eff* | 53 | | eff* | 56 | | eff* | 62 | @@ -4009,21 +4093,29 @@ ## hostCode:3 ## hostCode:13 +## hostCode:14 ## hostCode:42 -## effCode:19 ## effCode:53 ## effCode:56 -gets called with automation, whenever the window gets focus? +~~gets called with automation, whenever the window gets focus?~~ + +gets called, when a parameter has an automation track, and the window gains/loses focus: - FstClient::dispatcher(0x2a4c8b0, 56, 0, 0, 0x7fff4a83fb40, 0.000000)... + FstClient::dispatcher(0x2a4c8b0, 56, 2, 0, 0x7fff4a83fb40, 0.000000)... The address seems to be zeroed-out (at least the first 0x99 bytes). The index is the parameter index currently being automated... +Attempting to write something to the buffer does not seem to have any effect (in REAPER), +unless you exceed the boundary of buffer, which triggers a stack-smashing segfault. +It is triggered as soon as a non-NULL value is written at `(char*)ptr)[0x98]`. + +(This doesn't mean much, apart from the fact that we are writing out-of-bounds. +esp. it doesn't tell us anything about the valid size of the buffer.) ## effCode:62 This is called when the MIDI-dialog gets opened (right before effCode:66; but only once) @@ -4041,11 +4133,22 @@ FstClient::dispatcher(0x19b9250, 66, 0, 0, 0xeae040, 0.000000); FstClient::dispatcher(0x19b9250, 66, 0, 0, 0xeae040, 0.000000); ~~~ -### effCode:66 + +the index is the MIDI channel number (zero-based). + the pointer is an address to a memory region, where the first 4 bytes are 0, and the 2nd 4 bytes are an int32 between 34 and 72. -the numbers seem to be the visible notes on the virtual MIDI keyboard. + +i have no idea what the first number is (it is always 0), +but the second number is a MIDI-note number. +Writing a string into the buffer right after the first 8 bytes (that hold the two numbers), +will make REAPER show this string as labels for the given MIDI-note on the +virtual MIDI keyboard. + +Unfortunately we do not now the opcode name for this. +Given that there's a `effGetCurrentMidiProgram` opcode, +my guess would be something along the lines of `effGetMidiNoteName`. ## even more symbols @@ -4060,6 +4163,4 @@ | member | VstTimeInfo.samplesToNextClock | vstplugin~ | |----------------|--------------------------------|------------| | type | VstAEffectFlags | vstplugin~ | -| type | VstInt32 | vstplugin~ | -|----------------|--------------------------------|------------| -| function/macro | CCONST | vstplugin~ | + diff -Nru fst-0.120.0/fst/fst.h fst-0.122.0/fst/fst.h --- fst-0.120.0/fst/fst.h 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/fst/fst.h 2022-08-19 12:48:20.000000000 +0000 @@ -18,14 +18,14 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with striem. If not, see . + * along with FST. If not, see . */ #ifndef FST_fst_h_ #define FST_fst_h_ #define FST_MAJOR_VERSION 0 -#define FST_MINOR_VERSION 120 +#define FST_MINOR_VERSION 122 #define FST_MICRO_VERSION 0 #define FST_VERSIONNUM(X, Y, Z) \ @@ -66,6 +66,9 @@ #define FST_ENUM_UNKNOWN(x) FST_DEPRECATE_ENUM(x) = (100000 + __LINE__) /* name mangling */ +#ifdef FST2VST +# define _fstEffect AEffect +#endif # define FST_HOST_OPCODE(x, y) audioMaster##x = y # define FST_HOST_OPCODE_EXPERIMENTAL(x, y) FST_ENUM_EXPERIMENTAL( audioMaster##x, y) @@ -93,34 +96,64 @@ #define VSTCALLBACK -#if defined(_WIN32) && defined(__x86_64__) -typedef long long t_fstPtrInt; /* pointer sized int */ + /* t_fstPtrInt: pointer sized int */ +#if defined(_WIN32) && (defined(__x86_64__) || defined (_M_X64)) +typedef long long t_fstPtrInt; #else -typedef long t_fstPtrInt; /* pointer sized int */ +typedef long t_fstPtrInt; #endif + typedef int t_fstInt32; /* 32bit int */ typedef enum { FST_HOST_OPCODE(Automate, 0), /* IN:index, IN:fvalue, return 0 */ FST_HOST_OPCODE(Version, 1), /* return 2400 */ FST_HOST_OPCODE_EXPERIMENTAL(CurrentId, 2), /* return shellUIDToCreate */ + + + FST_HOST_OPCODE(WantMidi, 6), /* return 0 */ FST_HOST_OPCODE(GetTime, 7), /* return (fstTimeInfo*) */ FST_HOST_OPCODE(ProcessEvents, 8), /* IN:ptr(fstEvents*), return 0 */ + FST_HOST_OPCODE(TempoAt, 10), /* IN:ivalue, return (10000*BPM) */ + + /* 13: sending latency?? */ + FST_HOST_OPCODE(SizeWindow, 15), /* IN:index(width), IN:value(height), return 1 */ FST_HOST_OPCODE(GetSampleRate, 16), /* return sampleRate */ FST_HOST_OPCODE(GetBlockSize, 17), /* return blockSize */ + + + + + FST_HOST_OPCODE(GetCurrentProcessLevel, 23), /* return (!isRealtime)*4 */ + + + + + + + FST_HOST_OPCODE(GetVendorString, 32), /* OUT:ptr(char[MaxVendorStrLen]), return ptr */ FST_HOST_OPCODE(GetProductString, 33), /* OUT:ptr(char[MaxProductStrLen]), return ptr */ FST_HOST_OPCODE(GetVendorVersion, 34), /* return 0x0101 */ + + FST_HOST_OPCODE(CanDo, 37), /* IN:ptr(char*), return *ptr in {"sendFstEvents", "sizeWindow",...} */ + + + + FST_HOST_OPCODE(BeginEdit, 43), /* IN:index, return 0 */ FST_HOST_OPCODE(EndEdit, 44), /* IN:index, return 0 */ + + + FST_HOST_OPCODE_UNKNOWN(CloseWindow), /* ?, return 0 */ FST_HOST_OPCODE_UNKNOWN(OpenWindow), /* ?, return 0 */ FST_HOST_OPCODE_UNKNOWN(SetIcon), /* ?, return 0 */ @@ -169,6 +202,7 @@ fst_audioMasterLast /* last enum */ } t_fstHostOpcode;; + typedef enum { FST_EFFECT_OPCODE(Open, 0), /* return 0 */ FST_EFFECT_OPCODE(Close, 1), /* return 0 */ @@ -181,45 +215,74 @@ FST_EFFECT_OPCODE(GetParamLabel, 6), /* OUT:ptr(char[8]), return 0 */ FST_EFFECT_OPCODE(GetParamDisplay, 7), /* OUT:ptr(char[8]), return 0 */ FST_EFFECT_OPCODE(GetParamName, 8), /* OUT:ptr(char[8]), return 0 */ + FST_EFFECT_OPCODE(SetSampleRate, 10), /* IN:fvalue, return 0 */ FST_EFFECT_OPCODE(SetBlockSize, 11), /* IN:ivalue, return 0 */ FST_EFFECT_OPCODE(MainsChanged, 12), /* IN:ivalue, return 0; (handleResumeSuspend) */ - FST_EFFECT_OPCODE(EditGetRect, 13), /* OUT:ptr(ERect*), return ptr */ - FST_EFFECT_OPCODE(EditOpen, 14), + FST_EFFECT_OPCODE(EditOpen, 14), /* return 0 */ FST_EFFECT_OPCODE(EditClose, 15), /* return 0 */ + + + FST_EFFECT_OPCODE(EditIdle, 19), /* return 0 */ + + FST_EFFECT_OPCODE(Identify, 22), /* return ByteOrder::bigEndianInt ("NvEf") 1316373862 or 1715828302 */ FST_EFFECT_OPCODE(GetChunk, 23), /* IN:index, OUT:ptr(void*), return size */ FST_EFFECT_OPCODE(SetChunk, 24), /* IN:index, IN:ivalue(size), IN:ptr(void*), return 0 */ - FST_EFFECT_OPCODE(ProcessEvents, 25), /* IN:ptr(fstEvents*), return ((bool)MidiProcessed */ FST_EFFECT_OPCODE(CanBeAutomated, 26), /* (can parameter# be automated) IN:index, return 0 */ FST_EFFECT_OPCODE(String2Parameter, 27), /* IN:index, IN:ptr(char*), return (hasParam#) */ FST_EFFECT_OPCODE(GetProgramNameIndexed, 29), /* IN:index, OUT:ptr(char[24], return (hasProg#) */ + + + FST_EFFECT_OPCODE(GetInputProperties, 33), /* IN:index, OUT:ptr(fstPinProperties*), return 1|0 */ FST_EFFECT_OPCODE(GetOutputProperties, 34), /* IN:index, OUT:ptr(fstPinProperties*), return 1|0 */ FST_EFFECT_OPCODE(GetPlugCategory, 35), /* return category */ + + + + + FST_EFFECT_OPCODE(SetSpeakerArrangement, 42), /* IN:ivalue(fstSpeakerArrangement*in) IN:ptr(fstSpeakerArrangement*out) */ + FST_EFFECT_OPCODE(GetEffectName, 45), /* OUT:ptr(char[64]), return 1 */ + FST_EFFECT_OPCODE(GetVendorString, 47), /* OUT:ptr(char[64]), return 1 */ FST_EFFECT_OPCODE(GetProductString, 48), /* OUT:ptr(char[64]), return 1 */ FST_EFFECT_OPCODE(GetVendorVersion, 49), /* return version */ FST_EFFECT_OPCODE(VendorSpecific, 50), /* behaviour defined by vendor... */ - FST_EFFECT_OPCODE(CanDo, 51), /* IN:ptr(char*), returns 0|1|-1 */ + + + + + + FST_EFFECT_OPCODE(GetVstVersion, 58), /* return kVstVersion */ + + + + FST_EFFECT_OPCODE_EXPERIMENTAL(GetCurrentMidiProgram, 63), /* return -1 */ - FST_EFFECT_OPCODE(GetSpeakerArrangement, 69), /* OUT:ivalue(fstSpeakerArrangement*in) OUT:ptr(fstSpeakerArrangement*out), return (!(hasAUX || isMidi)) */ + /* we know what this does, but we don't know its name */ + FST_DEPRECATE_UNKNOWN(fst_effGetMidiNoteName) = 66, /* IN:index=MIDIchannel, IN:ptr({int unknown, int midinote, char*buffer}), OUT:ptr.buffer) */ + + FST_EFFECT_OPCODE(GetSpeakerArrangement, 69), /* OUT:ivalue(fstSpeakerArrangement*in) OUT:ptr(fstSpeakerArrangement*out), return (!(hasAUX || isMidi)) */ FST_EFFECT_OPCODE(ShellGetNextPlugin, 70), FST_EFFECT_OPCODE_EXPERIMENTAL(StartProcess, 71), FST_EFFECT_OPCODE_EXPERIMENTAL(StopProcess, 72), FST_EFFECT_OPCODE(SetTotalSampleToProcess, 73), /* return ivalue */ + + + FST_EFFECT_OPCODE(SetProcessPrecision, 77), /* IN:ivalue(ProcessPrecision64,..), return !isProcessing */ @@ -230,7 +293,6 @@ FST_EFFECT_OPCODE_UNKNOWN(EditMouse), FST_EFFECT_OPCODE_UNKNOWN(EditSleep), FST_EFFECT_OPCODE_UNKNOWN(EditTop), - FST_EFFECT_OPCODE_UNKNOWN(EditIdle), FST_EFFECT_OPCODE_UNKNOWN(GetNumMidiInputChannels), /* return 16*isMidi */ FST_EFFECT_OPCODE_UNKNOWN(GetNumMidiOutputChannels), /* return 16*isMidi */ @@ -254,12 +316,20 @@ typedef enum { FST_EFFECT_FLAG(HasEditor, 0), + + + FST_EFFECT_FLAG(CanReplacing, 4), FST_EFFECT_FLAG(ProgramChunks, 5), + + FST_EFFECT_FLAG(IsSynth, 8), FST_EFFECT_FLAG(NoSoundInStop, 9), + + FST_EFFECT_FLAG(CanDoubleReplacing, 12), } t_fstEffectFlags; + typedef enum { FST_EFFECT_CATEGORY_EXPERIMENTAL(Unknown, 0), FST_EFFECT_CATEGORY_EXPERIMENTAL(Effect, 1), @@ -310,6 +380,9 @@ FST_SPEAKER(Arr102, 28), FST_SPEAKER(ArrUserDefined, -2), +#if defined(__GNUC__) || defined(__clang__) +# warning document origin of kSpeakerM +#endif FST_SPEAKER_EXPERIMENTAL(M, 0), FST_SPEAKER(L, 1), FST_SPEAKER(R, 2), @@ -331,12 +404,10 @@ FST_SPEAKER_UNKNOWN(Trr), FST_SPEAKER_UNKNOWN(Lfe2), -#if defined(__GNUC__) || defined(__clang__) -# warning document origin of kSpeakerM -#endif FST_SPEAKER_UNKNOWN(Undefined), fst_speakerLast /* last enum */ } t_fstSpeakerArrangementType; + enum { /* fstTimeInfo.flags */ FST_FLAG(TransportChanged, 0), FST_FLAG(TransportPlaying, 1), @@ -354,6 +425,7 @@ FST_FLAG(SmpteValid , 14), FST_FLAG(ClockValid , 15) }; + enum { /* 197782 is where the array passed at opcode:33 overflows */ /* GVST/GChorus crashes with MaxVendorStrLen>130 */ @@ -373,7 +445,9 @@ FST_FLAG_UNKNOWN(PinIsActive), FST_FLAG_UNKNOWN(PinUseSpeaker), FST_FLAG_UNKNOWN(PinIsStereo), +}; +typedef enum { /* used as: t_fstTimeInfo.smpteFrameRate */ FST_CONSTANT_UNKNOWN(Smpte239fps), FST_CONSTANT_UNKNOWN(Smpte24fps), @@ -387,7 +461,7 @@ FST_CONSTANT_UNKNOWN(Smpte60fps), FST_CONSTANT_UNKNOWN(SmpteFilm16mm), FST_CONSTANT_UNKNOWN(SmpteFilm35mm), -}; +} t_fstSmpteFrameRates; enum { FST_CONSTANT(ProcessPrecision32, 0), @@ -402,7 +476,9 @@ enum { /* returned by audioMasterGetCurrentProcessLevel: */ FST_CONSTANT_EXPERIMENTAL(ProcessLevelUnknown, 0), + FST_CONSTANT(ProcessLevelRealtime, 2), + FST_CONSTANT(ProcessLevelOffline, 4), #if defined(__GNUC__) || defined(__clang__) # warning document origin of ProcesslevelUser @@ -511,6 +587,8 @@ } FST_UNKNOWN(t_fstPinProperties); +struct _fstEffect; + /* t_fstPtrInt dispatcher(effect, opcode, index, ivalue, ptr, fvalue); */ typedef t_fstPtrInt (*AEffectDispatcherProc)(struct _fstEffect*, int, int, t_fstPtrInt, void* const, float); /* void setParameter(effect, index, fvalue); */ @@ -561,6 +639,8 @@ } t_fstRectangle; +typedef t_fstHostOpcode AudioMasterOpcodesX; + typedef t_fstEvent FST_TYPE(Event); typedef t_fstMidiEvent FST_TYPE(MidiEvent); typedef t_fstSysexEvent FST_TYPE(MidiSysexEvent); @@ -568,6 +648,7 @@ typedef t_fstSpeakerProperties FST_TYPE(SpeakerProperties); typedef t_fstSpeakerArrangement FST_TYPE(SpeakerArrangement); typedef t_fstTimeInfo FST_TYPE(TimeInfo); +typedef t_fstSmpteFrameRates FST_TYPE(SmpteFrameRate); typedef t_fstPinProperties FST_TYPE(PinProperties); typedef t_fstEffectCategories FST_TYPE(PlugCategory); typedef t_fstEffectFlags FST_TYPE(AEffectFlags); @@ -578,9 +659,12 @@ typedef t_fstInt32 VstInt32; const int FST_CONST(EffectMagic, 0x56737450); -#if defined(__GNUC__) || defined(__clang__) -# warning document origin of CCONST + +/* see https://github.com/steinbergmedia/vst3_pluginterfaces/blob/efcfbf8019a2f1803b7be9936a81124abb583507/base/futils.h#L91-L95 + * for a GPL-v3 definition of CCONST + */ +#ifndef CCONST +# define CCONST(a,b,c,d) ((((unsigned char)a)<<24) + (((unsigned char)b)<<16) + (((unsigned char)c)<<8) + ((unsigned char)d)) #endif -#define CCONST(a,b,c,d) ((((unsigned char)a)<<24) + (((unsigned char)b)<<16) + (((unsigned char)c)<<8) + ((unsigned char)d)) #endif /* FST_fst_h_ */ diff -Nru fst-0.120.0/README.md fst-0.122.0/README.md --- fst-0.120.0/README.md 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/README.md 2022-08-19 12:48:20.000000000 +0000 @@ -7,23 +7,75 @@ Steinberg provides a VST2 SDK, but: - it has a proprietary license -- is no longer available from Steinberg (as they removed the VST2-SDK to push VST3) +- is no longer available from Steinberg (as they removed the VST2-SDK to push + VST3) FST is the attempt to create a bona-fide reverse-engineered header file, that is created without reference to the official VST SDK and without its developer(s) having agreed to the VST SDK license agreement. -All reverse-engineering steps are documented in the [REVERSE_ENGINEERING](docs/REVERSE_ENGINEERING.md) document. +All reverse-engineering steps are documented in the [REVERSE_ENGINEERING](docs/REVERSE_ENGINEERING.md) +document. ## USING You are free to use FST under our [LICENSE terms](#licensing). -However, Steinberg has trademarked the `VST` name, and explicitely forbids +However, Steinberg has trademarked the `VST` name, and explicitly forbids anyone from using this name without agreeing to *their* LICENSE terms. If you plan to release audio plugins based on the FST Interface, you are not allowed to call them `VST` or even say that they are `VST Compatible`. +## BONA-FIDA REVERSE-ENGINEERING + +Care is being taken to not break any license agreement or copyright terms. +We also take care not to expose or incriminate any Open Source +developer/project of unwittingly (or not) violating copyright terms or +license agreements. + +Our self-imposed rules for this purpose are: +- Do not use any material from Steinberg + - Never accept Steinberg's proprietary license agreement + - Never obtain the VST(2)-SDK, by whatever means +- Only use VST-enabled binaries and sources (hosts and plugins) from + commercial entities that do not require accepting any license terms. +- Do not use existing reverse-engineering attempts of the SDK + +### Some reasoning +We do not consider ourselves bound by Steinberg's license if we never accept it +explicitly or implicitly (e.g. by obtaining a version of the VST-SDKs +- even if it happens to be bundled with some 3rd party project). + +We only use Closed Source binaries from commercial entities under the assumption +that whowever makes their living from (also) selling plugins, will have a right +to do so (e.g. they are actually allowed to use the SDKs they are using, most +likely by coming to an agreement with the SDK vendors). +Conversely, we do not use binaries from independent Open Source developers +as it is not our job to track down the legitimacy of their use of SDKs. + +We only use binaries that do not require us to actively accept license +agreements, as they might contain clauses that prevent reverse-engineering. + +There are a couple of existing reverse-engineering attempts of the SDK, but we +haven't found any documentation on how they were created. +Therefore we cannot rule out that they might have been written with the use of +the original SDK (by this we do not imply that creating these attempts actually +infringed any copyright or license terms - only that we cannot be sure about it). + +## VERSIONING + +The versioning scheme of FST basically follows [semantic versioning](https://semver.org): + +Whenever a new opcode, etc. is discovered, the minor version number is +increased. Thus the minor version number (roughly) reflects the number of +discovered symbols. + +The micro version number is increased whenever a release is made without new +symbols (e.g. for a compatibility fix for a new compiler). + +The major version number will be incremented to `1` once the entire SDK has +been reverse engineered (as we do not anticipate any API breaking changes). + ## LICENSING FST is released under the [`GNU General Public License (version 3 or later)`](https://www.gnu.org/licenses/gpl-3.0.en.html). @@ -40,8 +92,8 @@ Opcodes that have not been reversed engineered yet are marked as `deprecated`, so you get a compiler warning when using them. -If you find you need a specific opcode that is not supported yet, please file a bug -at https://git.iem.at/zmoelnig/FST/issues +If you find you need a specific opcode that is not supported yet, please file a +bug at https://git.iem.at/zmoelnig/FST/issues -The more information you can provide, the more likely we will be able to implement missing -or fix broken things. +The more information you can provide, the more likely we will be able to +implement missing or fix broken things. diff -Nru fst-0.120.0/src/FstHost/FstHost.cpp fst-0.122.0/src/FstHost/FstHost.cpp --- fst-0.120.0/src/FstHost/FstHost.cpp 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/src/FstHost/FstHost.cpp 2022-08-19 12:48:20.000000000 +0000 @@ -544,7 +544,20 @@ return 0; } +int usage(const char*progname) { + fprintf(stderr, "usage: %s [ ...]\n", progname); + fprintf(stderr, "" + "\n" + "\tattempts to load each as a plugin\n" + "\tand runs some basic tests\n" + "\n" + ); + return 1; +} + int main(int argc, const char*argv[]) { + if(argc <= 1) + return usage(argv[0]); for(int i=1; i=90: stack smashing // <=85: ok snprintf((char*)ptr, 85, "JMZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); + case 66: { +#if 0 + char*cptr = (char*)ptr; + int*iptr = (int*)ptr; + printf("OPCODE66: %3d %3d\n", iptr[0], iptr[1]); + if (60 == iptr[1]) + snprintf((char*)ptr+8, 52, "middle C", iptr[1]); + else + snprintf((char*)ptr+8, 52, "note:#%d", iptr[1]); + #endif + } + //return 1; default: break; } @@ -124,6 +137,7 @@ AEffect*VSTPluginMain(AEffectDispatcherProc dispatch4host) { char pluginname[512] = {0}; char*pluginfile = getenv("FST_PROXYPLUGIN"); + printf("FstProxy: %s\n", pluginfile); if(!pluginfile)return 0; s_plug2host = dispatch4host; diff -Nru fst-0.120.0/src/fst_utils.h fst-0.122.0/src/fst_utils.h --- fst-0.120.0/src/fst_utils.h 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/src/fst_utils.h 2022-08-19 12:48:20.000000000 +0000 @@ -86,6 +86,7 @@ FST_UTILS__OPCODESTR(effEditTop); FST_UTILS__OPCODESTR(effGetChunk); FST_UTILS__OPCODESTR(effGetCurrentMidiProgram); + FST_UTILS__OPCODESTR(fst_effGetMidiNoteName); FST_UTILS__OPCODESTR(effGetEffectName); FST_UTILS__OPCODESTR(effGetInputProperties); FST_UTILS__OPCODESTR(effGetNumMidiInputChannels); @@ -200,6 +201,7 @@ case effEditTop: case effGetChunk: case effGetCurrentMidiProgram: + case fst_effGetMidiNoteName: case effGetEffectName: case effGetInputProperties: case effGetNumMidiInputChannels: diff -Nru fst-0.120.0/src/JstHost/JstHost.jucer fst-0.122.0/src/JstHost/JstHost.jucer --- fst-0.120.0/src/JstHost/JstHost.jucer 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/src/JstHost/JstHost.jucer 2022-08-19 12:48:20.000000000 +0000 @@ -1,6 +1,6 @@ - + @@ -25,14 +25,14 @@ - - - - - - - - + + + + + + + + diff -Nru fst-0.120.0/src/JstPlugin/JstPlugin.jucer fst-0.122.0/src/JstPlugin/JstPlugin.jucer --- fst-0.120.0/src/JstPlugin/JstPlugin.jucer 2021-03-10 15:33:52.000000000 +0000 +++ fst-0.122.0/src/JstPlugin/JstPlugin.jucer 2022-08-19 12:48:20.000000000 +0000 @@ -1,7 +1,7 @@ - + . +# along with FST. If not, see . import struct