diff --git a/veejay-current/sendVIMS/COPYING b/veejay-current/sendVIMS/COPYING new file mode 100644 index 00000000..7f87ef8b --- /dev/null +++ b/veejay-current/sendVIMS/COPYING @@ -0,0 +1,340 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 PDP.LICENSE, 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 + + Appendix: 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) 19yy + + 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., 675 Mass Ave, Cambridge, MA 02139, 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) 19yy 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/veejay-current/sendVIMS/ChangeLog b/veejay-current/sendVIMS/ChangeLog new file mode 100644 index 00000000..3dbf0e75 --- /dev/null +++ b/veejay-current/sendVIMS/ChangeLog @@ -0,0 +1,4 @@ +0.1 initial release by Tom +0.1.1 fixed status outlets +0.1.2 fixed selector range (0-600) to match veejay > 0.8 +0.1.4 update veejay >= 0.9.8 diff --git a/veejay-current/sendVIMS/Makefile b/veejay-current/sendVIMS/Makefile new file mode 100644 index 00000000..632e56c3 --- /dev/null +++ b/veejay-current/sendVIMS/Makefile @@ -0,0 +1,37 @@ +all: pd_linux + +include Makefile.defs + +VERSION = 0.1.4 + + +.SUFFIXES: .pd_linux + +pd_linux: sendVIMS.pd_linux selectors.h + + + + + +PD_CFLAGS = -DPD + +.c.pd_linux: + $(CC) $(PD_CFLAGS) $(OPTI_CFLAGS) $(DEBUG_CFLAGS) -DVERSION=\"$(VERSION)\" -o $*.o -c $*.c + $(CC) -export_dynamic -shared -o $*.pd_linux $*.o -lm + strip --strip-unneeded $*.pd_linux + rm $*.o + +clean: + rm -f *.pd_linux + rm -f *~ + +install: + install -m 644 *.pd_* $(PREFIX)/lib/pd/extra + install -m 644 help-*.pd $(PREFIX)/lib/pd/doc/5.reference/ + +dist: clean + rm -rf ../sendVIMS-$(VERSION) + mkdir ../sendVIMS-$(VERSION) + cp -av * ../sendVIMS-$(VERSION) + cd .. && tar vczf sendVIMS-$(VERSION).tar.gz sendVIMS-$(VERSION) + rm -rf ../sendVIMS-$(VERSION) diff --git a/veejay-current/sendVIMS/Makefile.defs b/veejay-current/sendVIMS/Makefile.defs new file mode 100644 index 00000000..75859a8e --- /dev/null +++ b/veejay-current/sendVIMS/Makefile.defs @@ -0,0 +1,3 @@ +CC = cc +PREFIX = /usr/local/ +OPTI_CFLAGS = -O3 -fomit-frame-pointer -ffast-math -funroll-loops diff --git a/veejay-current/sendVIMS/README b/veejay-current/sendVIMS/README new file mode 100644 index 00000000..91cf48a9 --- /dev/null +++ b/veejay-current/sendVIMS/README @@ -0,0 +1,43 @@ +sendVIMS - very simple VeeJay client for pure data + (C) 2002-2004 Niels Elburg + (C) 2004 Tom Schouten + +This is free software covered under the terms of the +GNU GPL. See the file COPYING for details. + +requirements: + veejay-1.4.3 + or latest veejay from SVN (http://veejay.dyne.org) + +pre build (optional): + copy the vims.h file from veejay-current/veejay/vims.h + from veejay's SVN repository + The vims.h is taken from veejay 0.8.1 + + perl parse-vims.pl vims.h + +building: + + +./configure && make && make install + + +'make install' copies these files to your pd directory: + +/lib/pd/extra/sendVIMS.pd_linux +/lib/pd/doc/5.reference/help-sendVIMS.pd + +the default is /usr/local/pd + + + +running: + +if the module is in your pd path it will be loaded automaticly. + + +the status line always has 13 status bytes, depending on the +the playback mode some may or may not be used (-). +0 = off, 1 = on + + diff --git a/veejay-current/sendVIMS/configure b/veejay-current/sendVIMS/configure new file mode 100755 index 00000000..5925382d --- /dev/null +++ b/veejay-current/sendVIMS/configure @@ -0,0 +1,49 @@ +#!/usr/bin/env perl + +# set sefaults for all options +$var{prefix} = "/usr/local/"; +$var{debug} = "no"; + +if ($ENV{CC}) {$var{CC} = $ENV{CC};} else {$var{CC} = "cc";} + +# print valid options +sub print_options { + foreach $key (keys %var){ + print "\t--$key=$var{$key}\n"; + } +} +sub do_help { + print "\navailable options with defaults: \n"; + print_options; + print "\n--enable|disable- is equivalent to --=yes|no\n"; + exit(0); +} + +# override with command line args +while ($a = shift) { + if ($a eq "--help") { do_help; } + elsif ($a =~ m/^--enable-(.+)/) { $var{$1} = "yes"; } + elsif ($a =~ m/^--disable-(.+)/) { $var{$1} = "no"; } + elsif ($a =~ m/^--(.+?)=(.+)/) { $var{$1} = $2; } + else {print "invalid argument ".$a."\n"; do_help;} +} + + +print "generating Makefile.defs\n"; +open CONFIG, ">Makefile.defs"; +sub config {print CONFIG shift; print CONFIG "\n";} + + +config "CC = $var{CC}" ; +config "PREFIX = $var{prefix}" ; + +if ($var{debug} eq "yes"){ + config "DEBUG_CFLAGS = -g -Wall -Werror -W -Wstrict-prototypes -Wno-unused -Wno-parentheses -Wno-switch -g"; +} +else { + config "OPTI_CFLAGS = -O3 -fomit-frame-pointer -ffast-math -funroll-loops"; +} + + + +close CONFIG; diff --git a/veejay-current/sendVIMS/help-sendVIMS.pd b/veejay-current/sendVIMS/help-sendVIMS.pd new file mode 100644 index 00000000..bcff96ca --- /dev/null +++ b/veejay-current/sendVIMS/help-sendVIMS.pd @@ -0,0 +1,89 @@ +#N canvas 44 39 828 878 10; +#X obj 407 24 sendVIMS; +#X msg 469 -84 connect localhost 3490; +#X msg 469 -62 disconnect; +#X text 573 -126 open a video stream ; +#X text 491 25 optional creation arguments: ; +#X text 79 -173 (c) 2004-2006 Niels Elburg & Tom Schouten; +#X text 37 -80 some command modifiers are supported. these can be prepended +to a standard veejay command.; +#X text 63 -41 '+ ' delay for n frames before sending command; +#X text 614 -81 connect to veejay. (no port specified : default); +#X text 493 41 default = localhost 3490; +#X msg 467 -142 + 10 p240 0 1; +#X msg 468 -117 p240 0 1; +#X msg 466 -172 quit; +#X obj 407 101 print status; +#X obj 407 73 spigot; +#X obj 448 49 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 105 71 unpack 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0; +#X floatatom 80 201 5 0 0 0 - - -; +#N canvas 488 217 481 424 aliases 0; +#X text 23 12 All veejay ports are addressable by their symbolic selector +\, which is 'p' plus the number of the port. Some messages have more +readable aliases.; +#X msg 15 141 video.play.forward; +#X msg 15 165 video.play.backward; +#X msg 15 117 video.play.stop; +#X msg 15 65 video.goto.start; +#X msg 270 258 quit; +#X floatatom 263 136 5 0 0 0 - - -; +#X floatatom 263 84 5 0 0 0 - - -; +#X msg 254 98 video.set.frame \$1; +#X msg 254 151 video.set.speed \$1; +#X obj 15 279 s \$0-0; +#X obj 16 361 r \$0-0; +#X obj 16 382 outlet; +#X obj 254 287 s \$0-0; +#X msg 15 89 video.goto.end; +#X msg 270 236 aliases; +#X text 331 235 print all aliases; +#X connect 1 0 10 0; +#X connect 2 0 10 0; +#X connect 3 0 10 0; +#X connect 4 0 10 0; +#X connect 5 0 13 0; +#X connect 6 0 9 0; +#X connect 7 0 8 0; +#X connect 8 0 13 0; +#X connect 9 0 13 0; +#X connect 11 0 12 0; +#X connect 14 0 10 0; +#X connect 15 0 13 0; +#X restore 470 -24 pd aliases; +#X text 38 -143 the object maps pd messages to veejay commands. the +veejay ports are accessed by a symbol composed of the letter 'p' followed +by the port number. see the veejay documentation for more info. (or +run 'veejay -u | less'); +#X text 556 -23 <- a list of aliases for the p port names; +#X floatatom 112 218 5 0 0 0 - - -; +#X floatatom 131 238 5 0 0 0 - - -; +#X text 182 123 Status outlets. The outlet values depend on the playback +mode. Properties like first and last frame \, looptype and trickplay +speed are n/a when playing in plain (2) or stream mode (1). Outlet +0 = elapsed render time (in ms) 1 = frame number 2 = playback mode +(0=sample \, 1=stream \, 2=plain) 3 = identifier (sample or stream) +4 = process effect chain (0=off \, 1=on) 5 = first frame of sample +6 = last frame of sample 7 = trickplay speed 8 = looptype (0=none \, +1=normal \, 2=bounce) 9 = recording (0=no \, 1=yes) 10 = frames to +record 11 = frames left to record (counts to 0) 12 = number of samples +or streams 13 = in position of sample 14 = out position of sample 15 += select fx entry (0=first \, 19=last) 16 = total number of samples +and streams 17 = cache consumed (0-100); +#X text 9 -189 sendVIMS: an interface to veejay-0.9.8 internal message +system; +#X msg 91 -194; +#X connect 0 0 14 0; +#X connect 0 0 16 0; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 0 0; +#X connect 14 0 13 0; +#X connect 15 0 14 1; +#X connect 16 0 17 0; +#X connect 16 1 21 0; +#X connect 16 2 22 0; +#X connect 18 0 0 0; diff --git a/veejay-current/sendVIMS/parse-vims.pl b/veejay-current/sendVIMS/parse-vims.pl new file mode 100755 index 00000000..bfe17830 --- /dev/null +++ b/veejay-current/sendVIMS/parse-vims.pl @@ -0,0 +1,17 @@ +#!/usr/bin/env perl + +# feed this script with vims.h to generate selectors.h + +print "// selector.h\n"; +print "// generated from vims.h\n"; +while (<>){ + if (m/VIMS_(\S+)\s*=\s*(\d+)\s*,/) { + $id = $2; # numeric id + $tag = lc $1; # convert to lower case + $tag =~ s/_/\./g; # pd-ify + + $nid = int( $id ); + + print "SELECTOR(\"" . $tag . "\", " . $id . ");\n" if $nid <= 400 or $nid >= 500; + } +} diff --git a/veejay-current/sendVIMS/sendVIMS.c b/veejay-current/sendVIMS/sendVIMS.c new file mode 100644 index 00000000..cba2f726 --- /dev/null +++ b/veejay-current/sendVIMS/sendVIMS.c @@ -0,0 +1,562 @@ +/* sendVIMS - very simple client for VeeJay + * (C) 2002-2004 Niels Elburg + * + * puredata module by Tom Schouten + * + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "m_pd.h" + + +#define POLL_INTERVAL (1.0f) // agressive polling +#define MAX_MSG 256 // maximum message size (bytes) + +#define QUEUE_SIZE (1<<8) // message queue size (power of 2) +#define QUEUE_MASK (QUEUE_SIZE - 1) + + +// some symbols used in comm +// (gensym not thread safe) +static t_symbol *s_disconnect = 0; +static t_symbol *s_veejay = 0; + +static t_symbol *selector[602]; + +/* DATA STRUCTURES */ + +typedef struct { + struct hostent *he; + struct sockaddr_in server_addr; + int handle; +} veejay_t; + + +typedef struct { + int delay; // nb of frames to delay this msg + char msg[MAX_MSG - sizeof(int)]; +} vj_msg_t; + +typedef struct { + t_symbol *selector; + int argc; + t_atom argv[(MAX_MSG / sizeof(t_atom)) - sizeof(t_symbol *) - sizeof(int)]; +} pd_msg_t; + + +typedef struct { + void *queue[QUEUE_SIZE]; + unsigned int read; + unsigned int write; +} queue_t; + +typedef struct { + t_object obj; + t_outlet *outlet; + + /* network */ + t_symbol *hostname; + int port; + veejay_t status_socket; + veejay_t command_socket; + + /* message queues */ + queue_t vq; /* pd -> veejay */ + queue_t pq; /* veejay -> pd */ + t_clock *clock; // polling clock + + /* thread */ + pthread_t thread; + jmp_buf errorhandler; + + /* obj status */ + int connected; // socket connected + int run; // communication thread running + +} sendVIMS_t; + + + + + + +/* CODE */ + + +/* messages */ + +// free message (pd_msg_t and vj_msg_t) +void msg_free(void *m){ + if (!m) return; + free(m); +} + +// map symbolic selector to numeric veejay id +int selector_map(t_symbol *s){ + int i; + + // map p syms + if (s->s_name[0] == 'p'){ + return atoi(s->s_name + 1); + } + + // check the stuff from selectors.h + for (i=0; i<602; i++){ + if (s == selector[i]) return i; + } + + // fallthrough + post("sendVIMS: selector %d not recognized", s->s_name); + return 0; +} + +void setup_selectors(void){ + memset(selector, 0, sizeof(selector)); +#define SELECTOR(name, id) selector[id] = gensym(name) +#include "selectors.h" +#undef SELECTOR +} + + + + +// create a pd message from a veejay message +// will be zero terminated (extra check) + + +pd_msg_t *pd_msg_new(char *msg){ + int i, parsed, size = -1; + char *body = msg + 5; + pd_msg_t *m = 0; + int s[24]; + int n = 0; + + /* get 24 ints */ + n = sscanf(body, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + s+0, s+1, s+2, s+3, + s+4, s+5, s+6, s+7, + s+8, s+9, s+10, s+11, + s+12, s + 13, s + 14, s + 15, s + 16, s + 17, s + 18, s + 19, s + 20, s + 21, s + 22, s + 23); + if (n != 24) goto error; + + /* create msg */ + m = malloc(sizeof(*m)); + m->selector = s_veejay; // not used + m->argc = n; + for(i=0; iargv + i, (float)s[i]); + return m; + + error: + msg_free(m); + post("Parsed only %d out of %d status outlets", n,20 ); + return 0; + +} + + +// create veejay message from a pd message +vj_msg_t *vj_msg_new(t_symbol *selector, int argc, t_atom *argv){ + vj_msg_t *m = malloc(sizeof(*m)); + char *body, *c = m->msg; + m->delay = 0; + m->msg[0] = 0; + + // the format of a message is simple + // if the first argument is a "+" the next argument (float) + // will be interpreted as a frame delay + + if (selector == gensym("+")){ + + // get delay + if (!argc) goto error; + if (argv->a_type != A_FLOAT) goto error; + m->delay = (int)argv->a_w.w_float; + argc--, argv++; + + // get real selector + if (!argc) goto error; + if (argv->a_type != A_SYMBOL) goto error; + selector = argv->a_w.w_symbol; + argc--, argv++; + } + + // the rest is interpreted as a veejay message + + // leave space for data header + c += sprintf(c, "V000D"); body = c; + + // map selector + c += sprintf(c, "%03d:", selector_map(selector)); + + // print args + while (argc){ + switch(argv->a_type){ + case A_SYMBOL: + c += sprintf(c, "%s", argv->a_w.w_symbol->s_name); + if(argc > 1) + c += sprintf(c, "%s", " "); + + break; + case A_FLOAT: + c += sprintf(c, "%d", (int)argv->a_w.w_float); + if(argc > 1) + c += sprintf(c, "%s", " "); + + break; + default: + goto error; + } + argc--,argv++; + } + c += sprintf(c, ";"); + sprintf(m->msg, "V%03d", strlen(body)); // fill header + m->msg[4] = 'D'; + return m; + + error: + post("sendVIMS: parse error"); + msg_free(m); + return 0; +} + + + +/* queues */ + + +void queue_write(queue_t *x, void *m){ + int messages = (x->write - x->read) & QUEUE_MASK; + if (messages == QUEUE_MASK){ + post("sendVIMS: message queue full: ignoring command"); + free(m); + } + else { + x->queue[x->write] = m; + x->write = (x->write + 1) & QUEUE_MASK; + } +} + +void *queue_read(queue_t *x){ + void *msg = 0; + int messages = (x->write - x->read) & QUEUE_MASK; + if (!messages) return 0; + else { + msg = x->queue[x->read]; + x->read = (x->read + 1) & QUEUE_MASK; + } + return msg; +} + +void queue_init(queue_t *x){ + memset(x, 0, sizeof(queue_t)); +} + + +/* pd object */ + + +// queue pd -> veejay +void sendVIMS_vq_write(sendVIMS_t *x, vj_msg_t *m){ queue_write(&x->vq, (void *)m); } +vj_msg_t *sendVIMS_vq_read(sendVIMS_t *x){ return (vj_msg_t *)queue_read(&x->vq); } + +// queue veejay -> pd +void sendVIMS_pq_write(sendVIMS_t *x, pd_msg_t *m){ queue_write(&x->pq, (void *)m); } +pd_msg_t *sendVIMS_pq_read(sendVIMS_t *x){ return (pd_msg_t *)queue_read(&x->pq); } + + +// connect a veejay port +static int vj_connect(veejay_t *v, char *name, int port_id ) { + v->he = gethostbyname(name); + v->handle = socket( AF_INET, SOCK_STREAM, 0); + v->server_addr.sin_family = AF_INET; + v->server_addr.sin_port = htons(port_id); + v->server_addr.sin_addr = *( (struct in_addr*) v->he->h_addr); + if(connect(v->handle, (struct sockaddr*) + &v->server_addr,sizeof(struct sockaddr))==-1) return -1; /* error */ + return 0; +} + + +// send disconnect command from thread +static void sendVIMS_disconnect_from_thread(sendVIMS_t *x){ + pd_msg_t *m = malloc(sizeof(*m)); + m->selector = s_disconnect; + m->argc = 0; + sendVIMS_pq_write(x, m); // send close command + longjmp(x->errorhandler, -1); // jump to thread error handler +} + +// read one chunk of status information +static pd_msg_t *sendVIMS_status(sendVIMS_t *x) { + int gotbytes = 0; + int wantbytes = 0; + pd_msg_t *m = 0; + char buf[100]; + int size = -1; + + // read header + wantbytes = 5; + gotbytes = recv(x->status_socket.handle, buf, wantbytes, 0); + if (wantbytes != gotbytes) goto error; + if (1 != sscanf(buf, "V%03dD", &size)) goto proto_error; + + // read body + wantbytes = size; + gotbytes = recv(x->status_socket.handle, buf + 5, wantbytes, 0); + if (wantbytes != gotbytes) goto error; + + // return a pd message + return pd_msg_new(buf); + + error: + if (gotbytes > 0) { + post("sendVIMS: message truncated: wanted %d bytes, got %d", + wantbytes, gotbytes); + } + else if (gotbytes == 0) { + post("sendVIMS: remote end closed connection"); + } + else { + perror("sendVIMS"); + } + return 0; + + proto_error: + post("sendVIMS: protocol error: not a valid veejay header."); + return 0; + +} + +// flush and get status messages +static void sendVIMS_flush(sendVIMS_t *x, int frames) { + pd_msg_t *m; + int n = 0; + while (frames--){ + m = sendVIMS_status(x); // get status message + if (!m) { + // disconnect on error + sendVIMS_disconnect_from_thread(x); + return; + } + sendVIMS_pq_write(x, m); // write it to queue + } +} + +// send a raw message to veejay +static void sendVIMS_send(sendVIMS_t *x, char *buf) { + + //post("sending msg: '%s'", buf); + if ((send(x->command_socket.handle, buf, strlen(buf), 0)) == -1) + { /* send the command */ + perror("sendVIMS: can't send: "); + sendVIMS_disconnect_from_thread(x); + } +} + + +// init struct with defaults +static void sendVIMS_init(sendVIMS_t *x){ + memset(&x->status_socket, 0, sizeof(veejay_t)); + memset(&x->command_socket, 0, sizeof(veejay_t)); + queue_init(&x->vq); + queue_init(&x->pq); + x->hostname = gensym("localhost"); + x->port = 3490; + x->connected = 0; + x->run = 0; +} + +// disco vj +static void sendVIMS_disconnect(sendVIMS_t *x){ + + void *m = 0; + + // stop thread + if (x->run){ + x->run = 0; + pthread_join(x->thread, 0); + } + + // close socket + if (x->connected){ + close(x->status_socket.handle); + close(x->command_socket.handle); + x->connected = 0; + post("sendVIMS: disconnected."); + } + + // clear vq & pq + while (m = sendVIMS_vq_read(x)) msg_free(m); + while (m = sendVIMS_pq_read(x)) msg_free(m); +} + +// veejay command thread +static void sendVIMS_thread(sendVIMS_t *x){ + vj_msg_t *m; + + /* install error handler: + just terminate thread (wait for join) */ + if (setjmp(x->errorhandler)) return; + + /* sync to veejay */ + while (x->run){ + + /* perform all commands in vq */ + while (m = sendVIMS_vq_read(x)){ + sendVIMS_flush(x, m->delay); // sync to next frame + sendVIMS_send(x, m->msg); // send command + } + + /* sync to next frame */ + sendVIMS_flush(x, 1); + } +} + + + +// co vj +static void sendVIMS_connect(sendVIMS_t *x, t_symbol *host, t_float fport){ + pthread_attr_t attr; + int port = (int)fport; + if (!port) port = 3490; // default veejay port + + /* connect */ + sendVIMS_disconnect(x); // disco first + if ((vj_connect(&x->command_socket, host->s_name, port)) == -1){ + post("sendVIMS: can't connect to veejay at %s:%d (command port)", host->s_name, port); + goto error; + } + if ((vj_connect(&x->status_socket, host->s_name, port+1)) == -1){ + post("sendVIMS: can't connect to veejay at %s:%d (status port)", host->s_name, port); + goto error; + } + x->connected = 1; + + /* start thread */ + x->run = 1; + pthread_attr_init(&attr); + pthread_attr_setschedpolicy(&attr, SCHED_OTHER); + pthread_create(&x->thread, &attr, (void* (*)(void *))sendVIMS_thread, x); + + /* done */ + post("sendVIMS: connected to %s:%d", host->s_name, port); + return; + + error: + sendVIMS_disconnect(x); + return; + +} + + +static void sendVIMS_reconnect(sendVIMS_t *x){ + sendVIMS_disconnect(x); + sendVIMS_connect(x, x->hostname, x->port); +} + +// pd input message handler +static void sendVIMS_anything(sendVIMS_t *x, t_symbol *selector, int argc, t_atom *argv){ + vj_msg_t *m = 0; + if (!x->connected) post("sendVIMS: not connected to veejay."); + else if (m = vj_msg_new(selector, argc, argv)) sendVIMS_vq_write(x, m); +} + + +t_class *sendVIMS_class = 0; + +static void sendVIMS_free(sendVIMS_t *x){ + sendVIMS_disconnect(x); + clock_free(x->clock); +} + +// pd queue poller +static void sendVIMS_tick(sendVIMS_t *x){ + pd_msg_t *m; + clock_delay(x->clock, POLL_INTERVAL); + + while (m = sendVIMS_pq_read(x)){ + if (m->selector == s_veejay){ + outlet_anything(x->outlet, gensym("list"), m->argc, m->argv); + } + else if (m->selector == s_disconnect){ + sendVIMS_disconnect(x); + } + msg_free(m); + } +} + +static void *sendVIMS_new(t_symbol *moi, int argc, t_atom *argv){ + sendVIMS_t *x = (sendVIMS_t *)pd_new(sendVIMS_class); + sendVIMS_init(x); + + x->clock = clock_new(x, (t_method)sendVIMS_tick); + x->outlet = outlet_new(&x->obj, gensym("anything")); + + if ((argc >= 1) && argv[0].a_type == A_SYMBOL){ + x->hostname = argv[1].a_w.w_symbol; + } + if ((argc >= 2) && argv[1].a_type == A_FLOAT){ + x->port = (int)argv[1].a_w.w_float; + } + sendVIMS_connect(x, x->hostname, x->port); + + sendVIMS_tick(x); // start clock + + return (void *)x; +} + +static void post_selectors(void){ + int i; + for (i=0; i<600; i++){ + if (selector[i]){ + post("p%03d = %s", i, selector[i]->s_name); + } + } +} + +void sendVIMS_setup(void){ + post("sendVIMS: version " VERSION); + post("sendVIMS: (c) 2004-2006 Niels Elburg & Tom Schouten"); + post("sendVIMS: assuming veejay-0.9.8"); + + s_disconnect = gensym("disconnect"); + s_veejay = gensym("veejay"); + setup_selectors(); + + sendVIMS_class = class_new(gensym("sendVIMS"), (t_newmethod)sendVIMS_new, + (t_method)sendVIMS_free, sizeof(sendVIMS_t), 0, A_GIMME, 0); + class_addanything(sendVIMS_class, (t_method)sendVIMS_anything); + class_addmethod(sendVIMS_class, (t_method)sendVIMS_reconnect, gensym("reconnect"), 0); + class_addmethod(sendVIMS_class, (t_method)sendVIMS_disconnect, gensym("disconnect"), 0); + class_addmethod(sendVIMS_class, (t_method)sendVIMS_connect, gensym("connect"), A_SYMBOL, A_DEFFLOAT, 0); + + class_addmethod(sendVIMS_class, (t_method)post_selectors, gensym("aliases"), 0); + +}