From 5b43da5a8491e6bb577b9e508c55c9619a1a850f Mon Sep 17 00:00:00 2001 From: Jamie Bullock Date: Wed, 8 Dec 2010 09:45:09 +0000 Subject: - moved dssi to pluginhost~ in preparation for renaming svn path=/trunk/externals/postlude/; revision=14575 --- dssi/README | 45 - dssi/RELEASE | 21 - dssi/doc/dssi-help.pd | 172 --- dssi/doc/output~.pd | 69 - dssi/gpl.txt | 340 ----- dssi/include/alsa/seq_event.h | 452 ------ dssi/include/dssi.h | 426 ------ dssi/include/ladspa.h | 603 -------- dssi/lesser.txt | 504 ------- dssi/makefile | 66 - dssi/src/dssi~.c | 2537 ---------------------------------- dssi/src/dssi~.h | 183 --- dssi/src/jload.c | 214 --- dssi/src/jsearch.c | 154 --- dssi/src/jutils.h | 69 - pluginhost~/README | 45 + pluginhost~/RELEASE | 21 + pluginhost~/doc/dssi-help.pd | 172 +++ pluginhost~/doc/output~.pd | 69 + pluginhost~/gpl.txt | 340 +++++ pluginhost~/include/alsa/seq_event.h | 452 ++++++ pluginhost~/include/dssi.h | 426 ++++++ pluginhost~/include/ladspa.h | 603 ++++++++ pluginhost~/lesser.txt | 504 +++++++ pluginhost~/makefile | 66 + pluginhost~/src/dssi~.c | 2537 ++++++++++++++++++++++++++++++++++ pluginhost~/src/dssi~.h | 183 +++ pluginhost~/src/jload.c | 214 +++ pluginhost~/src/jsearch.c | 154 +++ pluginhost~/src/jutils.h | 69 + 30 files changed, 5855 insertions(+), 5855 deletions(-) delete mode 100644 dssi/README delete mode 100644 dssi/RELEASE delete mode 100644 dssi/doc/dssi-help.pd delete mode 100644 dssi/doc/output~.pd delete mode 100644 dssi/gpl.txt delete mode 100644 dssi/include/alsa/seq_event.h delete mode 100644 dssi/include/dssi.h delete mode 100644 dssi/include/ladspa.h delete mode 100644 dssi/lesser.txt delete mode 100755 dssi/makefile delete mode 100644 dssi/src/dssi~.c delete mode 100644 dssi/src/dssi~.h delete mode 100644 dssi/src/jload.c delete mode 100644 dssi/src/jsearch.c delete mode 100644 dssi/src/jutils.h create mode 100644 pluginhost~/README create mode 100644 pluginhost~/RELEASE create mode 100644 pluginhost~/doc/dssi-help.pd create mode 100644 pluginhost~/doc/output~.pd create mode 100644 pluginhost~/gpl.txt create mode 100644 pluginhost~/include/alsa/seq_event.h create mode 100644 pluginhost~/include/dssi.h create mode 100644 pluginhost~/include/ladspa.h create mode 100644 pluginhost~/lesser.txt create mode 100755 pluginhost~/makefile create mode 100644 pluginhost~/src/dssi~.c create mode 100644 pluginhost~/src/dssi~.h create mode 100644 pluginhost~/src/jload.c create mode 100644 pluginhost~/src/jsearch.c create mode 100644 pluginhost~/src/jutils.h diff --git a/dssi/README b/dssi/README deleted file mode 100644 index ab164e8..0000000 --- a/dssi/README +++ /dev/null @@ -1,45 +0,0 @@ -dssi~ - a DSSI host for Pure Data -================================= - -This directory (dssi) contains sourcecode and possibly binaries for a DSSI host for Pure Data. To find out more about DSSI visit http://dssi.sourceforge.net. - -The functionality of the external is demonstrated in in the help patch (dssi/doc/help-dssi.pd). - - - -Requirements ------------- - -To compile dssi~ the following are required; - -DSSI >= 0.9 -LADSPA SDK >= 1.x -liblo >= 0.12 -alsa/seq_event.h - included -pd headers >= 0.37 - -The help patch requires: - -PD >= 0.39 - - - -Installation ------------- - -From the same directory as the makefile type: - -make -make install (as root) - -Once compiled the binary file and help file should be placed in directories that are included in Pure Data's search path. - - - -License -------- - -All files included in the dssi/src/ directory, and all binary files (if included) are licensed under the GNU GPL Version 2 (see gpl.txt for details). - -All files included in the dssi/include/ directory are licensed under the GNU Lesser General Public License (see lesser.txt for details). - diff --git a/dssi/RELEASE b/dssi/RELEASE deleted file mode 100644 index 948c9ea..0000000 --- a/dssi/RELEASE +++ /dev/null @@ -1,21 +0,0 @@ - -0.93 - -- Fixed control in bug and a few others - -0.91 - --Fixed bugs created by adding LADSPA support - -0.89 - --Added support for LADSPA plugins mostly using code from plugin~ --Reorganised inlet/outlet structure - -0.83 - --Added FluidSynth-DSSI patch load support (i.e. soundfonts) - -0.82 - --Added hexter6 patch load support diff --git a/dssi/doc/dssi-help.pd b/dssi/doc/dssi-help.pd deleted file mode 100644 index b4e5ba3..0000000 --- a/dssi/doc/dssi-help.pd +++ /dev/null @@ -1,172 +0,0 @@ -#N canvas 186 66 1411 654 10; -#X obj 1268 524 catch~ mix; -#X text 602 15 dssi~ - a DSSI host for Pure Data --------------------------------- -; -#X obj 7 63 cnv 15 1400 300 empty empty dssi~_instance_1 20 12 0 14 --257472 -66577 0; -#X obj 443 203 line; -#X msg 443 182 \$1 10; -#X obj 441 225 expr $f1 / 127 * 16383; -#X msg 443 122 0; -#X floatatom 300 185 5 0 0 0 - - -; -#X floatatom 443 165 5 0 0 0 - - -; -#X msg 72 256 n \$1; -#X obj 110 256 r chan; -#X obj 51 231 list prepend n 2; -#X obj 300 226 list prepend c 2; -#X obj 51 208 pack f f; -#X msg 33 147 60; -#X msg 78 147 80; -#X msg 300 205 7 \$1; -#X obj 441 247 list prepend b 2 0; -#X obj 441 324 throw~ mix; -#X obj 119 148 hsl 128 15 60 80 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 0 1; -#X obj 167 206 select -1; -#X obj 356 250 r chan; -#X obj 303 146 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 0 1; -#X obj 446 144 hsl 128 15 -63 63 0 1 empty empty empty -2 -6 0 8 -262144 --1 -1 6350 1; -#X obj 600 291 r dssi1-config; -#X obj 708 179 s dssi1-config; -#X obj 912 178 s dssi1-config; -#X obj 1194 180 s dssi1-config; -#X floatatom 595 142 5 0 0 0 - - -; -#X msg 318 250 c \$1; -#X obj 528 268 r chan; -#X msg 473 268 b \$1 0; -#X obj 1014 337 s chan; -#X floatatom 1015 319 5 1 2 1 channel - -; -#X text 283 98 ----control change----; -#X obj 667 222 r chan; -#X text 447 97 ----pitch bend----; -#X text 585 97 --program change--; -#X text 105 96 -----notes-----; -#X text 718 97 --sysex patch/bank load--; -#X obj 5 371 cnv 15 600 300 empty empty dssi~_instance_2 20 12 0 14 --225280 -66577 0; -#X obj 435 620 throw~ mix; -#X obj 474 122 loadbang; -#X msg 613 221 p \$1 0; -#X text 940 96 --configuration--; -#X text 947 113 (key value pair); -#X text 867 279 Select channel (hexter instance) for note \, bend \, -program and control data:; -#X obj 595 199 list prepend p 2 0; -#X text 1126 98 --show/hide GUI--; -#X obj 1266 547 dssi/output~; -#X obj 49 186 makenote 80 10000; -#X msg 1282 136 reset; -#X msg 1340 136 reset 1; -#X text 1286 98 -reset plugin-; -#X text 1286 115 (all notes off); -#X obj 229 315 print; -#X msg 78 305 listplugins; -#X msg 101 329 info; -#X msg 709 134 dssi load TX-SYX/TFI2.SYX 2; -#X msg 710 154 dssi load TX-SYX/TFI1.SYX 1; -#X msg 910 134 dssi configure polyphony 10 2; -#X msg 911 156 dssi configure GLOBAL:polyphony 10; -#X msg 1134 114 dssi hide; -#X msg 1135 135 dssi show; -#X msg 1206 114 dssi show 2; -#X text 806 212 LAST ARGUMENT GIVES PLUGIN INSTANCE TO BE CONFIGURED -\, NO LAST ARGUMENT=(ALL INSTANCES); -#X obj 388 620 print; -#X text 738 458 Usage: [dssi~ <[path to libary:plugin name] or [plugin -name]> ]; -#X obj 229 291 dssi~ /usr/local/lib/dssi/hexter.so:hexter 2; -#X msg 193 342 control #1 445; -#X obj 451 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 7900 1; -#X obj 378 582 dssi~ sine_faaa 6 -------------; -#X obj 284 438 expr $f1 \; $f1*2 \; $f1*3 \; $f1*4 \; $f1*5 \; $f1*6 -; -#X obj 285 397 loadbang; -#X msg 285 419 220; -#X obj 471 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 6700 1; -#X obj 491 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 6700 1; -#X obj 511 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 6100 1; -#X obj 531 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 0 1; -#X obj 551 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 --1 -1 0 1; -#X text 591 561 <- Audio rate control inputs can be audio or control -values; -#X text 14 491 Experimental - use with caution!; -#X msg 54 509 plug sine_faac 6; -#X connect 0 0 49 0; -#X connect 0 0 49 1; -#X connect 3 0 5 0; -#X connect 4 0 3 0; -#X connect 5 0 17 0; -#X connect 6 0 23 0; -#X connect 7 0 16 0; -#X connect 8 0 4 0; -#X connect 9 0 11 1; -#X connect 10 0 9 0; -#X connect 11 0 68 0; -#X connect 12 0 68 0; -#X connect 13 0 11 0; -#X connect 14 0 50 0; -#X connect 15 0 50 0; -#X connect 16 0 12 0; -#X connect 17 0 68 0; -#X connect 19 0 50 0; -#X connect 20 1 50 0; -#X connect 21 0 29 0; -#X connect 22 0 7 0; -#X connect 23 0 8 0; -#X connect 24 0 68 0; -#X connect 28 0 47 0; -#X connect 29 0 12 1; -#X connect 30 0 31 0; -#X connect 31 0 17 1; -#X connect 33 0 32 0; -#X connect 35 0 43 0; -#X connect 42 0 6 0; -#X connect 43 0 47 1; -#X connect 47 0 68 0; -#X connect 50 0 13 0; -#X connect 50 1 13 1; -#X connect 51 0 27 0; -#X connect 52 0 27 0; -#X connect 56 0 68 0; -#X connect 57 0 68 0; -#X connect 58 0 25 0; -#X connect 59 0 25 0; -#X connect 60 0 26 0; -#X connect 61 0 26 0; -#X connect 62 0 27 0; -#X connect 63 0 27 0; -#X connect 64 0 27 0; -#X connect 68 0 55 0; -#X connect 68 1 18 0; -#X connect 68 2 18 0; -#X connect 69 0 68 0; -#X connect 70 0 71 2; -#X connect 71 0 66 0; -#X connect 71 1 41 0; -#X connect 71 2 41 0; -#X connect 71 3 41 0; -#X connect 71 4 41 0; -#X connect 71 5 41 0; -#X connect 71 6 41 0; -#X connect 72 0 71 1; -#X connect 72 1 71 3; -#X connect 72 2 71 5; -#X connect 72 3 71 7; -#X connect 72 4 71 9; -#X connect 72 5 71 11; -#X connect 73 0 74 0; -#X connect 74 0 72 0; -#X connect 75 0 71 4; -#X connect 76 0 71 6; -#X connect 77 0 71 8; -#X connect 78 0 71 10; -#X connect 79 0 71 12; -#X connect 82 0 71 0; diff --git a/dssi/doc/output~.pd b/dssi/doc/output~.pd deleted file mode 100644 index 4db0809..0000000 --- a/dssi/doc/output~.pd +++ /dev/null @@ -1,69 +0,0 @@ -#N canvas 0 0 757 675 12; -#X obj 516 522 t b; -#X obj 516 469 f; -#X obj 516 547 f; -#X msg 630 546 0; -#X obj 516 499 moses 1; -#X obj 630 518 t b f; -#X obj 596 479 moses 1; -#X obj 29 97 dbtorms; -#X obj 85 170 inlet~; -#X msg 278 300 \; pd dsp 1; -#X obj 29 170 line~; -#X obj 64 242 *~; -#X obj 64 272 dac~; -#X obj 29 127 pack 0 50; -#X text 121 146 audio in; -#X text 301 496 test if less than 1 -->; -#X text 267 523 if true convert to bang -->; -#X text 100 96 <-- convert from dB to linear units; -#X floatatom 278 221 3 0 100 0 dB - -; -#X obj 516 449 bng 15 250 50 0 empty empty mute -38 7 0 12 -262144 --1 -1; -#X text 118 126 <-- make a ramp to avoid clicks or zipper noise; -#X obj 148 170 inlet~; -#X obj 154 241 *~; -#X text 502 399 MUTE logic:; -#X obj 278 193 r \$0-master-lvl; -#X obj 516 573 s \$0-master-lvl; -#X obj 293 247 s \$0-master-out; -#X obj 29 71 r \$0-master-out; -#X obj 596 450 r \$0-master-out; -#X text 60 10 Level control abstraction \, used in many of the Pd example -patches. The level and mute controls show up on the parent \, calling -patch.; -#X text 229 549 previous nonzero master-lvl -->; -#X text 301 453 recall previous; -#X text 301 471 value of master-lvl -->; -#X text 16 310 automatically start DSP -->; -#X obj 85 192 hip~ 3; -#X obj 147 192 hip~ 3; -#X text 26 608 NOTE: This abstraction was written by Miller Puckette -\, and is include with the PD examples as part of the 'standard' PD -documentation. JB 23/05/05; -#X connect 0 0 2 0; -#X connect 1 0 4 0; -#X connect 2 0 25 0; -#X connect 3 0 25 0; -#X connect 4 0 0 0; -#X connect 4 1 5 0; -#X connect 5 0 3 0; -#X connect 6 1 2 1; -#X connect 7 0 13 0; -#X connect 8 0 34 0; -#X connect 10 0 22 0; -#X connect 10 0 11 0; -#X connect 11 0 12 0; -#X connect 13 0 10 0; -#X connect 18 0 9 0; -#X connect 18 0 26 0; -#X connect 19 0 1 0; -#X connect 21 0 35 0; -#X connect 22 0 12 1; -#X connect 24 0 18 0; -#X connect 27 0 7 0; -#X connect 28 0 1 1; -#X connect 28 0 6 0; -#X connect 34 0 11 1; -#X connect 35 0 22 1; -#X coords 0 0 1 1 65 55 1; diff --git a/dssi/gpl.txt b/dssi/gpl.txt deleted file mode 100644 index 3912109..0000000 --- a/dssi/gpl.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/dssi/include/alsa/seq_event.h b/dssi/include/alsa/seq_event.h deleted file mode 100644 index 6d59ca4..0000000 --- a/dssi/include/alsa/seq_event.h +++ /dev/null @@ -1,452 +0,0 @@ -/** - * \file include/seq_event.h - * \brief Application interface library for the ALSA driver - * \author Jaroslav Kysela - * \author Abramo Bagnara - * \author Takashi Iwai - * \date 1998-2001 - * - * Application interface library for the ALSA driver - */ -/* - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __ALSA_SEQ_EVENT_H -#define __ALSA_SEQ_EVENT_H - -/** - * \defgroup SeqEvents Sequencer Event Definitions - * Sequencer Event Definitions - * \ingroup Sequencer - * \{ - */ - -/** - * Sequencer event data type - */ -typedef unsigned char snd_seq_event_type_t; - -/** Sequencer event type */ -enum snd_seq_event_type { - /** system status; event data type = #snd_seq_result_t */ - SND_SEQ_EVENT_SYSTEM = 0, - /** returned result status; event data type = #snd_seq_result_t */ - SND_SEQ_EVENT_RESULT, - - /** note on and off with duration; event data type = #snd_seq_ev_note_t */ - SND_SEQ_EVENT_NOTE = 5, - /** note on; event data type = #snd_seq_ev_note_t */ - SND_SEQ_EVENT_NOTEON, - /** note off; event data type = #snd_seq_ev_note_t */ - SND_SEQ_EVENT_NOTEOFF, - /** key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */ - SND_SEQ_EVENT_KEYPRESS, - - /** controller; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_CONTROLLER = 10, - /** program change; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_PGMCHANGE, - /** channel pressure; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_CHANPRESS, - /** pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */ - SND_SEQ_EVENT_PITCHBEND, - /** 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_CONTROL14, - /** 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_NONREGPARAM, - /** 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_REGPARAM, - - /** SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_SONGPOS = 20, - /** Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_SONGSEL, - /** midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_QFRAME, - /** SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_TIMESIGN, - /** SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */ - SND_SEQ_EVENT_KEYSIGN, - - /** MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_START = 30, - /** MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_CONTINUE, - /** MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_STOP, - /** Set tick queue position; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_SETPOS_TICK, - /** Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_SETPOS_TIME, - /** (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_TEMPO, - /** MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_CLOCK, - /** MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_TICK, - /** Queue timer skew; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_QUEUE_SKEW, - /** Sync position changed; event data type = #snd_seq_ev_queue_control_t */ - SND_SEQ_EVENT_SYNC_POS, - - /** Tune request; event data type = none */ - SND_SEQ_EVENT_TUNE_REQUEST = 40, - /** Reset to power-on state; event data type = none */ - SND_SEQ_EVENT_RESET, - /** Active sensing event; event data type = none */ - SND_SEQ_EVENT_SENSING, - - /** Echo-back event; event data type = any type */ - SND_SEQ_EVENT_ECHO = 50, - /** OSS emulation raw event; event data type = any type */ - SND_SEQ_EVENT_OSS, - - /** New client has connected; event data type = #snd_seq_addr_t */ - SND_SEQ_EVENT_CLIENT_START = 60, - /** Client has left the system; event data type = #snd_seq_addr_t */ - SND_SEQ_EVENT_CLIENT_EXIT, - /** Client status/info has changed; event data type = #snd_seq_addr_t */ - SND_SEQ_EVENT_CLIENT_CHANGE, - /** New port was created; event data type = #snd_seq_addr_t */ - SND_SEQ_EVENT_PORT_START, - /** Port was deleted from system; event data type = #snd_seq_addr_t */ - SND_SEQ_EVENT_PORT_EXIT, - /** Port status/info has changed; event data type = #snd_seq_addr_t */ - SND_SEQ_EVENT_PORT_CHANGE, - - /** Ports connected; event data type = #snd_seq_connect_t */ - SND_SEQ_EVENT_PORT_SUBSCRIBED, - /** Ports disconnected; event data type = #snd_seq_connect_t */ - SND_SEQ_EVENT_PORT_UNSUBSCRIBED, - - /** Sample select; event data type = #snd_seq_ev_sample_control_t */ - SND_SEQ_EVENT_SAMPLE = 70, - /** Sample cluster select; event data type = #snd_seq_ev_sample_control_t */ - SND_SEQ_EVENT_SAMPLE_CLUSTER, - /** voice start */ - SND_SEQ_EVENT_SAMPLE_START, - /** voice stop */ - SND_SEQ_EVENT_SAMPLE_STOP, - /** playback frequency */ - SND_SEQ_EVENT_SAMPLE_FREQ, - /** volume and balance */ - SND_SEQ_EVENT_SAMPLE_VOLUME, - /** sample loop */ - SND_SEQ_EVENT_SAMPLE_LOOP, - /** sample position */ - SND_SEQ_EVENT_SAMPLE_POSITION, - /** private (hardware dependent) event */ - SND_SEQ_EVENT_SAMPLE_PRIVATE1, - - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR0 = 90, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR1, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR2, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR3, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR4, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR5, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR6, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR7, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR8, - /** user-defined event; event data type = any (fixed size) */ - SND_SEQ_EVENT_USR9, - - /** begin of instrument management */ - SND_SEQ_EVENT_INSTR_BEGIN = 100, - /** end of instrument management */ - SND_SEQ_EVENT_INSTR_END, - /** query instrument interface info */ - SND_SEQ_EVENT_INSTR_INFO, - /** result of instrument interface info */ - SND_SEQ_EVENT_INSTR_INFO_RESULT, - /** query instrument format info */ - SND_SEQ_EVENT_INSTR_FINFO, - /** result of instrument format info */ - SND_SEQ_EVENT_INSTR_FINFO_RESULT, - /** reset instrument instrument memory */ - SND_SEQ_EVENT_INSTR_RESET, - /** get instrument interface status */ - SND_SEQ_EVENT_INSTR_STATUS, - /** result of instrument interface status */ - SND_SEQ_EVENT_INSTR_STATUS_RESULT, - /** put an instrument to port */ - SND_SEQ_EVENT_INSTR_PUT, - /** get an instrument from port */ - SND_SEQ_EVENT_INSTR_GET, - /** result of instrument query */ - SND_SEQ_EVENT_INSTR_GET_RESULT, - /** free instrument(s) */ - SND_SEQ_EVENT_INSTR_FREE, - /** get instrument list */ - SND_SEQ_EVENT_INSTR_LIST, - /** result of instrument list */ - SND_SEQ_EVENT_INSTR_LIST_RESULT, - /** set cluster parameters */ - SND_SEQ_EVENT_INSTR_CLUSTER, - /** get cluster parameters */ - SND_SEQ_EVENT_INSTR_CLUSTER_GET, - /** result of cluster parameters */ - SND_SEQ_EVENT_INSTR_CLUSTER_RESULT, - /** instrument change */ - SND_SEQ_EVENT_INSTR_CHANGE, - - /** system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */ - SND_SEQ_EVENT_SYSEX = 130, - /** error event; event data type = #snd_seq_ev_ext_t */ - SND_SEQ_EVENT_BOUNCE, - /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ - SND_SEQ_EVENT_USR_VAR0 = 135, - /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ - SND_SEQ_EVENT_USR_VAR1, - /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ - SND_SEQ_EVENT_USR_VAR2, - /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ - SND_SEQ_EVENT_USR_VAR3, - /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ - SND_SEQ_EVENT_USR_VAR4, - - /** NOP; ignored in any case */ - SND_SEQ_EVENT_NONE = 255 -}; - - -/** Sequencer event address */ -typedef struct snd_seq_addr { - unsigned char client; /**< Client id */ - unsigned char port; /**< Port id */ -} snd_seq_addr_t; - -/** Connection (subscription) between ports */ -typedef struct snd_seq_connect { - snd_seq_addr_t sender; /**< sender address */ - snd_seq_addr_t dest; /**< destination address */ -} snd_seq_connect_t; - - -/** Real-time data record */ -typedef struct snd_seq_real_time { - unsigned int tv_sec; /**< seconds */ - unsigned int tv_nsec; /**< nanoseconds */ -} snd_seq_real_time_t; - -/** (MIDI) Tick-time data record */ -typedef unsigned int snd_seq_tick_time_t; - -/** unioned time stamp */ -typedef union snd_seq_timestamp { - snd_seq_tick_time_t tick; /**< tick-time */ - struct snd_seq_real_time time; /**< real-time */ -} snd_seq_timestamp_t; - - -/** - * Event mode flags - * - * NOTE: only 8 bits available! - */ -#define SND_SEQ_TIME_STAMP_TICK (0<<0) /**< timestamp in clock ticks */ -#define SND_SEQ_TIME_STAMP_REAL (1<<0) /**< timestamp in real time */ -#define SND_SEQ_TIME_STAMP_MASK (1<<0) /**< mask for timestamp bits */ - -#define SND_SEQ_TIME_MODE_ABS (0<<1) /**< absolute timestamp */ -#define SND_SEQ_TIME_MODE_REL (1<<1) /**< relative to current time */ -#define SND_SEQ_TIME_MODE_MASK (1<<1) /**< mask for time mode bits */ - -#define SND_SEQ_EVENT_LENGTH_FIXED (0<<2) /**< fixed event size */ -#define SND_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /**< variable event size */ -#define SND_SEQ_EVENT_LENGTH_VARUSR (2<<2) /**< variable event size - user memory space */ -#define SND_SEQ_EVENT_LENGTH_MASK (3<<2) /**< mask for event length bits */ - -#define SND_SEQ_PRIORITY_NORMAL (0<<4) /**< normal priority */ -#define SND_SEQ_PRIORITY_HIGH (1<<4) /**< event should be processed before others */ -#define SND_SEQ_PRIORITY_MASK (1<<4) /**< mask for priority bits */ - - -/** Note event */ -typedef struct snd_seq_ev_note { - unsigned char channel; /**< channel number */ - unsigned char note; /**< note */ - unsigned char velocity; /**< velocity */ - unsigned char off_velocity; /**< note-off velocity; only for #SND_SEQ_EVENT_NOTE */ - unsigned int duration; /**< duration until note-off; only for #SND_SEQ_EVENT_NOTE */ -} snd_seq_ev_note_t; - -/** Controller event */ -typedef struct snd_seq_ev_ctrl { - unsigned char channel; /**< channel number */ - unsigned char unused[3]; /**< reserved */ - unsigned int param; /**< control parameter */ - signed int value; /**< control value */ -} snd_seq_ev_ctrl_t; - -/** generic set of bytes (12x8 bit) */ -typedef struct snd_seq_ev_raw8 { - unsigned char d[12]; /**< 8 bit value */ -} snd_seq_ev_raw8_t; - -/** generic set of integers (3x32 bit) */ -typedef struct snd_seq_ev_raw32 { - unsigned int d[3]; /**< 32 bit value */ -} snd_seq_ev_raw32_t; - -/** external stored data */ -typedef struct snd_seq_ev_ext { - unsigned int len; /**< length of data */ - void *ptr; /**< pointer to data (note: can be 64-bit) */ -} __attribute__((packed)) snd_seq_ev_ext_t; - -/** Instrument cluster type */ -typedef unsigned int snd_seq_instr_cluster_t; - -/** Instrument type */ -typedef struct snd_seq_instr { - snd_seq_instr_cluster_t cluster; /**< cluster id */ - unsigned int std; /**< instrument standard id; the upper byte means a private instrument (owner - client id) */ - unsigned short bank; /**< instrument bank id */ - unsigned short prg; /**< instrument program id */ -} snd_seq_instr_t; - -/** sample number */ -typedef struct snd_seq_ev_sample { - unsigned int std; /**< sample standard id */ - unsigned short bank; /**< sample bank id */ - unsigned short prg; /**< sample program id */ -} snd_seq_ev_sample_t; - -/** sample cluster */ -typedef struct snd_seq_ev_cluster { - snd_seq_instr_cluster_t cluster; /**< cluster id */ -} snd_seq_ev_cluster_t; - -/** sample position */ -typedef unsigned int snd_seq_position_t; /**< playback position (in samples) * 16 */ - -/** sample stop mode */ -typedef enum snd_seq_stop_mode { - SND_SEQ_SAMPLE_STOP_IMMEDIATELY = 0, /**< terminate playing immediately */ - SND_SEQ_SAMPLE_STOP_VENVELOPE = 1, /**< finish volume envelope */ - SND_SEQ_SAMPLE_STOP_LOOP = 2 /**< terminate loop and finish wave */ -} snd_seq_stop_mode_t; - -/** sample frequency */ -typedef int snd_seq_frequency_t; /**< playback frequency in HZ * 16 */ - -/** sample volume control; if any value is set to -1 == do not change */ -typedef struct snd_seq_ev_volume { - signed short volume; /**< range: 0-16383 */ - signed short lr; /**< left-right balance; range: 0-16383 */ - signed short fr; /**< front-rear balance; range: 0-16383 */ - signed short du; /**< down-up balance; range: 0-16383 */ -} snd_seq_ev_volume_t; - -/** simple loop redefinition */ -typedef struct snd_seq_ev_loop { - unsigned int start; /**< loop start (in samples) * 16 */ - unsigned int end; /**< loop end (in samples) * 16 */ -} snd_seq_ev_loop_t; - -/** Sample control events */ -typedef struct snd_seq_ev_sample_control { - unsigned char channel; /**< channel */ - unsigned char unused[3]; /**< reserved */ - union { - snd_seq_ev_sample_t sample; /**< sample number */ - snd_seq_ev_cluster_t cluster; /**< cluster number */ - snd_seq_position_t position; /**< position */ - snd_seq_stop_mode_t stop_mode; /**< stop mode */ - snd_seq_frequency_t frequency; /**< frequency */ - snd_seq_ev_volume_t volume; /**< volume */ - snd_seq_ev_loop_t loop; /**< loop control */ - unsigned char raw8[8]; /**< raw 8-bit */ - } param; /**< control parameters */ -} snd_seq_ev_sample_control_t; - - - -/** INSTR_BEGIN event */ -typedef struct snd_seq_ev_instr_begin { - int timeout; /**< zero = forever, otherwise timeout in ms */ -} snd_seq_ev_instr_begin_t; - -/** Result events */ -typedef struct snd_seq_result { - int event; /**< processed event type */ - int result; /**< status */ -} snd_seq_result_t; - -/** Queue skew values */ -typedef struct snd_seq_queue_skew { - unsigned int value; /**< skew value */ - unsigned int base; /**< skew base */ -} snd_seq_queue_skew_t; - -/** queue timer control */ -typedef struct snd_seq_ev_queue_control { - unsigned char queue; /**< affected queue */ - unsigned char unused[3]; /**< reserved */ - union { - signed int value; /**< affected value (e.g. tempo) */ - snd_seq_timestamp_t time; /**< time */ - unsigned int position; /**< sync position */ - snd_seq_queue_skew_t skew; /**< queue skew */ - unsigned int d32[2]; /**< any data */ - unsigned char d8[8]; /**< any data */ - } param; /**< data value union */ -} snd_seq_ev_queue_control_t; - - -/** Sequencer event */ -typedef struct snd_seq_event { - snd_seq_event_type_t type; /**< event type */ - unsigned char flags; /**< event flags */ - unsigned char tag; /**< tag */ - - unsigned char queue; /**< schedule queue */ - snd_seq_timestamp_t time; /**< schedule time */ - - snd_seq_addr_t source; /**< source address */ - snd_seq_addr_t dest; /**< destination address */ - - union { - snd_seq_ev_note_t note; /**< note information */ - snd_seq_ev_ctrl_t control; /**< MIDI control information */ - snd_seq_ev_raw8_t raw8; /**< raw8 data */ - snd_seq_ev_raw32_t raw32; /**< raw32 data */ - snd_seq_ev_ext_t ext; /**< external data */ - snd_seq_ev_queue_control_t queue; /**< queue control */ - snd_seq_timestamp_t time; /**< timestamp */ - snd_seq_addr_t addr; /**< address */ - snd_seq_connect_t connect; /**< connect information */ - snd_seq_result_t result; /**< operation result code */ - snd_seq_ev_instr_begin_t instr_begin; /**< instrument */ - snd_seq_ev_sample_control_t sample; /**< sample control */ - } data; /**< event data... */ -} snd_seq_event_t; - - -/** \} */ - -#endif /* __ALSA_SEQ_EVENT_H */ - diff --git a/dssi/include/dssi.h b/dssi/include/dssi.h deleted file mode 100644 index dd0cd91..0000000 --- a/dssi/include/dssi.h +++ /dev/null @@ -1,426 +0,0 @@ -/* -*- c-basic-offset: 4 -*- */ - -/* dssi.h - - DSSI version 0.9 - Copyright (c) 2004 Chris Cannam, Steve Harris and Sean Bolton - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation; either version 2.1 of - the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. -*/ - -#ifndef DSSI_INCLUDED -#define DSSI_INCLUDED - -#include -#include - -#define DSSI_VERSION "0.9" -#define DSSI_VERSION_MAJOR 0 -#define DSSI_VERSION_MINOR 9 - -#ifdef __cplusplus -extern "C" { -#endif - -/* - There is a need for an API that supports hosted MIDI soft synths - with GUIs in Linux audio applications. In time the GMPI initiative - should comprehensively address this need, but the requirement for - Linux applications to be able to support simple hosted synths is - here now, and GMPI is not. This proposal (the "DSSI Soft Synth - Interface" or DSSI, pronounced "dizzy") aims to provide a simple - solution in a way that we hope will prove complete and compelling - enough to support now, yet not so compelling as to supplant GMPI or - any other comprehensive future proposal. - - For simplicity and familiarity, this API is based as far as - possible on existing work -- the LADSPA plugin API for control - values and audio processing, and the ALSA sequencer event types for - MIDI event communication. The GUI part of the proposal is quite - new, but may also be applicable retroactively to LADSPA plugins - that do not otherwise support this synth interface. -*/ - -typedef struct _DSSI_Program_Descriptor { - - /** Bank number for this program. Note that DSSI does not support - MIDI-style separation of bank LSB and MSB values. There is no - restriction on the set of available banks: the numbers do not - need to be contiguous, there does not need to be a bank 0, etc. */ - unsigned long Bank; - - /** Program number (unique within its bank) for this program. - There is no restriction on the set of available programs: the - numbers do not need to be contiguous, there does not need to - be a program 0, etc. */ - unsigned long Program; - - /** Name of the program. */ - const char * Name; - -} DSSI_Program_Descriptor; - - -typedef struct _DSSI_Descriptor { - - /** - * DSSI_API_Version - * - * This member indicates the DSSI API level used by this plugin. - * If we're lucky, this will never be needed. For now all plugins - * must set it to 1. - */ - int DSSI_API_Version; - - /** - * LADSPA_Plugin - * - * A DSSI synth plugin consists of a LADSPA plugin plus an - * additional framework for controlling program settings and - * transmitting MIDI events. A plugin must fully implement the - * LADSPA descriptor fields as well as the required LADSPA - * functions including instantiate() and (de)activate(). It - * should also implement run(), with the same behaviour as if - * run_synth() (below) were called with no synth events. - * - * In order to instantiate a synth the host calls the LADSPA - * instantiate function, passing in this LADSPA_Descriptor - * pointer. The returned LADSPA_Handle is used as the argument - * for the DSSI functions below as well as for the LADSPA ones. - */ - const LADSPA_Descriptor *LADSPA_Plugin; - - /** - * configure() - * - * This member is a function pointer that sends a piece of - * configuration data to the plugin. The key argument specifies - * some aspect of the synth's configuration that is to be changed, - * and the value argument specifies a new value for it. A plugin - * that does not require this facility at all may set this member - * to NULL. - * - * This call is intended to set some session-scoped aspect of a - * plugin's behaviour, for example to tell the plugin to load - * sample data from a particular file. The plugin should act - * immediately on the request. The call should return NULL on - * success, or an error string that may be shown to the user. The - * host will free the returned value after use if it is non-NULL. - * - * Calls to configure() are not automated as timed events. - * Instead, a host should remember the last value associated with - * each key passed to configure() during a given session for a - * given plugin instance, and should call configure() with the - * correct value for each key the next time it instantiates the - * "same" plugin instance, for example on reloading a project in - * which the plugin was used before. Plugins should note that a - * host may typically instantiate a plugin multiple times with the - * same configuration values, and should share data between - * instances where practical. - * - * Calling configure() completely invalidates the program and bank - * information last obtained from the plugin. - * - * Reserved and special key prefixes - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * The DSSI: prefix - * ---------------- - * Configure keys starting with DSSI: are reserved for particular - * purposes documented in the DSSI specification. At the moment, - * there is one such key: DSSI:PROJECT_DIRECTORY. A host may call - * configure() passing this key and a directory path value. This - * indicates to the plugin and its UI that a directory at that - * path exists and may be used for project-local data. Plugins - * may wish to use the project directory as a fallback location - * when looking for other file data, or as a base for relative - * paths in other configuration values. - * - * The GLOBAL: prefix - * ------------------ - * Configure keys starting with GLOBAL: may be used by the plugin - * and its UI for any purpose, but are treated specially by the - * host. When one of these keys is used in a configure OSC call - * from the plugin UI, the host makes the corresponding configure - * call (preserving the GLOBAL: prefix) not only to the target - * plugin but also to all other plugins in the same instance - * group, as well as their UIs. Note that if any instance - * returns non-NULL from configure to indicate error, the host - * may stop there (and the set of plugins on which configure has - * been called will thus depend on the host implementation). - * See also the configure OSC call documentation in RFC.txt. - */ - char *(*configure)(LADSPA_Handle Instance, - const char *Key, - const char *Value); - - #define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:" - #define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:" - #define DSSI_PROJECT_DIRECTORY_KEY \ - DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY" - - /** - * get_program() - * - * This member is a function pointer that provides a description - * of a program (named preset sound) available on this synth. A - * plugin that does not support programs at all should set this - * member to NULL. - * - * The Index argument is an index into the plugin's list of - * programs, not a program number as represented by the Program - * field of the DSSI_Program_Descriptor. (This distinction is - * needed to support synths that use non-contiguous program or - * bank numbers.) - * - * This function returns a DSSI_Program_Descriptor pointer that is - * guaranteed to be valid only until the next call to get_program, - * deactivate, or configure, on the same plugin instance. This - * function must return NULL if passed an Index argument out of - * range, so that the host can use it to query the number of - * programs as well as their properties. - */ - const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance, - unsigned long Index); - - /** - * select_program() - * - * This member is a function pointer that selects a new program - * for this synth. The program change should take effect - * immediately at the start of the next run_synth() call. (This - * means that a host providing the capability of changing programs - * between any two notes on a track must vary the block size so as - * to place the program change at the right place. A host that - * wanted to avoid this would probably just instantiate a plugin - * for each program.) - * - * A plugin that does not support programs at all should set this - * member NULL. Plugins should ignore a select_program() call - * with an invalid bank or program. - * - * A plugin is not required to select any particular default - * program on activate(): it's the host's duty to set a program - * explicitly. The current program is invalidated by any call to - * configure(). - * - * A plugin is permitted to re-write the values of its input - * control ports when select_program is called. The host should - * re-read the input control port values and update its own - * records appropriately. (This is the only circumstance in - * which a DSSI plugin is allowed to modify its own input ports.) - */ - void (*select_program)(LADSPA_Handle Instance, - unsigned long Bank, - unsigned long Program); - - /** - * get_midi_controller_for_port() - * - * This member is a function pointer that returns the MIDI - * controller number or NRPN that should be mapped to the given - * input control port. If the given port should not have any MIDI - * controller mapped to it, the function should return DSSI_NONE. - * The behaviour of this function is undefined if the given port - * number does not correspond to an input control port. A plugin - * that does not want MIDI controllers mapped to ports at all may - * set this member NULL. - * - * Correct values can be got using the macros DSSI_CC(num) and - * DSSI_NRPN(num) as appropriate, and values can be combined using - * bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port - * should respond to CC #23 and NRPN #1069. - * - * The host is responsible for doing proper scaling from MIDI - * controller and NRPN value ranges to port ranges according to - * the plugin's LADSPA port hints. Hosts should not deliver - * through run_synth any MIDI controller events that have already - * been mapped to control port values. - * - * A plugin should not attempt to request mappings from - * controllers 0 or 32 (MIDI Bank Select MSB and LSB). - */ - int (*get_midi_controller_for_port)(LADSPA_Handle Instance, - unsigned long Port); - - /** - * run_synth() - * - * This member is a function pointer that runs a synth for a - * block. This is identical in function to the LADSPA run() - * function, except that it also supplies events to the synth. - * - * A plugin may provide this function, run_multiple_synths() (see - * below), both, or neither (if it is not in fact a synth). A - * plugin that does not provide this function must set this member - * to NULL. Authors of synth plugins are encouraged to provide - * this function if at all possible. - * - * The Events pointer points to a block of EventCount ALSA - * sequencer events, which is used to communicate MIDI and related - * events to the synth. Each event is timestamped relative to the - * start of the block, (mis)using the ALSA "tick time" field as a - * frame count. The host is responsible for ensuring that events - * with differing timestamps are already ordered by time. - * - * See also the notes on activation, port connection etc in - * ladpsa.h, in the context of the LADSPA run() function. - * - * Note Events - * ~~~~~~~~~~~ - * There are two minor requirements aimed at making the plugin - * writer's life as simple as possible: - * - * 1. A host must never send events of type SND_SEQ_EVENT_NOTE. - * Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON - * and NOTE_OFF events. A plugin should discard any one-point - * NOTE events it sees. - * - * 2. A host must not attempt to switch notes off by sending - * zero-velocity NOTE_ON events. It should always send true - * NOTE_OFFs. It is the host's responsibility to remap events in - * cases where an external MIDI source has sent it zero-velocity - * NOTE_ONs. - * - * Bank and Program Events - * ~~~~~~~~~~~~~~~~~~~~~~~ - * Hosts must map MIDI Bank Select MSB and LSB (0 and 32) - * controllers and MIDI Program Change events onto the banks and - * programs specified by the plugin, using the DSSI select_program - * call. No host should ever deliver a program change or bank - * select controller to a plugin via run_synth. - */ - void (*run_synth)(LADSPA_Handle Instance, - unsigned long SampleCount, - snd_seq_event_t *Events, - unsigned long EventCount); - - /** - * run_synth_adding() - * - * This member is a function pointer that runs an instance of a - * synth for a block, adding its outputs to the values already - * present at the output ports. This is provided for symmetry - * with LADSPA run_adding(), and is equally optional. A plugin - * that does not provide it must set this member to NULL. - */ - void (*run_synth_adding)(LADSPA_Handle Instance, - unsigned long SampleCount, - snd_seq_event_t *Events, - unsigned long EventCount); - - /** - * run_multiple_synths() - * - * This member is a function pointer that runs multiple synth - * instances for a block. This is very similar to run_synth(), - * except that Instances, Events, and EventCounts each point to - * arrays that hold the LADSPA handles, event buffers, and - * event counts for each of InstanceCount instances. That is, - * Instances points to an array of InstanceCount pointers to - * DSSI plugin instantiations, Events points to an array of - * pointers to each instantiation's respective event list, and - * EventCounts points to an array containing each instantiation's - * respective event count. - * - * A host using this function must guarantee that ALL active - * instances of the plugin are represented in each call to the - * function -- that is, a host may not call run_multiple_synths() - * for some instances of a given plugin and then call run_synth() - * as well for others. 'All .. instances of the plugin' means - * every instance sharing the same LADSPA label and shared object - * (*.so) file (rather than every instance sharing the same *.so). - * 'Active' means any instance for which activate() has been called - * but deactivate() has not. - * - * A plugin may provide this function, run_synths() (see above), - * both, or neither (if it not in fact a synth). A plugin that - * does not provide this function must set this member to NULL. - * Plugin authors implementing run_multiple_synths are strongly - * encouraged to implement run_synth as well if at all possible, - * to aid simplistic hosts, even where it would be less efficient - * to use it. - */ - void (*run_multiple_synths)(unsigned long InstanceCount, - LADSPA_Handle *Instances, - unsigned long SampleCount, - snd_seq_event_t **Events, - unsigned long *EventCounts); - - /** - * run_multiple_synths_adding() - * - * This member is a function pointer that runs multiple synth - * instances for a block, adding each synth's outputs to the - * values already present at the output ports. This is provided - * for symmetry with both the DSSI run_multiple_synths() and LADSPA - * run_adding() functions, and is equally optional. A plugin - * that does not provide it must set this member to NULL. - */ - void (*run_multiple_synths_adding)(unsigned long InstanceCount, - LADSPA_Handle *Instances, - unsigned long SampleCount, - snd_seq_event_t **Events, - unsigned long *EventCounts); -} DSSI_Descriptor; - -/** - * DSSI supports a plugin discovery method similar to that of LADSPA: - * - * - DSSI hosts may wish to locate DSSI plugin shared object files by - * searching the paths contained in the DSSI_PATH and LADSPA_PATH - * environment variables, if they are present. Both are expected - * to be colon-separated lists of directories to be searched (in - * order), and DSSI_PATH should be searched first if both variables - * are set. - * - * - Each shared object file containing DSSI plugins must include a - * function dssi_descriptor(), with the following function prototype - * and C-style linkage. Hosts may enumerate the plugin types - * available in the shared object file by repeatedly calling - * this function with successive Index values (beginning from 0), - * until a return value of NULL indicates no more plugin types are - * available. Each non-NULL return is the DSSI_Descriptor - * of a distinct plugin type. - */ - -const DSSI_Descriptor *dssi_descriptor(unsigned long Index); - -typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); - -/* - * Macros to specify particular MIDI controllers in return values from - * get_midi_controller_for_port() - */ - -#define DSSI_CC_BITS 0x20000000 -#define DSSI_NRPN_BITS 0x40000000 - -#define DSSI_NONE -1 -#define DSSI_CONTROLLER_IS_SET(n) (DSSI_NONE != (n)) - -#define DSSI_CC(n) (DSSI_CC_BITS | (n)) -#define DSSI_IS_CC(n) (DSSI_CC_BITS & (n)) -#define DSSI_CC_NUMBER(n) ((n) & 0x7f) - -#define DSSI_NRPN(n) (DSSI_NRPN_BITS | ((n) << 7)) -#define DSSI_IS_NRPN(n) (DSSI_NRPN_BITS & (n)) -#define DSSI_NRPN_NUMBER(n) (((n) >> 7) & 0x3fff) - -#ifdef __cplusplus -} -#endif - -#endif /* DSSI_INCLUDED */ diff --git a/dssi/include/ladspa.h b/dssi/include/ladspa.h deleted file mode 100644 index 5c30a8a..0000000 --- a/dssi/include/ladspa.h +++ /dev/null @@ -1,603 +0,0 @@ -/* ladspa.h - - Linux Audio Developer's Simple Plugin API Version 1.1[LGPL]. - Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, - Stefan Westerfeld. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation; either version 2.1 of - the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA. */ - -#ifndef LADSPA_INCLUDED -#define LADSPA_INCLUDED - -#define LADSPA_VERSION "1.1" -#define LADSPA_VERSION_MAJOR 1 -#define LADSPA_VERSION_MINOR 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ - -/* Overview: - - There is a large number of synthesis packages in use or development - on the Linux platform at this time. This API (`The Linux Audio - Developer's Simple Plugin API') attempts to give programmers the - ability to write simple `plugin' audio processors in C/C++ and link - them dynamically (`plug') into a range of these packages (`hosts'). - It should be possible for any host and any plugin to communicate - completely through this interface. - - This API is deliberately short and simple. To achieve compatibility - with a range of promising Linux sound synthesis packages it - attempts to find the `greatest common divisor' in their logical - behaviour. Having said this, certain limiting decisions are - implicit, notably the use of a fixed type (LADSPA_Data) for all - data transfer and absence of a parameterised `initialisation' - phase. See below for the LADSPA_Data typedef. - - Plugins are expected to distinguish between control and audio - data. Plugins have `ports' that are inputs or outputs for audio or - control data and each plugin is `run' for a `block' corresponding - to a short time interval measured in samples. Audio data is - communicated using arrays of LADSPA_Data, allowing a block of audio - to be processed by the plugin in a single pass. Control data is - communicated using single LADSPA_Data values. Control data has a - single value at the start of a call to the `run()' or `run_adding()' - function, and may be considered to remain this value for its - duration. The plugin may assume that all its input and output ports - have been connected to the relevant data location (see the - `connect_port()' function below) before it is asked to run. - - Plugins will reside in shared object files suitable for dynamic - linking by dlopen() and family. The file will provide a number of - `plugin types' that can be used to instantiate actual plugins - (sometimes known as `plugin instances') that can be connected - together to perform tasks. - - This API contains very limited error-handling. */ - -/*****************************************************************************/ - -/* Fundamental data type passed in and out of plugin. This data type - is used to communicate audio samples and control values. It is - assumed that the plugin will work sensibly given any numeric input - value although it may have a preferred range (see hints below). - - For audio it is generally assumed that 1.0f is the `0dB' reference - amplitude and is a `normal' signal level. */ - -typedef float LADSPA_Data; - -/*****************************************************************************/ - -/* Special Plugin Properties: - - Optional features of the plugin type are encapsulated in the - LADSPA_Properties type. This is assembled by ORing individual - properties together. */ - -typedef int LADSPA_Properties; - -/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a - real-time dependency (e.g. listens to a MIDI device) and so its - output must not be cached or subject to significant latency. */ -#define LADSPA_PROPERTY_REALTIME 0x1 - -/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin - may cease to work correctly if the host elects to use the same data - location for both input and output (see connect_port()). This - should be avoided as enabling this flag makes it impossible for - hosts to use the plugin to process audio `in-place.' */ -#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2 - -/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin - is capable of running not only in a conventional host but also in a - `hard real-time' environment. To qualify for this the plugin must - satisfy all of the following: - - (1) The plugin must not use malloc(), free() or other heap memory - management within its run() or run_adding() functions. All new - memory used in run() must be managed via the stack. These - restrictions only apply to the run() function. - - (2) The plugin will not attempt to make use of any library - functions with the exceptions of functions in the ANSI standard C - and C maths libraries, which the host is expected to provide. - - (3) The plugin will not access files, devices, pipes, sockets, IPC - or any other mechanism that might result in process or thread - blocking. - - (4) The plugin will take an amount of time to execute a run() or - run_adding() call approximately of form (A+B*SampleCount) where A - and B depend on the machine and host in use. This amount of time - may not depend on input signals or plugin state. The host is left - the responsibility to perform timings to estimate upper bounds for - A and B. */ -#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4 - -#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME) -#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN) -#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE) - -/*****************************************************************************/ - -/* Plugin Ports: - - Plugins have `ports' that are inputs or outputs for audio or - data. Ports can communicate arrays of LADSPA_Data (for audio - inputs/outputs) or single LADSPA_Data values (for control - input/outputs). This information is encapsulated in the - LADSPA_PortDescriptor type which is assembled by ORing individual - properties together. - - Note that a port must be an input or an output port but not both - and that a port must be a control or audio port but not both. */ - -typedef int LADSPA_PortDescriptor; - -/* Property LADSPA_PORT_INPUT indicates that the port is an input. */ -#define LADSPA_PORT_INPUT 0x1 - -/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */ -#define LADSPA_PORT_OUTPUT 0x2 - -/* Property LADSPA_PORT_CONTROL indicates that the port is a control - port. */ -#define LADSPA_PORT_CONTROL 0x4 - -/* Property LADSPA_PORT_AUDIO indicates that the port is a audio - port. */ -#define LADSPA_PORT_AUDIO 0x8 - -#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT) -#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT) -#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL) -#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO) - -/*****************************************************************************/ - -/* Plugin Port Range Hints: - - The host may wish to provide a representation of data entering or - leaving a plugin (e.g. to generate a GUI automatically). To make - this more meaningful, the plugin should provide `hints' to the host - describing the usual values taken by the data. - - Note that these are only hints. The host may ignore them and the - plugin must not assume that data supplied to it is meaningful. If - the plugin receives invalid input data it is expected to continue - to run without failure and, where possible, produce a sensible - output (e.g. a high-pass filter given a negative cutoff frequency - might switch to an all-pass mode). - - Hints are meaningful for all input and output ports but hints for - input control ports are expected to be particularly useful. - - More hint information is encapsulated in the - LADSPA_PortRangeHintDescriptor type which is assembled by ORing - individual hint types together. Hints may require further - LowerBound and UpperBound information. - - All the hint information for a particular port is aggregated in the - LADSPA_PortRangeHint structure. */ - -typedef int LADSPA_PortRangeHintDescriptor; - -/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field - of the LADSPA_PortRangeHint should be considered meaningful. The - value in this field should be considered the (inclusive) lower - bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also - specified then the value of LowerBound should be multiplied by the - sample rate. */ -#define LADSPA_HINT_BOUNDED_BELOW 0x1 - -/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field - of the LADSPA_PortRangeHint should be considered meaningful. The - value in this field should be considered the (inclusive) upper - bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also - specified then the value of UpperBound should be multiplied by the - sample rate. */ -#define LADSPA_HINT_BOUNDED_ABOVE 0x2 - -/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be - considered a Boolean toggle. Data less than or equal to zero should - be considered `off' or `false,' and data above zero should be - considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in - conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or - LADSPA_HINT_DEFAULT_1. */ -#define LADSPA_HINT_TOGGLED 0x4 - -/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified - should be interpreted as multiples of the sample rate. For - instance, a frequency range from 0Hz to the Nyquist frequency (half - the sample rate) could be requested by this hint in conjunction - with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds - at all must support this hint to retain meaning. */ -#define LADSPA_HINT_SAMPLE_RATE 0x8 - -/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the - user will find it more intuitive to view values using a logarithmic - scale. This is particularly useful for frequencies and gains. */ -#define LADSPA_HINT_LOGARITHMIC 0x10 - -/* Hint LADSPA_HINT_INTEGER indicates that a user interface would - probably wish to provide a stepped control taking only integer - values. Any bounds set should be slightly wider than the actual - integer range required to avoid floating point rounding errors. For - instance, the integer set {0,1,2,3} might be described as [-0.1, - 3.1]. */ -#define LADSPA_HINT_INTEGER 0x20 - -/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal' - value for the port that is sensible as a default. For instance, - this value is suitable for use as an initial value in a user - interface or as a value the host might assign to a control port - when the user has not provided one. Defaults are encoded using a - mask so only one default may be specified for a port. Some of the - hints make use of lower and upper bounds, in which case the - relevant bound or bounds must be available and - LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting - default must be rounded if LADSPA_HINT_INTEGER is present. Default - values were introduced in LADSPA v1.1. */ -#define LADSPA_HINT_DEFAULT_MASK 0x3C0 - -/* This default values indicates that no default is provided. */ -#define LADSPA_HINT_DEFAULT_NONE 0x0 - -/* This default hint indicates that the suggested lower bound for the - port should be used. */ -#define LADSPA_HINT_DEFAULT_MINIMUM 0x40 - -/* This default hint indicates that a low value between the suggested - lower and upper bounds should be chosen. For ports with - LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 + - log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper - * 0.25). */ -#define LADSPA_HINT_DEFAULT_LOW 0x80 - -/* This default hint indicates that a middle value between the - suggested lower and upper bounds should be chosen. For ports with - LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 + - log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper * - 0.5). */ -#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0 - -/* This default hint indicates that a high value between the suggested - lower and upper bounds should be chosen. For ports with - LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 + - log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper - * 0.75). */ -#define LADSPA_HINT_DEFAULT_HIGH 0x100 - -/* This default hint indicates that the suggested upper bound for the - port should be used. */ -#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140 - -/* This default hint indicates that the number 0 should be used. Note - that this default may be used in conjunction with - LADSPA_HINT_TOGGLED. */ -#define LADSPA_HINT_DEFAULT_0 0x200 - -/* This default hint indicates that the number 1 should be used. Note - that this default may be used in conjunction with - LADSPA_HINT_TOGGLED. */ -#define LADSPA_HINT_DEFAULT_1 0x240 - -/* This default hint indicates that the number 100 should be used. */ -#define LADSPA_HINT_DEFAULT_100 0x280 - -/* This default hint indicates that the Hz frequency of `concert A' - should be used. This will be 440 unless the host uses an unusual - tuning convention, in which case it may be within a few Hz. */ -#define LADSPA_HINT_DEFAULT_440 0x2C0 - -#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW) -#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE) -#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED) -#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE) -#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC) -#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER) - -#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK) -#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_MINIMUM) -#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_LOW) -#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_MIDDLE) -#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_HIGH) -#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_MAXIMUM) -#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_0) -#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_1) -#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_100) -#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ - == LADSPA_HINT_DEFAULT_440) - -typedef struct _LADSPA_PortRangeHint { - - /* Hints about the port. */ - LADSPA_PortRangeHintDescriptor HintDescriptor; - - /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When - LADSPA_HINT_SAMPLE_RATE is also active then this value should be - multiplied by the relevant sample rate. */ - LADSPA_Data LowerBound; - - /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When - LADSPA_HINT_SAMPLE_RATE is also active then this value should be - multiplied by the relevant sample rate. */ - LADSPA_Data UpperBound; - -} LADSPA_PortRangeHint; - -/*****************************************************************************/ - -/* Plugin Handles: - - This plugin handle indicates a particular instance of the plugin - concerned. It is valid to compare this to NULL (0 for C++) but - otherwise the host should not attempt to interpret it. The plugin - may use it to reference internal instance data. */ - -typedef void * LADSPA_Handle; - -/*****************************************************************************/ - -/* Descriptor for a Type of Plugin: - - This structure is used to describe a plugin type. It provides a - number of functions to examine the type, instantiate it, link it to - buffers and workspaces and to run it. */ - -typedef struct _LADSPA_Descriptor { - - /* This numeric identifier indicates the plugin type - uniquely. Plugin programmers may reserve ranges of IDs from a - central body to avoid clashes. Hosts may assume that IDs are - below 0x1000000. */ - unsigned long UniqueID; - - /* This identifier can be used as a unique, case-sensitive - identifier for the plugin type within the plugin file. Plugin - types should be identified by file and label rather than by index - or plugin name, which may be changed in new plugin - versions. Labels must not contain white-space characters. */ - const char * Label; - - /* This indicates a number of properties of the plugin. */ - LADSPA_Properties Properties; - - /* This member points to the null-terminated name of the plugin - (e.g. "Sine Oscillator"). */ - const char * Name; - - /* This member points to the null-terminated string indicating the - maker of the plugin. This can be an empty string but not NULL. */ - const char * Maker; - - /* This member points to the null-terminated string indicating any - copyright applying to the plugin. If no Copyright applies the - string "None" should be used. */ - const char * Copyright; - - /* This indicates the number of ports (input AND output) present on - the plugin. */ - unsigned long PortCount; - - /* This member indicates an array of port descriptors. Valid indices - vary from 0 to PortCount-1. */ - const LADSPA_PortDescriptor * PortDescriptors; - - /* This member indicates an array of null-terminated strings - describing ports (e.g. "Frequency (Hz)"). Valid indices vary from - 0 to PortCount-1. */ - const char * const * PortNames; - - /* This member indicates an array of range hints for each port (see - above). Valid indices vary from 0 to PortCount-1. */ - const LADSPA_PortRangeHint * PortRangeHints; - - /* This may be used by the plugin developer to pass any custom - implementation data into an instantiate call. It must not be used - or interpreted by the host. It is expected that most plugin - writers will not use this facility as LADSPA_Handle should be - used to hold instance data. */ - void * ImplementationData; - - /* This member is a function pointer that instantiates a plugin. A - handle is returned indicating the new plugin instance. The - instantiation function accepts a sample rate as a parameter. The - plugin descriptor from which this instantiate function was found - must also be passed. This function must return NULL if - instantiation fails. - - Note that instance initialisation should generally occur in - activate() rather than here. */ - LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, - unsigned long SampleRate); - - /* This member is a function pointer that connects a port on an - instantiated plugin to a memory location at which a block of data - for the port will be read/written. The data location is expected - to be an array of LADSPA_Data for audio ports or a single - LADSPA_Data value for control ports. Memory issues will be - managed by the host. The plugin must read/write the data at these - locations every time run() or run_adding() is called and the data - present at the time of this connection call should not be - considered meaningful. - - connect_port() may be called more than once for a plugin instance - to allow the host to change the buffers that the plugin is - reading or writing. These calls may be made before or after - activate() or deactivate() calls. - - connect_port() must be called at least once for each port before - run() or run_adding() is called. When working with blocks of - LADSPA_Data the plugin should pay careful attention to the block - size passed to the run function as the block allocated may only - just be large enough to contain the block of samples. - - Plugin writers should be aware that the host may elect to use the - same buffer for more than one port and even use the same buffer - for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). - However, overlapped buffers or use of a single buffer for both - audio and control data may result in unexpected behaviour. */ - void (*connect_port)(LADSPA_Handle Instance, - unsigned long Port, - LADSPA_Data * DataLocation); - - /* This member is a function pointer that initialises a plugin - instance and activates it for use. This is separated from - instantiate() to aid real-time support and so that hosts can - reinitialise a plugin instance by calling deactivate() and then - activate(). In this case the plugin instance must reset all state - information dependent on the history of the plugin instance - except for any data locations provided by connect_port() and any - gain set by set_run_adding_gain(). If there is nothing for - activate() to do then the plugin writer may provide a NULL rather - than an empty function. - - When present, hosts must call this function once before run() (or - run_adding()) is called for the first time. This call should be - made as close to the run() call as possible and indicates to - real-time plugins that they are now live. Plugins should not rely - on a prompt call to run() after activate(). activate() may not be - called again unless deactivate() is called first. Note that - connect_port() may be called before or after a call to - activate(). */ - void (*activate)(LADSPA_Handle Instance); - - /* This method is a function pointer that runs an instance of a - plugin for a block. Two parameters are required: the first is a - handle to the particular instance to be run and the second - indicates the block size (in samples) for which the plugin - instance may run. - - Note that if an activate() function exists then it must be called - before run() or run_adding(). If deactivate() is called for a - plugin instance then the plugin instance may not be reused until - activate() has been called again. - - If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE - then there are various things that the plugin should not do - within the run() or run_adding() functions (see above). */ - void (*run)(LADSPA_Handle Instance, - unsigned long SampleCount); - - /* This method is a function pointer that runs an instance of a - plugin for a block. This has identical behaviour to run() except - in the way data is output from the plugin. When run() is used, - values are written directly to the memory areas associated with - the output ports. However when run_adding() is called, values - must be added to the values already present in the memory - areas. Furthermore, output values written must be scaled by the - current gain set by set_run_adding_gain() (see below) before - addition. - - run_adding() is optional. When it is not provided by a plugin, - this function pointer must be set to NULL. When it is provided, - the function set_run_adding_gain() must be provided also. */ - void (*run_adding)(LADSPA_Handle Instance, - unsigned long SampleCount); - - /* This method is a function pointer that sets the output gain for - use when run_adding() is called (see above). If this function is - never called the gain is assumed to default to 1. Gain - information should be retained when activate() or deactivate() - are called. - - This function should be provided by the plugin if and only if the - run_adding() function is provided. When it is absent this - function pointer must be set to NULL. */ - void (*set_run_adding_gain)(LADSPA_Handle Instance, - LADSPA_Data Gain); - - /* This is the counterpart to activate() (see above). If there is - nothing for deactivate() to do then the plugin writer may provide - a NULL rather than an empty function. - - Hosts must deactivate all activated units after they have been - run() (or run_adding()) for the last time. This call should be - made as close to the last run() call as possible and indicates to - real-time plugins that they are no longer live. Plugins should - not rely on prompt deactivation. Note that connect_port() may be - called before or after a call to deactivate(). - - Deactivation is not similar to pausing as the plugin instance - will be reinitialised when activate() is called to reuse it. */ - void (*deactivate)(LADSPA_Handle Instance); - - /* Once an instance of a plugin has been finished with it can be - deleted using the following function. The instance handle passed - ceases to be valid after this call. - - If activate() was called for a plugin instance then a - corresponding call to deactivate() must be made before cleanup() - is called. */ - void (*cleanup)(LADSPA_Handle Instance); - -} LADSPA_Descriptor; - -/**********************************************************************/ - -/* Accessing a Plugin: */ - -/* The exact mechanism by which plugins are loaded is host-dependent, - however all most hosts will need to know is the name of shared - object file containing the plugin types. To allow multiple hosts to - share plugin types, hosts may wish to check for environment - variable LADSPA_PATH. If present, this should contain a - colon-separated path indicating directories that should be searched - (in order) when loading plugin types. - - A plugin programmer must include a function called - "ladspa_descriptor" with the following function prototype within - the shared object file. This function will have C-style linkage (if - you are using C++ this is taken care of by the `extern "C"' clause - at the top of the file). - - A host will find the plugin shared object file by one means or - another, find the ladspa_descriptor() function, call it, and - proceed from there. - - Plugin types are accessed by index (not ID) using values from 0 - upwards. Out of range indexes must result in this function - returning NULL, so the plugin count can be determined by checking - for the least index that results in NULL being returned. */ - -const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); - -/* Datatype corresponding to the ladspa_descriptor() function. */ -typedef const LADSPA_Descriptor * -(*LADSPA_Descriptor_Function)(unsigned long Index); - -/**********************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* LADSPA_INCLUDED */ - -/* EOF */ diff --git a/dssi/lesser.txt b/dssi/lesser.txt deleted file mode 100644 index 8add30a..0000000 --- a/dssi/lesser.txt +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/dssi/makefile b/dssi/makefile deleted file mode 100755 index 6a87da9..0000000 --- a/dssi/makefile +++ /dev/null @@ -1,66 +0,0 @@ -NAME=dssi~ -CSYM=dssi~ - -LIBDIR=/usr/local/lib -PDDIR=$(LIBDIR)/pd -INSTALLPATH=$(PDDIR)/extra/ -ARCHITECTURE=i386 -DEBUG=0 - -current: pd_linux - - -# ----------------------- Linux ----------------------- - -pd_linux: src/$(NAME).pd_linux - -.SUFFIXES: .pd_linux - -#LINUXCFLAGS = -DPD -O3 -fPIC -funroll-loops -fomit-frame-pointer \ - -Wall -W -Wshadow -Wstrict-prototypes -Werror \ - -Wno-unused -Wno-parentheses -Wno-switch - -# Debug -LINUXCFLAGS = -ggdb -g -DPD -O0 -fPIC -funroll-loops -fomit-frame-pointer \ - -Wall -W -Wshadow -Wstrict-prototypes -Werror \ - -Wno-unused -Wno-parentheses -Wno-switch -DDEBUG=$(DEBUG) - -LINUXINCLUDE = -I/usr/include -I./include - -.c.pd_linux: - $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -c src/jsearch.c - $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -c src/jload.c - $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -c src/dssi~.c - gcc --export-dynamic -shared -o $(NAME).pd_linux dssi~.o jload.o jsearch.o -lc -lm -llo -# strip --strip-unneeded $(NAME).pd_linux - cp $(NAME).pd_linux ~/pd-externals/ - rm -f *.o - -# ----------------------- Mac OSX ----------------------- - -pd_darwin: src/$(NAME).pd_darwin - -.SUFFIXES: .pd_darwin - -DARWINCFLAGS = -DPD -arch $(ARCHITECTURE) -O3 -Wall -W -Wshadow -Wstrict-prototypes \ - -Wno-unused -Wno-parentheses -Wno-switch -L/usr/local/lib/ -DDEBUG=$(DEBUG) - -DARWININCLUDE = -I ./ -I ../src -I/usr/local/include/ -I ./include -I/usr/local/include/dssi/ - -.c.pd_darwin: - $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) -c src/jsearch.c - $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) -c src/jload.c - $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) -c src/dssi~.c - $(CC) -arch $(ARCHITECTURE) -bundle -undefined suppress -flat_namespace -llo -o $(NAME).pd_darwin dssi~.o jload.o jsearch.o - rm -f *.o - -# ----------------------- Generic ----------------------- - -clean: - rm -f *.o *.pd_* so_locations - -install: - cp dssi~.pd_* $(INSTALLPATH) - install -d $(PDDIR)/doc/5.reference/dssi/ - install -m 644 doc/*-help* $(PDDIR)/doc/5.reference/ - install -m 644 doc/output~.pd $(PDDIR)/doc/5.reference/dssi/ diff --git a/dssi/src/dssi~.c b/dssi/src/dssi~.c deleted file mode 100644 index f195637..0000000 --- a/dssi/src/dssi~.c +++ /dev/null @@ -1,2537 +0,0 @@ -/* dssi~ - A DSSI host for PD - * - * Copyright (C) 2006 Jamie Bullock and others - * - * This file incorporates code from the following sources: - * - * jack-dssi-host (BSD-style license): Copyright 2004 Chris Cannam, Steve Harris and Sean Bolton. - * - * Hexter (GPL license): Copyright (C) 2004 Sean Bolton and others. - * - * plugin~ (GPL license): Copyright (C) 2000 Jarno Seppänen, remIXed 2005 - * - * - * This program is free software; you can redistribute it and/or - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -#include "dssi~.h" -#include "jutils.h" - -static t_class *dssi_tilde_class; - -/*From dx7_voice_data.c by Sean Bolton */ - -static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/*static void init_MidiEventBuf(snd_seq_event_t *MidiEventBuf){ - int i; - for(i = 0; i < EVENT_BUFSIZE; i++){ - MidiEventBuf[i].*/ - -/* - * encode_7in6 - ** Taken from gui_data.c by Sean Bolton ** - * - * encode a block of 7-bit data, in base64-ish style - */ - static char * -encode_7in6(uint8_t *data, int length) -{ - char *buffer; - int in, reg, above, below, shift, out; - int outchars = (length * 7 + 5) / 6; - unsigned int sum = 0; - - if (!(buffer = (char *)malloc(25 + outchars))) - return NULL; - - out = snprintf(buffer, 12, "%d ", length); - - in = reg = above = below = 0; - while (outchars) { - if (above == 6) { - buffer[out] = base64[reg >> 7]; - reg &= 0x7f; - above = 0; - out++; - outchars--; - } - if (below == 0) { - if (in < length) { - reg |= data[in] & 0x7f; - sum += data[in]; - } - below = 7; - in++; - } - shift = 6 - above; - if (below < shift) shift = below; - reg <<= shift; - above += shift; - below -= shift; - } - - snprintf(buffer + out, 12, " %d", sum); - - return buffer; -} - -/* - * dx7_bulk_dump_checksum - ** Taken from dx7_voice_data.c by Sean Bolton ** - */ - static int -dx7_bulk_dump_checksum(uint8_t *data, int length) -{ - int sum = 0; - int i; - - for (i = 0; i < length; sum -= data[i++]); - return sum & 0x7F; -} - -static DSSI_Descriptor * ladspa_to_dssi( - LADSPA_Descriptor *ladspaDesc){ - DSSI_Descriptor *dssiDesc; - dssiDesc = (DSSI_Descriptor *)calloc(1, sizeof(DSSI_Descriptor)); - ((DSSI_Descriptor *)dssiDesc)->DSSI_API_Version = 1; - ((DSSI_Descriptor *)dssiDesc)->LADSPA_Plugin = - (LADSPA_Descriptor *)ladspaDesc; - return (DSSI_Descriptor *)dssiDesc; -} -/* - static void dssi_tilde_load_plugin(const char *dll_path, void **dll_handle){ - - *dll_handle = dlopen(dll_path, RTLD_NOW | RTLD_LOCAL); - if (*dll_handle){ - post("%s loaded successfully", dll_path); - } - else - post("Failed: %s", dlerror()); - - } - */ -static void dssi_tilde_port_info(t_dssi_tilde *x){ - t_int i; - - for (i = 0; i < (t_int)x->descriptor->LADSPA_Plugin->PortCount; i++) { - - x->port_info[i].type.a_type = A_SYMBOL; - x->port_info[i].data_type.a_type = A_SYMBOL; - x->port_info[i].name.a_type = A_SYMBOL; - x->port_info[i].upper_bound.a_type = A_FLOAT; - x->port_info[i].lower_bound.a_type = A_FLOAT; - x->port_info[i].p_default.a_type = A_FLOAT; - - LADSPA_PortDescriptor pod = - x->descriptor->LADSPA_Plugin->PortDescriptors[i]; -#if DEBUG - post("Port %d: %s", i, x->descriptor->LADSPA_Plugin->PortNames[i]); -#endif - if (LADSPA_IS_PORT_AUDIO(pod)) { - x->port_info[i].data_type.a_w.w_symbol = - gensym("audio"); - if (LADSPA_IS_PORT_INPUT(pod)){ - x->port_info[i].type.a_w.w_symbol = - gensym("in"); - ++x->plugin_ins; - } - else if (LADSPA_IS_PORT_OUTPUT(pod)){ - x->port_info[i].type.a_w.w_symbol = - gensym("out"); - ++x->plugin_outs; - } - } - else if (LADSPA_IS_PORT_CONTROL(pod)) { - x->port_info[i].data_type.a_w.w_symbol = - gensym("control"); - if (LADSPA_IS_PORT_INPUT(pod)){ - x->port_info[i].type.a_w.w_symbol = - gensym("in"); - ++x->plugin_controlIns; - } - else if (LADSPA_IS_PORT_OUTPUT(pod)){ - ++x->plugin_controlOuts; - x->port_info[i].type.a_w.w_symbol = - gensym("out"); - } - } - if (LADSPA_IS_HINT_BOUNDED_BELOW( - x->descriptor->LADSPA_Plugin->PortRangeHints[i].HintDescriptor)) - x->port_info[i].lower_bound.a_w.w_float = - x->descriptor->LADSPA_Plugin-> - PortRangeHints[i].LowerBound; - else - x->port_info[i].lower_bound.a_w.w_float = 0; - - if (LADSPA_IS_HINT_BOUNDED_ABOVE( - x->descriptor->LADSPA_Plugin->PortRangeHints[i].HintDescriptor)) - x->port_info[i].upper_bound.a_w.w_float = - x->descriptor->LADSPA_Plugin-> - PortRangeHints[i].UpperBound; - else - x->port_info[i].lower_bound.a_w.w_float = 1; - - x->port_info[i].p_default.a_w.w_float = (float) - get_port_default(x, i); - - x->port_info[i].name.a_w.w_symbol = - gensym ((char *) - x->descriptor->LADSPA_Plugin->PortNames[i]); - } -#if DEBUG - post("%d inputs, %d outputs, %d control inputs, %d control outs", x->plugin_ins, x->plugin_outs, x->plugin_controlIns, x->plugin_controlOuts); -#endif -} - -static void dssi_tilde_assign_ports(t_dssi_tilde *x){ - int i; - -#if DEBUG - post("%d instances", x->n_instances); -#endif - - x->plugin_ins *= x->n_instances; - x->plugin_outs *= x->n_instances; - x->plugin_controlIns *= x->n_instances; - x->plugin_controlOuts *= x->n_instances; - -#if DEBUG - post("%d plugin outs", x->plugin_outs); -#endif - - x->plugin_InputBuffers = - (float **)malloc(x->plugin_ins * sizeof(float *)); - x->plugin_OutputBuffers = - (float **)malloc(x->plugin_outs * sizeof(float *)); - x->plugin_ControlDataInput = - (float *)calloc(x->plugin_controlIns, sizeof(float)); - x->plugin_ControlDataOutput = - (float *)calloc(x->plugin_controlOuts, sizeof(float)); - for(i = 0; i < x->plugin_ins; i++) - x->plugin_InputBuffers[i] = - (float *)calloc(x->blksize, sizeof(float)); - for(i = 0; i < x->plugin_outs; i++) - x->plugin_OutputBuffers[i] = - (float *)calloc(x->blksize, sizeof(float)); - x->instanceEventBuffers = - (snd_seq_event_t **)malloc(x->n_instances * sizeof(snd_seq_event_t *)); - - x->instanceHandles = (LADSPA_Handle *)malloc(x->n_instances * - sizeof(LADSPA_Handle)); - x->instanceEventCounts = (unsigned long *)malloc(x->n_instances * - sizeof(unsigned long)); - - for(i = 0; i < x->n_instances; i++){ - x->instanceEventBuffers[i] = (snd_seq_event_t *)malloc(EVENT_BUFSIZE * - sizeof(snd_seq_event_t)); - - x->instances[i].plugin_PortControlInNumbers = - (int *)malloc(x->descriptor->LADSPA_Plugin->PortCount * - sizeof(int));/* hmmm... as we don't support instances of differing plugin types, we probably don't need to do this dynamically*/ - } - - x->plugin_ControlInPortNumbers = - (unsigned long *)malloc(sizeof(unsigned long) * x->plugin_controlIns); - -#if DEBUG - post("Buffers assigned!"); -#endif - -} - -static void dssi_tilde_init_instance(t_dssi_tilde *x, t_int instance){ - - x->instances[instance].pluginPrograms = NULL; - x->instances[instance].currentBank = 0; - x->instances[instance].currentProgram = 0; - x->instances[instance].uiTarget = NULL; - x->instances[instance].ui_osc_control_path = NULL; - x->instances[instance].ui_osc_program_path = NULL; - x->instances[instance].ui_osc_show_path = NULL; - x->instances[instance].ui_osc_hide_path = NULL; - x->instances[instance].ui_osc_quit_path = NULL; - x->instances[instance].ui_osc_configure_path = NULL; - x->instances[instance].uiNeedsProgramUpdate = 0; - x->instances[instance].pendingProgramChange = -1; - x->instances[instance].plugin_ProgramCount = 0; - x->instances[instance].pendingBankMSB = -1; - x->instances[instance].pendingBankLSB = -1; - x->instances[instance].ui_hidden = 1; - x->instances[instance].ui_show = 0; - x->instances[instance].gui_pid = 0; -#if DEBUG - post("Instance %d initialized!", instance); -#endif - -} - -static void dssi_tilde_connect_ports(t_dssi_tilde *x, t_int instance){ - - t_int i; - - for(i = 0; i < (t_int)x->descriptor->LADSPA_Plugin->PortCount; i++){ -#if DEBUG - post("PortCount: %d of %d", i, - x->descriptor->LADSPA_Plugin->PortCount); -#endif - LADSPA_PortDescriptor pod = - x->descriptor->LADSPA_Plugin->PortDescriptors[i]; - - x->instances[instance].plugin_PortControlInNumbers[i] = -1; - - if (LADSPA_IS_PORT_AUDIO(pod)) { - if (LADSPA_IS_PORT_INPUT(pod)) { - x->descriptor->LADSPA_Plugin->connect_port - (x->instanceHandles[instance], i, - x->plugin_InputBuffers[x->ports_in++]); - } - else if (LADSPA_IS_PORT_OUTPUT(pod)) { - x->descriptor->LADSPA_Plugin->connect_port - (x->instanceHandles[instance], i, - x->plugin_OutputBuffers[x->ports_out++]); -#if DEBUG - post("Audio Input port %d connected", x->ports_in); - post("Audio Output port %d connected", x->ports_out); -#endif - } - } - else if (LADSPA_IS_PORT_CONTROL(pod)) { - if (LADSPA_IS_PORT_INPUT(pod)) { - x->plugin_ControlInPortNumbers[x->ports_controlIn] = (unsigned long) i; - x->instances[instance].plugin_PortControlInNumbers[i] = x->ports_controlIn; - x->plugin_ControlDataInput[x->ports_controlIn] = - (t_float) get_port_default(x, i); -#if DEBUG - post("default for port %d, controlIn, %d is %.2f",i, - x->ports_controlIn, x->plugin_ControlDataInput[x->ports_controlIn]); -#endif - - x->descriptor->LADSPA_Plugin->connect_port - (x->instanceHandles[instance], i, - &x->plugin_ControlDataInput[x->ports_controlIn++]); - - } else if (LADSPA_IS_PORT_OUTPUT(pod)) { - x->descriptor->LADSPA_Plugin->connect_port - (x->instanceHandles[instance], i, - &x->plugin_ControlDataOutput[x->ports_controlOut++]); - } -#if DEBUG - post("Control Input port %d connected", x->ports_controlIn); - post("Control Output port %d connected", x->ports_controlOut); -#endif - } - } - -#if DEBUG - post("ports connected!"); -#endif - -} - -static void dssi_tilde_activate_plugin(t_dssi_tilde *x, t_int instance){ - - if(x->descriptor->LADSPA_Plugin->activate){ -#if DEBUG - post("trying to activate instance: %d", instance); -#endif - x->descriptor->LADSPA_Plugin->activate(x->instanceHandles[instance]); - } -#if DEBUG - post("plugin activated!"); -#endif -} - -static void dssi_tilde_deactivate_plugin(t_dssi_tilde *x, t_float instance_f){ - - t_int instance = (t_int)instance_f; - if(x->descriptor->LADSPA_Plugin->deactivate) - x->descriptor->LADSPA_Plugin->deactivate(x->instanceHandles[instance]); -#if DEBUG - post("plugin deactivated!"); -#endif -} - -static void osc_error(int num, const char *msg, const char *where) -{ - post("dssi~: osc error %d in path %s: %s\n",num, where, msg); -} - -static void query_programs(t_dssi_tilde *x, t_int instance) { - int i; -#if DEBUG - post("querying programs"); -#endif - /* free old lot */ - if (x->instances[instance].pluginPrograms) { - for (i = 0; i < x->instances[instance].plugin_ProgramCount; i++) - free((void *)x->instances[instance].pluginPrograms[i].Name); - free((char *)x->instances[instance].pluginPrograms); - x->instances[instance].pluginPrograms = NULL; - x->instances[instance].plugin_ProgramCount = 0; - } - - x->instances[instance].pendingBankLSB = -1; - x->instances[instance].pendingBankMSB = -1; - x->instances[instance].pendingProgramChange = -1; - - if (x->descriptor->get_program && - x->descriptor->select_program) { - - /* Count the plugins first */ - /*FIX ?? */ - for (i = 0; x->descriptor-> - get_program(x->instanceHandles[instance], i); ++i); - - if (i > 0) { - x->instances[instance].plugin_ProgramCount = i; - x->instances[instance].pluginPrograms = - (DSSI_Program_Descriptor *)malloc(i * sizeof(DSSI_Program_Descriptor)); - while (i > 0) { - const DSSI_Program_Descriptor *descriptor; - --i; - descriptor = x->descriptor-> - get_program(x->instanceHandles[instance], i); - x->instances[instance].pluginPrograms[i].Bank = - descriptor->Bank; - x->instances[instance].pluginPrograms[i].Program = - descriptor->Program; - x->instances[instance].pluginPrograms[i].Name = - strdup(descriptor->Name); -#if DEBUG - post("program %d is MIDI bank %lu program %lu, named '%s'",i, - x->instances[instance].pluginPrograms[i].Bank, - x->instances[instance].pluginPrograms[i].Program, - x->instances[instance].pluginPrograms[i].Name); -#endif - } - } - /* No - it should be 0 anyway - dssi_init */ - /* else - x->instances[instance].plugin_ProgramCount = 0; - */ } -} - -static LADSPA_Data get_port_default(t_dssi_tilde *x, int port) -{ - LADSPA_Descriptor *plugin = (LADSPA_Descriptor *)x->descriptor->LADSPA_Plugin; - LADSPA_PortRangeHint hint = plugin->PortRangeHints[port]; - float lower = hint.LowerBound * - (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? x->sr : 1.0f); - float upper = hint.UpperBound * - (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? x->sr : 1.0f); - - if (!LADSPA_IS_HINT_HAS_DEFAULT(hint.HintDescriptor)) { - if (!LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) || - !LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) { - /* No hint, its not bounded, wild guess */ - return 0.0f; - } - - if (lower <= 0.0f && upper >= 0.0f) { - /* It spans 0.0, 0.0 is often a good guess */ - return 0.0f; - } - - /* No clues, return minimum */ - return lower; - } - - /* Try all the easy ones */ - - if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor)) { - return 0.0f; - } else if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor)) { - return 1.0f; - } else if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor)) { - return 100.0f; - } else if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor)) { - return 440.0f; - } - - /* All the others require some bounds */ - - if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) { - if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor)) { - return lower; - } - } - if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) { - if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor)) { - return upper; - } - if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) { - if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor)) { - return lower * 0.75f + upper * 0.25f; - } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor)) { - return lower * 0.5f + upper * 0.5f; - } else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor)) { - return lower * 0.25f + upper * 0.75f; - } - } - } - - /* fallback */ - return 0.0f; -} - -static unsigned dssi_tilde_get_parm_number (t_dssi_tilde *x, - const char *str) -/* find out if str points to a parameter number or not and return the - number or zero. The number string has to begin with a '#' character */ -{ - long num = 0; - char* strend = NULL; - - if (str == NULL) { - return 0; - } - if (str[0] != '#') { - return 0; - } - num = strtol (&str[1], &strend, 10); - if (str[1] == 0 || *strend != 0) { - /* invalid string */ - return 0; - } - else if (num >= 1 && num <= (long)x->plugin_controlIns) { - /* string ok and within range */ - return (unsigned)num; - } - else { - /* number out of range */ - return 0; - } -} - -static void dssi_tilde_set_control_input_by_index (t_dssi_tilde *x, - signed ctrl_input_index, - float value, - t_int instance) -{ - long port, portno; - - if (ctrl_input_index >= x->plugin_controlIns) { - post("dssi~: control port number %d is out of range [1, %d]", - ctrl_input_index + 1, x->plugin_controlIns); - return; - } - -#if DEBUG - post("ctrl input number = %d", ctrl_input_index); -#endif - - - port = x->plugin_ControlInPortNumbers[ctrl_input_index]; - - - /* FIX - temporary hack */ - if(x->is_DSSI) - portno = - x->instances[instance].plugin_PortControlInNumbers[ctrl_input_index + 1]; - else - portno = - x->instances[instance].plugin_PortControlInNumbers[ctrl_input_index]; -#if DEBUG - post("Global ctrl input number = %d", ctrl_input_index); - post("Global ctrl input value = %.2f", value); -#endif - - - - - /* set the appropriate control port value */ - x->plugin_ControlDataInput[portno] = value; - - /* Update the UI if there is one */ - if(x->is_DSSI){ - if(x->instances[instance].uiTarget == NULL){ -#if DEBUG - post("dssi~: unable to send to NULL target"); -#endif - return; - } - if(x->instances[instance].ui_osc_control_path == NULL){ -#if DEBUG - post("dssi~: unable to send to NULL control path"); -#endif - return; - } - lo_send(x->instances[instance].uiTarget, - x->instances[instance].ui_osc_control_path, "if", port, value); - } - - -} - -static void dssi_tilde_set_control_input_by_name (t_dssi_tilde *x, - const char* name, - float value, - t_int instance) -{ - unsigned port_index = 0; - unsigned ctrl_input_index = 0; - int found_port = 0; /* boolean */ - - if (name == NULL || strlen (name) == 0) { - post("dssi~: no control port name specified"); - return; - } - - /* compare control name to LADSPA control input ports' names - case-insensitively */ - found_port = 0; - ctrl_input_index = 0; - for (port_index = 0; port_index < x->descriptor->LADSPA_Plugin->PortCount; port_index++) - { - LADSPA_PortDescriptor port_type; - port_type = x->descriptor->LADSPA_Plugin->PortDescriptors[port_index]; - if (LADSPA_IS_PORT_CONTROL (port_type) - && LADSPA_IS_PORT_INPUT (port_type)) - { - const char* port_name = NULL; - unsigned cmp_length = 0; - port_name = x->descriptor->LADSPA_Plugin->PortNames[port_index]; - cmp_length = MIN (strlen (name), strlen (port_name)); - if (cmp_length != 0 - && strncasecmp (name, port_name, cmp_length) == 0) - { - /* found the first port to match */ - found_port = 1; - break; - } - ctrl_input_index++; - } - } - - if (!found_port) - { - post("dssi~: plugin doesn't have a control input port named \"%s\"", - name); - return; - } - - dssi_tilde_set_control_input_by_index (x, ctrl_input_index, value, instance); -} - -static void dssi_tilde_control (t_dssi_tilde *x, - t_symbol* ctrl_name, - t_float ctrl_value, - t_float instance_f) -/* Change the value of a named control port of the plug-in */ -{ - unsigned parm_num = 0; - t_int instance = (t_int)instance_f - 1; - int n_instances = x->n_instances; - - if (instance > x->n_instances || instance < -1){ - post("dssi~: control: invalid instance number %d", instance); - return; - } - -#if DEBUG - post("Received LADSPA control data for instance %d", instance); -#endif - - if (ctrl_name->s_name == NULL || strlen (ctrl_name->s_name) == 0) { - post("dssi~: control messages must have a name and a value"); - return; - } - parm_num = dssi_tilde_get_parm_number (x, ctrl_name->s_name); - if (parm_num) { - if(instance >= 0) - dssi_tilde_set_control_input_by_index (x, parm_num - 1, - ctrl_value, instance); - else if (instance == -1){ - while(n_instances--) - dssi_tilde_set_control_input_by_index (x, parm_num - 1, - ctrl_value, n_instances); - } - } - else { - if(instance >= 0) - dssi_tilde_set_control_input_by_name (x, ctrl_name->s_name, - ctrl_value, instance); - else if (instance == -1){ - while(n_instances--) - dssi_tilde_set_control_input_by_name (x, - ctrl_name->s_name, ctrl_value, n_instances); - } - } -} - -static void dssi_tilde_info (t_dssi_tilde *x){ - unsigned int i, - ctrl_portno, - audio_portno; - t_atom argv[7]; - - ctrl_portno = audio_portno = 0; - - if (x->descriptor == NULL) - return; - - for(i = 0; i < x->descriptor->LADSPA_Plugin->PortCount; i++){ - memcpy(&argv[0], &x->port_info[i].type, - sizeof(t_atom)); - memcpy(&argv[1], &x->port_info[i].data_type, - sizeof(t_atom)); - memcpy(&argv[3], &x->port_info[i].name, - sizeof(t_atom)); - memcpy(&argv[4], &x->port_info[i].lower_bound, - sizeof(t_atom)); - memcpy(&argv[5], &x->port_info[i].upper_bound, - sizeof(t_atom)); - memcpy(&argv[6], &x->port_info[i].p_default, - sizeof(t_atom)); - argv[2].a_type = A_FLOAT; - if(!strcmp(argv[1].a_w.w_symbol->s_name, "control")) - argv[2].a_w.w_float = (t_float)++ctrl_portno; - - else if(!strcmp(argv[1].a_w.w_symbol->s_name, "audio")) - argv[2].a_w.w_float = (t_float)++audio_portno; - - outlet_anything (x->control_outlet, gensym ("port"), 7, argv); - } -} - -static void dssi_tilde_ladspa_description(t_dssi_tilde *x, t_atom *at, - DSSI_Descriptor *psDescriptor){ - at[0].a_w.w_symbol = - gensym ((char*)psDescriptor->LADSPA_Plugin->Name); - outlet_anything (x->control_outlet, gensym ("name"), 1, at); - at[0].a_w.w_symbol = - gensym ((char*)psDescriptor->LADSPA_Plugin->Label); - outlet_anything (x->control_outlet, gensym ("label"), 1, at); - at[0].a_type = A_FLOAT; - at[0].a_w.w_float = psDescriptor->LADSPA_Plugin->UniqueID; - outlet_anything (x->control_outlet, gensym ("id"), 1, at); - at[0].a_type = A_SYMBOL; - at[0].a_w.w_symbol = - gensym ((char*)psDescriptor->LADSPA_Plugin->Maker); - outlet_anything (x->control_outlet, gensym ("maker"), 1, at); -} - -static void dssi_tilde_ladspa_describe(const char * pcFullFilename, - void * pvPluginHandle, - DSSI_Descriptor_Function fDescriptorFunction, - void* user_data, - int is_DSSI) { - - t_dssi_tilde *x = (((void**)user_data)[0]); - t_atom at[1]; - DSSI_Descriptor *psDescriptor; - long lIndex; - - at[0].a_type = A_SYMBOL; - at[0].a_w.w_symbol = gensym ((char*)pcFullFilename); - outlet_anything (x->control_outlet, gensym ("library"), 1, at); - - if(is_DSSI){ -#if DEBUG - post("DSSI plugin found by listinfo"); -#endif - for (lIndex = 0; - (psDescriptor = (DSSI_Descriptor *) - fDescriptorFunction(lIndex)) != NULL; lIndex++) - dssi_tilde_ladspa_description(x, &at[0], psDescriptor); - } - - else if(!is_DSSI) - lIndex = 0; - do{ - psDescriptor = ladspa_to_dssi((LADSPA_Descriptor *)fDescriptorFunction(lIndex++)); - /* psDescriptor = (DSSI_Descriptor *)calloc(1, - sizeof(DSSI_Descriptor)); - ((DSSI_Descriptor *)psDescriptor)->DSSI_API_Version = 1; - ((DSSI_Descriptor *)psDescriptor)->LADSPA_Plugin = - (LADSPA_Descriptor *) - fDescriptorFunction(lIndex++); - */ - if(psDescriptor->LADSPA_Plugin != NULL){ - dssi_tilde_ladspa_description(x, &at[0], psDescriptor); - free((DSSI_Descriptor *)psDescriptor); - } - else - break; - } while(1); - /* Not needed - dlclose(pvPluginHandle); - */ -} - -static void dssi_tilde_list_plugins (t_dssi_tilde *x) { - void* user_data[1]; - user_data[0] = x; - LADSPAPluginSearch(dssi_tilde_ladspa_describe,(void*)user_data); -} - -static int osc_debug_handler(const char *path, const char *types, lo_arg **argv, - int argc, void *data, t_dssi_tilde *x) -{ - int i; - printf("got unhandled OSC message:\npath: <%s>\n", path); - for (i=0; iinstances[instance].currentProgram; - - argv[0].a_w.w_float = (t_float)instance; - argv[1].a_w.w_float = x->instances[instance].pluginPrograms[i].Program; - argv[2].a_w.w_symbol = - gensym ((char*)x->instances[instance].pluginPrograms[i].Name); - outlet_anything (x->control_outlet, gensym ("program"), 3, argv); - -} - -static void dssi_tilde_program_change(t_dssi_tilde *x, int instance){ - /* jack-dssi-host queues program changes by using pending program change variables. In the audio callback, if a program change is received via MIDI it over writes the pending value (if any) set by the GUI. If unset, or processed the value will default back to -1. The following call to select_program is then made. I don't think it eventually needs to be done this way - i.e. do we need 'pending'? */ -#if DEBUG - post("executing program change"); -#endif - if (x->instances[instance].pendingProgramChange >= 0){ - if (x->instances[instance].pendingBankLSB >= 0) { - if (x->instances[instance].pendingBankMSB >= 0) { - x->instances[instance].currentBank = x->instances[instance].pendingBankLSB + 128 * x->instances[instance].pendingBankMSB; - } - else { - x->instances[instance].currentBank = x->instances[instance].pendingBankLSB + - 128 * (x->instances[instance].currentBank / 128); - } - } - else if (x->instances[instance].pendingBankMSB >= 0) { - x->instances[instance].currentBank = (x->instances[instance].currentBank % 128) + 128 * x->instances[instance].pendingBankMSB; - } - - x->instances[instance].currentProgram = x->instances[instance].pendingProgramChange; - - if (x->descriptor->select_program) { - x->descriptor->select_program(x->instanceHandles[instance], - x->instances[instance].currentBank, x->instances[instance].currentProgram); - } - if (x->instances[instance].uiNeedsProgramUpdate){ -#if DEBUG - post("Updating GUI program"); -#endif - /* FIX - this is a hack to make text ui work*/ - if(x->instances[instance].uiTarget) - lo_send(x->instances[instance].uiTarget, - x->instances[instance].ui_osc_program_path, "ii", - x->instances[instance].currentBank, - x->instances[instance].currentProgram); - - } - x->instances[instance].uiNeedsProgramUpdate = 0; - x->instances[instance].pendingProgramChange = -1; - x->instances[instance].pendingBankMSB = -1; - x->instances[instance].pendingBankLSB = -1; - } - dssi_tilde_get_current_program(x, instance); -} - -static int osc_program_handler(t_dssi_tilde *x, lo_arg **argv, int instance) -{ - unsigned long bank = argv[0]->i; - unsigned long program = argv[1]->i; - int i; - int found = 0; - -#if DEBUG - post("osc_program_hander active!"); - - post("%d programs", x->instances[instance].plugin_ProgramCount); - -#endif - for (i = 0; i < x->instances[instance].plugin_ProgramCount; ++i) { - if (x->instances[instance].pluginPrograms[i].Bank == bank && - x->instances[instance].pluginPrograms[i].Program == program) { - post("dssi~: OSC: setting bank %u, program %u, name %s\n", - bank, program, x->instances[instance].pluginPrograms[i].Name); - - found = 1; - break; - } - } - - if (!found) { - printf(": OSC: UI requested unknown program: bank %d, program %u: sending to plugin anyway (plugin should ignore it)\n", (int)bank,(int)program); - } - - x->instances[instance].pendingBankMSB = bank / 128; - x->instances[instance].pendingBankLSB = bank % 128; - x->instances[instance].pendingProgramChange = program; -#if DEBUG - post("bank = %d, program = %d, BankMSB = %d BankLSB = %d", bank, program, x->instances[instance].pendingBankMSB, x->instances[instance].pendingBankLSB); -#endif - dssi_tilde_program_change(x, instance); - - return 0; -} - -static int osc_control_handler(t_dssi_tilde *x, lo_arg **argv, int instance) -{ - int port = argv[0]->i; - LADSPA_Data value = argv[1]->f; - - x->plugin_ControlDataInput[x->instances[instance].plugin_PortControlInNumbers[port]] = value; -#if DEBUG - post("OSC: port %d = %f", port, value); -#endif - - return 0; -} - -static int osc_midi_handler(t_dssi_tilde *x, lo_arg **argv, t_int instance) -{ - - int ev_type = 0, chan = 0; -#if DEBUG - post("OSC: got midi request for" - "(%02x %02x %02x %02x)", - argv[0]->m[0], argv[0]->m[1], argv[0]->m[2], argv[0]->m[3]); -#endif - chan = instance; -#if DEBUG - post("channel: %d", chan); -#endif - - if(argv[0]->m[1] <= 239){ - if(argv[0]->m[1] >= 224) - ev_type = SND_SEQ_EVENT_PITCHBEND; - else if(argv[0]->m[1] >= 208) - ev_type = SND_SEQ_EVENT_CHANPRESS; - else if(argv[0]->m[1] >= 192) - ev_type = SND_SEQ_EVENT_PGMCHANGE; - else if(argv[0]->m[1] >= 176) - ev_type = SND_SEQ_EVENT_CONTROLLER; - else if(argv[0]->m[1] >= 160) - ev_type = SND_SEQ_EVENT_KEYPRESS; - else if(argv[0]->m[1] >= 144) - ev_type = SND_SEQ_EVENT_NOTEON; - else if(argv[0]->m[1] >= 128) - ev_type = SND_SEQ_EVENT_NOTEOFF; - } - if(ev_type != 0) - MIDIbuf(ev_type, chan, argv[0]->m[2], argv[0]->m[3], x); - - return 0; -} - -static int osc_configure_handler(t_dssi_tilde *x, lo_arg **argv, int instance) -{ - const char *key = (const char *)&argv[0]->s; - const char *value = (const char *)&argv[1]->s; - char *message; - -#if DEBUG - post("osc_configure_handler active!"); -#endif - - if (x->descriptor->configure) { - - if (!strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, - strlen(DSSI_RESERVED_CONFIGURE_PREFIX))) { - fprintf(stderr, ": OSC: UI for plugin '' attempted to use reserved configure key \"%s\", ignoring\n", key); - return 0; - } - - message = x->descriptor->configure(x->instanceHandles[instance], key, value); - if (message) { - printf(": on configure '%s', plugin '' returned error '%s'\n", - key, message); - free(message); - } - - query_programs(x, instance); - - } - - return 0; -} - -static int osc_exiting_handler(t_dssi_tilde *x, lo_arg **argv, int instance){ - -#if DEBUG - post("exiting handler called: Freeing ui_osc"); -#endif - if(x->instances[instance].uiTarget){ - lo_address_free(x->instances[instance].uiTarget); - x->instances[instance].uiTarget = NULL; - } - free(x->instances[instance].ui_osc_control_path); - free(x->instances[instance].ui_osc_configure_path); - free(x->instances[instance].ui_osc_hide_path); - free(x->instances[instance].ui_osc_program_path); - free(x->instances[instance].ui_osc_show_path); - free(x->instances[instance].ui_osc_quit_path); - x->instances[instance].uiTarget = NULL; - x->instances[instance].ui_osc_control_path = NULL; - x->instances[instance].ui_osc_configure_path = NULL; - x->instances[instance].ui_osc_hide_path = NULL; - x->instances[instance].ui_osc_program_path = NULL; - x->instances[instance].ui_osc_show_path = NULL; - x->instances[instance].ui_osc_quit_path = NULL; - - x->instances[instance].ui_hidden = 1; - - return 0; -} - -static int osc_update_handler(t_dssi_tilde *x, lo_arg **argv, int instance) -{ - const char *url = (char *)&argv[0]->s; - const char *path; - t_int i; - char *host, *port; - t_dssi_configure_pair *p; - - p = x->configure_buffer_head; - -#if DEBUG - post("OSC: got update request from <%s>, instance %d", url, instance); -#endif - - if (x->instances[instance].uiTarget) - lo_address_free(x->instances[instance].uiTarget); - host = lo_url_get_hostname(url); - port = lo_url_get_port(url); - x->instances[instance].uiTarget = lo_address_new(host, port); - free(host); - free(port); - - path = lo_url_get_path(url); - - if (x->instances[instance].ui_osc_control_path) - free(x->instances[instance].ui_osc_control_path); - x->instances[instance].ui_osc_control_path = - (char *)malloc(strlen(path) + 10); - sprintf(x->instances[instance].ui_osc_control_path, "%s/control", path); - - if (x->instances[instance].ui_osc_configure_path) - free(x->instances[instance].ui_osc_configure_path); - x->instances[instance].ui_osc_configure_path = - (char *)malloc(strlen(path) + 12); - sprintf(x->instances[instance].ui_osc_configure_path, "%s/configure", path); - - if (x->instances[instance].ui_osc_program_path) - free(x->instances[instance].ui_osc_program_path); - x->instances[instance].ui_osc_program_path = - (char *)malloc(strlen(path) + 10); - sprintf(x->instances[instance].ui_osc_program_path, "%s/program", path); - - if (x->instances[instance].ui_osc_quit_path) - free(x->instances[instance].ui_osc_quit_path); - x->instances[instance].ui_osc_quit_path = (char *)malloc(strlen(path) + 10); - sprintf(x->instances[instance].ui_osc_quit_path, "%s/quit", path); - - if (x->instances[instance].ui_osc_show_path) - free(x->instances[instance].ui_osc_show_path); - x->instances[instance].ui_osc_show_path = (char *)malloc(strlen(path) + 10); - sprintf(x->instances[instance].ui_osc_show_path, "%s/show", path); - - if (x->instances[instance].ui_osc_hide_path) - free(x->instances[instance].ui_osc_hide_path); - x->instances[instance].ui_osc_hide_path = (char *)malloc(strlen(path) + 10); - sprintf(x->instances[instance].ui_osc_hide_path, "%s/hide", path); - - free((char *)path); - - while(p){ - if(p->instance == instance) - dssi_tilde_send_configure(x, p->key, - p->value, instance); - p = p->next; - } - - /* Send current bank/program (-FIX- another race...) */ - if (x->instances[instance].pendingProgramChange >= 0) - dssi_tilde_program_change(x, instance); -#if DEBUG - post("pendingProgramChange = %d", x->instances[instance].pendingProgramChange); -#endif - if (x->instances[instance].pendingProgramChange < 0) { - unsigned long bank = x->instances[instance].currentBank; - unsigned long program = x->instances[instance].currentProgram; - x->instances[instance].uiNeedsProgramUpdate = 0; - if (x->instances[instance].uiTarget) { - lo_send(x->instances[instance].uiTarget, - x->instances[instance].ui_osc_program_path, - "ii", bank, program); - } - } - - /* Send control ports */ - for (i = 0; i < x->plugin_controlIns; i++) { - lo_send(x->instances[instance].uiTarget, x->instances[instance].ui_osc_control_path, "if", - x->plugin_ControlInPortNumbers[i], x->plugin_ControlDataInput[i]); -#if DEBUG - post("Port: %d, Default value: %.2f", x->plugin_ControlInPortNumbers[i], x->plugin_ControlDataInput[i]); -#endif - } - - /* Send 'show' */ - if (x->instances[instance].ui_show) { - lo_send(x->instances[instance].uiTarget, x->instances[instance].ui_osc_show_path, ""); - x->instances[instance].ui_hidden = 0; - x->instances[instance].ui_show = 0; - } - - return 0; -} - -static void dssi_tilde_osc_setup(t_dssi_tilde *x, int instance){ - - if(instance == 0){ - x->osc_thread = lo_server_thread_new(NULL, osc_error); - char *osc_url_tmp; - osc_url_tmp = lo_server_thread_get_url(x->osc_thread); -#if DEBUG - post("string length of osc_url_tmp:%d", strlen(osc_url_tmp)); -#endif - x->osc_url_base = (char *)malloc(sizeof(char) - * (strlen(osc_url_tmp) + strlen("dssi") + 1)); - sprintf(x->osc_url_base, "%s%s", osc_url_tmp, "dssi"); - free(osc_url_tmp); - lo_server_thread_add_method(x->osc_thread, NULL, NULL, - osc_message_handler, x); - lo_server_thread_start(x->osc_thread); - } - x->instances[instance].osc_url_path = (char *)malloc(sizeof(char) * - (strlen(x->plugin_basename) + strlen(x->descriptor->LADSPA_Plugin->Label) + strlen("chan00") + 3)); - sprintf(x->instances[instance].osc_url_path, "%s/%s/chan%02d", x->plugin_basename, - x->descriptor->LADSPA_Plugin->Label, instance); -#if DEBUG - post("OSC Path is: %s", x->instances[instance].osc_url_path); - post("OSC thread started: %s", x->osc_url_base); -#endif -} - -static void dssi_tilde_init_programs(t_dssi_tilde *x, int instance){ - -#if DEBUG - post("Setting up program data"); -#endif - query_programs(x, instance); - if (x->descriptor->select_program && - x->instances[instance].plugin_ProgramCount > 0) { - - /* select program at index 0 */ - unsigned long bank = - x->instances[instance].pluginPrograms[0].Bank; - x->instances[instance].pendingBankMSB = bank / 128; - x->instances[instance].pendingBankLSB = bank % 128; - x->instances[instance].pendingProgramChange = - x->instances[instance].pluginPrograms[0].Program; - x->instances[instance].uiNeedsProgramUpdate = 1; - } -} - -static void dssi_tilde_load_gui(t_dssi_tilde *x, int instance){ - t_int err = 0; - char *osc_url; - char *gui_path; - struct dirent *dir_entry = NULL; - char *gui_base; - size_t baselen; - DIR *dp; - char *gui_str; - - gui_base = (char *)malloc((baselen = sizeof(char) * (strlen(x->plugin_full_path) - strlen(".so"))) + 1); - - strncpy(gui_base, x->plugin_full_path, baselen); - gui_base[baselen] = '\0'; - - /* don't use strndup - GNU only */ - /* gui_base = strndup(x->plugin_full_path, baselen);*/ -#if DEBUG - post("gui_base: %s", gui_base); -#endif - - gui_str = (char *)malloc(sizeof(char) * (strlen("channel 00") + 1)); - sprintf (gui_str,"channel %02d", instance); - -#if DEBUG - post("GUI name string, %s", gui_str); -#endif - - if(!(dp = opendir(gui_base))){ - post("dssi~: unable to find GUI in %s, continuing without...", gui_base); - return; - } - else { - while((dir_entry = readdir(dp))){ - if (dir_entry->d_name[0] == '.') continue; - if (strchr(dir_entry->d_name, '_')){ - if (strstr(dir_entry->d_name, "gtk") || - strstr(dir_entry->d_name, "qt") || - strstr(dir_entry->d_name, "text")) - break; - } - } -#if DEBUG - post("GUI filename: %s", dir_entry->d_name); -#endif - } - - gui_path = (char *)malloc(sizeof(char) * (strlen(gui_base) + strlen("/") + - strlen(dir_entry->d_name) + 1)); - - sprintf(gui_path, "%s/%s", gui_base, dir_entry->d_name); - - free(gui_base); -#if DEBUG - post("gui_path: %s", gui_path); -#endif - - osc_url = (char *)malloc - (sizeof(char) * (strlen(x->osc_url_base) + - strlen(x->instances[instance].osc_url_path) + 2)); - - /* char osc_url[1024];*/ - sprintf(osc_url, "%s/%s", x->osc_url_base, - x->instances[instance].osc_url_path); - post("dssi~: instance %d URL: %s",instance, osc_url); -#if DEBUG - post("Trying to open GUI!"); -#endif - - x->instances[instance].gui_pid = fork(); - if (x->instances[instance].gui_pid == 0){ - //pthread_mutex_init(&x->midiEventBufferMutex, NULL); - err = execlp(gui_path, gui_path, osc_url, dir_entry->d_name, - x->descriptor->LADSPA_Plugin->Label, gui_str, NULL); - perror("exec failed"); - exit(1); /* terminates the process */ - } - -#if DEBUG - post("errorcode = %d", err); -#endif - - free(gui_path); - free(osc_url); - free(gui_str); - if(dp){ - -#if DEBUG - post("directory handle closed = %d", closedir(dp)); -#endif - } -} - -static void MIDIbuf(int type, int chan, int param, int val, t_dssi_tilde *x){ - - if(chan > x->n_instances - 1 || chan < 0){ - post("dssi~: note discarded: MIDI data is destined for a channel that doesn't exist"); - return; - } - - t_int time_ref = x->time_ref; - t_int mapped; - - pthread_mutex_lock(&x->midiEventBufferMutex); - - mapped = x->channelMap[chan + 1] - 1; - - x->midiEventBuf[x->bufWriteIndex].time.time.tv_sec = - (t_int)(clock_gettimesince(time_ref) * .001); - x->midiEventBuf[x->bufWriteIndex].time.time.tv_nsec = - (t_int)(clock_gettimesince(time_ref) * 1000); /*actually usec - we can't store this in nsec! */ - - if ((type == SND_SEQ_EVENT_NOTEON && val != 0) || - type != SND_SEQ_EVENT_NOTEON) { - x->midiEventBuf[x->bufWriteIndex].type = type; - switch (type) { - case SND_SEQ_EVENT_NOTEON: - x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; - x->midiEventBuf[x->bufWriteIndex].data.note.note = param; - x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; - break; - case SND_SEQ_EVENT_NOTEOFF: - x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; - x->midiEventBuf[x->bufWriteIndex].data.note.note = param; - x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; - break; - case SND_SEQ_EVENT_CONTROLLER: - x->midiEventBuf[x->bufWriteIndex].data.control.channel = mapped; - x->midiEventBuf[x->bufWriteIndex].data.control.param = param; - x->midiEventBuf[x->bufWriteIndex].data.control.value = val; - break; - case SND_SEQ_EVENT_PITCHBEND: - x->midiEventBuf[x->bufWriteIndex].data.control.channel = mapped; - x->midiEventBuf[x->bufWriteIndex].data.control.param = 0; - x->midiEventBuf[x->bufWriteIndex].data.control.value = val; - break; - case SND_SEQ_EVENT_CHANPRESS: - x->midiEventBuf[x->bufWriteIndex].data.control.channel = mapped; - x->midiEventBuf[x->bufWriteIndex].data.control.param = 0; - x->midiEventBuf[x->bufWriteIndex].data.control.value = val; - break; - case SND_SEQ_EVENT_KEYPRESS: - x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; - x->midiEventBuf[x->bufWriteIndex].data.note.note = param; - x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; - break; - case SND_SEQ_EVENT_PGMCHANGE: - x->instances[mapped].pendingBankMSB = (param - 1) / 128; - x->instances[mapped].pendingBankLSB = (param - 1) % 128; - x->instances[mapped].pendingProgramChange = val; - x->instances[mapped].uiNeedsProgramUpdate = 1; -#if DEBUG - post("pgm chabge received in buffer: MSB: %d, LSB %d, prog: %d", - x->instances[mapped].pendingBankMSB, x->instances[mapped].pendingBankLSB, val); -#endif - dssi_tilde_program_change(x, mapped); - break; - } - } - else if (type == SND_SEQ_EVENT_NOTEON && val == 0) { - x->midiEventBuf[x->bufWriteIndex].type = SND_SEQ_EVENT_NOTEOFF; - x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; - x->midiEventBuf[x->bufWriteIndex].data.note.note = param; - x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; - } - -#if DEBUG - post("MIDI received in buffer: chan %d, param %d, val %d, mapped to %d", - chan, param, val, mapped); -#endif - x->bufWriteIndex = (x->bufWriteIndex + 1) % EVENT_BUFSIZE; - pthread_mutex_unlock(&x->midiEventBufferMutex); /**release mutex*/ -} - -static void dssi_tilde_list(t_dssi_tilde *x, t_symbol *s, int argc, t_atom *argv) { - char *msg_type; - int ev_type = 0; - msg_type = (char *)malloc(TYPE_STRING_SIZE); - atom_string(argv, msg_type, TYPE_STRING_SIZE); - int chan = (int)atom_getfloatarg(1, argc, argv) - 1; - int param = (int)atom_getfloatarg(2, argc, argv); - int val = (int)atom_getfloatarg(3, argc, argv); - int n_instances = x->n_instances; - - switch (msg_type[0]){ - case ASCII_n: ev_type = SND_SEQ_EVENT_NOTEON; - break; - case ASCII_c: ev_type = SND_SEQ_EVENT_CONTROLLER; - break; - case ASCII_p: ev_type = SND_SEQ_EVENT_PGMCHANGE; - break; - case ASCII_b: ev_type = SND_SEQ_EVENT_PITCHBEND; - break; - case ASCII_t: ev_type = SND_SEQ_EVENT_CHANPRESS; - break; - case ASCII_a: ev_type = SND_SEQ_EVENT_KEYPRESS; - break; - } -#if DEBUG - post("initial midi NOTE:, arg1 = %d, arg2 = %d, arg3 = %d, arg4 = %d",ev_type,chan,param,val); -#endif - if(ev_type != 0){ - if(chan >= 0) - MIDIbuf(ev_type, chan, param, val, x); - else { - while(n_instances--) - MIDIbuf(ev_type, n_instances, param, val, x); - } - } - free(msg_type); -} - -static char *dssi_tilde_send_configure(t_dssi_tilde *x, char *key, - char *value, t_int instance){ - - char *debug; - - debug = x->descriptor->configure( - x->instanceHandles[instance], - key, value); - if(x->instances[instance].uiTarget != NULL && x->is_DSSI) - lo_send(x->instances[instance].uiTarget, - x->instances[instance].ui_osc_configure_path, - "ss", key, value); - query_programs(x, instance); - - return debug; -} - -static void dssi_show(t_dssi_tilde *x, t_int instance, t_int toggle){ - - if(x->instances[instance].uiTarget){ - if (x->instances[instance].ui_hidden && toggle) { - lo_send(x->instances[instance].uiTarget, - x->instances[instance].ui_osc_show_path, ""); - x->instances[instance].ui_hidden = 0; - } - else if (!x->instances[instance].ui_hidden && !toggle) { - lo_send(x->instances[instance].uiTarget, - x->instances[instance].ui_osc_hide_path, ""); - x->instances[instance].ui_hidden = 1; - } - } - else if(toggle){ - x->instances[instance].ui_show = 1; - dssi_tilde_load_gui(x, instance); - - } -} - -static t_int dssi_tilde_configure_buffer(t_dssi_tilde *x, char *key, - char *value, t_int instance){ - - /*#ifdef BLAH*/ - t_dssi_configure_pair *current, *p; - t_int add_node; - add_node = 0; - current = x->configure_buffer_head; - - while(current){ - if(!strcmp(current->key, key) && - current->instance == instance) - break; - current = current->next; - } - if(current) - free(current->value); - else { - current = (t_dssi_configure_pair *)malloc(sizeof - (t_dssi_configure_pair)); - current->next = x->configure_buffer_head; - x->configure_buffer_head = current; - current->key = strdup(key); - current->instance = instance; - } - current->value = strdup(value); - - p = x->configure_buffer_head; - - /*FIX: eventually give ability to query this buffer (to outlet?) */ -#if DEBUG - while(p){ - post("key: %s", p->key); - post("val: %s", p->value); - post("instance: %d", p->instance); - p = p->next; - } -#endif - return 0; -} - -static t_int dssi_tilde_configure_buffer_free(t_dssi_tilde *x){ - t_dssi_configure_pair *curr, *prev; - prev = curr = NULL; - - for(curr = x->configure_buffer_head; curr != NULL; curr = curr->next){ - if(prev != NULL) - free(prev); - free(curr->key); - free(curr->value); - prev = curr; - } - free(curr); - - return 0; -} - -/* - static void dssi_tilde_plug (t_dssi_tilde *x, t_symbol* plug_name) { - plugin_tilde_ladspa_close_plugin(x); - x->plugin_library_filename = NULL; - x->plugin_library_filename = plugin_tilde_search_plugin_by_label (x, plug_name->s_name); - if (x->plugin_library_filename == NULL) - post("plugin~: plugin not found in any library"); - if (plugin_tilde_open_plugin (x, plug_name->s_name, x->plugin_library_filename,(unsigned long)sys_getsr ())) - post("plugin~: Unable to open plugin"); - } - */ - -static t_int dssi_tilde_reset(t_dssi_tilde *x, t_float instance_f){ - - t_int instance = (t_int)instance_f - 1; - if (instance == -1){ - for(instance = 0; instance < x->n_instances; instance++) { - if (x->descriptor->LADSPA_Plugin->deactivate && - x->descriptor->LADSPA_Plugin->activate){ - x->descriptor->LADSPA_Plugin->deactivate - (x->instanceHandles[instance]); - x->descriptor->LADSPA_Plugin->activate - (x->instanceHandles[instance]); - } - } - } - else if (x->descriptor->LADSPA_Plugin->deactivate && - x->descriptor->LADSPA_Plugin->activate) { - x->descriptor->LADSPA_Plugin->deactivate - (x->instanceHandles[instance]); - x->descriptor->LADSPA_Plugin->activate - (x->instanceHandles[instance]); - } - return 0; -} - -static void dssi_tilde_search_plugin_callback ( - const char* full_filename, - void* plugin_handle, - DSSI_Descriptor_Function descriptor_function, - void* user_data, - int is_DSSI) -{ - DSSI_Descriptor* descriptor = NULL; - unsigned plug_index = 0; - - char** out_lib_name = (char**)(((void**)user_data)[0]); - char* name = (char*)(((void**)user_data)[1]); - - /* Stop searching when a first matching plugin is found */ - if (*out_lib_name == NULL) - { -#if DEBUG - post("plugin~: searching plugin \"%s\"...", full_filename); -#endif - for(plug_index = 0;(is_DSSI ? - (descriptor = - (DSSI_Descriptor *)descriptor_function(plug_index)) : - ((DSSI_Descriptor *)(descriptor = - ladspa_to_dssi((LADSPA_Descriptor *) - descriptor_function(plug_index)))->LADSPA_Plugin)) - != NULL; plug_index++){ -#if DEBUG - post("plugin~: label \"%s\"", descriptor->LADSPA_Plugin->Label); -#endif - if (strcasecmp (name, descriptor->LADSPA_Plugin->Label) - == 0) - { - *out_lib_name = strdup (full_filename); -#if DEBUG - post("plugin~: found plugin \"%s\" in library \"%s\"", - name, full_filename); -#endif - /* if(!is_DSSI){ - free((DSSI_Descriptor *)descriptor); - descriptor = NULL; - }*/ - break; - } - /* if (descriptor != NULL){ - free((DSSI_Descriptor *)descriptor); - descriptor = NULL; - }*/ - } - } -} - -static const char* plugin_tilde_search_plugin_by_label (t_dssi_tilde *x, - const char *name) -{ - char* lib_name = NULL; - void* user_data[2]; - - user_data[0] = (void*)(&lib_name); - user_data[1] = (void*)name; -#if DEBUG - post("search plugin by label: '%s'\n", name); -#endif - - lib_name = NULL; - LADSPAPluginSearch (dssi_tilde_search_plugin_callback, - (void*)user_data); - - /* The callback (allocates and) writes lib_name, if it finds the plugin */ - return lib_name; - -} - -static t_int dssi_tilde_dssi_methods(t_dssi_tilde *x, t_symbol *s, int argc, t_atom *argv) -{ - if (!x->is_DSSI) { - post("dssi~: plugin is not a DSSI plugin, operation not supported"); - return 0; - } - char *msg_type, - *debug, - *filename, - *filepath, - *key, - *value, - *temp, - mydir[MAXPDSTRING]; - int instance = -1, - pathlen, - toggle, - fd, - n_instances = x->n_instances, - count, - i, - chan, - maxpatches; - t_float val; - long filelength = 0; - unsigned char *raw_patch_data = NULL; - FILE *fp = NULL; - size_t filename_length, key_size, value_size; - dx7_patch_t *patchbuf, *firstpatch; - msg_type = (char *)malloc(TYPE_STRING_SIZE); - atom_string(argv, msg_type, TYPE_STRING_SIZE); - debug = NULL; - key = NULL; - value = NULL; - maxpatches = 128; - patchbuf = malloc(32 * sizeof(dx7_patch_t)); - firstpatch = &patchbuf[0]; - val = 0; - - /*FIX: Temporary - at the moment we always load the first 32 patches to 0 */ - if(strcmp(msg_type, "configure")){ - instance = (int)atom_getfloatarg(2, argc, argv) - 1; - - if(!strcmp(msg_type, "load") && x->descriptor->configure){ - filename = argv[1].a_w.w_symbol->s_name; - post("dssi~: loading patch: %s for instance %d", filename, instance); - - if(!strcmp(x->descriptor->LADSPA_Plugin->Label, "hexter") || - !strcmp(x->descriptor->LADSPA_Plugin->Label, "hexter6")) { - - key = malloc(10 * sizeof(char)); /* holds "patchesN" */ - strcpy(key, "patches0"); - - /* FIX: duplicates code from load_plugin() */ - fd = canvas_open(x->x_canvas, filename, "", - mydir, &filename, MAXPDSTRING, 0); - - if(fd >= 0){ - filepath = mydir; - pathlen = strlen(mydir); - temp = &mydir[pathlen]; - sprintf(temp, "/%s", filename); - fp = fopen(filepath, "rb"); - } - else{ - post("dssi~: unable to get file descriptor"); - } - - /*From dx7_voice_data by Sean Bolton */ - if(fp == NULL){ - post("dssi~: unable to open patch file: %s", filename); - return 0; - } - if (fseek(fp, 0, SEEK_END) || - (filelength = ftell(fp)) == -1 || - fseek(fp, 0, SEEK_SET)) { - post("dssi~: couldn't get length of patch file: %s", - filename); - fclose(fp); - return 0; - } - if (filelength == 0) { - post("dssi~: patch file has zero length"); - fclose(fp); - return 0; - } else if (filelength > 16384) { - post("dssi~: patch file is too large"); - fclose(fp); - return 0; - } - if (!(raw_patch_data = (unsigned char *) - malloc(filelength))) { - post( - "dssi~: couldn't allocate memory for raw patch file"); - fclose(fp); - return 0; - } - if (fread(raw_patch_data, 1, filelength, fp) - != (size_t)filelength) { - post("dssi~: short read on patch file: %s", filename); - free(raw_patch_data); - fclose(fp); - return 0; - } - fclose(fp); -#if DEBUG - post("Patch file length is %ul", filelength); -#endif - /* figure out what kind of file it is */ - filename_length = strlen(filename); - if (filename_length > 4 && - !strcmp(filename + filename_length - 4, ".dx7") && - filelength % DX7_VOICE_SIZE_PACKED == 0) { - /* It's a raw DX7 patch bank */ - -#if DEBUG - post("Raw DX7 format patch bank passed"); -#endif - count = filelength / DX7_VOICE_SIZE_PACKED; - if (count > maxpatches) - count = maxpatches; - memcpy(firstpatch, raw_patch_data, count * - DX7_VOICE_SIZE_PACKED); - - } else if (filelength > 6 && - raw_patch_data[0] == 0xf0 && - raw_patch_data[1] == 0x43 && - /*This was used to fix some problem with Galaxy exports - possibly dump in worng format. It is not needed, but it did work, so in future, we may be able to support more formats not just DX7 */ - /* ((raw_patch_data[2] & 0xf0) == 0x00 || - raw_patch_data[2] == 0x7e) &&*/ - (raw_patch_data[2] & 0xf0) == 0x00 && - raw_patch_data[3] == 0x09 && - (raw_patch_data[4] == 0x10 || - raw_patch_data[4] == 0x20) && - /* 0x10 is actual, 0x20 matches typo in manual */ - raw_patch_data[5] == 0x00) { - /* It's a DX7 sys-ex 32 voice dump */ - -#if DEBUG - post("SYSEX header check passed"); -#endif - - if (filelength != DX7_DUMP_SIZE_BULK || - raw_patch_data[DX7_DUMP_SIZE_BULK - 1] != 0xf7) { - post("dssi~: badly formatted DX7 32 voice dump!"); - count = 0; - -#ifdef CHECKSUM_PATCH_FILES_ON_LOAD - } else if (dx7_bulk_dump_checksum(&raw_patch_data[6], - DX7_VOICE_SIZE_PACKED * 32) != - raw_patch_data[DX7_DUMP_SIZE_BULK - 2]) { - - post("dssi~: DX7 32 voice dump with bad checksum!"); - count = 0; - -#endif - } else { - - count = 32; - if (count > maxpatches) - count = maxpatches; - memcpy(firstpatch, raw_patch_data + 6, count * DX7_VOICE_SIZE_PACKED); - - } - } else { - - /* unsuccessful load */ - post("dssi~: unknown patch bank file format!"); - count = 0; - - } - - free(raw_patch_data); - - if(count == 32) - value = encode_7in6((uint8_t *)&patchbuf[0].data[0], - count * DX7_VOICE_SIZE_PACKED); - - } - else if(!strcmp(x->descriptor->LADSPA_Plugin->Label, - "FluidSynth-DSSI")){ - key = malloc(6 * sizeof(char)); - strcpy(key, "load"); - value = filename; - } - else{ - post("dssi~: %s patches are not supported", - x->descriptor->LADSPA_Plugin->Label); - } - - } - - if(!strcmp(msg_type, "dir") && x->descriptor->configure){ - pathlen = strlen(argv[1].a_w.w_symbol->s_name) + 2; - x->project_dir = malloc((pathlen) * sizeof(char)); - atom_string(&argv[1], x->project_dir, pathlen); - post("dssi~: project directory for instance %d has been set to: %s", instance, x->project_dir); - key = DSSI_PROJECT_DIRECTORY_KEY; - value = x->project_dir; - } - - else if(!strcmp(msg_type, "dir")) - post("dssi~: %s %s: operation not supported", msg_type, - argv[1].a_w.w_symbol->s_name); - - if(!strcmp(msg_type, "show") || !strcmp(msg_type, "hide")){ - instance = (int)atom_getfloatarg(1, argc, argv) - 1; - if(!strcmp(msg_type, "show")) - toggle = 1; - else - toggle = 0; - - if(instance == -1){ - while(n_instances--) - dssi_show(x, n_instances, toggle); - } - else - dssi_show(x, instance, toggle); - } - - if(!strcmp(msg_type, "remap")) { - /* remap channel to instance */ - for(i = 0; i < x->n_instances && i < 128; i++){ - chan = (int)atom_getfloatarg(1 + i, argc, argv); - post("dssi~: remapped MIDI channel %d to %d", 1+i, chan); - x->channelMap[i+1] = chan; - } - } - - } - - /*Use this to send arbitrary configure message to plugin */ - else if(!strcmp(msg_type, "configure")){ - key = - (char *)malloc(key_size = (strlen(argv[1].a_w.w_symbol->s_name) + 2) * sizeof(char)); - atom_string(&argv[1], key, key_size); - if(argc >= 3){ - if (argv[2].a_type == A_FLOAT){ - val = atom_getfloatarg(2, argc, argv); - value = (char *)malloc(TYPE_STRING_SIZE * - sizeof(char)); - sprintf(value, "%.2f", val); - } - else if(argv[2].a_type == A_SYMBOL){ - value = - (char *)malloc(value_size = - (strlen(argv[2].a_w.w_symbol->s_name) + 2) * - sizeof(char)); - atom_string(&argv[2], value, value_size); - } - - } - - if(argc == 4 && argv[3].a_type == A_FLOAT) - instance = atom_getfloatarg(3, argc, argv) - 1; - else if (n_instances) - instance = -1; - } - - if(key != NULL && value != NULL){ - if(instance == -1){ - while(n_instances--){ - debug = dssi_tilde_send_configure( - x, key, value, n_instances); - dssi_tilde_configure_buffer(x, key, value, n_instances); - } - } - /*FIX: Put some error checking in here to make sure instance is valid*/ - else{ - - debug = dssi_tilde_send_configure(x, key, value, instance); - dssi_tilde_configure_buffer(x, key, value, instance); - } - } -#if DEBUG - post("The plugin returned %s", debug); -#endif - free(msg_type); - free(patchbuf); - - return 0; -} - -static void dssi_tilde_bang(t_dssi_tilde *x) -{ - t_atom at[3]; - - at[0].a_type = A_FLOAT; - at[1].a_type = A_SYMBOL; - at[2].a_type = A_SYMBOL; - - if(x->plugin_label != NULL){ - at[0].a_w.w_float = x->n_instances; - at[1].a_w.w_symbol = gensym ((char *)x->plugin_label); - } - else{ - at[0].a_w.w_float = 0; - at[1].a_w.w_symbol = gensym ("plugin"); - } - at[2].a_w.w_symbol = gensym ("instances"); - outlet_anything (x->control_outlet, gensym ("running"), 3, at); -} - -static t_int *dssi_tilde_perform(t_int *w) -{ - int N = (t_int)(w[2]); - t_dssi_tilde *x = (t_dssi_tilde *)(w[1]); - t_float **inputs = (t_float **)(&w[3]); - t_float **outputs = (t_float **)(&w[3] + x->plugin_ins); - int i, n, timediff, framediff, instance = 0; - /*See comment for dssi_tilde_plug_plugin */ - if(x->dsp){ - x->dsp_loop = 1; - - for(i = 0; i < x->plugin_ins; i++) - memcpy(x->plugin_InputBuffers[i], inputs[i], N * - sizeof(LADSPA_Data)); - - for (i = 0; i < x->n_instances; i++) - x->instanceEventCounts[i] = 0; - - for (;x->bufReadIndex != x->bufWriteIndex; x->bufReadIndex = - (x->bufReadIndex + 1) % EVENT_BUFSIZE) { - - instance = x->midiEventBuf[x->bufReadIndex].data.note.channel; - - /*This should never happen, but check anyway*/ - if(instance > x->n_instances || instance < 0){ - post( - "dssi~: %s: discarding spurious MIDI data, for instance %d", - x->descriptor->LADSPA_Plugin->Label, - instance); -#if DEBUG - post("n_instances = %d", x->n_instances); -#endif - continue; - } - - if (x->instanceEventCounts[instance] == EVENT_BUFSIZE){ - post("dssi~: MIDI overflow on channel %d", instance); - continue; - } - - timediff = (t_int)(clock_gettimesince(x->time_ref) * 1000) - - x->midiEventBuf[x->bufReadIndex].time.time.tv_nsec; - framediff = (t_int)((t_float)timediff * .000001 / x->sr_inv); - - if (framediff >= N || framediff < 0) - x->midiEventBuf[x->bufReadIndex].time.tick = 0; - else - x->midiEventBuf[x->bufReadIndex].time.tick = - N - framediff - 1; - - x->instanceEventBuffers[instance] - [x->instanceEventCounts[instance]] = - x->midiEventBuf[x->bufReadIndex]; -#if DEBUG - post("%s, note received on channel %d", - x->descriptor->LADSPA_Plugin->Label, - x->instanceEventBuffers[instance] - [x->instanceEventCounts[instance]].data.note.channel); -#endif - x->instanceEventCounts[instance]++; - -#if DEBUG - post("Instance event count for instance %d of %d: %d\n", - instance + 1, x->n_instances, x->instanceEventCounts[instance]); -#endif - - } - - i = 0; - while(i < x->n_instances){ - if(x->instanceHandles[i] && - x->descriptor->run_multiple_synths){ - x->descriptor->run_multiple_synths - (x->n_instances, x->instanceHandles, - (unsigned long)N, x->instanceEventBuffers, - &x->instanceEventCounts[0]); - break; - } - else if (x->instanceHandles[i] && - x->descriptor->run_synth){ - x->descriptor->run_synth(x->instanceHandles[i], - (unsigned long)N, x->instanceEventBuffers[i], - x->instanceEventCounts[i]); - i++; - } - else if (x->instanceHandles[i] && - x->descriptor->LADSPA_Plugin->run){ - x->descriptor->LADSPA_Plugin->run - (x->instanceHandles[i], N); - i++; - } - } - - - for(i = 0; i < x->plugin_outs; i++) - memcpy(outputs[i], (t_float *)x->plugin_OutputBuffers[i], N * - sizeof(LADSPA_Data)); - - /* - for(i = 0; i < x->plugin_outs; i++) - memcpy(x->outlets[i], (t_outlet *)x->plugin_OutputBuffers[i], N * - sizeof(LADSPA_Data));*/ - x->dsp_loop = 0; - } - return w + (x->plugin_ins + x->plugin_outs + 3); -} - -static void dssi_tilde_dsp(t_dssi_tilde *x, t_signal **sp) -{ - if(x->n_instances){ - - - t_int *dsp_vector, i, N, M; - - M = x->plugin_ins + x->plugin_outs + 2; - - dsp_vector = (t_int *) getbytes(M * sizeof(t_int)); - - dsp_vector[0] = (t_int)x; - dsp_vector[1] = (t_int)sp[0]->s_n; - - for(i = 2; i < M; i++) - dsp_vector[i] = (t_int)sp[i - 1]->s_vec; - - dsp_addv(dssi_tilde_perform, M, dsp_vector); - - - /* int n, m; - - t_float **outlets; - t_float **inlets; - - for(n = 0, m = 1; n < x->plugin_ins; n++, m++) - inlets[n] = sp[m]->s_vec; - for(n = 0; n < x->plugin_outs; n++, ++m) - outlets[n] = sp[m]->s_vec; - -*/ /* - - t_float **outlets = (t_float **)x->outlets; - t_float **inlets = (t_float **)x->inlets; - - m = 1; - - for(n = 0; n < x->plugin_ins; n++) - *inlets++ = sp[m++]->s_vec; - for(n = 0; n < x->plugin_outs; n++) - *outlets++ = sp[m++]->s_vec; - */ } - /* dsp_add(dssi_tilde_perform, 2, sp[0]->s_n, x); */ - -} - -static void dssi_tilde_quit_plugin(t_dssi_tilde *x){ - - t_int i, instance; - for(instance = 0; instance < x->n_instances; instance++) { - if(x->instances[instance].uiTarget && x->is_DSSI){ - lo_send(x->instances[instance].uiTarget, - x->instances[instance].ui_osc_quit_path, ""); - lo_address_free(x->instances[instance].uiTarget); - x->instances[instance].uiTarget = NULL; - } - /* no -- see comment in osc_exiting_handler */ - /* if (!instances[i].inactive) { */ - /* if (x->descriptor->LADSPA_Plugin->deactivate) { - x->descriptor->LADSPA_Plugin->deactivate - (x->instanceHandles[instance]); - }*/ - dssi_tilde_deactivate_plugin(x, (t_float)instance); - /* } */ - if (x->descriptor->LADSPA_Plugin && - x->descriptor->LADSPA_Plugin->cleanup) { - x->descriptor->LADSPA_Plugin->cleanup - (x->instanceHandles[instance]); - } - } -} - -static void dssi_tilde_free_plugin(t_dssi_tilde *x){ - - t_int i, instance; - if(x->plugin_label != NULL) - free((char *)x->plugin_label); - if(x->plugin_handle != NULL){ - instance = x->n_instances; - free((LADSPA_Handle)x->instanceHandles); - free(x->plugin_ControlInPortNumbers); - free((t_float *)x->plugin_InputBuffers); - free(x->instanceEventCounts); - free(x->plugin_ControlDataInput); - free(x->plugin_ControlDataOutput); - - while(instance--){ - - if(x->instances[instance].gui_pid){ -#if DEBUG - post("Killing GUI process PID = %d", x->instances[instance].gui_pid); -#endif - kill(x->instances[instance].gui_pid, SIGINT); - } - if (x->instances[instance].pluginPrograms) { - for (i = 0; i < - x->instances[instance].plugin_ProgramCount; i++) - free((void *) - x->instances[instance].pluginPrograms[i].Name); - free((char *)x->instances[instance].pluginPrograms); - x->instances[instance].pluginPrograms = NULL; - x->instances[instance].plugin_ProgramCount = 0; - } - free(x->instanceEventBuffers[instance]); - if(x->is_DSSI){ - free(x->instances[instance].ui_osc_control_path); - free(x->instances[instance].ui_osc_configure_path); - free(x->instances[instance].ui_osc_program_path); - free(x->instances[instance].ui_osc_show_path); - free(x->instances[instance].ui_osc_hide_path); - free(x->instances[instance].ui_osc_quit_path); - free(x->instances[instance].osc_url_path); - } - free(x->instances[instance].plugin_PortControlInNumbers); - if(x->plugin_outs) - free(x->plugin_OutputBuffers[instance]); - } - if(x->is_DSSI){ - if(x->project_dir != NULL) - free(x->project_dir); - free(x->osc_url_base); - dssi_tilde_configure_buffer_free(x); - } - free((snd_seq_event_t *)x->instanceEventBuffers); - free(x->instances); - free((t_float *)x->plugin_OutputBuffers); - - /*sleep(1);*/ - if(x->plugin_ins){ - for(i = 0; i < x->plugin_ins; i++) - inlet_free((t_inlet *)x->inlets[i]); - freebytes(x->inlets, x->plugin_ins * sizeof(t_inlet *)); - } - - if(x->plugin_outs){ - for(i = 0; i < x->plugin_outs; i++) - outlet_free((t_outlet *)x->outlets[i]); - freebytes(x->outlets, x->plugin_outs * sizeof(t_outlet *)); - } - if(x->control_outlet) - outlet_free(x->control_outlet); - if(x->plugin_basename) - free(x->plugin_basename); - if(x->port_info) - free(x->port_info); - } -} - -static void dssi_tilde_init_plugin(t_dssi_tilde *x){ - - x->project_dir = NULL; - x->configure_buffer_head = NULL; - x->outlets = NULL; - x->inlets = NULL; - x->control_outlet = NULL; - x->plugin_handle = NULL; - x->plugin_full_path = NULL; - x->plugin_label = NULL; - x->plugin_basename = NULL; - x->osc_url_base = NULL; - x->plugin_ControlDataInput = x->plugin_ControlDataOutput = NULL; - x->plugin_InputBuffers = x->plugin_OutputBuffers = NULL; - x->plugin_ControlInPortNumbers = NULL; - x->port_info = NULL; - x->descriptor = NULL; - x->instanceEventCounts = NULL; - x->instances = NULL; - x->instanceHandles = NULL; - x->is_DSSI = 0; - x->n_instances = 0; - x->dsp = 0; - x->dsp_loop = 0; - x->plugin_ins = x->plugin_outs = - x->plugin_controlIns = x->plugin_controlOuts = 0; - x->ports_in = x->ports_out = x->ports_controlIn = x->ports_controlOut = 0; - x->bufWriteIndex = x->bufReadIndex = 0; - -} - -static void *dssi_tilde_load_plugin(t_dssi_tilde *x, t_int argc, t_atom *argv){ - char *plugin_basename = NULL, - *plugin_full_path = NULL, - *tmpstr, - *plugin_label, - plugin_dir[MAXPDSTRING]; - -#if DEBUG - post("argc = %d", argc); -#endif - int i, - stop, - fd; - size_t pathlen; - - stop = 0; - - if (argc){ - char *argstr = strdup(argv[0].a_w.w_symbol->s_name); - - if(strstr(argstr, ":") != NULL){ - tmpstr = strtok(argstr, ":"); - plugin_full_path = strdup(tmpstr); - plugin_label = strtok(NULL, ":"); - // first part of the string is empty, i.e. ':mystring' - if (plugin_label == NULL) { - x->plugin_label = plugin_full_path; - plugin_full_path = NULL; - } else { - x->plugin_label = strdup(plugin_label); - } - } - else{ - x->plugin_label = strdup(argstr); - tmpstr = (char *)plugin_tilde_search_plugin_by_label(x, x->plugin_label); - if(tmpstr) - plugin_full_path = strdup(tmpstr); - } - free(argstr); -#if DEBUG - post("plugin path = %s", plugin_full_path); - post("plugin name = %s", x->plugin_label); -#endif - - if(plugin_full_path != NULL){ - /* First try to load as is: this will work if plugin_full_path is an - * absolute path, or the name of a library that is in DSSI_PATH - * or LADSPA_PATH environment variables */ - x->plugin_full_path = (char *)plugin_full_path; - /* If that didn't work, search for it in the 'canvas' path, which - * includes the Pd search dirs and any 'extra' paths set with - * [declare] */ - fd = canvas_open(x->x_canvas, plugin_full_path, "", - plugin_dir, &plugin_basename, MAXPDSTRING, 0); - - if (fd >= 0) { -#if DEBUG - post("plugin directory is %s, filename is %s", - plugin_dir, plugin_basename); -#endif - x->plugin_basename = strdup(plugin_basename); - pathlen = strlen(plugin_dir); - tmpstr = &plugin_dir[pathlen]; - sprintf(tmpstr, "/%s", plugin_basename); - tmpstr = plugin_dir; - x->plugin_handle = loadLADSPAPluginLibrary(tmpstr); - } else { - x->plugin_handle = loadLADSPAPluginLibrary(plugin_full_path); - } - - if (x->plugin_handle == NULL) - error("dssi~: can't find plugin in Pd paths, " - "try using [declare] to specify the path."); - - } - - if (x->plugin_handle != NULL){ - tmpstr = strdup(plugin_full_path); - /* Don't bother working out the plugin name if we used canvas_open() - * to get the path */ - if(plugin_basename == NULL){ - if(strstr(tmpstr, ".so")){ - plugin_basename = strtok((char *)tmpstr, "/"); - while(strstr(plugin_basename, ".so") == NULL) - plugin_basename = strtok(NULL, "/"); - x->plugin_basename = strdup(plugin_basename); -#if DEBUG - post("plugin basename = %s", x->plugin_basename); -#endif - } - else{ - post("dssi~: invalid plugin path, must end in .so"); - return (void *) x; - } - } - free(tmpstr); - if(x->desc_func = (DSSI_Descriptor_Function)dlsym(x->plugin_handle, "dssi_descriptor")){ - x->is_DSSI = 1; - x->descriptor = (DSSI_Descriptor *)x->desc_func(0); - } - else if(x->desc_func = - (DSSI_Descriptor_Function)dlsym(x->plugin_handle, "ladspa_descriptor")){ - x->is_DSSI = 0; - x->descriptor = - ladspa_to_dssi((LADSPA_Descriptor *) - x->desc_func(0)); - } - - - if(argc >= 2) - x->n_instances = (t_int)argv[1].a_w.w_float; - else - x->n_instances = 1; - - -#if DEBUG - post("n_instances = %d", x->n_instances); -#endif - x->instances = (t_dssi_instance *)malloc(sizeof(t_dssi_instance) * - x->n_instances); - - if(x->descriptor){ -#if DEBUG - post("%s loaded successfully!", - x->descriptor->LADSPA_Plugin->Label); -#endif - - /*allocate memory for port_info*/ - - x->port_info = (t_port_info *)malloc - (x->descriptor->LADSPA_Plugin->PortCount * - sizeof(t_port_info)); - - dssi_tilde_port_info(x); - dssi_tilde_assign_ports(x); - for(i = 0; i < x->n_instances; i++){ - x->instanceHandles[i] = - x->descriptor->LADSPA_Plugin-> - instantiate(x->descriptor->LADSPA_Plugin, x->sr); - if (!x->instanceHandles[i]){ - post("dssi~: instantiation of instance %d failed", i); - stop = 1; - break; - } - } - if(!stop){ - for(i = 0;i < x->n_instances; i++) - dssi_tilde_init_instance(x, i); - for(i = 0;i < x->n_instances; i++) - dssi_tilde_connect_ports(x, i); - for(i = 0;i < x->n_instances; i++) - dssi_tilde_activate_plugin(x, i); - - if(x->is_DSSI){ - for(i = 0;i < x->n_instances; i++) - dssi_tilde_osc_setup(x, i); -#if LOADGUI - for(i = 0;i < x->n_instances; i++) - dssi_tilde_load_gui(x, i); -#endif - for(i = 0;i < x->n_instances; i++) - dssi_tilde_init_programs(x, i); - - for(i = 0; i < x->n_instances && i < 128; i++){ - x->channelMap[i] = i; - } - } - } - } - } - else - post("dssi~: error: plugin not loaded"); - } - else - post("dssi~: no arguments given, please supply a path"); - - x->control_outlet = - outlet_new (&x->x_obj, gensym("control")); - - if (x->plugin_handle != NULL){ - if(x->plugin_outs){ - x->outlets = (t_outlet **)getbytes(x->plugin_outs * sizeof(t_outlet *)); - for(i = 0;i < x->plugin_outs; i++) - x->outlets[i] = outlet_new(&x->x_obj, &s_signal); - /* x->outlets = - (t_float **)calloc(x->plugin_outs, - sizeof(t_float *)); - */ - } - else - post("dssi~: error: plugin has no outputs"); - if(x->plugin_ins){ - x->inlets = (t_inlet **)getbytes(x->plugin_ins * sizeof(t_inlet *)); - for(i = 0;i < x->plugin_ins; i++) - x->inlets[i] = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - /* x->inlets = - (t_float **)calloc(x->plugin_ins, - sizeof(t_float *)); - */ - } - else - post("dssi~: error: plugin has no inputs"); - - x->dsp = 1; - post("dssi~: %d instances of %s, ready.", x->n_instances, - x->plugin_label); - } - else - post("dssi~: error: no plugin handle"); - - return (void *)x; -} - - -/* This method is currently buggy. PD's inlet/outlet handling seems buggy if you try to create ins/outs on the fly. Needs further investigation ...*/ -static void dssi_tilde_plug_plugin(t_dssi_tilde *x, t_symbol *s, int argc, t_atom *argv){ - - x->dsp = 0; - dssi_tilde_quit_plugin(x); - while(1){ - if(!x->dsp_loop){ - dssi_tilde_free_plugin(x); - break; - } - } - dssi_tilde_init_plugin(x); - dssi_tilde_load_plugin(x, argc, argv); -} - -static void *dssi_tilde_new(t_symbol *s, t_int argc, t_atom *argv){ - - t_dssi_tilde *x = (t_dssi_tilde *)pd_new(dssi_tilde_class); - post("\n========================================\ndssi~: DSSI/LADSPA host - version %.2f\n========================================\n", VERSION); - - dssi_tilde_init_plugin(x); - - x->sr = (t_int)sys_getsr(); - x->sr_inv = 1 / (t_float)x->sr; - x->time_ref = (t_int)clock_getlogicaltime; - x->blksize = sys_getblksize(); - x->dsp = 0; - x->x_canvas = canvas_getcurrent(); - - pthread_mutex_init(&x->midiEventBufferMutex, NULL); - return dssi_tilde_load_plugin(x, argc, argv); - -} - -static void dssi_tilde_free(t_dssi_tilde *x){ - -#if DEBUG - post("Calling dssi_tilde_free"); -#endif - - dssi_tilde_quit_plugin(x); - dssi_tilde_free_plugin(x); - -} - -static void dssi_tilde_sigchld_handler(int sig) { - wait(NULL); -} - -void dssi_tilde_setup(void) { - - dssi_tilde_class = class_new(gensym("dssi~"), (t_newmethod)dssi_tilde_new, - (t_method)dssi_tilde_free, sizeof(t_dssi_tilde), 0, A_GIMME, 0); - class_addlist(dssi_tilde_class, dssi_tilde_list); - class_addbang(dssi_tilde_class, dssi_tilde_bang); - class_addmethod(dssi_tilde_class, - (t_method)dssi_tilde_dsp, gensym("dsp"), 0); - class_addmethod(dssi_tilde_class, (t_method)dssi_tilde_dssi_methods, - gensym("dssi"), A_GIMME, 0); - class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_control, - gensym ("control"),A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0); - class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_info, - gensym ("info"),0); - class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_list_plugins, - gensym ("listplugins"),0); - class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_reset, - gensym ("reset"), A_DEFFLOAT, 0); - class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_plug_plugin, - gensym ("plug"),A_GIMME,0); - /* class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_activate_plugin, - gensym ("activate"),A_DEFFLOAT - 1,0); - class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_deactivate_plugin, - gensym ("deactivate"),A_DEFFLOAT - 1,0);*/ - class_sethelpsymbol(dssi_tilde_class, gensym("dssi-help")); - CLASS_MAINSIGNALIN(dssi_tilde_class, t_dssi_tilde, f); - signal(SIGCHLD, dssi_tilde_sigchld_handler); -} - -static int osc_message_handler(const char *path, const char *types, - lo_arg **argv,int argc, void *data, void *user_data) -{ -#if DEBUG - post("osc_message_handler active"); -#endif - int i, instance = 0; - const char *method; - char chantemp[2]; - t_dssi_tilde *x = (t_dssi_tilde *)(user_data); - - if (strncmp(path, "/dssi/", 6)){ -#if DEBUG - post("calling osc_debug_handler"); -#endif - return osc_debug_handler(path, types, argv, argc, data, x); - } - for (i = 0; i < x->n_instances; i++) { - if (!strncmp(path + 6, x->instances[i].osc_url_path, - strlen(x->instances[i].osc_url_path))) { - instance = i; - break; - } - } -#if DEBUG - for(i = 0; i < argc; i++){ - post("got osc request %c from instance %d, path: %s", - types[i],instance,path); - } -#endif - - if (!x->instances[instance].osc_url_path){ -#if DEBUG - post("calling osc_debug_handler"); -#endif - return osc_debug_handler(path, types, argv, argc, data, x); - } - method = path + 6 + strlen(x->instances[instance].osc_url_path); - if (*method != '/' || *(method + 1) == 0){ -#if DEBUG - post("calling osc_debug_handler"); -#endif - return osc_debug_handler(path, types, argv, argc, data, x); - } - method++; - - if (!strcmp(method, "configure") && argc == 2 && !strcmp(types, "ss")) { - -#if DEBUG - post("calling osc_configure_handler"); -#endif - return osc_configure_handler(x, argv, instance); - - } else if (!strcmp(method, "control") && argc == 2 && !strcmp(types, "if")) { -#if DEBUG - post("calling osc_control_handler"); -#endif - return osc_control_handler(x, argv, instance); - } - - else if (!strcmp(method, "midi") && argc == 1 && !strcmp(types, "m")) { - -#if DEBUG - post("calling osc_midi_handler"); -#endif - return osc_midi_handler(x, argv, instance); - - } else if (!strcmp(method, "program") && argc == 2 && !strcmp(types, "ii")){ -#if DEBUG - post("calling osc_program_handler"); -#endif - return osc_program_handler(x, argv, instance); - - } else if (!strcmp(method, "update") && argc == 1 && !strcmp(types, "s")){ -#if DEBUG - post("calling osc_update_handler"); -#endif - return osc_update_handler(x, argv, instance); - - } else if (!strcmp(method, "exiting") && argc == 0) { - - return osc_exiting_handler(x, argv, instance); - } - - return osc_debug_handler(path, types, argv, argc, data, x); -} - diff --git a/dssi/src/dssi~.h b/dssi/src/dssi~.h deleted file mode 100644 index 6aadb85..0000000 --- a/dssi/src/dssi~.h +++ /dev/null @@ -1,183 +0,0 @@ -/* dssi~ - A DSSI host for PD - * - * Copyright 2006 Jamie Bullock and others - * - * This file incorporates code from the following sources: - * - * jack-dssi-host (BSD-style license): Copyright 2004 Chris Cannam, Steve Harris and Sean Bolton. - * - * Hexter (GPL license): Copyright (C) 2004 Sean Bolton and others. - * - * - * This program is free software; you can redistribute it and/or - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "m_pd.h" -#include "dssi.h" -#include -#include -#include -#include -#include -#include /*for exit()*/ -#include /* for fork() */ -#include /* for kill() */ -#include /* for wait() */ -#include /* for readdir() */ - -#define DX7_VOICE_SIZE_PACKED 128 /*From hexter_types.h by Sean Bolton */ -#define DX7_DUMP_SIZE_BULK 4096+8 - - -#define VERSION 0.99 -#define EVENT_BUFSIZE 1024 -#define OSC_BASE_MAX 1024 -#define TYPE_STRING_SIZE 20 /* Max size of event type string (must be two more bytes than needed) */ -#define DIR_STRING_SIZE 1024 /* Max size of directory string */ -#define ASCII_n 110 -#define ASCII_p 112 -#define ASCII_c 99 -#define ASCII_b 98 -#define ASCII_t 116 -#define ASCII_a 97 - -#define LOADGUI 0 /* FIX: depracate this */ -#ifdef DEBUG -#define CHECKSUM_PATCH_FILES_ON_LOAD 1 -#endif - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif - - -/*From dx7_voice.h by Sean Bolton */ - -typedef struct _dx7_patch_t { - uint8_t data[128]; -} dx7_patch_t; - -typedef struct _dssi_instance { - - long currentBank; - long currentProgram; - int pendingBankLSB; - int pendingBankMSB; - int pendingProgramChange; - - int plugin_ProgramCount; - DSSI_Program_Descriptor *pluginPrograms; - - lo_address uiTarget; /*osc stuff */ - int ui_hidden; - int ui_show; - int uiNeedsProgramUpdate; - char *ui_osc_control_path; - char *ui_osc_configure_path; - char *ui_osc_program_path; - char *ui_osc_show_path; - char *ui_osc_hide_path; - char *ui_osc_quit_path; - - int *plugin_PortControlInNumbers; /*not sure if this should go here?*/ - - char *osc_url_path; - pid_t gui_pid; - -} t_dssi_instance; - -struct dssi_configure_pair { - t_int instance; - char *key, - *value; - struct dssi_configure_pair *next; -}; - -typedef struct dssi_configure_pair t_dssi_configure_pair; - -typedef struct _port_info { - t_atom type, - data_type, - name, - lower_bound, - upper_bound, - p_default; -} t_port_info; - -typedef struct _dssi_tilde { - t_object x_obj; - t_int is_DSSI; - char *plugin_label; - char *plugin_full_path; /*absolute path to plugin */ - t_canvas *x_canvas; /* pointer to the canvas the object is instantiated on */ - void *plugin_handle; - char *project_dir; /* project dircetory */ - LADSPA_Handle *instanceHandles; /*was handle*/ - t_dssi_instance *instances; - int n_instances; - unsigned long *instanceEventCounts; - unsigned char channelMap[128]; - snd_seq_event_t **instanceEventBuffers; - - snd_seq_event_t midiEventBuf[EVENT_BUFSIZE]; - /*static snd_seq_event_t **instanceEventBuffers;*/ - int bufWriteIndex, bufReadIndex; - pthread_mutex_t midiEventBufferMutex; - /*static pthread_mutex_t listHandlerMutex = PTHREAD_MUTEX_INITIALIZER;*/ - - DSSI_Descriptor_Function desc_func; - DSSI_Descriptor *descriptor; - - t_port_info *port_info; - - t_int ports_in, ports_out, ports_controlIn, ports_controlOut; - t_int plugin_ins;/* total audio input ports for plugin*/ - t_int plugin_outs;/* total audio output ports plugin*/ - t_int plugin_controlIns;/* total control input ports*/ - t_int plugin_controlOuts;/* total control output ports */ - - unsigned long *plugin_ControlInPortNumbers; /*Array of input port numbers for the plugin */ - - t_float **plugin_InputBuffers, **plugin_OutputBuffers; /* arrays of arrays for buffering audio for each audio port */ - t_float *plugin_ControlDataInput, *plugin_ControlDataOutput; /*arrays for control data for each port (1 item per 'run')*/ - lo_server_thread osc_thread; - char *osc_url_base; - char *plugin_basename; - - t_int time_ref; /*logical time reference */ - t_int sr; - t_float sr_inv; - t_int blksize; - t_float f; - - t_outlet **outlets; - t_inlet **inlets; - t_outlet *control_outlet; - - t_dssi_configure_pair *configure_buffer_head; - - t_int dsp; /* boolean dsp setting */ - t_int dsp_loop; - -} t_dssi_tilde; - -static char *dssi_tilde_send_configure(t_dssi_tilde *x, char *key, - char *value, t_int instance); -static int osc_message_handler(const char *path, const char *types, - lo_arg **argv, int argc, void *data, void *user_data); -static LADSPA_Data get_port_default(t_dssi_tilde *x, int port); -static void MIDIbuf(int type, int chan, int param, int val, t_dssi_tilde *x); - - diff --git a/dssi/src/jload.c b/dssi/src/jload.c deleted file mode 100644 index 1672b91..0000000 --- a/dssi/src/jload.c +++ /dev/null @@ -1,214 +0,0 @@ -/* load.c - - Free software by Richard W.E. Furse. Do with as you will. No - warranty. */ - -/* patched by Jarno Seppänen, jams@cs.tut.fi, for plugin~ */ - -/* patched by Jamie Bullock, jamie@postlude.co.uk, for dssi~ */ - -/*****************************************************************************/ - -#include -#include -#include -#include - -/*****************************************************************************/ - -#include "ladspa.h" -#include "jutils.h" - -/*****************************************************************************/ - -/* This function provides a wrapping of dlopen(). When the filename is - not an absolute path (i.e. does not begin with / character), this - routine will search the LADSPA_PATH for the file. */ -static void * -dlopenLADSPA(const char * pcFilename, int iFlag) { - - char * pcBuffer; - const char * pcEnd; - const char * pcLADSPAPath; - const char * pcStart; - int iEndsInSO; - int iNeedSlash; - size_t iFilenameLength; - void * pvResult; - char *pluginPath; - - - iFilenameLength = strlen(pcFilename); - pvResult = NULL; - - /* First we just try calling dlopen(). This works if the user knows - about dlopen() and has placed the file on the LD_LIBRARY path or - has used an absolute directory. */ - pvResult = dlopen(pcFilename, iFlag); - if (pvResult != NULL) - return pvResult; - - /* If the filename is not absolute then we wish to check along the - LADSPA_PATH path to see if we can find the file there. */ - if (pcFilename[0] != '/') { - - pcLADSPAPath = NULL; - - if(getenv("LADSPA_PATH") && getenv("DSSI_PATH")){ - pluginPath = malloc(sizeof(char) * - (strlen(getenv("LADSPA_PATH")) + 1) + - sizeof(char) * strlen(getenv("DSSI_PATH"))); - sprintf(pluginPath, "%s:%s", - getenv("LADSPA_PATH"), getenv("DSSI_PATH")); - pcLADSPAPath = pluginPath; - free(pluginPath); - } - if (pcLADSPAPath == NULL) { - fprintf(stderr, "Warning: no LADSPA_PATH and DSSI_PATH, assuming /usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi\n"); - pcLADSPAPath = - "/usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi"; - } - - if (pcLADSPAPath) { - - pcStart = pcLADSPAPath; - while (*pcStart != '\0') { - pcEnd = pcStart; - while (*pcEnd != ':' && *pcEnd != '\0') - pcEnd++; - - pcBuffer = malloc(iFilenameLength + 2 + (pcEnd - pcStart)); - if (pcEnd > pcStart) - strncpy(pcBuffer, pcStart, pcEnd - pcStart); - iNeedSlash = 0; - if (pcEnd > pcStart) - if (*(pcEnd - 1) != '/') { - iNeedSlash = 1; - pcBuffer[pcEnd - pcStart] = '/'; - } - strcpy(pcBuffer + iNeedSlash + (pcEnd - pcStart), pcFilename); - - pvResult = dlopen(pcBuffer, iFlag); - - free (pcBuffer); - if (pvResult != NULL){ - return pvResult; - } - - pcStart = pcEnd; - if (*pcStart == ':') - pcStart++; - } - } else { - fputs ("warning: You haven't specified the LADSPA_PATH environment variable and didn't specify an absolute path to the plug-in.\n" - "Please set the LADSPA_PATH variable to point to your LADSPA plug-in directories (eg. \"export LADSPA_PATH=/usr/local/lib/ladspa\").\n", stderr); - } - } - - /* As a last ditch effort, check if filename does not end with - ".so". In this case, add this suffix and recurse. */ - iEndsInSO = 0; - if (iFilenameLength > 3) - iEndsInSO = (strcmp(pcFilename + iFilenameLength - 3, ".so") == 0); - if (!iEndsInSO) { - pcBuffer = malloc(iFilenameLength + 4); - strcpy(pcBuffer, pcFilename); - strcat(pcBuffer, ".so"); - pvResult = dlopenLADSPA(pcBuffer, iFlag); - } - - if (pvResult != NULL) - return pvResult; - - /* If nothing has worked, then at least we can make sure we set the - correct error message - and this should correspond to a call to - dlopen() with the actual filename requested. The dlopen() manual - page does not specify whether the first or last error message - will be kept when multiple calls are made to dlopen(). We've - covered the former case - now we can handle the latter by calling - dlopen() again here. */ - return dlopen(pcFilename, iFlag); -} - -/*****************************************************************************/ - -void * -loadLADSPAPluginLibrary(const char * pcPluginFilename) { - - void * pvPluginHandle; - - pvPluginHandle = dlopenLADSPA(pcPluginFilename, RTLD_NOW); - if (!pvPluginHandle) { - fprintf(stderr, - "Failed to load plugin \"%s\": %s\n", - pcPluginFilename, - dlerror()); -#if 0 - exit(1); -#else - return NULL; -#endif - } - - return pvPluginHandle; -} - -/*****************************************************************************/ - -void -unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary) { - dlclose(pvLADSPAPluginLibrary); -} - -/*****************************************************************************/ - -const LADSPA_Descriptor * -findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary, - const char * pcPluginLibraryFilename, - const char * pcPluginLabel) { - - const LADSPA_Descriptor * psDescriptor; - LADSPA_Descriptor_Function pfDescriptorFunction; - unsigned long lPluginIndex; - - dlerror(); - pfDescriptorFunction - = (LADSPA_Descriptor_Function)dlsym(pvLADSPAPluginLibrary, - "ladspa_descriptor"); - if (!pfDescriptorFunction) { - const char * pcError = dlerror(); - if (pcError) - fprintf(stderr, - "Unable to find ladspa_descriptor() function in plugin " - "library file \"%s\": %s.\n" - "Are you sure this is a LADSPA plugin file?\n", - pcPluginLibraryFilename, - pcError); -#if 0 - exit(1); -#else - return NULL; -#endif - } - - for (lPluginIndex = 0;; lPluginIndex++) { - psDescriptor = pfDescriptorFunction(lPluginIndex); - if (psDescriptor == NULL) { - fprintf(stderr, - "Unable to find label \"%s\" in plugin library file \"%s\".\n", - pcPluginLabel, - pcPluginLibraryFilename); -#if 0 - exit(1); -#else - return NULL; -#endif - } - if (strcmp(psDescriptor->Label, pcPluginLabel) == 0) - return psDescriptor; - } -} - -/*****************************************************************************/ - -/* EOF */ diff --git a/dssi/src/jsearch.c b/dssi/src/jsearch.c deleted file mode 100644 index 593c6f5..0000000 --- a/dssi/src/jsearch.c +++ /dev/null @@ -1,154 +0,0 @@ -/* search.c - - Free software by Richard W.E. Furse. Do with as you will. No - warranty. */ - -/* patched by Jarno Seppänen, jams@cs.tut.fi, for plugin~ */ - -/* patched by Jamie Bullock, jamie@postlude.co.uk, for dssi~ */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -/*****************************************************************************/ - -#include "dssi.h" -#include "jutils.h" - -/*****************************************************************************/ - -/* Search just the one directory. */ - static void -LADSPADirectoryPluginSearch (const char * pcDirectory, - LADSPAPluginSearchCallbackFunction fCallbackFunction, - void* user_data) -{ - char * pcFilename; - DIR * psDirectory; - DSSI_Descriptor_Function fDescriptorFunction; - long lDirLength; - long iNeedSlash; - struct dirent * psDirectoryEntry; - void * pvPluginHandle; - int is_DSSI = 0; - - lDirLength = strlen(pcDirectory); - if (!lDirLength) - return; - if (pcDirectory[lDirLength - 1] == '/') - iNeedSlash = 0; - else - iNeedSlash = 1; - - psDirectory = opendir(pcDirectory); - if (!psDirectory) - return; - - while (1) { - - psDirectoryEntry = readdir(psDirectory); - if (!psDirectoryEntry) { - closedir(psDirectory); - return; - } - - pcFilename = malloc(lDirLength - + strlen(psDirectoryEntry->d_name) - + 1 + iNeedSlash); - strcpy(pcFilename, pcDirectory); - if (iNeedSlash) - strcat(pcFilename, "/"); - strcat(pcFilename, psDirectoryEntry->d_name); - - pvPluginHandle = dlopen(pcFilename, RTLD_LAZY); - if (pvPluginHandle) { - /* This is a file and the file is a shared library! */ - - dlerror(); - if(fDescriptorFunction = (DSSI_Descriptor_Function)dlsym(pvPluginHandle, - "ladspa_descriptor")) - is_DSSI = 0; - - else if(fDescriptorFunction = (DSSI_Descriptor_Function)dlsym(pvPluginHandle, - "dssi_descriptor")) - is_DSSI = 1; - - if (dlerror() == NULL && fDescriptorFunction) { - /* We've successfully found a ladspa_descriptor function. Pass - it to the callback function. */ - fCallbackFunction(pcFilename, - pvPluginHandle, - fDescriptorFunction, - user_data, - is_DSSI); - dlclose (pvPluginHandle); - } - else { - /* It was a library, but not a LADSPA one. Unload it. */ - dlclose(pcFilename); - } - } - } -} - -/*****************************************************************************/ - - void -LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction, - void* user_data) -{ - - char * pcBuffer; - const char * pcEnd; - const char * pcLADSPAPath; - char *pluginPath; - const char * pcStart; - - - pcLADSPAPath = NULL; - - if(getenv("LADSPA_PATH") && getenv("DSSI_PATH")){ - pluginPath = malloc(sizeof(char) * - (strlen(getenv("LADSPA_PATH")) + 1) + - sizeof(char) * strlen(getenv("DSSI_PATH"))); - sprintf(pluginPath, "%s:%s", - getenv("LADSPA_PATH"), getenv("DSSI_PATH")); - pcLADSPAPath = pluginPath; - free(pluginPath); - } - if (pcLADSPAPath == NULL) { - fprintf(stderr, "Warning: no LADSPA_PATH and DSSI_PATH, assuming /usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi\n"); - pcLADSPAPath = - "/usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi"; - } - - pcStart = pcLADSPAPath; - while (*pcStart != '\0') { - pcEnd = pcStart; - while (*pcEnd != ':' && *pcEnd != '\0') - pcEnd++; - - pcBuffer = malloc(1 + pcEnd - pcStart); - if (pcEnd > pcStart) - strncpy(pcBuffer, pcStart, pcEnd - pcStart); - pcBuffer[pcEnd - pcStart] = '\0'; - - LADSPADirectoryPluginSearch(pcBuffer, fCallbackFunction, user_data); - - pcStart = pcEnd; - if (*pcStart == ':') - pcStart++; - } -} - - -/*****************************************************************************/ - -/* EOF */ diff --git a/dssi/src/jutils.h b/dssi/src/jutils.h deleted file mode 100644 index fdf718f..0000000 --- a/dssi/src/jutils.h +++ /dev/null @@ -1,69 +0,0 @@ -/* utils.h - - Free software by Richard W.E. Furse. Do with as you will. No - warranty. */ - -/* patched by Jarno Seppänen, jams@cs.tut.fi, for plugin~ */ - -/* patched by Jamie Bullock, jamie@postlude.co.uk, for dssi~ */ - -#ifndef LADSPA_SDK_LOAD_PLUGIN_LIB -#define LADSPA_SDK_LOAD_PLUGIN_LIB - -/*****************************************************************************/ - -#include "dssi.h" - -/*****************************************************************************/ - -/* Functions in load.c: */ - -/* This function call takes a plugin library filename, searches for - the library along the LADSPA_PATH, loads it with dlopen() and - returns a plugin handle for use with findPluginDescriptor() or - unloadLADSPAPluginLibrary(). Errors are handled by writing a - message to stderr and calling exit(1). It is alright (although - inefficient) to call this more than once for the same file. */ -void * loadLADSPAPluginLibrary(const char * pcPluginFilename); - -/* This function unloads a LADSPA plugin library. */ -void unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary); - -/* This function locates a LADSPA plugin within a plugin library - loaded with loadLADSPAPluginLibrary(). Errors are handled by - writing a message to stderr and calling exit(1). Note that the - plugin library filename is only included to help provide - informative error messages. */ -const LADSPA_Descriptor * -findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary, - const char * pcPluginLibraryFilename, - const char * pcPluginLabel); - -/*****************************************************************************/ - -/* Functions in search.c: */ - -/* Callback function for use with LADSPAPluginSearch(). The callback - function passes the filename (full path), a plugin handle (dlopen() - style) and a LADSPA_DescriptorFunction (from which - LADSPA_Descriptors can be acquired). */ -typedef void LADSPAPluginSearchCallbackFunction -(const char * pcFullFilename, - void * pvPluginHandle, - DSSI_Descriptor_Function fDescriptorFunction, - void* user_data, - int is_DSSI); - -/* Search through the $(LADSPA_PATH) (or a default path) for any - LADSPA plugin libraries. Each plugin library is tested using - dlopen() and dlsym(,"ladspa_descriptor"). After loading each - library, the callback function is called to process it. This - function leaves items passed to the callback function open. */ -void LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction, - void* user_data); - -/*****************************************************************************/ - -#endif - -/* EOF */ diff --git a/pluginhost~/README b/pluginhost~/README new file mode 100644 index 0000000..ab164e8 --- /dev/null +++ b/pluginhost~/README @@ -0,0 +1,45 @@ +dssi~ - a DSSI host for Pure Data +================================= + +This directory (dssi) contains sourcecode and possibly binaries for a DSSI host for Pure Data. To find out more about DSSI visit http://dssi.sourceforge.net. + +The functionality of the external is demonstrated in in the help patch (dssi/doc/help-dssi.pd). + + + +Requirements +------------ + +To compile dssi~ the following are required; + +DSSI >= 0.9 +LADSPA SDK >= 1.x +liblo >= 0.12 +alsa/seq_event.h - included +pd headers >= 0.37 + +The help patch requires: + +PD >= 0.39 + + + +Installation +------------ + +From the same directory as the makefile type: + +make +make install (as root) + +Once compiled the binary file and help file should be placed in directories that are included in Pure Data's search path. + + + +License +------- + +All files included in the dssi/src/ directory, and all binary files (if included) are licensed under the GNU GPL Version 2 (see gpl.txt for details). + +All files included in the dssi/include/ directory are licensed under the GNU Lesser General Public License (see lesser.txt for details). + diff --git a/pluginhost~/RELEASE b/pluginhost~/RELEASE new file mode 100644 index 0000000..948c9ea --- /dev/null +++ b/pluginhost~/RELEASE @@ -0,0 +1,21 @@ + +0.93 + +- Fixed control in bug and a few others + +0.91 + +-Fixed bugs created by adding LADSPA support + +0.89 + +-Added support for LADSPA plugins mostly using code from plugin~ +-Reorganised inlet/outlet structure + +0.83 + +-Added FluidSynth-DSSI patch load support (i.e. soundfonts) + +0.82 + +-Added hexter6 patch load support diff --git a/pluginhost~/doc/dssi-help.pd b/pluginhost~/doc/dssi-help.pd new file mode 100644 index 0000000..b4e5ba3 --- /dev/null +++ b/pluginhost~/doc/dssi-help.pd @@ -0,0 +1,172 @@ +#N canvas 186 66 1411 654 10; +#X obj 1268 524 catch~ mix; +#X text 602 15 dssi~ - a DSSI host for Pure Data --------------------------------- +; +#X obj 7 63 cnv 15 1400 300 empty empty dssi~_instance_1 20 12 0 14 +-257472 -66577 0; +#X obj 443 203 line; +#X msg 443 182 \$1 10; +#X obj 441 225 expr $f1 / 127 * 16383; +#X msg 443 122 0; +#X floatatom 300 185 5 0 0 0 - - -; +#X floatatom 443 165 5 0 0 0 - - -; +#X msg 72 256 n \$1; +#X obj 110 256 r chan; +#X obj 51 231 list prepend n 2; +#X obj 300 226 list prepend c 2; +#X obj 51 208 pack f f; +#X msg 33 147 60; +#X msg 78 147 80; +#X msg 300 205 7 \$1; +#X obj 441 247 list prepend b 2 0; +#X obj 441 324 throw~ mix; +#X obj 119 148 hsl 128 15 60 80 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 167 206 select -1; +#X obj 356 250 r chan; +#X obj 303 146 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 446 144 hsl 128 15 -63 63 0 1 empty empty empty -2 -6 0 8 -262144 +-1 -1 6350 1; +#X obj 600 291 r dssi1-config; +#X obj 708 179 s dssi1-config; +#X obj 912 178 s dssi1-config; +#X obj 1194 180 s dssi1-config; +#X floatatom 595 142 5 0 0 0 - - -; +#X msg 318 250 c \$1; +#X obj 528 268 r chan; +#X msg 473 268 b \$1 0; +#X obj 1014 337 s chan; +#X floatatom 1015 319 5 1 2 1 channel - -; +#X text 283 98 ----control change----; +#X obj 667 222 r chan; +#X text 447 97 ----pitch bend----; +#X text 585 97 --program change--; +#X text 105 96 -----notes-----; +#X text 718 97 --sysex patch/bank load--; +#X obj 5 371 cnv 15 600 300 empty empty dssi~_instance_2 20 12 0 14 +-225280 -66577 0; +#X obj 435 620 throw~ mix; +#X obj 474 122 loadbang; +#X msg 613 221 p \$1 0; +#X text 940 96 --configuration--; +#X text 947 113 (key value pair); +#X text 867 279 Select channel (hexter instance) for note \, bend \, +program and control data:; +#X obj 595 199 list prepend p 2 0; +#X text 1126 98 --show/hide GUI--; +#X obj 1266 547 dssi/output~; +#X obj 49 186 makenote 80 10000; +#X msg 1282 136 reset; +#X msg 1340 136 reset 1; +#X text 1286 98 -reset plugin-; +#X text 1286 115 (all notes off); +#X obj 229 315 print; +#X msg 78 305 listplugins; +#X msg 101 329 info; +#X msg 709 134 dssi load TX-SYX/TFI2.SYX 2; +#X msg 710 154 dssi load TX-SYX/TFI1.SYX 1; +#X msg 910 134 dssi configure polyphony 10 2; +#X msg 911 156 dssi configure GLOBAL:polyphony 10; +#X msg 1134 114 dssi hide; +#X msg 1135 135 dssi show; +#X msg 1206 114 dssi show 2; +#X text 806 212 LAST ARGUMENT GIVES PLUGIN INSTANCE TO BE CONFIGURED +\, NO LAST ARGUMENT=(ALL INSTANCES); +#X obj 388 620 print; +#X text 738 458 Usage: [dssi~ <[path to libary:plugin name] or [plugin +name]> ]; +#X obj 229 291 dssi~ /usr/local/lib/dssi/hexter.so:hexter 2; +#X msg 193 342 control #1 445; +#X obj 451 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 7900 1; +#X obj 378 582 dssi~ sine_faaa 6 -------------; +#X obj 284 438 expr $f1 \; $f1*2 \; $f1*3 \; $f1*4 \; $f1*5 \; $f1*6 +; +#X obj 285 397 loadbang; +#X msg 285 419 220; +#X obj 471 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 6700 1; +#X obj 491 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 6700 1; +#X obj 511 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 6100 1; +#X obj 531 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 0 1; +#X obj 551 394 vsl 15 128 0 1 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 0 1; +#X text 591 561 <- Audio rate control inputs can be audio or control +values; +#X text 14 491 Experimental - use with caution!; +#X msg 54 509 plug sine_faac 6; +#X connect 0 0 49 0; +#X connect 0 0 49 1; +#X connect 3 0 5 0; +#X connect 4 0 3 0; +#X connect 5 0 17 0; +#X connect 6 0 23 0; +#X connect 7 0 16 0; +#X connect 8 0 4 0; +#X connect 9 0 11 1; +#X connect 10 0 9 0; +#X connect 11 0 68 0; +#X connect 12 0 68 0; +#X connect 13 0 11 0; +#X connect 14 0 50 0; +#X connect 15 0 50 0; +#X connect 16 0 12 0; +#X connect 17 0 68 0; +#X connect 19 0 50 0; +#X connect 20 1 50 0; +#X connect 21 0 29 0; +#X connect 22 0 7 0; +#X connect 23 0 8 0; +#X connect 24 0 68 0; +#X connect 28 0 47 0; +#X connect 29 0 12 1; +#X connect 30 0 31 0; +#X connect 31 0 17 1; +#X connect 33 0 32 0; +#X connect 35 0 43 0; +#X connect 42 0 6 0; +#X connect 43 0 47 1; +#X connect 47 0 68 0; +#X connect 50 0 13 0; +#X connect 50 1 13 1; +#X connect 51 0 27 0; +#X connect 52 0 27 0; +#X connect 56 0 68 0; +#X connect 57 0 68 0; +#X connect 58 0 25 0; +#X connect 59 0 25 0; +#X connect 60 0 26 0; +#X connect 61 0 26 0; +#X connect 62 0 27 0; +#X connect 63 0 27 0; +#X connect 64 0 27 0; +#X connect 68 0 55 0; +#X connect 68 1 18 0; +#X connect 68 2 18 0; +#X connect 69 0 68 0; +#X connect 70 0 71 2; +#X connect 71 0 66 0; +#X connect 71 1 41 0; +#X connect 71 2 41 0; +#X connect 71 3 41 0; +#X connect 71 4 41 0; +#X connect 71 5 41 0; +#X connect 71 6 41 0; +#X connect 72 0 71 1; +#X connect 72 1 71 3; +#X connect 72 2 71 5; +#X connect 72 3 71 7; +#X connect 72 4 71 9; +#X connect 72 5 71 11; +#X connect 73 0 74 0; +#X connect 74 0 72 0; +#X connect 75 0 71 4; +#X connect 76 0 71 6; +#X connect 77 0 71 8; +#X connect 78 0 71 10; +#X connect 79 0 71 12; +#X connect 82 0 71 0; diff --git a/pluginhost~/doc/output~.pd b/pluginhost~/doc/output~.pd new file mode 100644 index 0000000..4db0809 --- /dev/null +++ b/pluginhost~/doc/output~.pd @@ -0,0 +1,69 @@ +#N canvas 0 0 757 675 12; +#X obj 516 522 t b; +#X obj 516 469 f; +#X obj 516 547 f; +#X msg 630 546 0; +#X obj 516 499 moses 1; +#X obj 630 518 t b f; +#X obj 596 479 moses 1; +#X obj 29 97 dbtorms; +#X obj 85 170 inlet~; +#X msg 278 300 \; pd dsp 1; +#X obj 29 170 line~; +#X obj 64 242 *~; +#X obj 64 272 dac~; +#X obj 29 127 pack 0 50; +#X text 121 146 audio in; +#X text 301 496 test if less than 1 -->; +#X text 267 523 if true convert to bang -->; +#X text 100 96 <-- convert from dB to linear units; +#X floatatom 278 221 3 0 100 0 dB - -; +#X obj 516 449 bng 15 250 50 0 empty empty mute -38 7 0 12 -262144 +-1 -1; +#X text 118 126 <-- make a ramp to avoid clicks or zipper noise; +#X obj 148 170 inlet~; +#X obj 154 241 *~; +#X text 502 399 MUTE logic:; +#X obj 278 193 r \$0-master-lvl; +#X obj 516 573 s \$0-master-lvl; +#X obj 293 247 s \$0-master-out; +#X obj 29 71 r \$0-master-out; +#X obj 596 450 r \$0-master-out; +#X text 60 10 Level control abstraction \, used in many of the Pd example +patches. The level and mute controls show up on the parent \, calling +patch.; +#X text 229 549 previous nonzero master-lvl -->; +#X text 301 453 recall previous; +#X text 301 471 value of master-lvl -->; +#X text 16 310 automatically start DSP -->; +#X obj 85 192 hip~ 3; +#X obj 147 192 hip~ 3; +#X text 26 608 NOTE: This abstraction was written by Miller Puckette +\, and is include with the PD examples as part of the 'standard' PD +documentation. JB 23/05/05; +#X connect 0 0 2 0; +#X connect 1 0 4 0; +#X connect 2 0 25 0; +#X connect 3 0 25 0; +#X connect 4 0 0 0; +#X connect 4 1 5 0; +#X connect 5 0 3 0; +#X connect 6 1 2 1; +#X connect 7 0 13 0; +#X connect 8 0 34 0; +#X connect 10 0 22 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 13 0 10 0; +#X connect 18 0 9 0; +#X connect 18 0 26 0; +#X connect 19 0 1 0; +#X connect 21 0 35 0; +#X connect 22 0 12 1; +#X connect 24 0 18 0; +#X connect 27 0 7 0; +#X connect 28 0 1 1; +#X connect 28 0 6 0; +#X connect 34 0 11 1; +#X connect 35 0 22 1; +#X coords 0 0 1 1 65 55 1; diff --git a/pluginhost~/gpl.txt b/pluginhost~/gpl.txt new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/pluginhost~/gpl.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/pluginhost~/include/alsa/seq_event.h b/pluginhost~/include/alsa/seq_event.h new file mode 100644 index 0000000..6d59ca4 --- /dev/null +++ b/pluginhost~/include/alsa/seq_event.h @@ -0,0 +1,452 @@ +/** + * \file include/seq_event.h + * \brief Application interface library for the ALSA driver + * \author Jaroslav Kysela + * \author Abramo Bagnara + * \author Takashi Iwai + * \date 1998-2001 + * + * Application interface library for the ALSA driver + */ +/* + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __ALSA_SEQ_EVENT_H +#define __ALSA_SEQ_EVENT_H + +/** + * \defgroup SeqEvents Sequencer Event Definitions + * Sequencer Event Definitions + * \ingroup Sequencer + * \{ + */ + +/** + * Sequencer event data type + */ +typedef unsigned char snd_seq_event_type_t; + +/** Sequencer event type */ +enum snd_seq_event_type { + /** system status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_SYSTEM = 0, + /** returned result status; event data type = #snd_seq_result_t */ + SND_SEQ_EVENT_RESULT, + + /** note on and off with duration; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTE = 5, + /** note on; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEON, + /** note off; event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_NOTEOFF, + /** key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */ + SND_SEQ_EVENT_KEYPRESS, + + /** controller; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROLLER = 10, + /** program change; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_PGMCHANGE, + /** channel pressure; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CHANPRESS, + /** pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */ + SND_SEQ_EVENT_PITCHBEND, + /** 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_CONTROL14, + /** 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_NONREGPARAM, + /** 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_REGPARAM, + + /** SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGPOS = 20, + /** Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_SONGSEL, + /** midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_QFRAME, + /** SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_TIMESIGN, + /** SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */ + SND_SEQ_EVENT_KEYSIGN, + + /** MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_START = 30, + /** MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CONTINUE, + /** MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_STOP, + /** Set tick queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TICK, + /** Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SETPOS_TIME, + /** (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TEMPO, + /** MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_CLOCK, + /** MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_TICK, + /** Queue timer skew; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_QUEUE_SKEW, + /** Sync position changed; event data type = #snd_seq_ev_queue_control_t */ + SND_SEQ_EVENT_SYNC_POS, + + /** Tune request; event data type = none */ + SND_SEQ_EVENT_TUNE_REQUEST = 40, + /** Reset to power-on state; event data type = none */ + SND_SEQ_EVENT_RESET, + /** Active sensing event; event data type = none */ + SND_SEQ_EVENT_SENSING, + + /** Echo-back event; event data type = any type */ + SND_SEQ_EVENT_ECHO = 50, + /** OSS emulation raw event; event data type = any type */ + SND_SEQ_EVENT_OSS, + + /** New client has connected; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_START = 60, + /** Client has left the system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_EXIT, + /** Client status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_CLIENT_CHANGE, + /** New port was created; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_START, + /** Port was deleted from system; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_EXIT, + /** Port status/info has changed; event data type = #snd_seq_addr_t */ + SND_SEQ_EVENT_PORT_CHANGE, + + /** Ports connected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_SUBSCRIBED, + /** Ports disconnected; event data type = #snd_seq_connect_t */ + SND_SEQ_EVENT_PORT_UNSUBSCRIBED, + + /** Sample select; event data type = #snd_seq_ev_sample_control_t */ + SND_SEQ_EVENT_SAMPLE = 70, + /** Sample cluster select; event data type = #snd_seq_ev_sample_control_t */ + SND_SEQ_EVENT_SAMPLE_CLUSTER, + /** voice start */ + SND_SEQ_EVENT_SAMPLE_START, + /** voice stop */ + SND_SEQ_EVENT_SAMPLE_STOP, + /** playback frequency */ + SND_SEQ_EVENT_SAMPLE_FREQ, + /** volume and balance */ + SND_SEQ_EVENT_SAMPLE_VOLUME, + /** sample loop */ + SND_SEQ_EVENT_SAMPLE_LOOP, + /** sample position */ + SND_SEQ_EVENT_SAMPLE_POSITION, + /** private (hardware dependent) event */ + SND_SEQ_EVENT_SAMPLE_PRIVATE1, + + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR0 = 90, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR1, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR2, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR3, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR4, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR5, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR6, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR7, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR8, + /** user-defined event; event data type = any (fixed size) */ + SND_SEQ_EVENT_USR9, + + /** begin of instrument management */ + SND_SEQ_EVENT_INSTR_BEGIN = 100, + /** end of instrument management */ + SND_SEQ_EVENT_INSTR_END, + /** query instrument interface info */ + SND_SEQ_EVENT_INSTR_INFO, + /** result of instrument interface info */ + SND_SEQ_EVENT_INSTR_INFO_RESULT, + /** query instrument format info */ + SND_SEQ_EVENT_INSTR_FINFO, + /** result of instrument format info */ + SND_SEQ_EVENT_INSTR_FINFO_RESULT, + /** reset instrument instrument memory */ + SND_SEQ_EVENT_INSTR_RESET, + /** get instrument interface status */ + SND_SEQ_EVENT_INSTR_STATUS, + /** result of instrument interface status */ + SND_SEQ_EVENT_INSTR_STATUS_RESULT, + /** put an instrument to port */ + SND_SEQ_EVENT_INSTR_PUT, + /** get an instrument from port */ + SND_SEQ_EVENT_INSTR_GET, + /** result of instrument query */ + SND_SEQ_EVENT_INSTR_GET_RESULT, + /** free instrument(s) */ + SND_SEQ_EVENT_INSTR_FREE, + /** get instrument list */ + SND_SEQ_EVENT_INSTR_LIST, + /** result of instrument list */ + SND_SEQ_EVENT_INSTR_LIST_RESULT, + /** set cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER, + /** get cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER_GET, + /** result of cluster parameters */ + SND_SEQ_EVENT_INSTR_CLUSTER_RESULT, + /** instrument change */ + SND_SEQ_EVENT_INSTR_CHANGE, + + /** system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_SYSEX = 130, + /** error event; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_BOUNCE, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR0 = 135, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR1, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR2, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR3, + /** reserved for user apps; event data type = #snd_seq_ev_ext_t */ + SND_SEQ_EVENT_USR_VAR4, + + /** NOP; ignored in any case */ + SND_SEQ_EVENT_NONE = 255 +}; + + +/** Sequencer event address */ +typedef struct snd_seq_addr { + unsigned char client; /**< Client id */ + unsigned char port; /**< Port id */ +} snd_seq_addr_t; + +/** Connection (subscription) between ports */ +typedef struct snd_seq_connect { + snd_seq_addr_t sender; /**< sender address */ + snd_seq_addr_t dest; /**< destination address */ +} snd_seq_connect_t; + + +/** Real-time data record */ +typedef struct snd_seq_real_time { + unsigned int tv_sec; /**< seconds */ + unsigned int tv_nsec; /**< nanoseconds */ +} snd_seq_real_time_t; + +/** (MIDI) Tick-time data record */ +typedef unsigned int snd_seq_tick_time_t; + +/** unioned time stamp */ +typedef union snd_seq_timestamp { + snd_seq_tick_time_t tick; /**< tick-time */ + struct snd_seq_real_time time; /**< real-time */ +} snd_seq_timestamp_t; + + +/** + * Event mode flags + * + * NOTE: only 8 bits available! + */ +#define SND_SEQ_TIME_STAMP_TICK (0<<0) /**< timestamp in clock ticks */ +#define SND_SEQ_TIME_STAMP_REAL (1<<0) /**< timestamp in real time */ +#define SND_SEQ_TIME_STAMP_MASK (1<<0) /**< mask for timestamp bits */ + +#define SND_SEQ_TIME_MODE_ABS (0<<1) /**< absolute timestamp */ +#define SND_SEQ_TIME_MODE_REL (1<<1) /**< relative to current time */ +#define SND_SEQ_TIME_MODE_MASK (1<<1) /**< mask for time mode bits */ + +#define SND_SEQ_EVENT_LENGTH_FIXED (0<<2) /**< fixed event size */ +#define SND_SEQ_EVENT_LENGTH_VARIABLE (1<<2) /**< variable event size */ +#define SND_SEQ_EVENT_LENGTH_VARUSR (2<<2) /**< variable event size - user memory space */ +#define SND_SEQ_EVENT_LENGTH_MASK (3<<2) /**< mask for event length bits */ + +#define SND_SEQ_PRIORITY_NORMAL (0<<4) /**< normal priority */ +#define SND_SEQ_PRIORITY_HIGH (1<<4) /**< event should be processed before others */ +#define SND_SEQ_PRIORITY_MASK (1<<4) /**< mask for priority bits */ + + +/** Note event */ +typedef struct snd_seq_ev_note { + unsigned char channel; /**< channel number */ + unsigned char note; /**< note */ + unsigned char velocity; /**< velocity */ + unsigned char off_velocity; /**< note-off velocity; only for #SND_SEQ_EVENT_NOTE */ + unsigned int duration; /**< duration until note-off; only for #SND_SEQ_EVENT_NOTE */ +} snd_seq_ev_note_t; + +/** Controller event */ +typedef struct snd_seq_ev_ctrl { + unsigned char channel; /**< channel number */ + unsigned char unused[3]; /**< reserved */ + unsigned int param; /**< control parameter */ + signed int value; /**< control value */ +} snd_seq_ev_ctrl_t; + +/** generic set of bytes (12x8 bit) */ +typedef struct snd_seq_ev_raw8 { + unsigned char d[12]; /**< 8 bit value */ +} snd_seq_ev_raw8_t; + +/** generic set of integers (3x32 bit) */ +typedef struct snd_seq_ev_raw32 { + unsigned int d[3]; /**< 32 bit value */ +} snd_seq_ev_raw32_t; + +/** external stored data */ +typedef struct snd_seq_ev_ext { + unsigned int len; /**< length of data */ + void *ptr; /**< pointer to data (note: can be 64-bit) */ +} __attribute__((packed)) snd_seq_ev_ext_t; + +/** Instrument cluster type */ +typedef unsigned int snd_seq_instr_cluster_t; + +/** Instrument type */ +typedef struct snd_seq_instr { + snd_seq_instr_cluster_t cluster; /**< cluster id */ + unsigned int std; /**< instrument standard id; the upper byte means a private instrument (owner - client id) */ + unsigned short bank; /**< instrument bank id */ + unsigned short prg; /**< instrument program id */ +} snd_seq_instr_t; + +/** sample number */ +typedef struct snd_seq_ev_sample { + unsigned int std; /**< sample standard id */ + unsigned short bank; /**< sample bank id */ + unsigned short prg; /**< sample program id */ +} snd_seq_ev_sample_t; + +/** sample cluster */ +typedef struct snd_seq_ev_cluster { + snd_seq_instr_cluster_t cluster; /**< cluster id */ +} snd_seq_ev_cluster_t; + +/** sample position */ +typedef unsigned int snd_seq_position_t; /**< playback position (in samples) * 16 */ + +/** sample stop mode */ +typedef enum snd_seq_stop_mode { + SND_SEQ_SAMPLE_STOP_IMMEDIATELY = 0, /**< terminate playing immediately */ + SND_SEQ_SAMPLE_STOP_VENVELOPE = 1, /**< finish volume envelope */ + SND_SEQ_SAMPLE_STOP_LOOP = 2 /**< terminate loop and finish wave */ +} snd_seq_stop_mode_t; + +/** sample frequency */ +typedef int snd_seq_frequency_t; /**< playback frequency in HZ * 16 */ + +/** sample volume control; if any value is set to -1 == do not change */ +typedef struct snd_seq_ev_volume { + signed short volume; /**< range: 0-16383 */ + signed short lr; /**< left-right balance; range: 0-16383 */ + signed short fr; /**< front-rear balance; range: 0-16383 */ + signed short du; /**< down-up balance; range: 0-16383 */ +} snd_seq_ev_volume_t; + +/** simple loop redefinition */ +typedef struct snd_seq_ev_loop { + unsigned int start; /**< loop start (in samples) * 16 */ + unsigned int end; /**< loop end (in samples) * 16 */ +} snd_seq_ev_loop_t; + +/** Sample control events */ +typedef struct snd_seq_ev_sample_control { + unsigned char channel; /**< channel */ + unsigned char unused[3]; /**< reserved */ + union { + snd_seq_ev_sample_t sample; /**< sample number */ + snd_seq_ev_cluster_t cluster; /**< cluster number */ + snd_seq_position_t position; /**< position */ + snd_seq_stop_mode_t stop_mode; /**< stop mode */ + snd_seq_frequency_t frequency; /**< frequency */ + snd_seq_ev_volume_t volume; /**< volume */ + snd_seq_ev_loop_t loop; /**< loop control */ + unsigned char raw8[8]; /**< raw 8-bit */ + } param; /**< control parameters */ +} snd_seq_ev_sample_control_t; + + + +/** INSTR_BEGIN event */ +typedef struct snd_seq_ev_instr_begin { + int timeout; /**< zero = forever, otherwise timeout in ms */ +} snd_seq_ev_instr_begin_t; + +/** Result events */ +typedef struct snd_seq_result { + int event; /**< processed event type */ + int result; /**< status */ +} snd_seq_result_t; + +/** Queue skew values */ +typedef struct snd_seq_queue_skew { + unsigned int value; /**< skew value */ + unsigned int base; /**< skew base */ +} snd_seq_queue_skew_t; + +/** queue timer control */ +typedef struct snd_seq_ev_queue_control { + unsigned char queue; /**< affected queue */ + unsigned char unused[3]; /**< reserved */ + union { + signed int value; /**< affected value (e.g. tempo) */ + snd_seq_timestamp_t time; /**< time */ + unsigned int position; /**< sync position */ + snd_seq_queue_skew_t skew; /**< queue skew */ + unsigned int d32[2]; /**< any data */ + unsigned char d8[8]; /**< any data */ + } param; /**< data value union */ +} snd_seq_ev_queue_control_t; + + +/** Sequencer event */ +typedef struct snd_seq_event { + snd_seq_event_type_t type; /**< event type */ + unsigned char flags; /**< event flags */ + unsigned char tag; /**< tag */ + + unsigned char queue; /**< schedule queue */ + snd_seq_timestamp_t time; /**< schedule time */ + + snd_seq_addr_t source; /**< source address */ + snd_seq_addr_t dest; /**< destination address */ + + union { + snd_seq_ev_note_t note; /**< note information */ + snd_seq_ev_ctrl_t control; /**< MIDI control information */ + snd_seq_ev_raw8_t raw8; /**< raw8 data */ + snd_seq_ev_raw32_t raw32; /**< raw32 data */ + snd_seq_ev_ext_t ext; /**< external data */ + snd_seq_ev_queue_control_t queue; /**< queue control */ + snd_seq_timestamp_t time; /**< timestamp */ + snd_seq_addr_t addr; /**< address */ + snd_seq_connect_t connect; /**< connect information */ + snd_seq_result_t result; /**< operation result code */ + snd_seq_ev_instr_begin_t instr_begin; /**< instrument */ + snd_seq_ev_sample_control_t sample; /**< sample control */ + } data; /**< event data... */ +} snd_seq_event_t; + + +/** \} */ + +#endif /* __ALSA_SEQ_EVENT_H */ + diff --git a/pluginhost~/include/dssi.h b/pluginhost~/include/dssi.h new file mode 100644 index 0000000..dd0cd91 --- /dev/null +++ b/pluginhost~/include/dssi.h @@ -0,0 +1,426 @@ +/* -*- c-basic-offset: 4 -*- */ + +/* dssi.h + + DSSI version 0.9 + Copyright (c) 2004 Chris Cannam, Steve Harris and Sean Bolton + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +*/ + +#ifndef DSSI_INCLUDED +#define DSSI_INCLUDED + +#include +#include + +#define DSSI_VERSION "0.9" +#define DSSI_VERSION_MAJOR 0 +#define DSSI_VERSION_MINOR 9 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + There is a need for an API that supports hosted MIDI soft synths + with GUIs in Linux audio applications. In time the GMPI initiative + should comprehensively address this need, but the requirement for + Linux applications to be able to support simple hosted synths is + here now, and GMPI is not. This proposal (the "DSSI Soft Synth + Interface" or DSSI, pronounced "dizzy") aims to provide a simple + solution in a way that we hope will prove complete and compelling + enough to support now, yet not so compelling as to supplant GMPI or + any other comprehensive future proposal. + + For simplicity and familiarity, this API is based as far as + possible on existing work -- the LADSPA plugin API for control + values and audio processing, and the ALSA sequencer event types for + MIDI event communication. The GUI part of the proposal is quite + new, but may also be applicable retroactively to LADSPA plugins + that do not otherwise support this synth interface. +*/ + +typedef struct _DSSI_Program_Descriptor { + + /** Bank number for this program. Note that DSSI does not support + MIDI-style separation of bank LSB and MSB values. There is no + restriction on the set of available banks: the numbers do not + need to be contiguous, there does not need to be a bank 0, etc. */ + unsigned long Bank; + + /** Program number (unique within its bank) for this program. + There is no restriction on the set of available programs: the + numbers do not need to be contiguous, there does not need to + be a program 0, etc. */ + unsigned long Program; + + /** Name of the program. */ + const char * Name; + +} DSSI_Program_Descriptor; + + +typedef struct _DSSI_Descriptor { + + /** + * DSSI_API_Version + * + * This member indicates the DSSI API level used by this plugin. + * If we're lucky, this will never be needed. For now all plugins + * must set it to 1. + */ + int DSSI_API_Version; + + /** + * LADSPA_Plugin + * + * A DSSI synth plugin consists of a LADSPA plugin plus an + * additional framework for controlling program settings and + * transmitting MIDI events. A plugin must fully implement the + * LADSPA descriptor fields as well as the required LADSPA + * functions including instantiate() and (de)activate(). It + * should also implement run(), with the same behaviour as if + * run_synth() (below) were called with no synth events. + * + * In order to instantiate a synth the host calls the LADSPA + * instantiate function, passing in this LADSPA_Descriptor + * pointer. The returned LADSPA_Handle is used as the argument + * for the DSSI functions below as well as for the LADSPA ones. + */ + const LADSPA_Descriptor *LADSPA_Plugin; + + /** + * configure() + * + * This member is a function pointer that sends a piece of + * configuration data to the plugin. The key argument specifies + * some aspect of the synth's configuration that is to be changed, + * and the value argument specifies a new value for it. A plugin + * that does not require this facility at all may set this member + * to NULL. + * + * This call is intended to set some session-scoped aspect of a + * plugin's behaviour, for example to tell the plugin to load + * sample data from a particular file. The plugin should act + * immediately on the request. The call should return NULL on + * success, or an error string that may be shown to the user. The + * host will free the returned value after use if it is non-NULL. + * + * Calls to configure() are not automated as timed events. + * Instead, a host should remember the last value associated with + * each key passed to configure() during a given session for a + * given plugin instance, and should call configure() with the + * correct value for each key the next time it instantiates the + * "same" plugin instance, for example on reloading a project in + * which the plugin was used before. Plugins should note that a + * host may typically instantiate a plugin multiple times with the + * same configuration values, and should share data between + * instances where practical. + * + * Calling configure() completely invalidates the program and bank + * information last obtained from the plugin. + * + * Reserved and special key prefixes + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * The DSSI: prefix + * ---------------- + * Configure keys starting with DSSI: are reserved for particular + * purposes documented in the DSSI specification. At the moment, + * there is one such key: DSSI:PROJECT_DIRECTORY. A host may call + * configure() passing this key and a directory path value. This + * indicates to the plugin and its UI that a directory at that + * path exists and may be used for project-local data. Plugins + * may wish to use the project directory as a fallback location + * when looking for other file data, or as a base for relative + * paths in other configuration values. + * + * The GLOBAL: prefix + * ------------------ + * Configure keys starting with GLOBAL: may be used by the plugin + * and its UI for any purpose, but are treated specially by the + * host. When one of these keys is used in a configure OSC call + * from the plugin UI, the host makes the corresponding configure + * call (preserving the GLOBAL: prefix) not only to the target + * plugin but also to all other plugins in the same instance + * group, as well as their UIs. Note that if any instance + * returns non-NULL from configure to indicate error, the host + * may stop there (and the set of plugins on which configure has + * been called will thus depend on the host implementation). + * See also the configure OSC call documentation in RFC.txt. + */ + char *(*configure)(LADSPA_Handle Instance, + const char *Key, + const char *Value); + + #define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:" + #define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:" + #define DSSI_PROJECT_DIRECTORY_KEY \ + DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY" + + /** + * get_program() + * + * This member is a function pointer that provides a description + * of a program (named preset sound) available on this synth. A + * plugin that does not support programs at all should set this + * member to NULL. + * + * The Index argument is an index into the plugin's list of + * programs, not a program number as represented by the Program + * field of the DSSI_Program_Descriptor. (This distinction is + * needed to support synths that use non-contiguous program or + * bank numbers.) + * + * This function returns a DSSI_Program_Descriptor pointer that is + * guaranteed to be valid only until the next call to get_program, + * deactivate, or configure, on the same plugin instance. This + * function must return NULL if passed an Index argument out of + * range, so that the host can use it to query the number of + * programs as well as their properties. + */ + const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance, + unsigned long Index); + + /** + * select_program() + * + * This member is a function pointer that selects a new program + * for this synth. The program change should take effect + * immediately at the start of the next run_synth() call. (This + * means that a host providing the capability of changing programs + * between any two notes on a track must vary the block size so as + * to place the program change at the right place. A host that + * wanted to avoid this would probably just instantiate a plugin + * for each program.) + * + * A plugin that does not support programs at all should set this + * member NULL. Plugins should ignore a select_program() call + * with an invalid bank or program. + * + * A plugin is not required to select any particular default + * program on activate(): it's the host's duty to set a program + * explicitly. The current program is invalidated by any call to + * configure(). + * + * A plugin is permitted to re-write the values of its input + * control ports when select_program is called. The host should + * re-read the input control port values and update its own + * records appropriately. (This is the only circumstance in + * which a DSSI plugin is allowed to modify its own input ports.) + */ + void (*select_program)(LADSPA_Handle Instance, + unsigned long Bank, + unsigned long Program); + + /** + * get_midi_controller_for_port() + * + * This member is a function pointer that returns the MIDI + * controller number or NRPN that should be mapped to the given + * input control port. If the given port should not have any MIDI + * controller mapped to it, the function should return DSSI_NONE. + * The behaviour of this function is undefined if the given port + * number does not correspond to an input control port. A plugin + * that does not want MIDI controllers mapped to ports at all may + * set this member NULL. + * + * Correct values can be got using the macros DSSI_CC(num) and + * DSSI_NRPN(num) as appropriate, and values can be combined using + * bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port + * should respond to CC #23 and NRPN #1069. + * + * The host is responsible for doing proper scaling from MIDI + * controller and NRPN value ranges to port ranges according to + * the plugin's LADSPA port hints. Hosts should not deliver + * through run_synth any MIDI controller events that have already + * been mapped to control port values. + * + * A plugin should not attempt to request mappings from + * controllers 0 or 32 (MIDI Bank Select MSB and LSB). + */ + int (*get_midi_controller_for_port)(LADSPA_Handle Instance, + unsigned long Port); + + /** + * run_synth() + * + * This member is a function pointer that runs a synth for a + * block. This is identical in function to the LADSPA run() + * function, except that it also supplies events to the synth. + * + * A plugin may provide this function, run_multiple_synths() (see + * below), both, or neither (if it is not in fact a synth). A + * plugin that does not provide this function must set this member + * to NULL. Authors of synth plugins are encouraged to provide + * this function if at all possible. + * + * The Events pointer points to a block of EventCount ALSA + * sequencer events, which is used to communicate MIDI and related + * events to the synth. Each event is timestamped relative to the + * start of the block, (mis)using the ALSA "tick time" field as a + * frame count. The host is responsible for ensuring that events + * with differing timestamps are already ordered by time. + * + * See also the notes on activation, port connection etc in + * ladpsa.h, in the context of the LADSPA run() function. + * + * Note Events + * ~~~~~~~~~~~ + * There are two minor requirements aimed at making the plugin + * writer's life as simple as possible: + * + * 1. A host must never send events of type SND_SEQ_EVENT_NOTE. + * Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON + * and NOTE_OFF events. A plugin should discard any one-point + * NOTE events it sees. + * + * 2. A host must not attempt to switch notes off by sending + * zero-velocity NOTE_ON events. It should always send true + * NOTE_OFFs. It is the host's responsibility to remap events in + * cases where an external MIDI source has sent it zero-velocity + * NOTE_ONs. + * + * Bank and Program Events + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Hosts must map MIDI Bank Select MSB and LSB (0 and 32) + * controllers and MIDI Program Change events onto the banks and + * programs specified by the plugin, using the DSSI select_program + * call. No host should ever deliver a program change or bank + * select controller to a plugin via run_synth. + */ + void (*run_synth)(LADSPA_Handle Instance, + unsigned long SampleCount, + snd_seq_event_t *Events, + unsigned long EventCount); + + /** + * run_synth_adding() + * + * This member is a function pointer that runs an instance of a + * synth for a block, adding its outputs to the values already + * present at the output ports. This is provided for symmetry + * with LADSPA run_adding(), and is equally optional. A plugin + * that does not provide it must set this member to NULL. + */ + void (*run_synth_adding)(LADSPA_Handle Instance, + unsigned long SampleCount, + snd_seq_event_t *Events, + unsigned long EventCount); + + /** + * run_multiple_synths() + * + * This member is a function pointer that runs multiple synth + * instances for a block. This is very similar to run_synth(), + * except that Instances, Events, and EventCounts each point to + * arrays that hold the LADSPA handles, event buffers, and + * event counts for each of InstanceCount instances. That is, + * Instances points to an array of InstanceCount pointers to + * DSSI plugin instantiations, Events points to an array of + * pointers to each instantiation's respective event list, and + * EventCounts points to an array containing each instantiation's + * respective event count. + * + * A host using this function must guarantee that ALL active + * instances of the plugin are represented in each call to the + * function -- that is, a host may not call run_multiple_synths() + * for some instances of a given plugin and then call run_synth() + * as well for others. 'All .. instances of the plugin' means + * every instance sharing the same LADSPA label and shared object + * (*.so) file (rather than every instance sharing the same *.so). + * 'Active' means any instance for which activate() has been called + * but deactivate() has not. + * + * A plugin may provide this function, run_synths() (see above), + * both, or neither (if it not in fact a synth). A plugin that + * does not provide this function must set this member to NULL. + * Plugin authors implementing run_multiple_synths are strongly + * encouraged to implement run_synth as well if at all possible, + * to aid simplistic hosts, even where it would be less efficient + * to use it. + */ + void (*run_multiple_synths)(unsigned long InstanceCount, + LADSPA_Handle *Instances, + unsigned long SampleCount, + snd_seq_event_t **Events, + unsigned long *EventCounts); + + /** + * run_multiple_synths_adding() + * + * This member is a function pointer that runs multiple synth + * instances for a block, adding each synth's outputs to the + * values already present at the output ports. This is provided + * for symmetry with both the DSSI run_multiple_synths() and LADSPA + * run_adding() functions, and is equally optional. A plugin + * that does not provide it must set this member to NULL. + */ + void (*run_multiple_synths_adding)(unsigned long InstanceCount, + LADSPA_Handle *Instances, + unsigned long SampleCount, + snd_seq_event_t **Events, + unsigned long *EventCounts); +} DSSI_Descriptor; + +/** + * DSSI supports a plugin discovery method similar to that of LADSPA: + * + * - DSSI hosts may wish to locate DSSI plugin shared object files by + * searching the paths contained in the DSSI_PATH and LADSPA_PATH + * environment variables, if they are present. Both are expected + * to be colon-separated lists of directories to be searched (in + * order), and DSSI_PATH should be searched first if both variables + * are set. + * + * - Each shared object file containing DSSI plugins must include a + * function dssi_descriptor(), with the following function prototype + * and C-style linkage. Hosts may enumerate the plugin types + * available in the shared object file by repeatedly calling + * this function with successive Index values (beginning from 0), + * until a return value of NULL indicates no more plugin types are + * available. Each non-NULL return is the DSSI_Descriptor + * of a distinct plugin type. + */ + +const DSSI_Descriptor *dssi_descriptor(unsigned long Index); + +typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); + +/* + * Macros to specify particular MIDI controllers in return values from + * get_midi_controller_for_port() + */ + +#define DSSI_CC_BITS 0x20000000 +#define DSSI_NRPN_BITS 0x40000000 + +#define DSSI_NONE -1 +#define DSSI_CONTROLLER_IS_SET(n) (DSSI_NONE != (n)) + +#define DSSI_CC(n) (DSSI_CC_BITS | (n)) +#define DSSI_IS_CC(n) (DSSI_CC_BITS & (n)) +#define DSSI_CC_NUMBER(n) ((n) & 0x7f) + +#define DSSI_NRPN(n) (DSSI_NRPN_BITS | ((n) << 7)) +#define DSSI_IS_NRPN(n) (DSSI_NRPN_BITS & (n)) +#define DSSI_NRPN_NUMBER(n) (((n) >> 7) & 0x3fff) + +#ifdef __cplusplus +} +#endif + +#endif /* DSSI_INCLUDED */ diff --git a/pluginhost~/include/ladspa.h b/pluginhost~/include/ladspa.h new file mode 100644 index 0000000..5c30a8a --- /dev/null +++ b/pluginhost~/include/ladspa.h @@ -0,0 +1,603 @@ +/* ladspa.h + + Linux Audio Developer's Simple Plugin API Version 1.1[LGPL]. + Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, + Stefan Westerfeld. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. */ + +#ifndef LADSPA_INCLUDED +#define LADSPA_INCLUDED + +#define LADSPA_VERSION "1.1" +#define LADSPA_VERSION_MAJOR 1 +#define LADSPA_VERSION_MINOR 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ + +/* Overview: + + There is a large number of synthesis packages in use or development + on the Linux platform at this time. This API (`The Linux Audio + Developer's Simple Plugin API') attempts to give programmers the + ability to write simple `plugin' audio processors in C/C++ and link + them dynamically (`plug') into a range of these packages (`hosts'). + It should be possible for any host and any plugin to communicate + completely through this interface. + + This API is deliberately short and simple. To achieve compatibility + with a range of promising Linux sound synthesis packages it + attempts to find the `greatest common divisor' in their logical + behaviour. Having said this, certain limiting decisions are + implicit, notably the use of a fixed type (LADSPA_Data) for all + data transfer and absence of a parameterised `initialisation' + phase. See below for the LADSPA_Data typedef. + + Plugins are expected to distinguish between control and audio + data. Plugins have `ports' that are inputs or outputs for audio or + control data and each plugin is `run' for a `block' corresponding + to a short time interval measured in samples. Audio data is + communicated using arrays of LADSPA_Data, allowing a block of audio + to be processed by the plugin in a single pass. Control data is + communicated using single LADSPA_Data values. Control data has a + single value at the start of a call to the `run()' or `run_adding()' + function, and may be considered to remain this value for its + duration. The plugin may assume that all its input and output ports + have been connected to the relevant data location (see the + `connect_port()' function below) before it is asked to run. + + Plugins will reside in shared object files suitable for dynamic + linking by dlopen() and family. The file will provide a number of + `plugin types' that can be used to instantiate actual plugins + (sometimes known as `plugin instances') that can be connected + together to perform tasks. + + This API contains very limited error-handling. */ + +/*****************************************************************************/ + +/* Fundamental data type passed in and out of plugin. This data type + is used to communicate audio samples and control values. It is + assumed that the plugin will work sensibly given any numeric input + value although it may have a preferred range (see hints below). + + For audio it is generally assumed that 1.0f is the `0dB' reference + amplitude and is a `normal' signal level. */ + +typedef float LADSPA_Data; + +/*****************************************************************************/ + +/* Special Plugin Properties: + + Optional features of the plugin type are encapsulated in the + LADSPA_Properties type. This is assembled by ORing individual + properties together. */ + +typedef int LADSPA_Properties; + +/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a + real-time dependency (e.g. listens to a MIDI device) and so its + output must not be cached or subject to significant latency. */ +#define LADSPA_PROPERTY_REALTIME 0x1 + +/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin + may cease to work correctly if the host elects to use the same data + location for both input and output (see connect_port()). This + should be avoided as enabling this flag makes it impossible for + hosts to use the plugin to process audio `in-place.' */ +#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2 + +/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin + is capable of running not only in a conventional host but also in a + `hard real-time' environment. To qualify for this the plugin must + satisfy all of the following: + + (1) The plugin must not use malloc(), free() or other heap memory + management within its run() or run_adding() functions. All new + memory used in run() must be managed via the stack. These + restrictions only apply to the run() function. + + (2) The plugin will not attempt to make use of any library + functions with the exceptions of functions in the ANSI standard C + and C maths libraries, which the host is expected to provide. + + (3) The plugin will not access files, devices, pipes, sockets, IPC + or any other mechanism that might result in process or thread + blocking. + + (4) The plugin will take an amount of time to execute a run() or + run_adding() call approximately of form (A+B*SampleCount) where A + and B depend on the machine and host in use. This amount of time + may not depend on input signals or plugin state. The host is left + the responsibility to perform timings to estimate upper bounds for + A and B. */ +#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4 + +#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME) +#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN) +#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE) + +/*****************************************************************************/ + +/* Plugin Ports: + + Plugins have `ports' that are inputs or outputs for audio or + data. Ports can communicate arrays of LADSPA_Data (for audio + inputs/outputs) or single LADSPA_Data values (for control + input/outputs). This information is encapsulated in the + LADSPA_PortDescriptor type which is assembled by ORing individual + properties together. + + Note that a port must be an input or an output port but not both + and that a port must be a control or audio port but not both. */ + +typedef int LADSPA_PortDescriptor; + +/* Property LADSPA_PORT_INPUT indicates that the port is an input. */ +#define LADSPA_PORT_INPUT 0x1 + +/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */ +#define LADSPA_PORT_OUTPUT 0x2 + +/* Property LADSPA_PORT_CONTROL indicates that the port is a control + port. */ +#define LADSPA_PORT_CONTROL 0x4 + +/* Property LADSPA_PORT_AUDIO indicates that the port is a audio + port. */ +#define LADSPA_PORT_AUDIO 0x8 + +#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT) +#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT) +#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL) +#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO) + +/*****************************************************************************/ + +/* Plugin Port Range Hints: + + The host may wish to provide a representation of data entering or + leaving a plugin (e.g. to generate a GUI automatically). To make + this more meaningful, the plugin should provide `hints' to the host + describing the usual values taken by the data. + + Note that these are only hints. The host may ignore them and the + plugin must not assume that data supplied to it is meaningful. If + the plugin receives invalid input data it is expected to continue + to run without failure and, where possible, produce a sensible + output (e.g. a high-pass filter given a negative cutoff frequency + might switch to an all-pass mode). + + Hints are meaningful for all input and output ports but hints for + input control ports are expected to be particularly useful. + + More hint information is encapsulated in the + LADSPA_PortRangeHintDescriptor type which is assembled by ORing + individual hint types together. Hints may require further + LowerBound and UpperBound information. + + All the hint information for a particular port is aggregated in the + LADSPA_PortRangeHint structure. */ + +typedef int LADSPA_PortRangeHintDescriptor; + +/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) lower + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of LowerBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_BELOW 0x1 + +/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field + of the LADSPA_PortRangeHint should be considered meaningful. The + value in this field should be considered the (inclusive) upper + bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also + specified then the value of UpperBound should be multiplied by the + sample rate. */ +#define LADSPA_HINT_BOUNDED_ABOVE 0x2 + +/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be + considered a Boolean toggle. Data less than or equal to zero should + be considered `off' or `false,' and data above zero should be + considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in + conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or + LADSPA_HINT_DEFAULT_1. */ +#define LADSPA_HINT_TOGGLED 0x4 + +/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified + should be interpreted as multiples of the sample rate. For + instance, a frequency range from 0Hz to the Nyquist frequency (half + the sample rate) could be requested by this hint in conjunction + with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds + at all must support this hint to retain meaning. */ +#define LADSPA_HINT_SAMPLE_RATE 0x8 + +/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the + user will find it more intuitive to view values using a logarithmic + scale. This is particularly useful for frequencies and gains. */ +#define LADSPA_HINT_LOGARITHMIC 0x10 + +/* Hint LADSPA_HINT_INTEGER indicates that a user interface would + probably wish to provide a stepped control taking only integer + values. Any bounds set should be slightly wider than the actual + integer range required to avoid floating point rounding errors. For + instance, the integer set {0,1,2,3} might be described as [-0.1, + 3.1]. */ +#define LADSPA_HINT_INTEGER 0x20 + +/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal' + value for the port that is sensible as a default. For instance, + this value is suitable for use as an initial value in a user + interface or as a value the host might assign to a control port + when the user has not provided one. Defaults are encoded using a + mask so only one default may be specified for a port. Some of the + hints make use of lower and upper bounds, in which case the + relevant bound or bounds must be available and + LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting + default must be rounded if LADSPA_HINT_INTEGER is present. Default + values were introduced in LADSPA v1.1. */ +#define LADSPA_HINT_DEFAULT_MASK 0x3C0 + +/* This default values indicates that no default is provided. */ +#define LADSPA_HINT_DEFAULT_NONE 0x0 + +/* This default hint indicates that the suggested lower bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MINIMUM 0x40 + +/* This default hint indicates that a low value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 + + log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper + * 0.25). */ +#define LADSPA_HINT_DEFAULT_LOW 0x80 + +/* This default hint indicates that a middle value between the + suggested lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 + + log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper * + 0.5). */ +#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0 + +/* This default hint indicates that a high value between the suggested + lower and upper bounds should be chosen. For ports with + LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 + + log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper + * 0.75). */ +#define LADSPA_HINT_DEFAULT_HIGH 0x100 + +/* This default hint indicates that the suggested upper bound for the + port should be used. */ +#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140 + +/* This default hint indicates that the number 0 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_0 0x200 + +/* This default hint indicates that the number 1 should be used. Note + that this default may be used in conjunction with + LADSPA_HINT_TOGGLED. */ +#define LADSPA_HINT_DEFAULT_1 0x240 + +/* This default hint indicates that the number 100 should be used. */ +#define LADSPA_HINT_DEFAULT_100 0x280 + +/* This default hint indicates that the Hz frequency of `concert A' + should be used. This will be 440 unless the host uses an unusual + tuning convention, in which case it may be within a few Hz. */ +#define LADSPA_HINT_DEFAULT_440 0x2C0 + +#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW) +#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE) +#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED) +#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE) +#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC) +#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER) + +#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK) +#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MINIMUM) +#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_LOW) +#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MIDDLE) +#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_HIGH) +#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_MAXIMUM) +#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_0) +#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_1) +#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_100) +#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ + == LADSPA_HINT_DEFAULT_440) + +typedef struct _LADSPA_PortRangeHint { + + /* Hints about the port. */ + LADSPA_PortRangeHintDescriptor HintDescriptor; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data LowerBound; + + /* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When + LADSPA_HINT_SAMPLE_RATE is also active then this value should be + multiplied by the relevant sample rate. */ + LADSPA_Data UpperBound; + +} LADSPA_PortRangeHint; + +/*****************************************************************************/ + +/* Plugin Handles: + + This plugin handle indicates a particular instance of the plugin + concerned. It is valid to compare this to NULL (0 for C++) but + otherwise the host should not attempt to interpret it. The plugin + may use it to reference internal instance data. */ + +typedef void * LADSPA_Handle; + +/*****************************************************************************/ + +/* Descriptor for a Type of Plugin: + + This structure is used to describe a plugin type. It provides a + number of functions to examine the type, instantiate it, link it to + buffers and workspaces and to run it. */ + +typedef struct _LADSPA_Descriptor { + + /* This numeric identifier indicates the plugin type + uniquely. Plugin programmers may reserve ranges of IDs from a + central body to avoid clashes. Hosts may assume that IDs are + below 0x1000000. */ + unsigned long UniqueID; + + /* This identifier can be used as a unique, case-sensitive + identifier for the plugin type within the plugin file. Plugin + types should be identified by file and label rather than by index + or plugin name, which may be changed in new plugin + versions. Labels must not contain white-space characters. */ + const char * Label; + + /* This indicates a number of properties of the plugin. */ + LADSPA_Properties Properties; + + /* This member points to the null-terminated name of the plugin + (e.g. "Sine Oscillator"). */ + const char * Name; + + /* This member points to the null-terminated string indicating the + maker of the plugin. This can be an empty string but not NULL. */ + const char * Maker; + + /* This member points to the null-terminated string indicating any + copyright applying to the plugin. If no Copyright applies the + string "None" should be used. */ + const char * Copyright; + + /* This indicates the number of ports (input AND output) present on + the plugin. */ + unsigned long PortCount; + + /* This member indicates an array of port descriptors. Valid indices + vary from 0 to PortCount-1. */ + const LADSPA_PortDescriptor * PortDescriptors; + + /* This member indicates an array of null-terminated strings + describing ports (e.g. "Frequency (Hz)"). Valid indices vary from + 0 to PortCount-1. */ + const char * const * PortNames; + + /* This member indicates an array of range hints for each port (see + above). Valid indices vary from 0 to PortCount-1. */ + const LADSPA_PortRangeHint * PortRangeHints; + + /* This may be used by the plugin developer to pass any custom + implementation data into an instantiate call. It must not be used + or interpreted by the host. It is expected that most plugin + writers will not use this facility as LADSPA_Handle should be + used to hold instance data. */ + void * ImplementationData; + + /* This member is a function pointer that instantiates a plugin. A + handle is returned indicating the new plugin instance. The + instantiation function accepts a sample rate as a parameter. The + plugin descriptor from which this instantiate function was found + must also be passed. This function must return NULL if + instantiation fails. + + Note that instance initialisation should generally occur in + activate() rather than here. */ + LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, + unsigned long SampleRate); + + /* This member is a function pointer that connects a port on an + instantiated plugin to a memory location at which a block of data + for the port will be read/written. The data location is expected + to be an array of LADSPA_Data for audio ports or a single + LADSPA_Data value for control ports. Memory issues will be + managed by the host. The plugin must read/write the data at these + locations every time run() or run_adding() is called and the data + present at the time of this connection call should not be + considered meaningful. + + connect_port() may be called more than once for a plugin instance + to allow the host to change the buffers that the plugin is + reading or writing. These calls may be made before or after + activate() or deactivate() calls. + + connect_port() must be called at least once for each port before + run() or run_adding() is called. When working with blocks of + LADSPA_Data the plugin should pay careful attention to the block + size passed to the run function as the block allocated may only + just be large enough to contain the block of samples. + + Plugin writers should be aware that the host may elect to use the + same buffer for more than one port and even use the same buffer + for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). + However, overlapped buffers or use of a single buffer for both + audio and control data may result in unexpected behaviour. */ + void (*connect_port)(LADSPA_Handle Instance, + unsigned long Port, + LADSPA_Data * DataLocation); + + /* This member is a function pointer that initialises a plugin + instance and activates it for use. This is separated from + instantiate() to aid real-time support and so that hosts can + reinitialise a plugin instance by calling deactivate() and then + activate(). In this case the plugin instance must reset all state + information dependent on the history of the plugin instance + except for any data locations provided by connect_port() and any + gain set by set_run_adding_gain(). If there is nothing for + activate() to do then the plugin writer may provide a NULL rather + than an empty function. + + When present, hosts must call this function once before run() (or + run_adding()) is called for the first time. This call should be + made as close to the run() call as possible and indicates to + real-time plugins that they are now live. Plugins should not rely + on a prompt call to run() after activate(). activate() may not be + called again unless deactivate() is called first. Note that + connect_port() may be called before or after a call to + activate(). */ + void (*activate)(LADSPA_Handle Instance); + + /* This method is a function pointer that runs an instance of a + plugin for a block. Two parameters are required: the first is a + handle to the particular instance to be run and the second + indicates the block size (in samples) for which the plugin + instance may run. + + Note that if an activate() function exists then it must be called + before run() or run_adding(). If deactivate() is called for a + plugin instance then the plugin instance may not be reused until + activate() has been called again. + + If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE + then there are various things that the plugin should not do + within the run() or run_adding() functions (see above). */ + void (*run)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that runs an instance of a + plugin for a block. This has identical behaviour to run() except + in the way data is output from the plugin. When run() is used, + values are written directly to the memory areas associated with + the output ports. However when run_adding() is called, values + must be added to the values already present in the memory + areas. Furthermore, output values written must be scaled by the + current gain set by set_run_adding_gain() (see below) before + addition. + + run_adding() is optional. When it is not provided by a plugin, + this function pointer must be set to NULL. When it is provided, + the function set_run_adding_gain() must be provided also. */ + void (*run_adding)(LADSPA_Handle Instance, + unsigned long SampleCount); + + /* This method is a function pointer that sets the output gain for + use when run_adding() is called (see above). If this function is + never called the gain is assumed to default to 1. Gain + information should be retained when activate() or deactivate() + are called. + + This function should be provided by the plugin if and only if the + run_adding() function is provided. When it is absent this + function pointer must be set to NULL. */ + void (*set_run_adding_gain)(LADSPA_Handle Instance, + LADSPA_Data Gain); + + /* This is the counterpart to activate() (see above). If there is + nothing for deactivate() to do then the plugin writer may provide + a NULL rather than an empty function. + + Hosts must deactivate all activated units after they have been + run() (or run_adding()) for the last time. This call should be + made as close to the last run() call as possible and indicates to + real-time plugins that they are no longer live. Plugins should + not rely on prompt deactivation. Note that connect_port() may be + called before or after a call to deactivate(). + + Deactivation is not similar to pausing as the plugin instance + will be reinitialised when activate() is called to reuse it. */ + void (*deactivate)(LADSPA_Handle Instance); + + /* Once an instance of a plugin has been finished with it can be + deleted using the following function. The instance handle passed + ceases to be valid after this call. + + If activate() was called for a plugin instance then a + corresponding call to deactivate() must be made before cleanup() + is called. */ + void (*cleanup)(LADSPA_Handle Instance); + +} LADSPA_Descriptor; + +/**********************************************************************/ + +/* Accessing a Plugin: */ + +/* The exact mechanism by which plugins are loaded is host-dependent, + however all most hosts will need to know is the name of shared + object file containing the plugin types. To allow multiple hosts to + share plugin types, hosts may wish to check for environment + variable LADSPA_PATH. If present, this should contain a + colon-separated path indicating directories that should be searched + (in order) when loading plugin types. + + A plugin programmer must include a function called + "ladspa_descriptor" with the following function prototype within + the shared object file. This function will have C-style linkage (if + you are using C++ this is taken care of by the `extern "C"' clause + at the top of the file). + + A host will find the plugin shared object file by one means or + another, find the ladspa_descriptor() function, call it, and + proceed from there. + + Plugin types are accessed by index (not ID) using values from 0 + upwards. Out of range indexes must result in this function + returning NULL, so the plugin count can be determined by checking + for the least index that results in NULL being returned. */ + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); + +/* Datatype corresponding to the ladspa_descriptor() function. */ +typedef const LADSPA_Descriptor * +(*LADSPA_Descriptor_Function)(unsigned long Index); + +/**********************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* LADSPA_INCLUDED */ + +/* EOF */ diff --git a/pluginhost~/lesser.txt b/pluginhost~/lesser.txt new file mode 100644 index 0000000..8add30a --- /dev/null +++ b/pluginhost~/lesser.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/pluginhost~/makefile b/pluginhost~/makefile new file mode 100755 index 0000000..6a87da9 --- /dev/null +++ b/pluginhost~/makefile @@ -0,0 +1,66 @@ +NAME=dssi~ +CSYM=dssi~ + +LIBDIR=/usr/local/lib +PDDIR=$(LIBDIR)/pd +INSTALLPATH=$(PDDIR)/extra/ +ARCHITECTURE=i386 +DEBUG=0 + +current: pd_linux + + +# ----------------------- Linux ----------------------- + +pd_linux: src/$(NAME).pd_linux + +.SUFFIXES: .pd_linux + +#LINUXCFLAGS = -DPD -O3 -fPIC -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch + +# Debug +LINUXCFLAGS = -ggdb -g -DPD -O0 -fPIC -funroll-loops -fomit-frame-pointer \ + -Wall -W -Wshadow -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch -DDEBUG=$(DEBUG) + +LINUXINCLUDE = -I/usr/include -I./include + +.c.pd_linux: + $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -c src/jsearch.c + $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -c src/jload.c + $(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -c src/dssi~.c + gcc --export-dynamic -shared -o $(NAME).pd_linux dssi~.o jload.o jsearch.o -lc -lm -llo +# strip --strip-unneeded $(NAME).pd_linux + cp $(NAME).pd_linux ~/pd-externals/ + rm -f *.o + +# ----------------------- Mac OSX ----------------------- + +pd_darwin: src/$(NAME).pd_darwin + +.SUFFIXES: .pd_darwin + +DARWINCFLAGS = -DPD -arch $(ARCHITECTURE) -O3 -Wall -W -Wshadow -Wstrict-prototypes \ + -Wno-unused -Wno-parentheses -Wno-switch -L/usr/local/lib/ -DDEBUG=$(DEBUG) + +DARWININCLUDE = -I ./ -I ../src -I/usr/local/include/ -I ./include -I/usr/local/include/dssi/ + +.c.pd_darwin: + $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) -c src/jsearch.c + $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) -c src/jload.c + $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) -c src/dssi~.c + $(CC) -arch $(ARCHITECTURE) -bundle -undefined suppress -flat_namespace -llo -o $(NAME).pd_darwin dssi~.o jload.o jsearch.o + rm -f *.o + +# ----------------------- Generic ----------------------- + +clean: + rm -f *.o *.pd_* so_locations + +install: + cp dssi~.pd_* $(INSTALLPATH) + install -d $(PDDIR)/doc/5.reference/dssi/ + install -m 644 doc/*-help* $(PDDIR)/doc/5.reference/ + install -m 644 doc/output~.pd $(PDDIR)/doc/5.reference/dssi/ diff --git a/pluginhost~/src/dssi~.c b/pluginhost~/src/dssi~.c new file mode 100644 index 0000000..f195637 --- /dev/null +++ b/pluginhost~/src/dssi~.c @@ -0,0 +1,2537 @@ +/* dssi~ - A DSSI host for PD + * + * Copyright (C) 2006 Jamie Bullock and others + * + * This file incorporates code from the following sources: + * + * jack-dssi-host (BSD-style license): Copyright 2004 Chris Cannam, Steve Harris and Sean Bolton. + * + * Hexter (GPL license): Copyright (C) 2004 Sean Bolton and others. + * + * plugin~ (GPL license): Copyright (C) 2000 Jarno Seppänen, remIXed 2005 + * + * + * This program is free software; you can redistribute it and/or + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "dssi~.h" +#include "jutils.h" + +static t_class *dssi_tilde_class; + +/*From dx7_voice_data.c by Sean Bolton */ + +static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/*static void init_MidiEventBuf(snd_seq_event_t *MidiEventBuf){ + int i; + for(i = 0; i < EVENT_BUFSIZE; i++){ + MidiEventBuf[i].*/ + +/* + * encode_7in6 + ** Taken from gui_data.c by Sean Bolton ** + * + * encode a block of 7-bit data, in base64-ish style + */ + static char * +encode_7in6(uint8_t *data, int length) +{ + char *buffer; + int in, reg, above, below, shift, out; + int outchars = (length * 7 + 5) / 6; + unsigned int sum = 0; + + if (!(buffer = (char *)malloc(25 + outchars))) + return NULL; + + out = snprintf(buffer, 12, "%d ", length); + + in = reg = above = below = 0; + while (outchars) { + if (above == 6) { + buffer[out] = base64[reg >> 7]; + reg &= 0x7f; + above = 0; + out++; + outchars--; + } + if (below == 0) { + if (in < length) { + reg |= data[in] & 0x7f; + sum += data[in]; + } + below = 7; + in++; + } + shift = 6 - above; + if (below < shift) shift = below; + reg <<= shift; + above += shift; + below -= shift; + } + + snprintf(buffer + out, 12, " %d", sum); + + return buffer; +} + +/* + * dx7_bulk_dump_checksum + ** Taken from dx7_voice_data.c by Sean Bolton ** + */ + static int +dx7_bulk_dump_checksum(uint8_t *data, int length) +{ + int sum = 0; + int i; + + for (i = 0; i < length; sum -= data[i++]); + return sum & 0x7F; +} + +static DSSI_Descriptor * ladspa_to_dssi( + LADSPA_Descriptor *ladspaDesc){ + DSSI_Descriptor *dssiDesc; + dssiDesc = (DSSI_Descriptor *)calloc(1, sizeof(DSSI_Descriptor)); + ((DSSI_Descriptor *)dssiDesc)->DSSI_API_Version = 1; + ((DSSI_Descriptor *)dssiDesc)->LADSPA_Plugin = + (LADSPA_Descriptor *)ladspaDesc; + return (DSSI_Descriptor *)dssiDesc; +} +/* + static void dssi_tilde_load_plugin(const char *dll_path, void **dll_handle){ + + *dll_handle = dlopen(dll_path, RTLD_NOW | RTLD_LOCAL); + if (*dll_handle){ + post("%s loaded successfully", dll_path); + } + else + post("Failed: %s", dlerror()); + + } + */ +static void dssi_tilde_port_info(t_dssi_tilde *x){ + t_int i; + + for (i = 0; i < (t_int)x->descriptor->LADSPA_Plugin->PortCount; i++) { + + x->port_info[i].type.a_type = A_SYMBOL; + x->port_info[i].data_type.a_type = A_SYMBOL; + x->port_info[i].name.a_type = A_SYMBOL; + x->port_info[i].upper_bound.a_type = A_FLOAT; + x->port_info[i].lower_bound.a_type = A_FLOAT; + x->port_info[i].p_default.a_type = A_FLOAT; + + LADSPA_PortDescriptor pod = + x->descriptor->LADSPA_Plugin->PortDescriptors[i]; +#if DEBUG + post("Port %d: %s", i, x->descriptor->LADSPA_Plugin->PortNames[i]); +#endif + if (LADSPA_IS_PORT_AUDIO(pod)) { + x->port_info[i].data_type.a_w.w_symbol = + gensym("audio"); + if (LADSPA_IS_PORT_INPUT(pod)){ + x->port_info[i].type.a_w.w_symbol = + gensym("in"); + ++x->plugin_ins; + } + else if (LADSPA_IS_PORT_OUTPUT(pod)){ + x->port_info[i].type.a_w.w_symbol = + gensym("out"); + ++x->plugin_outs; + } + } + else if (LADSPA_IS_PORT_CONTROL(pod)) { + x->port_info[i].data_type.a_w.w_symbol = + gensym("control"); + if (LADSPA_IS_PORT_INPUT(pod)){ + x->port_info[i].type.a_w.w_symbol = + gensym("in"); + ++x->plugin_controlIns; + } + else if (LADSPA_IS_PORT_OUTPUT(pod)){ + ++x->plugin_controlOuts; + x->port_info[i].type.a_w.w_symbol = + gensym("out"); + } + } + if (LADSPA_IS_HINT_BOUNDED_BELOW( + x->descriptor->LADSPA_Plugin->PortRangeHints[i].HintDescriptor)) + x->port_info[i].lower_bound.a_w.w_float = + x->descriptor->LADSPA_Plugin-> + PortRangeHints[i].LowerBound; + else + x->port_info[i].lower_bound.a_w.w_float = 0; + + if (LADSPA_IS_HINT_BOUNDED_ABOVE( + x->descriptor->LADSPA_Plugin->PortRangeHints[i].HintDescriptor)) + x->port_info[i].upper_bound.a_w.w_float = + x->descriptor->LADSPA_Plugin-> + PortRangeHints[i].UpperBound; + else + x->port_info[i].lower_bound.a_w.w_float = 1; + + x->port_info[i].p_default.a_w.w_float = (float) + get_port_default(x, i); + + x->port_info[i].name.a_w.w_symbol = + gensym ((char *) + x->descriptor->LADSPA_Plugin->PortNames[i]); + } +#if DEBUG + post("%d inputs, %d outputs, %d control inputs, %d control outs", x->plugin_ins, x->plugin_outs, x->plugin_controlIns, x->plugin_controlOuts); +#endif +} + +static void dssi_tilde_assign_ports(t_dssi_tilde *x){ + int i; + +#if DEBUG + post("%d instances", x->n_instances); +#endif + + x->plugin_ins *= x->n_instances; + x->plugin_outs *= x->n_instances; + x->plugin_controlIns *= x->n_instances; + x->plugin_controlOuts *= x->n_instances; + +#if DEBUG + post("%d plugin outs", x->plugin_outs); +#endif + + x->plugin_InputBuffers = + (float **)malloc(x->plugin_ins * sizeof(float *)); + x->plugin_OutputBuffers = + (float **)malloc(x->plugin_outs * sizeof(float *)); + x->plugin_ControlDataInput = + (float *)calloc(x->plugin_controlIns, sizeof(float)); + x->plugin_ControlDataOutput = + (float *)calloc(x->plugin_controlOuts, sizeof(float)); + for(i = 0; i < x->plugin_ins; i++) + x->plugin_InputBuffers[i] = + (float *)calloc(x->blksize, sizeof(float)); + for(i = 0; i < x->plugin_outs; i++) + x->plugin_OutputBuffers[i] = + (float *)calloc(x->blksize, sizeof(float)); + x->instanceEventBuffers = + (snd_seq_event_t **)malloc(x->n_instances * sizeof(snd_seq_event_t *)); + + x->instanceHandles = (LADSPA_Handle *)malloc(x->n_instances * + sizeof(LADSPA_Handle)); + x->instanceEventCounts = (unsigned long *)malloc(x->n_instances * + sizeof(unsigned long)); + + for(i = 0; i < x->n_instances; i++){ + x->instanceEventBuffers[i] = (snd_seq_event_t *)malloc(EVENT_BUFSIZE * + sizeof(snd_seq_event_t)); + + x->instances[i].plugin_PortControlInNumbers = + (int *)malloc(x->descriptor->LADSPA_Plugin->PortCount * + sizeof(int));/* hmmm... as we don't support instances of differing plugin types, we probably don't need to do this dynamically*/ + } + + x->plugin_ControlInPortNumbers = + (unsigned long *)malloc(sizeof(unsigned long) * x->plugin_controlIns); + +#if DEBUG + post("Buffers assigned!"); +#endif + +} + +static void dssi_tilde_init_instance(t_dssi_tilde *x, t_int instance){ + + x->instances[instance].pluginPrograms = NULL; + x->instances[instance].currentBank = 0; + x->instances[instance].currentProgram = 0; + x->instances[instance].uiTarget = NULL; + x->instances[instance].ui_osc_control_path = NULL; + x->instances[instance].ui_osc_program_path = NULL; + x->instances[instance].ui_osc_show_path = NULL; + x->instances[instance].ui_osc_hide_path = NULL; + x->instances[instance].ui_osc_quit_path = NULL; + x->instances[instance].ui_osc_configure_path = NULL; + x->instances[instance].uiNeedsProgramUpdate = 0; + x->instances[instance].pendingProgramChange = -1; + x->instances[instance].plugin_ProgramCount = 0; + x->instances[instance].pendingBankMSB = -1; + x->instances[instance].pendingBankLSB = -1; + x->instances[instance].ui_hidden = 1; + x->instances[instance].ui_show = 0; + x->instances[instance].gui_pid = 0; +#if DEBUG + post("Instance %d initialized!", instance); +#endif + +} + +static void dssi_tilde_connect_ports(t_dssi_tilde *x, t_int instance){ + + t_int i; + + for(i = 0; i < (t_int)x->descriptor->LADSPA_Plugin->PortCount; i++){ +#if DEBUG + post("PortCount: %d of %d", i, + x->descriptor->LADSPA_Plugin->PortCount); +#endif + LADSPA_PortDescriptor pod = + x->descriptor->LADSPA_Plugin->PortDescriptors[i]; + + x->instances[instance].plugin_PortControlInNumbers[i] = -1; + + if (LADSPA_IS_PORT_AUDIO(pod)) { + if (LADSPA_IS_PORT_INPUT(pod)) { + x->descriptor->LADSPA_Plugin->connect_port + (x->instanceHandles[instance], i, + x->plugin_InputBuffers[x->ports_in++]); + } + else if (LADSPA_IS_PORT_OUTPUT(pod)) { + x->descriptor->LADSPA_Plugin->connect_port + (x->instanceHandles[instance], i, + x->plugin_OutputBuffers[x->ports_out++]); +#if DEBUG + post("Audio Input port %d connected", x->ports_in); + post("Audio Output port %d connected", x->ports_out); +#endif + } + } + else if (LADSPA_IS_PORT_CONTROL(pod)) { + if (LADSPA_IS_PORT_INPUT(pod)) { + x->plugin_ControlInPortNumbers[x->ports_controlIn] = (unsigned long) i; + x->instances[instance].plugin_PortControlInNumbers[i] = x->ports_controlIn; + x->plugin_ControlDataInput[x->ports_controlIn] = + (t_float) get_port_default(x, i); +#if DEBUG + post("default for port %d, controlIn, %d is %.2f",i, + x->ports_controlIn, x->plugin_ControlDataInput[x->ports_controlIn]); +#endif + + x->descriptor->LADSPA_Plugin->connect_port + (x->instanceHandles[instance], i, + &x->plugin_ControlDataInput[x->ports_controlIn++]); + + } else if (LADSPA_IS_PORT_OUTPUT(pod)) { + x->descriptor->LADSPA_Plugin->connect_port + (x->instanceHandles[instance], i, + &x->plugin_ControlDataOutput[x->ports_controlOut++]); + } +#if DEBUG + post("Control Input port %d connected", x->ports_controlIn); + post("Control Output port %d connected", x->ports_controlOut); +#endif + } + } + +#if DEBUG + post("ports connected!"); +#endif + +} + +static void dssi_tilde_activate_plugin(t_dssi_tilde *x, t_int instance){ + + if(x->descriptor->LADSPA_Plugin->activate){ +#if DEBUG + post("trying to activate instance: %d", instance); +#endif + x->descriptor->LADSPA_Plugin->activate(x->instanceHandles[instance]); + } +#if DEBUG + post("plugin activated!"); +#endif +} + +static void dssi_tilde_deactivate_plugin(t_dssi_tilde *x, t_float instance_f){ + + t_int instance = (t_int)instance_f; + if(x->descriptor->LADSPA_Plugin->deactivate) + x->descriptor->LADSPA_Plugin->deactivate(x->instanceHandles[instance]); +#if DEBUG + post("plugin deactivated!"); +#endif +} + +static void osc_error(int num, const char *msg, const char *where) +{ + post("dssi~: osc error %d in path %s: %s\n",num, where, msg); +} + +static void query_programs(t_dssi_tilde *x, t_int instance) { + int i; +#if DEBUG + post("querying programs"); +#endif + /* free old lot */ + if (x->instances[instance].pluginPrograms) { + for (i = 0; i < x->instances[instance].plugin_ProgramCount; i++) + free((void *)x->instances[instance].pluginPrograms[i].Name); + free((char *)x->instances[instance].pluginPrograms); + x->instances[instance].pluginPrograms = NULL; + x->instances[instance].plugin_ProgramCount = 0; + } + + x->instances[instance].pendingBankLSB = -1; + x->instances[instance].pendingBankMSB = -1; + x->instances[instance].pendingProgramChange = -1; + + if (x->descriptor->get_program && + x->descriptor->select_program) { + + /* Count the plugins first */ + /*FIX ?? */ + for (i = 0; x->descriptor-> + get_program(x->instanceHandles[instance], i); ++i); + + if (i > 0) { + x->instances[instance].plugin_ProgramCount = i; + x->instances[instance].pluginPrograms = + (DSSI_Program_Descriptor *)malloc(i * sizeof(DSSI_Program_Descriptor)); + while (i > 0) { + const DSSI_Program_Descriptor *descriptor; + --i; + descriptor = x->descriptor-> + get_program(x->instanceHandles[instance], i); + x->instances[instance].pluginPrograms[i].Bank = + descriptor->Bank; + x->instances[instance].pluginPrograms[i].Program = + descriptor->Program; + x->instances[instance].pluginPrograms[i].Name = + strdup(descriptor->Name); +#if DEBUG + post("program %d is MIDI bank %lu program %lu, named '%s'",i, + x->instances[instance].pluginPrograms[i].Bank, + x->instances[instance].pluginPrograms[i].Program, + x->instances[instance].pluginPrograms[i].Name); +#endif + } + } + /* No - it should be 0 anyway - dssi_init */ + /* else + x->instances[instance].plugin_ProgramCount = 0; + */ } +} + +static LADSPA_Data get_port_default(t_dssi_tilde *x, int port) +{ + LADSPA_Descriptor *plugin = (LADSPA_Descriptor *)x->descriptor->LADSPA_Plugin; + LADSPA_PortRangeHint hint = plugin->PortRangeHints[port]; + float lower = hint.LowerBound * + (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? x->sr : 1.0f); + float upper = hint.UpperBound * + (LADSPA_IS_HINT_SAMPLE_RATE(hint.HintDescriptor) ? x->sr : 1.0f); + + if (!LADSPA_IS_HINT_HAS_DEFAULT(hint.HintDescriptor)) { + if (!LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor) || + !LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) { + /* No hint, its not bounded, wild guess */ + return 0.0f; + } + + if (lower <= 0.0f && upper >= 0.0f) { + /* It spans 0.0, 0.0 is often a good guess */ + return 0.0f; + } + + /* No clues, return minimum */ + return lower; + } + + /* Try all the easy ones */ + + if (LADSPA_IS_HINT_DEFAULT_0(hint.HintDescriptor)) { + return 0.0f; + } else if (LADSPA_IS_HINT_DEFAULT_1(hint.HintDescriptor)) { + return 1.0f; + } else if (LADSPA_IS_HINT_DEFAULT_100(hint.HintDescriptor)) { + return 100.0f; + } else if (LADSPA_IS_HINT_DEFAULT_440(hint.HintDescriptor)) { + return 440.0f; + } + + /* All the others require some bounds */ + + if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) { + if (LADSPA_IS_HINT_DEFAULT_MINIMUM(hint.HintDescriptor)) { + return lower; + } + } + if (LADSPA_IS_HINT_BOUNDED_ABOVE(hint.HintDescriptor)) { + if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(hint.HintDescriptor)) { + return upper; + } + if (LADSPA_IS_HINT_BOUNDED_BELOW(hint.HintDescriptor)) { + if (LADSPA_IS_HINT_DEFAULT_LOW(hint.HintDescriptor)) { + return lower * 0.75f + upper * 0.25f; + } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(hint.HintDescriptor)) { + return lower * 0.5f + upper * 0.5f; + } else if (LADSPA_IS_HINT_DEFAULT_HIGH(hint.HintDescriptor)) { + return lower * 0.25f + upper * 0.75f; + } + } + } + + /* fallback */ + return 0.0f; +} + +static unsigned dssi_tilde_get_parm_number (t_dssi_tilde *x, + const char *str) +/* find out if str points to a parameter number or not and return the + number or zero. The number string has to begin with a '#' character */ +{ + long num = 0; + char* strend = NULL; + + if (str == NULL) { + return 0; + } + if (str[0] != '#') { + return 0; + } + num = strtol (&str[1], &strend, 10); + if (str[1] == 0 || *strend != 0) { + /* invalid string */ + return 0; + } + else if (num >= 1 && num <= (long)x->plugin_controlIns) { + /* string ok and within range */ + return (unsigned)num; + } + else { + /* number out of range */ + return 0; + } +} + +static void dssi_tilde_set_control_input_by_index (t_dssi_tilde *x, + signed ctrl_input_index, + float value, + t_int instance) +{ + long port, portno; + + if (ctrl_input_index >= x->plugin_controlIns) { + post("dssi~: control port number %d is out of range [1, %d]", + ctrl_input_index + 1, x->plugin_controlIns); + return; + } + +#if DEBUG + post("ctrl input number = %d", ctrl_input_index); +#endif + + + port = x->plugin_ControlInPortNumbers[ctrl_input_index]; + + + /* FIX - temporary hack */ + if(x->is_DSSI) + portno = + x->instances[instance].plugin_PortControlInNumbers[ctrl_input_index + 1]; + else + portno = + x->instances[instance].plugin_PortControlInNumbers[ctrl_input_index]; +#if DEBUG + post("Global ctrl input number = %d", ctrl_input_index); + post("Global ctrl input value = %.2f", value); +#endif + + + + + /* set the appropriate control port value */ + x->plugin_ControlDataInput[portno] = value; + + /* Update the UI if there is one */ + if(x->is_DSSI){ + if(x->instances[instance].uiTarget == NULL){ +#if DEBUG + post("dssi~: unable to send to NULL target"); +#endif + return; + } + if(x->instances[instance].ui_osc_control_path == NULL){ +#if DEBUG + post("dssi~: unable to send to NULL control path"); +#endif + return; + } + lo_send(x->instances[instance].uiTarget, + x->instances[instance].ui_osc_control_path, "if", port, value); + } + + +} + +static void dssi_tilde_set_control_input_by_name (t_dssi_tilde *x, + const char* name, + float value, + t_int instance) +{ + unsigned port_index = 0; + unsigned ctrl_input_index = 0; + int found_port = 0; /* boolean */ + + if (name == NULL || strlen (name) == 0) { + post("dssi~: no control port name specified"); + return; + } + + /* compare control name to LADSPA control input ports' names + case-insensitively */ + found_port = 0; + ctrl_input_index = 0; + for (port_index = 0; port_index < x->descriptor->LADSPA_Plugin->PortCount; port_index++) + { + LADSPA_PortDescriptor port_type; + port_type = x->descriptor->LADSPA_Plugin->PortDescriptors[port_index]; + if (LADSPA_IS_PORT_CONTROL (port_type) + && LADSPA_IS_PORT_INPUT (port_type)) + { + const char* port_name = NULL; + unsigned cmp_length = 0; + port_name = x->descriptor->LADSPA_Plugin->PortNames[port_index]; + cmp_length = MIN (strlen (name), strlen (port_name)); + if (cmp_length != 0 + && strncasecmp (name, port_name, cmp_length) == 0) + { + /* found the first port to match */ + found_port = 1; + break; + } + ctrl_input_index++; + } + } + + if (!found_port) + { + post("dssi~: plugin doesn't have a control input port named \"%s\"", + name); + return; + } + + dssi_tilde_set_control_input_by_index (x, ctrl_input_index, value, instance); +} + +static void dssi_tilde_control (t_dssi_tilde *x, + t_symbol* ctrl_name, + t_float ctrl_value, + t_float instance_f) +/* Change the value of a named control port of the plug-in */ +{ + unsigned parm_num = 0; + t_int instance = (t_int)instance_f - 1; + int n_instances = x->n_instances; + + if (instance > x->n_instances || instance < -1){ + post("dssi~: control: invalid instance number %d", instance); + return; + } + +#if DEBUG + post("Received LADSPA control data for instance %d", instance); +#endif + + if (ctrl_name->s_name == NULL || strlen (ctrl_name->s_name) == 0) { + post("dssi~: control messages must have a name and a value"); + return; + } + parm_num = dssi_tilde_get_parm_number (x, ctrl_name->s_name); + if (parm_num) { + if(instance >= 0) + dssi_tilde_set_control_input_by_index (x, parm_num - 1, + ctrl_value, instance); + else if (instance == -1){ + while(n_instances--) + dssi_tilde_set_control_input_by_index (x, parm_num - 1, + ctrl_value, n_instances); + } + } + else { + if(instance >= 0) + dssi_tilde_set_control_input_by_name (x, ctrl_name->s_name, + ctrl_value, instance); + else if (instance == -1){ + while(n_instances--) + dssi_tilde_set_control_input_by_name (x, + ctrl_name->s_name, ctrl_value, n_instances); + } + } +} + +static void dssi_tilde_info (t_dssi_tilde *x){ + unsigned int i, + ctrl_portno, + audio_portno; + t_atom argv[7]; + + ctrl_portno = audio_portno = 0; + + if (x->descriptor == NULL) + return; + + for(i = 0; i < x->descriptor->LADSPA_Plugin->PortCount; i++){ + memcpy(&argv[0], &x->port_info[i].type, + sizeof(t_atom)); + memcpy(&argv[1], &x->port_info[i].data_type, + sizeof(t_atom)); + memcpy(&argv[3], &x->port_info[i].name, + sizeof(t_atom)); + memcpy(&argv[4], &x->port_info[i].lower_bound, + sizeof(t_atom)); + memcpy(&argv[5], &x->port_info[i].upper_bound, + sizeof(t_atom)); + memcpy(&argv[6], &x->port_info[i].p_default, + sizeof(t_atom)); + argv[2].a_type = A_FLOAT; + if(!strcmp(argv[1].a_w.w_symbol->s_name, "control")) + argv[2].a_w.w_float = (t_float)++ctrl_portno; + + else if(!strcmp(argv[1].a_w.w_symbol->s_name, "audio")) + argv[2].a_w.w_float = (t_float)++audio_portno; + + outlet_anything (x->control_outlet, gensym ("port"), 7, argv); + } +} + +static void dssi_tilde_ladspa_description(t_dssi_tilde *x, t_atom *at, + DSSI_Descriptor *psDescriptor){ + at[0].a_w.w_symbol = + gensym ((char*)psDescriptor->LADSPA_Plugin->Name); + outlet_anything (x->control_outlet, gensym ("name"), 1, at); + at[0].a_w.w_symbol = + gensym ((char*)psDescriptor->LADSPA_Plugin->Label); + outlet_anything (x->control_outlet, gensym ("label"), 1, at); + at[0].a_type = A_FLOAT; + at[0].a_w.w_float = psDescriptor->LADSPA_Plugin->UniqueID; + outlet_anything (x->control_outlet, gensym ("id"), 1, at); + at[0].a_type = A_SYMBOL; + at[0].a_w.w_symbol = + gensym ((char*)psDescriptor->LADSPA_Plugin->Maker); + outlet_anything (x->control_outlet, gensym ("maker"), 1, at); +} + +static void dssi_tilde_ladspa_describe(const char * pcFullFilename, + void * pvPluginHandle, + DSSI_Descriptor_Function fDescriptorFunction, + void* user_data, + int is_DSSI) { + + t_dssi_tilde *x = (((void**)user_data)[0]); + t_atom at[1]; + DSSI_Descriptor *psDescriptor; + long lIndex; + + at[0].a_type = A_SYMBOL; + at[0].a_w.w_symbol = gensym ((char*)pcFullFilename); + outlet_anything (x->control_outlet, gensym ("library"), 1, at); + + if(is_DSSI){ +#if DEBUG + post("DSSI plugin found by listinfo"); +#endif + for (lIndex = 0; + (psDescriptor = (DSSI_Descriptor *) + fDescriptorFunction(lIndex)) != NULL; lIndex++) + dssi_tilde_ladspa_description(x, &at[0], psDescriptor); + } + + else if(!is_DSSI) + lIndex = 0; + do{ + psDescriptor = ladspa_to_dssi((LADSPA_Descriptor *)fDescriptorFunction(lIndex++)); + /* psDescriptor = (DSSI_Descriptor *)calloc(1, + sizeof(DSSI_Descriptor)); + ((DSSI_Descriptor *)psDescriptor)->DSSI_API_Version = 1; + ((DSSI_Descriptor *)psDescriptor)->LADSPA_Plugin = + (LADSPA_Descriptor *) + fDescriptorFunction(lIndex++); + */ + if(psDescriptor->LADSPA_Plugin != NULL){ + dssi_tilde_ladspa_description(x, &at[0], psDescriptor); + free((DSSI_Descriptor *)psDescriptor); + } + else + break; + } while(1); + /* Not needed + dlclose(pvPluginHandle); + */ +} + +static void dssi_tilde_list_plugins (t_dssi_tilde *x) { + void* user_data[1]; + user_data[0] = x; + LADSPAPluginSearch(dssi_tilde_ladspa_describe,(void*)user_data); +} + +static int osc_debug_handler(const char *path, const char *types, lo_arg **argv, + int argc, void *data, t_dssi_tilde *x) +{ + int i; + printf("got unhandled OSC message:\npath: <%s>\n", path); + for (i=0; iinstances[instance].currentProgram; + + argv[0].a_w.w_float = (t_float)instance; + argv[1].a_w.w_float = x->instances[instance].pluginPrograms[i].Program; + argv[2].a_w.w_symbol = + gensym ((char*)x->instances[instance].pluginPrograms[i].Name); + outlet_anything (x->control_outlet, gensym ("program"), 3, argv); + +} + +static void dssi_tilde_program_change(t_dssi_tilde *x, int instance){ + /* jack-dssi-host queues program changes by using pending program change variables. In the audio callback, if a program change is received via MIDI it over writes the pending value (if any) set by the GUI. If unset, or processed the value will default back to -1. The following call to select_program is then made. I don't think it eventually needs to be done this way - i.e. do we need 'pending'? */ +#if DEBUG + post("executing program change"); +#endif + if (x->instances[instance].pendingProgramChange >= 0){ + if (x->instances[instance].pendingBankLSB >= 0) { + if (x->instances[instance].pendingBankMSB >= 0) { + x->instances[instance].currentBank = x->instances[instance].pendingBankLSB + 128 * x->instances[instance].pendingBankMSB; + } + else { + x->instances[instance].currentBank = x->instances[instance].pendingBankLSB + + 128 * (x->instances[instance].currentBank / 128); + } + } + else if (x->instances[instance].pendingBankMSB >= 0) { + x->instances[instance].currentBank = (x->instances[instance].currentBank % 128) + 128 * x->instances[instance].pendingBankMSB; + } + + x->instances[instance].currentProgram = x->instances[instance].pendingProgramChange; + + if (x->descriptor->select_program) { + x->descriptor->select_program(x->instanceHandles[instance], + x->instances[instance].currentBank, x->instances[instance].currentProgram); + } + if (x->instances[instance].uiNeedsProgramUpdate){ +#if DEBUG + post("Updating GUI program"); +#endif + /* FIX - this is a hack to make text ui work*/ + if(x->instances[instance].uiTarget) + lo_send(x->instances[instance].uiTarget, + x->instances[instance].ui_osc_program_path, "ii", + x->instances[instance].currentBank, + x->instances[instance].currentProgram); + + } + x->instances[instance].uiNeedsProgramUpdate = 0; + x->instances[instance].pendingProgramChange = -1; + x->instances[instance].pendingBankMSB = -1; + x->instances[instance].pendingBankLSB = -1; + } + dssi_tilde_get_current_program(x, instance); +} + +static int osc_program_handler(t_dssi_tilde *x, lo_arg **argv, int instance) +{ + unsigned long bank = argv[0]->i; + unsigned long program = argv[1]->i; + int i; + int found = 0; + +#if DEBUG + post("osc_program_hander active!"); + + post("%d programs", x->instances[instance].plugin_ProgramCount); + +#endif + for (i = 0; i < x->instances[instance].plugin_ProgramCount; ++i) { + if (x->instances[instance].pluginPrograms[i].Bank == bank && + x->instances[instance].pluginPrograms[i].Program == program) { + post("dssi~: OSC: setting bank %u, program %u, name %s\n", + bank, program, x->instances[instance].pluginPrograms[i].Name); + + found = 1; + break; + } + } + + if (!found) { + printf(": OSC: UI requested unknown program: bank %d, program %u: sending to plugin anyway (plugin should ignore it)\n", (int)bank,(int)program); + } + + x->instances[instance].pendingBankMSB = bank / 128; + x->instances[instance].pendingBankLSB = bank % 128; + x->instances[instance].pendingProgramChange = program; +#if DEBUG + post("bank = %d, program = %d, BankMSB = %d BankLSB = %d", bank, program, x->instances[instance].pendingBankMSB, x->instances[instance].pendingBankLSB); +#endif + dssi_tilde_program_change(x, instance); + + return 0; +} + +static int osc_control_handler(t_dssi_tilde *x, lo_arg **argv, int instance) +{ + int port = argv[0]->i; + LADSPA_Data value = argv[1]->f; + + x->plugin_ControlDataInput[x->instances[instance].plugin_PortControlInNumbers[port]] = value; +#if DEBUG + post("OSC: port %d = %f", port, value); +#endif + + return 0; +} + +static int osc_midi_handler(t_dssi_tilde *x, lo_arg **argv, t_int instance) +{ + + int ev_type = 0, chan = 0; +#if DEBUG + post("OSC: got midi request for" + "(%02x %02x %02x %02x)", + argv[0]->m[0], argv[0]->m[1], argv[0]->m[2], argv[0]->m[3]); +#endif + chan = instance; +#if DEBUG + post("channel: %d", chan); +#endif + + if(argv[0]->m[1] <= 239){ + if(argv[0]->m[1] >= 224) + ev_type = SND_SEQ_EVENT_PITCHBEND; + else if(argv[0]->m[1] >= 208) + ev_type = SND_SEQ_EVENT_CHANPRESS; + else if(argv[0]->m[1] >= 192) + ev_type = SND_SEQ_EVENT_PGMCHANGE; + else if(argv[0]->m[1] >= 176) + ev_type = SND_SEQ_EVENT_CONTROLLER; + else if(argv[0]->m[1] >= 160) + ev_type = SND_SEQ_EVENT_KEYPRESS; + else if(argv[0]->m[1] >= 144) + ev_type = SND_SEQ_EVENT_NOTEON; + else if(argv[0]->m[1] >= 128) + ev_type = SND_SEQ_EVENT_NOTEOFF; + } + if(ev_type != 0) + MIDIbuf(ev_type, chan, argv[0]->m[2], argv[0]->m[3], x); + + return 0; +} + +static int osc_configure_handler(t_dssi_tilde *x, lo_arg **argv, int instance) +{ + const char *key = (const char *)&argv[0]->s; + const char *value = (const char *)&argv[1]->s; + char *message; + +#if DEBUG + post("osc_configure_handler active!"); +#endif + + if (x->descriptor->configure) { + + if (!strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, + strlen(DSSI_RESERVED_CONFIGURE_PREFIX))) { + fprintf(stderr, ": OSC: UI for plugin '' attempted to use reserved configure key \"%s\", ignoring\n", key); + return 0; + } + + message = x->descriptor->configure(x->instanceHandles[instance], key, value); + if (message) { + printf(": on configure '%s', plugin '' returned error '%s'\n", + key, message); + free(message); + } + + query_programs(x, instance); + + } + + return 0; +} + +static int osc_exiting_handler(t_dssi_tilde *x, lo_arg **argv, int instance){ + +#if DEBUG + post("exiting handler called: Freeing ui_osc"); +#endif + if(x->instances[instance].uiTarget){ + lo_address_free(x->instances[instance].uiTarget); + x->instances[instance].uiTarget = NULL; + } + free(x->instances[instance].ui_osc_control_path); + free(x->instances[instance].ui_osc_configure_path); + free(x->instances[instance].ui_osc_hide_path); + free(x->instances[instance].ui_osc_program_path); + free(x->instances[instance].ui_osc_show_path); + free(x->instances[instance].ui_osc_quit_path); + x->instances[instance].uiTarget = NULL; + x->instances[instance].ui_osc_control_path = NULL; + x->instances[instance].ui_osc_configure_path = NULL; + x->instances[instance].ui_osc_hide_path = NULL; + x->instances[instance].ui_osc_program_path = NULL; + x->instances[instance].ui_osc_show_path = NULL; + x->instances[instance].ui_osc_quit_path = NULL; + + x->instances[instance].ui_hidden = 1; + + return 0; +} + +static int osc_update_handler(t_dssi_tilde *x, lo_arg **argv, int instance) +{ + const char *url = (char *)&argv[0]->s; + const char *path; + t_int i; + char *host, *port; + t_dssi_configure_pair *p; + + p = x->configure_buffer_head; + +#if DEBUG + post("OSC: got update request from <%s>, instance %d", url, instance); +#endif + + if (x->instances[instance].uiTarget) + lo_address_free(x->instances[instance].uiTarget); + host = lo_url_get_hostname(url); + port = lo_url_get_port(url); + x->instances[instance].uiTarget = lo_address_new(host, port); + free(host); + free(port); + + path = lo_url_get_path(url); + + if (x->instances[instance].ui_osc_control_path) + free(x->instances[instance].ui_osc_control_path); + x->instances[instance].ui_osc_control_path = + (char *)malloc(strlen(path) + 10); + sprintf(x->instances[instance].ui_osc_control_path, "%s/control", path); + + if (x->instances[instance].ui_osc_configure_path) + free(x->instances[instance].ui_osc_configure_path); + x->instances[instance].ui_osc_configure_path = + (char *)malloc(strlen(path) + 12); + sprintf(x->instances[instance].ui_osc_configure_path, "%s/configure", path); + + if (x->instances[instance].ui_osc_program_path) + free(x->instances[instance].ui_osc_program_path); + x->instances[instance].ui_osc_program_path = + (char *)malloc(strlen(path) + 10); + sprintf(x->instances[instance].ui_osc_program_path, "%s/program", path); + + if (x->instances[instance].ui_osc_quit_path) + free(x->instances[instance].ui_osc_quit_path); + x->instances[instance].ui_osc_quit_path = (char *)malloc(strlen(path) + 10); + sprintf(x->instances[instance].ui_osc_quit_path, "%s/quit", path); + + if (x->instances[instance].ui_osc_show_path) + free(x->instances[instance].ui_osc_show_path); + x->instances[instance].ui_osc_show_path = (char *)malloc(strlen(path) + 10); + sprintf(x->instances[instance].ui_osc_show_path, "%s/show", path); + + if (x->instances[instance].ui_osc_hide_path) + free(x->instances[instance].ui_osc_hide_path); + x->instances[instance].ui_osc_hide_path = (char *)malloc(strlen(path) + 10); + sprintf(x->instances[instance].ui_osc_hide_path, "%s/hide", path); + + free((char *)path); + + while(p){ + if(p->instance == instance) + dssi_tilde_send_configure(x, p->key, + p->value, instance); + p = p->next; + } + + /* Send current bank/program (-FIX- another race...) */ + if (x->instances[instance].pendingProgramChange >= 0) + dssi_tilde_program_change(x, instance); +#if DEBUG + post("pendingProgramChange = %d", x->instances[instance].pendingProgramChange); +#endif + if (x->instances[instance].pendingProgramChange < 0) { + unsigned long bank = x->instances[instance].currentBank; + unsigned long program = x->instances[instance].currentProgram; + x->instances[instance].uiNeedsProgramUpdate = 0; + if (x->instances[instance].uiTarget) { + lo_send(x->instances[instance].uiTarget, + x->instances[instance].ui_osc_program_path, + "ii", bank, program); + } + } + + /* Send control ports */ + for (i = 0; i < x->plugin_controlIns; i++) { + lo_send(x->instances[instance].uiTarget, x->instances[instance].ui_osc_control_path, "if", + x->plugin_ControlInPortNumbers[i], x->plugin_ControlDataInput[i]); +#if DEBUG + post("Port: %d, Default value: %.2f", x->plugin_ControlInPortNumbers[i], x->plugin_ControlDataInput[i]); +#endif + } + + /* Send 'show' */ + if (x->instances[instance].ui_show) { + lo_send(x->instances[instance].uiTarget, x->instances[instance].ui_osc_show_path, ""); + x->instances[instance].ui_hidden = 0; + x->instances[instance].ui_show = 0; + } + + return 0; +} + +static void dssi_tilde_osc_setup(t_dssi_tilde *x, int instance){ + + if(instance == 0){ + x->osc_thread = lo_server_thread_new(NULL, osc_error); + char *osc_url_tmp; + osc_url_tmp = lo_server_thread_get_url(x->osc_thread); +#if DEBUG + post("string length of osc_url_tmp:%d", strlen(osc_url_tmp)); +#endif + x->osc_url_base = (char *)malloc(sizeof(char) + * (strlen(osc_url_tmp) + strlen("dssi") + 1)); + sprintf(x->osc_url_base, "%s%s", osc_url_tmp, "dssi"); + free(osc_url_tmp); + lo_server_thread_add_method(x->osc_thread, NULL, NULL, + osc_message_handler, x); + lo_server_thread_start(x->osc_thread); + } + x->instances[instance].osc_url_path = (char *)malloc(sizeof(char) * + (strlen(x->plugin_basename) + strlen(x->descriptor->LADSPA_Plugin->Label) + strlen("chan00") + 3)); + sprintf(x->instances[instance].osc_url_path, "%s/%s/chan%02d", x->plugin_basename, + x->descriptor->LADSPA_Plugin->Label, instance); +#if DEBUG + post("OSC Path is: %s", x->instances[instance].osc_url_path); + post("OSC thread started: %s", x->osc_url_base); +#endif +} + +static void dssi_tilde_init_programs(t_dssi_tilde *x, int instance){ + +#if DEBUG + post("Setting up program data"); +#endif + query_programs(x, instance); + if (x->descriptor->select_program && + x->instances[instance].plugin_ProgramCount > 0) { + + /* select program at index 0 */ + unsigned long bank = + x->instances[instance].pluginPrograms[0].Bank; + x->instances[instance].pendingBankMSB = bank / 128; + x->instances[instance].pendingBankLSB = bank % 128; + x->instances[instance].pendingProgramChange = + x->instances[instance].pluginPrograms[0].Program; + x->instances[instance].uiNeedsProgramUpdate = 1; + } +} + +static void dssi_tilde_load_gui(t_dssi_tilde *x, int instance){ + t_int err = 0; + char *osc_url; + char *gui_path; + struct dirent *dir_entry = NULL; + char *gui_base; + size_t baselen; + DIR *dp; + char *gui_str; + + gui_base = (char *)malloc((baselen = sizeof(char) * (strlen(x->plugin_full_path) - strlen(".so"))) + 1); + + strncpy(gui_base, x->plugin_full_path, baselen); + gui_base[baselen] = '\0'; + + /* don't use strndup - GNU only */ + /* gui_base = strndup(x->plugin_full_path, baselen);*/ +#if DEBUG + post("gui_base: %s", gui_base); +#endif + + gui_str = (char *)malloc(sizeof(char) * (strlen("channel 00") + 1)); + sprintf (gui_str,"channel %02d", instance); + +#if DEBUG + post("GUI name string, %s", gui_str); +#endif + + if(!(dp = opendir(gui_base))){ + post("dssi~: unable to find GUI in %s, continuing without...", gui_base); + return; + } + else { + while((dir_entry = readdir(dp))){ + if (dir_entry->d_name[0] == '.') continue; + if (strchr(dir_entry->d_name, '_')){ + if (strstr(dir_entry->d_name, "gtk") || + strstr(dir_entry->d_name, "qt") || + strstr(dir_entry->d_name, "text")) + break; + } + } +#if DEBUG + post("GUI filename: %s", dir_entry->d_name); +#endif + } + + gui_path = (char *)malloc(sizeof(char) * (strlen(gui_base) + strlen("/") + + strlen(dir_entry->d_name) + 1)); + + sprintf(gui_path, "%s/%s", gui_base, dir_entry->d_name); + + free(gui_base); +#if DEBUG + post("gui_path: %s", gui_path); +#endif + + osc_url = (char *)malloc + (sizeof(char) * (strlen(x->osc_url_base) + + strlen(x->instances[instance].osc_url_path) + 2)); + + /* char osc_url[1024];*/ + sprintf(osc_url, "%s/%s", x->osc_url_base, + x->instances[instance].osc_url_path); + post("dssi~: instance %d URL: %s",instance, osc_url); +#if DEBUG + post("Trying to open GUI!"); +#endif + + x->instances[instance].gui_pid = fork(); + if (x->instances[instance].gui_pid == 0){ + //pthread_mutex_init(&x->midiEventBufferMutex, NULL); + err = execlp(gui_path, gui_path, osc_url, dir_entry->d_name, + x->descriptor->LADSPA_Plugin->Label, gui_str, NULL); + perror("exec failed"); + exit(1); /* terminates the process */ + } + +#if DEBUG + post("errorcode = %d", err); +#endif + + free(gui_path); + free(osc_url); + free(gui_str); + if(dp){ + +#if DEBUG + post("directory handle closed = %d", closedir(dp)); +#endif + } +} + +static void MIDIbuf(int type, int chan, int param, int val, t_dssi_tilde *x){ + + if(chan > x->n_instances - 1 || chan < 0){ + post("dssi~: note discarded: MIDI data is destined for a channel that doesn't exist"); + return; + } + + t_int time_ref = x->time_ref; + t_int mapped; + + pthread_mutex_lock(&x->midiEventBufferMutex); + + mapped = x->channelMap[chan + 1] - 1; + + x->midiEventBuf[x->bufWriteIndex].time.time.tv_sec = + (t_int)(clock_gettimesince(time_ref) * .001); + x->midiEventBuf[x->bufWriteIndex].time.time.tv_nsec = + (t_int)(clock_gettimesince(time_ref) * 1000); /*actually usec - we can't store this in nsec! */ + + if ((type == SND_SEQ_EVENT_NOTEON && val != 0) || + type != SND_SEQ_EVENT_NOTEON) { + x->midiEventBuf[x->bufWriteIndex].type = type; + switch (type) { + case SND_SEQ_EVENT_NOTEON: + x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; + x->midiEventBuf[x->bufWriteIndex].data.note.note = param; + x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; + break; + case SND_SEQ_EVENT_NOTEOFF: + x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; + x->midiEventBuf[x->bufWriteIndex].data.note.note = param; + x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; + break; + case SND_SEQ_EVENT_CONTROLLER: + x->midiEventBuf[x->bufWriteIndex].data.control.channel = mapped; + x->midiEventBuf[x->bufWriteIndex].data.control.param = param; + x->midiEventBuf[x->bufWriteIndex].data.control.value = val; + break; + case SND_SEQ_EVENT_PITCHBEND: + x->midiEventBuf[x->bufWriteIndex].data.control.channel = mapped; + x->midiEventBuf[x->bufWriteIndex].data.control.param = 0; + x->midiEventBuf[x->bufWriteIndex].data.control.value = val; + break; + case SND_SEQ_EVENT_CHANPRESS: + x->midiEventBuf[x->bufWriteIndex].data.control.channel = mapped; + x->midiEventBuf[x->bufWriteIndex].data.control.param = 0; + x->midiEventBuf[x->bufWriteIndex].data.control.value = val; + break; + case SND_SEQ_EVENT_KEYPRESS: + x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; + x->midiEventBuf[x->bufWriteIndex].data.note.note = param; + x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; + break; + case SND_SEQ_EVENT_PGMCHANGE: + x->instances[mapped].pendingBankMSB = (param - 1) / 128; + x->instances[mapped].pendingBankLSB = (param - 1) % 128; + x->instances[mapped].pendingProgramChange = val; + x->instances[mapped].uiNeedsProgramUpdate = 1; +#if DEBUG + post("pgm chabge received in buffer: MSB: %d, LSB %d, prog: %d", + x->instances[mapped].pendingBankMSB, x->instances[mapped].pendingBankLSB, val); +#endif + dssi_tilde_program_change(x, mapped); + break; + } + } + else if (type == SND_SEQ_EVENT_NOTEON && val == 0) { + x->midiEventBuf[x->bufWriteIndex].type = SND_SEQ_EVENT_NOTEOFF; + x->midiEventBuf[x->bufWriteIndex].data.note.channel = mapped; + x->midiEventBuf[x->bufWriteIndex].data.note.note = param; + x->midiEventBuf[x->bufWriteIndex].data.note.velocity = val; + } + +#if DEBUG + post("MIDI received in buffer: chan %d, param %d, val %d, mapped to %d", + chan, param, val, mapped); +#endif + x->bufWriteIndex = (x->bufWriteIndex + 1) % EVENT_BUFSIZE; + pthread_mutex_unlock(&x->midiEventBufferMutex); /**release mutex*/ +} + +static void dssi_tilde_list(t_dssi_tilde *x, t_symbol *s, int argc, t_atom *argv) { + char *msg_type; + int ev_type = 0; + msg_type = (char *)malloc(TYPE_STRING_SIZE); + atom_string(argv, msg_type, TYPE_STRING_SIZE); + int chan = (int)atom_getfloatarg(1, argc, argv) - 1; + int param = (int)atom_getfloatarg(2, argc, argv); + int val = (int)atom_getfloatarg(3, argc, argv); + int n_instances = x->n_instances; + + switch (msg_type[0]){ + case ASCII_n: ev_type = SND_SEQ_EVENT_NOTEON; + break; + case ASCII_c: ev_type = SND_SEQ_EVENT_CONTROLLER; + break; + case ASCII_p: ev_type = SND_SEQ_EVENT_PGMCHANGE; + break; + case ASCII_b: ev_type = SND_SEQ_EVENT_PITCHBEND; + break; + case ASCII_t: ev_type = SND_SEQ_EVENT_CHANPRESS; + break; + case ASCII_a: ev_type = SND_SEQ_EVENT_KEYPRESS; + break; + } +#if DEBUG + post("initial midi NOTE:, arg1 = %d, arg2 = %d, arg3 = %d, arg4 = %d",ev_type,chan,param,val); +#endif + if(ev_type != 0){ + if(chan >= 0) + MIDIbuf(ev_type, chan, param, val, x); + else { + while(n_instances--) + MIDIbuf(ev_type, n_instances, param, val, x); + } + } + free(msg_type); +} + +static char *dssi_tilde_send_configure(t_dssi_tilde *x, char *key, + char *value, t_int instance){ + + char *debug; + + debug = x->descriptor->configure( + x->instanceHandles[instance], + key, value); + if(x->instances[instance].uiTarget != NULL && x->is_DSSI) + lo_send(x->instances[instance].uiTarget, + x->instances[instance].ui_osc_configure_path, + "ss", key, value); + query_programs(x, instance); + + return debug; +} + +static void dssi_show(t_dssi_tilde *x, t_int instance, t_int toggle){ + + if(x->instances[instance].uiTarget){ + if (x->instances[instance].ui_hidden && toggle) { + lo_send(x->instances[instance].uiTarget, + x->instances[instance].ui_osc_show_path, ""); + x->instances[instance].ui_hidden = 0; + } + else if (!x->instances[instance].ui_hidden && !toggle) { + lo_send(x->instances[instance].uiTarget, + x->instances[instance].ui_osc_hide_path, ""); + x->instances[instance].ui_hidden = 1; + } + } + else if(toggle){ + x->instances[instance].ui_show = 1; + dssi_tilde_load_gui(x, instance); + + } +} + +static t_int dssi_tilde_configure_buffer(t_dssi_tilde *x, char *key, + char *value, t_int instance){ + + /*#ifdef BLAH*/ + t_dssi_configure_pair *current, *p; + t_int add_node; + add_node = 0; + current = x->configure_buffer_head; + + while(current){ + if(!strcmp(current->key, key) && + current->instance == instance) + break; + current = current->next; + } + if(current) + free(current->value); + else { + current = (t_dssi_configure_pair *)malloc(sizeof + (t_dssi_configure_pair)); + current->next = x->configure_buffer_head; + x->configure_buffer_head = current; + current->key = strdup(key); + current->instance = instance; + } + current->value = strdup(value); + + p = x->configure_buffer_head; + + /*FIX: eventually give ability to query this buffer (to outlet?) */ +#if DEBUG + while(p){ + post("key: %s", p->key); + post("val: %s", p->value); + post("instance: %d", p->instance); + p = p->next; + } +#endif + return 0; +} + +static t_int dssi_tilde_configure_buffer_free(t_dssi_tilde *x){ + t_dssi_configure_pair *curr, *prev; + prev = curr = NULL; + + for(curr = x->configure_buffer_head; curr != NULL; curr = curr->next){ + if(prev != NULL) + free(prev); + free(curr->key); + free(curr->value); + prev = curr; + } + free(curr); + + return 0; +} + +/* + static void dssi_tilde_plug (t_dssi_tilde *x, t_symbol* plug_name) { + plugin_tilde_ladspa_close_plugin(x); + x->plugin_library_filename = NULL; + x->plugin_library_filename = plugin_tilde_search_plugin_by_label (x, plug_name->s_name); + if (x->plugin_library_filename == NULL) + post("plugin~: plugin not found in any library"); + if (plugin_tilde_open_plugin (x, plug_name->s_name, x->plugin_library_filename,(unsigned long)sys_getsr ())) + post("plugin~: Unable to open plugin"); + } + */ + +static t_int dssi_tilde_reset(t_dssi_tilde *x, t_float instance_f){ + + t_int instance = (t_int)instance_f - 1; + if (instance == -1){ + for(instance = 0; instance < x->n_instances; instance++) { + if (x->descriptor->LADSPA_Plugin->deactivate && + x->descriptor->LADSPA_Plugin->activate){ + x->descriptor->LADSPA_Plugin->deactivate + (x->instanceHandles[instance]); + x->descriptor->LADSPA_Plugin->activate + (x->instanceHandles[instance]); + } + } + } + else if (x->descriptor->LADSPA_Plugin->deactivate && + x->descriptor->LADSPA_Plugin->activate) { + x->descriptor->LADSPA_Plugin->deactivate + (x->instanceHandles[instance]); + x->descriptor->LADSPA_Plugin->activate + (x->instanceHandles[instance]); + } + return 0; +} + +static void dssi_tilde_search_plugin_callback ( + const char* full_filename, + void* plugin_handle, + DSSI_Descriptor_Function descriptor_function, + void* user_data, + int is_DSSI) +{ + DSSI_Descriptor* descriptor = NULL; + unsigned plug_index = 0; + + char** out_lib_name = (char**)(((void**)user_data)[0]); + char* name = (char*)(((void**)user_data)[1]); + + /* Stop searching when a first matching plugin is found */ + if (*out_lib_name == NULL) + { +#if DEBUG + post("plugin~: searching plugin \"%s\"...", full_filename); +#endif + for(plug_index = 0;(is_DSSI ? + (descriptor = + (DSSI_Descriptor *)descriptor_function(plug_index)) : + ((DSSI_Descriptor *)(descriptor = + ladspa_to_dssi((LADSPA_Descriptor *) + descriptor_function(plug_index)))->LADSPA_Plugin)) + != NULL; plug_index++){ +#if DEBUG + post("plugin~: label \"%s\"", descriptor->LADSPA_Plugin->Label); +#endif + if (strcasecmp (name, descriptor->LADSPA_Plugin->Label) + == 0) + { + *out_lib_name = strdup (full_filename); +#if DEBUG + post("plugin~: found plugin \"%s\" in library \"%s\"", + name, full_filename); +#endif + /* if(!is_DSSI){ + free((DSSI_Descriptor *)descriptor); + descriptor = NULL; + }*/ + break; + } + /* if (descriptor != NULL){ + free((DSSI_Descriptor *)descriptor); + descriptor = NULL; + }*/ + } + } +} + +static const char* plugin_tilde_search_plugin_by_label (t_dssi_tilde *x, + const char *name) +{ + char* lib_name = NULL; + void* user_data[2]; + + user_data[0] = (void*)(&lib_name); + user_data[1] = (void*)name; +#if DEBUG + post("search plugin by label: '%s'\n", name); +#endif + + lib_name = NULL; + LADSPAPluginSearch (dssi_tilde_search_plugin_callback, + (void*)user_data); + + /* The callback (allocates and) writes lib_name, if it finds the plugin */ + return lib_name; + +} + +static t_int dssi_tilde_dssi_methods(t_dssi_tilde *x, t_symbol *s, int argc, t_atom *argv) +{ + if (!x->is_DSSI) { + post("dssi~: plugin is not a DSSI plugin, operation not supported"); + return 0; + } + char *msg_type, + *debug, + *filename, + *filepath, + *key, + *value, + *temp, + mydir[MAXPDSTRING]; + int instance = -1, + pathlen, + toggle, + fd, + n_instances = x->n_instances, + count, + i, + chan, + maxpatches; + t_float val; + long filelength = 0; + unsigned char *raw_patch_data = NULL; + FILE *fp = NULL; + size_t filename_length, key_size, value_size; + dx7_patch_t *patchbuf, *firstpatch; + msg_type = (char *)malloc(TYPE_STRING_SIZE); + atom_string(argv, msg_type, TYPE_STRING_SIZE); + debug = NULL; + key = NULL; + value = NULL; + maxpatches = 128; + patchbuf = malloc(32 * sizeof(dx7_patch_t)); + firstpatch = &patchbuf[0]; + val = 0; + + /*FIX: Temporary - at the moment we always load the first 32 patches to 0 */ + if(strcmp(msg_type, "configure")){ + instance = (int)atom_getfloatarg(2, argc, argv) - 1; + + if(!strcmp(msg_type, "load") && x->descriptor->configure){ + filename = argv[1].a_w.w_symbol->s_name; + post("dssi~: loading patch: %s for instance %d", filename, instance); + + if(!strcmp(x->descriptor->LADSPA_Plugin->Label, "hexter") || + !strcmp(x->descriptor->LADSPA_Plugin->Label, "hexter6")) { + + key = malloc(10 * sizeof(char)); /* holds "patchesN" */ + strcpy(key, "patches0"); + + /* FIX: duplicates code from load_plugin() */ + fd = canvas_open(x->x_canvas, filename, "", + mydir, &filename, MAXPDSTRING, 0); + + if(fd >= 0){ + filepath = mydir; + pathlen = strlen(mydir); + temp = &mydir[pathlen]; + sprintf(temp, "/%s", filename); + fp = fopen(filepath, "rb"); + } + else{ + post("dssi~: unable to get file descriptor"); + } + + /*From dx7_voice_data by Sean Bolton */ + if(fp == NULL){ + post("dssi~: unable to open patch file: %s", filename); + return 0; + } + if (fseek(fp, 0, SEEK_END) || + (filelength = ftell(fp)) == -1 || + fseek(fp, 0, SEEK_SET)) { + post("dssi~: couldn't get length of patch file: %s", + filename); + fclose(fp); + return 0; + } + if (filelength == 0) { + post("dssi~: patch file has zero length"); + fclose(fp); + return 0; + } else if (filelength > 16384) { + post("dssi~: patch file is too large"); + fclose(fp); + return 0; + } + if (!(raw_patch_data = (unsigned char *) + malloc(filelength))) { + post( + "dssi~: couldn't allocate memory for raw patch file"); + fclose(fp); + return 0; + } + if (fread(raw_patch_data, 1, filelength, fp) + != (size_t)filelength) { + post("dssi~: short read on patch file: %s", filename); + free(raw_patch_data); + fclose(fp); + return 0; + } + fclose(fp); +#if DEBUG + post("Patch file length is %ul", filelength); +#endif + /* figure out what kind of file it is */ + filename_length = strlen(filename); + if (filename_length > 4 && + !strcmp(filename + filename_length - 4, ".dx7") && + filelength % DX7_VOICE_SIZE_PACKED == 0) { + /* It's a raw DX7 patch bank */ + +#if DEBUG + post("Raw DX7 format patch bank passed"); +#endif + count = filelength / DX7_VOICE_SIZE_PACKED; + if (count > maxpatches) + count = maxpatches; + memcpy(firstpatch, raw_patch_data, count * + DX7_VOICE_SIZE_PACKED); + + } else if (filelength > 6 && + raw_patch_data[0] == 0xf0 && + raw_patch_data[1] == 0x43 && + /*This was used to fix some problem with Galaxy exports - possibly dump in worng format. It is not needed, but it did work, so in future, we may be able to support more formats not just DX7 */ + /* ((raw_patch_data[2] & 0xf0) == 0x00 || + raw_patch_data[2] == 0x7e) &&*/ + (raw_patch_data[2] & 0xf0) == 0x00 && + raw_patch_data[3] == 0x09 && + (raw_patch_data[4] == 0x10 || + raw_patch_data[4] == 0x20) && + /* 0x10 is actual, 0x20 matches typo in manual */ + raw_patch_data[5] == 0x00) { + /* It's a DX7 sys-ex 32 voice dump */ + +#if DEBUG + post("SYSEX header check passed"); +#endif + + if (filelength != DX7_DUMP_SIZE_BULK || + raw_patch_data[DX7_DUMP_SIZE_BULK - 1] != 0xf7) { + post("dssi~: badly formatted DX7 32 voice dump!"); + count = 0; + +#ifdef CHECKSUM_PATCH_FILES_ON_LOAD + } else if (dx7_bulk_dump_checksum(&raw_patch_data[6], + DX7_VOICE_SIZE_PACKED * 32) != + raw_patch_data[DX7_DUMP_SIZE_BULK - 2]) { + + post("dssi~: DX7 32 voice dump with bad checksum!"); + count = 0; + +#endif + } else { + + count = 32; + if (count > maxpatches) + count = maxpatches; + memcpy(firstpatch, raw_patch_data + 6, count * DX7_VOICE_SIZE_PACKED); + + } + } else { + + /* unsuccessful load */ + post("dssi~: unknown patch bank file format!"); + count = 0; + + } + + free(raw_patch_data); + + if(count == 32) + value = encode_7in6((uint8_t *)&patchbuf[0].data[0], + count * DX7_VOICE_SIZE_PACKED); + + } + else if(!strcmp(x->descriptor->LADSPA_Plugin->Label, + "FluidSynth-DSSI")){ + key = malloc(6 * sizeof(char)); + strcpy(key, "load"); + value = filename; + } + else{ + post("dssi~: %s patches are not supported", + x->descriptor->LADSPA_Plugin->Label); + } + + } + + if(!strcmp(msg_type, "dir") && x->descriptor->configure){ + pathlen = strlen(argv[1].a_w.w_symbol->s_name) + 2; + x->project_dir = malloc((pathlen) * sizeof(char)); + atom_string(&argv[1], x->project_dir, pathlen); + post("dssi~: project directory for instance %d has been set to: %s", instance, x->project_dir); + key = DSSI_PROJECT_DIRECTORY_KEY; + value = x->project_dir; + } + + else if(!strcmp(msg_type, "dir")) + post("dssi~: %s %s: operation not supported", msg_type, + argv[1].a_w.w_symbol->s_name); + + if(!strcmp(msg_type, "show") || !strcmp(msg_type, "hide")){ + instance = (int)atom_getfloatarg(1, argc, argv) - 1; + if(!strcmp(msg_type, "show")) + toggle = 1; + else + toggle = 0; + + if(instance == -1){ + while(n_instances--) + dssi_show(x, n_instances, toggle); + } + else + dssi_show(x, instance, toggle); + } + + if(!strcmp(msg_type, "remap")) { + /* remap channel to instance */ + for(i = 0; i < x->n_instances && i < 128; i++){ + chan = (int)atom_getfloatarg(1 + i, argc, argv); + post("dssi~: remapped MIDI channel %d to %d", 1+i, chan); + x->channelMap[i+1] = chan; + } + } + + } + + /*Use this to send arbitrary configure message to plugin */ + else if(!strcmp(msg_type, "configure")){ + key = + (char *)malloc(key_size = (strlen(argv[1].a_w.w_symbol->s_name) + 2) * sizeof(char)); + atom_string(&argv[1], key, key_size); + if(argc >= 3){ + if (argv[2].a_type == A_FLOAT){ + val = atom_getfloatarg(2, argc, argv); + value = (char *)malloc(TYPE_STRING_SIZE * + sizeof(char)); + sprintf(value, "%.2f", val); + } + else if(argv[2].a_type == A_SYMBOL){ + value = + (char *)malloc(value_size = + (strlen(argv[2].a_w.w_symbol->s_name) + 2) * + sizeof(char)); + atom_string(&argv[2], value, value_size); + } + + } + + if(argc == 4 && argv[3].a_type == A_FLOAT) + instance = atom_getfloatarg(3, argc, argv) - 1; + else if (n_instances) + instance = -1; + } + + if(key != NULL && value != NULL){ + if(instance == -1){ + while(n_instances--){ + debug = dssi_tilde_send_configure( + x, key, value, n_instances); + dssi_tilde_configure_buffer(x, key, value, n_instances); + } + } + /*FIX: Put some error checking in here to make sure instance is valid*/ + else{ + + debug = dssi_tilde_send_configure(x, key, value, instance); + dssi_tilde_configure_buffer(x, key, value, instance); + } + } +#if DEBUG + post("The plugin returned %s", debug); +#endif + free(msg_type); + free(patchbuf); + + return 0; +} + +static void dssi_tilde_bang(t_dssi_tilde *x) +{ + t_atom at[3]; + + at[0].a_type = A_FLOAT; + at[1].a_type = A_SYMBOL; + at[2].a_type = A_SYMBOL; + + if(x->plugin_label != NULL){ + at[0].a_w.w_float = x->n_instances; + at[1].a_w.w_symbol = gensym ((char *)x->plugin_label); + } + else{ + at[0].a_w.w_float = 0; + at[1].a_w.w_symbol = gensym ("plugin"); + } + at[2].a_w.w_symbol = gensym ("instances"); + outlet_anything (x->control_outlet, gensym ("running"), 3, at); +} + +static t_int *dssi_tilde_perform(t_int *w) +{ + int N = (t_int)(w[2]); + t_dssi_tilde *x = (t_dssi_tilde *)(w[1]); + t_float **inputs = (t_float **)(&w[3]); + t_float **outputs = (t_float **)(&w[3] + x->plugin_ins); + int i, n, timediff, framediff, instance = 0; + /*See comment for dssi_tilde_plug_plugin */ + if(x->dsp){ + x->dsp_loop = 1; + + for(i = 0; i < x->plugin_ins; i++) + memcpy(x->plugin_InputBuffers[i], inputs[i], N * + sizeof(LADSPA_Data)); + + for (i = 0; i < x->n_instances; i++) + x->instanceEventCounts[i] = 0; + + for (;x->bufReadIndex != x->bufWriteIndex; x->bufReadIndex = + (x->bufReadIndex + 1) % EVENT_BUFSIZE) { + + instance = x->midiEventBuf[x->bufReadIndex].data.note.channel; + + /*This should never happen, but check anyway*/ + if(instance > x->n_instances || instance < 0){ + post( + "dssi~: %s: discarding spurious MIDI data, for instance %d", + x->descriptor->LADSPA_Plugin->Label, + instance); +#if DEBUG + post("n_instances = %d", x->n_instances); +#endif + continue; + } + + if (x->instanceEventCounts[instance] == EVENT_BUFSIZE){ + post("dssi~: MIDI overflow on channel %d", instance); + continue; + } + + timediff = (t_int)(clock_gettimesince(x->time_ref) * 1000) - + x->midiEventBuf[x->bufReadIndex].time.time.tv_nsec; + framediff = (t_int)((t_float)timediff * .000001 / x->sr_inv); + + if (framediff >= N || framediff < 0) + x->midiEventBuf[x->bufReadIndex].time.tick = 0; + else + x->midiEventBuf[x->bufReadIndex].time.tick = + N - framediff - 1; + + x->instanceEventBuffers[instance] + [x->instanceEventCounts[instance]] = + x->midiEventBuf[x->bufReadIndex]; +#if DEBUG + post("%s, note received on channel %d", + x->descriptor->LADSPA_Plugin->Label, + x->instanceEventBuffers[instance] + [x->instanceEventCounts[instance]].data.note.channel); +#endif + x->instanceEventCounts[instance]++; + +#if DEBUG + post("Instance event count for instance %d of %d: %d\n", + instance + 1, x->n_instances, x->instanceEventCounts[instance]); +#endif + + } + + i = 0; + while(i < x->n_instances){ + if(x->instanceHandles[i] && + x->descriptor->run_multiple_synths){ + x->descriptor->run_multiple_synths + (x->n_instances, x->instanceHandles, + (unsigned long)N, x->instanceEventBuffers, + &x->instanceEventCounts[0]); + break; + } + else if (x->instanceHandles[i] && + x->descriptor->run_synth){ + x->descriptor->run_synth(x->instanceHandles[i], + (unsigned long)N, x->instanceEventBuffers[i], + x->instanceEventCounts[i]); + i++; + } + else if (x->instanceHandles[i] && + x->descriptor->LADSPA_Plugin->run){ + x->descriptor->LADSPA_Plugin->run + (x->instanceHandles[i], N); + i++; + } + } + + + for(i = 0; i < x->plugin_outs; i++) + memcpy(outputs[i], (t_float *)x->plugin_OutputBuffers[i], N * + sizeof(LADSPA_Data)); + + /* + for(i = 0; i < x->plugin_outs; i++) + memcpy(x->outlets[i], (t_outlet *)x->plugin_OutputBuffers[i], N * + sizeof(LADSPA_Data));*/ + x->dsp_loop = 0; + } + return w + (x->plugin_ins + x->plugin_outs + 3); +} + +static void dssi_tilde_dsp(t_dssi_tilde *x, t_signal **sp) +{ + if(x->n_instances){ + + + t_int *dsp_vector, i, N, M; + + M = x->plugin_ins + x->plugin_outs + 2; + + dsp_vector = (t_int *) getbytes(M * sizeof(t_int)); + + dsp_vector[0] = (t_int)x; + dsp_vector[1] = (t_int)sp[0]->s_n; + + for(i = 2; i < M; i++) + dsp_vector[i] = (t_int)sp[i - 1]->s_vec; + + dsp_addv(dssi_tilde_perform, M, dsp_vector); + + + /* int n, m; + + t_float **outlets; + t_float **inlets; + + for(n = 0, m = 1; n < x->plugin_ins; n++, m++) + inlets[n] = sp[m]->s_vec; + for(n = 0; n < x->plugin_outs; n++, ++m) + outlets[n] = sp[m]->s_vec; + +*/ /* + + t_float **outlets = (t_float **)x->outlets; + t_float **inlets = (t_float **)x->inlets; + + m = 1; + + for(n = 0; n < x->plugin_ins; n++) + *inlets++ = sp[m++]->s_vec; + for(n = 0; n < x->plugin_outs; n++) + *outlets++ = sp[m++]->s_vec; + */ } + /* dsp_add(dssi_tilde_perform, 2, sp[0]->s_n, x); */ + +} + +static void dssi_tilde_quit_plugin(t_dssi_tilde *x){ + + t_int i, instance; + for(instance = 0; instance < x->n_instances; instance++) { + if(x->instances[instance].uiTarget && x->is_DSSI){ + lo_send(x->instances[instance].uiTarget, + x->instances[instance].ui_osc_quit_path, ""); + lo_address_free(x->instances[instance].uiTarget); + x->instances[instance].uiTarget = NULL; + } + /* no -- see comment in osc_exiting_handler */ + /* if (!instances[i].inactive) { */ + /* if (x->descriptor->LADSPA_Plugin->deactivate) { + x->descriptor->LADSPA_Plugin->deactivate + (x->instanceHandles[instance]); + }*/ + dssi_tilde_deactivate_plugin(x, (t_float)instance); + /* } */ + if (x->descriptor->LADSPA_Plugin && + x->descriptor->LADSPA_Plugin->cleanup) { + x->descriptor->LADSPA_Plugin->cleanup + (x->instanceHandles[instance]); + } + } +} + +static void dssi_tilde_free_plugin(t_dssi_tilde *x){ + + t_int i, instance; + if(x->plugin_label != NULL) + free((char *)x->plugin_label); + if(x->plugin_handle != NULL){ + instance = x->n_instances; + free((LADSPA_Handle)x->instanceHandles); + free(x->plugin_ControlInPortNumbers); + free((t_float *)x->plugin_InputBuffers); + free(x->instanceEventCounts); + free(x->plugin_ControlDataInput); + free(x->plugin_ControlDataOutput); + + while(instance--){ + + if(x->instances[instance].gui_pid){ +#if DEBUG + post("Killing GUI process PID = %d", x->instances[instance].gui_pid); +#endif + kill(x->instances[instance].gui_pid, SIGINT); + } + if (x->instances[instance].pluginPrograms) { + for (i = 0; i < + x->instances[instance].plugin_ProgramCount; i++) + free((void *) + x->instances[instance].pluginPrograms[i].Name); + free((char *)x->instances[instance].pluginPrograms); + x->instances[instance].pluginPrograms = NULL; + x->instances[instance].plugin_ProgramCount = 0; + } + free(x->instanceEventBuffers[instance]); + if(x->is_DSSI){ + free(x->instances[instance].ui_osc_control_path); + free(x->instances[instance].ui_osc_configure_path); + free(x->instances[instance].ui_osc_program_path); + free(x->instances[instance].ui_osc_show_path); + free(x->instances[instance].ui_osc_hide_path); + free(x->instances[instance].ui_osc_quit_path); + free(x->instances[instance].osc_url_path); + } + free(x->instances[instance].plugin_PortControlInNumbers); + if(x->plugin_outs) + free(x->plugin_OutputBuffers[instance]); + } + if(x->is_DSSI){ + if(x->project_dir != NULL) + free(x->project_dir); + free(x->osc_url_base); + dssi_tilde_configure_buffer_free(x); + } + free((snd_seq_event_t *)x->instanceEventBuffers); + free(x->instances); + free((t_float *)x->plugin_OutputBuffers); + + /*sleep(1);*/ + if(x->plugin_ins){ + for(i = 0; i < x->plugin_ins; i++) + inlet_free((t_inlet *)x->inlets[i]); + freebytes(x->inlets, x->plugin_ins * sizeof(t_inlet *)); + } + + if(x->plugin_outs){ + for(i = 0; i < x->plugin_outs; i++) + outlet_free((t_outlet *)x->outlets[i]); + freebytes(x->outlets, x->plugin_outs * sizeof(t_outlet *)); + } + if(x->control_outlet) + outlet_free(x->control_outlet); + if(x->plugin_basename) + free(x->plugin_basename); + if(x->port_info) + free(x->port_info); + } +} + +static void dssi_tilde_init_plugin(t_dssi_tilde *x){ + + x->project_dir = NULL; + x->configure_buffer_head = NULL; + x->outlets = NULL; + x->inlets = NULL; + x->control_outlet = NULL; + x->plugin_handle = NULL; + x->plugin_full_path = NULL; + x->plugin_label = NULL; + x->plugin_basename = NULL; + x->osc_url_base = NULL; + x->plugin_ControlDataInput = x->plugin_ControlDataOutput = NULL; + x->plugin_InputBuffers = x->plugin_OutputBuffers = NULL; + x->plugin_ControlInPortNumbers = NULL; + x->port_info = NULL; + x->descriptor = NULL; + x->instanceEventCounts = NULL; + x->instances = NULL; + x->instanceHandles = NULL; + x->is_DSSI = 0; + x->n_instances = 0; + x->dsp = 0; + x->dsp_loop = 0; + x->plugin_ins = x->plugin_outs = + x->plugin_controlIns = x->plugin_controlOuts = 0; + x->ports_in = x->ports_out = x->ports_controlIn = x->ports_controlOut = 0; + x->bufWriteIndex = x->bufReadIndex = 0; + +} + +static void *dssi_tilde_load_plugin(t_dssi_tilde *x, t_int argc, t_atom *argv){ + char *plugin_basename = NULL, + *plugin_full_path = NULL, + *tmpstr, + *plugin_label, + plugin_dir[MAXPDSTRING]; + +#if DEBUG + post("argc = %d", argc); +#endif + int i, + stop, + fd; + size_t pathlen; + + stop = 0; + + if (argc){ + char *argstr = strdup(argv[0].a_w.w_symbol->s_name); + + if(strstr(argstr, ":") != NULL){ + tmpstr = strtok(argstr, ":"); + plugin_full_path = strdup(tmpstr); + plugin_label = strtok(NULL, ":"); + // first part of the string is empty, i.e. ':mystring' + if (plugin_label == NULL) { + x->plugin_label = plugin_full_path; + plugin_full_path = NULL; + } else { + x->plugin_label = strdup(plugin_label); + } + } + else{ + x->plugin_label = strdup(argstr); + tmpstr = (char *)plugin_tilde_search_plugin_by_label(x, x->plugin_label); + if(tmpstr) + plugin_full_path = strdup(tmpstr); + } + free(argstr); +#if DEBUG + post("plugin path = %s", plugin_full_path); + post("plugin name = %s", x->plugin_label); +#endif + + if(plugin_full_path != NULL){ + /* First try to load as is: this will work if plugin_full_path is an + * absolute path, or the name of a library that is in DSSI_PATH + * or LADSPA_PATH environment variables */ + x->plugin_full_path = (char *)plugin_full_path; + /* If that didn't work, search for it in the 'canvas' path, which + * includes the Pd search dirs and any 'extra' paths set with + * [declare] */ + fd = canvas_open(x->x_canvas, plugin_full_path, "", + plugin_dir, &plugin_basename, MAXPDSTRING, 0); + + if (fd >= 0) { +#if DEBUG + post("plugin directory is %s, filename is %s", + plugin_dir, plugin_basename); +#endif + x->plugin_basename = strdup(plugin_basename); + pathlen = strlen(plugin_dir); + tmpstr = &plugin_dir[pathlen]; + sprintf(tmpstr, "/%s", plugin_basename); + tmpstr = plugin_dir; + x->plugin_handle = loadLADSPAPluginLibrary(tmpstr); + } else { + x->plugin_handle = loadLADSPAPluginLibrary(plugin_full_path); + } + + if (x->plugin_handle == NULL) + error("dssi~: can't find plugin in Pd paths, " + "try using [declare] to specify the path."); + + } + + if (x->plugin_handle != NULL){ + tmpstr = strdup(plugin_full_path); + /* Don't bother working out the plugin name if we used canvas_open() + * to get the path */ + if(plugin_basename == NULL){ + if(strstr(tmpstr, ".so")){ + plugin_basename = strtok((char *)tmpstr, "/"); + while(strstr(plugin_basename, ".so") == NULL) + plugin_basename = strtok(NULL, "/"); + x->plugin_basename = strdup(plugin_basename); +#if DEBUG + post("plugin basename = %s", x->plugin_basename); +#endif + } + else{ + post("dssi~: invalid plugin path, must end in .so"); + return (void *) x; + } + } + free(tmpstr); + if(x->desc_func = (DSSI_Descriptor_Function)dlsym(x->plugin_handle, "dssi_descriptor")){ + x->is_DSSI = 1; + x->descriptor = (DSSI_Descriptor *)x->desc_func(0); + } + else if(x->desc_func = + (DSSI_Descriptor_Function)dlsym(x->plugin_handle, "ladspa_descriptor")){ + x->is_DSSI = 0; + x->descriptor = + ladspa_to_dssi((LADSPA_Descriptor *) + x->desc_func(0)); + } + + + if(argc >= 2) + x->n_instances = (t_int)argv[1].a_w.w_float; + else + x->n_instances = 1; + + +#if DEBUG + post("n_instances = %d", x->n_instances); +#endif + x->instances = (t_dssi_instance *)malloc(sizeof(t_dssi_instance) * + x->n_instances); + + if(x->descriptor){ +#if DEBUG + post("%s loaded successfully!", + x->descriptor->LADSPA_Plugin->Label); +#endif + + /*allocate memory for port_info*/ + + x->port_info = (t_port_info *)malloc + (x->descriptor->LADSPA_Plugin->PortCount * + sizeof(t_port_info)); + + dssi_tilde_port_info(x); + dssi_tilde_assign_ports(x); + for(i = 0; i < x->n_instances; i++){ + x->instanceHandles[i] = + x->descriptor->LADSPA_Plugin-> + instantiate(x->descriptor->LADSPA_Plugin, x->sr); + if (!x->instanceHandles[i]){ + post("dssi~: instantiation of instance %d failed", i); + stop = 1; + break; + } + } + if(!stop){ + for(i = 0;i < x->n_instances; i++) + dssi_tilde_init_instance(x, i); + for(i = 0;i < x->n_instances; i++) + dssi_tilde_connect_ports(x, i); + for(i = 0;i < x->n_instances; i++) + dssi_tilde_activate_plugin(x, i); + + if(x->is_DSSI){ + for(i = 0;i < x->n_instances; i++) + dssi_tilde_osc_setup(x, i); +#if LOADGUI + for(i = 0;i < x->n_instances; i++) + dssi_tilde_load_gui(x, i); +#endif + for(i = 0;i < x->n_instances; i++) + dssi_tilde_init_programs(x, i); + + for(i = 0; i < x->n_instances && i < 128; i++){ + x->channelMap[i] = i; + } + } + } + } + } + else + post("dssi~: error: plugin not loaded"); + } + else + post("dssi~: no arguments given, please supply a path"); + + x->control_outlet = + outlet_new (&x->x_obj, gensym("control")); + + if (x->plugin_handle != NULL){ + if(x->plugin_outs){ + x->outlets = (t_outlet **)getbytes(x->plugin_outs * sizeof(t_outlet *)); + for(i = 0;i < x->plugin_outs; i++) + x->outlets[i] = outlet_new(&x->x_obj, &s_signal); + /* x->outlets = + (t_float **)calloc(x->plugin_outs, + sizeof(t_float *)); + */ + } + else + post("dssi~: error: plugin has no outputs"); + if(x->plugin_ins){ + x->inlets = (t_inlet **)getbytes(x->plugin_ins * sizeof(t_inlet *)); + for(i = 0;i < x->plugin_ins; i++) + x->inlets[i] = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + /* x->inlets = + (t_float **)calloc(x->plugin_ins, + sizeof(t_float *)); + */ + } + else + post("dssi~: error: plugin has no inputs"); + + x->dsp = 1; + post("dssi~: %d instances of %s, ready.", x->n_instances, + x->plugin_label); + } + else + post("dssi~: error: no plugin handle"); + + return (void *)x; +} + + +/* This method is currently buggy. PD's inlet/outlet handling seems buggy if you try to create ins/outs on the fly. Needs further investigation ...*/ +static void dssi_tilde_plug_plugin(t_dssi_tilde *x, t_symbol *s, int argc, t_atom *argv){ + + x->dsp = 0; + dssi_tilde_quit_plugin(x); + while(1){ + if(!x->dsp_loop){ + dssi_tilde_free_plugin(x); + break; + } + } + dssi_tilde_init_plugin(x); + dssi_tilde_load_plugin(x, argc, argv); +} + +static void *dssi_tilde_new(t_symbol *s, t_int argc, t_atom *argv){ + + t_dssi_tilde *x = (t_dssi_tilde *)pd_new(dssi_tilde_class); + post("\n========================================\ndssi~: DSSI/LADSPA host - version %.2f\n========================================\n", VERSION); + + dssi_tilde_init_plugin(x); + + x->sr = (t_int)sys_getsr(); + x->sr_inv = 1 / (t_float)x->sr; + x->time_ref = (t_int)clock_getlogicaltime; + x->blksize = sys_getblksize(); + x->dsp = 0; + x->x_canvas = canvas_getcurrent(); + + pthread_mutex_init(&x->midiEventBufferMutex, NULL); + return dssi_tilde_load_plugin(x, argc, argv); + +} + +static void dssi_tilde_free(t_dssi_tilde *x){ + +#if DEBUG + post("Calling dssi_tilde_free"); +#endif + + dssi_tilde_quit_plugin(x); + dssi_tilde_free_plugin(x); + +} + +static void dssi_tilde_sigchld_handler(int sig) { + wait(NULL); +} + +void dssi_tilde_setup(void) { + + dssi_tilde_class = class_new(gensym("dssi~"), (t_newmethod)dssi_tilde_new, + (t_method)dssi_tilde_free, sizeof(t_dssi_tilde), 0, A_GIMME, 0); + class_addlist(dssi_tilde_class, dssi_tilde_list); + class_addbang(dssi_tilde_class, dssi_tilde_bang); + class_addmethod(dssi_tilde_class, + (t_method)dssi_tilde_dsp, gensym("dsp"), 0); + class_addmethod(dssi_tilde_class, (t_method)dssi_tilde_dssi_methods, + gensym("dssi"), A_GIMME, 0); + class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_control, + gensym ("control"),A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_info, + gensym ("info"),0); + class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_list_plugins, + gensym ("listplugins"),0); + class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_reset, + gensym ("reset"), A_DEFFLOAT, 0); + class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_plug_plugin, + gensym ("plug"),A_GIMME,0); + /* class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_activate_plugin, + gensym ("activate"),A_DEFFLOAT - 1,0); + class_addmethod (dssi_tilde_class,(t_method)dssi_tilde_deactivate_plugin, + gensym ("deactivate"),A_DEFFLOAT - 1,0);*/ + class_sethelpsymbol(dssi_tilde_class, gensym("dssi-help")); + CLASS_MAINSIGNALIN(dssi_tilde_class, t_dssi_tilde, f); + signal(SIGCHLD, dssi_tilde_sigchld_handler); +} + +static int osc_message_handler(const char *path, const char *types, + lo_arg **argv,int argc, void *data, void *user_data) +{ +#if DEBUG + post("osc_message_handler active"); +#endif + int i, instance = 0; + const char *method; + char chantemp[2]; + t_dssi_tilde *x = (t_dssi_tilde *)(user_data); + + if (strncmp(path, "/dssi/", 6)){ +#if DEBUG + post("calling osc_debug_handler"); +#endif + return osc_debug_handler(path, types, argv, argc, data, x); + } + for (i = 0; i < x->n_instances; i++) { + if (!strncmp(path + 6, x->instances[i].osc_url_path, + strlen(x->instances[i].osc_url_path))) { + instance = i; + break; + } + } +#if DEBUG + for(i = 0; i < argc; i++){ + post("got osc request %c from instance %d, path: %s", + types[i],instance,path); + } +#endif + + if (!x->instances[instance].osc_url_path){ +#if DEBUG + post("calling osc_debug_handler"); +#endif + return osc_debug_handler(path, types, argv, argc, data, x); + } + method = path + 6 + strlen(x->instances[instance].osc_url_path); + if (*method != '/' || *(method + 1) == 0){ +#if DEBUG + post("calling osc_debug_handler"); +#endif + return osc_debug_handler(path, types, argv, argc, data, x); + } + method++; + + if (!strcmp(method, "configure") && argc == 2 && !strcmp(types, "ss")) { + +#if DEBUG + post("calling osc_configure_handler"); +#endif + return osc_configure_handler(x, argv, instance); + + } else if (!strcmp(method, "control") && argc == 2 && !strcmp(types, "if")) { +#if DEBUG + post("calling osc_control_handler"); +#endif + return osc_control_handler(x, argv, instance); + } + + else if (!strcmp(method, "midi") && argc == 1 && !strcmp(types, "m")) { + +#if DEBUG + post("calling osc_midi_handler"); +#endif + return osc_midi_handler(x, argv, instance); + + } else if (!strcmp(method, "program") && argc == 2 && !strcmp(types, "ii")){ +#if DEBUG + post("calling osc_program_handler"); +#endif + return osc_program_handler(x, argv, instance); + + } else if (!strcmp(method, "update") && argc == 1 && !strcmp(types, "s")){ +#if DEBUG + post("calling osc_update_handler"); +#endif + return osc_update_handler(x, argv, instance); + + } else if (!strcmp(method, "exiting") && argc == 0) { + + return osc_exiting_handler(x, argv, instance); + } + + return osc_debug_handler(path, types, argv, argc, data, x); +} + diff --git a/pluginhost~/src/dssi~.h b/pluginhost~/src/dssi~.h new file mode 100644 index 0000000..6aadb85 --- /dev/null +++ b/pluginhost~/src/dssi~.h @@ -0,0 +1,183 @@ +/* dssi~ - A DSSI host for PD + * + * Copyright 2006 Jamie Bullock and others + * + * This file incorporates code from the following sources: + * + * jack-dssi-host (BSD-style license): Copyright 2004 Chris Cannam, Steve Harris and Sean Bolton. + * + * Hexter (GPL license): Copyright (C) 2004 Sean Bolton and others. + * + * + * This program is free software; you can redistribute it and/or + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "m_pd.h" +#include "dssi.h" +#include +#include +#include +#include +#include +#include /*for exit()*/ +#include /* for fork() */ +#include /* for kill() */ +#include /* for wait() */ +#include /* for readdir() */ + +#define DX7_VOICE_SIZE_PACKED 128 /*From hexter_types.h by Sean Bolton */ +#define DX7_DUMP_SIZE_BULK 4096+8 + + +#define VERSION 0.99 +#define EVENT_BUFSIZE 1024 +#define OSC_BASE_MAX 1024 +#define TYPE_STRING_SIZE 20 /* Max size of event type string (must be two more bytes than needed) */ +#define DIR_STRING_SIZE 1024 /* Max size of directory string */ +#define ASCII_n 110 +#define ASCII_p 112 +#define ASCII_c 99 +#define ASCII_b 98 +#define ASCII_t 116 +#define ASCII_a 97 + +#define LOADGUI 0 /* FIX: depracate this */ +#ifdef DEBUG +#define CHECKSUM_PATCH_FILES_ON_LOAD 1 +#endif + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + + +/*From dx7_voice.h by Sean Bolton */ + +typedef struct _dx7_patch_t { + uint8_t data[128]; +} dx7_patch_t; + +typedef struct _dssi_instance { + + long currentBank; + long currentProgram; + int pendingBankLSB; + int pendingBankMSB; + int pendingProgramChange; + + int plugin_ProgramCount; + DSSI_Program_Descriptor *pluginPrograms; + + lo_address uiTarget; /*osc stuff */ + int ui_hidden; + int ui_show; + int uiNeedsProgramUpdate; + char *ui_osc_control_path; + char *ui_osc_configure_path; + char *ui_osc_program_path; + char *ui_osc_show_path; + char *ui_osc_hide_path; + char *ui_osc_quit_path; + + int *plugin_PortControlInNumbers; /*not sure if this should go here?*/ + + char *osc_url_path; + pid_t gui_pid; + +} t_dssi_instance; + +struct dssi_configure_pair { + t_int instance; + char *key, + *value; + struct dssi_configure_pair *next; +}; + +typedef struct dssi_configure_pair t_dssi_configure_pair; + +typedef struct _port_info { + t_atom type, + data_type, + name, + lower_bound, + upper_bound, + p_default; +} t_port_info; + +typedef struct _dssi_tilde { + t_object x_obj; + t_int is_DSSI; + char *plugin_label; + char *plugin_full_path; /*absolute path to plugin */ + t_canvas *x_canvas; /* pointer to the canvas the object is instantiated on */ + void *plugin_handle; + char *project_dir; /* project dircetory */ + LADSPA_Handle *instanceHandles; /*was handle*/ + t_dssi_instance *instances; + int n_instances; + unsigned long *instanceEventCounts; + unsigned char channelMap[128]; + snd_seq_event_t **instanceEventBuffers; + + snd_seq_event_t midiEventBuf[EVENT_BUFSIZE]; + /*static snd_seq_event_t **instanceEventBuffers;*/ + int bufWriteIndex, bufReadIndex; + pthread_mutex_t midiEventBufferMutex; + /*static pthread_mutex_t listHandlerMutex = PTHREAD_MUTEX_INITIALIZER;*/ + + DSSI_Descriptor_Function desc_func; + DSSI_Descriptor *descriptor; + + t_port_info *port_info; + + t_int ports_in, ports_out, ports_controlIn, ports_controlOut; + t_int plugin_ins;/* total audio input ports for plugin*/ + t_int plugin_outs;/* total audio output ports plugin*/ + t_int plugin_controlIns;/* total control input ports*/ + t_int plugin_controlOuts;/* total control output ports */ + + unsigned long *plugin_ControlInPortNumbers; /*Array of input port numbers for the plugin */ + + t_float **plugin_InputBuffers, **plugin_OutputBuffers; /* arrays of arrays for buffering audio for each audio port */ + t_float *plugin_ControlDataInput, *plugin_ControlDataOutput; /*arrays for control data for each port (1 item per 'run')*/ + lo_server_thread osc_thread; + char *osc_url_base; + char *plugin_basename; + + t_int time_ref; /*logical time reference */ + t_int sr; + t_float sr_inv; + t_int blksize; + t_float f; + + t_outlet **outlets; + t_inlet **inlets; + t_outlet *control_outlet; + + t_dssi_configure_pair *configure_buffer_head; + + t_int dsp; /* boolean dsp setting */ + t_int dsp_loop; + +} t_dssi_tilde; + +static char *dssi_tilde_send_configure(t_dssi_tilde *x, char *key, + char *value, t_int instance); +static int osc_message_handler(const char *path, const char *types, + lo_arg **argv, int argc, void *data, void *user_data); +static LADSPA_Data get_port_default(t_dssi_tilde *x, int port); +static void MIDIbuf(int type, int chan, int param, int val, t_dssi_tilde *x); + + diff --git a/pluginhost~/src/jload.c b/pluginhost~/src/jload.c new file mode 100644 index 0000000..1672b91 --- /dev/null +++ b/pluginhost~/src/jload.c @@ -0,0 +1,214 @@ +/* load.c + + Free software by Richard W.E. Furse. Do with as you will. No + warranty. */ + +/* patched by Jarno Seppänen, jams@cs.tut.fi, for plugin~ */ + +/* patched by Jamie Bullock, jamie@postlude.co.uk, for dssi~ */ + +/*****************************************************************************/ + +#include +#include +#include +#include + +/*****************************************************************************/ + +#include "ladspa.h" +#include "jutils.h" + +/*****************************************************************************/ + +/* This function provides a wrapping of dlopen(). When the filename is + not an absolute path (i.e. does not begin with / character), this + routine will search the LADSPA_PATH for the file. */ +static void * +dlopenLADSPA(const char * pcFilename, int iFlag) { + + char * pcBuffer; + const char * pcEnd; + const char * pcLADSPAPath; + const char * pcStart; + int iEndsInSO; + int iNeedSlash; + size_t iFilenameLength; + void * pvResult; + char *pluginPath; + + + iFilenameLength = strlen(pcFilename); + pvResult = NULL; + + /* First we just try calling dlopen(). This works if the user knows + about dlopen() and has placed the file on the LD_LIBRARY path or + has used an absolute directory. */ + pvResult = dlopen(pcFilename, iFlag); + if (pvResult != NULL) + return pvResult; + + /* If the filename is not absolute then we wish to check along the + LADSPA_PATH path to see if we can find the file there. */ + if (pcFilename[0] != '/') { + + pcLADSPAPath = NULL; + + if(getenv("LADSPA_PATH") && getenv("DSSI_PATH")){ + pluginPath = malloc(sizeof(char) * + (strlen(getenv("LADSPA_PATH")) + 1) + + sizeof(char) * strlen(getenv("DSSI_PATH"))); + sprintf(pluginPath, "%s:%s", + getenv("LADSPA_PATH"), getenv("DSSI_PATH")); + pcLADSPAPath = pluginPath; + free(pluginPath); + } + if (pcLADSPAPath == NULL) { + fprintf(stderr, "Warning: no LADSPA_PATH and DSSI_PATH, assuming /usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi\n"); + pcLADSPAPath = + "/usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi"; + } + + if (pcLADSPAPath) { + + pcStart = pcLADSPAPath; + while (*pcStart != '\0') { + pcEnd = pcStart; + while (*pcEnd != ':' && *pcEnd != '\0') + pcEnd++; + + pcBuffer = malloc(iFilenameLength + 2 + (pcEnd - pcStart)); + if (pcEnd > pcStart) + strncpy(pcBuffer, pcStart, pcEnd - pcStart); + iNeedSlash = 0; + if (pcEnd > pcStart) + if (*(pcEnd - 1) != '/') { + iNeedSlash = 1; + pcBuffer[pcEnd - pcStart] = '/'; + } + strcpy(pcBuffer + iNeedSlash + (pcEnd - pcStart), pcFilename); + + pvResult = dlopen(pcBuffer, iFlag); + + free (pcBuffer); + if (pvResult != NULL){ + return pvResult; + } + + pcStart = pcEnd; + if (*pcStart == ':') + pcStart++; + } + } else { + fputs ("warning: You haven't specified the LADSPA_PATH environment variable and didn't specify an absolute path to the plug-in.\n" + "Please set the LADSPA_PATH variable to point to your LADSPA plug-in directories (eg. \"export LADSPA_PATH=/usr/local/lib/ladspa\").\n", stderr); + } + } + + /* As a last ditch effort, check if filename does not end with + ".so". In this case, add this suffix and recurse. */ + iEndsInSO = 0; + if (iFilenameLength > 3) + iEndsInSO = (strcmp(pcFilename + iFilenameLength - 3, ".so") == 0); + if (!iEndsInSO) { + pcBuffer = malloc(iFilenameLength + 4); + strcpy(pcBuffer, pcFilename); + strcat(pcBuffer, ".so"); + pvResult = dlopenLADSPA(pcBuffer, iFlag); + } + + if (pvResult != NULL) + return pvResult; + + /* If nothing has worked, then at least we can make sure we set the + correct error message - and this should correspond to a call to + dlopen() with the actual filename requested. The dlopen() manual + page does not specify whether the first or last error message + will be kept when multiple calls are made to dlopen(). We've + covered the former case - now we can handle the latter by calling + dlopen() again here. */ + return dlopen(pcFilename, iFlag); +} + +/*****************************************************************************/ + +void * +loadLADSPAPluginLibrary(const char * pcPluginFilename) { + + void * pvPluginHandle; + + pvPluginHandle = dlopenLADSPA(pcPluginFilename, RTLD_NOW); + if (!pvPluginHandle) { + fprintf(stderr, + "Failed to load plugin \"%s\": %s\n", + pcPluginFilename, + dlerror()); +#if 0 + exit(1); +#else + return NULL; +#endif + } + + return pvPluginHandle; +} + +/*****************************************************************************/ + +void +unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary) { + dlclose(pvLADSPAPluginLibrary); +} + +/*****************************************************************************/ + +const LADSPA_Descriptor * +findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary, + const char * pcPluginLibraryFilename, + const char * pcPluginLabel) { + + const LADSPA_Descriptor * psDescriptor; + LADSPA_Descriptor_Function pfDescriptorFunction; + unsigned long lPluginIndex; + + dlerror(); + pfDescriptorFunction + = (LADSPA_Descriptor_Function)dlsym(pvLADSPAPluginLibrary, + "ladspa_descriptor"); + if (!pfDescriptorFunction) { + const char * pcError = dlerror(); + if (pcError) + fprintf(stderr, + "Unable to find ladspa_descriptor() function in plugin " + "library file \"%s\": %s.\n" + "Are you sure this is a LADSPA plugin file?\n", + pcPluginLibraryFilename, + pcError); +#if 0 + exit(1); +#else + return NULL; +#endif + } + + for (lPluginIndex = 0;; lPluginIndex++) { + psDescriptor = pfDescriptorFunction(lPluginIndex); + if (psDescriptor == NULL) { + fprintf(stderr, + "Unable to find label \"%s\" in plugin library file \"%s\".\n", + pcPluginLabel, + pcPluginLibraryFilename); +#if 0 + exit(1); +#else + return NULL; +#endif + } + if (strcmp(psDescriptor->Label, pcPluginLabel) == 0) + return psDescriptor; + } +} + +/*****************************************************************************/ + +/* EOF */ diff --git a/pluginhost~/src/jsearch.c b/pluginhost~/src/jsearch.c new file mode 100644 index 0000000..593c6f5 --- /dev/null +++ b/pluginhost~/src/jsearch.c @@ -0,0 +1,154 @@ +/* search.c + + Free software by Richard W.E. Furse. Do with as you will. No + warranty. */ + +/* patched by Jarno Seppänen, jams@cs.tut.fi, for plugin~ */ + +/* patched by Jamie Bullock, jamie@postlude.co.uk, for dssi~ */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +/*****************************************************************************/ + +#include "dssi.h" +#include "jutils.h" + +/*****************************************************************************/ + +/* Search just the one directory. */ + static void +LADSPADirectoryPluginSearch (const char * pcDirectory, + LADSPAPluginSearchCallbackFunction fCallbackFunction, + void* user_data) +{ + char * pcFilename; + DIR * psDirectory; + DSSI_Descriptor_Function fDescriptorFunction; + long lDirLength; + long iNeedSlash; + struct dirent * psDirectoryEntry; + void * pvPluginHandle; + int is_DSSI = 0; + + lDirLength = strlen(pcDirectory); + if (!lDirLength) + return; + if (pcDirectory[lDirLength - 1] == '/') + iNeedSlash = 0; + else + iNeedSlash = 1; + + psDirectory = opendir(pcDirectory); + if (!psDirectory) + return; + + while (1) { + + psDirectoryEntry = readdir(psDirectory); + if (!psDirectoryEntry) { + closedir(psDirectory); + return; + } + + pcFilename = malloc(lDirLength + + strlen(psDirectoryEntry->d_name) + + 1 + iNeedSlash); + strcpy(pcFilename, pcDirectory); + if (iNeedSlash) + strcat(pcFilename, "/"); + strcat(pcFilename, psDirectoryEntry->d_name); + + pvPluginHandle = dlopen(pcFilename, RTLD_LAZY); + if (pvPluginHandle) { + /* This is a file and the file is a shared library! */ + + dlerror(); + if(fDescriptorFunction = (DSSI_Descriptor_Function)dlsym(pvPluginHandle, + "ladspa_descriptor")) + is_DSSI = 0; + + else if(fDescriptorFunction = (DSSI_Descriptor_Function)dlsym(pvPluginHandle, + "dssi_descriptor")) + is_DSSI = 1; + + if (dlerror() == NULL && fDescriptorFunction) { + /* We've successfully found a ladspa_descriptor function. Pass + it to the callback function. */ + fCallbackFunction(pcFilename, + pvPluginHandle, + fDescriptorFunction, + user_data, + is_DSSI); + dlclose (pvPluginHandle); + } + else { + /* It was a library, but not a LADSPA one. Unload it. */ + dlclose(pcFilename); + } + } + } +} + +/*****************************************************************************/ + + void +LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction, + void* user_data) +{ + + char * pcBuffer; + const char * pcEnd; + const char * pcLADSPAPath; + char *pluginPath; + const char * pcStart; + + + pcLADSPAPath = NULL; + + if(getenv("LADSPA_PATH") && getenv("DSSI_PATH")){ + pluginPath = malloc(sizeof(char) * + (strlen(getenv("LADSPA_PATH")) + 1) + + sizeof(char) * strlen(getenv("DSSI_PATH"))); + sprintf(pluginPath, "%s:%s", + getenv("LADSPA_PATH"), getenv("DSSI_PATH")); + pcLADSPAPath = pluginPath; + free(pluginPath); + } + if (pcLADSPAPath == NULL) { + fprintf(stderr, "Warning: no LADSPA_PATH and DSSI_PATH, assuming /usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi\n"); + pcLADSPAPath = + "/usr/lib/ladspa:/usr/local/lib/ladspa:/usr/lib/dssi:/usr/local/lib/dssi"; + } + + pcStart = pcLADSPAPath; + while (*pcStart != '\0') { + pcEnd = pcStart; + while (*pcEnd != ':' && *pcEnd != '\0') + pcEnd++; + + pcBuffer = malloc(1 + pcEnd - pcStart); + if (pcEnd > pcStart) + strncpy(pcBuffer, pcStart, pcEnd - pcStart); + pcBuffer[pcEnd - pcStart] = '\0'; + + LADSPADirectoryPluginSearch(pcBuffer, fCallbackFunction, user_data); + + pcStart = pcEnd; + if (*pcStart == ':') + pcStart++; + } +} + + +/*****************************************************************************/ + +/* EOF */ diff --git a/pluginhost~/src/jutils.h b/pluginhost~/src/jutils.h new file mode 100644 index 0000000..fdf718f --- /dev/null +++ b/pluginhost~/src/jutils.h @@ -0,0 +1,69 @@ +/* utils.h + + Free software by Richard W.E. Furse. Do with as you will. No + warranty. */ + +/* patched by Jarno Seppänen, jams@cs.tut.fi, for plugin~ */ + +/* patched by Jamie Bullock, jamie@postlude.co.uk, for dssi~ */ + +#ifndef LADSPA_SDK_LOAD_PLUGIN_LIB +#define LADSPA_SDK_LOAD_PLUGIN_LIB + +/*****************************************************************************/ + +#include "dssi.h" + +/*****************************************************************************/ + +/* Functions in load.c: */ + +/* This function call takes a plugin library filename, searches for + the library along the LADSPA_PATH, loads it with dlopen() and + returns a plugin handle for use with findPluginDescriptor() or + unloadLADSPAPluginLibrary(). Errors are handled by writing a + message to stderr and calling exit(1). It is alright (although + inefficient) to call this more than once for the same file. */ +void * loadLADSPAPluginLibrary(const char * pcPluginFilename); + +/* This function unloads a LADSPA plugin library. */ +void unloadLADSPAPluginLibrary(void * pvLADSPAPluginLibrary); + +/* This function locates a LADSPA plugin within a plugin library + loaded with loadLADSPAPluginLibrary(). Errors are handled by + writing a message to stderr and calling exit(1). Note that the + plugin library filename is only included to help provide + informative error messages. */ +const LADSPA_Descriptor * +findLADSPAPluginDescriptor(void * pvLADSPAPluginLibrary, + const char * pcPluginLibraryFilename, + const char * pcPluginLabel); + +/*****************************************************************************/ + +/* Functions in search.c: */ + +/* Callback function for use with LADSPAPluginSearch(). The callback + function passes the filename (full path), a plugin handle (dlopen() + style) and a LADSPA_DescriptorFunction (from which + LADSPA_Descriptors can be acquired). */ +typedef void LADSPAPluginSearchCallbackFunction +(const char * pcFullFilename, + void * pvPluginHandle, + DSSI_Descriptor_Function fDescriptorFunction, + void* user_data, + int is_DSSI); + +/* Search through the $(LADSPA_PATH) (or a default path) for any + LADSPA plugin libraries. Each plugin library is tested using + dlopen() and dlsym(,"ladspa_descriptor"). After loading each + library, the callback function is called to process it. This + function leaves items passed to the callback function open. */ +void LADSPAPluginSearch(LADSPAPluginSearchCallbackFunction fCallbackFunction, + void* user_data); + +/*****************************************************************************/ + +#endif + +/* EOF */ -- cgit v1.2.1