From 3274ae0d6960d493365ee0b1bfce7ab07a18cb26 Mon Sep 17 00:00:00 2001 From: Lucas Cordiviola Date: Thu, 28 Oct 2021 00:46:36 -0300 Subject: [PATCH] initial commit --- .gitignore | 9 + build/Release32/Pd_Gain-gui/Pd_Gain-gui.pd | 166 +++ build/Release32/Pd_Gain-gui/Pd_Gain-gui.pdv | 55 + .../Release32/Pd_Gain-nogui/Pd_Gain-nogui.pd | 35 + .../Release32/Pd_Gain-nogui/Pd_Gain-nogui.pdv | 49 + build/Release32/Pd_Gain/Pd_Gain.pd | 35 + build/Release32/Pd_Gain/Pd_Gain.pdv | 49 + build/Release32/Pd_Midi/Pd_Midi.pd | 170 +++ build/Release32/Pd_Midi/Pd_Midi.pdv | 52 + build/Release32/readme.txt | 1 + build/Release64/Pd_Gain-gui/Pd_Gain-gui.pd | 166 +++ build/Release64/Pd_Gain-gui/Pd_Gain-gui.pdv | 56 + .../Release64/Pd_Gain-nogui/Pd_Gain-nogui.pd | 35 + .../Release64/Pd_Gain-nogui/Pd_Gain-nogui.pdv | 49 + build/Release64/Pd_Gain/Pd_Gain.pd | 35 + build/Release64/Pd_Gain/Pd_Gain.pdv | 49 + build/Release64/Pd_Midi/Pd_Midi.pd | 170 +++ build/Release64/Pd_Midi/Pd_Midi.pdv | 53 + build/Release64/readme.txt | 1 + vst-scheduler/makefile | 20 + vst-scheduler/vstschedlib.c | 730 +++++++++++ vst-template/makefile | 43 + vst-template/pdvst.cpp | 1138 +++++++++++++++++ vst-template/pdvst.hpp | 175 +++ vst-template/pdvstEditor.cpp | 217 ++++ vst-template/pdvstEditor.hpp | 61 + vst-template/pdvstMain.cpp | 383 ++++++ vst-template/pdvstTransfer.h | 135 ++ 28 files changed, 4137 insertions(+) create mode 100644 .gitignore create mode 100644 build/Release32/Pd_Gain-gui/Pd_Gain-gui.pd create mode 100644 build/Release32/Pd_Gain-gui/Pd_Gain-gui.pdv create mode 100644 build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pd create mode 100644 build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pdv create mode 100644 build/Release32/Pd_Gain/Pd_Gain.pd create mode 100644 build/Release32/Pd_Gain/Pd_Gain.pdv create mode 100644 build/Release32/Pd_Midi/Pd_Midi.pd create mode 100644 build/Release32/Pd_Midi/Pd_Midi.pdv create mode 100644 build/Release32/readme.txt create mode 100644 build/Release64/Pd_Gain-gui/Pd_Gain-gui.pd create mode 100644 build/Release64/Pd_Gain-gui/Pd_Gain-gui.pdv create mode 100644 build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pd create mode 100644 build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pdv create mode 100644 build/Release64/Pd_Gain/Pd_Gain.pd create mode 100644 build/Release64/Pd_Gain/Pd_Gain.pdv create mode 100644 build/Release64/Pd_Midi/Pd_Midi.pd create mode 100644 build/Release64/Pd_Midi/Pd_Midi.pdv create mode 100644 build/Release64/readme.txt create mode 100644 vst-scheduler/makefile create mode 100644 vst-scheduler/vstschedlib.c create mode 100644 vst-template/makefile create mode 100644 vst-template/pdvst.cpp create mode 100644 vst-template/pdvst.hpp create mode 100644 vst-template/pdvstEditor.cpp create mode 100644 vst-template/pdvstEditor.hpp create mode 100644 vst-template/pdvstMain.cpp create mode 100644 vst-template/pdvstTransfer.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..04c7242 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# folders + +build/Release32/.pd +build/Release64/.pd +vstsdk2.4 + +# binaries + +*.dll \ No newline at end of file diff --git a/build/Release32/Pd_Gain-gui/Pd_Gain-gui.pd b/build/Release32/Pd_Gain-gui/Pd_Gain-gui.pd new file mode 100644 index 0000000..57c786a --- /dev/null +++ b/build/Release32/Pd_Gain-gui/Pd_Gain-gui.pd @@ -0,0 +1,166 @@ +#N canvas 313 -10 860 681 12; +#X obj 26 400 r rvstplugname; +#X msg 25 423 \; gui-label label \$1; +#X obj 37 22 r rvstopengui; +#X obj 24 86 select 0 1; +#X obj 22 227 delay 10; +#X obj 32 486 loadbang; +#X msg 31 512 1; +#X msg 68 513 0; +#N canvas 0 50 746 518 audio_stuff 0; +#X obj 104 322 adc~; +#X obj 104 401 dac~; +#X msg 47 286 \$1 30; +#X obj 47 311 line~; +#X obj 143 371 *~; +#X obj 104 371 *~; +#X obj 48 47 r rvstparameter0; +#X obj 48 229 * 100; +#X obj 47 253 dbtorms; +#X msg 79 81 set \$1; +#X obj 80 189 s svstparameter0; +#X obj 79 107 s level-rcv; +#X obj 80 144 r level-snd; +#X text 192 107 update pd-slider when parameter is changed from host +; +#X text 230 168 update host when parameter is changed from pd-slider +; +#X text 19 12 audio stuff example; +#X obj 315 283 loadbang; +#X msg 315 312 \; pd dsp 1 \;; +#X obj 368 463 tabwrite~ scope; +#X obj 375 433 metro 120; +#X obj 366 403 loadbang; +#X obj 280 413 *~ 5; +#X obj 280 438 clip~ -1 1; +#X connect 0 0 5 0; +#X connect 0 1 4 0; +#X connect 2 0 3 0; +#X connect 3 0 4 1; +#X connect 3 0 5 1; +#X connect 4 0 1 1; +#X connect 4 0 21 0; +#X connect 5 0 1 0; +#X connect 5 0 21 0; +#X connect 6 0 7 0; +#X connect 6 0 9 0; +#X connect 7 0 8 0; +#X connect 8 0 2 0; +#X connect 9 0 11 0; +#X connect 12 0 10 0; +#X connect 12 0 7 0; +#X connect 16 0 17 0; +#X connect 19 0 18 0; +#X connect 20 0 19 0; +#X connect 21 0 22 0; +#X connect 22 0 18 0; +#X restore 518 403 pd audio_stuff; +#X text 67 50 <- the host signals when gui has to be visible; +#X msg 75 195 vis 1; +#X obj 62 147 t b b; +#X text 124 197 display gui window; +#X text 186 79 0 = hide \, 1 = show; +#N canvas 0 50 450 300 hidePdConsole 0; +#X obj 78 48 inlet; +#X obj 76 149 hcs/sys_gui; +#X msg 75 117 wm withdraw .pdwindow; +#X msg 248 114 wm iconify .pdwindow; +#X obj 79 79 select 1 0; +#X connect 0 0 4 0; +#X connect 2 0 1 0; +#X connect 3 0 1 0; +#X connect 4 0 2 0; +#X connect 4 1 3 0; +#X restore 29 544 pd hidePdConsole; +#X text 163 545 (needs hcs/sys_gui external); +#N canvas 0 0 320 154 \$0-gui 0; +#X obj 5 5 cnv 15 300 190 empty gui-label empty 10 12 0 14 -233017 +-66577 0; +#X obj 13 53 vsl 60 128 0 1 0 0 level-snd level-rcv LEVEL 0 -9 0 10 +-262144 -1 -1 0 1; +#N canvas 0 50 450 250 (subpatch) 0; +#X array scope 300 float 1; +#A 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +#X coords 0 1 299 -1 120 70 1 0 0; +#X restore 138 57 graph; +#X obj 136 163 bng 15 250 50 0 \$0-show_parent empty show_parent_window +17 7 0 10 -262144 -1 -1; +#X text 101 145 click here to see main patch; +#X restore 517 361 pd \$0-gui; +#X obj 21 298 s pd-\$0-gui; +#X obj 29 653 s pd-Pd_Gain(gui).pd; +#X msg 29 624 vis 0; +#X obj 28 601 loadbang; +#X obj 104 602 r \$0-show_parent; +#X msg 104 627 vis 1; +#X obj 40 57 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X obj 58 113 delay 10; +#X msg 21 254 vis 0; +#X msg 206 252 vis 0; +#X obj 208 229 loadbang; +#X text 67 255 hide gui window; +#X obj 597 127 tgl 15 1 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X text 618 126 enable embedding (experimental); +#X text 110 300 (<- rename with the name of your gui window); +#X text 603 361 <- the actual gui window; +#N canvas 0 50 645 376 embedding_gui_into_host(experimental) 0; +#X obj 86 151 inlet; +#X obj 135 153 inlet; +#X obj 86 205 spigot; +#X obj 83 321 s guiName; +#X text 157 216 <- send to host the title of your gui window; +#X obj 84 268 f \$0; +#X msg 83 295 symbol \$1-gui; +#X obj 84 243 delay 10; +#X obj 154 180 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X text 90 40 In order to embed a puredata (tcl) gui window into host +\, the patch has to process values received from host (rvstopengui) +\, and send to it the title of the window to be embedded., f 61; +#X text 230 244 this may crash the tcl gui and thus puredata....; +#X msg 501 327 map 0 \, map 1; +#X connect 0 0 2 0; +#X connect 1 0 2 1; +#X connect 1 0 8 0; +#X connect 2 0 7 0; +#X connect 5 0 6 0; +#X connect 6 0 3 0; +#X connect 7 0 5 0; +#X restore 436 165 pd embedding_gui_into_host(experimental), f 23 +; +#X text 9 381 * Receiving plug & instance name from host; +#X text 14 349 *** OTHER TRICKS ***; +#X text 10 461 * Hiding pd-console window on startup; +#X text 13 573 * Hiding main patch (this one!) on startup; +#X text 545 13 PDVST; +#X connect 0 0 1 0; +#X connect 2 0 23 0; +#X connect 2 0 3 0; +#X connect 3 0 4 0; +#X connect 3 1 24 0; +#X connect 4 0 25 0; +#X connect 5 0 6 0; +#X connect 6 0 14 0; +#X connect 7 0 14 0; +#X connect 10 0 17 0; +#X connect 11 0 33 0; +#X connect 11 1 10 0; +#X connect 19 0 18 0; +#X connect 20 0 19 0; +#X connect 21 0 22 0; +#X connect 22 0 18 0; +#X connect 24 0 11 0; +#X connect 25 0 17 0; +#X connect 26 0 17 0; +#X connect 27 0 26 0; +#X connect 29 0 33 1; diff --git a/build/Release32/Pd_Gain-gui/Pd_Gain-gui.pdv b/build/Release32/Pd_Gain-gui/Pd_Gain-gui.pdv new file mode 100644 index 0000000..4f0c706 --- /dev/null +++ b/build/Release32/Pd_Gain-gui/Pd_Gain-gui.pdv @@ -0,0 +1,55 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, defaults to /pdvst/pd/bin) +PDPATH =D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Gain(gui).pd + +# Unique four character VST plugin ID +ID = pdgg + +# Whether this is a VSTi +SYNTH = FALSE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = TRUE + +# Dimensions of this custom GUI (in pixels) +GUIHEIGHT = 250 + +# Warning : with tcl/tk, don't try smaller values than 320 +GUIWIDTH = 320 + + +# Display Pd GUI or not +# (Hint : choose TRUE if you use some pd-window as custom gui) +DEBUG = TRUE + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +# Define another program +PROGRAM = Att -6db + +# Set first parameter value for this program +PARAMETER0 = 0.94 + + +# Define another program +PROGRAM = Mute + +# Set first parameter value for this program +PARAMETER0 = 0. diff --git a/build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pd b/build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pd new file mode 100644 index 0000000..0b97269 --- /dev/null +++ b/build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pd @@ -0,0 +1,35 @@ +#N canvas 0 265 595 358 12; +#X obj 78 87 adc~, f 6; +#X obj 73 241 loadbang; +#X msg 73 271 \; pd dsp 1 \;; +#X obj 77 162 dac~, f 6; +#X msg 142 52 \$1 30; +#X obj 142 87 line~; +#X obj 122 127 *~; +#X obj 78 127 *~; +#X obj 142 11 r gain; +#X obj 242 8 r rvstparameter0; +#X obj 242 235 * 100; +#X obj 242 263 dbtorms; +#X obj 242 290 s gain; +#X obj 300 225 s svstparameter0; +#X obj 277 75 vsl 50 128 0 1 0 0 empty empty empty 0 -9 0 10 -262144 +-1 -1 0 1; +#X msg 277 42 set \$1; +#X text 355 117 range is 0..1; +#X connect 0 0 7 0; +#X connect 0 1 6 0; +#X connect 1 0 2 0; +#X connect 4 0 5 0; +#X connect 5 0 6 1; +#X connect 5 0 7 1; +#X connect 6 0 3 1; +#X connect 7 0 3 0; +#X connect 8 0 4 0; +#X connect 9 0 10 0; +#X connect 9 0 15 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 14 0 13 0; +#X connect 14 0 10 0; +#X connect 15 0 14 0; diff --git a/build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pdv b/build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pdv new file mode 100644 index 0000000..1a63fc9 --- /dev/null +++ b/build/Release32/Pd_Gain-nogui/Pd_Gain-nogui.pdv @@ -0,0 +1,49 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, will search in \pdvst\pd\ +# then in \.pd\ +PDPATH = D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Gain(nogui).pd + +# Unique four character VST plugin ID +ID = pdgn + +# Whether this is a VSTi +SYNTH = FALSE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = FALSE + +# Display Pd GUI or not +DEBUG = FALSE + +# External libraries (comma delimited list, relative to pdvst/) +# ***OBSOLETE, use [declare] inside patch instead*** +#LIB = + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full Blast + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +#another program +PROGRAM = Muted + +PARAMETER0 = 0.0 + +#another program +PROGRAM = -6dB + +PARAMETER0 = 0.94 diff --git a/build/Release32/Pd_Gain/Pd_Gain.pd b/build/Release32/Pd_Gain/Pd_Gain.pd new file mode 100644 index 0000000..0b97269 --- /dev/null +++ b/build/Release32/Pd_Gain/Pd_Gain.pd @@ -0,0 +1,35 @@ +#N canvas 0 265 595 358 12; +#X obj 78 87 adc~, f 6; +#X obj 73 241 loadbang; +#X msg 73 271 \; pd dsp 1 \;; +#X obj 77 162 dac~, f 6; +#X msg 142 52 \$1 30; +#X obj 142 87 line~; +#X obj 122 127 *~; +#X obj 78 127 *~; +#X obj 142 11 r gain; +#X obj 242 8 r rvstparameter0; +#X obj 242 235 * 100; +#X obj 242 263 dbtorms; +#X obj 242 290 s gain; +#X obj 300 225 s svstparameter0; +#X obj 277 75 vsl 50 128 0 1 0 0 empty empty empty 0 -9 0 10 -262144 +-1 -1 0 1; +#X msg 277 42 set \$1; +#X text 355 117 range is 0..1; +#X connect 0 0 7 0; +#X connect 0 1 6 0; +#X connect 1 0 2 0; +#X connect 4 0 5 0; +#X connect 5 0 6 1; +#X connect 5 0 7 1; +#X connect 6 0 3 1; +#X connect 7 0 3 0; +#X connect 8 0 4 0; +#X connect 9 0 10 0; +#X connect 9 0 15 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 14 0 13 0; +#X connect 14 0 10 0; +#X connect 15 0 14 0; diff --git a/build/Release32/Pd_Gain/Pd_Gain.pdv b/build/Release32/Pd_Gain/Pd_Gain.pdv new file mode 100644 index 0000000..6ad9ad0 --- /dev/null +++ b/build/Release32/Pd_Gain/Pd_Gain.pdv @@ -0,0 +1,49 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, will search in \pdvst\pd\ +# then in \.pd\ +PDPATH = D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Gain.pd + +# Unique four character VST plugin ID +ID = pdga + +# Whether this is a VSTi +SYNTH = FALSE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = FALSE + +# Display Pd GUI or not +DEBUG = TRUE + +# External libraries (comma delimited list, relative to pdvst/) +# ***OBSOLETE, use [declare] inside patch instead*** +#LIB = + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full Blast + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +#another program +PROGRAM = Muted + +PARAMETER0 = 0.0 + +#another program +PROGRAM = -6dB + +PARAMETER0 = 0.94 diff --git a/build/Release32/Pd_Midi/Pd_Midi.pd b/build/Release32/Pd_Midi/Pd_Midi.pd new file mode 100644 index 0000000..43581a4 --- /dev/null +++ b/build/Release32/Pd_Midi/Pd_Midi.pd @@ -0,0 +1,170 @@ +#N canvas 0 0 346 350 12; +#X obj 5 5 cnv 15 300 210 empty gui-label empty 20 12 0 14 -233017 +-66577 0; +#X floatatom 13 41 5 0 0 1 vstTimeInfo.ppqPos vstTimeInfo.ppqPos - +, f 5; +#X floatatom 13 61 5 0 0 1 vstTimeInfo.tempo vstTimeInfo.tempo -, +f 5; +#X floatatom 13 81 5 0 0 1 vstTimeInfo.timeSigNumerator vstTimeInfo.timeSigNumerator +-, f 5; +#X floatatom 13 101 5 0 0 1 vstTimeInfo.timeSigDenominator vstTimeInfo.timeSigDenominator +-, f 5; +#N canvas 325 81 624 438 beep(vstTimeInfo) 0; +#X obj 84 333 dac~; +#X obj 158 250 line~; +#X obj 86 305 *~; +#X obj 73 279 osc~ 4000; +#X obj 152 0 r vstTimeInfo.ppqPos; +#X obj 180 104 int; +#X obj 201 154 change; +#X obj 197 187 t b; +#X obj 176 70 * 4; +#X obj 56 49 int; +#X obj 55 127 change; +#X obj 51 160 t b; +#X obj 137 36 t f f; +#X msg 61 194 3600; +#X msg 111 194 4000; +#X msg 189 216 0.03 \, 0 100; +#X connect 1 0 2 1; +#X connect 2 0 0 0; +#X connect 2 0 0 1; +#X connect 3 0 2 0; +#X connect 4 0 12 0; +#X connect 5 0 6 0; +#X connect 6 0 7 0; +#X connect 7 0 15 0; +#X connect 7 0 14 0; +#X connect 8 0 5 0; +#X connect 9 0 10 0; +#X connect 10 0 11 0; +#X connect 11 0 13 0; +#X connect 12 0 9 0; +#X connect 12 1 8 0; +#X connect 13 0 3 0; +#X connect 14 0 3 0; +#X connect 15 0 1 0; +#X restore 12 143 pd beep(vstTimeInfo); +#X text 15 17 those are the vstTimeInfo receivers; +#X floatatom 13 121 5 0 0 1 vstTimeInfo.flags vstTimeInfo.flags -, +f 5; +#N canvas 0 50 450 300 midi_stuff 0; +#X obj 71 63 notein; +#X obj 71 114 noteout; +#X obj 32 90 + 7; +#X text 45 186 see midi_objects help file; +#X floatatom 212 113 3 0 0 0 - - -, f 3; +#X obj 167 61 notein; +#X obj 167 87 stripnote; +#X floatatom 167 112 3 0 0 0 - - -, f 3; +#X text 342 57 MIDI OUT; +#X text 167 37 MIDI IN; +#X floatatom 290 112 3 0 0 0 - - -, f 3; +#X floatatom 260 111 3 0 0 0 - - -, f 3; +#X obj 260 86 ctlin; +#N canvas 0 50 484 446 midi 0; +#X obj 96 65 inlet; +#X obj 96 262 noteout; +#X floatatom 96 92 0 0 0 0 - - -; +#X obj 338 113 loadbang; +#X obj 96 184 metro; +#X obj 96 236 makenote; +#X floatatom 189 166 0 0 0 0 - - -; +#X obj 96 210 f; +#X floatatom 145 166 0 0 0 0 - - -; +#X floatatom 233 166 0 0 0 0 - - -; +#X floatatom 276 166 0 0 0 0 - - -; +#X msg 338 148 500; +#X msg 370 148 60; +#X msg 399 148 64; +#X msg 427 148 250; +#X text 144 145 rate; +#X text 187 145 pitch; +#X text 232 145 vel; +#X text 268 146 length; +#X obj 230 257 ctlout 1; +#X floatatom 230 228 0 0 0 0 - - -; +#X connect 0 0 2 0; +#X connect 2 0 4 0; +#X connect 3 0 11 0; +#X connect 3 0 12 0; +#X connect 3 0 13 0; +#X connect 3 0 14 0; +#X connect 4 0 7 0; +#X connect 5 0 1 0; +#X connect 5 1 1 1; +#X connect 6 0 7 1; +#X connect 7 0 5 0; +#X connect 8 0 4 1; +#X connect 9 0 5 1; +#X connect 10 0 5 2; +#X connect 11 0 8 0; +#X connect 12 0 6 0; +#X connect 13 0 9 0; +#X connect 14 0 10 0; +#X connect 20 0 19 0; +#X restore 342 107 pd midi; +#X obj 342 81 tgl 20 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 +; +#X obj 167 132 bng 20 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X obj 260 133 bng 20 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X connect 0 0 2 0; +#X connect 0 0 1 0; +#X connect 0 1 1 1; +#X connect 0 2 1 2; +#X connect 2 0 1 0; +#X connect 5 0 6 0; +#X connect 5 1 6 1; +#X connect 6 0 7 0; +#X connect 6 1 4 0; +#X connect 7 0 15 0; +#X connect 11 0 16 0; +#X connect 12 0 11 0; +#X connect 12 1 10 0; +#X connect 14 0 13 0; +#X restore 11 166 pd midi_stuff; +#N canvas 0 50 675 489 audio_stuff 0; +#X obj 104 322 adc~; +#X obj 104 401 dac~; +#X msg 47 286 \$1 30; +#X obj 47 311 line~; +#X obj 143 371 *~; +#X obj 104 371 *~; +#X obj 48 47 r rvstparameter0; +#X obj 48 229 * 100; +#X obj 47 253 dbtorms; +#X msg 79 81 set \$1; +#X obj 80 189 s svstparameter0; +#X obj 79 107 s level-rcv; +#X obj 80 144 r level-snd; +#X text 192 107 update pd-slider when parameter is changed from host +; +#X text 230 168 update host when parameter is changed from pd-slider +; +#X text 19 12 audio stuff example; +#X obj 315 283 loadbang; +#X msg 315 312 \; pd dsp 1 \;; +#X obj 222 217 vsl 60 128 0 1 0 0 level-snd level-rcv LEVEL 0 -9 0 +10 -262144 -1 -1 0 1; +#X connect 0 0 5 0; +#X connect 0 1 4 0; +#X connect 2 0 3 0; +#X connect 3 0 4 1; +#X connect 3 0 5 1; +#X connect 4 0 1 1; +#X connect 5 0 1 0; +#X connect 6 0 7 0; +#X connect 6 0 9 0; +#X connect 7 0 8 0; +#X connect 8 0 2 0; +#X connect 9 0 11 0; +#X connect 12 0 10 0; +#X connect 12 0 7 0; +#X connect 16 0 17 0; +#X restore 11 188 pd audio_stuff; +#X text 17 222 Whether you set pdvst as VST or VSTi \, it will always +receive midi-in and audio-in., f 39; +#X text 14 271 You can set an external midi device for midiin and midiout +(but not an external audio device), f 39; diff --git a/build/Release32/Pd_Midi/Pd_Midi.pdv b/build/Release32/Pd_Midi/Pd_Midi.pdv new file mode 100644 index 0000000..a02ccd9 --- /dev/null +++ b/build/Release32/Pd_Midi/Pd_Midi.pdv @@ -0,0 +1,52 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, defaults to /pdvst/pd/bin) +PDPATH = D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Midi.pd + +# Unique four character VST plugin ID +ID = pdmd + +# Whether this is a VSTi +SYNTH = TRUE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = FALSE + +# Display Pd GUI or not +# (Hint : choose TRUE if you use some pd-window as custom gui) +DEBUG = TRUE + +# External libraries (comma delimited list, relative to pdvst/) +#(obsolete, use [declare] object inside pd-patch instead) +#LIB = + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +# Define another program +PROGRAM = Att -6db + +# Set first parameter value for this program +PARAMETER0 = 0.94 + + +# Define another program +PROGRAM = Mute + +# Set first parameter value for this program +PARAMETER0 = 0. diff --git a/build/Release32/readme.txt b/build/Release32/readme.txt new file mode 100644 index 0000000..0e491a3 --- /dev/null +++ b/build/Release32/readme.txt @@ -0,0 +1 @@ +for use with 32 bits host \ No newline at end of file diff --git a/build/Release64/Pd_Gain-gui/Pd_Gain-gui.pd b/build/Release64/Pd_Gain-gui/Pd_Gain-gui.pd new file mode 100644 index 0000000..57c786a --- /dev/null +++ b/build/Release64/Pd_Gain-gui/Pd_Gain-gui.pd @@ -0,0 +1,166 @@ +#N canvas 313 -10 860 681 12; +#X obj 26 400 r rvstplugname; +#X msg 25 423 \; gui-label label \$1; +#X obj 37 22 r rvstopengui; +#X obj 24 86 select 0 1; +#X obj 22 227 delay 10; +#X obj 32 486 loadbang; +#X msg 31 512 1; +#X msg 68 513 0; +#N canvas 0 50 746 518 audio_stuff 0; +#X obj 104 322 adc~; +#X obj 104 401 dac~; +#X msg 47 286 \$1 30; +#X obj 47 311 line~; +#X obj 143 371 *~; +#X obj 104 371 *~; +#X obj 48 47 r rvstparameter0; +#X obj 48 229 * 100; +#X obj 47 253 dbtorms; +#X msg 79 81 set \$1; +#X obj 80 189 s svstparameter0; +#X obj 79 107 s level-rcv; +#X obj 80 144 r level-snd; +#X text 192 107 update pd-slider when parameter is changed from host +; +#X text 230 168 update host when parameter is changed from pd-slider +; +#X text 19 12 audio stuff example; +#X obj 315 283 loadbang; +#X msg 315 312 \; pd dsp 1 \;; +#X obj 368 463 tabwrite~ scope; +#X obj 375 433 metro 120; +#X obj 366 403 loadbang; +#X obj 280 413 *~ 5; +#X obj 280 438 clip~ -1 1; +#X connect 0 0 5 0; +#X connect 0 1 4 0; +#X connect 2 0 3 0; +#X connect 3 0 4 1; +#X connect 3 0 5 1; +#X connect 4 0 1 1; +#X connect 4 0 21 0; +#X connect 5 0 1 0; +#X connect 5 0 21 0; +#X connect 6 0 7 0; +#X connect 6 0 9 0; +#X connect 7 0 8 0; +#X connect 8 0 2 0; +#X connect 9 0 11 0; +#X connect 12 0 10 0; +#X connect 12 0 7 0; +#X connect 16 0 17 0; +#X connect 19 0 18 0; +#X connect 20 0 19 0; +#X connect 21 0 22 0; +#X connect 22 0 18 0; +#X restore 518 403 pd audio_stuff; +#X text 67 50 <- the host signals when gui has to be visible; +#X msg 75 195 vis 1; +#X obj 62 147 t b b; +#X text 124 197 display gui window; +#X text 186 79 0 = hide \, 1 = show; +#N canvas 0 50 450 300 hidePdConsole 0; +#X obj 78 48 inlet; +#X obj 76 149 hcs/sys_gui; +#X msg 75 117 wm withdraw .pdwindow; +#X msg 248 114 wm iconify .pdwindow; +#X obj 79 79 select 1 0; +#X connect 0 0 4 0; +#X connect 2 0 1 0; +#X connect 3 0 1 0; +#X connect 4 0 2 0; +#X connect 4 1 3 0; +#X restore 29 544 pd hidePdConsole; +#X text 163 545 (needs hcs/sys_gui external); +#N canvas 0 0 320 154 \$0-gui 0; +#X obj 5 5 cnv 15 300 190 empty gui-label empty 10 12 0 14 -233017 +-66577 0; +#X obj 13 53 vsl 60 128 0 1 0 0 level-snd level-rcv LEVEL 0 -9 0 10 +-262144 -1 -1 0 1; +#N canvas 0 50 450 250 (subpatch) 0; +#X array scope 300 float 1; +#A 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +#X coords 0 1 299 -1 120 70 1 0 0; +#X restore 138 57 graph; +#X obj 136 163 bng 15 250 50 0 \$0-show_parent empty show_parent_window +17 7 0 10 -262144 -1 -1; +#X text 101 145 click here to see main patch; +#X restore 517 361 pd \$0-gui; +#X obj 21 298 s pd-\$0-gui; +#X obj 29 653 s pd-Pd_Gain(gui).pd; +#X msg 29 624 vis 0; +#X obj 28 601 loadbang; +#X obj 104 602 r \$0-show_parent; +#X msg 104 627 vis 1; +#X obj 40 57 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X obj 58 113 delay 10; +#X msg 21 254 vis 0; +#X msg 206 252 vis 0; +#X obj 208 229 loadbang; +#X text 67 255 hide gui window; +#X obj 597 127 tgl 15 1 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X text 618 126 enable embedding (experimental); +#X text 110 300 (<- rename with the name of your gui window); +#X text 603 361 <- the actual gui window; +#N canvas 0 50 645 376 embedding_gui_into_host(experimental) 0; +#X obj 86 151 inlet; +#X obj 135 153 inlet; +#X obj 86 205 spigot; +#X obj 83 321 s guiName; +#X text 157 216 <- send to host the title of your gui window; +#X obj 84 268 f \$0; +#X msg 83 295 symbol \$1-gui; +#X obj 84 243 delay 10; +#X obj 154 180 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X text 90 40 In order to embed a puredata (tcl) gui window into host +\, the patch has to process values received from host (rvstopengui) +\, and send to it the title of the window to be embedded., f 61; +#X text 230 244 this may crash the tcl gui and thus puredata....; +#X msg 501 327 map 0 \, map 1; +#X connect 0 0 2 0; +#X connect 1 0 2 1; +#X connect 1 0 8 0; +#X connect 2 0 7 0; +#X connect 5 0 6 0; +#X connect 6 0 3 0; +#X connect 7 0 5 0; +#X restore 436 165 pd embedding_gui_into_host(experimental), f 23 +; +#X text 9 381 * Receiving plug & instance name from host; +#X text 14 349 *** OTHER TRICKS ***; +#X text 10 461 * Hiding pd-console window on startup; +#X text 13 573 * Hiding main patch (this one!) on startup; +#X text 545 13 PDVST; +#X connect 0 0 1 0; +#X connect 2 0 23 0; +#X connect 2 0 3 0; +#X connect 3 0 4 0; +#X connect 3 1 24 0; +#X connect 4 0 25 0; +#X connect 5 0 6 0; +#X connect 6 0 14 0; +#X connect 7 0 14 0; +#X connect 10 0 17 0; +#X connect 11 0 33 0; +#X connect 11 1 10 0; +#X connect 19 0 18 0; +#X connect 20 0 19 0; +#X connect 21 0 22 0; +#X connect 22 0 18 0; +#X connect 24 0 11 0; +#X connect 25 0 17 0; +#X connect 26 0 17 0; +#X connect 27 0 26 0; +#X connect 29 0 33 1; diff --git a/build/Release64/Pd_Gain-gui/Pd_Gain-gui.pdv b/build/Release64/Pd_Gain-gui/Pd_Gain-gui.pdv new file mode 100644 index 0000000..6df44c6 --- /dev/null +++ b/build/Release64/Pd_Gain-gui/Pd_Gain-gui.pdv @@ -0,0 +1,56 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, defaults to /pdvst/pd/bin) +# then in \.pd\ +#PDPATH =D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Gain-gui.pd + +# Unique four character VST plugin ID +ID = pdgg + +# Whether this is a VSTi +SYNTH = FALSE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = TRUE + +# Dimensions of this custom GUI (in pixels) +GUIHEIGHT = 250 + +# Warning : with tcl/tk, don't try smaller values than 320 +GUIWIDTH = 320 + + +# Display Pd GUI or not +# (Hint : choose TRUE if you use some pd-window as custom gui) +DEBUG = TRUE + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +# Define another program +PROGRAM = Att -6db + +# Set first parameter value for this program +PARAMETER0 = 0.94 + + +# Define another program +PROGRAM = Mute + +# Set first parameter value for this program +PARAMETER0 = 0. diff --git a/build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pd b/build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pd new file mode 100644 index 0000000..0b97269 --- /dev/null +++ b/build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pd @@ -0,0 +1,35 @@ +#N canvas 0 265 595 358 12; +#X obj 78 87 adc~, f 6; +#X obj 73 241 loadbang; +#X msg 73 271 \; pd dsp 1 \;; +#X obj 77 162 dac~, f 6; +#X msg 142 52 \$1 30; +#X obj 142 87 line~; +#X obj 122 127 *~; +#X obj 78 127 *~; +#X obj 142 11 r gain; +#X obj 242 8 r rvstparameter0; +#X obj 242 235 * 100; +#X obj 242 263 dbtorms; +#X obj 242 290 s gain; +#X obj 300 225 s svstparameter0; +#X obj 277 75 vsl 50 128 0 1 0 0 empty empty empty 0 -9 0 10 -262144 +-1 -1 0 1; +#X msg 277 42 set \$1; +#X text 355 117 range is 0..1; +#X connect 0 0 7 0; +#X connect 0 1 6 0; +#X connect 1 0 2 0; +#X connect 4 0 5 0; +#X connect 5 0 6 1; +#X connect 5 0 7 1; +#X connect 6 0 3 1; +#X connect 7 0 3 0; +#X connect 8 0 4 0; +#X connect 9 0 10 0; +#X connect 9 0 15 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 14 0 13 0; +#X connect 14 0 10 0; +#X connect 15 0 14 0; diff --git a/build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pdv b/build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pdv new file mode 100644 index 0000000..84e4099 --- /dev/null +++ b/build/Release64/Pd_Gain-nogui/Pd_Gain-nogui.pdv @@ -0,0 +1,49 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, will search in \pdvst\pd\ +# then in \.pd\ +#PDPATH = D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Gain-nogui.pd + +# Unique four character VST plugin ID +ID = pdgn + +# Whether this is a VSTi +SYNTH = FALSE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = FALSE + +# Display Pd GUI or not +DEBUG = FALSE + +# External libraries (comma delimited list, relative to pdvst/) +# ***OBSOLETE, use [declare] inside patch instead*** +#LIB = + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full Blast + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +#another program +PROGRAM = Muted + +PARAMETER0 = 0.0 + +#another program +PROGRAM = -6dB + +PARAMETER0 = 0.94 diff --git a/build/Release64/Pd_Gain/Pd_Gain.pd b/build/Release64/Pd_Gain/Pd_Gain.pd new file mode 100644 index 0000000..0b97269 --- /dev/null +++ b/build/Release64/Pd_Gain/Pd_Gain.pd @@ -0,0 +1,35 @@ +#N canvas 0 265 595 358 12; +#X obj 78 87 adc~, f 6; +#X obj 73 241 loadbang; +#X msg 73 271 \; pd dsp 1 \;; +#X obj 77 162 dac~, f 6; +#X msg 142 52 \$1 30; +#X obj 142 87 line~; +#X obj 122 127 *~; +#X obj 78 127 *~; +#X obj 142 11 r gain; +#X obj 242 8 r rvstparameter0; +#X obj 242 235 * 100; +#X obj 242 263 dbtorms; +#X obj 242 290 s gain; +#X obj 300 225 s svstparameter0; +#X obj 277 75 vsl 50 128 0 1 0 0 empty empty empty 0 -9 0 10 -262144 +-1 -1 0 1; +#X msg 277 42 set \$1; +#X text 355 117 range is 0..1; +#X connect 0 0 7 0; +#X connect 0 1 6 0; +#X connect 1 0 2 0; +#X connect 4 0 5 0; +#X connect 5 0 6 1; +#X connect 5 0 7 1; +#X connect 6 0 3 1; +#X connect 7 0 3 0; +#X connect 8 0 4 0; +#X connect 9 0 10 0; +#X connect 9 0 15 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 14 0 13 0; +#X connect 14 0 10 0; +#X connect 15 0 14 0; diff --git a/build/Release64/Pd_Gain/Pd_Gain.pdv b/build/Release64/Pd_Gain/Pd_Gain.pdv new file mode 100644 index 0000000..cebb542 --- /dev/null +++ b/build/Release64/Pd_Gain/Pd_Gain.pdv @@ -0,0 +1,49 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, will search in \pdvst\pd\ +# then in \.pd\ +#PDPATH = D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Gain.pd + +# Unique four character VST plugin ID +ID = pdga + +# Whether this is a VSTi +SYNTH = FALSE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = FALSE + +# Display Pd GUI or not +DEBUG = TRUE + +# External libraries (comma delimited list, relative to pdvst/) +# ***OBSOLETE, use [declare] inside patch instead*** +#LIB = + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full Blast + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +#another program +PROGRAM = Muted + +PARAMETER0 = 0.0 + +#another program +PROGRAM = -6dB + +PARAMETER0 = 0.94 diff --git a/build/Release64/Pd_Midi/Pd_Midi.pd b/build/Release64/Pd_Midi/Pd_Midi.pd new file mode 100644 index 0000000..43581a4 --- /dev/null +++ b/build/Release64/Pd_Midi/Pd_Midi.pd @@ -0,0 +1,170 @@ +#N canvas 0 0 346 350 12; +#X obj 5 5 cnv 15 300 210 empty gui-label empty 20 12 0 14 -233017 +-66577 0; +#X floatatom 13 41 5 0 0 1 vstTimeInfo.ppqPos vstTimeInfo.ppqPos - +, f 5; +#X floatatom 13 61 5 0 0 1 vstTimeInfo.tempo vstTimeInfo.tempo -, +f 5; +#X floatatom 13 81 5 0 0 1 vstTimeInfo.timeSigNumerator vstTimeInfo.timeSigNumerator +-, f 5; +#X floatatom 13 101 5 0 0 1 vstTimeInfo.timeSigDenominator vstTimeInfo.timeSigDenominator +-, f 5; +#N canvas 325 81 624 438 beep(vstTimeInfo) 0; +#X obj 84 333 dac~; +#X obj 158 250 line~; +#X obj 86 305 *~; +#X obj 73 279 osc~ 4000; +#X obj 152 0 r vstTimeInfo.ppqPos; +#X obj 180 104 int; +#X obj 201 154 change; +#X obj 197 187 t b; +#X obj 176 70 * 4; +#X obj 56 49 int; +#X obj 55 127 change; +#X obj 51 160 t b; +#X obj 137 36 t f f; +#X msg 61 194 3600; +#X msg 111 194 4000; +#X msg 189 216 0.03 \, 0 100; +#X connect 1 0 2 1; +#X connect 2 0 0 0; +#X connect 2 0 0 1; +#X connect 3 0 2 0; +#X connect 4 0 12 0; +#X connect 5 0 6 0; +#X connect 6 0 7 0; +#X connect 7 0 15 0; +#X connect 7 0 14 0; +#X connect 8 0 5 0; +#X connect 9 0 10 0; +#X connect 10 0 11 0; +#X connect 11 0 13 0; +#X connect 12 0 9 0; +#X connect 12 1 8 0; +#X connect 13 0 3 0; +#X connect 14 0 3 0; +#X connect 15 0 1 0; +#X restore 12 143 pd beep(vstTimeInfo); +#X text 15 17 those are the vstTimeInfo receivers; +#X floatatom 13 121 5 0 0 1 vstTimeInfo.flags vstTimeInfo.flags -, +f 5; +#N canvas 0 50 450 300 midi_stuff 0; +#X obj 71 63 notein; +#X obj 71 114 noteout; +#X obj 32 90 + 7; +#X text 45 186 see midi_objects help file; +#X floatatom 212 113 3 0 0 0 - - -, f 3; +#X obj 167 61 notein; +#X obj 167 87 stripnote; +#X floatatom 167 112 3 0 0 0 - - -, f 3; +#X text 342 57 MIDI OUT; +#X text 167 37 MIDI IN; +#X floatatom 290 112 3 0 0 0 - - -, f 3; +#X floatatom 260 111 3 0 0 0 - - -, f 3; +#X obj 260 86 ctlin; +#N canvas 0 50 484 446 midi 0; +#X obj 96 65 inlet; +#X obj 96 262 noteout; +#X floatatom 96 92 0 0 0 0 - - -; +#X obj 338 113 loadbang; +#X obj 96 184 metro; +#X obj 96 236 makenote; +#X floatatom 189 166 0 0 0 0 - - -; +#X obj 96 210 f; +#X floatatom 145 166 0 0 0 0 - - -; +#X floatatom 233 166 0 0 0 0 - - -; +#X floatatom 276 166 0 0 0 0 - - -; +#X msg 338 148 500; +#X msg 370 148 60; +#X msg 399 148 64; +#X msg 427 148 250; +#X text 144 145 rate; +#X text 187 145 pitch; +#X text 232 145 vel; +#X text 268 146 length; +#X obj 230 257 ctlout 1; +#X floatatom 230 228 0 0 0 0 - - -; +#X connect 0 0 2 0; +#X connect 2 0 4 0; +#X connect 3 0 11 0; +#X connect 3 0 12 0; +#X connect 3 0 13 0; +#X connect 3 0 14 0; +#X connect 4 0 7 0; +#X connect 5 0 1 0; +#X connect 5 1 1 1; +#X connect 6 0 7 1; +#X connect 7 0 5 0; +#X connect 8 0 4 1; +#X connect 9 0 5 1; +#X connect 10 0 5 2; +#X connect 11 0 8 0; +#X connect 12 0 6 0; +#X connect 13 0 9 0; +#X connect 14 0 10 0; +#X connect 20 0 19 0; +#X restore 342 107 pd midi; +#X obj 342 81 tgl 20 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 +; +#X obj 167 132 bng 20 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X obj 260 133 bng 20 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X connect 0 0 2 0; +#X connect 0 0 1 0; +#X connect 0 1 1 1; +#X connect 0 2 1 2; +#X connect 2 0 1 0; +#X connect 5 0 6 0; +#X connect 5 1 6 1; +#X connect 6 0 7 0; +#X connect 6 1 4 0; +#X connect 7 0 15 0; +#X connect 11 0 16 0; +#X connect 12 0 11 0; +#X connect 12 1 10 0; +#X connect 14 0 13 0; +#X restore 11 166 pd midi_stuff; +#N canvas 0 50 675 489 audio_stuff 0; +#X obj 104 322 adc~; +#X obj 104 401 dac~; +#X msg 47 286 \$1 30; +#X obj 47 311 line~; +#X obj 143 371 *~; +#X obj 104 371 *~; +#X obj 48 47 r rvstparameter0; +#X obj 48 229 * 100; +#X obj 47 253 dbtorms; +#X msg 79 81 set \$1; +#X obj 80 189 s svstparameter0; +#X obj 79 107 s level-rcv; +#X obj 80 144 r level-snd; +#X text 192 107 update pd-slider when parameter is changed from host +; +#X text 230 168 update host when parameter is changed from pd-slider +; +#X text 19 12 audio stuff example; +#X obj 315 283 loadbang; +#X msg 315 312 \; pd dsp 1 \;; +#X obj 222 217 vsl 60 128 0 1 0 0 level-snd level-rcv LEVEL 0 -9 0 +10 -262144 -1 -1 0 1; +#X connect 0 0 5 0; +#X connect 0 1 4 0; +#X connect 2 0 3 0; +#X connect 3 0 4 1; +#X connect 3 0 5 1; +#X connect 4 0 1 1; +#X connect 5 0 1 0; +#X connect 6 0 7 0; +#X connect 6 0 9 0; +#X connect 7 0 8 0; +#X connect 8 0 2 0; +#X connect 9 0 11 0; +#X connect 12 0 10 0; +#X connect 12 0 7 0; +#X connect 16 0 17 0; +#X restore 11 188 pd audio_stuff; +#X text 17 222 Whether you set pdvst as VST or VSTi \, it will always +receive midi-in and audio-in., f 39; +#X text 14 271 You can set an external midi device for midiin and midiout +(but not an external audio device), f 39; diff --git a/build/Release64/Pd_Midi/Pd_Midi.pdv b/build/Release64/Pd_Midi/Pd_Midi.pdv new file mode 100644 index 0000000..e25994b --- /dev/null +++ b/build/Release64/Pd_Midi/Pd_Midi.pdv @@ -0,0 +1,53 @@ +# Number of audio input and output channels +CHANNELS = 2 + +# installation directory of puredata (optional) +# If non specified, defaults to /pdvst/pd/bin) +# then in \.pd\ +#PDPATH = D:\Programs\pd-0.48-1-test\ + +# Main Pd patch of the plugin +MAIN = Pd_Midi.pd + +# Unique four character VST plugin ID +ID = pdmd + +# Whether this is a VSTi +SYNTH = TRUE + +# Whether there is a custom GUI (e.g. GrIPD) +CUSTOMGUI = FALSE + +# Display Pd GUI or not +# (Hint : choose TRUE if you use some pd-window as custom gui) +DEBUG = TRUE + +# External libraries (comma delimited list, relative to pdvst/) +#(obsolete, use [declare] object inside pd-patch instead) +#LIB = + +# Number of VST parameters (up to 128) +PARAMETERS = 1 + +# Name of first VST parameter +# used when CUSTOMGUI is false or VST host doesn't support custom editors +NAMEPARAMETER0 = Level + +# Define a program (up to 128) +PROGRAM = Full + +# Set first parameter value for this program +PARAMETER0 = 1.0 + +# Define another program +PROGRAM = Att -6db + +# Set first parameter value for this program +PARAMETER0 = 0.94 + + +# Define another program +PROGRAM = Mute + +# Set first parameter value for this program +PARAMETER0 = 0. diff --git a/build/Release64/readme.txt b/build/Release64/readme.txt new file mode 100644 index 0000000..8052ed5 --- /dev/null +++ b/build/Release64/readme.txt @@ -0,0 +1 @@ +for use with 64 bits host \ No newline at end of file diff --git a/vst-scheduler/makefile b/vst-scheduler/makefile new file mode 100644 index 0000000..d1e74ad --- /dev/null +++ b/vst-scheduler/makefile @@ -0,0 +1,20 @@ +# Compile with MinGW. +# You can call this makefile with: +# make PDDIR= +# or you can specify it below: + +PDDIR= + +WINARCH := $(shell $(CC) -dumpmachine) + +ifeq (i686% , $(WINARCH)) + arch = 32 +else + arch = 64 +endif + +ALL: vstschedlib.c + gcc -Wall -I$(PDDIR)src -I../vst-template vstschedlib.c -static-libgcc \ + -shared -L$(PDDIR)bin -l:pd.dll -o vstschedlib.dll + strip vstschedlib.dll + cp vstschedlib.dll ../build/pd-scheduler$(arch)/vstschedlib.dll \ No newline at end of file diff --git a/vst-scheduler/vstschedlib.c b/vst-scheduler/vstschedlib.c new file mode 100644 index 0000000..4c34557 --- /dev/null +++ b/vst-scheduler/vstschedlib.c @@ -0,0 +1,730 @@ +/* PdVst v0.0.2 - VST - Pd bridging plugin +** Copyright (C) 2004 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#define _WIN32_WINDOWS 0x410 +#include +#include +#include +#include "m_pd.h" +#include "s_stuff.h" +#include "pdvstTransfer.h" +#define MAXARGS 1024 +#define MAXSTRLEN 1024 +#define TIMEUNITPERSEC (32.*441000.) + +#define kVstTransportChanged 1 +#define kVstTransportPlaying 2 + +#define kVstTransportRecording 8 +#ifdef VSTMIDIOUTENABLE + EXTERN int midi_outhead; + int _midi_outtail=0; // _midi_outtail defined locally + typedef struct _midiqelem + { + double q_time; + int q_portno; + unsigned char q_onebyte; + unsigned char q_byte1; + unsigned char q_byte2; + unsigned char q_byte3; + } t_midiqelem; + + #ifndef MIDIQSIZE + #define MIDIQSIZE 1024 + #endif /*MIDIQSIZE */ + + EXTERN t_midiqelem midi_outqueue[MIDIQSIZE]; + //EXTERN int msw_nmidiout; + int msw_nmidiout=0; + +#endif // VSTMIDIOUTENABLE + + +typedef struct _vstParameterReceiver +{ + t_object x_obj; + t_symbol *x_sym; +}t_vstParameterReceiver; + +typedef struct _vstGuiNameReceiver +{ + t_object x_obj; +}t_vstGuiNameReceiver; + +t_vstGuiNameReceiver *vstGuiNameReceiver; + +t_vstParameterReceiver *vstParameterReceivers[MAXPARAMETERS]; + +t_class *vstParameterReceiver_class; +t_class *vstGuiNameReceiver_class; + +char *pdvstTransferMutexName, + *pdvstTransferFileMapName, + *vstProcEventName, + *pdProcEventName; +pdvstTransferData *pdvstData; +HANDLE vstHostProcess, + pdvstTransferMutex, + pdvstTransferFileMap, + vstProcEvent, + pdProcEvent; + pdvstTimeInfo timeInfo; + +int tokenizeCommandLineString(char *clString, char **tokens) +{ + int i, charCount = 0; + int tokCount= 0; + int quoteOpen = 0; + + for (i = 0; i < (signed int)strlen(clString); i++) + { + if (clString[i] == '"') + { + quoteOpen = !quoteOpen; + } + else if (clString[i] == ' ' && !quoteOpen) + { + tokens[tokCount][charCount] = 0; + tokCount++; + charCount = 0; + } + else + { + tokens[tokCount][charCount] = clString[i]; + charCount++; + } + } + tokens[tokCount][charCount] = 0; + tokCount++; + return tokCount; +} + +void parseArgs(int argc, char **argv) +{ + int vstHostProcessId; + + while ((argc > 0) && (**argv == '-')) + { + if (strcmp(*argv, "-vsthostid") == 0) + { + vstHostProcessId = atoi(argv[1]); + vstHostProcess = OpenProcess(PROCESS_ALL_ACCESS, + FALSE, + vstHostProcessId); + if (vstHostProcess == NULL) + { + exit(1); + } + argc -= 2; + argv += 2; + } + if (strcmp(*argv, "-mutexname") == 0) + { + pdvstTransferMutexName = argv[1]; + argc -= 2; + argv += 2; + } + if (strcmp(*argv, "-filemapname") == 0) + { + pdvstTransferFileMapName = argv[1]; + argc -= 2; + argv += 2; + } + if (strcmp(*argv, "-vstproceventname") == 0) + { + vstProcEventName = argv[1]; + argc -= 2; + argv += 2; + } + if (strcmp(*argv, "-pdproceventname") == 0) + { + pdProcEventName = argv[1]; + argc -= 2; + argv += 2; + } + else + { + argc--; + argv++; + } + } +} + +int setPdvstGuiState(int state) +{ + t_symbol *tempSym; + + tempSym = gensym("rvstopengui"); + if (tempSym->s_thing) + { + pd_float(tempSym->s_thing, (float)state); + return 1; + } + else + return 0; +} + + +int setPdvstPlugName(char* instanceName) +{ + t_symbol *tempSym; + tempSym = gensym("rvstplugname"); + if (tempSym->s_thing) + { + pd_symbol(tempSym->s_thing, gensym(instanceName)); + return 1; + } + else + return 0; +} + + +int setPdvstFloatParameter(int index, float value) +{ + t_symbol *tempSym; + char string[1024]; + + sprintf(string, "rvstparameter%d", index); + tempSym = gensym(string); + if (tempSym->s_thing) + { + pd_float(tempSym->s_thing, value); + return 1; + } + else + { + return 0; + } +} + +void sendPdVstFloatParameter(t_vstParameterReceiver *x, t_float floatValue) +{ + int index; + + index = atoi(x->x_sym->s_name + strlen("svstParameter")); + WaitForSingleObject(pdvstTransferMutex, INFINITE); + pdvstData->vstParameters[index].type = FLOAT_TYPE; + pdvstData->vstParameters[index].direction = PD_SEND; + pdvstData->vstParameters[index].updated = 1; + pdvstData->vstParameters[index].value.floatData = floatValue; + ReleaseMutex(pdvstTransferMutex); +} + +void sendPdVstGuiName(t_vstGuiNameReceiver *x, t_symbol *symbolValue) +{ + WaitForSingleObject(pdvstTransferMutex, INFINITE); + pdvstData->guiName.type = STRING_TYPE; + pdvstData->guiName.direction = PD_SEND; + pdvstData->guiName.updated = 1; + strcpy(pdvstData->guiName.value.stringData,symbolValue->s_name); + + ReleaseMutex(pdvstTransferMutex); + +} + +void makePdvstParameterReceivers() +{ + int i; + char string[1024]; + + for (i = 0; i < MAXPARAMETERS; i++) + { + vstParameterReceivers[i] = (t_vstParameterReceiver *)pd_new(vstParameterReceiver_class); + sprintf(string, "svstparameter%d", i); + vstParameterReceivers[i]->x_sym = gensym(string); + pd_bind(&vstParameterReceivers[i]->x_obj.ob_pd, gensym(string)); + } +} + +void makePdvstGuiNameReceiver() +{ + vstGuiNameReceiver = (t_vstGuiNameReceiver *)pd_new(vstGuiNameReceiver_class); + pd_bind(&vstGuiNameReceiver->x_obj.ob_pd, gensym("guiName")); + +} + + + +void send_dacs(void) +{ + int i, j, sampleCount, nChannels, blockSize; + t_sample *soundin, *soundout; + + soundin = get_sys_soundin(); + soundout = get_sys_soundout(); + nChannels = pdvstData->nChannels; + blockSize = pdvstData->blockSize; + if (blockSize == *(get_sys_schedblocksize())) + { + sampleCount = 0; + for (i = 0; i < nChannels; i++) + { + for (j = 0; j < blockSize; j++) + { + soundin[sampleCount] = pdvstData->samples[i][j]; + pdvstData->samples[i][j] = soundout[sampleCount]; + soundout[sampleCount] = 0; + sampleCount++; + } + } + } +} + +void scheduler_tick( void) +{ +//l sys_addhist(0); + send_dacs(); +//l sys_setmiditimediff(0, 1e-6 * *(get_sys_schedadvance())); +//l sys_addhist(1); + /// { JYG + //sched_tick(*(get_sys_time()) + *(get_sys_time_per_dsp_tick())); + sched_tick(); + /// JYG } +//l sys_addhist(2); + sys_pollmidiqueue(); + sys_pollgui(); +//l sys_addhist(3); +} +/* +int HFClock() +{ + LARGE_INTEGER freq, now; + + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&now); + return (int)((now.QuadPart * 1000) / freq.QuadPart); +} +*/ + +int scheduler() +{ + int i, + blockTime, + + active = 1; + DWORD vstHostProcessStatus = 0; + + + vstParameterReceiver_class = class_new(gensym("vstParameterReceiver"), + 0, + 0, + sizeof(t_vstParameterReceiver), + 0, + 0); + + class_addfloat(vstParameterReceiver_class, (t_method)sendPdVstFloatParameter); + makePdvstParameterReceivers(); + + vstGuiNameReceiver_class = class_new(gensym("vstGuiNameReceiver"), + 0, + 0, + sizeof(t_vstGuiNameReceiver), + 0, + 0); + + class_addsymbol(vstGuiNameReceiver_class,(t_method)sendPdVstGuiName); + makePdvstGuiNameReceiver(); + + *(get_sys_time_per_dsp_tick()) = (TIMEUNITPERSEC) * \ + ((double)*(get_sys_schedblocksize())) / \ + *(get_sys_dacsr()); +//l sys_clearhist(); + //if (*(get_sys_sleepgrain()) < 1000) // JYG + if (*(get_sys_sleepgrain()) < 100) + { + *(get_sys_sleepgrain()) = *(get_sys_schedadvance()) / 4; + } + if (*(get_sys_sleepgrain()) < 100) + { + *(get_sys_sleepgrain()) = 100; + } + else if (*(get_sys_sleepgrain()) > 5000) + { + *(get_sys_sleepgrain()) = 5000; + } + sys_initmidiqueue(); + + #ifdef VSTMIDIOUTENABLE + pdvstData->midiOutQueueSize=0; + #endif // VSTMIDIOUTENABLE + while (active) + { + WaitForSingleObject(pdvstTransferMutex, INFINITE); + active = pdvstData->active; + // check sample rate + if (pdvstData->sampleRate != (int)sys_getsr()) + { + post("check samplerate"); + sys_setchsr(pdvstData->nChannels, + pdvstData->nChannels, + pdvstData->sampleRate); + } + // check for vstParameter changed + if (pdvstData->guiState.direction == PD_RECEIVE && \ + pdvstData->guiState.updated) + { + if(setPdvstGuiState((int)pdvstData->guiState.value.floatData)) + pdvstData->guiState.updated=0; + } + // JYG { check for vstplug instance name + if (pdvstData->plugName.direction == PD_RECEIVE && \ + pdvstData->plugName.updated) + { + if (setPdvstPlugName((char*)pdvstData->plugName.value.stringData)) + pdvstData->plugName.updated=0; + } + + if (pdvstData->hostTimeInfo.updated) + { + pdvstData->hostTimeInfo.updated=0; + t_symbol *tempSym; + + if (timeInfo.flags!=pdvstData->hostTimeInfo.flags) + { + timeInfo.flags=pdvstData->hostTimeInfo.flags; + + tempSym = gensym("vstTimeInfo.flags"); + if (tempSym->s_thing) + { + pd_float(tempSym->s_thing, (float)timeInfo.flags); + } + else + { + timeInfo.flags=0; + pdvstData->hostTimeInfo.updated=1; // keep flag as updated + } + + } + + if ((timeInfo.flags&(kVstTransportChanged|kVstTransportPlaying|kVstTransportRecording))||(timeInfo.ppqPos!=(float)pdvstData->hostTimeInfo.ppqPos)) + { + timeInfo.ppqPos=(float)pdvstData->hostTimeInfo.ppqPos; + + tempSym = gensym("vstTimeInfo.ppqPos"); + if (tempSym->s_thing) + { + pd_float(tempSym->s_thing, timeInfo.ppqPos); + } + else + { + timeInfo.ppqPos=0.; + pdvstData->hostTimeInfo.updated=1; // keep flag as updated + } + } + if ((timeInfo.flags&kVstTransportChanged)|(timeInfo.tempo!=(float)pdvstData->hostTimeInfo.tempo)) + { + timeInfo.tempo=(float)pdvstData->hostTimeInfo.tempo; + + tempSym = gensym("vstTimeInfo.tempo"); + if (tempSym->s_thing) + { + pd_float(tempSym->s_thing, timeInfo.tempo); + } + else + { + timeInfo.tempo=0.; + pdvstData->hostTimeInfo.updated=1; // keep flag as updated + } + } + + if ((timeInfo.flags&kVstTransportChanged)|timeInfo.timeSigNumerator!=pdvstData->hostTimeInfo.timeSigNumerator) + { + timeInfo.timeSigNumerator=pdvstData->hostTimeInfo.timeSigNumerator; + + tempSym = gensym("vstTimeInfo.timeSigNumerator"); + if (tempSym->s_thing) + { + pd_float(tempSym->s_thing, (float)timeInfo.timeSigNumerator); + } + else + { + timeInfo.timeSigNumerator=0; + pdvstData->hostTimeInfo.updated=1; // keep flag as updated + } + } + if ((timeInfo.flags&kVstTransportChanged)| timeInfo.timeSigDenominator!=pdvstData->hostTimeInfo.timeSigDenominator) + { + timeInfo.timeSigDenominator=pdvstData->hostTimeInfo.timeSigDenominator; + + tempSym = gensym("vstTimeInfo.timeSigDenominator"); + if (tempSym->s_thing) + { + pd_float(tempSym->s_thing, (float)timeInfo.timeSigDenominator); + } + else + { + timeInfo.timeSigDenominator=0; + pdvstData->hostTimeInfo.updated=1; // keep flag as updated + } + } + + } + + + + // JYG } + for (i = 0; i < pdvstData->nParameters; i++) + { + if (pdvstData->vstParameters[i].direction == PD_RECEIVE && \ + pdvstData->vstParameters[i].updated) + { + if (pdvstData->vstParameters[i].type == FLOAT_TYPE) + { + if (setPdvstFloatParameter(i, + pdvstData->vstParameters[i].value.floatData)) + { + pdvstData->vstParameters[i].updated = 0; + } + } + } + } + // check for new midi-in message (VSTi) + if (pdvstData->midiQueueUpdated) + { + for (i = 0; i < pdvstData->midiQueueSize; i++) + { + if (pdvstData->midiQueue[i].messageType == NOTE_ON) + { + inmidi_noteon(0, + pdvstData->midiQueue[i].channelNumber, + pdvstData->midiQueue[i].dataByte1, + pdvstData->midiQueue[i].dataByte2); + } + else if (pdvstData->midiQueue[i].messageType == NOTE_OFF) + { + inmidi_noteon(0, + pdvstData->midiQueue[i].channelNumber, + pdvstData->midiQueue[i].dataByte1, + 0); + } + else if (pdvstData->midiQueue[i].messageType == CONTROLLER_CHANGE) + { + inmidi_controlchange(0, + pdvstData->midiQueue[i].channelNumber, + pdvstData->midiQueue[i].dataByte1, + pdvstData->midiQueue[i].dataByte2); + } + else if (pdvstData->midiQueue[i].messageType == PROGRAM_CHANGE) + { + inmidi_programchange(0, + pdvstData->midiQueue[i].channelNumber, + pdvstData->midiQueue[i].dataByte1); + } + else if (pdvstData->midiQueue[i].messageType == PITCH_BEND) + { + int value = (((int)pdvstData->midiQueue[i].dataByte2) * 16) + \ + (int)pdvstData->midiQueue[i].dataByte1; + + inmidi_pitchbend(0, + pdvstData->midiQueue[i].channelNumber, + value); + } + else if (pdvstData->midiQueue[i].messageType == CHANNEL_PRESSURE) + { + inmidi_aftertouch(0, + pdvstData->midiQueue[i].channelNumber, + pdvstData->midiQueue[i].dataByte1); + } + else if (pdvstData->midiQueue[i].messageType == KEY_PRESSURE) + { + inmidi_polyaftertouch(0, + pdvstData->midiQueue[i].channelNumber, + pdvstData->midiQueue[i].dataByte1, + pdvstData->midiQueue[i].dataByte2); + } + else if (pdvstData->midiQueue[i].messageType == OTHER) + { + // FIXME: what to do? + } + else + { + post("pdvstData->midiQueue error"); // FIXME: error? + } + } + pdvstData->midiQueueSize = 0; + pdvstData->midiQueueUpdated = 0; + } + + /// flush vstmidi out messages here +#ifdef VSTMIDIOUTENABLE + if (msw_nmidiout==0) + { + int i=pdvstData->midiOutQueueSize; // si la midiOutQueue n'a pas été vidée, rajouter des éléments à la fin de celle-ci + while (midi_outhead != _midi_outtail) + { + int statusType = midi_outqueue[_midi_outtail].q_byte1 & 0xF0; + int statusChannel = midi_outqueue[_midi_outtail].q_byte1 & 0x0F; + + // faut il gérer midi_outqueue[_midi_outtail].q_onebyte ? + + ///copie de la pile midi_outqueue dans la pile vst midiOutQueue + pdvstData->midiOutQueue[i].channelNumber= statusChannel; + pdvstData->midiOutQueue[i].statusByte = midi_outqueue[_midi_outtail].q_byte1; + pdvstData->midiOutQueue[i].dataByte1= midi_outqueue[_midi_outtail].q_byte2; + pdvstData->midiOutQueue[i].dataByte2= midi_outqueue[_midi_outtail].q_byte3; + + if (statusType == 0x90) + if (midi_outqueue[_midi_outtail].q_byte3==0) + // note off + { + pdvstData->midiOutQueue[i].messageType = NOTE_OFF; + pdvstData->midiOutQueue[i].statusByte = statusChannel|0x80; + // post("note_off[%d] : %d",i,midi_outqueue[_midi_outtail].q_byte2); + + } + + else + { + // note on + pdvstData->midiOutQueue[i].messageType = NOTE_ON; + //post("note_on[%d] : %d",i,midi_outqueue[_midi_outtail].q_byte2); + + } + else if (statusType == 0xA0) + // key pressure + pdvstData->midiOutQueue[i].messageType = KEY_PRESSURE; + else if (statusType == 0xB0) + // controller change + pdvstData->midiOutQueue[i].messageType = CONTROLLER_CHANGE; + else if (statusType == 0xC0) + // program change + pdvstData->midiOutQueue[i].messageType = PROGRAM_CHANGE; + else if (statusType == 0xD0) + // channel pressure + pdvstData->midiOutQueue[i].messageType = CHANNEL_PRESSURE; + else if (statusType == 0xE0) + // pitch bend + pdvstData->midiOutQueue[i].messageType = PITCH_BEND; + else + // something else + pdvstData->midiOutQueue[i].messageType = OTHER; + + + _midi_outtail = (_midi_outtail + 1 == MIDIQSIZE ? 0 : _midi_outtail + 1); + i = i + 1; + if (i>= MAXMIDIOUTQUEUESIZE) + break; + + } + if (i>0) + { + pdvstData->midiOutQueueSize=i; + pdvstData->midiOutQueueUpdated=1; + } + else + { + pdvstData->midiOutQueueSize=0; + pdvstData->midiOutQueueUpdated=0; + } + } +#endif // VSTMIDIOUTENABLE + + // run at approx. real-time + blockTime = (int)((float)(pdvstData->blockSize) / \ + (float)pdvstData->sampleRate * 1000.0); + if (blockTime < 1) + { + blockTime = 1; + } + if (pdvstData->syncToVst) + { + ReleaseMutex(pdvstTransferMutex); + if (WaitForSingleObject(vstProcEvent, 1000) == WAIT_TIMEOUT) + { + // we have probably lost sync by now (1 sec) + WaitForSingleObject(pdvstTransferMutex, 100); + pdvstData->syncToVst = 0; + ReleaseMutex(pdvstTransferMutex); + } + ResetEvent(vstProcEvent); + scheduler_tick(); + SetEvent(pdProcEvent); + } + else + { + ReleaseMutex(pdvstTransferMutex); + scheduler_tick(); + Sleep(blockTime); + } + GetExitCodeProcess(vstHostProcess, &vstHostProcessStatus); + if (vstHostProcessStatus != STILL_ACTIVE) + { + active = 0; + } + } + return 1; +} + +int pd_extern_sched(char *flags) +{ + int i, argc; + char *argv[MAXARGS]; +//l sys_audioapi = API_NONE; + + + t_audiosettings as; + + sys_get_audio_settings(&as); + as.a_api = API_NONE; + sys_set_audio_settings(&as); + +// + for (i = 0; i < MAXARGS; i++) + { + argv[i] = (char *)malloc(MAXSTRLEN * sizeof(char)); + } + argc = tokenizeCommandLineString(flags, argv); + parseArgs(argc, argv); + pdvstTransferMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, pdvstTransferMutexName); + vstProcEvent = OpenEvent(EVENT_ALL_ACCESS, 0, vstProcEventName); + pdProcEvent = OpenEvent(EVENT_ALL_ACCESS, 0, pdProcEventName); + pdvstTransferFileMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, + 0, + pdvstTransferFileMapName); + pdvstData = (pdvstTransferData *)MapViewOfFile(pdvstTransferFileMap, + FILE_MAP_ALL_ACCESS, + 0, + 0, + sizeof(pdvstTransferData)); + WaitForSingleObject(pdvstTransferMutex, INFINITE); +//l *(get_sys_schedadvance()) = *(get_sys_main_advance()) * 1000; +//l post("Hello, appel sys_setchsr dans _main. Version 64"); + sys_setchsr(pdvstData->nChannels, + pdvstData->nChannels, + pdvstData->sampleRate); + ReleaseMutex(pdvstTransferMutex); + //timeBeginPeriod(1); + scheduler(); + UnmapViewOfFile(pdvstData); + CloseHandle(pdvstTransferFileMap); + CloseHandle(pdvstTransferMutex); + for (i = 0; i < MAXARGS; i++) + { + free(argv[i]); + } + return (0); +} + + + + + + + diff --git a/vst-template/makefile b/vst-template/makefile new file mode 100644 index 0000000..0c88237 --- /dev/null +++ b/vst-template/makefile @@ -0,0 +1,43 @@ +# Compile with MinGW. +# Download "vstsdk2_4.zip" from https://archive.org/download/VST2SDK +# extract the folder an place it: +# +# ├──build/ +# ├──vst-scheduler/ +# ├──vstsdk2.4/ +# ├──vst-template/ +# + +FOO=../vstsdk2.4/ +FOO2=../vstsdk2.4/public.sdk/source/vst2.x/ + + +SOURCES= \ +pdvst.cpp \ +pdvstMain.cpp \ +pdvstEditor.cpp \ +$(FOO2)AudioEffect.cpp \ +$(FOO2)audioeffectx.cpp \ +$(empty) + +WINARCH := $(shell $(CC) -dumpmachine) + +ifeq (i686% , $(WINARCH)) + arch = 32 +else + arch = 64 +endif + + +ALL: $(SOURCES) + g++ -Wall -I. -I$(FOO) -I$(FOO2) \ + $(SOURCES) -static-libgcc -static-libstdc++ -static -lpthread -shared -o pdvst-template.dll + strip pdvst-template.dll + cp pdvst-template.dll ../build/Release$(arch)/.template/pdvst-template.dll + cp pdvst-template.dll ../build/Release$(arch)/Pd_Gain.dll + cp pdvst-template.dll ../build/Release$(arch)/Pd_Gain-gui.dll + cp pdvst-template.dll ../build/Release$(arch)/Pd_Gain-nogui.dll + cp pdvst-template.dll ../build/Release$(arch)/Pd_Midi.dll + + + diff --git a/vst-template/pdvst.cpp b/vst-template/pdvst.cpp new file mode 100644 index 0000000..3afae12 --- /dev/null +++ b/vst-template/pdvst.cpp @@ -0,0 +1,1138 @@ +/* PdVst v0.0.2 - VST - Pd bridging plugin +** Copyright (C) 2004 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#define _WIN32_WINDOWS 0x410 + +#include "pdvst.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef _MSC_VER +#define stat _stat +#endif + +extern HINSTANCE hInstance; +extern bool globalDebug; +extern int globalNChannels; +extern int globalNPrograms; +extern int globalNParams; +extern long globalPluginId; +extern int globalNExternalLibs; +extern char globalExternalLib[MAXEXTERNS][MAXSTRLEN]; +extern char globalVstParamName[MAXPARAMETERS][MAXSTRLEN]; +extern char globalPluginPath[MAXFILENAMELEN]; +extern char globalVstPluginPath[MAXFILENAMELEN]; // chemin d'accès dans le dossier vst contenant la dll) +extern char globalPluginName[MAXSTRLEN]; +extern char globalPdFile[MAXFILENAMELEN]; +extern char globalPureDataPath[MAXFILENAMELEN]; +extern char globalHostPdvstPath[MAXFILENAMELEN]; +extern bool globalCustomGui; +extern int globalCustomGuiWidth; +extern int globalCustomGuiHeight; + +extern bool globalIsASynth; +extern pdvstProgram globalProgram[MAXPROGRAMS]; + +int pdvst::referenceCount = 0; + + + /* change '/' characters to the system's native file separator */ +void sys_bashfilename(const char *from, char *to) +{ + char c; + while ((c = *from++)) + { +#ifdef _WIN32 + if (c == '/') c = '\\'; +#endif + *to++ = c; + } + *to = 0; +} + /* change the system's native file separator to '/' characters */ +void sys_unbashfilename(const char *from, char *to) +{ + char c; + while ((c = *from++)) + { +#ifdef _WIN32 + if (c == '\\') c = '/'; +#endif + *to++ = c; + } + *to = 0; +} + +/* +bool fexists(const char *filename) +{ + std::ifstream ifile(filename); + return ifile; +} + +*/ + + +//------------------------------------------------------------------------------------------------------- +AudioEffect* createEffectInstance (audioMasterCallback audioMaster) +{ + + return new pdvst (audioMaster); +} + +pdvst::pdvst(audioMasterCallback audioMaster) + :AudioEffectX(audioMaster, globalNPrograms, globalNParams) +{ + // set debug output + debugFile = fopen("pdvstdebug.txt", "wt"); + // debugFile = NULL; + + // copy global data + isASynth = globalIsASynth; + customGui = globalCustomGui; + customGuiHeight = globalCustomGuiHeight; + customGuiWidth = globalCustomGuiWidth; + nChannels = globalNChannels; + nPrograms = globalNPrograms; + nParameters = globalNParams; + pluginId = globalPluginId; + nExternalLibs = globalNExternalLibs; + debugLog("name: %s", globalPluginName); + debugLog("synth: %d", globalIsASynth); + + // VST setup + setNumInputs(nChannels); + setNumOutputs(nChannels); + setUniqueID(pluginId); + setInitialDelay(PDBLKSIZE * 2); + canProcessReplacing(); + if (isASynth) + { + isSynth(); + } + + int i, j; + + + + // initialize memory + vstParamName = new char*[MAXPARAMETERS]; + for (i = 0; i < MAXPARAMETERS; i++) + vstParamName[i] = new char[MAXSTRLEN]; + memset(vstParam, 0, MAXPARAMETERS * sizeof(float)); + program = new pdvstProgram[MAXPROGRAMS]; + + for (i = 0; i < nExternalLibs; i++) + { + strcpy(externalLib[i], globalExternalLib[i]); + } + debugLog("channels: %d", nChannels); + audioBuffer = new pdVstBuffer(nChannels); + for (i = 0; i < MAXPARAMETERS; i++) + { + strcpy(vstParamName[i], globalVstParamName[i]); + } + strcpy(pluginPath, globalPluginPath); + strcpy(vstPluginPath, globalVstPluginPath); + strcpy(pluginName, globalPluginName); + strcpy(pdFile, globalPdFile); + debugLog("path: %s", pluginPath); + debugLog("nParameters = %d", nParameters); + debugLog("nPrograms = %d", nPrograms); + for (i = 0; i < nPrograms; i++) + { + strcpy(program[i].name, globalProgram[i].name); + for (j = 0; j < nParameters; j++) + { + program[i].paramValue[j] = globalProgram[i].paramValue[j]; + } + debugLog(" %s", program[i].name); + } + // create editor + if (customGui) + { + editor = new pdvstEditor(this); + + debugLog(" -has custom GUI-"); + } + guiNameUpdated=false; + + #ifdef VSTMIDIOUTENABLE + // initializing structures for midiout support + + nbFramesWithoutMidiOutEvent=0; + + evnts = (struct VstEvents*)malloc(sizeof(struct VstEvents) + + MAXMIDIOUTQUEUESIZE*sizeof(VstEvent*)); + //initialisation du tableau midiEvnts[MAXMIDIOUTQUEUESIZE]; + for (int k=0; kevents[k] = (VstEvent*)&midiEvnts[k]; + } + + + #endif //VSTMIDIOUTENABLE + + + + //timeBeginPeriod(1); + debugLog("startingPd..."); + // start pd.exe + startPd(); + debugLog("done"); + //setProgram(curProgram); + referenceCount++; + + // {JYG see pdvst::setProgram below for explanation + timeFromStartup=GetTickCount(); + // JYG } +} + +pdvst::~pdvst() +{ + int i; + + referenceCount--; + pdvstData->active = 0; + CloseHandle(pdvstTransferMutex); + UnmapViewOfFile(pdvstTransferFileMap); + CloseHandle(pdvstTransferFileMap); + for (i = 0; i < MAXPARAMETERS; i++) + delete vstParamName[i]; + delete vstParamName; + delete program; + delete audioBuffer; + if (debugFile) + { + fclose(debugFile); + } +} + +void pdvst::debugLog(char *fmt, ...) +{ + va_list ap; + + if (debugFile) + { + va_start(ap, fmt); + vfprintf(debugFile, fmt, ap); + va_end(ap); + putc('\n', debugFile); + fflush(debugFile); + } +} + +void pdvst::startPd() +{ + + int i; + STARTUPINFO si; + PROCESS_INFORMATION pi; + char commandLineArgs[MAXSTRLEN], + debugString[MAXSTRLEN],pathToCheck[MAXSTRLEN]; + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + sprintf(pdvstTransferMutexName, "mutex%d%x", GetCurrentProcessId(), this); + sprintf(pdvstTransferFileMapName, "filemap%d%x", GetCurrentProcessId(), this); + sprintf(vstProcEventName, "vstprocevent%d%x", GetCurrentProcessId(), this); + sprintf(pdProcEventName, "pdprocevent%d%x", GetCurrentProcessId(), this); + pdvstTransferMutex = CreateMutex(NULL, 0, pdvstTransferMutexName); + vstProcEvent = CreateEvent(NULL, TRUE, TRUE, vstProcEventName); + pdProcEvent = CreateEvent(NULL, TRUE, FALSE, pdProcEventName); + pdvstTransferFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, + NULL, + PAGE_READWRITE, + 0, + sizeof(pdvstTransferData), + pdvstTransferFileMapName); + pdvstData = (pdvstTransferData *)MapViewOfFile(pdvstTransferFileMap, + FILE_MAP_ALL_ACCESS, + 0, + 0, + sizeof(pdvstTransferData)); + pdvstData->active = 1; + pdvstData->blockSize = PDBLKSIZE; + pdvstData->nChannels = nChannels; + pdvstData->sampleRate = (int)getSampleRate(); + pdvstData->nParameters = nParameters; + pdvstData->guiState.updated = 0; + pdvstData->guiState.type = FLOAT_TYPE; + pdvstData->guiState.direction = PD_RECEIVE; + for (i = 0; i < MAXPARAMETERS; i++) + { + pdvstData->vstParameters[i].direction = PD_RECEIVE; + pdvstData->vstParameters[i].updated = 0; + } + if (globalDebug) + { + strcpy(debugString, ""); + } + else + { + strcpy(debugString, " -nogui"); + } + if (strcmp(globalPureDataPath, "") == 0) // unspecified puredata path. Defaults to globalHostPdvstPath + { + sprintf(commandLineArgs, "%s\\pd\\bin\\pd.exe", globalHostPdvstPath); + if( access( commandLineArgs, F_OK ) != -1 ) // check if file exists + sprintf(commandLineArgs, "\"%s\\pd\\bin\\pd.exe\"", globalHostPdvstPath); + else + { + sprintf(commandLineArgs, "%s..\\.pd\\bin\\pd.exe", globalPluginPath); + //MessageBox(NULL,commandLineArgs,"commandLineArgs...",MB_OK); + if( access( commandLineArgs, F_OK ) != -1 ) // check if file exists + sprintf(commandLineArgs, "\"%s..\\.pd\\bin\\pd.exe\"", globalPluginPath); + else + { + sprintf(errorMessage,"pd.exe program not found in \n1: %spd\\bin\\\n2: %s..\\.pd\\bin\\\nCheck your settings in \n%s%s.pdv", + globalHostPdvstPath,globalPluginPath,globalPluginPath,globalPluginName); + MessageBox(NULL,errorMessage,"ERROR",MB_OK); + return; + } + } + } + else + { + sprintf(commandLineArgs, "%s\\bin\\pd.exe", globalPureDataPath); + if ( access( commandLineArgs, F_OK ) != -1 ) // file exists + sprintf(commandLineArgs,"\"%s\\bin\\pd.exe\"", globalPureDataPath); + else + { + sprintf(errorMessage,"pd.exe program not found. Check your settings in \n%s%s.pdv \n setup file. (search for the line PDPATH)", + globalPluginPath,globalPluginName); + MessageBox(NULL,errorMessage,"ERROR",MB_OK); + return; + } + } + + + + // if (!fexists(commandLineArgs)) + // sprintf(commandLineArgs, "\"%s\\pd\\bin\\pd.exe\"", pluginPath); + // check validity of pd.exe path + /* + struct stat statbuf; + sys_bashfilename(commandLineArgs, pathToCheck); + if (stat(pathToCheck, &statbuf) < 0) + // if failed, use defaults + sprintf(commandLineArgs, "\"%s\\pd\\bin\\pd.exe\"", pluginPath);*/ + + + sprintf(commandLineArgs, + "%s%s", + commandLineArgs, + debugString); + sprintf(commandLineArgs, + "%s -schedlib vstschedlib", + commandLineArgs); + sprintf(commandLineArgs, + "%s -extraflags \"-vstproceventname %s -pdproceventname %s -vsthostid %d -mutexname %s -filemapname %s\"", + commandLineArgs, + vstProcEventName, + pdProcEventName, + GetCurrentProcessId(), + pdvstTransferMutexName, + pdvstTransferFileMapName); + sprintf(commandLineArgs, + "%s -outchannels %d -inchannels %d", + commandLineArgs, + nChannels, + nChannels); + sprintf(commandLineArgs, + "%s -r %d", + commandLineArgs, + (int)getSampleRate()); + + sprintf(commandLineArgs, + "%s -open \"%s%s\"", + commandLineArgs, + pluginPath, + pdFile); + sprintf(commandLineArgs, + "%s -path \"%s\"", + commandLineArgs, + pluginPath); + for (i = 0; i < nExternalLibs; i++) + { + sprintf(commandLineArgs, + "%s -lib %s", + commandLineArgs, + externalLib[i]); + } + debugLog("command line: %s", commandLineArgs); + suspend(); + CreateProcess(NULL, + commandLineArgs, + NULL, + NULL, + 0, + 0, + NULL, + NULL, + &si, + &pi); +} + +void pdvst::sendGuiAction(int action) +{ + WaitForSingleObject(pdvstTransferMutex, 10);// if (WaitForSingleObject(pdvstTransferMutex, 100)!= WAIT_TIMEOUT) + { + pdvstData->guiState.direction = PD_RECEIVE; + pdvstData->guiState.type = FLOAT_TYPE; + pdvstData->guiState.value.floatData = (float)action; + pdvstData->guiState.updated = 1; + ReleaseMutex(pdvstTransferMutex); + } +} + +void pdvst::sendPlugName(char * pName ) // pour envoyer le nom du plugin à puredata +{ + + WaitForSingleObject(pdvstTransferMutex, 10);//if (WaitForSingleObject(pdvstTransferMutex, 100)!= WAIT_TIMEOUT) + { + pdvstData->plugName.direction = PD_RECEIVE; + pdvstData->plugName.type = STRING_TYPE; + strcpy(pdvstData->plugName.value.stringData,pName); + pdvstData->plugName.updated = 1; + ReleaseMutex(pdvstTransferMutex); + } +} + +void pdvst::setSyncToVst(int value) +{ + + if (WaitForSingleObject(pdvstTransferMutex, 10)==WAIT_OBJECT_0) + { + if (pdvstData->syncToVst != value) + { + pdvstData->syncToVst = value; + } + ReleaseMutex(pdvstTransferMutex); + } + +} + +void pdvst::suspend() +{ + int i; + + setSyncToVst(0); + SetEvent(vstProcEvent); + for (i = 0; i < audioBuffer->nChannels; i++) + { + memset(audioBuffer->in[i], 0, audioBuffer->size * sizeof(float)); + memset(audioBuffer->out[i], 0, audioBuffer->size * sizeof(float)); + } + audioBuffer->inFrameCount = audioBuffer->outFrameCount = 0; + dspActive = false; + setInitialDelay(PDBLKSIZE * 2); +} + +void pdvst::resume() +{ + int i; + + setSyncToVst(1); + SetEvent(vstProcEvent); + for (i = 0; i < audioBuffer->nChannels; i++) + { + memset(audioBuffer->in[i], 0, audioBuffer->size * sizeof(float)); + memset(audioBuffer->out[i], 0, audioBuffer->size * sizeof(float)); + } + audioBuffer->inFrameCount = audioBuffer->outFrameCount = 0; + dspActive = true; + setInitialDelay(PDBLKSIZE * 2); + if (isASynth) + { + //wantEvents(); deprecated since VST 2.4 + } +} + +void pdvst::setProgram(VstInt32 prgmNum) +{ + debugLog("appel de setProgram %d", prgmNum); + int i; + if (prgmNum >= 0 && prgmNum < nPrograms) + { + curProgram = prgmNum; + + + // {JYG to prevent host call of setProgram to override current param settings + // see https://www.kvraudio.com/forum/viewtopic.php?p=6391144 + // sprintf(errorMessage,"GetTickCount=%d\ntimeFromStartup=%d", + // GetTickCount(),timeFromStartup); + //MessageBox(NULL, errorMessage,"setProgram",MB_OK); + if ((GetTickCount()-timeFromStartup) < 1000) + return; + else + { + for (i = 0; i < nParameters; i++) + { + setParameter(i, program[curProgram].paramValue[i]); + // MessageBox(NULL,"setvalue","setProgram",MB_OK); + } + } + } + +} + +VstInt32 pdvst::getProgram() +{ + return curProgram; +} + +void pdvst::setProgramName(char *name) +{ + strcpy(program[curProgram].name, name); +} + +void pdvst::getProgramName(char *name) +{ + strcpy(name, program[curProgram].name); + // {JYG see pdvst::setProgram below for explanation + timeFromStartup=GetTickCount(); + // JYG } +} + +void pdvst::setParameter(VstInt32 index, float value) +{ + if (vstParam[index] != value) + { + vstParam[index] = value; + WaitForSingleObject(pdvstTransferMutex, 10);// if (WaitForSingleObject(pdvstTransferMutex, 100)!= WAIT_TIMEOUT) + { + pdvstData->vstParameters[index].type = FLOAT_TYPE; + pdvstData->vstParameters[index].value.floatData = value; + pdvstData->vstParameters[index].direction = PD_RECEIVE; + pdvstData->vstParameters[index].updated = 1; + ReleaseMutex(pdvstTransferMutex); + } + } +} + +float pdvst::getParameter(VstInt32 index) +{ + if (index >= 0 && index < MAXPARAMETERS) + return vstParam[index]; + else + return 0; +} + +void pdvst::getParameterName(VstInt32 index, char *label) +{ + if (index >= 0 && index < MAXPARAMETERS) + strcpy(label, vstParamName[index]); +} + +void pdvst::getParameterDisplay(VstInt32 index, char *text) +{ + if (index >= 0 && index < MAXPARAMETERS) + float2string(vstParam[index], text, 10); +} + +void pdvst::getParameterLabel(VstInt32 index, char *label) +{ + strcpy(label, ""); + /* if (index >= 0 && index < MAXPARAMETERS) + strcpy(label, vstParamName[index]);*/ +} + +// FIXME +bool pdvst::getEffectName(char* name) +{ + strcpy (name, globalPluginName); + return true; +} + +// FIXME +bool pdvst::getOutputProperties(VstInt32 index, VstPinProperties* properties) +{ + if (1)//index < 2) + { + sprintf (properties->label, "pd-vst %1d", index + 1); + properties->flags = kVstPinIsActive; + if ((index %2)==0) + properties->flags |= kVstPinIsStereo; // make channel 1+2 stereo + return true; + } + return false; +} + +VstInt32 pdvst::canDo(char* text) +{ + //if (isASynth) + if (1) + { + if (!strcmp (text, "sendVstEvents")) + return 1; + if (!strcmp (text, "sendVstMidiEvent")) + return 1; + if (!strcmp (text, "receiveVstEvents")) + return 1; + if (!strcmp (text, "receiveVstMidiEvent")) + return 1; + } + return -1; +} + +void pdvst::process(float **input, float **output, VstInt32 sampleFrames) +{ + #ifdef VSTMIDIOUTENABLE + + WaitForSingleObject(pdvstTransferMutex, 10);//if (WaitForSingleObject(pdvstTransferMutex, 100)!= WAIT_TIMEOUT) + { + if (pdvstData->midiOutQueueUpdated) + { + // Faire une loop pour parcourir la midiqueue et recopier + //dans la structure midiOutEvents + int midiOutQueueSize=pdvstData->midiOutQueueSize; + for (int ka=0;kamidiOutQueue[ka].statusByte; + midiEvnts[ka].midiData[1] = pdvstData->midiOutQueue[ka].dataByte1; + midiEvnts[ka].midiData[2] = pdvstData->midiOutQueue[ka].dataByte2; + } + evnts->numEvents=midiOutQueueSize; + + sendVstEventsToHost(evnts); /// TODO : rajouter un test de réussite + pdvstData->midiOutQueueUpdated=0; + pdvstData->midiOutQueueSize=0; + + evnts->numEvents=0; + } + ReleaseMutex(pdvstTransferMutex); + } + + #endif // VSTMIDIOUTENABLE + + + /* // Get play head information + VstTimeInfo * info = getTimeInfo( + kVstTempoValid | + kVstPpqPosValid | + kVstTransportPlaying | + kVstTransportChanged | + kVstTransportCycleActive | + kVstTransportRecording | + kVstAutomationWriting | + kVstAutomationReading | + 0); + + /* if(infos) + { + m_playing_list.setFloat(0, m_playinfos.isPlaying); + m_playing_list.setFloat(1, m_playinfos.timeInSeconds); + sendMessageAnything(m_patch_tie, s_playing, m_playing_list); + m_measure_list.setFloat(0, m_playinfos.bpm); + m_measure_list.setFloat(1, m_playinfos.timeSigNumerator); + m_measure_list.setFloat(2, m_playinfos.timeSigDenominator); + m_measure_list.setFloat(3, m_playinfos.ppqPosition); + m_measure_list.setFloat(4, m_playinfos.ppqPositionOfLastBarStart); +sendMessageAnything(m_patch_tie, s_measure, m_measure_list); + +*/ + + int i, j, k, l; + int framesOut = 0; + + if (!dspActive) + { + resume(); + } + else + { + setSyncToVst(1); + } + + + for (i = 0; i < sampleFrames; i++) + { + for (j = 0; j < audioBuffer->nChannels; j++) + { + audioBuffer->in[j][audioBuffer->inFrameCount] = input[j][i]; + } + (audioBuffer->inFrameCount)++; + // if enough samples to process then do it + if (audioBuffer->inFrameCount >= PDBLKSIZE) + { + audioBuffer->inFrameCount = 0; + updatePdvstParameters(); + // wait for pd process event + // { JYG + //WaitForSingleObject(pdProcEvent, 10000);///int couldSync = WaitForSingleObject(pdProcEvent, 100)!= WAIT_TIMEOUT; + WaitForSingleObject(pdProcEvent,10); + //WaitForSingleObject(pdProcEvent, 10000); + /// JYG: 10000 était une valeur trop élevée qui faisait planter ableton live 8.04, va savoir pourquoi + // JYG } + ///if (couldSync) + ResetEvent(pdProcEvent); + + for (k = 0; k < PDBLKSIZE; k++) + { + for (l = 0; l < audioBuffer->nChannels; l++) + { + while (audioBuffer->outFrameCount >= audioBuffer->size) + { + audioBuffer->resize(audioBuffer->size * 2); + } + // get pd processed samples + ///if (couldSync) + { + // get pd processed samples + audioBuffer->out[l][audioBuffer->outFrameCount] = pdvstData->samples[l][k]; + // put new samples in for processing + pdvstData->samples[l][k] = audioBuffer->in[l][k]; + } + + } + (audioBuffer->outFrameCount)++; + } + ///if (couldSync) + pdvstData->sampleRate = (int)getSampleRate(); + // signal vst process event + SetEvent(vstProcEvent); + } + } + // output pd processed samples + for (i = 0; i < sampleFrames; i++) + { + for (j = 0; j < audioBuffer->nChannels; j++) + { + if (audioBuffer->outFrameCount > 0) + { + output[j][i] = audioBuffer->out[j][i]; + } + else + { + output[j][i] = 0; + } + } + if (audioBuffer->outFrameCount > 0) + { + audioBuffer->outFrameCount--; + framesOut++; + } + } + // shift any remaining buffered out samples + if (audioBuffer->outFrameCount > 0) + { + for (i = 0; i < audioBuffer->nChannels; i++) + { + memmove(&(audioBuffer->out[i][0]), + &(audioBuffer->out[i][framesOut]), + (audioBuffer->outFrameCount) * sizeof(float)); + } + } +} + +DWORD WINAPI NotifySyncError(LPVOID lpParam) { + MessageBoxA(NULL, "Le processus PureData met du temps à répondre", "PdVST", MB_OK); + return 0; +} + +void pdvst::processReplacing(float **input, float **output, VstInt32 sampleFrames) +{ + #ifdef VSTMIDIOUTENABLE + + if (WaitForSingleObject(pdvstTransferMutex, 10)==WAIT_OBJECT_0) + { + if (pdvstData->midiOutQueueUpdated) + { + // Faire une loop pour parcourir la midiqueue et recopier + //dans la structure midiOutEvents + int midiOutQueueSize=pdvstData->midiOutQueueSize; + for (int ka=0;kamidiOutQueue[ka].statusByte; + midiEvnts[ka].midiData[1] = pdvstData->midiOutQueue[ka].dataByte1; + midiEvnts[ka].midiData[2] = pdvstData->midiOutQueue[ka].dataByte2; + } + evnts->numEvents=midiOutQueueSize; + + sendVstEventsToHost(evnts); // rajouter un test de réussite + pdvstData->midiOutQueueUpdated=0; + pdvstData->midiOutQueueSize=0; + + evnts->numEvents=0; + } + else + { + // Envoyer périodiquement un sendVstEventsToHost(no_event) pour signifier + // à Ableton Live qu'on est bien vivant et qu'on envoie du midi + // (tous les 120 tours de buffer) + nbFramesWithoutMidiOutEvent++; + if (nbFramesWithoutMidiOutEvent>120) + { + nbFramesWithoutMidiOutEvent=0; + midiEvnts[0].midiData[0]=0; + midiEvnts[0].midiData[1]=0; + midiEvnts[0].midiData[2]=0; + evnts->numEvents=1; + sendVstEventsToHost(evnts); + } + + } + + ReleaseMutex(pdvstTransferMutex); + } + + #endif // VSTMIDIOUTENABLE + + + // Get play head information + VstTimeInfo * infos = getTimeInfo( + kVstTempoValid | + kVstPpqPosValid | + kVstTransportPlaying | + kVstTransportChanged | + kVstTransportCycleActive | + kVstTransportRecording | + kVstAutomationWriting | + kVstAutomationReading | + 0); + + if(infos) + { + if (WaitForSingleObject(pdvstTransferMutex, 10)==WAIT_OBJECT_0) + { + + pdvstData->hostTimeInfo.updated=1; + //copying vstTimeInfo into pdvst transfer data structure + pdvstData->hostTimeInfo.samplePos=infos->samplePos; ///< current Position in audio samples (always valid) + pdvstData->hostTimeInfo.sampleRate=infos->sampleRate; ///< current Sample Rate in Herz (always valid) + pdvstData->hostTimeInfo.nanoSeconds=infos->nanoSeconds; ///< System Time in nanoseconds (10^-9 second) + pdvstData->hostTimeInfo.ppqPos=infos->ppqPos; ///< Musical Position, in Quarter Note (1.0 equals 1 Quarter Note) + pdvstData->hostTimeInfo.tempo=infos->tempo; ///< current Tempo in BPM (Beats Per Minute) + pdvstData->hostTimeInfo.barStartPos=infos->barStartPos; ///< last Bar Start Position, in Quarter Note + pdvstData->hostTimeInfo.cycleStartPos=infos->cycleStartPos; ///< Cycle Start (left locator), in Quarter Note + pdvstData->hostTimeInfo.cycleEndPos=infos->cycleEndPos; ///< Cycle End (right locator), in Quarter Note + pdvstData->hostTimeInfo.timeSigNumerator=(int)infos->timeSigNumerator; ///< Time Signature Numerator (e.g. 3 for 3/4) + pdvstData->hostTimeInfo.timeSigDenominator=(int)infos->timeSigDenominator; ///< Time Signature Denominator (e.g. 4 for 3/4) + pdvstData->hostTimeInfo.smpteOffset=(int)infos->smpteOffset; ///< SMPTE offset (in SMPTE subframes (bits; 1/80 of a frame)). The current SMPTE position can be calculated using #samplePos, #sampleRate, and #smpteFrameRate. + pdvstData->hostTimeInfo.smpteFrameRate=(int)infos->smpteFrameRate; ///< @see VstSmpteFrameRate + pdvstData->hostTimeInfo.samplesToNextClock=(int)infos->samplesToNextClock; ///< MIDI Clock Resolution (24 Per Quarter Note), can be negative (nearest clock) + pdvstData->hostTimeInfo.flags=(int)infos->flags; + + ReleaseMutex(pdvstTransferMutex); + } + } + + int i, j, k, l; + int framesOut = 0; + + if (!dspActive) + { + resume(); + } + else + { + setSyncToVst(1); + } + + + for (i = 0; i < sampleFrames; i++) + { + for (j = 0; j < audioBuffer->nChannels; j++) + { + audioBuffer->in[j][audioBuffer->inFrameCount] = input[j][i]; + } + (audioBuffer->inFrameCount)++; + // if enough samples to process then do it + if (audioBuffer->inFrameCount >= PDBLKSIZE) + { + audioBuffer->inFrameCount = 0; + updatePdvstParameters(); + // wait for pd process event + // { JYG + int gotPdProcEvent = (WaitForSingleObject(pdProcEvent, 10)==WAIT_OBJECT_0); + // WaitForSingleObject(pdProcEvent,100); + //WaitForSingleObject(pdProcEvent, 10000); + // JYG: 10000 était une valeur trop élevée qui faisait planter ableton live + // JYG } + if (gotPdProcEvent) + { + ResetEvent(pdProcEvent); + syncDefeatNumber=0; + } + else if (syncDefeatNumber==50) + { + //afficher messageErreur + //CreateThread(NULL, 0, &NotifySyncError, NULL, 0, NULL); + //startPd(); + syncDefeatNumber++; + + } + + else + syncDefeatNumber++; + + for (k = 0; k < PDBLKSIZE; k++) + { + for (l = 0; l < audioBuffer->nChannels; l++) + { + while (audioBuffer->outFrameCount >= audioBuffer->size) + { + audioBuffer->resize(audioBuffer->size * 2); + } + // get pd processed samples + if (gotPdProcEvent) + { + // get pd processed samples + audioBuffer->out[l][audioBuffer->outFrameCount] = pdvstData->samples[l][k]; + // put new samples in for processing + pdvstData->samples[l][k] = audioBuffer->in[l][k]; + } + + } + (audioBuffer->outFrameCount)++; + } + pdvstData->sampleRate = (int)getSampleRate(); + // signal vst process event + SetEvent(vstProcEvent); + } + } + // output pd processed samples + for (i = 0; i < sampleFrames; i++) + { + for (j = 0; j < audioBuffer->nChannels; j++) + { + if (audioBuffer->outFrameCount > 0) + { + output[j][i] = audioBuffer->out[j][i]; + } + else + { + output[j][i] = 0; + } + } + if (audioBuffer->outFrameCount > 0) + { + audioBuffer->outFrameCount--; + framesOut++; + } + } + // shift any remaining buffered out samples + if (audioBuffer->outFrameCount > 0) + { + for (i = 0; i < audioBuffer->nChannels; i++) + { + memmove(&(audioBuffer->out[i][0]), + &(audioBuffer->out[i][framesOut]), + (audioBuffer->outFrameCount) * sizeof(float)); + } + } + +} + +VstInt32 pdvst::processEvents(VstEvents* ev) +{ + VstMidiEvent* event; + char* midiData; + long statusType; + long statusChannel; + + WaitForSingleObject(pdvstTransferMutex, 10);/// if (WaitForSingleObject(pdvstTransferMutex, 100)!= WAIT_TIMEOUT) + // valeur d'attente courte (1000 au lieu de 10000 dans pdvst 0.2) + + { + for (long i = 0; i < ev->numEvents; i++) + { + if ((ev->events[i])->type != kVstMidiType) + { + continue; + } + event = (VstMidiEvent*)ev->events[i]; + midiData = event->midiData; + statusType = midiData[0] & 0xF0; + statusChannel = midiData[0] & 0x0F; + pdvstData->midiQueue[pdvstData->midiQueueSize].statusByte = midiData[0]; + pdvstData->midiQueue[pdvstData->midiQueueSize].dataByte1 = midiData[1]; + pdvstData->midiQueue[pdvstData->midiQueueSize].dataByte2 = midiData[2]; + if (statusType == 0x80) + { + // note off + pdvstData->midiQueue[pdvstData->midiQueueSize].channelNumber = statusChannel; + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = NOTE_OFF; + } + else if (statusType == 0x90) + { + // note on + pdvstData->midiQueue[pdvstData->midiQueueSize].channelNumber = statusChannel; + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = NOTE_ON; + } + else if (statusType == 0xA0) + { + // key pressure + pdvstData->midiQueue[pdvstData->midiQueueSize].channelNumber = statusChannel; + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = KEY_PRESSURE; + } + else if (statusType == 0xB0) + { + // controller change + pdvstData->midiQueue[pdvstData->midiQueueSize].channelNumber = statusChannel; + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = CONTROLLER_CHANGE; + } + else if (statusType == 0xC0) + { + // program change + pdvstData->midiQueue[pdvstData->midiQueueSize].channelNumber = statusChannel; + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = PROGRAM_CHANGE; + } + else if (statusType == 0xD0) + { + // channel pressure + pdvstData->midiQueue[pdvstData->midiQueueSize].channelNumber = statusChannel; + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = CHANNEL_PRESSURE; + } + else if (statusType == 0xE0) + { + // pitch bend + pdvstData->midiQueue[pdvstData->midiQueueSize].channelNumber = statusChannel; + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = PITCH_BEND; + } + else + { + // something else + pdvstData->midiQueue[pdvstData->midiQueueSize].messageType = OTHER; + } + pdvstData->midiQueueSize++; + event++; + } + pdvstData->midiQueueUpdated = 1; + ReleaseMutex(pdvstTransferMutex); + return 1; + } + ///else + return 0; +} + +void pdvst::updatePdvstParameters() +{ + int i; + + + WaitForSingleObject(pdvstTransferMutex, 10); + // WaitForSingleObject(pdvstTransferMutex, 10000);///if (WaitForSingleObject(pdvstTransferMutex, 100)!= WAIT_TIMEOUT) + { + for (i = 0; i < pdvstData->nParameters; i++) + { + if (pdvstData->vstParameters[i].direction == PD_SEND && \ + pdvstData->vstParameters[i].updated) + { + if (pdvstData->vstParameters[i].type == FLOAT_TYPE) + { + //beginEdit (i); + setParameterAutomated(i, + pdvstData->vstParameters[i].value.floatData); + //endEdit(i); + updateDisplay (); + } + pdvstData->vstParameters[i].updated = 0; + } + } + + if (pdvstData->guiName.direction == PD_SEND && \ + pdvstData->guiName.updated) + { + if (pdvstData->guiName.type == STRING_TYPE) + { + strcpy(guiName, pdvstData->guiName.value.stringData); + + pdvstData->guiName.updated=0; + // signal to vesteditor that guiname is updated + guiNameUpdated=true; + } + + + + + } + + ReleaseMutex(pdvstTransferMutex); + } + +} + +pdVstBuffer::pdVstBuffer(int nChans) +{ + int i; + + nChannels = nChans; + in = (float **)malloc(nChannels * sizeof(float *)); + out = (float **)malloc(nChannels * sizeof(float *)); + for (i = 0; i < nChannels; i++) + { + in[i] = (float *)calloc(DEFPDVSTBUFFERSIZE, + sizeof(float)); + out[i] = (float *)calloc(DEFPDVSTBUFFERSIZE, + sizeof(float)); + } + size = DEFPDVSTBUFFERSIZE; +} + +pdVstBuffer::~pdVstBuffer() +{ + int i; + + for (i = 0; i < nChannels; i++) + { + free(in[i]); + free(out[i]); + } +} + +void pdVstBuffer::resize(int newSize) +{ + int i; + + for (i = 0; i < nChannels; i++) + { + in[i] = (float *)realloc(in[i], newSize * sizeof(float)); + out[i] = (float *)realloc(out[i], newSize * sizeof(float)); + } + size = newSize; +} + + diff --git a/vst-template/pdvst.hpp b/vst-template/pdvst.hpp new file mode 100644 index 0000000..36a5d1b --- /dev/null +++ b/vst-template/pdvst.hpp @@ -0,0 +1,175 @@ +/* PdVst v0.0.2 - VST - Pd bridging plugin +** Copyright (C) 2004 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#ifndef __PDVST_H +#define __PDVST_H + +#include "audioeffectx.h" +#include "pdvstEditor.hpp" +#include +#include +#include +#include + +#define PDBLKSIZE 64 +#define MAXEXTERNS 128 +#define MAXVSTBUFSIZE 4096 +#define MAXPARAMS 128 +#define MAXPROGRAMS 128 +#define MAXCHANS 128 +#define MAXFILENAMELEN 1024 +#define MAXSTRLEN 4096 +#define MAXEXTERNS 128 +#define PDWAITMAX 1000 +#define SETUPFILEEXT ".pdv" +#define DEFPDVSTBUFFERSIZE 1024 + +extern "C" +{ + #include "pdvstTransfer.h" +} + +/* program data */ +typedef struct _pdvstProgram +{ + char name[MAXSTRLEN]; + float paramValue[MAXPARAMETERS]; +} pdvstProgram; + +class pdVstBuffer +{ + + friend class pdvst; + +public: + pdVstBuffer(int nChans); + ~pdVstBuffer(); + void resize(int newSize); + +protected: + int nChannels; + int inFrameCount; + int outFrameCount; + int size; + float **in; + float **out; +}; + +class pdvst : public AudioEffectX +{ + friend class pdvstEditor; + +public: + pdvst(audioMasterCallback audioMaster); + ~pdvst(); + + virtual void process(float **inputs, float **outputs, VstInt32 sampleFrames); + virtual void processReplacing(float **inputs, float **outputs, + VstInt32 sampleFrames); + virtual VstInt32 processEvents (VstEvents* events); + virtual void setProgram(VstInt32 prgmNum); + virtual VstInt32 getProgram(); + virtual void setProgramName(char *name); + virtual void getProgramName(char *name); + virtual void setParameter(VstInt32 index, float value); + virtual float getParameter(VstInt32 index); + virtual void getParameterLabel(VstInt32 index, char *label); + virtual void getParameterDisplay(VstInt32 index, char *text); + virtual void getParameterName(VstInt32 index, char *text); + virtual bool getEffectName(char* name); + virtual bool getOutputProperties(VstInt32 index, VstPinProperties* properties); + virtual VstInt32 canDo (char* text); + // virtual VstInt32 canMono (); + virtual void suspend(); + virtual void resume(); + void sendGuiAction(int action); + void sendPlugName(char * name ); // JYG : to send plug name to puredatapatch + + LPTSTR displayString;//= new TCHAR[MAXSTRINGSIZE]; + + HWND pdGui; + +protected: + static int referenceCount; + void debugLog(char *fmt, ...); + FILE *debugFile; + int pdInFrameCount; + int pdOutFrameCount; + pdVstBuffer *audioBuffer; + char pluginPath[MAXFILENAMELEN]; + char vstPluginPath[MAXFILENAMELEN]; + char pluginName[MAXSTRLEN]; + long pluginId; + char pdFile[MAXFILENAMELEN]; + char errorMessage[MAXFILENAMELEN]; + char externalLib[MAXEXTERNS][MAXSTRLEN]; + float vstParam[MAXPARAMS]; + char **vstParamName; + int nParameters; + pdvstProgram *program; + int nPrograms; + int nChannels; + int nExternalLibs; + bool customGui; + int customGuiHeight; + int customGuiWidth; + + bool isASynth; + bool dspActive; + HANDLE pdvstTransferMutex, + pdvstTransferFileMap, + vstProcEvent, + pdProcEvent; + pdvstTransferData *pdvstData; + char pdvstTransferMutexName[1024]; + char pdvstTransferFileMapName[1024]; + char vstProcEventName[1024]; + char pdProcEventName[1024]; + char guiName[1024]; + bool guiNameUpdated; // used to signal to editor that the parameter guiName has changed + void startPd(); + void parseSetupFile(); + + void updatePdvstParameters(); + void setSyncToVst(int value); + // {JYG + DWORD timeFromStartup; // to measure time before vst::setProgram call + #ifdef VSTMIDIOUTENABLE + /** Stores a single midi event. + * The 'events' fields points to midiEvent. + */ + VstEvents midiOutEvents; + /** Last played note information is stored in midiEvent. + */ + VstMidiEvent midiEvent; + + // version alternative (http://stackoverflow.com/questions/359125/how-to-store-data-in-variable-length-arrays-without-causing-memory-corruption) + struct VstEvents *evnts; + VstMidiEvent midiEvnts[MAXMIDIOUTQUEUESIZE]; + + int nbFramesWithoutMidiOutEvent; + #endif //VSTMIDIOUTENABLE + int syncDefeatNumber; + + + // JYG } +}; + +#endif diff --git a/vst-template/pdvstEditor.cpp b/vst-template/pdvstEditor.cpp new file mode 100644 index 0000000..c6777f2 --- /dev/null +++ b/vst-template/pdvstEditor.cpp @@ -0,0 +1,217 @@ +/* PdVst v0.0.2 - VST - Pd bridging plugin +** Copyright (C) 2004 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#ifndef __pdvstEditor +#include "pdvstEditor.hpp" +#endif + +#ifndef __PDVST_H +#include "pdvst.hpp" +#endif + +#include +#include + +extern HINSTANCE hInstance; +//extern int pdGuiWindowHeight, pdGuiWindowWidth; +int useCount = 0; + +pdvstEditor::pdvstEditor(AudioEffect *effect) + : AEffEditor(effect) +{ + systemWindowHidden=false; + effect->setEditor(this); + + editWindow = NULL; + //((pdvst *)(effect))->debugLog("begin editor"); +} + +pdvstEditor::~pdvstEditor() +{ +} + +bool pdvstEditor::getRect(ERect **erect) +{ + static ERect r = {0,0,((pdvst *)this->effect)->customGuiHeight,((pdvst *)this->effect)->customGuiWidth}; + *erect = &r; + return (true); +} + + +bool pdvstEditor::open(void *ptr) +{ + + + systemWindow = ptr; + + + + WNDCLASS myWindowClass; + + useCount++; + if (useCount == 1) + { + myWindowClass.style = 0; + myWindowClass.lpfnWndProc = (WNDPROC)windowProc; + myWindowClass.cbClsExtra = 0; + myWindowClass.cbWndExtra = 0; + myWindowClass.hInstance = hInstance; + myWindowClass.hIcon = 0; + myWindowClass.hCursor = 0; + myWindowClass.hbrBackground = GetSysColorBrush(COLOR_APPWORKSPACE); + // myWindowClass.hbrBackground = CreateSolidBrush(RGB(180, 180, 180)); + myWindowClass.lpszMenuName = 0; + myWindowClass.lpszClassName = "pdvstWindowClass"; + RegisterClass(&myWindowClass); + } + LPTSTR plugName= new TCHAR[MAXSTRINGSIZE]; + + GetWindowText((HWND)systemWindow,plugName,MAXSTRINGSIZE); + ((pdvst *)this->effect)->sendPlugName((char *) plugName ); + + // sprintf( ((pdvst *)this->effect)->displayString,"valeurSetParameter=%f",((pdvst *)this->effect)->vstParam[0]); + + + //((pdvst *)this->effect)->sendPlugName((char *) ((pdvst *)this->effect)->displayString ); + ////// + editWindow = CreateWindowEx(0, "pdvstWindowClass", "Window", + WS_CHILD | WS_VISIBLE, 0,0,((pdvst *)this->effect)->customGuiWidth,((pdvst *)this->effect)->customGuiHeight, + (HWND)systemWindow, NULL, hInstance, NULL); + SetWindowLongPtr(editWindow, GWLP_USERDATA, (LONG_PTR)this); + + /* openButton = CreateWindowEx(0, "Button", "open", WS_CHILD | WS_VISIBLE, + 70, 24, 120, 25, editWindow, NULL, hInstance, + NULL); + */ + + ((pdvst *)this->effect)->sendGuiAction(1); + return (true); +} + + + +void pdvstEditor::close() +{ + if (pdGuiWindow) + { + // detach pdGuiWindow from editWindow + SetParent(pdGuiWindow,NULL); + //Remove WS_CHILD style and add WS_POPUP style + DWORD style = GetWindowLong(pdGuiWindow,GWL_STYLE); + // style = style & ~(WS_POPUPWINDOW); + style = style | WS_POPUP; + style = style & ~(WS_CHILD); + style = style |(WS_SYSMENU); + style = style | (WS_BORDER); + SetWindowLong(pdGuiWindow,GWL_STYLE,style); + systemWindowHidden=false; + pdGuiWindow=NULL; + } + + if (editWindow) + { + ((pdvst *)this->effect)->sendGuiAction(0); + DestroyWindow(editWindow); + } + + editWindow = NULL; + useCount = 0; + UnregisterClass("pdvstWindowClass", hInstance); +} + +void pdvstEditor::idle() +{ + + // JYG :: masquer la fenêtre GUI créée par hôte VST pour laisser puredata le faire + // SetWindowPos((HWND)systemWindow,HWND_TOPMOST,-300,-300,0,0,SWP_NOSIZE); // déplacer la fenetre + // SetWindowPos((HWND)systemWindow,NULL,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW); //masquer la fenêtre + // systemWindowHidden=true; + // JYG + if (((pdvst *)this->effect)->guiNameUpdated) + if (editWindow)//&&!pdGuiWindow) + { + HWND tref=NULL; + parms.ref = &tref; + strcpy(parms.s,(char*)((pdvst *)this->effect)->guiName); + parms.exact = false; + EnumWindows(enumwnd,(LPARAM)&parms); + pdGuiWindow = tref; + + // pdGuiWindow=FindWindow(NULL,"Pd_Gain(gui).pd - C:/Program Files (x86)/Ableton/Live 8.0.4/Program/pdvst"); + // pdGuiWindow=FindWindow(NULL,(char*)((pdvst *)this->effect)->guiName); + if (pdGuiWindow) + { + if(SetParent(pdGuiWindow,(HWND)editWindow))//systemWindow)) + { + ((pdvst *)this->effect)->guiNameUpdated=0; + //Remove WS_POPUP style and add WS_CHILD style + DWORD style = GetWindowLong(pdGuiWindow,GWL_STYLE); + // style = style & ~(WS_POPUPWINDOW); + style = style & ~(WS_POPUP); + style = style & ~(WS_CHILD); // WS_CHILD Crashes tcltk with reaper + style = style & ~(WS_SYSMENU); + style = style & ~(WS_BORDER); + style = style & ~(WS_HSCROLL); + style = style & ~(WS_VSCROLL); + style = style & ~(WS_SIZEBOX); + style = style & ~(WS_CAPTION); + SetWindowLong(pdGuiWindow,GWL_STYLE,style); + MoveWindow(pdGuiWindow, 0,0,((pdvst *)this->effect)->customGuiWidth,((pdvst *)this->effect)->customGuiHeight,TRUE); + systemWindowHidden=true; + } + } + } + AEffEditor::idle(); +} + +LONG WINAPI pdvstEditor::windowProc(HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + pdvstEditor *self = (pdvstEditor *)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (message == WM_COMMAND) + { + if (HIWORD(wParam) == BN_CLICKED && + (HWND)lParam == self->openButton) + { + // ((pdvst *)self->effect)->sendGuiAction(1); + } + } + + return (DefWindowProc(hwnd, message, wParam, lParam)); +} + + + + BOOL CALLBACK enumwnd(HWND hwnd,LPARAM lParam) +{ + enumparms *parms = (enumparms *)lParam; + char buf[256]; + GetWindowText(hwnd,buf,sizeof buf); + if(parms->exact? strcmp(buf,parms->s) == 0 : strstr(buf,parms->s) != NULL) { + *parms->ref = hwnd; + return FALSE; + } + else { + // also search for child windows + EnumChildWindows(hwnd,enumwnd,lParam); + return TRUE; + } +} +// *********** diff --git a/vst-template/pdvstEditor.hpp b/vst-template/pdvstEditor.hpp new file mode 100644 index 0000000..ce92428 --- /dev/null +++ b/vst-template/pdvstEditor.hpp @@ -0,0 +1,61 @@ +/* PdVst v0.0.2 - VST - Pd bridging plugin +** Copyright (C) 2004 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#ifndef __pdvstEditor +#define __pdvstEditor +#include +#include +#include "aeffeditor.h" + + typedef struct _enumparms + { + HWND *ref; + char s[1024]; + bool exact; + }enumparms; + +class pdvstEditor : public AEffEditor +{ + friend class pdvst; +public: + pdvstEditor(AudioEffect *effect); + virtual ~pdvstEditor (); + + HWND openButton;; + HWND editWindow; + HWND pdGuiWindow; + static LONG WINAPI windowProc(HWND mhwnd, UINT message, + WPARAM wParam, LPARAM lParam); + +protected: + virtual bool getRect(ERect **erect); + virtual bool open(void *ptr); + virtual void close(); + virtual void idle(); + + +private: + void *systemWindow; + bool systemWindowHidden; + enumparms parms; + +}; +#endif +static BOOL CALLBACK enumwnd(HWND hwnd,LPARAM lParam); diff --git a/vst-template/pdvstMain.cpp b/vst-template/pdvstMain.cpp new file mode 100644 index 0000000..6c6b813 --- /dev/null +++ b/vst-template/pdvstMain.cpp @@ -0,0 +1,383 @@ +/* PdVst v0.0.2 - VST - Pd bridging plugin +** Copyright (C) 2004 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ +#include +#include +#include "pdvst.hpp" +#include + +static AudioEffect *effect = 0; +bool oome = false; +//HINSTANCE hInstance; +bool globalIsASynth = false; +bool globalDebug = false; +int globalNChannels = 0; +int globalNPrograms = 0; +int globalNParams = 0; +int globalNExternalLibs = 0; +long globalPluginId = 'pdvp'; +char globalExternalLib[MAXEXTERNS][MAXSTRLEN]; +char globalVstParamName[MAXPARAMS][MAXSTRLEN]; +char globalPluginPath[MAXFILENAMELEN]; +char globalVstPluginPath[MAXFILENAMELEN]; +char globalPluginName[MAXSTRLEN]; +char globalPdFile[MAXFILENAMELEN]; +char globalPureDataPath[MAXFILENAMELEN]; +char globalHostPdvstPath[MAXFILENAMELEN]; +bool globalCustomGui = false; +int globalCustomGuiWidth= 320; +int globalCustomGuiHeight= 150; +pdvstProgram globalProgram[MAXPROGRAMS]; + +char *trimWhitespace(char *str); +void parseSetupFile(); + + +#include "audioeffect.h" + +//------------------------------------------------------------------------ +/** Must be implemented externally. */ +extern AudioEffect* createEffectInstance (audioMasterCallback audioMaster); + +extern "C" { +#if defined (__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) + #define VST_EXPORT __attribute__ ((visibility ("default"))) +#else + #define VST_EXPORT +#endif + +VST_EXPORT AEffect *VSTPluginMain(audioMasterCallback audioMaster) +{ + // get vst version + if (!audioMaster(0, audioMasterVersion, 0, 0, 0, 0)) + return 0; // old version + +// Create the AudioEffect + AudioEffect* effect = createEffectInstance (audioMaster); + if (!effect) + return 0; + + return effect->getAeffect(); +} + +// support for old hosts not looking for VSTPluginMain +#if (TARGET_API_MAC_CARBON && __ppc__) +VST_EXPORT AEffect* main_macho (audioMasterCallback audioMaster) { return VSTPluginMain (audioMaster); } +#elif WIN32 +VST_EXPORT AEffect* MAIN (audioMasterCallback audioMaster) { return VSTPluginMain (audioMaster); } +#elif BEOS +VST_EXPORT AEffect* main_plugin (audioMasterCallback audioMaster) { return VSTPluginMain (audioMaster); } +#endif + +} // extern "C" + + + + +#if WIN32 +#include +void* hInstance; + +extern "C" { + +BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved) +{ + hInstance = hInst; + parseSetupFile(); + return 1; +} +} // extern "C" +#endif + + +char *trimWhitespace(char *str) +{ + char *buf; + + if (strlen(str) > 0) + { + buf = str; + while (isspace(*buf) && (buf - str) <= (int)strlen(str)) + buf++; + memmove(str, buf, (strlen(buf) + 1) * sizeof(char)); + if (strlen(str) > 0) + { + buf = str + strlen(str) - 1; + while (isspace(*buf) && (buf >= str)) + { + *buf = 0; + buf--; + } + } + } + return (str); +} + +void parseSetupFile() +{ + FILE *setupFile; + char setupFileName[MAXFILENAMELEN]; + char tFileName[MAXFILENAMELEN]; + char line[MAXSTRLEN]; + char param[MAXSTRLEN]; + char value[MAXSTRLEN]; + char vstDataPath[MAXSTRLEN]; + char vstSetupFileName[MAXSTRLEN]; // path to setup file if it is located in vst subdir + int i, equalPos, progNum = -1; + + // find filepaths + GetModuleFileName((HMODULE)hInstance, + (LPTSTR)tFileName, + (DWORD)MAXFILENAMELEN); + + if (strrchr(tFileName, '\\')) + { + strcpy(globalPluginName, strrchr(tFileName, '\\') + 1); + } + else + { + strcpy(globalPluginName, tFileName); + } + + // alternate setup file path in vst plugins folder + if (strrchr(tFileName, '\\')) + { + + strcpy(vstDataPath, tFileName); + *(strrchr(vstDataPath, '\\') + 1) = 0; + sprintf(vstDataPath, "%s%s\\", vstDataPath,globalPluginName); + // remove .dll extension (from globalPluginName) + if (strstr(vstDataPath, ".dll")) + *(strstr(vstDataPath, ".dll")) = 0; + if (strstr(vstDataPath, ".DLL")) + *(strstr(vstDataPath, ".DLL")) = 0; + sprintf(vstDataPath, "%s\\", vstDataPath); // + // path to alternate setup file + sprintf(vstSetupFileName,"%s%s",vstDataPath,globalPluginName); + // remove .dll extension + if (strstr(vstSetupFileName, ".dll")) + *(strstr(vstSetupFileName, ".dll")) = 0; + if (strstr(vstSetupFileName, ".DLL")) + *(strstr(vstSetupFileName, ".DLL")) = 0; + // add SETUPFILEEXT extension + sprintf(vstSetupFileName,"%s%s",vstSetupFileName,SETUPFILEEXT); + //MessageBox(NULL, vstDataPath,"vstDataPath",MB_OK) ; + //MessageBox(NULL, vstSetupFileName,"vstSetupFileName",MB_OK) ; + + + } + + + GetModuleFileName(NULL, + (LPTSTR)tFileName, + (DWORD)MAXFILENAMELEN); + if (strrchr(tFileName, '\\')) + { + strcpy(globalPluginPath, tFileName); + *(strrchr(globalPluginPath, '\\') + 1) = 0; + sprintf(globalPluginPath, "%spdvst\\", globalPluginPath); + } + else + { + strcpy(globalPluginPath, tFileName); + } + strcpy(globalHostPdvstPath,globalPluginPath); + + // remove .dll extension + if (strstr(strlwr(globalPluginName), ".dll")) + *(strstr(strlwr(globalPluginName), ".dll")) = 0; + sprintf(setupFileName, + "%s%s%s", + globalPluginPath, + globalPluginName, + SETUPFILEEXT); + + + + // initialize program info + + + + strcpy(globalProgram[0].name, "Default"); + memset(globalProgram[0].paramValue, 0, MAXPARAMS * sizeof(float)); + // initialize parameter info + globalNParams = 0; + for (i = 0; i < MAXPARAMS; i++) + strcpy(globalVstParamName[i], ""); + globalNPrograms = 1; + + + // check existence of setup file in vst-subfolder + if( access(vstSetupFileName, F_OK ) != -1 ) + // if exists choose this alternate file + { + setupFile = fopen(vstSetupFileName, "r"); + //strcpy(setupFileName,vstSetupFileName); + strcpy(globalPluginPath,vstDataPath); + + } + else + setupFile = fopen(setupFileName, "r"); + // parse the setup file + if (setupFile) { + while (fgets(line, sizeof(line), setupFile)) + { + equalPos = strchr(line, '=') - line; + if (equalPos > 0 && line[0] != '#') + { + strcpy(param, line); + param[equalPos] = 0; + strcpy(value, line + equalPos + 1); + strcpy(param, trimWhitespace(strlwr(param))); + strcpy(value, trimWhitespace(value)); + // number of channels + if (strcmp(param, "channels") == 0) + globalNChannels = atoi(value); + + // main PD patch + if (strcmp(param, "main") == 0) + { + // strcpy(globalPdFile, strlwr(value)); + strcpy(globalPdFile, value); + } + if (strcmp(param, "pdpath") == 0) + { + // strcpy(globalPureDataPath, strlwr(value)); + strcpy(globalPureDataPath, value); + + } + // vst plugin ID + if (strcmp(param, "id") == 0) + { + globalPluginId = 0; + for (i = 0; i < 4; i++) + globalPluginId += (long)pow((double)16,(int) (i * 2)) * value[3 - i]; + } + // is vst instrument + if (strcmp(param, "synth") == 0) + { + if (strcmp(strlwr(value), "true") == 0) + { + globalIsASynth = true; + } + else if (strcmp(strlwr(value), "false") == 0) + { + globalIsASynth = false; + } + } + // external libraries + if (strcmp(param, "lib") == 0) + { + while (strlen(value) > 0) + { + if (strchr(value, ',') == NULL) + { + strcpy(globalExternalLib[globalNExternalLibs], value); + value[0] = 0; + } + else + { + int commaIndex = strchr(value, ',') - value; + strncpy(globalExternalLib[globalNExternalLibs], + value, + commaIndex); + memmove(value, + value + commaIndex + 1, + (strlen(value) - commaIndex) * sizeof(char)); + strcpy(value, trimWhitespace(value)); + } + globalNExternalLibs++; + } + } + // has custom gui + if (strcmp(param, "customgui") == 0) + { + if (strcmp(strlwr(value), "true") == 0) + { + globalCustomGui = true; + } + else if (strcmp(strlwr(value), "false") == 0) + { + globalCustomGui = false; + } + + } + // custom gui height + if (strcmp(param, "guiheight") == 0) + globalCustomGuiHeight = atoi(value); + + // custom gui width + if (strcmp(param, "guiwidth") == 0) + { + globalCustomGuiWidth = atoi(value); + + } + // debug (show Pd GUI) + if (strcmp(param, "debug") == 0) + { + if (strcmp(strlwr(value), "true") == 0) + { + globalDebug = true; + } + else if (strcmp(strlwr(value), "false") == 0) + { + globalDebug = false; + } + } + // number of parameters + if (strcmp(param, "parameters") == 0) + { + int numParams = atoi(value); + + if (numParams >= 0 && numParams < MAXPARAMS) + globalNParams = numParams; + } + // parameters names + if (strstr(param, "nameparameter") == \ + param && globalNPrograms < MAXPARAMS) + { + int paramNum = atoi(param + strlen("nameparameter")); + + if (paramNum < MAXPARAMS && paramNum >= 0) + strcpy(globalVstParamName[paramNum], value); + } + // program name + if (strcmp(param, "program") == 0 && \ + globalNPrograms < MAXPROGRAMS) + { + progNum++; + strcpy(globalProgram[progNum].name, value); + globalNPrograms = progNum + 1; + } + // program parameters + if (strstr(param, "parameter") == \ + param && globalNPrograms < MAXPROGRAMS && + !isalpha(param[strlen("parameter")])) + { + int paramNum = atoi(param + strlen("parameter")); + + if (paramNum < MAXPARAMS && paramNum >= 0) + globalProgram[progNum].paramValue[paramNum] = \ + (float)atof(value); + } + } + } + } + fclose(setupFile); +} diff --git a/vst-template/pdvstTransfer.h b/vst-template/pdvstTransfer.h new file mode 100644 index 0000000..ec6f84a --- /dev/null +++ b/vst-template/pdvstTransfer.h @@ -0,0 +1,135 @@ +/* PdVst v0.0.2 - VST - Pd bridging plugin +** Copyright (C) 2004 Joseph A. Sarlo +** +** This program is free software; you can redistribute it and/orsig +** modify it under the terms of the GNU General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +** +** jsarlo@ucsd.edu +*/ + +#ifndef __pdvstTransfer_H +#define __pdvstTransfer_H + +#include +#define VSTMIDIOUTENABLE +#define MAXCHANNELS 16 +#define MAXPARAMETERS 128 +#define MAXBLOCKSIZE 256 +#define MAXSTRINGSIZE 4096 +#define MAXMIDIQUEUESIZE 1024 + +//#ifdef VSTMIDIOUTENABLE + #define MAXMIDIOUTQUEUESIZE 1024 +//#endif // VSTMIDIOUTENABLE + + + + + +typedef enum _pdvstParameterDataType +{ + FLOAT_TYPE, + STRING_TYPE +} pdvstParameterDataType; + +typedef enum _pdvstParameterState +{ + PD_SEND, + PD_RECEIVE +} pdvstParameterState; + +typedef enum _pdvstMidiMessageType +{ + NOTE_OFF, + NOTE_ON, + KEY_PRESSURE, + CONTROLLER_CHANGE, + PROGRAM_CHANGE, + CHANNEL_PRESSURE, + PITCH_BEND, + OTHER +} pdvstMidiMessageType; + +typedef union _pdvstParameterData +{ + float floatData; + char stringData[MAXSTRINGSIZE]; +} pdvstParameterData; + +typedef struct _pdvstParameter +{ + int updated; + pdvstParameterDataType type; + pdvstParameterData value; + pdvstParameterState direction; +} pdvstParameter; + +typedef struct _pdvstMidiMessage +{ + pdvstMidiMessageType messageType; + int channelNumber; + char statusByte; + char dataByte1; + char dataByte2; +} pdvstMidiMessage; + +typedef struct _vstTimeInfo +{ + int updated; +//------------------------------------------------------------------------------------------------------- + double samplePos; ///< current Position in audio samples (always valid) + double sampleRate; ///< current Sample Rate in Herz (always valid) + double nanoSeconds; ///< System Time in nanoseconds (10^-9 second) + double ppqPos; ///< Musical Position, in Quarter Note (1.0 equals 1 Quarter Note) + double tempo; ///< current Tempo in BPM (Beats Per Minute) + double barStartPos; ///< last Bar Start Position, in Quarter Note + double cycleStartPos; ///< Cycle Start (left locator), in Quarter Note + double cycleEndPos; ///< Cycle End (right locator), in Quarter Note + int timeSigNumerator; ///< Time Signature Numerator (e.g. 3 for 3/4) + int timeSigDenominator; ///< Time Signature Denominator (e.g. 4 for 3/4) + int smpteOffset; ///< SMPTE offset (in SMPTE subframes (bits; 1/80 of a frame)). The current SMPTE position can be calculated using #samplePos, #sampleRate, and #smpteFrameRate. + int smpteFrameRate; ///< @see VstSmpteFrameRate + int samplesToNextClock; ///< MIDI Clock Resolution (24 Per Quarter Note), can be negative (nearest clock) + int flags; ///< @see VstTimeInfoFlags +//------------------------------------------------------------------------------------------------------- +}pdvstTimeInfo; + + +typedef struct _pdvstTransferData +{ + int active; + int syncToVst; + int nChannels; + int sampleRate; + int blockSize; + int nParameters; + int midiQueueSize; + int midiQueueUpdated; + float samples[MAXCHANNELS][MAXBLOCKSIZE]; + pdvstParameter vstParameters[MAXPARAMETERS]; + pdvstMidiMessage midiQueue[MAXMIDIQUEUESIZE]; + pdvstParameter guiState; + pdvstParameter plugName; // transmitted by host + pdvstParameter guiName; // transmitted by pd : name of gui window to be embedded + // #ifdef VSTMIDIOUTENABLE + int midiOutQueueSize; + int midiOutQueueUpdated; + pdvstMidiMessage midiOutQueue[MAXMIDIOUTQUEUESIZE]; + + // #endif // VSTMIDIOUTENABLE + pdvstTimeInfo hostTimeInfo; + +} pdvstTransferData; + +#endif