From 19ff5f54a824d7b3cd7f2683d9e524e446984735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Tue, 1 Apr 2008 13:44:04 +0000 Subject: an old project - wandering whether it still works svn path=/trunk/externals/hardware/; revision=9672 --- MIDIvice/LICENSE.txt | 290 +++++++++++++ MIDIvice/README.txt | 92 ++++ MIDIvice/doc/motormix.pd | 193 +++++++++ MIDIvice/src/MIDIvice.c | 36 ++ MIDIvice/src/MIDIvice.h | 38 ++ MIDIvice/src/makefile | 75 ++++ MIDIvice/src/motormix.c | 865 ++++++++++++++++++++++++++++++++++++++ MIDIvice/src/motormix_buttons.txt | 374 ++++++++++++++++ 8 files changed, 1963 insertions(+) create mode 100644 MIDIvice/LICENSE.txt create mode 100644 MIDIvice/README.txt create mode 100644 MIDIvice/doc/motormix.pd create mode 100644 MIDIvice/src/MIDIvice.c create mode 100644 MIDIvice/src/MIDIvice.h create mode 100644 MIDIvice/src/makefile create mode 100644 MIDIvice/src/motormix.c create mode 100644 MIDIvice/src/motormix_buttons.txt (limited to 'MIDIvice') diff --git a/MIDIvice/LICENSE.txt b/MIDIvice/LICENSE.txt new file mode 100644 index 0000000..fa0bef4 --- /dev/null +++ b/MIDIvice/LICENSE.txt @@ -0,0 +1,290 @@ +GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. + +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 diff --git a/MIDIvice/README.txt b/MIDIvice/README.txt new file mode 100644 index 0000000..a57ec6e --- /dev/null +++ b/MIDIvice/README.txt @@ -0,0 +1,92 @@ +the MIDIvice library +==================== + +VERSION: +0.1 + +-------------------- + +GENERAL:: +the MIDIvice library is a collection of externals for miller.s.puckette's realtime-computermusic-environment called "puredata" (or abbreviated "pd") +this MIDIvice-library will be of no use, if you don't have a running version of pd on your system. +check out for http://puredata.info to learn more about pd and how to get it + +LICENSE:: +the MIDIvice library is published under the Gnu General Public License that is included (LICENSE.txt). +some parts of the code are taken directly from the pd source-code, they, of course, fall under the license pd is published under. + +AUTHORS:: +this software is copyleft 2002-2008 by IOhannes m zmoelnig , Institute of Electronic Music and Acoustics, University of Music and Dramatic Arts, Graz, Austria + +-------------------- + +PURPOSE:: +MIDIvice attempts to make handling of complex(!!!) MIDI-devices easier under Pd. It's like hiding all the SysEx-crap. +Such devices include + - mixing-consoles + - controllable patch-bays + - Synthesizers (for doing SampleDumps etc.) + +Such devices do NOT include: +- Synthesizers (for playing purposes; there is enough support under pd, i think) +- hardware, that gives your PC the possibility of doing MIDI (so really, i am not going to write another device-driver for your USBMIDI thing) + +SUPPORTED DEVICES:: +- MotorMix(tm) by cm-labs(r) - http://www.cmlabs.net + 8-channel motorfader-box with lots of buttons, LCDisplay and pan-pots. + the MotorMix-specification were supplied by cm-labs (Many thanks !!). + You can now download it from ftp://ftp.iem.at/pub/pd/Externals/MIDIvice/motormix.pdf + + objects: + MotorMix - ping and reset the MotorMix + motormix_rotary - get movements of the rotaries + motormix_encoder - get movement and push-state of the special "encoder"-rotary + motormix_faderIn - get movements of the faders + motormix_faderOut - move the motorfaders + motormix_button - get button press/releases + motormix_LED - switch on/off the button-LEDs (ot let them blink) + motormix_LCDtext - display some text on the MotorMix-LCDisplay + motormix_LCDgraph - display some simple graphics on the MotorMix-LCDisplay + motormix_7seg - display something on MotorMix's 7segment dispay + +-------------------- + +TODO:: +support for FriendChip digital patchbays +support for TCelectronics M-5000 +... +feel free to send me your wish-list (probably with MIDI-specifications) + +BUGS: +none known (right now) +motormix_button/LED could be more intuitive... + +-------------------- + +INSTALLING:: +linux : +change to directory source +adapt the makefile to match your system (where is pd installed ?) +"make clean" +"make" +"make install" +this will install the MIDIvice library into /pd/extra +documentation will be installed to /pd/doc/5.reference/MIDIvice +alternatively you can try "make everything" + +win32 : +i haven't had time to compile and test the MIDIvice-library under Windos yet. +Good luck ! + +darwin : +TODO + +irix : +though i have physical access to both SGI's O2s and indys, i haven't tried to compile the MIDIvice library there. +Good luck ! + +-------------------- + +RUNNING:: +add the "MIDIvice" library to your startup-path +see doc/ for more information diff --git a/MIDIvice/doc/motormix.pd b/MIDIvice/doc/motormix.pd new file mode 100644 index 0000000..2663f0a --- /dev/null +++ b/MIDIvice/doc/motormix.pd @@ -0,0 +1,193 @@ +#N canvas 171 107 566 570 10; +#X msg 77 131 bang; +#X msg 121 131 reset; +#X msg 178 131 help; +#N canvas 269 178 589 510 switches 0; +#X obj 83 99 motormix_button; +#X floatatom 83 122 5 0 0; +#X floatatom 183 122 5 0 0; +#X text 182 144 press/release; +#X text 81 148 button#; +#X obj 83 457 motormix_LED; +#X msg 181 299 1; +#X msg 181 321 0; +#X msg 181 343 -1; +#X floatatom 83 321 5 0 128; +#X obj 132 379 t b f; +#X text 93 301 button#; +#X text 215 299 on; +#X text 212 320 off; +#X text 217 344 blink; +#X obj 83 215 spigot; +#X obj 120 198 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 +1; +#X floatatom 162 429 5 0 0; +#X text 16 13 get button-states (pressed/released) and illuminated +the button-LEDs.; +#X text 337 89 get state; +#X text 316 409 illuminate LED; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 1 0 15 0; +#X connect 6 0 10 0; +#X connect 7 0 10 0; +#X connect 8 0 10 0; +#X connect 9 0 5 0; +#X connect 10 0 5 0; +#X connect 10 1 17 0; +#X connect 15 0 9 0; +#X connect 16 0 15 1; +#X connect 17 0 5 1; +#X restore 79 386 pd switches; +#N canvas 221 144 600 463 faders 0; +#X obj 312 58 motormix_faderIn; +#X floatatom 312 81 5 0 0; +#X floatatom 365 81 5 0 0; +#X floatatom 419 80 5 0 0; +#X floatatom 107 80 5 0 0; +#X floatatom 228 80 5 0 0; +#X obj 107 58 motormix_faderIn 1; +#X text 311 102 value; +#X text 361 103 touched; +#X text 423 103 fader#; +#X text 107 100 value; +#X text 223 99 touched; +#X obj 309 348 motormix_faderOut; +#X obj 97 348 motormix_faderOut 4; +#X floatatom 309 326 5 0 128; +#X floatatom 97 326 5 0 128; +#X floatatom 423 326 5 1 8; +#X text 306 309 value; +#X text 422 309 fader#; +#X text 93 310 value; +#X text 36 18 get fader-values:; +#X text 33 278 move the motor-faders:; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 0 2 3 0; +#X connect 6 0 4 0; +#X connect 6 1 5 0; +#X connect 14 0 12 0; +#X connect 15 0 13 0; +#X connect 16 0 12 1; +#X restore 77 307 pd faders; +#N canvas 417 60 470 311 rotaries 0; +#X obj 290 73 motormix_rotary; +#X floatatom 290 96 5 0 0; +#X floatatom 390 96 5 0 0; +#X floatatom 36 87 5 0 0; +#X obj 36 64 motormix_rotary 4; +#X text 39 110 increment; +#X text 284 121 increment; +#X text 396 122 rotary#; +#X obj 68 233 motormix_encoder; +#X floatatom 68 257 5 0 0; +#X floatatom 175 258 5 0 0; +#X text 178 281 push; +#X text 68 280 increment; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 4 0 3 0; +#X connect 8 0 9 0; +#X connect 8 1 10 0; +#X restore 77 342 pd rotaries; +#N canvas 179 9 750 744 LCDisplay 0; +#X obj 72 391 motormix_LCDtext; +#X msg 72 92 MotorMix (tm) is now supported by pd !!!; +#X msg 107 126 clear; +#X msg 108 149 clear 1; +#X msg 109 172 clear 2; +#X text 174 127 clear LCD-display; +#X text 172 149 clear 1st row; +#X text 174 174 clear 2nd row; +#X msg 121 218 (l) forum::fuer::umlaeute:2002; +#X obj 121 241 t a b; +#X msg 179 291 0; +#X msg 151 264 45; +#X msg 198 324 10 20; +#X text 243 325 start position and string-length; +#X floatatom 207 605 5 0 0; +#X floatatom 79 541 5 0 128; +#X floatatom 143 576 5 0 8; +#X obj 79 627 motormix_LCDgraph 3; +#X text 208 589 type; +#X text 132 559 channel#; +#X text 80 523 value; +#X text 272 534 LCDgraph-types:; +#X text 395 580 03__single vertical line; +#X text 394 533 00__left justified horizontal bar graph; +#X text 395 549 01__centered horizontal bar graph; +#X text 394 564 02__right justified horizontal bar graph; +#X text 395 595 04__left justified double vertical line; +#X text 396 611 05__centered spreading bar; +#X text 395 626 06__ascending bar graph; +#X text 396 642 07__descending bar graph; +#X text 184 11 write some text to the MotorMix-display; +#X floatatom 151 326 5 0 0; +#X symbolatom 48 66 10 0 0; +#X text 139 66 some text; +#X text 206 292 start position (0..79); +#X text 112 457 put some graphics on the second-line of the LCDisplay +(like pannings \, gain-reductions...); +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 8 0 9 0; +#X connect 9 0 0 0; +#X connect 9 1 11 0; +#X connect 10 0 31 0; +#X connect 11 0 31 0; +#X connect 12 0 0 1; +#X connect 14 0 17 2; +#X connect 15 0 17 0; +#X connect 16 0 17 1; +#X connect 31 0 0 1; +#X connect 32 0 0 0; +#X restore 87 458 pd LCDisplay; +#N canvas 146 108 501 430 7segment-display 0; +#X obj 71 370 motormix_7seg; +#X obj 99 337 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 +; +#X obj 157 338 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 +1; +#X text 206 335 toggle points on/off; +#X text 184 11 write something to the 7-segment-display; +#X floatatom 71 59 5 0 0; +#X obj 138 142 % 10; +#X obj 107 142 / 10; +#X obj 107 163 pack; +#X obj 107 121 t f f; +#X floatatom 107 99 5 0 99; +#X symbolatom 128 255 10 0 0; +#X text 119 60 write " %d"; +#X text 147 164 set 1st and 2nd char; +#X symbolatom 128 230 10 0 0; +#X text 215 230 set 1st char; +#X text 215 256 set 2nd char; +#X connect 1 0 0 1; +#X connect 2 0 0 3; +#X connect 5 0 0 0; +#X connect 6 0 8 1; +#X connect 7 0 8 0; +#X connect 8 0 0 0; +#X connect 9 0 7 0; +#X connect 9 1 6 0; +#X connect 10 0 9 0; +#X connect 11 0 0 2; +#X connect 14 0 0 0; +#X restore 86 484 pd 7segment-display; +#X text 183 306 get/set the motorfaders; +#X text 184 343 get the state of the rotaries ("pan"); +#X text 184 384 get button-presses an illuminate their LEDs; +#X text 257 457 write something to the LCDisplay; +#X text 256 484 write something to the 7segment-display; +#X text 161 28 MotorMix (tm) by CM-labs; +#X obj 77 225 print MotorMix; +#X msg 77 201 OK; +#X obj 77 171 motormix; +#X connect 0 0 16 0; +#X connect 1 0 16 0; +#X connect 2 0 16 0; +#X connect 15 0 14 0; +#X connect 16 0 15 0; diff --git a/MIDIvice/src/MIDIvice.c b/MIDIvice/src/MIDIvice.c new file mode 100644 index 0000000..67cf293 --- /dev/null +++ b/MIDIvice/src/MIDIvice.c @@ -0,0 +1,36 @@ +#include "MIDIvice.h" +void motormix_setup(); + +typedef struct MIDIvice +{ + t_object t_ob; +} t_MIDIvice; + +t_class *MIDIvice_class; + +static void MIDIvice_help(void) +{ + post("\nMIDIvice "VERSION); + post("supported devices:"); + post("\tmotormix\t\tMotorMix(tm) by cm-labs(r)" + "\n"); +} + +void *MIDIvice_new(void) +{ + t_MIDIvice *x = (t_MIDIvice *)pd_new(MIDIvice_class); + return (void *)x; +} + + +void MIDIvice_setup(void) +{ + motormix_setup(); + + /* ************************************** */ + post("\n\tMIDIvice "VERSION); + post("\tcopyleft forum::für::umläute @ IEM/KUG 2002-2008"); + + MIDIvice_class = class_new(gensym("MIDIvice"), MIDIvice_new, 0, sizeof(t_MIDIvice), 0, 0); + class_addmethod(MIDIvice_class, MIDIvice_help, gensym("help"), 0); +} diff --git a/MIDIvice/src/MIDIvice.h b/MIDIvice/src/MIDIvice.h new file mode 100644 index 0000000..65382a7 --- /dev/null +++ b/MIDIvice/src/MIDIvice.h @@ -0,0 +1,38 @@ +/* ********************************************** */ +/* the MIDIvice external */ +/* externals for controlling MIDI-devices */ +/* ********************************************** */ +/* forum::für::umläute */ +/* ********************************************** */ + +/* the MIDIvice external is a runtime-library for miller s. puckette's realtime-computermusic-software "pure data" + * therefore you NEED "pure data" to make any use of the MIDIvice external + * (except if you want to use the code for other things) + * download "pure data" at + + http://iem.kug.ac.at/pd + ftp://iem.kug.ac.at/pd + + * + * if you are looking for the latest release of the MIDIvice-external you should have another look at + + ftp://iem.kug.ac.at/pd/Externals/MIDIvice + + * + * MIDIvice is published under the GNU GeneralPublicLicense, that must be shipped with MIDIvice. + * if you are using Debian GNU/linux, the GNU-GPL can be found under /usr/share/common-licenses/GPL + * if you still haven't found a copy of the GNU-GPL, have a look at http://www.gnu.org + * + * "pure data" has it's own license, that comes shipped with "pure data". + * + * there are ABSOLUTELY NO WARRANTIES for anything + */ + +#ifndef INCLUDE_MIDIVICE_H__ +#define INCLUDE_MIDIVICE_H__ + +#include "m_pd.h" + +#define VERSION "0.1" + +#endif diff --git a/MIDIvice/src/makefile b/MIDIvice/src/makefile new file mode 100644 index 0000000..447d820 --- /dev/null +++ b/MIDIvice/src/makefile @@ -0,0 +1,75 @@ +current: all + + +# the MIDIVICE-EXTERNAL-makefile +# everything is GnuGPL that should come with the MIDIvice.tgz +# NO WARRANTIES FOR ANYTHING +# et cetera +# 1999:forum::für::umläute:2001 + +# make sure that the "m_pd.h" is somehow available either by putting it into this +# directory, by adding it's path to the INCLUDE-path or by putting it into an +# already included path, e.g. "/usr/local/include/" + +#these are the user adjustables : adjust them to fit into your system +# PD will install to $(DESTDIR)$(INSTALLL_PREFIX)$(PDLIBDIR), which is /usr/local/lib/pd +# by default +DESTDIR = +INSTALL_PREFIX = /usr/local +PDLIBDIR = /lib/pd +#these were the user adjustables + + +TARGETS = MIDIvice \ + motormix + +# ----------------------- LINUX ---------------------------- +.SUFFIXES: .pd_linux + + +LINUXOBJECTS = $(TARGETS:%=%.o) +ARCH = $(shell uname --machine) + +PD_DIR = $(DESTDIR)$(INSTALL_PREFIX)$(PDLIBDIR) + +ifeq (${ARCH},alpha) +AFLAGS = -mieee -mcpu=ev56 +endif + +LINCLUDE = + +$(LINUXOBJECTS): *.h + +CFLAGS = -O2 -g -Wall $(LINCLUDE) $(UCFLAGS) $(AFLAGS) + +everything: clean all install distclean + +distclean: + touch dummy.o + touch dummy.pd_linux + touch dummy~ + touch _dummy + rm *.o *.pd_linux *~ _* + +clean: + touch dummy.o + touch dummy.pd_linux + rm *.o *.pd_linux + +all: $(LINUXOBJECTS) + + @echo :: $(LINUXOBJECTS) + + ld -export_dynamic -shared -o MIDIvice.pd_linux *.o -lc -lm + strip --strip-unneeded MIDIvice.pd_linux + +.c.pd_linux: + cc $(CFLAGS) -O2 -DPD -fPIC $(INCLUDE) -c -o $*.o $*.c + + +install: installdocs + install -m 644 MIDIvice.pd_linux $(PD_DIR)/extra + +installdocs: + install -d $(PD_DIR)/doc/5.reference/MIDIvice + install -m644 ../doc/* $(PD_DIR)/doc/5.reference/MIDIvice diff --git a/MIDIvice/src/motormix.c b/MIDIvice/src/motormix.c new file mode 100644 index 0000000..982a268 --- /dev/null +++ b/MIDIvice/src/motormix.c @@ -0,0 +1,865 @@ + +/* 2801:forum::für::umläute:2002 */ + +/* + motormix by CM-labs +*/ + +#include "MIDIvice.h" +#include +#include + +#define LCD_TEXT 0x10 +#define LCD_GRAPH 0x11 +#define SEG7 0x12 + +static int x_port = 0; +static t_symbol *ctlin_sym; +static t_symbol *notein_sym; + +void outmidi_noteon(int portno, int channel, int pitch, int velo); +void outmidi_controlchange(int portno, int channel, int ctlno, int value); +void sys_putmidibyte(int portno, int byte); + +static void outmidi_byte(unsigned char byte) +{ sys_putmidibyte(x_port, byte); } + + + +/* ------------------------- LCDtext ------------------------------- */ + +static t_class *LCDtext_class; +typedef struct _LCDtext +{ + t_object x_obj; + + int pos; + int length; + t_binbuf *bbuf; +} t_LCDtext; + + +static void LCD_header(unsigned char type) +{ + outmidi_byte(0xF0); + outmidi_byte(0x00); + outmidi_byte(0x01); + outmidi_byte(0x0F); + outmidi_byte(0x00); + outmidi_byte(0x11); + outmidi_byte(0x00); + outmidi_byte(type); +} +static void LCD_footer(void) +{ + outmidi_byte(0xF7); +} + +static void LCDtext_text(t_LCDtext *x) +{ + char *c, *str=0; + int n, slen; + int pos = x->pos; + int len = x->length; + int rest=0; + + if (!x->bbuf)return; + + binbuf_gettext(x->bbuf, &str, &slen); + c=str; + if (len>slen){ + n=slen; + rest=len-slen; + } else n=len?len:slen; + + if (n>0x50-pos)n=0x50-pos; + + LCD_header(LCD_TEXT); + outmidi_byte(pos); + while(n--)outmidi_byte(*c++); + while(rest--)outmidi_byte(' '); + LCD_footer(); + + freebytes(str, slen); +} + +static void LCDtext_clear(t_LCDtext *x, t_float fmode) +{ + int mode = fmode; + int offset = (mode==2)?0x28:0x00; + int n = (mode>0)?0x28:0x50; + + post("offset=%d\tn=%d", offset, n); + + LCD_header(LCD_TEXT); + outmidi_byte(offset); + + while(n--)outmidi_byte(' '); + + LCD_footer(); +} + +static void LCDtext_any(t_LCDtext *x, t_symbol *s, int argc, t_atom *argv) +{ + // t_atom a; + binbuf_clear(x->bbuf); + + if ((s != &s_list)&&(s != &s_float)&&(s != &s_symbol)){ + t_atom a; + SETSYMBOL(&a, s); + binbuf_add(x->bbuf, 1, &a); + } + binbuf_add(x->bbuf, argc, argv); + + LCDtext_text(x); +} + +static void LCDtext_pos(t_LCDtext *x, t_float pos, t_float len) +{ + if (pos<0 )pos=0; + if (pos>80)pos=80; + if (len<0 )len=0; + + x->pos=pos; + x->length=len; +} + + +static void *LCDtext_new(t_floatarg f) +{ + t_LCDtext *x = (t_LCDtext *)pd_new(LCDtext_class); + int pos = f; + + if (pos<0)pos=0; + if (pos>0x4f)pos=0x4f; + x->pos=pos; + // floatinlet_new(&x->x_obj, &x->pos); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("")); + + x->bbuf = binbuf_new(); + + return (x); +} +static void LCDtext_setup(void) +{ + LCDtext_class = class_new(gensym("motormix_LCDtext"), (t_newmethod)LCDtext_new, + 0, sizeof(t_LCDtext), 0, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)LCDtext_new, gensym("mm_LCDtext"), A_DEFFLOAT, 0); + + class_addmethod(LCDtext_class, (t_method)LCDtext_pos, gensym(""), A_DEFFLOAT, A_DEFFLOAT, 0); + class_addmethod(LCDtext_class, (t_method)LCDtext_clear, gensym("clear"), A_DEFFLOAT, 0); + class_addbang(LCDtext_class, (t_method)LCDtext_text); + + class_addanything(LCDtext_class, LCDtext_any); + class_sethelpsymbol(LCDtext_class, gensym("MIDIvice/motormix")); +} +/* ------------------------- LCDgraph ------------------------------- */ + +static t_class *LCDgraph_class; +typedef struct _LCDgraph +{ + t_object x_obj; + + t_float pos; + int type; +} t_LCDgraph; + +static void LCDgraph_valpos(int pos, int val) +{ + if ((pos<1)||(pos>8))return; + if (val<0)val=0; + if (val>127)val=127; + outmidi_byte(pos-1); + outmidi_byte(val); +} + +static void LCDgraph_float(t_LCDgraph *x, t_float f) +{ + if ((x->pos<1)||(x->pos>8))return; + + LCD_header(LCD_GRAPH); + outmidi_byte(x->type); + LCDgraph_valpos(x->pos, f); + LCD_footer(); +} + +static void LCDgraph_clear(t_LCDgraph *x) +{ + int n = 0x28; + int pos=0x28; + + LCD_header(LCD_TEXT); + outmidi_byte(pos); + while(n--)outmidi_byte(' '); + LCD_footer(); +} + + +static void LCDgraph_pos(t_LCDgraph *x, t_float pos) +{ + x->pos=pos; +} +static void LCDgraph_typ(t_LCDgraph *x, t_float type) +{ + if (type<0 )type=0; + if (type>7)type=7; + + x->type=type; +} +static void *LCDgraph_new(t_float ftype) +{ + t_LCDgraph *x = (t_LCDgraph *)pd_new(LCDgraph_class); + + LCDgraph_typ(x, ftype); + floatinlet_new(&x->x_obj, &x->pos); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("type")); + x->pos=0; + + return (x); +} +static void LCDgraph_setup(void) +{ + LCDgraph_class = class_new(gensym("motormix_LCDgraph"), (t_newmethod)LCDgraph_new, + 0, sizeof(t_LCDgraph), 0, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)LCDgraph_new, gensym("mm_LCDgraph"), A_DEFFLOAT, 0); + + class_addmethod(LCDgraph_class, (t_method)LCDgraph_typ, gensym("type"), A_DEFFLOAT, 0); + class_addmethod(LCDgraph_class, (t_method)LCDgraph_pos, gensym(""), A_DEFFLOAT, 0); + class_addmethod(LCDgraph_class, (t_method)LCDgraph_clear, gensym("clear"), 0); + class_addfloat (LCDgraph_class, (t_method)LCDgraph_float); + + // class_addbang(LCDgraph_class, (t_method)LCDgraph_graph); + class_sethelpsymbol(LCDgraph_class, gensym("MIDIvice/motormix")); +} + +/* ------------------------- seg7 ------------------------------- */ + +static t_class *seg7_class; +typedef struct _seg7 +{ + t_object x_obj; + + t_float point1, point2; + char c1, c2; +} t_seg7; + +static void seg7_nibblebyte(char c, int point) +{ + char C = toupper(c); + char lo=C&0x0F; + char hi=(C>>4)&0x0F; + if (point)hi|=0x40; + // post("C=%c=%c", c, C); + // post("hi=%x\tlo=%x", hi, lo); + + outmidi_byte(hi); + outmidi_byte(lo); +} + +static void seg7_write(char c1, int pt1, char c2, int pt2) +{ + LCD_header(SEG7); + + seg7_nibblebyte(c1, pt1); + seg7_nibblebyte(c2, pt2); + + LCD_footer(); +} + +static void seg7_clear(t_seg7 *x, t_float fmode) +{ + int mode = fmode; + + LCD_header(SEG7); + if (mode!=2)seg7_nibblebyte(' ', 0); + else seg7_nibblebyte(0, 0); + if (mode!=1)seg7_nibblebyte(' ', 0); + else seg7_nibblebyte(0, 0); + + LCD_footer(); +} + +static void seg7_list(t_seg7 *x, t_symbol *s, int argc, t_atom* argv) +{ + char seg1, seg2; + int pt1=(x->point1 != 0); + int pt2=(x->point2 != 0); + + seg1=(argv->a_type==A_SYMBOL)? + *atom_getsymbol(argv)->s_name: + (atom_getint(argv)%10+0x30); + argv++; + if (argc>1)seg2=(argv->a_type==A_SYMBOL)?*atom_getsymbol(argv)->s_name:(atom_getint(argv)%10+0x30); + else { + seg2=seg1; + seg1=' '; + } + // post("seg1=%c\tseg2=%c", seg1, seg2); + + x->c1=seg1; + x->c2=seg2; + + seg7_write(seg1, pt1, seg2, pt2); +} +static void seg7_symbol(t_seg7 *x, t_symbol *s) +{ + int pt1=(x->point1 != 0); + int pt2=(x->point2 != 0); + char c1=*s->s_name; + char c2=x->c2; + + x->c1=c1; + + // post("c1=%c\tc2=%c", c1, c2); + + seg7_write(c1, pt1, c2, pt2); +} +static void seg7_symbol2(t_seg7 *x, t_symbol *s) +{ + x->c2=*s->s_name; +} +static void seg7_bang(t_seg7 *x) +{ + int pt1=(x->point1 != 0); + int pt2=(x->point2 != 0); + char c1=x->c1; + char c2=x->c2; + + seg7_write(c1, pt1, c2, pt2); +} + +static void *seg7_new(void) +{ + t_seg7 *x = (t_seg7 *)pd_new(seg7_class); + + floatinlet_new(&x->x_obj, &x->point1); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("symbol"), gensym("")); + floatinlet_new(&x->x_obj, &x->point2); + + x->point1=x->point2=0; + x->c1=x->c2=0; + + return (x); +} +static void seg7_setup(void) +{ + seg7_class = class_new(gensym("motormix_7seg"), (t_newmethod)seg7_new, + 0, sizeof(t_seg7), 0, A_GIMME, 0); + class_addcreator((t_newmethod)seg7_new, gensym("mm_7seg"), A_GIMME, 0); + class_addbang(seg7_class, seg7_bang); + class_addlist(seg7_class, seg7_list); + class_addsymbol(seg7_class, seg7_symbol); + class_addmethod(seg7_class, (t_method)seg7_clear, gensym("clear"), A_DEFFLOAT, 0); + class_addmethod(seg7_class, (t_method)seg7_symbol2, gensym(""), A_DEFSYMBOL, 0); + class_sethelpsymbol(seg7_class, gensym("MIDIvice/motormix")); +} + +/* ------------------------- LED ------------------------------- */ + +static t_class *LED_class; +typedef struct _LED +{ + t_object x_obj; + + t_float LED; + t_float state; +} t_LED; + +static void LED_float(t_LED *x, t_float f) +{ + int MSB, LSB; + int state = x->state; + int offset = 0; + int id = f; + + if (id<0)return; + LSB=id%8; + MSB=id/8; + + x->LED=id; + + + if (state>0)offset=0x40; + else if (state<0)offset=0x50; + + // if (MSB<8)offset++; +#if 0 + post("LED: %x %x %x %x", 0x0C, MSB, 0x2C, LSB+offset); + // post("LED: %d %d %d %d\n", 0x0C, MSB, 0x2C, LSB+offset); +#endif + outmidi_controlchange(x_port>>4, x_port&15, 0x0C, MSB); + outmidi_controlchange(x_port>>4, x_port&15, 0x2C, LSB+offset); +} + +static void LED_symbol(t_LED *x, t_symbol *s) +{ + post("motormix_LED: no method for symbol"); +} + +static void LED_bang(t_LED *x) +{ + LED_float(x, x->LED); +} + +static void *LED_new(void) +{ + t_LED *x = (t_LED *)pd_new(LED_class); + + x->LED=-1; + floatinlet_new(&x->x_obj, &x->state); + + x->state=0; + + return (x); +} +static void LED_setup(void) +{ + LED_class = class_new(gensym("motormix_LED"), (t_newmethod)LED_new, + 0, sizeof(t_LED), 0, 0); + class_addcreator((t_newmethod)LED_new, gensym("mm_LED"), 0); + + class_addsymbol(LED_class, LED_symbol); + class_addfloat (LED_class, LED_float); + class_addbang (LED_class, LED_bang); + class_sethelpsymbol(LED_class, gensym("MIDIvice/motormix")); +} + + +/* button */ +static t_class *button_class; +typedef struct _button +{ + t_object x_obj; + int o_itsme; // the fader changed + int o_imtouched; // the fader was touched + + t_outlet *o_value; // actual fader-value + t_outlet *o_touch; // 1=touched; 0=released + + int activefader; + int fader; + unsigned char MSB, LSB; +} t_button; + +static void button_touch(t_button *x, unsigned char value, unsigned char control) +{ + int pressed=0; + int MSB=x->MSB; + int LSB=0; + + x->o_imtouched=0; + + if (x->MSB<8){ + if ((value==0x00) || (value==0x40))return; + } + + LSB=value; + + if (LSB>=0x40){ + pressed=1; + LSB-=0x40; + } + + outlet_float(x->o_touch, pressed); + outlet_float(x->o_value, MSB*8+LSB); +} + +static void button_list(t_button *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char ctl = atom_getfloatarg(0, argc, argv); + unsigned char val = atom_getfloatarg(1, argc, argv); + // int channel = atom_getfloatarg(2, argc, argv); + + if (x->o_imtouched)button_touch(x, val, ctl); + + if (ctl==0x0f){ + x->o_imtouched=1; + x->MSB=val; + } +} +static void button_free(t_button *x) +{ + pd_unbind(&x->x_obj.ob_pd, ctlin_sym); +} +static void *button_new() +{ + t_button *x = (t_button *)pd_new(button_class); + + x->o_value=outlet_new(&x->x_obj, &s_float); + x->o_touch=outlet_new(&x->x_obj, &s_float); + + x->o_imtouched = 0; + + pd_bind(&x->x_obj.ob_pd, ctlin_sym); + + return (x); +} +static void button_setup(void) +{ + button_class = class_new(gensym("motormix_button"), (t_newmethod)button_new, (t_method)button_free, + sizeof(t_button), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)button_new, gensym("mm_button"), A_DEFFLOAT, 0); + + class_addlist(button_class, button_list); + class_sethelpsymbol(button_class, gensym("MIDIvice/motormix")); +} + +/* ------------------------- rotary ------------------------------- */ + + +static t_class *rotary_class; +typedef struct _rotary +{ + t_object x_obj; + + t_outlet *o_value; // actual rot-value + t_outlet *o_rot; // rot-number + + int rot; +} t_rotary; + +static void rotary_list(t_rotary *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char ctl = atom_getfloatarg(0, argc, argv); + unsigned char val = atom_getfloatarg(1, argc, argv); + // int channel = atom_getfloatarg(2, argc, argv); + + if ((ctl>=0x40) && (ctl<0x48)) { + if (x->rot) { + if (ctl+1-0x40==x->rot){ + // int value = (val>=64)?val-64:-val; + outlet_float(x->o_value, (val>=64)?val-64:-val); + } + } else { + outlet_float(x->o_rot, (t_float)(ctl-0x40+1)); + outlet_float(x->o_value, (val>=64)?val-64:-val); + } + } +} +static void rotary_free(t_rotary *x) +{ + pd_unbind(&x->x_obj.ob_pd, ctlin_sym); +} +static void *rotary_new(t_floatarg f) +{ + t_rotary *x = (t_rotary *)pd_new(rotary_class); + + if ((f<0) || (f>=9)){ + post("motormix_rotary: rot [%d] specified. only rotariess 1..8(&0) are valid", (int)f); + f=0; + } + x->rot = f; + + x->o_value=outlet_new(&x->x_obj, &s_float); + if (!x->rot) x->o_rot=outlet_new(&x->x_obj, &s_float); + + pd_bind(&x->x_obj.ob_pd, ctlin_sym); + + return (x); +} +static void rotary_setup(void) +{ + rotary_class = class_new(gensym("motormix_rotary"), (t_newmethod)rotary_new, (t_method)rotary_free, + sizeof(t_rotary), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)rotary_new, gensym("mm_rotary"), A_DEFFLOAT, 0); + + class_addlist(rotary_class, rotary_list); + class_sethelpsymbol(rotary_class, gensym("MIDIvice/motormix")); +} + +/* ------------------------- encoder ------------------------------- */ + +static t_class *encoder_class; +typedef struct _encoder +{ + t_object x_obj; + + t_outlet *o_value; // actual rot-value + t_outlet *o_push; // pushed +} t_encoder; + +static void encoder_list(t_encoder *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char ctl = atom_getfloatarg(0, argc, argv); + unsigned char val = atom_getfloatarg(1, argc, argv); + // int channel = atom_getfloatarg(2, argc, argv); + + if (ctl==0x48) outlet_float(x->o_value, (val>=64)?val-64:-val); + else if (ctl==0x49)outlet_float(x->o_push, (t_float)(val==0x01)); +} +static void encoder_free(t_encoder *x) +{ + pd_unbind(&x->x_obj.ob_pd, ctlin_sym); +} +static void *encoder_new(void) +{ + t_encoder *x = (t_encoder *)pd_new(encoder_class); + + x->o_value=outlet_new(&x->x_obj, &s_float); + x->o_push =outlet_new(&x->x_obj, &s_float); + + pd_bind(&x->x_obj.ob_pd, ctlin_sym); + + return (x); +} +static void encoder_setup(void) +{ + encoder_class = class_new(gensym("motormix_encoder"), (t_newmethod)encoder_new, (t_method)encoder_free, + sizeof(t_encoder), CLASS_NOINLET, 0); + class_addcreator((t_newmethod)encoder_new, gensym("mm_encoder"), 0); + + class_addlist(encoder_class, encoder_list); + class_sethelpsymbol(encoder_class, gensym("MIDIvice/motormix")); +} + + +/* ------------------------- faderIn ------------------------------- */ + +static t_class *faderIn_class; +typedef struct _faderIn +{ + t_object x_obj; + int o_itsme; // the fader changed + int o_imtouched; // the fader was touched + + t_outlet *o_value; // actual fader-value + t_outlet *o_touch; // 1=touched; 0=released + t_outlet *o_fader; // fader-number + + int activefader; + int fader; + unsigned char MSB, LSB; +} t_faderIn; + +static void faderIn_parse(t_faderIn *x, unsigned char value, unsigned char control) +{ + unsigned int fader = (x->fader)?x->fader:x->activefader; + x->o_itsme=0; + + if (fader+31==control){ + x->LSB=value; + if (!x->fader)outlet_float(x->o_fader, x->activefader); + outlet_float(x->o_value, x->MSB+(1./128)*x->LSB); + } +} +static void faderIn_touch(t_faderIn *x, unsigned char value, unsigned char control) +{ + x->o_imtouched=0; + + if (control==0x2F){ + switch (value) { + case 0x00: + if (!x->fader)outlet_float(x->o_fader, x->activefader); + outlet_float(x->o_touch, 0.); + break; + case 0x40: + if (!x->fader)outlet_float(x->o_fader, x->activefader); + outlet_float(x->o_touch, 1.); + default: + break; + } + } +} + +static void faderIn_list(t_faderIn *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char ctl = atom_getfloatarg(0, argc, argv); + unsigned char val = atom_getfloatarg(1, argc, argv); + // int channel = atom_getfloatarg(2, argc, argv); + + if (x->o_itsme) faderIn_parse(x, val, ctl); + if (x->o_imtouched)faderIn_touch(x, val, ctl); + + if (ctl==0x0f){ + if (x->fader) { + if (val+1==x->fader){ // touched me + x->o_imtouched=1; + } + } else { + if (val<=7){ // touched us + x->o_imtouched=1; + x->activefader=val+1; + } + } + } else if (ctl<0x08) { + if (x->fader) { + if (ctl+1==x->fader){ + x->o_itsme=1; + x->MSB=val; + } + } else { + x->o_itsme=1; + x->activefader=ctl+1; + x->MSB=val; + } + } +} +static void faderIn_free(t_faderIn *x) +{ + pd_unbind(&x->x_obj.ob_pd, ctlin_sym); +} +static void *faderIn_new(t_floatarg f) +{ + t_faderIn *x = (t_faderIn *)pd_new(faderIn_class); + + if ((f<0) || (f>=9)){ + post("motormix_fader: fader [%d] specified. only faders 1..8(&0) are valid", (int)f); + f=0; + } + x->fader = f; + + x->o_value=outlet_new(&x->x_obj, &s_float); + x->o_touch=outlet_new(&x->x_obj, &s_float); + if (!x->fader) x->o_fader=outlet_new(&x->x_obj, &s_float); + + x->o_itsme = 0; + x->o_imtouched = 0; + x->activefader = 0; + + pd_bind(&x->x_obj.ob_pd, ctlin_sym); + + return (x); +} +static void faderIn_setup(void) +{ + faderIn_class = class_new(gensym("motormix_faderIn"), (t_newmethod)faderIn_new, (t_method)faderIn_free, + sizeof(t_faderIn), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)faderIn_new, gensym("mm_faderIn"), A_DEFFLOAT, 0); + + class_addlist(faderIn_class, faderIn_list); + class_sethelpsymbol(faderIn_class, gensym("MIDIvice/motormix")); +} + +/* ------------------------- faderOut ------------------------------- */ + +static t_class *faderOut_class; +typedef struct _faderOut +{ + t_object x_obj; + + t_float fader; +} t_faderOut; + +static void faderOut_float(t_faderOut *x, t_float f) +{ + int fader=x->fader; + unsigned char MSB, LSB; + if (f>=128)f=128; + else if (f<0)f=0; + if ((fader<1) || (fader>8))return; + + MSB=f; + LSB=(f-MSB)*128; + outmidi_controlchange(x_port>>4, x_port&15, fader-1, MSB); + outmidi_controlchange(x_port>>4, x_port&15, fader-1+32, LSB); +} + +static void *faderOut_new(t_floatarg f) +{ + t_faderOut *x = (t_faderOut *)pd_new(faderOut_class); + + if ((f<0) || (f>=9)){ + post("motormix_fader: fader [%d] specified. only faders 1..8(&0) are valid", (int)f); + f=0; + } + x->fader=f; + if (!x->fader)floatinlet_new(&x->x_obj, &x->fader); + + return (x); +} +static void faderOut_setup(void) +{ + faderOut_class = class_new(gensym("motormix_faderOut"), (t_newmethod)faderOut_new, + 0, sizeof(t_faderOut), 0, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)faderOut_new, gensym("mm_faderOut"), A_DEFFLOAT, 0); + + class_addfloat(faderOut_class, faderOut_float); + class_sethelpsymbol(faderOut_class, gensym("MIDIvice/motormix")); +} + +/* ------------------------- motormix ------------------------------- */ + +static t_class *motormix_class; +typedef struct _motormix +{ + t_object x_obj; +} t_motormix; +static void motormix_return(t_motormix *x, t_symbol *s, int argc, t_atom *argv) +{ + int p = atom_getfloatarg(0, argc, argv); + int v = atom_getfloatarg(1, argc, argv); + + if ((p==0x00) && (v==0x7F)) + outlet_bang(x->x_obj.ob_outlet); +} + +static void motormix_bang(t_motormix *x) +{ outmidi_noteon(x_port>>4, x_port&15,0,0); } + +static void motormix_help(t_motormix *x) +{ + post("MIDIvice - motormix\n==================="); + post("support for MotorMix (tm) by cm-labs (r)"); + post(" \tmotormix_faderIn" + "\n\tmotormix_rotary" + "\n\tmotormix_encoder" + "\n\tmotormix_button" + "\n\tmotormix_faderOut" + "\n\tmotormix_LED" + "\n\tmotormix_LCDtext" + "\n\tmotormix_LCDgraph" + "\n\tmotormix_7seg"); + post("(l) forum::für::umläute @ IEM, Graz; 2002"); +} +static void motormix_reset(t_motormix *x) +{ /* this LOOKs like a reset; i don't know what it really is... */ + LCD_header(SEG7); + LCD_footer(); +} +static void motormix_free(t_motormix *x) +{ + pd_unbind(&x->x_obj.ob_pd, notein_sym); +} +static void *motormix_new(t_floatarg f) +{ + t_motormix *x = (t_motormix *)pd_new(motormix_class); + x_port=f; + outlet_new(&x->x_obj, &s_float); + pd_bind(&x->x_obj.ob_pd, notein_sym); + // outmidi_noteon(x_port>>4,x_port&15,0,0); // isn't this dangerous ??? + return (x); +} + +void motormix_setup(void) +{ + motormix_class = class_new(gensym("motormix"), (t_newmethod)motormix_new, (t_method)motormix_free, + sizeof(t_motormix), 0/*0CLASS_NOINLET*/, /*A_DEFFLOAT,*/ 0); + + class_addcreator((t_newmethod)motormix_new, gensym("MotorMix"), /*A_DEFFLOAT,*/ 0); + + class_addmethod(motormix_class, (t_method)motormix_help, gensym("help"), 0); + class_addbang(motormix_class, motormix_bang); + class_addmethod(motormix_class, (t_method)motormix_reset, gensym("reset"), 0); + class_addlist(motormix_class, motormix_return); + + class_sethelpsymbol(motormix_class, gensym("MIDIvice/motormix")); + + ctlin_sym = gensym("#ctlin"); + notein_sym = gensym("#notein"); + + button_setup(); + faderIn_setup(); + faderOut_setup(); + rotary_setup(); + encoder_setup(); + LED_setup(); + + LCDtext_setup(); + LCDgraph_setup(); + seg7_setup(); + + /* we have to send a motormix_ping once before it starts reacting. + * this seems to be a problem with pd, but i don't have hardware to test it right now + */ + outmidi_noteon(x_port>>4,x_port&15,0,0); +} diff --git a/MIDIvice/src/motormix_buttons.txt b/MIDIvice/src/motormix_buttons.txt new file mode 100644 index 0000000..47c4004 --- /dev/null +++ b/MIDIvice/src/motormix_buttons.txt @@ -0,0 +1,374 @@ + +static int LED_sym2id(t_symbol *s) +{ + int id=-1; + + if (s==gensym("1"))id=1; // + + else if (s==gensym("2"))id=2; // + + else if (s==gensym("3"))id=3; // + + else if (s==gensym("4"))id=4; // + + else if (s==gensym("5"))id=5; // + + else if (s==gensym("6"))id=6; // + + else if (s==gensym("7"))id=7; // + + else if (s==gensym("8"))id=8; // + + else if (s==gensym("a"))id=10; + else if (s==gensym("b"))id=11; + else if (s==gensym("c"))id=12; + else if (s==gensym("d"))id=13; + else if (s==gensym("e"))id=14; + else if (s==gensym("f"))id=15; + else if (s==gensym("g"))id=16; + else if (s==gensym("h"))id=17; + else if (s==gensym("i"))id=18;// + + else if (s==gensym("j"))id=19;// + + else if (s==gensym("k"))id=20;// + + else if (s==gensym("l"))id=21;// + + else if (s==gensym("m"))id=22;// + + else if (s==gensym("n"))id=23;// + + else if (s==gensym("o"))id=24;// + + else if (s==gensym("p"))id=25;// + + else if (s==gensym("q"))id=26;// + + else if (s==gensym("r"))id=27;// + + else if (s==gensym("s"))id=28;// + + else if (s==gensym("t"))id=29;// + + else if (s==gensym("u"))id=30;// + + else if (s==gensym("v"))id=31;// + + else if (s==gensym("w"))id=32;// + + else if (s==gensym("x"))id=33;// + + else if (s==gensym("y"))id=34;// + + else if (s==gensym("z"))id=35;// + + else if (s==gensym("0"))id=0;// + + else if (s==gensym("9"))id=9;// + + else if (s==gensym("*"))id=36;// + + else if (s==gensym("="))id=37;// + + else if (s==gensym("/"))id=38;// + + else if (s==gensym("."))id=39;// + + else if (s==gensym("shift")) id=40; + else if (s==gensym("undo")) id=41; + else if (s==gensym("default"))id=42; + else if (s==gensym("all")) id=43; + else if (s==gensym("window")) id=44; + else if (s==gensym("plug-in"))id=45;//... + else if (s==gensym("suspend"))id=46; + else if (s==gensym("auto")) id=47; + + else if (s==gensym("escape")) id=48;// + else if (s==gensym("enter")) id=49; + else if (s==gensym("last")) id=40; + else if (s==gensym("next")) id=51; + else if (s==gensym("rewind")) id=52; + else if (s==gensym("f-fwd")) id=53;// + else if (s==gensym("stop")) id=54; + else if (s==gensym("play")) id=55; + + else if (s==gensym("bank")) id=56; + else if (s==gensym("group")) id=57; + else if (s==gensym("record")) id=58; + else if (s==gensym("functA")) id=59; + else if (s==gensym("write")) id=50; + else if (s==gensym("functB")) id=61; + else if (s==gensym("burn")) id=62; + else if (s==gensym("functC")) id=63; + else if (s==gensym("fx")) id=64;//... + else if (s==gensym("fxbyps")) id=65;//... + else if (s==gensym("effect1"))id=66;//. + else if (s==gensym("eff-1")) id=67;//. + else if (s==gensym("mute")) id=68;//... + else if (s==gensym("s-mute")) id=69;//... + else if (s==gensym("effect2"))id=60;//. + else if (s==gensym("eff-2")) id=71;//. + else if (s==gensym("pre")) id=72;//... + else if (s==gensym("post")) id=73;//... + else if (s==gensym("pre/pst"))id=74;//... + else if (s==gensym("effect3"))id=75;//. + else if (s==gensym("eff-3")) id=76;//. + else if (s==gensym("sel")) id=77;//... + else if (s==gensym("select")) id=77;//... + else if (s==gensym("effect4"))id=78;//. + else if (s==gensym("eff-4")) id=79;//. + + + return id; +} + +static void LED_id2rowcol(int id, int* row, int *col) +{ + *row=-1; + *col=-1; + + if (id==1)*row=0,*col=0; //1 + else if (id==2)*row=0,*col=1; + else if (id==3)*row=0,*col=2; + else if (id==4)*row=0,*col=3; + else if (id==5)*row=0,*col=4; + else if (id==6)*row=0,*col=5; + else if (id==7)*row=0,*col=6; + else if (id==8)*row=0,*col=7; + + else if (id==10)*row=4,*col=0;//a + else if (id==11)*row=4,*col=1; + else if (id==12)*row=4,*col=2; + else if (id==13)*row=4,*col=3; + else if (id==14)*row=4,*col=4; + else if (id==15)*row=4,*col=5; + else if (id==16)*row=4,*col=6; + else if (id==17)*row=4,*col=7; + else if (id==18)*row=3,*col=0;//i + else if (id==19)*row=3,*col=1; + else if (id==20)*row=3,*col=2; + else if (id==21)*row=3,*col=3; + else if (id==22)*row=3,*col=4; + else if (id==23)*row=3,*col=5; + else if (id==24)*row=3,*col=6; + else if (id==25)*row=3,*col=7; + else if (id==26)*row=2,*col=0;//q + else if (id==27)*row=2,*col=1; + else if (id==28)*row=2,*col=2; + else if (id==29)*row=2,*col=3; + else if (id==30)*row=2,*col=4; + else if (id==31)*row=2,*col=5; + else if (id==32)*row=2,*col=6; + else if (id==33)*row=2,*col=7; + else if (id==34)*row=1,*col=0;//y + else if (id==35)*row=1,*col=1; + else if (id==0) *row=1,*col=2; + else if (id==9) *row=1,*col=3; + else if (id==36)*row=1,*col=4; + else if (id==37)*row=1,*col=5; + else if (id==38)*row=1,*col=6; + else if (id==39)*row=1,*col=7; + + else if (id==40)*row=0,*col=8;//shift -- LEFT SIDE + else if (id==41)*row=1,*col=8; + else if (id==42)*row=2,*col=8; + else if (id==43)*row=3,*col=8; + else if (id==44)*row=4,*col=8; + else if (id==45)*row=5,*col=8; + else if (id==46)*row=6,*col=8; + else if (id==47)*row=7,*col=8; + else if (id==48)*row=0,*col=9;//escape -- RIGHT SIDE + else if (id==49)*row=1,*col=9; + else if (id==50)*row=2,*col=9; + else if (id==51)*row=3,*col=9; + else if (id==52)*row=4,*col=9; + else if (id==53)*row=5,*col=9; + else if (id==54)*row=6,*col=9; + else if (id==55)*row=7,*col=9; + else if (id==56)*row=0,*col=10;//left-arrow -- VIEW + else if (id==57)*row=1,*col=10; + else if (id==58)*row=2,*col=10; + else if (id==59)*row=3,*col=10; + else if (id==50)*row=4,*col=10; + else if (id==61)*row=5,*col=10; + else if (id==62)*row=6,*col=10; + else if (id==63)*row=7,*col=10; + else if (id==64)*row=0,*col=11; + else if (id==65)*row=0,*col=11; + else if (id==66)*row=1,*col=11; + else if (id==67)*row=1,*col=11; + else if (id==68)*row=2,*col=11; + else if (id==69)*row=2,*col=11; + else if (id==60)*row=3,*col=11; + else if (id==71)*row=3,*col=11; + else if (id==72)*row=4,*col=11; + else if (id==73)*row=4,*col=11; + else if (id==74)*row=4,*col=11; + else if (id==75)*row=5,*col=11; + else if (id==76)*row=5,*col=11; + else if (id==77)*row=6,*col=11; + else if (id==78)*row=7,*col=11; + else if (id==79)*row=7,*col=11; +} + + +static t_class *LED_class; +typedef struct _LED +{ + t_object x_obj; + + t_float LED; + t_float state; +} t_LED; + +static void LED_float(t_LED *x, t_float f) +{ + int row, col; + int state = x->state; + int offset = 0; + int id = f; + + LED_id2rowcol(id, &row, &col); + + if (id<0)return; + + if (state>0)offset=0x40; + else if (state<0)offset=0x50; + + + if (col<8)offset++; +#if 0 + post("LED: %x %x %x %x", 0x0C, col, 0x2C, row+offset); + post("LED: %d %d %d %d\n", 0x0C, col, 0x2C, row+offset); +#endif + outmidi_controlchange(x_port>>4, x_port&15, 0x0C, col); + outmidi_controlchange(x_port>>4, x_port&15, 0x2C, row+offset); +} + +static void LED_symbol(t_LED *x, t_symbol *s) +{ + LED_float(x, LED_sym2id(s)); +} + +static void LED_bang(t_LED *x) +{ + +} + +static void *LED_new(void) +{ + t_LED *x = (t_LED *)pd_new(LED_class); + + x->LED=-1; + floatinlet_new(&x->x_obj, &x->state); + + x->state=0; + + return (x); +} +static void LED_setup(void) +{ + LED_class = class_new(gensym("motormix_LED"), (t_newmethod)LED_new, + 0, sizeof(t_LED), 0, 0); + class_addcreator((t_newmethod)LED_new, gensym("LED"), 0); + + class_addsymbol(LED_class, LED_symbol); + class_addfloat (LED_class, LED_float); + class_addbang (LED_class, LED_bang); + class_sethelpsymbol(LED_class, gensym("zexy/motormix")); +} + +/* button */ +static t_class *button_class; +typedef struct _button +{ + t_object x_obj; + int o_itsme; // the fader changed + int o_imtouched; // the fader was touched + + t_outlet *o_value; // actual fader-value + t_outlet *o_touch; // 1=touched; 0=released + + int activefader; + int fader; + unsigned char MSB, LSB; +} t_button; + +static void button_touch(t_button *x, unsigned char value, unsigned char control) +{ + int pressed=0; + int MSB=x->MSB; + int LSB=0; + int id=0; + + x->o_imtouched=0; + + if (x->MSB<8){ + if ((value==0x00) || (value==0x40))return; + } + + if (value>=0x40){ + pressed=1; + value-=0x40; + } + + LSB=value; + + post("MSB=%d, LSB=%d", MSB, LSB); + + switch (MSB) { + case 0x08: /* left side */ + id=MSB+40; + break; + case 0x09: /* right side */ + id=MSB+ + break; + case 0x0A: /* VIEW */ + break; + case 0x0B: /* fx */ + break; + default: + if (MSB>0x08)return; + switch (LSB) { + case 0x01: /* 1..8 */ + id=MSB+1; + break; + case 0x05: /* a..h */ + id=MSB+10; + break; + case 0x04: /* i..p */ + id=MSB+18; + break; + case 0x03: /* q..x */ + id=MSB+26; + break; + case 0x02: /* y.. . */ + switch (MSB){ + case 0: case 1: + id=MSB+34; + break; + case 2: + id=0; + break; + case 3: + id=9; + break; + default: + id=MSB+32; + } + break; + default: + return; + } + } + + + outlet_float(x->o_touch, pressed); + outlet_float(x->o_value, id); +} + +static void button_list(t_button *x, t_symbol *s, int argc, t_atom *argv) +{ + unsigned char ctl = atom_getfloatarg(0, argc, argv); + unsigned char val = atom_getfloatarg(1, argc, argv); + // int channel = atom_getfloatarg(2, argc, argv); + + if (x->o_imtouched)button_touch(x, val, ctl); + + if (ctl==0x0f){ + x->o_imtouched=1; + x->MSB=val; + } +} + +static void *button_new() +{ + t_button *x = (t_button *)pd_new(button_class); + + x->o_value=outlet_new(&x->x_obj, &s_float); + x->o_touch=outlet_new(&x->x_obj, &s_float); + + x->o_imtouched = 0; + + pd_bind(&x->x_obj.ob_pd, ctlin_sym); + + return (x); +} +static void button_setup(void) +{ + button_class = class_new(gensym("motormix_button"), (t_newmethod)button_new, + 0, sizeof(t_button), CLASS_NOINLET, A_DEFFLOAT, 0); + class_addcreator((t_newmethod)button_new, gensym("button"), A_DEFFLOAT, 0); + + class_addlist(button_class, button_list); + class_sethelpsymbol(button_class, gensym("zexy/motormix")); +} -- cgit v1.2.1