diff --git a/branches/V-1.5.3/sendVIMS/COPYING b/branches/V-1.5.3/sendVIMS/COPYING new file mode 100644 index 00000000..7f87ef8b --- /dev/null +++ b/branches/V-1.5.3/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/branches/V-1.5.3/sendVIMS/ChangeLog b/branches/V-1.5.3/sendVIMS/ChangeLog new file mode 100644 index 00000000..3dbf0e75 --- /dev/null +++ b/branches/V-1.5.3/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/branches/V-1.5.3/sendVIMS/Makefile b/branches/V-1.5.3/sendVIMS/Makefile new file mode 100644 index 00000000..632e56c3 --- /dev/null +++ b/branches/V-1.5.3/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/branches/V-1.5.3/sendVIMS/Makefile.defs b/branches/V-1.5.3/sendVIMS/Makefile.defs new file mode 100644 index 00000000..75859a8e --- /dev/null +++ b/branches/V-1.5.3/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/branches/V-1.5.3/sendVIMS/README b/branches/V-1.5.3/sendVIMS/README new file mode 100644 index 00000000..bc48f1c6 --- /dev/null +++ b/branches/V-1.5.3/sendVIMS/README @@ -0,0 +1,47 @@ + +#2010: untested against 1.6.0 + + +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/branches/V-1.5.3/sendVIMS/configure b/branches/V-1.5.3/sendVIMS/configure new file mode 100755 index 00000000..5925382d --- /dev/null +++ b/branches/V-1.5.3/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/branches/V-1.5.3/sendVIMS/help-sendVIMS.pd b/branches/V-1.5.3/sendVIMS/help-sendVIMS.pd new file mode 100644 index 00000000..bcff96ca --- /dev/null +++ b/branches/V-1.5.3/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/branches/V-1.5.3/sendVIMS/parse-vims.pl b/branches/V-1.5.3/sendVIMS/parse-vims.pl new file mode 100755 index 00000000..bfe17830 --- /dev/null +++ b/branches/V-1.5.3/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/branches/V-1.5.3/sendVIMS/sendVIMS.c b/branches/V-1.5.3/sendVIMS/sendVIMS.c new file mode 100644 index 00000000..2bbd1a17 --- /dev/null +++ b/branches/V-1.5.3/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 %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, s + 24, s + 25, s + 26); + if (n != 27) 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); + +} diff --git a/branches/V-1.5.3/veejay-client/AUTHORS b/branches/V-1.5.3/veejay-client/AUTHORS new file mode 100644 index 00000000..96df44f6 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/AUTHORS @@ -0,0 +1,21 @@ +Tim Philipp Müller + (CellRendererSpin 15 minute hack - good enough) + +Matthijs v. Henten : + Glade-2 interface design + Icon/picture design + +Thomas Reinhold + Samplebank + +Dursun Koca + Veejay Logo (V) design + +Niels Elburg + Lead programming + +Contributions by: + Toni < oc2pus@arcor.de > + (making gveejay happen on GTK 2.4, veejay.spec file) + + diff --git a/branches/V-1.5.3/veejay-client/COPYING b/branches/V-1.5.3/veejay-client/COPYING new file mode 100644 index 00000000..d60c31a9 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/COPYING @@ -0,0 +1,340 @@ + 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. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/branches/V-1.5.3/veejay-client/ChangeLog b/branches/V-1.5.3/veejay-client/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/branches/V-1.5.3/veejay-client/Makefile.am b/branches/V-1.5.3/veejay-client/Makefile.am new file mode 100644 index 00000000..bbe09457 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/Makefile.am @@ -0,0 +1,179 @@ +# Process with automake to produce Makefile.in +SUBDIRS = src + +EXTRA_DIST = \ + autogen.sh\ + depcomp \ + cpuinfo.sh \ + autogen.sh \ + debian/copyright \ + debian/changelog \ + debian/control \ + debian/rules \ + share/bg.png \ + share/bg_black.png \ + share/bg_blue.png \ + share/bg_green.png \ + share/bg_grey.png \ + share/bg_red.png \ + share/bg_yellow.png \ + share/blackwhite.rc \ + share/button_back.png \ + share/button_bounce.png \ + share/button_dec.png \ + share/button_down.png \ + share/button_fbw.png \ + share/button_ffw.png \ + share/button_gotoend.png \ + share/button_gotostart.png \ + share/button_inc.png \ + share/button_loop.png \ + share/button_looponce.png \ + share/button_mini_decrement.png \ + share/button_mini_increment.png \ + share/button_next.png \ + share/button_pause.png \ + share/button_play.png \ + share/button_playmode.png \ + share/button_prev.png \ + share/button_rand.png \ + share/button_reverse.png \ + share/button_right.png \ + share/button_skip.png \ + share/button_skull.png \ + share/button_text.png \ + share/button_up.png \ + share/fx_entry_off.png \ + share/fx_entry_on.png \ + share/gveejay-default.rc \ + share/gveejay.glade \ + share/gveejay.rc \ + share/gveejay.reloaded.glade \ + share/gveejay.reloaded.glade.bak \ + share/gveejay.reloaded.gladep \ + share/gveejay.reloaded.gladep.bak \ + share/gveejay.reloaded.glade~ \ + share/high_contrast.rc \ + share/icon_apply.png \ + share/icon_berserk.png \ + share/icon_bezerk.png \ + share/icon_bounce.png \ + share/icon_bug.png \ + share/icon_bundle.png \ + share/icon_cache.png \ + share/icon_clear.png \ + share/icon_clearall.png \ + share/icon_color.png \ + share/icon_connect.png \ + share/icon_copy.png \ + share/icon_crop.png \ + share/icon_cut.png \ + share/icon_disconnect.png \ + share/icon_fadein.png \ + share/icon_fadeout.png \ + share/icon_jack.png \ + share/icon_keybind.png \ + share/icon_keydetach.png \ + share/icon_keyframe.png \ + share/icon_launch.png \ + share/icon_loop.png \ + share/icon_looponce.png \ + share/icon_macroclear.png \ + share/icon_macropause.png \ + share/icon_macroplay.png \ + share/icon_macrorec.png \ + share/icon_mask.png \ + share/icon_minus.png \ + share/icon_new.png \ + share/icon_noloop.png \ + share/icon_open.png \ + share/icon_openlist.png \ + share/icon_openstream.png \ + share/icon_osd.png \ + share/icon_paste.png \ + share/icon_plarge.png \ + share/icon_playmode.png \ + share/icon_plus.png \ + share/icon_psmall.png \ + share/icon_question.png \ + share/icon_record.png \ + share/icon_recordstop.png \ + share/icon_recstop.png \ + share/icon_refresh.png \ + share/icon_render.png \ + share/icon_save.png \ + share/icon_saveas.png \ + share/icon_screenshot.png \ + share/icon_send.png \ + share/icon_skull.png \ + share/icon_stream.png \ + share/icon_trash.png \ + share/icon_video.png \ + share/knob.png \ + share/reloaded_classic.glade \ + share/smooth.rc \ + share/sync.png \ + share/veejay-icon.png \ + share/veejay-logo-small.png \ + share/veejay-logo.png \ + gveejay-paths.sh.in + +DISTCLEANFILES = \ + confdefs.h \ + config.cache \ + config.status \ + config.log \ + gveejay-paths.h + + +MAINTAINERCLEANFILES = \ + compile \ + depcomp \ + install-sh \ + missing \ + mkinstalldirs \ + Makefile.in \ + aclocal.m4 \ + config.guess \ + config.h.in \ + config.sub \ + configure \ + ltmain.sh \ + stamp-h.in + +## .glade files must be in same directory as pixmaps ?!! +install-data-local: + @$(NORMAL_INSTALL) + if test -d $(srcdir)/share; then \ + $(mkinstalldirs) $(DESTDIR)$(pkgdatadir); \ + for dialog in $(srcdir)/share/*; do \ + if test -f $$dialog; then \ + $(INSTALL_DATA) $$dialog $(DESTDIR)$(pkgdatadir); \ + fi \ + done \ + fi; + + + +gveejay-path.h: gveejay-paths.sh + @sh $< > $@.tmp ; + if cmp -s $@.tmp $@; then + rm $@.tmp; + else + mv $@.tmp $@ ; echo updated gveejay-paths.h; + fi + +dist-hook: + rm -f $(distdir)/gveejay-paths.sh + +## make rpms +rpm: Makefile + $(MAKE) dist + rpmbuild -ta --clean $(PACKAGE)-$(VERSION).tar.gz + +## make debs +deb: Makefile dist + -chmod -R +w $(PACKAGE)-$(VERSION) + rm -rf $(PACKAGE)-$(VERSION) + tar xzf $(PACKAGE)-$(VERSION).tar.gz + cd $(PACKAGE)-$(VERSION); dpkg-buildpackage -rfakeroot diff --git a/branches/V-1.5.3/veejay-client/NEWS b/branches/V-1.5.3/veejay-client/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/branches/V-1.5.3/veejay-client/README b/branches/V-1.5.3/veejay-client/README new file mode 100644 index 00000000..39060d3a --- /dev/null +++ b/branches/V-1.5.3/veejay-client/README @@ -0,0 +1,113 @@ + + ~== + ~==== + :... ~~==== + :...... ~~~~==== + :.....: ~~~~==== + :...... -~~~~=== + :....... --~~~~~== + :....... ::~~~~~~= + :...... "::~~~~== + :....., :::~~~=== + :..... =::~~~~=== + :...... :::~~~==== + ....... ::~~~~~=== + ....... :::~~~~~~== + ...... ~::~~~~~~== + ...... |::~~~=| + ..... :::|:~==| + ..::: |:=|||==+ + ., :., :|||?||+= + ..::,,.: :||=~=.|| + ,...::,,, |~:=|||||+| + :..,:::||||~~~====++ + ,:,,,:::~~~~~===++++ Reloaded + ,::::~~~====++++ + ~~~~~===+++++ version 1.4.x + ~~===+++++++: + N=++++++++++ Nov. 2008. + +++++++++ + ++++:::: + ::::: + || + + + :: Reloaded, a graphical interface for Veejay :: + + + FEATURE OVERVIEW + + +General: + + # Thin client (TCP/IP) + # MIDI support (auto learning) + # Slick interface designed for live performing + # Tracks multiple veejay servers + +Install +======= + +See file 'INSTALL' + +See doc/Howto_Compile.html +See doc/Howto_Compile_on_Ubuntu.html + +Documentation +============= + +See source code. + +Running +======= + +$ reloaded + + +To use a midi controller with veejay you must connect +the veejay's sequencer port to the MIDI controller port. +There is a utility 'aconnect' (comes with ALSA) that does this. + +1. List inputs (midi keyboards) + $ aconnect -i + + client 129: 'Virtual Keyboard' [type=user] + + +2. List outputs (Veejay) + $ aconnect -o + + client 128: 'Veejay' [type=user] + + +3. Connect the ports + + $ aconnect 129 128 + + +4. Launch reloaded + + + +Know bugs +========= +- Multitracker crashes when using very high resolution video + + + + +About +===== + +GveejayReloaded is a client for veejay. As long as veejay (the server) +is running, you can connect and disconnect from it with reloaded. + + + + + + + + + + diff --git a/branches/V-1.5.3/veejay-client/autogen.sh b/branches/V-1.5.3/veejay-client/autogen.sh new file mode 100755 index 00000000..ba7e3840 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/autogen.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + + +autoreconf -v -f -i diff --git a/branches/V-1.5.3/veejay-client/configure.ac b/branches/V-1.5.3/veejay-client/configure.ac new file mode 100644 index 00000000..ed302e6a --- /dev/null +++ b/branches/V-1.5.3/veejay-client/configure.ac @@ -0,0 +1,703 @@ +dnl Process this file with autoconf to produce a configure script. +dnl AC_INIT +AC_INIT([reloaded],[1.5.3],[nwelburg@gmail.com]) +AC_PREREQ(2.57) +AC_CONFIG_SRCDIR([src/gveejay.c]) + +RELOADED_MAJOR_VERSION=1 +RELOADED_MINOR_VERSION=5 +RELOADED_MICRO_VERSION=2 +RELOADED_VERSION=$VEEJAY_MAJOR_VERSION.$VEEJAY_MINOR_VERSION.$VEEJAY_MICRO_VERSION +RELOADED_CODENAME="Reloaded - build $RELOADED_MAJOR_VERSION $RELOADED_MINOR_VERSION $RELOADED_MICRO_VERSION" +AC_CONFIG_HEADERS([config.h]) + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE([1.7]) +AM_MAINTAINER_MODE +AM_INIT_AUTOMAKE([dist-bzip2]) + +AC_DEFINE(HAVE_CONFIG_H,1,[Include config.h]) +# libtool versioning +LT_RELEASE=$RELOADED_MAJOR_VERSION.$RELOADED_MINOR_VERSION.$RELOADED_MICRO_VERSION +LT_CURRENT=$RELOADED_MICRO_VERSION +LT_REVISION=$RELOADED_MICRO_VERSION +LT_AGE=$RELOADED_MICRO_VERSION +AC_SUBST(LT_RELEASE) +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +AC_SUBST(LT_AGE) + +dnl kill CFLAGS +CFLAGS="" +AC_ARG_ENABLE(strict, + AC_HELP_STRING([--enable-strict], + [Compile in paranoia assertion checking])) +AC_ARG_ENABLE(debug, + AC_HELP_STRING([--enable-debug], + [Compile in debugging information])) +AC_ARG_ENABLE(profile, + AC_HELP_STRING([--enable-profiling], + [Compile in profiling information])) +AC_ARG_ENABLE(compile-warnings, + AC_HELP_STRING([--enable-compile-warnings], + [Turn on compiler warnings.])) +AC_ARG_ENABLE(warnings_as_errors, + AC_HELP_STRING([--enable-warnings_as_errors], + [Compiler warnings are errors.])) +AC_ARG_ENABLE(simd-accel, + AC_HELP_STRING([--enable-simd-accel], + [use SIMD multimedia instructions such as MMX, AltiVec, etc.if possible])) +AC_ARG_WITH(extra-cflags, + AC_HELP_STRING([--with-extra-cflags=flags], + [Options to be added to CFLAGS (optional)])) +AC_ARG_WITH(pixbuf, + AC_HELP_STRING([--without-pixbuf], [Do not use GDK pixbuf]), + [], [with_pixbuf=yes]) + +AC_GNU_SOURCE + +dnl Initialize libtool +AC_PROG_LIBTOOL + +dnl Checks for programs. +AC_PROG_AWK +AC_PROG_CC +AM_PROG_CC_STDC +AC_PROG_YACC +AM_PROG_LEX +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_LN_S +AC_C_BIGENDIAN +AC_C_CONST +AC_C_INLINE +AC_SYS_LARGEFILE + +dnl configure AS and ASFLAGS... +AM_PROG_AS + +AC_CHECK_HEADERS([fenv.h stdint.h inttypes.h sys/types.h alloca.h]) + +dnl AX_PREFIXED_DEFINE([RELOADED], [HAVE_STDINT_H]) +dnl AX_PREFIXED_DEFINE([RELOADED], [HAVE_INTTYPES_H]) + +AC_CHECK_FUNCS([posix_memalign memalign fmax lround pow bzero gettimeofday memset mmap strndup strstr strncasecmp]) +AC_CHECK_FUNCS([sched_get_priority_max]) +AC_CHECK_FUNCS([select socket getpagesize memcpy]) + +AC_CHECK_FUNC(getopt_long, + [AC_DEFINE(HAVE_GETOPT_LONG, 1, [long getopt support])], + [ # FreeBSD and BSD/OS have a gnugetopt library for this: + AC_CHECK_LIB([gnugetopt], [getopt_long], + [AC_DEFINE(HAVE_GETOPT_LONG, 1, + [long getopt support]) + LIBGETOPT_LIB="-lgnugetopt"]) + ]) + +AC_CHECK_SIZEOF([int]) +AC_CHECK_SIZEOF([long int]) +AC_CHECK_SIZEOF([size_t]) +AC_CHECK_SIZEOF([float]) + + + +AC_SUBST(LIBGETOPT_LIB) + +AC_TYPE_SIGNAL + +AC_MSG_NOTICE([The host is $host $host_cpu $host_vendor $host_os .]) + +case $host in + *-*-linux*) + AC_CHECK_HEADER(linux/version.h, + [have_linux=true + AC_DEFINE(HAVE_LINUX,,[Linux platform]) + ], + [AC_MSG_ERROR([version.h not found - please install the linux kernel headers]) + ]) + LIBM_LIBS="-lm" + ;; + *-apple-darwin*) + AC_DEFINE(HAVE_DARWIN,,[MAC OS X Darin]) + dnl OS-X/Darwin needs no-cpp-precomp + CFLAGS="$CFLAGS -no-cpp-precomp" + have_darwin=true + LIBM_LIBS="" + ;; + *) + AC_MSG_WARN([Alien platform - Good Luck!]) + LIBM_LIBS="" + ;; +esac + + +dnl ====== check for PKG_CONFIG_PATH +if test x"$PKG_CONFIG_PATH" = x ; then + AC_MSG_NOTICE([The PKG_CONFIG_PATH variable was not set]) + AC_MSG_NOTICE([You should set it to the directories that contain the .pc files]) + AC_MSG_ERROR([Abort]) +fi + + +AC_SUBST(LIBM_LIBS) + +dnl ********************************************************************* +dnl Check for the pthread lib +dnl +AC_SUBST(PTHREAD_LIBS) +have_pthread=false +AC_CHECK_LIB(pthread, pthread_create, + [ PTHREAD_LIBS="-lpthread" + AC_DEFINE(HAVE_LIBPTHREAD,,[Compiling with pthread library]) + have_pthread=true ],,) + +AC_CHECK_FUNC(pthread_attr_getstacksize, + [ + AC_DEFINE(HAVE_PTHREADSTACKSIZE,,[Using pthread stack size]) + ] ) + + +have_alsa=false +AC_CHECK_LIB( asound, snd_seq_open, + [ + AC_DEFINE( HAVE_ALSA,1, [Whether or not we have alsa]) + ALSA_LIBS="-lasound" + AC_SUBST(ALSA_LIBS) + have_alsa=true ],,) + +AC_CHECK_HEADER(alsa/asoundlib.h,,[AC_MSG_ERROR([alsa/asoundlib.h not found - please install the alsa header])] ) + +have_dl_dlopen=false +AC_CHECK_LIB(dl,dlopen) +if test "$ac_cv_lib_dl_dlopen" = "yes"; then + AC_DEFINE(HAVE_DL_DLOPEN,,[Compile with dlopen support]) + have_dl_dlopen=true +fi + +dnl Check for Veejay +have_veejay=false +PKG_CHECK_MODULES( VEEJAY, [veejay >= 1.5.2 ], + [ + AC_SUBST(VEEJAY_CFLAGS) + AC_SUBST(VEEJAY_LIBS) + have_veejay=true + AC_DEFINE(HAVE_VEEJAY,1, [Veejay installed])] + , + [have_veejay=false]) + +if test x$have_veejay != xtrue ; then + PKG_CHECK_MODULES(VEEJAY, [veejay >= 1.4.8 ], + [ + AC_MSG_WARN([veejay-server old but should be compatible!]) + ], + [ + AC_MSG_ERROR([Cannot find veejay]) + ]) +fi + +have_pixbuf=false +if test x$with_pixbuf != xno ; then + PKG_CHECK_MODULES(PIXBUF, [gtk+-2.0 >= 2.8 gdk-pixbuf-2.0], + [ + AC_SUBST(PIXBUF_CFLAGS) + AC_SUBST(PIXBUF_LIBS) + have_pixbuf=true + AC_DEFINE(USE_GDK_PIXBUF, 1, [use gdk image load / save])], + [have_pixbuf=false]) +fi + +dnl ******************************************************************** +dnl Check to see if __progname is provided by the system +dnl ******************************************************************** +AC_CACHE_CHECK([for __progname], + [mjt_cv_extern___progname], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], + [[extern char *__progname; + puts(__progname);]])], + [mjt_cv_extern___progname=yes], + [mjt_cv_extern___progname=no])]) +if test x$mjt_cv_extern___progname = xyes ; then + AC_DEFINE(HAVE___PROGNAME, 1, [Is __progname defined by system?]) +fi + +dnl Look for X +AC_PATH_XTRA +AM_CONDITIONAL(HAVE_X, test x$have_x = xyes) + +AC_MSG_CHECKING(whether to compile in profiling information) +if test "x$enable_profiling" = "xyes" ; then + debugCFLAGS="$debugCFLAGS -fprofile-arcs -ftest-coverage" + DEBUGLIBS="-lgcov" + AC_SUBST(DEBUGLIBS) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +AC_MSG_CHECKING(whether to compile in assertion checking) +if test "x$enable_strict" = "xyes" ; then + debugCFLAGS="$debugCFLAGS -g -DSTRICT_CHECKING" + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +have_asm_nasm=false +have_asm_mmx=false +have_asm_sse=false +have_asm_sse2=false +have_asm_mmx2=false +have_asm_3dnow=false +have_cmov=false +have_x86cpu=false +have_x86_64cpu=false +have_altivec=false +have_mips=false +have_ppccpu=false +have_ps2=false + +OP_CFLAGS="" +YUVCFLAGS="-fif-conversion" + +AC_MSG_CHECKING([Architecture]) +case $host_cpu in + i[[3-7]]86) + AC_DEFINE(HAVE_X86CPU,, [Compiling for x86 architecture CPU]) + AC_DEFINE(ARCH_X86,1,[Compiling for x86 architecture]) + have_x86cpu=true + + PROGRAM_NOPIC="-fno-PIC" + + if test "x$enable_debug" != "xyes" ; then + OP_CFLAGS="-O3" + fi + + AC_SUBST(OP_CFLAGS) + AC_SUBST(YUVCFLAGS) + + dnl If the host is pentium, align on double word boundary + case $host_cpu in + i686) + CFLAGS="$CFLAGS" + ;; + *) + ;; + esac + + ;; + x86_64*|k8-*) + AC_DEFINE(HAVE_X86_CPU,, [Compiling for x86-64 architecture CPU]) + AC_DEFINE(ARCH_X86_64,1, [Compiling for x86-64 architecture CPU]) + have_x86cpu=true + have_x86_64cpu=true + CFLAGS="$CFLAGS -fPIC -DPIC" + ;; + powerpc | powerpc64) + AC_DEFINE(HAVE_PPCCPU,, [Compiling for PowerPC CPU]) + AC_DEFINE(ARCH_PPC,,[Compiling for PowerPC]) + have_ppccpu=true + + case $host in + *-apple-darwin*) + PROGRAM_NOPIC="-mdynamic-no-pic" # dynamic-no-pic is an Apple gcc option +dnl CFLAGS="$CFLAGS -no-cpp-precomp" + + ;; + *) + PROGRAM_NOPIC="" + ;; + esac + ;; + mips | mipsel) + AC_DEFINE(ARCH_MIPS,,[Compiling for MIPS CPU]) + AC_DEFINE(HAVE_MIPS,,[Compiling for MIPS CPU]) + have_mips=true + AC_MSG_CHECKING([if we are compiling on playstation2 hardware]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], + [[#include + #include + ]])], + [have_ps2=true], + [have_ps2=false]) + + if test x$have_ps2 = xtrue ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PS2,,[Compile for playstation2]) + else + AC_MSG_RESULT(no) + fi + + ;; + *) + AC_MSG_RESULT([unknown]) + ;; +esac + +dnl This flag is used for PROGRAMS not SHARED LIBRARIES. PIC code is required +dnl for shared libraries but is slower than non-pic code. Compute bound +dnl programs such as yuvdenoise and y4mspatialfilter can use this flag by +dnl simply adding programname_CFLAGS=@PROGRAM_NOPIC@ to the Makefile.am + +AC_SUBST(PROGRAM_NOPIC) + +if test x$have_x86cpu = xtrue +then + AC_CACHE_CHECK(for MMX on processor(s), ac_cv_flag_mmx, [ + if grep "^flags.* mmx" /proc/cpuinfo > /dev/null; then + ac_cv_flag_mmx=yes + else + ac_cv_flag_mmx=no + fi + ]) + + if test $ac_cv_flag_mmx = yes; then + AC_DEFINE(HAVE_ASM_MMX,,[Compiling in MMX support]) + AC_DEFINE(HAVE_MMX,,[Compiling in MMX support]) + have_asm_mmx=true + fi + + AC_CACHE_CHECK(for SSE on processor(s), ac_cv_flag_sse, [ + if grep "^flags.* sse" /proc/cpuinfo > /dev/null; then + ac_cv_flag_sse=yes + else + ac_cv_flag_sse=no + fi + ]) + + if test $ac_cv_flag_sse = yes; then + AC_DEFINE(HAVE_ASM_SSE,,[Compiling in SSE support]) + AC_DEFINE(HAVE_SSE,,[Compiling in SSE support]) + have_asm_sse=true + fi + + + dnl check for sse2 + AC_CACHE_CHECK(for SSE2 on processor(s), ac_cv_flag_sse2, [ + if grep "^flags.* sse2" /proc/cpuinfo > /dev/null; then + ac_cv_flag_sse2=yes + else + ac_cv_flag_sse2=no + fi + ]) + + if test $ac_cv_flag_sse2 = yes; then + AC_DEFINE(HAVE_ASM_SSE2,,[Compiling in SSE2 support]) + AC_DEFINE(HAVE_SSE2,,[Compiling in SSE2 support]) + have_asm_sse2=true + fi + + AC_CACHE_CHECK(for 3DNOW on processor(s), ac_cv_flag_3dnow, [ + if grep "^flags.* 3dnow" /proc/cpuinfo > /dev/null; then + ac_cv_flag_3dnow=yes + else + ac_cv_flag_3dnow=no + fi + ]) + + if test $ac_cv_flag_3dnow = yes; then + AC_DEFINE(HAVE_ASM_3DNOW,,[Compiling in 3Dnow]) + have_asm_3dnow=true + fi + + AC_CACHE_CHECK(for CMOV on processor(s), ac_cv_flag_cmov, [ + if grep "^flags.* cmov" /proc/cpuinfo > /dev/null; then + ac_cv_flag_cmov=yes + else + ac_cv_flag_cmov=yes + fi + ]) + + if test $ac_cv_flag_cmov = yes; then + AC_DEFINE(HAVE_CMOV,,[Compiling in CMOV]) + have_cmov=true + fi + + + dnl check for MMX2 + AC_CACHE_CHECK(for MMX2 on processor(s), ac_cv_flag_mmx2, [ + if grep "^flags.* mmxext" /proc/cpuinfo > /dev/null; then + ac_cv_flag_mmx2=yes + else + ac_cv_flag_mmx2=yes + fi + ]) + + if test $ac_cv_flag_mmx2 = yes; then + AC_DEFINE(HAVE_ASM_MMX2,,[Compiling in MMX2]) + AC_DEFINE(HAVE_MMX2,,[Compiling in MMX2]) + AC_DEFINE(HAVE_ASM_MMXEXT,,[Compiling in MMXEXT]) + have_asm_mmx2=true + fi + +fi + +if test x$have_ppccpu = xtrue +then + AC_MSG_CHECKING([compiler support for AltiVec]) + cat > conftest.c < +#endif +int main() { + union { vector signed int v; + signed int i; + } vi; + vi.v = vec_splat_s32(1); + return vi.i; +} +EOF + ALTIVEC_CFLAGS="" + if $CC -o conftest conftest.c >/dev/null 2>&1; then + have_altivec=true + elif $CC $CFLAGS -faltivec -o conftest conftest.c >/dev/null 2>&1; then + # Mac OS X style + have_altivec=true + ALTIVEC_CFLAGS="-faltivec" + elif $CC $CFLAGS -fvec -o conftest conftest.c >/dev/null 2>&1; then + # Motorola style + have_altivec=true + ALTIVEC_CFLAGS="-fvec" + elif $CC $CFLAGS -DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec -o conftest conftest.c >/dev/null 2>&1; then + # gcc 3.1 style + have_altivec=true + ALTIVEC_CFLAGS="-DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec" + fi + rm -f conftest*; + + if test x$have_altivec = xtrue + then + # add -O3 flag + ALTIVEC_CFLAGS="-O3 ${ALTIVEC_CFLAGS}" + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_ALTIVEC,, + [Inline PPC Altivec primitives available]) + AC_SUBST(ALTIVEC_CFLAGS) + else + AC_MSG_RESULT(no) + fi + + +fi + +if test ! -r $srcdir/cpuinfo.sh; then + AC_MSG_ERROR([cpuinfo.sh script not found - do a cvs update]) +fi + + +if test x$have_x86cpu = xtrue -o x$have_ppccpu = xtrue; then + if test x$host_alias != x; then + dnl Cross compiling + AC_MSG_CHECKING(sub-architecture settings) + if test x$have_x86cpu = xtrue; then + host_mod_cpu=`echo $host_cpu|tr _ -` + ARCHFLAGS="-march=$host_mod_cpu -mcpu=$host_mod_cpu" + AC_MSG_RESULT($ARCHFLAGS) + fi + else + AC_MSG_CHECKING(sub-architecture settings) + chmod +x $srcdir/cpuinfo.sh + + if test x$have_x86cpu = xtrue; then + ARCHFLAGS=`$srcdir/cpuinfo.sh x86` + fi + if test x$have_ppccpu = xtrue; then + ARCHFLAGS=`$srcdir/cpuinfo.sh ppc` + fi + AC_MSG_RESULT($ARCHFLAGS) + fi +fi + + +if test x$have_x86cpu = xtrue; +then + AC_MSG_NOTICE([enable_debug = $enable_debug]) + if test "x$enable_debug" != "xyes" ; + then + AC_MSG_NOTICE([debug koekje]) + if test $ac_cv_flag_sse = yes; then + CFLAGS="$CFLAGS -msse -mfpmath=sse" + AC_MSG_NOTICE([cflags aangepast]) + fi + if test $av_cv_flag_sse2 = yes; then + CFLAGS="$CFLAGS -msse2 -mfpmath=sse" + AC_MSG_NOTICE([cflags aangepast]) + fi + fi +fi + +AC_MSG_RESULT($CFLAGS) + + +AC_DEFINE_UNQUOTED(HAVE_FFMPEG_UNINSTALLED,, + [Defined if building against uninstalled FFmpeg source]) + +PKG_CHECK_MODULES(LIBAVUTIL, [libavutil >= 49.7.0],have_avutil=true,have_avutil=false) +PKG_CHECK_MODULES(LIBAVCODEC,[libavcodec >= 51.57.2],have_avcodec=true,have_avcodec=false) +PKG_CHECK_MODULES(LIBAVFORMAT,[libavformat >= 52.14.0],have_avformat=true,have_avformat=false) +PKG_CHECK_MODULES(LIBSWSCALE,[libswscale >= 0.7.1],have_swscale=true,have_swscale=false) +if test x$have_swscale = xfalse; +then + AC_MSG_ERROR([libswscale not found.]) +fi +if test x$have_avutil = xfalse; +then + AC_MSG_ERROR([libavutil not found.]) +fi +if test x$have_avformat = xfalse; +then + AC_MSG_ERROR([libavformat not found.]) +fi +if test x$have_avcodec = xfalse; +then + AC_MSG_ERROR([libavcodec not found.]) +fi + +FFMPEG_CFLAGS="${LIBAVFORMAT_CFLAGS} ${LIBAVCODEC_CFLAGS} ${LIBAVUTIL_CFLAGS} ${LIBSWSCALE_CFLAGS}" +FFMPEG_LIBS="${LIBAVFORMAT_LIBS} ${LIBAVCODEC_LIBS} ${LIBAVUTIL_LIBS} ${LIBSWSCALE_LIBS}" +AC_SUBST(FFMPEG_CFLAGS) +AC_SUBST(FFMPEG_LIBS) + + +dnl ********************************************************************** +dnl All the conditional stuff for the Makefiles +AM_CONDITIONAL(HAVE_ASM_MMX, test x$have_asm_mmx = xtrue) +AM_CONDITIONAL(HAVE_X86CPU, test x$have_x86cpu = xtrue) +AM_CONDITIONAL(HAVE_PPCCPU, test x$have_ppccpu = xtrue) +AM_CONDITIONAL(ARCH_PPC, test x$have_ppccpu = xtrue) +AM_CONDITIONAL(ARCH_X86, test x$have_x86cpu = xtrue) +AM_CONDITIONAL(HAVE_ALTIVEC, test x$have_altivec = xtrue) +AM_CONDITIONAL(HAVE_ASM_MMX2, test x$have_asm_mmx2 = xtrue) +AM_CONDITIONAL(HAVE_ASM_SSE, test x$have_asm_sse = xtrue) +AM_CONDITIONAL(HAVE_ASM_SSE2, test x$have_asm_sse2 = xtrue) +AM_CONDITIONAL(HAVE_ASM_NASM, test x$have_asm_nasm = xtrue) +AM_CONDITIONAL(HAVE_MMX, test x$have_asm_mmx = xtrue) +AM_CONDITIONAL(HAVE_SSE, test x$have_asm_sse = xtrue) +AM_CONDITIONAL(HAVE_SSE2, test x$have_asm_sse2 = xtrue) +AM_CONDITIONAL(HAVE_MMX2, test x$have_asm_mmx2 = xtrue) +AM_CONDITIONAL(HAVE_DL_DLOPEN, test x$have_dl_dlopen = xtrue) +dnl ********************************************************************* +dnl Check for what warnings we want gcc to use and adjust the CFLAGS +dnl as needed. This only works for GCC. +dnl We do this last as it can screw up library detection etc... + +CFLAGS="$ARCHFLAGS $CFLAGS" +CXXFLAGS="$ARCHFLAGS $CXXFLAGS" + + +if test "x${GCC}" != "xyes" ; then + enable_compile_warnings=no +fi + +AC_MSG_CHECKING(what warning flags to pass to the C compiler) +warnCFLAGS= +warnCXXFLAGS= +if test "x$enable_compile_warnings" != "xno" ; then + if test "x$GCC" = "xyes" ; then + case "$CFLAGS" in + *-Wall*) ;; + *) warnCFLAGS="-Wall -Wunused " ;; + esac + if test "x$enable_compile_warnings" = "xyes" ; then + warnCFLAGS="$warnCFLAGS -Wmissing-prototypes -Wundef -Wshadow -Wbad-function-cast -Wconversion -Wpadded -Wunreachable-code -Wmissing-declarations -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" + warnCXXFLAGS="$warnCXXFLAGS -Wmissing-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" + fi + if test "x$enable_warnings_as_errors" = "xyes" ; then + warnCFLAGS="$warnCFLAGS -Werror" + warnCXXFLAGS="$warnCXXFLAGS -Werror" + fi + fi +fi + +if test "x$cflags_set" != "xyes" ; then + if test "x$enable_debug" = "xyes" ; then + CFLAGS="$debugCFLAGS $warnCFLAGS $CFLAGS" + else + CFLAGS="$CFLAGS $warnCFLAGS" + fi + CXXFLAGS="$CXXFLAGS $warnCXXFLAGS" + cflags_set=yes +fi + + +if test x"$with_extra_cflags" != "x"; then + CFLAGS="$CFLAGS $with_extra_cflags" + CXXFLAGS="$CXXFLAGS $with_extra_cflags" +fi + +reloaded_datadir="${datadir}/reloaded" +AC_SUBST(reloaded_datadir) +sh gveejay-paths.sh > gveejay-paths.h + +glib_modules="glib-2.0 >= 2.4" +PKG_CHECK_MODULES(GLIB, [$glib_modules]) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +gtk_modules="gtk+-2.0 >= 2.8" +PKG_CHECK_MODULES(GTK, [$gtk_modules]) +AC_SUBST(GTK_CFLAGS) +AC_SUBST(GTK_LIBS) + +libglade_modules="libglade-2.0 >= 2.0.1" +PKG_CHECK_MODULES(GLADE, [$libglade_modules]) +AC_SUBST(GLADE_CFLAGS) +AC_SUBST(GLADE_LIBS) + + +dnl ********************************************************************** +dnl Output a Makefile or two and the lib/header descriptor script +dnl +AC_CONFIG_FILES([ +Makefile +src/Makefile +gveejay-paths.sh +]) +AC_OUTPUT + +AC_DEFINE(VERSION, ${VERSION}) + +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ GVeejayReloaded ${VERSION} build configuration :]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Compiler flags: $CFLAGS]) +AC_MSG_NOTICE([ $YUVCFLAGS]) +AC_MSG_NOTICE([ $OP_CFLAGS]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Architecture: ${host_cpu} ]) +AC_MSG_NOTICE([]) +if test "$have_x86cpu" = "true" ; then +AC_MSG_NOTICE([ x86 ]) +AC_MSG_NOTICE([ MMX enabled : ${ac_cv_flag_mmx}]) +AC_MSG_NOTICE([ MMX2 enabled : ${ac_cv_flag_mmx2}]) +AC_MSG_NOTICE([ SSE enabled : ${ac_cv_flag_sse}]) +AC_MSG_NOTICE([ SSE2 enabled : ${ac_cv_flag_sse2}]) +AC_MSG_NOTICE([ 3DNOW enabled : ${ac_cv_flag_3dnow}]) +AC_MSG_NOTICE([ CMOV enabled : ${ac_cv_flag_cmov}]) +fi + +if test "$have_ppccpu" = "true" ; then +AC_MSG_NOTICE([ ppc]) +AC_MSG_NOTICE([ AltiVec enabled : ${have_altivec}]) +fi + +if test "$have_mips" = "true" ; then +AC_MSG_NOTICE([ mips]) +AC_MSG_NOTICE([ PS/2 enabled : ${have_ps2}]) +fi +AC_MSG_NOTICE([]) +if test "$have_linux" = "true" ; then +AC_MSG_NOTICE([ Platform: Linux]) +fi + +if test "$have_darwin" = "true" ; then +AC_MSG_NOTICE([ Platform: Darwin]) +AC_MSG_NOTICE([ Good luck! You can be the first! ]) +fi +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Required dependencies:]) +AC_MSG_NOTICE([ - Veejay 1.5.2 : ${have_veejay}]) +AC_MSG_NOTICE([ - POSIX Threads (pthread) : ${have_pthread}]) +AC_MSG_NOTICE([ - FFmpeg AVCodec : ${have_avcodec} ]) +AC_MSG_NOTICE([ - FFmpeg Swscaler : ${have_swscale} ]) +AC_MSG_NOTICE([ - GDK Pixbuf support : ${have_pixbuf}]) +AC_MSG_NOTICE([ - Alsa support (midi sequencer) : ${have_alsa}]) diff --git a/branches/V-1.5.3/veejay-client/cpuinfo.sh b/branches/V-1.5.3/veejay-client/cpuinfo.sh new file mode 100755 index 00000000..a8e6ace8 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/cpuinfo.sh @@ -0,0 +1,336 @@ +#!/bin/sh + +if test x"$CC" = x; then + CC=gcc +fi + +if test $# -ne 1; then + echo "Please give the arch (ppc or x86) as an argument!" 1>&2 + exit 1 +fi + +if test `uname -s` = Darwin; then + IsDarwin=yes +else + IsDarwin=no +fi + +target=$1 + +cc_version=`$CC -dumpversion` +_cc_major=`echo $cc_version | cut -d'.' -f1` +_cc_minor=`echo $cc_version | cut -d'.' -f2` + +if test $_cc_major -ge 4; then + _opt_mcpu="-mtune" +else + _opt_mcpu="-mcpu" +fi + +do_cc() +{ + $CC -o conftest conftest.c $@ >/dev/null 2>&1 +} + +extcheck() +{ +cat > conftest.c < +void catch() { exit(1); } +int main(void){ + signal(SIGILL, catch); + __asm__ __volatile__ ("$1":::"memory"); + exit(0); +} +EOF + +do_cc +if test -x ./conftest; then + ./conftest + if test $? -ne 0; then + return 1 + fi + return 0 +else + return 1 +fi +} + +do_x86() +{ + +CFLAGS=-O +if test $IsDarwin = yes; then + CFLAGS="$CFLAGS -fno-pic -Wl,-read_only_relocs -Wl,suppress" +fi + +if test -r /proc/cpuinfo; then + _cpuinfo="cat /proc/cpuinfo" +else + $CC $CFLAGS -o cpuinfo utils/cpuinfo.c + _cpuinfo="./cpuinfo" +fi + +# Cpu determination logic adapted from the MPlayer configure script. + +pname=`$_cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -n 1` +pvendor=`$_cpuinfo | grep 'vendor_id' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pfamily=`$_cpuinfo | grep 'cpu family' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pmodel=`$_cpuinfo | grep -v 'model name' | grep 'model' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pstep=`$_cpuinfo | grep 'stepping' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pparam=`$_cpuinfo | grep 'features' | cut -d':' -f2 | head -n 1` + +if test -z "$pparam" ; then + pparam=`$_cpuinfo | grep 'flags' | cut -d ':' -f 2 | head -n 1` +fi + +_mmx=no +_3dnow=no +_3dnowex=no +_mmx2=no +_sse=no +_sse2=no +_mtrr=no + +for i in $pparam ; do + case "$i" in + 3dnow) _3dnow=yes ;; + 3dnowext) _3dnow=yes _3dnowex=yes ;; + mmx) _mmx=yes ;; + mmxext) _mmx2=yes ;; + mtrr|k6_mtrr|cyrix_arr) _mtrr=yes ;; + xmm|sse|kni) _sse=yes _mmx2=yes ;; + sse2) _sse2=yes ;; + esac +done + +case "$pvendor" in + AuthenticAMD) + case "$pfamily" in + 3)proc=i386 + ;; + 4) proc=i486 + ;; + 5) iproc=586 + # models are: K5/SSA5 K5 K5 K5 ? ? K6 K6 K6-2 K6-3 + # K6 model 13 are the K6-2+ and K6-III+ + if test "$pmodel" -eq 9 -o "$pmodel" -eq 13; then + proc=k6-3 + elif test "$pmodel" -ge 8; then + proc=k6-2 + elif test "$pmodel" -ge 6; then + proc=k6 + else + proc=i586 + fi + ;; + 6) iproc=686 + if test "$pmodel" -ge 7; then + proc=athlon-4 + elif test "$pmodel" -ge 6; then + if test "$_sse" = yes && test "$pstep" -ge 2; then + proc=athlon-xp + else + proc=athlon-4 + fi + elif test "$pmodel" -ge 4; then + proc=athlon-tbird + else + proc=athlon + fi + ;; + 15) + # Despite what the gcc into says 'athlon64' is not accepted as + # synonym for 'k8' + proc=k8 + ;; + *) proc=athlon-xp + ;; + esac + ;; + GenuineIntel) + case "$pfamily" in + 3) proc=i386 + ;; + 4) proc=i486 + ;; + 5) iproc=586 + if test "$pmodel" -eq 4 || test "$pmodel" -eq 8; then + proc=pentium-mmx # 4 is desktop, 8 is mobile + else + proc=i586 + fi + ;; + 6) iproc=686 + if test "$pmodel" -ge 15; then + proc=nocona + elif test "$pmodel" -ge 13; then + proc=pentium-m + elif test "$pmodel" -ge 7; then + proc=pentium3 + elif test "$pmodel" -ge 3; then + proc=pentium2 + else + proc=i686 + fi + ;; + 15) proc=pentium4 + ;; + *) proc=pentium4 + ;; + esac + ;; + unknown) + case "$pfamily" in + 3) proc=i386 + ;; + 4) proc=i486 + ;; + *) proc=i586 + ;; + esac + ;; + *) + proc=i586 + ;; +esac + +# check that gcc supports our CPU, if not, fall back to earlier ones + +cat > conftest.c << EOF +int main(void) { return 0; } +EOF +if test "$proc" = "athlon64" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon-xp +fi + +if test "$proc" = "athlon-xp" || test "$proc" = "athlon-4" || test "$proc" = "athlon-tbird"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon +fi + +if test "$proc" = "k6-3" || test "$proc" = "k6-2"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=k6 +fi + +if test "$proc" = "k6"; then + do_cc -march=$proc $_opt_mcpu=$proc + if test $? -ne 0; then + if do_cc -march=i586 $_opt_mcpu=i686; then + proc=i586-i686 + else + proc=i586 + fi + fi +fi + +if test "$proc" = "pentium4" || test "$proc" = "pentium3" || test "$proc" = "pentium2" || test "$proc" = "athlon"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i686 +fi +if test "$proc" = "i686" || test "$proc" = "pentium-mmx"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i586 +fi +if test "$proc" = "i586" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i486 +fi +if test "$proc" = "i486" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i386 +fi +if test "$proc" = "i386" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=error +fi +if test "$proc" = "error" ; then + echo "Your $_cc does not even support \"i386\" for '-march' and $_opt_mcpu." + _mcpu="" + _march="" +elif test "$proc" = "i586-i686"; then + _march="-march=i586" + _mcpu="$_opt_mcpu=i686" +else + _march="-march=$proc" + _mcpu="$_opt_mcpu=$proc" +fi + +if test $_cc_major -ge 3; then + extcheck "xorps %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse" + extcheck "xorpd %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse2" + + if test x"$_gcc3_ext" != "x"; then + # if we had to disable sse/sse2 because the active kernel does not + # support this instruction set extension, we also have to tell + # gcc3 to not generate sse/sse2 instructions for normal C code + cat > conftest.c << EOF +int main(void) { return 0; } +EOF + do_cc $_march $_gcc3_ext && _march="$_march $_gcc3_ext" + fi +fi + +echo $_march $_mcpu +rm -f conftest.c conftest cpuinfo +return 0 +} + +do_ppc() +{ +# Linux on a PPC has /proc/info +# Darwin (OS/X) has the hostinfo command +# If neither of those we have no idea what to do - so do nothing. +if test -r /proc/cpuinfo; then + proc=`grep cpu /proc/cpuinfo | cut -d':' -f2 | cut -d',' -f1 | cut -b 2- | head -n 1` +elif test $IsDarwin = yes; then + proc=`hostinfo | grep "Processor type" | cut -f3 -d' ' | sed 's/ppc//'` +else + return 0 +fi + +case "$proc" in + 601) _march="$_opt_mcpu=601" _mcpu='-mtune=601' + ;; + 603) _march="$_opt_mcpu=603" _mcpu='-mtune=603' + ;; + 603e|603ev) _march="$_opt_mcpu=603e" _mcpu='-mtune=603e' + ;; + 604|604e|604r|604ev) _march="$_opt_mcpu=604" _mcpu='-mtune=604' + ;; + 740|740/750|745/755) _march="$_opt_mcpu=740" _mcpu='-mtune=740' + ;; + 750|750CX) _march="$_opt_mcpu=750" _mcpu='-mtune=750' + ;; + *) ;; +esac + +# gcc 3.1(.1) and up supports 7400 and 7450 +if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "1" || test "$_cc_major" -ge "4"; then + case "$proc" in + 7400*|7410*) _march="$_opt_mcpu=7400" _mcpu='-mtune=7400' ;; + 7450*|7455*) _march="$_opt_mcpu=7450" _mcpu='-mtune=7450' ;; + *) ;; + esac +fi + +# gcc 3.2 and up supports 970 +if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "3" || test "$_cc_major" -ge "4"; then + case "$proc" in + 970*) if test $IsDarwin = yes; then + _march="$_opt_mcpu=G5 -mpowerpc64 -mpowerpc-gpopt -falign-loops=16 -force_cpusubtype_ALL" _mcpu='-mtune=G5' + else + _march="$_opt_mcpu=970" _mcpu='-mtune=970' + fi + ;; + *) ;; + esac +fi + +echo $_march $_mcpu +return 0 +} + +# +# The script that runs the various functions above +# + +if test $target = x86; then + do_x86 +elif test $target = ppc; then + do_ppc +fi diff --git a/branches/V-1.5.3/veejay-client/debian/README.Debian b/branches/V-1.5.3/veejay-client/debian/README.Debian new file mode 100644 index 00000000..4c8630fe --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/README.Debian @@ -0,0 +1,6 @@ +reloaded for Debian +------------------- + + + + -- root Tue, 11 Nov 2008 18:31:53 +0100 diff --git a/branches/V-1.5.3/veejay-client/debian/changelog b/branches/V-1.5.3/veejay-client/debian/changelog new file mode 100644 index 00000000..fdad0add --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/changelog @@ -0,0 +1,10 @@ +reloaded (1.5.2) unstable; urgency=low + + * 1.5.2 release + + * 1.4-3 release + + * Initial official release + + -- Niels Elburg Sat, 19 Dec 2009 19:38:26 +0100 + diff --git a/branches/V-1.5.3/veejay-client/debian/compat b/branches/V-1.5.3/veejay-client/debian/compat new file mode 100644 index 00000000..7ed6ff82 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/compat @@ -0,0 +1 @@ +5 diff --git a/branches/V-1.5.3/veejay-client/debian/control b/branches/V-1.5.3/veejay-client/debian/control new file mode 100644 index 00000000..399b6032 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/control @@ -0,0 +1,12 @@ +Source: reloaded +Section: video +Priority: extra +Maintainer: Niels Elburg +Build-Depends: debhelper (>= 5), autotools-dev,libgtk2.0-dev,libavformat-dev,libavcodec-dev,libglib2.0-dev,libmjpegtools-dev,libavutil-dev,libmjpegtools-dev,libpthread-stubs0-dev,libglade2-dev +Standards-Version: 3.7.2 + +Package: reloaded +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: The is the graphical interface to Veejay - a 'visual' instrument and realtime video sampler + diff --git a/branches/V-1.5.3/veejay-client/debian/copyright b/branches/V-1.5.3/veejay-client/debian/copyright new file mode 100644 index 00000000..b363ff40 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/copyright @@ -0,0 +1,21 @@ +This package was debianized by niels on +Sun, Dec 20 2009 15:35:35 +0100. + +It was downloaded from http://www.veejayhq.net + +Upstream Author(s): + + Niels Elburg + Matthijs v. Henten + +Copyright: + + + + +License: + + You are free to distribute this software under the terms of + the GNU General Public License. + On Debian systems, the complete text of the GNU General Public + License can be found in the file `/usr/share/common-licenses/GPL' diff --git a/branches/V-1.5.3/veejay-client/debian/dirs b/branches/V-1.5.3/veejay-client/debian/dirs new file mode 100644 index 00000000..ca882bbb --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/branches/V-1.5.3/veejay-client/debian/docs b/branches/V-1.5.3/veejay-client/debian/docs new file mode 100644 index 00000000..50bd824b --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/docs @@ -0,0 +1,2 @@ +NEWS +README diff --git a/branches/V-1.5.3/veejay-client/debian/files b/branches/V-1.5.3/veejay-client/debian/files new file mode 100644 index 00000000..0685d538 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/files @@ -0,0 +1 @@ +reloaded_1.4-6_i386.deb video extra diff --git a/branches/V-1.5.3/veejay-client/debian/menu.ex b/branches/V-1.5.3/veejay-client/debian/menu.ex new file mode 100644 index 00000000..d47b1385 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/menu.ex @@ -0,0 +1,2 @@ +?package(reloaded):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\ + title="reloaded" command="/usr/bin/reloaded" diff --git a/branches/V-1.5.3/veejay-client/debian/postinst.ex b/branches/V-1.5.3/veejay-client/debian/postinst.ex new file mode 100644 index 00000000..afa7f524 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/postinst.ex @@ -0,0 +1,41 @@ +#!/bin/sh +# postinst script for reloaded +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-client/debian/postrm.ex b/branches/V-1.5.3/veejay-client/debian/postrm.ex new file mode 100644 index 00000000..b7d53cc5 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/postrm.ex @@ -0,0 +1,39 @@ +#!/bin/sh +# postrm script for reloaded +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-client/debian/preinst.ex b/branches/V-1.5.3/veejay-client/debian/preinst.ex new file mode 100644 index 00000000..4648b207 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/preinst.ex @@ -0,0 +1,37 @@ +#!/bin/sh +# preinst script for reloaded +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-client/debian/prerm.ex b/branches/V-1.5.3/veejay-client/debian/prerm.ex new file mode 100644 index 00000000..ac6ccf97 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/prerm.ex @@ -0,0 +1,40 @@ +#!/bin/sh +# prerm script for reloaded +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-client/debian/reloaded-default.ex b/branches/V-1.5.3/veejay-client/debian/reloaded-default.ex new file mode 100644 index 00000000..16d41d4e --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/reloaded-default.ex @@ -0,0 +1,10 @@ +# Defaults for reloaded initscript +# sourced by /etc/init.d/reloaded +# installed at /etc/default/reloaded by the maintainer scripts + +# +# This is a POSIX shell fragment +# + +# Additional options that are passed to the Daemon. +DAEMON_OPTS="" diff --git a/branches/V-1.5.3/veejay-client/debian/reloaded.doc-base.EX b/branches/V-1.5.3/veejay-client/debian/reloaded.doc-base.EX new file mode 100644 index 00000000..438980a3 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/reloaded.doc-base.EX @@ -0,0 +1,22 @@ +Document: reloaded +Title: Debian reloaded Manual +Author: +Abstract: This manual describes what reloaded is + and how it can be used to + manage online manuals on Debian systems. +Section: unknown + +Format: debiandoc-sgml +Files: /usr/share/doc/reloaded/reloaded.sgml.gz + +Format: postscript +Files: /usr/share/doc/reloaded/reloaded.ps.gz + +Format: text +Files: /usr/share/doc/reloaded/reloaded.text.gz + +Format: HTML +Index: /usr/share/doc/reloaded/html/index.html +Files: /usr/share/doc/reloaded/html/*.html + + diff --git a/branches/V-1.5.3/veejay-client/debian/reloaded.substvars b/branches/V-1.5.3/veejay-client/debian/reloaded.substvars new file mode 100644 index 00000000..9821d1a0 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/reloaded.substvars @@ -0,0 +1 @@ +shlibs:Depends=libogg0 , libasound2 (>> 1.0.14), libvorbis0a (>= 1.2.0), libraw1394-8, libc6 (>= 2.4), libswscale1d (>= 0.cvs20070307), libcairo2 (>= 1.6.0), libvorbisenc2 (>= 1.1.2), veejay, libxml2 , libatk1.0-0 (>= 1.20.0), libgtk2.0-0 (>= 2.12.0), libmjpegtools0c2a (>= 1:1.8.0), libpango1.0-0 (>= 1.20.1), libavcodec1d (>= 0.cvs20070307), libglade2-0 (>= 1:2.6.1), libavutil1d (>= 0.cvs20070307), libx11-6, libtheora0, libglib2.0-0 (>= 2.16.0) diff --git a/branches/V-1.5.3/veejay-client/debian/rules b/branches/V-1.5.3/veejay-client/debian/rules new file mode 100755 index 00000000..a1aea8c7 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/debian/rules @@ -0,0 +1,116 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) +CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE) +else +CROSS= --build $(DEB_BUILD_GNU_TYPE) +endif + + + + +# shared library versions, option 1 +version=2.0.5 +major=2 +# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so +#version=`ls src/.libs/lib*.so.* | \ +# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` +#major=`ls src/.libs/lib*.so.* | \ +# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` + +config.status: configure + dh_testdir + # Add here commands to configure the package. +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure $(CROSS) --enable-debug --prefix=/usr --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs" + + +build: build-stamp +build-stamp: config.status + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + [ ! -f Makefile ] || $(MAKE) distclean + rm -f config.sub config.guess + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + + # Add here commands to install the package into debian/tmp + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + dh_install -i + +# Build architecture-independent files here. +binary-indep: build install + mkdir -p $(CURDIR)/debian/tmp/usr/share/reloaded + cp -va $(CURDIR)/share $(CURDIR)/debian/tmp/usr/share/reloaded +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples + dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/branches/V-1.5.3/veejay-client/gveejay-paths.sh.in b/branches/V-1.5.3/veejay-client/gveejay-paths.sh.in new file mode 100644 index 00000000..ca89f217 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/gveejay-paths.sh.in @@ -0,0 +1,22 @@ +#!/bin/sh -e + +prefix="@prefix@" +datadir="@datadir@" + +DATADIRNAME="@DATADIRNAME@" + +reloaded_datadir="@reloaded_datadir@" + +cat << EOF +/* + This file has been automatically generated. Do not edit + +*/ +#ifndef GVEEJAY_PATHS_H +#define GVEEJAY_PATHS_H + +#define RELOADED_DATADIR "$reloaded_datadir" + +#endif /* GVEEJAY_PATHS_H */ +EOF + diff --git a/branches/V-1.5.3/veejay-client/gveejay.spec.in b/branches/V-1.5.3/veejay-client/gveejay.spec.in new file mode 100644 index 00000000..cb8eb405 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/gveejay.spec.in @@ -0,0 +1,114 @@ +# norootforbuild +# neededforbuild update-desktop-files gtk2-devel-packages glib2 gtk2 libglade3 gtk2-devel glib2-devel libglade-devel libxml2-devel pkgconfig + +%define name reloaded +%define version 1.5.2 +%define release reloaded +%define prefix /usr + +%define builddir $RPM_BUILD_DIR/%{name}-%{version} + +Summary: Video Mixing/Editing Instrument +Name: %{name} +Version: %{version} +Release: %{release} +Prefix: %{prefix} +Copyright: GNU GPL +URL: http://veejayq.net +Packager: nelburg +Group: Productivity/Multimedia/Video/Editors and Convertors +Source: %{name}-%{version}.tar.bz2 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Prereq: /sbin/ldconfig +#Requires: libxml2 >= 2.5.4 +#Requires: gtk2 +#Requires: glib2 +#Requires: libglade2 +#Requires: libxml2 >= 2.5.4 +#Requires: cairo +#BuildRequires: pkgconfig +#BuildRequires: gtk2-devel +#BuildRequires: glib2-devel +#BuildRequires: libglade2-devel + +%description +Veejay is a visual instrument and realtime video sampler. +It allows you to 'play' the video like you would play a Piano and it allows +you to record the resulting video directly to disk for immediate playback (video sampling). + +GVeejayReloaded is the graphical interface for Veejay. + +Author: Niels Elburg + +Requires: gtk2 +Requires: glib2 +Requires: libglade2 +Requires: libxml2 >= 2.5.4 + +%prep +%setup -q -n %{name}-%{version} + +./autogen.sh +%{?suse_update_config:%{suse_update_config -f}} + +CFLAGS="$RPM_OPT_FLAGS" \ +CXXFLAGS="$RPM_OPT_FLAGS" \ +./configure \ + --prefix=%{prefix} \ + --mandir=%{_mandir} + +%build +# Setup for parallel builds +numprocs=`egrep -c ^cpu[0-9]+ /proc/stat || :` +if [ "$numprocs" = "0" ]; then + numprocs=1 +fi +make -j$numprocs + +%install +[ -d %{buildroot} -a "%{buildroot}" != "" ] && rm -rf %{buildroot} + +make install-strip \ + DESTDIR=%{buildroot} + +# icon and menu-entry +mkdir -p %{buildroot}%{_datadir}/pixmaps +install -m 644 share/%{name}-logo.png %{buildroot}%{_datadir}/pixmaps/gveejay.png +cat > gveejay.desktop << EOF +[Desktop Entry] +Comment=Video Mixing/Editing Instrument +Exec=reloaded +GenericName= +Icon=%{name} +MimeType= +Name=Reloaded +Path= +StartupNotify=true +Terminal=false +Type=Application +EOF +%suse_update_desktop_file -i reloaded AudioVideo Player + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%clean +[ -d %{buildroot} -a "%{buildroot}" != "" ] && rm -rf %{buildroot} + +%files +%defattr(-, root, root) +%doc AUTHORS BUGS COPYING ChangeLog INSTALL README* +%doc doc +%{_bindir}/%{name} +%{_datadir}/%{name}/*.png +# reloaded +%{_bindir}/src +%{_datadir}/%{name}/gveejay-reloaded-2.glade +%{_datadir}/%{name}/gveejay.rc +%{_datadir}/pixmaps/gveejay.png +%{_datadir}/applications/gveejay.desktop + +%changelog -n veejay +Dec 20, 2009. Updated rpm spec for reloaded 1.5.2 +Mar 21, 2007. Initial rpm spec for gveejayreloaded diff --git a/branches/V-1.5.3/veejay-client/menu/gveejayreloaded.desktop b/branches/V-1.5.3/veejay-client/menu/gveejayreloaded.desktop new file mode 100644 index 00000000..299dc2b3 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/menu/gveejayreloaded.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=GVeejayReloaded +Comment=Graphical Veejay Client +Exec=gveejayreloaded +Terminal=false +Type=Application +Icon=veejay-icon.png +Categories=AudioVideoEditing;AudioVideo; diff --git a/branches/V-1.5.3/veejay-client/menu/veejay1.desktop b/branches/V-1.5.3/veejay-client/menu/veejay1.desktop new file mode 100644 index 00000000..31bce654 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/menu/veejay1.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=Veejay (720x576 with audio) +Comment=Start new veejay project, 720x576 with default audio settings +Exec=veejay -v -W720 -H576 -a1 -d +Terminal=true +Type=Application +Icon=veejay-icon.png +Categories=AudioVideoEditing;AudioVideo; diff --git a/branches/V-1.5.3/veejay-client/menu/veejay2.desktop b/branches/V-1.5.3/veejay-client/menu/veejay2.desktop new file mode 100644 index 00000000..8f9c8ff1 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/menu/veejay2.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=Veejay (720x576 without audio) +Comment=Start new Veejay project, 720x576 without audio +Exec=veejay -v -W720 -H576 -a0 -d +Terminal=true +Type=Application +Icon=veejay-icon.png +Categories=AudioVideoEditing;AudioVideo; diff --git a/branches/V-1.5.3/veejay-client/menu/veejay3.desktop b/branches/V-1.5.3/veejay-client/menu/veejay3.desktop new file mode 100644 index 00000000..c0e53f5e --- /dev/null +++ b/branches/V-1.5.3/veejay-client/menu/veejay3.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=Veejay (640x480, /dev/video0) +Comment=Start veejay server with capture device #0 in 640x480 +Exec=veejay -A1 -v -W640 -H480 +Terminal=true +Type=Application +Icon=veejay-icon.png +Categories=AudioVideoEditing;AudioVideo; diff --git a/branches/V-1.5.3/veejay-client/menu/veejay4.desktop b/branches/V-1.5.3/veejay-client/menu/veejay4.desktop new file mode 100644 index 00000000..53e6a3e6 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/menu/veejay4.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=Veejay (720x576, /dev/video0) +Comment=Start veejay server from capture device #0 in 720x576 +Exec=veejay -A1 -v -W720 -H576 +Terminal=true +Type=Application +Icon=veejay-icon.png +Categories=AudioVideoEditing;AudioVideo; diff --git a/branches/V-1.5.3/veejay-client/menu/veejay5.desktop b/branches/V-1.5.3/veejay-client/menu/veejay5.desktop new file mode 100644 index 00000000..5371c744 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/menu/veejay5.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Name=Veejay (352x288, /dev/video0) +Comment=Start veejay server with capture device #0 in 352x288 +Exec=veejay -A1 -v -W352 -H288 +Terminal=true +Type=Application +Icon=veejay-icon.png +Categories=AudioVideoEditing;AudioVideo; diff --git a/branches/V-1.5.3/veejay-client/share/bg.png b/branches/V-1.5.3/veejay-client/share/bg.png new file mode 100644 index 00000000..92c332d4 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/bg.png differ diff --git a/branches/V-1.5.3/veejay-client/share/bg_black.png b/branches/V-1.5.3/veejay-client/share/bg_black.png new file mode 100644 index 00000000..acc56362 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/bg_black.png differ diff --git a/branches/V-1.5.3/veejay-client/share/bg_blue.png b/branches/V-1.5.3/veejay-client/share/bg_blue.png new file mode 100644 index 00000000..f1f1b98d Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/bg_blue.png differ diff --git a/branches/V-1.5.3/veejay-client/share/bg_green.png b/branches/V-1.5.3/veejay-client/share/bg_green.png new file mode 100644 index 00000000..af8aa721 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/bg_green.png differ diff --git a/branches/V-1.5.3/veejay-client/share/bg_grey.png b/branches/V-1.5.3/veejay-client/share/bg_grey.png new file mode 100644 index 00000000..20ba15d7 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/bg_grey.png differ diff --git a/branches/V-1.5.3/veejay-client/share/bg_red.png b/branches/V-1.5.3/veejay-client/share/bg_red.png new file mode 100644 index 00000000..16e4811c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/bg_red.png differ diff --git a/branches/V-1.5.3/veejay-client/share/bg_yellow.png b/branches/V-1.5.3/veejay-client/share/bg_yellow.png new file mode 100644 index 00000000..c245dd3b Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/bg_yellow.png differ diff --git a/branches/V-1.5.3/veejay-client/share/blackwhite.rc b/branches/V-1.5.3/veejay-client/share/blackwhite.rc new file mode 100644 index 00000000..11331dcc --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/blackwhite.rc @@ -0,0 +1,118 @@ +# Edit these colors and fonts however you like. +style "default" +{ + engine "hcengine" {} + xthickness = 1 + ythickness = 1 + GtkWidget::shadow_type = GTK_SHADOW_ETCHED_OUT + #GtkWidget::interior_focus = 0 + #GtkWidget::focus_padding = 0 + #GtkWidget::default_border = {0, 0, 0, 0} + #GtkWidget::default_outside_border = {0, 0, 0, 0} + GtkWidget::default_spacing = 0 + GtkScale::stepper_size = 8 + GtkRange::through-width = 4 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 10 + + font_name = "Sans 8" + + fg[NORMAL] = "#ffffff" # borders etc. + fg[PRELIGHT] = "#000000" + fg[ACTIVE] = "#ffffff" # ook borders, van sliders en notebook + fg[SELECTED] = "#000000" + fg[INSENSITIVE] = "#505050" + + bg[NORMAL] = "#303030" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#202020" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#00ff00" + bg[INSENSITIVE] = "#000000" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#c0c0c0" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#303060"# achtergrond van lists, status bars + base[PRELIGHT] = "#00fff0" + base[ACTIVE] = "#0000ff" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + +style "text" +{ + font_name = "Sans 8" + + fg[NORMAL] = "#ffffff" # borders etc. + fg[PRELIGHT] = "#ffffff" + fg[ACTIVE] = "#ffffff" # ook borders, van sliders en notebook + fg[SELECTED] = "#ffffff" + fg[INSENSITIVE] = "#ffffff" + + bg[NORMAL] = "#27282F" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#454f60" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + + +style "buttons" +{ + + font_name = "Sans 8" + + fg[NORMAL] = "#888888" + fg[PRELIGHT] = "#888888" + fg[ACTIVE] = "#888888" + fg[SELECTED] = "#888888" + fg[INSENSITIVE] = "#888888" + + bg[NORMAL] = "#27282F" + bg[PRELIGHT] = "#aaacc1" + bg[ACTIVE] = "#454f60" + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + + + +class "GtkButton" style "default" +class "GtkSpinButton" style "default" +class "GtkToggleButton" style "default" +class "GtkCheckBox" style "default" + +class "GtkLabel" style "default" + +class "GtkWidget" style "default" diff --git a/branches/V-1.5.3/veejay-client/share/button_back.png b/branches/V-1.5.3/veejay-client/share/button_back.png new file mode 100644 index 00000000..c2295b5b Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_back.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_bounce.png b/branches/V-1.5.3/veejay-client/share/button_bounce.png new file mode 100644 index 00000000..82bbce6a Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_bounce.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_dec.png b/branches/V-1.5.3/veejay-client/share/button_dec.png new file mode 100644 index 00000000..4fc75576 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_dec.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_down.png b/branches/V-1.5.3/veejay-client/share/button_down.png new file mode 100644 index 00000000..99621523 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_down.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_fbw.png b/branches/V-1.5.3/veejay-client/share/button_fbw.png new file mode 100644 index 00000000..32e6b085 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_fbw.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_ffw.png b/branches/V-1.5.3/veejay-client/share/button_ffw.png new file mode 100644 index 00000000..50108d46 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_ffw.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_gotoend.png b/branches/V-1.5.3/veejay-client/share/button_gotoend.png new file mode 100644 index 00000000..d7d362f0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_gotoend.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_gotostart.png b/branches/V-1.5.3/veejay-client/share/button_gotostart.png new file mode 100644 index 00000000..c0ed75cc Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_gotostart.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_inc.png b/branches/V-1.5.3/veejay-client/share/button_inc.png new file mode 100644 index 00000000..862e48ee Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_inc.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_loop.png b/branches/V-1.5.3/veejay-client/share/button_loop.png new file mode 100644 index 00000000..aacf503f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_loop.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_looponce.png b/branches/V-1.5.3/veejay-client/share/button_looponce.png new file mode 100644 index 00000000..3e2e20d9 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_looponce.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_mini_decrement.png b/branches/V-1.5.3/veejay-client/share/button_mini_decrement.png new file mode 100644 index 00000000..46dbe3ea Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_mini_decrement.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_mini_increment.png b/branches/V-1.5.3/veejay-client/share/button_mini_increment.png new file mode 100644 index 00000000..f307df4c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_mini_increment.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_next.png b/branches/V-1.5.3/veejay-client/share/button_next.png new file mode 100644 index 00000000..d5902fb0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_next.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_pause.png b/branches/V-1.5.3/veejay-client/share/button_pause.png new file mode 100644 index 00000000..50b227a8 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_pause.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_play.png b/branches/V-1.5.3/veejay-client/share/button_play.png new file mode 100644 index 00000000..e63e771f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_play.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_playmode.png b/branches/V-1.5.3/veejay-client/share/button_playmode.png new file mode 100644 index 00000000..cdc841b0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_playmode.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_prev.png b/branches/V-1.5.3/veejay-client/share/button_prev.png new file mode 100644 index 00000000..653c503f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_prev.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_rand.png b/branches/V-1.5.3/veejay-client/share/button_rand.png new file mode 100644 index 00000000..f2dd61cc Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_rand.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_reverse.png b/branches/V-1.5.3/veejay-client/share/button_reverse.png new file mode 100644 index 00000000..59bd29e0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_reverse.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_right.png b/branches/V-1.5.3/veejay-client/share/button_right.png new file mode 100644 index 00000000..3ec7b43f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_right.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_skip.png b/branches/V-1.5.3/veejay-client/share/button_skip.png new file mode 100644 index 00000000..7d649bb5 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_skip.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_skull.png b/branches/V-1.5.3/veejay-client/share/button_skull.png new file mode 100644 index 00000000..bbed6da0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_skull.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_text.png b/branches/V-1.5.3/veejay-client/share/button_text.png new file mode 100644 index 00000000..bfd19e8d Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_text.png differ diff --git a/branches/V-1.5.3/veejay-client/share/button_up.png b/branches/V-1.5.3/veejay-client/share/button_up.png new file mode 100644 index 00000000..862e48ee Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/button_up.png differ diff --git a/branches/V-1.5.3/veejay-client/share/fx_entry_off.png b/branches/V-1.5.3/veejay-client/share/fx_entry_off.png new file mode 100644 index 00000000..adb5cafb Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/fx_entry_off.png differ diff --git a/branches/V-1.5.3/veejay-client/share/fx_entry_on.png b/branches/V-1.5.3/veejay-client/share/fx_entry_on.png new file mode 100644 index 00000000..8de23e6c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/fx_entry_on.png differ diff --git a/branches/V-1.5.3/veejay-client/share/gveejay-default.rc b/branches/V-1.5.3/veejay-client/share/gveejay-default.rc new file mode 100644 index 00000000..9fb9e798 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/gveejay-default.rc @@ -0,0 +1,21 @@ +# Edit these colors and fonts however you like. +style "default" +{ + xthickness = 1 + ythickness = 1 + GtkWidget::shadow_type = GTK_SHADOW_ETCHED_OUT + #GtkWidget::interior_focus = 0 + #GtkWidget::focus_padding = 0 + #GtkWidget::default_border = {0, 0, 0, 0} + #GtkWidget::default_outside_border = {0, 0, 0, 0} + GtkWidget::default_spacing = 0 + GtkScale::stepper_size = 8 + GtkRange::through-width = 4 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 10 + font_name = "Sans 8" +} + + +class "GtkWidget" style "default" diff --git a/branches/V-1.5.3/veejay-client/share/gveejay.glade b/branches/V-1.5.3/veejay-client/share/gveejay.glade new file mode 100644 index 00000000..7a8745eb --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/gveejay.glade @@ -0,0 +1,9693 @@ + + + + + + + True + gveejay - graphical veejay + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_EAST + True + + + + True + False + 3 + + + + True + False + 0 + + + + True + False + 3 + + + + True + True + False + 0 + + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + True + True + 0 + localhost + True + * + False + + + 0 + True + True + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 3490 1024 65535 1 4 4 + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + * + False + + + 0 + True + True + + + + + + True + Open EditList/Videofile + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + 0 + False + False + + + + + + + + True + veejay launch/connect + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + Launch/reconnect + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Cancel + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Screenshot + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Toggle Bezerk Mode + True + GTK_RELIEF_NORMAL + True + False + False + + + + + True + icon_berserk.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Display Debug + True + GTK_RELIEF_NORMAL + True + False + False + + + + + True + icon_bug.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Change Playback Mode + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_playmode.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Take Background Mask(diff overlay) + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_mask.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + False + False + + + + + True + icon_jack.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create a new solid colored stream + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_color.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Open Veejay Liveset / Action file + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Veejay Liveset / Actionfile + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Editlist positon + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 00000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 14 + False + 0 + + + 0 + False + False + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 0 + False + False + + + + + + True + Editlist frames + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 00000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 14 + False + 0 + + + 0 + False + False + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + 0.800000011921 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_fbw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_reverse.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_pause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_ffw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + True + True + True + GTK_POS_LEFT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 1 2 4 + + + + 0 + True + True + + + + + + True + 1 + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_prev.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_skip.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Mark current position as start of a new sample + True + [... + True + GTK_RELIEF_NORMAL + True + + + + 0 + True + True + + + + + + True + Mark current position as sample end and create new sample + True + ...] + True + GTK_RELIEF_NORMAL + True + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + True + False + GTK_POS_TOP + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.0010000000475 0.10000000149 0 + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + True + True + True + GTK_POS_BOTTOM + 2 + GTK_UPDATE_CONTINUOUS + True + 0 0 1 0.0500000007451 0.10000000149 0.20000000298 + + + + 0 + False + True + + + + + + True + True + True + GTK_POS_BOTTOM + 2 + GTK_UPDATE_CONTINUOUS + True + 1 0 1 0.00999999977648 0.10000000149 0 + + + + 0 + False + True + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + True + True + 0 + + + + + True + True + True + False + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_ETCHED_IN + GTK_CORNER_TOP_LEFT + + + + 230 + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + False + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + 33 + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + False + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + + + + + + + + 0 + True + True + + + + + False + True + + + + + + True + Console + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 5 + 2 + False + 0 + 3 + + + + True + Timecode + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Current position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Start position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + End position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + False + 0 + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 0 + False + False + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 0 + False + False + + + + + 1 + 2 + 0 + 1 + fill + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 25 25 + + + + 1 + 2 + 3 + 4 + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 25 25 + + + + 1 + 2 + 4 + 5 + + + + + + + True + Speed + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 -100 100 1 5 5 + + + + 1 + 2 + 2 + 3 + + + + + + + True + False + 0 + + + + True + 000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 0 + False + False + + + + + + True + Enable/disable effectchain + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + + True + EffectChain + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + False + + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Play once + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_looponce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + + True + Normal Loop + True + GTK_RELIEF_NORMAL + True + True + False + True + loop_none + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_bounce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + + True + Pingpong loop + True + GTK_RELIEF_NORMAL + True + False + False + True + loop_none + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_loop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + GTK_PACK_END + + + + + + + + True + <b>Loop Types</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Start / Stop randomizer + True + rand() + True + GTK_RELIEF_NORMAL + True + False + False + + + + 0 + False + False + + + + + + True + True + Free Style + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + + + True + <b>Sample randomizer</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + False + GTK_POS_LEFT + 4 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0 + + + + 0 + True + True + + + + + + True + True + False + GTK_POS_LEFT + 4 + GTK_UPDATE_CONTINUOUS + True + 0 0 1 0.00999999977648 0.10000000149 0 + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + Bind marker + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + True + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + Clear marker + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + + + True + <b>Markers</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + + + True + <b>Sample properties</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + True + EffectChain + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + + + 0 + True + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + False + True + + + + + + + False + True + + + + + + True + Color dial + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + True + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 5 + 2 + False + 0 + 0 + + + + True + Brightness + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Contrast + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Color + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + Hue + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 3 + 4 + fill + fill + + + + + + True + White + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 4 + 5 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + + True + Capture card settings + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + True + Capture card controls + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + Hardware controls + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + True + <b>Stream properties</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + Stream + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 3 + 2 + False + 0 + 5 + + + + True + <i>Starting position</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + <i>Duration:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + <i>Ending position:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 10 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + + + True + <b>Current Selection</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.270000010729 + 0 + 3 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 2 + 2 + False + 0 + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 10 10 + + + + 0 + 1 + 0 + 1 + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 10 10 + + + + 0 + 1 + 1 + 2 + + + + + + + True + Take current position as ending position + True + Set end + True + GTK_RELIEF_NORMAL + True + + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + Take current position as starting position + True + Set start + True + GTK_RELIEF_NORMAL + True + + + + 1 + 2 + 0 + 1 + fill + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + Cut selection to buffer + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_cut.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy selection to buffer + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Paste from buffer into editlist at current position + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selection (without buffer) + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_trash.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Crop to selection + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_crop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + Paste at position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 10 10 + + + 0 + True + True + + + + + + True + Paste buffer at position + True + Paste At! + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + 2 + False + True + + + + + + + + True + <b>EditList Operations</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 3 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + Editlist + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + 0 + True + True + + + + + + True + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + Play selected sample/stream + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + Open Samplelist + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Samplelist + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete Sample + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy sample to new + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + False + False + + + + + False + True + + + + + + True + Sample list + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + 0 + True + True + + + + + + True + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + Add Videofiles to EditList + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Selection + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save EditList + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Create sample from selection + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + False + True + + + + + + True + Editlist + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Samplelist + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + False + True + False + False + False + + + + + 0 + True + True + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + False + True + False + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + Entry enabled + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + 0 + True + True + + + + + + True + Set fade duration + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1 0.0500000007451 0.10000000149 0.10000000149 + + + + 0 + False + False + + + + + + True + Fade In + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_fadein.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Fade Out + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_fadeout.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Clear Entry + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create bundle + True + GTK_RELIEF_HALF + True + + + + + True + icon_bundle.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Clear Chain + True + GTK_RELIEF_HALF + True + + + + + True + icon_clearall.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P0 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 146 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P1 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P2 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 136 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P3 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P4 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 177 0 255 0 0 0 + + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P5 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 86 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P6 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 126 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + P7 + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + + + True + <b>Effect controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Loops + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Frames + True + GTK_RELIEF_NORMAL + True + True + False + True + sample_mulloop + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 10 10 + + + + 0 + True + True + + + + + + True + 00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 0 + False + False + + + + + 0 + False + False + + + + + + 133 + True + MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YV12 +YV16 + False + True + True + + + 0 + False + True + + + + + + True + True + Play when finished + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel recording + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + 0 + False + False + + + + + + + + True + <b>Record to sample</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + label389 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + No. of frames to record: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 10 10 + + + + 0 + True + True + + + + + + True + 0:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 16 + 3 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + 100 + True + MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YV12 +YV16 + False + True + True + + + 0 + False + True + + + + + + True + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + True + Play when finished + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + False + + + + + + True + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel recording + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + + PANGO_ELLIPSIZE_NONE + + + 0 + False + False + + + + + + + + True + <b>Record to sample</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + label390 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Effect controls + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + False + True + + + + + + + False + True + + + + + + True + Color picker + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + Effect mixing sources + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + False + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Effect Chain + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + False + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + True + + + + + 0 + True + True + + + + + + True + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + New + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Load Actionfile + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Write Actionfile + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + VIMS commands + True + GTK_RELIEF_NORMAL + True + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_question.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Set/Change Key + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keybind.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selected bundle + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Deatach Key from selected event + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keydetach.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Apply changes to this bundle + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Clear text + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + True + <b>VIMS Bundle</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + False + True + + + + + + True + VIMS Bundles + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + True + 0 + + + + 140 + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + 0 + True + True + + + + + + + + True + Device + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + True + Video4Linux / Digital Video + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + 0 + False + True + + + + + + True + True + True + 0 + + + + True + 2 + 5 + False + 0 + 4 + + + + True + True + Try + True + GTK_RELIEF_NORMAL + True + + + + 4 + 5 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 4490 1 65535 1 10 10 + + + 4 + 5 + 0 + 1 + + + + + + + True + Port Number + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + True + True + 0 + + True + * + False + + + 2 + 3 + 0 + 1 + + + + + + + True + Remote + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + Use multicast + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + + + True + Network + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + True + True + 0 + + + + True + 2 + 5 + False + 0 + 4 + + + + True + Filename + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + True + True + 0 + + True + * + False + + + 2 + 4 + 0 + 1 + + + + + + + True + True + Try + True + GTK_RELIEF_NORMAL + True + + + + 4 + 5 + 1 + 2 + fill + + + + + + + True + Load Actionfile + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 4 + 5 + 0 + 1 + fill + + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + use YUV4MPEG + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + use FFmpeg + True + GTK_RELIEF_NORMAL + True + False + False + True + inputstream_filey4m + + + 0 + False + False + + + + + + True + True + use picture + True + GTK_RELIEF_NORMAL + True + False + False + True + inputstream_filey4m + + + 0 + False + False + + + + + + + + + + True + Types + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + 1 + 0 + 2 + 3 + fill + fill + + + + + + + + True + File + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + + + True + <b>Input Streams</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + False + 0 + + + + True + False + 5 + + + + True + 2 + 4 + False + 0 + 0 + + + + True + Width: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Height: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + X offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + Y offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 10 10 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 10 10 + + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 10 10 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 10 10 + + + 3 + 4 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + True + SAR + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + + 0 + True + True + + + + + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + Fullscreen + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + 30 + True + wbmp,wmf,jpeg,ani,bmp,gif,ico,pcx,png,pnm,ras,tga,xmb,tiff,xpm,svg + True + True + True + 4 + jpg + False + * + False + + + 0 + False + True + + + + + + True + Apply changes to primary output settings + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_apply.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + + + True + <b>Primary Video Window (SDL)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Input/Output + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + + + True + False + 30 + + + + True + False + 3 + + + + True + 352x288 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + @ + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 25 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + fps + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + PAL + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Top First + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + 44000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Hz/ + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 16 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + bits/ + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 2 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Ch + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + 0 + True + True + + + + + + True + 1 + 0.5 + 0 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 3 + + + + True + Playing now: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 00000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 7 + False + 0 + + + 0 + False + False + + + + + + + 0 + True + True + + + + + label_item + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + True + True + 0 + 600:; + True + * + False + + + + 3 + True + True + + + + + + True + Send VIMS to veejay + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + VIMS commands + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_question.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + True + VIMS messenger + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + CPU remaining time + GTK_PROGRESS_RIGHT_TO_LEFT + 0 + 0.10000000149 + CPU remaining + PANGO_ELLIPSIZE_NONE + + + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + True + False + True + 0 + + True + * + False + + + 0 + False + False + + + + + + + + False + window1 + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_EAST + True + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 19 0 19 1 10 10 + + + + 0 + False + True + + + + + + True + True + True + True + 0 + + True + * + False + 15 + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + Render to selected entry + True + GTK_RELIEF_NORMAL + True + + + + True + icon_render.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Move to new sample + True + GTK_RELIEF_NORMAL + True + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + button116 + True + GTK_RELIEF_NORMAL + True + + + 0 + False + False + + + + + + + + + + + 0 + False + True + + + + + + + diff --git a/branches/V-1.5.3/veejay-client/share/gveejay.rc b/branches/V-1.5.3/veejay-client/share/gveejay.rc new file mode 100644 index 00000000..fbbfa605 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/gveejay.rc @@ -0,0 +1,137 @@ +# Edit these colors and fonts however you like. +style "default" +{ +# engine "hcengine" {} + xthickness = 1 + ythickness = 1 + GtkWidget::shadow_type = GTK_SHADOW_ETCHED_IN + #GtkWidget::interior_focus = 0 + #GtkWidget::focus_padding = 0 + #GtkWidget::default_border = {0, 0, 0, 0} + #GtkWidget::default_outside_border = {0, 0, 0, 0} + GtkWidget::default_spacing = 0 + GtkScale::stepper_size = 8 + GtkRange::through-width = 4 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 12 + + font_name = "Sans 8" + + fg[NORMAL] = "#646464" # borders etc. + fg[PRELIGHT] = "#646464" + fg[ACTIVE] = "#646464" # ook borders, van sliders en notebook + fg[SELECTED] = "#646464" + fg[INSENSITIVE] = "#404040" + + bg[NORMAL] = "#27282F" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#454f60" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + +style "text" +{ + font_name = "Sans 8" + + fg[NORMAL] = "#ffffff" # borders etc. + fg[PRELIGHT] = "#ffffff" + fg[ACTIVE] = "#ffffff" # ook borders, van sliders en notebook + fg[SELECTED] = "#ffffff" + fg[INSENSITIVE] = "#ffffff" + + bg[NORMAL] = "#27282F" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#454f60" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + + +style "buttons" +{ + + font_name = "Sans 8" + + fg[NORMAL] = "#888888" + fg[PRELIGHT] = "#888888" + fg[ACTIVE] = "#888888" + fg[SELECTED] = "#888888" + fg[INSENSITIVE] = "#888888" + + bg[NORMAL] = "#27282F" + bg[PRELIGHT] = "#aaacc1" + bg[ACTIVE] = "#454f60" + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} +style "treeview" = "default" +{ + engine "pixmap" + { + # don't draw the focus around listitems + image + { + function = FOCUS + } + } +} +style "header" +{ + + GtkTreeView::odd_row_color = "#2c2c2c" + GtkTreeView::even_row_color = "#555555" + +} + +class "GtkButton" style "buttons" +class "GtkSpinButton" style "buttons" +class "GtkToggleButton" style "buttons" +class "GtkCheckBox" style "buttons" +widget_class "*Tree*" style "header" +class "GtkTreeView" style "treeview" +class "GtkLabel" style "text" +class "*List" style "text" +class "GtkListItem" style "text" +class "*GtkCList*" style "text" +class "GtkWidget" style "default" diff --git a/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.glade b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.glade new file mode 100644 index 00000000..551a29cd --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.glade @@ -0,0 +1,18494 @@ + + + + + + + True + Reloaded - Connect to a veejay server + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ALWAYS + False + 356 + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + Reloaded Launcher + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + GTK_RELIEF_HALF + True + 0 + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Connect + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + False + GTK_PACK_END + + + + + + True + False + 3 + + + + True + veejay-logo-small.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + ver.3144 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 2 + 2 + False + 0 + 0 + + + + True + Hostname/IP address + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + True + True + 255 + localhost + True + * + False + + + + + 0 + 1 + 1 + 2 + + + + + + + True + Port + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 3490 1024 65535 1 0 0 + + + 1 + 2 + 1 + 2 + + + + + + + + + + + True + <b>Connection</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + 8 + False + True + + + + + + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + 0 + False + False + GTK_PACK_END + + + + + + + + VIMS Bundles + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + 600 + 548 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + New + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Load Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Write Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Set/Change Key + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keybind.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selected bundle + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Deatach Key from selected event + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keydetach.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + True + True + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + False + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + 0 + + + + True + Apply changes to this bundle + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + Clear text + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 1 + False + True + + + + + + + + True + <b>Edit VIMS message contents </b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + Preferences + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 2 + 20 + 0 + 0 + + + + True + 2 + 4 + True + 2 + 5 + + + + True + Width + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Image format + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 2 + 1 + 2 + fill + + + + + + + True + Height + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 4096 1 0 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 4096 1 0 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + Type extension to select image format (jpeg, png, ...) + True + True + True + 12 + jpeg + True + * + False + 5 + + + 2 + 4 + 1 + 2 + fill + + + + + + + + 0 + False + True + + + + + + + + + + True + <b>Screenshot Dimensions</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + False + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 20 + 12 + 0 + + + + True + 3 + 4 + True + 2 + 5 + + + + True + Width: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Height: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 176 1 800 1 0 0 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 144 1 800 1 0 0 + + + + 1 + 2 + 1 + 2 + fill + + + + + + + Frame delay + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 1 100 1 0 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + Keep 4:3 aspect + True + GTK_RELIEF_HALF + True + True + False + True + + + 2 + 4 + 1 + 2 + fill + + + + + + + True + FPS + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + False + 0 + + + + True + True + False + GTK_POS_TOP + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0.019999999553 1 0.019999999553 0 0 + + + + 0 + True + True + + + + + 1 + 3 + 2 + 3 + fill + fill + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 3 + 4 + 2 + 3 + fill + + + + + + + + + + + True + <b>Video preview</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 3 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + False + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 1 + + + + True + True + Record video from Viewport + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + True + False + + + + + + True + Configure Viewport + True + GTK_RELIEF_NORMAL + True + + + 0 + False + False + + + + + + + + + + True + <b>Viewport settings</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 20 + 12 + 0 + + + + True + False + 0 + + + + True + 2 + 4 + True + 2 + 5 + + + + True + Width: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Height: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + X offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + Y offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 2 0 4096 1 0 0 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 0 0 + + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 0 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 0 0 + + + 3 + 4 + 1 + 2 + fill + + + + + + 8 + True + True + + + + + + True + True + Keep 4:3 aspect + True + GTK_RELIEF_HALF + True + True + False + True + + + 2 + True + True + + + + + + True + True + Fullscreen (CTRL-F = window) + True + GTK_RELIEF_HALF + True + False + False + True + + + + 2 + True + True + + + + + + True + GTK_BUTTONBOX_START + 10 + + + + True + Apply changes to primary output settings + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-execute + 2 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Apply + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-close + 2 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close SDL + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + 0 + True + True + + + + + + + + + + True + <b>Primary Video Window (SDL)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + 0 + True + True + + + + + 3 + True + True + + + + + + + + GVeejay Reloaded - New input stream + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + 400 + 400 + True + False + icon_stream.png + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + 340 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + True + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + Double click to active, single click column for changing settings + True + True + False + False + True + False + False + False + + + + + + + + True + <b>Device</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + True + False + 0 + + + + True + 2 + 4 + False + 0 + 4 + + + + True + True + True + True + 200 + localhost + True + * + False + + + 2 + 3 + 0 + 1 + + + + + + + True + Remote + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + Use multicast + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Port Number + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 4490 1 65535 1 0 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + True + Try + True + GTK_RELIEF_HALF + True + + + + 3 + 4 + 1 + 2 + + + + + + + + + True + <b>Network</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 2 + 5 + False + 0 + 4 + + + + True + Filename + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + use YUV4MPEG + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + use FFmpeg + True + GTK_RELIEF_HALF + True + False + False + True + inputstream_filey4m + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + True + True + 0 + + True + * + False + + + 2 + 4 + 0 + 1 + + + + + + + True + True + Try + True + GTK_RELIEF_HALF + True + + + 4 + 5 + 1 + 2 + fill + + + + + + + True + Load Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 4 + 5 + 0 + 1 + fill + + + + + + + + + True + <b>File</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 1 + 4 + False + 0 + 0 + + + + True + Close this window + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-close + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 3 + 4 + 0 + 1 + shrink + shrink + + + + + 0 + False + False + + + + + + + + + + True + <b>Stream types</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + False + ladida + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0 + GTK_SHADOW_NONE + + + + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + * + False + + + + 0 + True + True + + + + + + + + + + True + Open advanced properties dialog + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + gtk-preferences + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + True + <b>Video File</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Open Veejay Liveset / Action file + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + bg_red.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Veejay Liveset / Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + bg_yellow.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel + True + GTK_RELIEF_HALF + True + + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + + + + + + True + Play selected slot + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + + True + True + button119 + True + GTK_RELIEF_HALF + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + GTK_POS_TOP + 0 + GTK_UPDATE_CONTINUOUS + False + 0.10000000149 0 1 0.00999999977648 0.10000000149 0 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + Reloaded + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + veejay-icon.png + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + True + False + 0 + + + + True + + + + True + _GVeejay + True + + + + + + + True + Sample + True + + + + True + button_loop.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _New from file + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Copy + True + + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Delete + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + Stream + True + + + + True + icon_stream.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _New + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _New Solid + True + + + + + True + icon_color.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Delete + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _MIDI + True + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _learn MIDI + True + False + + + + + + + True + _MIDI enable + True + False + midilearn + + + + + + + True + + + + + + True + _Clear MIDI layout + True + + + + + + + + + + + True + _Save + True + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + Save samplelist + True + + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save actionfile + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save MIDI layout + True + + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Load + True + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + Load samplelist + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load actionfile + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load MIDI layout + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load Calibration + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + + + + + + True + gtk-quit + True + + + + + + + + + + + True + + + + + + True + _View + True + + + + + + + True + Preferences + True + + + + + True + gtk-preferences + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + Image Calibration + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + VIMS _Bundles + True + + + + + True + icon_bundle.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Help + True + + + + + + + True + About Reloaded + True + + + + + True + icon_question.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Report a problem + True + + + + + True + icon_bug.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + Enable or disable selected FX + True + + True + GTK_RELIEF_HALF + True + True + False + True + + + + 0 + False + False + + + + + + + + + + 36 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 19 1 0 0 + + + + 0 + False + True + + + + + + True + True + True + True + 0 + + True + * + False + 15 + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p0</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 146 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p1</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 201 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p2</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 255 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p3</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p4</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p5</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 86 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p6</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 126 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + + 0 + False + False + + + + + + + + True + <b>p7</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Mixing effects + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Image effects + True + GTK_RELIEF_HALF + True + False + False + True + mixing_effects + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + False + GTK_POS_RIGHT + False + False + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + video effects + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 270 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + image effects + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 270 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>FX list</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + + True + False + 0 + + + + + + + 0 + True + True + + + + + + + + + False + True + + + + + + True + <b>mixing sources</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_NONE + + + + True + False + True + + + + + + + False + True + + + + + + True + <b>RGB control</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + + + True + <b>FX controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>FX</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + <b>current control:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + P0 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + True + False + + + + + + True + Toggle keyframing for this chain entry + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_keyframe.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + 0 + + + + True + Apply this keyframe + True + GTK_RELIEF_HALF + True + + + + + True + icon_apply.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + Start keyframing + True + GTK_RELIEF_HALF + True + False + False + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Reset + True + GTK_RELIEF_HALF + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 1 + 8 + False + 0 + 0 + + + + True + True + 0 + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + 2 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + True + 3 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + 4 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 4 + 5 + 0 + 1 + fill + + + + + + + True + True + 5 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 5 + 6 + 0 + 1 + fill + + + + + + + True + True + 6 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 6 + 7 + 0 + 1 + fill + + + + + + + True + True + 7 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 7 + 8 + 0 + 1 + fill + + + + + + + True + True + 1 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 1 + 2 + 0 + 1 + fill + + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + 0 + 1 + 0 + 1 + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + Linear + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Spline + True + GTK_RELIEF_HALF + True + False + False + True + curve_typelinear + + + + 0 + False + False + + + + + + True + True + Freehand + True + GTK_RELIEF_HALF + True + False + False + True + curve_typelinear + + + + 0 + False + False + + + + + + + + True + <b>Curve drawing method</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 2 + 5 + False + 0 + 0 + + + + True + startframe + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 1 + 2 + 0 + 1 + + + + + + + True + endframe + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 3 + 4 + 0 + 1 + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 0 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.490000009537 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 0 + False + 0 + + + 3 + 4 + 1 + 2 + fill + + + + + + + Update start/end + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_refresh.png + 0.5 + 0.5 + 0 + 0 + + + + + 4 + 5 + 1 + 2 + fill + + + + + + + + + True + <b>timeline</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>FX Anim</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 4 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Play and repeat sample grid + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Play and record this sequence to a new sample + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Stop recording from this sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 30 + 0 + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + + + 0 + True + True + + + + + + + + + + True + <b>SEQ record to new sample</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + + + + + + + + 0 + True + True + + + + + + True + Click an empty slot to place current selected sample. + SHIFT-Click a slot to remove the sample. + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + True + <b>Sample Grid</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + + False + True + + + + + + True + <b>SEQ</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Add Track + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close Track + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + False + False + + + + + + True + False + 0 + + + + + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_reverse.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_pause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_skip.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_dec.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_inc.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_prev.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + + + + + True + <b>Sync controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + sync start! + True + GTK_RELIEF_NORMAL + True + + + + + True + sync.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>MT</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + New SRT Sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_text.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + 25 + True + 1 +2 +3 +4 +5 + False + True + True + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 6 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + 0 + + + + True + Delete this SRT Sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + button_skull.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Apply Text and Start/End position + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_apply.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Load SRT file + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + Save SRT file + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + + + + 0 + False + False + GTK_PACK_END + + + + + + + + True + Select a SRT sequence or create new + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + True + Edit subtitle + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 3 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + 75 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 0 + False + True + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + End + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + 75 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 0 + False + True + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + + + + + True + Change frame start and frame end position + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 5 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 6 + 0 + 12 + 0 + + + + True + False + 0 + + + + 100 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Veejay Font + False + True + True + + + + + + + True + Font face + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100 1 0 0 + + + + + + + True + Size + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + <b>X</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1000 1 0 0 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + <b>Y</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1000 1 0 0 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + True + Position + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + + + + + True + Change font face, size and position + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 5 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 5 + 0 + 12 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Outline + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Border + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this foreground color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Foreground color + True + FG + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this background color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Background color + True + BG + True + GTK_RELIEF_NORMAL + True + False + False + True + textcolorfg + + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this line color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Line color + True + LC + True + GTK_RELIEF_NORMAL + True + False + False + True + textcolorfg + + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 17 + 0 + 4 + 4 + + + + True + 4 + 5 + False + 0 + 0 + + + + 24 + 24 + True + + + 1 + 2 + 0 + 1 + fill + + + + + + 24 + 24 + True + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + 24 + 24 + True + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 0 + 1 + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 1 + 2 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 2 + 3 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 255 1 10 0 + + + + 2 + 5 + 3 + 4 + fill + fill + + + + + + True + <b>R</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + 4 + fill + + + + + + + True + <b>G</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + 4 + fill + + + + + + + True + <b>B</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + 4 + fill + + + + + + + True + <b>A</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + 4 + fill + + + + + + + + 0 + True + True + + + + + + + + + + + + True + Change foreground,background and linecolor + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + + + + False + True + + + + + + True + <b>SRT</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + False + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 2 + + + + True + False + 0 + + + + True + False + 0 + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + True + + + + + + True + Enable/disable effectchain + True + GTK_RELIEF_HALF + True + True + False + True + + + + + True + Effect chain enabled + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + True + GTK_PACK_END + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 6 + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 7 + False + 0 + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 20 + 0 + + + + True + False + 0 + + + + True + True + Loops + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Frames + True + GTK_RELIEF_HALF + True + True + False + True + sample_mulloop + + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + + + + + + + + + True + <b>Timecode</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 0 0 + + + + + + + True + <b>Duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + VJ20 (YUV 4:2:0 Planar) +VJ22 (YUV 4:2:2 Planar) +MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YV16 (YCbCr 4:2:2 Planar) +I420 (YCbCr 4:2:0 Planar) +Quicktime-DV +Quicktime-MJPEG +MLZO +YUV (current) + False + True + True + + + + + + True + <b>Codec</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_HALF + True + + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Cancel recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + Auto play sample after recording + True + Autoplay + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + False + False + + + + + 0 + False + True + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + + + + True + <b>Recording Progress</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>Record to Disk</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 15 + 0 + 12 + 51 + + + + True + False + 0 + + + + True + True + True + True + 0 + Untitled + True + * + False + + + 0 + False + False + + + + + + True + True + Change title + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + True + + + + + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 8 + False + False + + + + + + True + End position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Playback speed + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 8 + False + False + + + + + + True + Slow motion multiplier + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 0 0 + + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 0 0 + + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 -25 25 1 0 0 + + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 1 12 1 0 0 + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + + + True + + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + False + True + + + + + + True + <b>Properties</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Create sample from selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save EditList + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Add Videofiles to EditList + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + 2 + 3 + False + 0 + 0 + + + + True + 00000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + Positon + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + Total frames + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + 000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + True + 3 + 2 + False + 0 + 5 + + + + True + <i>Starting position</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + <i>Duration:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + <i>Ending position:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 0 + 1 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 2 + 3 + + + + + + 0 + False + True + + + + + + True + 2 + 2 + False + 0 + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 0 0 + + + + 1 + 2 + 1 + 2 + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 0 0 + + + + 1 + 2 + 0 + 1 + + + + + + True + Take current position as starting position + True + Set start + True + GTK_RELIEF_HALF + True + + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Take current position as ending position + True + Set end + True + GTK_RELIEF_HALF + True + + + + 0 + 1 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + Cut selection to buffer + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_cut.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy selection to buffer + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Paste from buffer into editlist at current position + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selection (without buffer) + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_trash.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Crop to selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_crop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Paste at this position + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 0 0 + + + 0 + True + True + + + + + + True + Paste buffer at position + True + GTK_RELIEF_HALF + True + + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>EditList</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Frames: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 50 0 999999 1 0 0 + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 0 + False + False + + + + + + True + True + Effect chain enabled + True + GTK_RELIEF_HALF + True + True + False + True + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 8 + False + 0 + + + + + + True + <b>Timecode</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 0 0 + + + + + + + True + <b>Duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + 120 + True + VJ20 (YUV 4:2:0 Planar 0-255/0-255) +VJ22 (YUV 4:2:2 Planar 0-255/0-255) +MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YV16 (YCbCr 4:2:2 Planar, 16-235/16-240) +I420 (YCbCr 4:2:0 Planar, 16-235/16-240) +Quicktime-DV +Quicktime-MJPEG +MLZO +YUV (current) + False + True + True + + + + + + True + <b>Codec</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + False + False + True + + + + True + Autoplay + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + + PANGO_ELLIPSIZE_NONE + + + + + + + + + + True + <b>Recording progress</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>Record to Disk</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + True + + + + False + True + + + + + + True + <b>Solid Stream</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + True + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 6 + 2 + False + 0 + 0 + + + + True + Brightness + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Contrast + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 4 + 5 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 0 + 1 + fill + + + + + + True + Color + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 5 + 6 + fill + fill + + + + + + True + Hue + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + True + White + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + Saturation + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 3 + 4 + fill + fill + + + + + + + + + + True + <b>capture card controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + <b>Video4Linux</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + Stream + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 7 + 2 + True + 0 + 0 + + + + True + Interlacing + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + Top First + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + Norm + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + PAL + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 3 + 4 + fill + + + + + + + True + Audio bits + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + 16 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 4 + 5 + fill + + + + + + + True + Audio Channels + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + 2 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 5 + 6 + fill + + + + + + + True + Audio rate + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 6 + 7 + fill + + + + + + + True + 44000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 6 + 7 + fill + + + + + + + True + Resolution + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + 25 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + 352x288 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + FPS + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + + + + False + True + + + + + + True + Plain + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + False + True + + + + + + True + <b>Sample</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + liveview on/off + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + gray + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + Very low quality preview + True + 1/8 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + Low quality preview + True + 1/4 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + Medium quality preview + True + 1/2 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + High quality preview + True + 1/1 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + 3 + False + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + veejay-logo.png + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 2 + 6 + True + 0 + 0 + + + + True + Length: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 7 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 1 + 2 + 0 + 1 + + + + + + + True + 00000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 5 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + Time: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + + + + + + + True + Frame: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 3 + 4 + 0 + 1 + + + + + + + True + 00000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 3 + 4 + 1 + 2 + + + + + + + True + M: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + 5 + 0 + 1 + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 5 + 6 + 0 + 1 + + + + + + + True + hint + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 5 + 6 + 1 + 2 + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_fbw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_reverse.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_pause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_ffw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_prev.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_skip.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Change Playback Mode + True + GTK_RELIEF_HALF + True + + + + + True + icon_playmode.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Mark current position as start of a new sample + True + [... + True + GTK_RELIEF_HALF + True + + + + 0 + False + False + + + + + + True + Mark current position as sample end and create new sample + True + ...] + True + GTK_RELIEF_HALF + True + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Toggle Bezerk Mode + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_berserk.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Take Background Mask(diff overlay) + True + GTK_RELIEF_HALF + True + + + + + True + icon_mask.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + 0 + False + True + GTK_PACK_END + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 2 + 0 + 0 + 2 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Normal Loop + True + GTK_RELIEF_HALF + True + True + False + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_loop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Random Frame + True + GTK_RELIEF_HALF + True + False + False + True + loop_normal + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_bounce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 2 + 0 + 32 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + Play once + True + GTK_RELIEF_NORMAL + True + False + False + True + loop_normal + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_looponce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + 0 + False + False + + + + + + True + Random Frame + True + GTK_RELIEF_HALF + True + False + False + True + loop_normal + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_rand.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + 50 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 0 0 0 0 + + + + 0 + True + True + + + + + + 50 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 1 0 13 0 0 0 + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + GTK_RELIEF_NONE + True + + + + + True + button_back.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + Active bank: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100 1 0 0 + + + + 0 + True + True + + + + + + + + + 0 + True + False + + + + + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + GTK_RELIEF_NONE + True + + + + + True + button_next.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + + + + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>Samplebank</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_ALWAYS + GTK_SHADOW_ETCHED_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + 1 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Fade in FX Chain + True + GTK_RELIEF_HALF + True + + + + + True + icon_fadein.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Fade Out FX Chain + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_fadeout.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 6 + False + False + + + + + 0 + False + True + + + + + + True + Toggle logarithmic scale + True + Log + True + GTK_RELIEF_HALF + True + False + False + True + + + 1 + False + False + + + + + + 82 + True + True + False + GTK_POS_LEFT + 1 + GTK_UPDATE_CONTINUOUS + True + 0 0 255 1 10 0 + + + + 0 + True + True + + + + + + True + Switch to sample #B after completing fade. + True + GTK_RELIEF_HALF + True + False + False + True + + + + + True + icon_follow.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Create bundle + True + GTK_RELIEF_HALF + True + + + + + True + icon_bundle.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Clear Entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Cut entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_cut.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Copy entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Paste entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Enable/Disable all keyframes + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_keyframe.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Clear Chain + True + GTK_RELIEF_HALF + True + + + + + True + icon_clearall.png + 0.5 + 0.5 + 0 + 0 + + + + + 100 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + FX Chain Fade duration in frames + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0.949999999255 0 1 0.0500000007451 0 0 + + + + 0 + True + True + + + + + 0 + False + False + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>FX Chain</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Take Screenshot + True + GTK_RELIEF_HALF + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + + localhost:3490 + True + GTK_RELIEF_HALF + True + + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + Disconnect + True + GTK_RELIEF_HALF + True + + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Display Debug + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_bug.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Enable jack + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_jack.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Display OSD status + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_osd.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Enable/Disable EDL Cache (see veejay console) + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_cache.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Drop audio/video frames and keep in sync (by default enabled) + True + Sync + True + GTK_RELIEF_NORMAL + True + True + False + + + + 0 + False + False + + + + + + + + + + + + + + True + <b>Actions</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + 150 + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + * + False + + + + 3 + True + True + + + + + + True + Send VIMS to veejay + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + _Clear + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + repeat + True + GTK_RELIEF_NORMAL + True + False + False + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + True + <b>VIMS messenger</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>Veejay</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Refresh Veejay's Working Directory + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + True + False + False + False + + + + + 0 + True + True + + + + + + + + + 0 + True + True + + + + + + True + Listing of Veejay's working directory. Doube click a row to add it as a Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>Media</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Add a video or image file as a new sample + True + GTK_RELIEF_HALF + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create a new stream (v4l, dv, network ...) + True + GTK_RELIEF_HALF + True + + + + + True + icon_stream.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create a new solid colored stream + True + GTK_RELIEF_HALF + True + + + + + True + icon_color.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Open Samplelist + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Samplelist + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy sample to new + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selected slot + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Switch to property panel + True + GTK_RELIEF_HALF + True + + + + + True + gtk-preferences + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Randomize sample duration, free cut-off + True + Free Style + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + False + True + + + + + + True + Start / Stop randomizer + True + GTK_RELIEF_HALF + True + False + False + + + + + 20 + 20 + True + button_rand.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Pause event playback + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + + True + icon_macropause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Start recording events (keyboard and user interface) + True + GTK_RELIEF_NORMAL + True + False + False + True + macrostop + + + + + True + icon_macrorec.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Start playing recorded events + True + GTK_RELIEF_NORMAL + True + False + False + True + macrostop + + + + + True + icon_macroplay.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Clear recorded events + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_macroclear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + 24 + 24 + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + 24 + 24 + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + 150 + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 25 1 100 1 10 0 + + + + 0 + False + True + + + + + + True + Fallback to default framerate + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_refresh.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + 400 + True + False + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + [hostname] + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 12 + False + False + + + + + + True + [port] + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + 110 + True + cpumeter + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 96 + True + cache filled + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + False + True + + + + + + 84 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + + + Image Calibration + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + + True + False + 0 + + + + True + Please select a source to calibrate + False + False + GTK_JUSTIFY_LEFT + False + False + 0.0399999991059 + 0.5 + 0 + 4 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + Calibrate Stream + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + True + <b>Select a Source</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + Source + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.97000002861 + 0.5 + 0 + 1 + 0 + 0 + 12 + 0 + + + + True + True + View DarkFrame + True + GTK_RELIEF_NORMAL + True + + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + 352 + 288 + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Dark Frame + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.97000002861 + 0.5 + 0 + 1 + 0 + 0 + 12 + 0 + + + + True + True + View LightFrame + True + GTK_RELIEF_NORMAL + True + + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Light Frame + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.97000002861 + 0.5 + 0 + 1 + 0 + 0 + 12 + 0 + + + + True + True + View FlatFrame + True + GTK_RELIEF_NORMAL + True + + + + + + + + 0 + False + True + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Flat Frame + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Frames + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 10 0 10000 1 10 10 + + + 0 + False + True + + + + + + + + + + True + <b>Duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 8 + 8 + 8 + + + + True + False + 0 + + + + True + Method + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + 0 + 0 + GTK_SHADOW_NONE + + + + True + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + Median + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + True + Average + True + GTK_RELIEF_NORMAL + True + True + False + True + cali_method_median + + + 0 + False + False + + + + + + + + + + True + + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0 + 1 + 0.439999997616 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 64 1 10 10 + + + 0 + True + True + + + + + + True + Kernel Size + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + + + True + <b>Combine</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + Stream + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Global + True + GTK_RELIEF_NORMAL + True + False + False + True + radiobutton6 + + + 0 + False + False + + + + + + + + + + True + <b>Run configuration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0 + 0.00999999977648 + 1 + 1 + 0 + 0 + 133 + 132 + + + + True + False + 58 + + + + True + True + Reset + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + True + Take Black Frames + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + False + True + Save + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + + + + 8 + False + True + + + + + 0 + False + True + + + + + + + diff --git a/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.glade.bak b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.glade.bak new file mode 100644 index 00000000..43f9d77b --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.glade.bak @@ -0,0 +1,18494 @@ + + + + + + + True + Reloaded - Connect to a veejay server + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ALWAYS + False + 356 + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + Reloaded Launcher + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + GTK_RELIEF_HALF + True + 0 + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Connect + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + False + GTK_PACK_END + + + + + + True + False + 3 + + + + True + veejay-logo-small.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + ver.3144 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 2 + 2 + False + 0 + 0 + + + + True + Hostname/IP address + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + True + True + 255 + localhost + True + * + False + + + + + 0 + 1 + 1 + 2 + + + + + + + True + Port + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 3490 1024 65535 1 0 0 + + + 1 + 2 + 1 + 2 + + + + + + + + + + + True + <b>Connection</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + 8 + False + True + + + + + + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + 0 + False + False + GTK_PACK_END + + + + + + + + VIMS Bundles + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + 600 + 548 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + New + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Load Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Write Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Set/Change Key + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keybind.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selected bundle + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Deatach Key from selected event + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keydetach.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + True + True + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + False + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + 0 + + + + True + Apply changes to this bundle + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + Clear text + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 1 + False + True + + + + + + + + True + <b>Edit VIMS message contents </b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + Preferences + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + False + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 2 + 20 + 0 + 0 + + + + True + 2 + 4 + True + 2 + 5 + + + + True + Width + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Image format + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 2 + 1 + 2 + fill + + + + + + + True + Height + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 4096 1 0 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 4096 1 0 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + Type extension to select image format (jpeg, png, ...) + True + True + True + 12 + jpeg + True + * + False + 5 + + + 2 + 4 + 1 + 2 + fill + + + + + + + + 0 + False + True + + + + + + + + + + True + <b>Screenshot Dimensions</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + False + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 20 + 12 + 0 + + + + True + 3 + 4 + True + 2 + 5 + + + + True + Width: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Height: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 176 1 800 1 0 0 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 144 1 800 1 0 0 + + + + 1 + 2 + 1 + 2 + fill + + + + + + + Frame delay + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 1 100 1 0 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + Keep 4:3 aspect + True + GTK_RELIEF_HALF + True + True + False + True + + + 2 + 4 + 1 + 2 + fill + + + + + + + True + FPS + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + False + 0 + + + + True + True + False + GTK_POS_TOP + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0.019999999553 1 0.019999999553 0 0 + + + + 0 + True + True + + + + + 1 + 3 + 2 + 3 + fill + fill + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 3 + 4 + 2 + 3 + fill + + + + + + + + + + + True + <b>Video preview</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 3 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + False + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 1 + + + + True + True + Record video from Viewport + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + True + False + + + + + + True + Configure Viewport + True + GTK_RELIEF_NORMAL + True + + + 0 + False + False + + + + + + + + + + True + <b>Viewport settings</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 20 + 12 + 0 + + + + True + False + 0 + + + + True + 2 + 4 + True + 2 + 5 + + + + True + Width: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Height: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + X offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + Y offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 2 0 4096 1 0 0 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 0 0 + + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 0 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 0 0 + + + 3 + 4 + 1 + 2 + fill + + + + + + 8 + True + True + + + + + + True + True + Keep 4:3 aspect + True + GTK_RELIEF_HALF + True + True + False + True + + + 2 + True + True + + + + + + True + True + Fullscreen (CTRL-F = window) + True + GTK_RELIEF_HALF + True + False + False + True + + + + 2 + True + True + + + + + + True + GTK_BUTTONBOX_START + 10 + + + + True + Apply changes to primary output settings + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-execute + 2 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Apply + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-close + 2 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close SDL + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + 0 + True + True + + + + + + + + + + True + <b>Primary Video Window (SDL)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + 0 + True + True + + + + + 3 + True + True + + + + + + + + GVeejay Reloaded - New input stream + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + 400 + 400 + True + False + icon_stream.png + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + 340 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + True + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + Double click to active, single click column for changing settings + True + True + False + False + True + False + False + False + + + + + + + + True + <b>Device</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + True + False + 0 + + + + True + 2 + 4 + False + 0 + 4 + + + + True + True + True + True + 200 + localhost + True + * + False + + + 2 + 3 + 0 + 1 + + + + + + + True + Remote + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + Use multicast + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Port Number + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 4490 1 65535 1 0 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + True + Try + True + GTK_RELIEF_HALF + True + + + + 3 + 4 + 1 + 2 + + + + + + + + + True + <b>Network</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 2 + 5 + False + 0 + 4 + + + + True + Filename + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + use YUV4MPEG + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + use FFmpeg + True + GTK_RELIEF_HALF + True + False + False + True + inputstream_filey4m + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + True + True + 0 + + True + * + False + + + 2 + 4 + 0 + 1 + + + + + + + True + True + Try + True + GTK_RELIEF_HALF + True + + + 4 + 5 + 1 + 2 + fill + + + + + + + True + Load Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 4 + 5 + 0 + 1 + fill + + + + + + + + + True + <b>File</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 1 + 4 + False + 0 + 0 + + + + True + Close this window + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-close + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 3 + 4 + 0 + 1 + shrink + shrink + + + + + 0 + False + False + + + + + + + + + + True + <b>Stream types</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + False + ladida + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0 + GTK_SHADOW_NONE + + + + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + * + False + + + + 0 + True + True + + + + + + + + + + True + Open advanced properties dialog + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + gtk-preferences + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + True + <b>Video File</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Open Veejay Liveset / Action file + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + bg_red.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Veejay Liveset / Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + bg_yellow.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel + True + GTK_RELIEF_HALF + True + + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + + + + + + True + Play selected slot + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + + True + True + button119 + True + GTK_RELIEF_HALF + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + GTK_POS_TOP + 0 + GTK_UPDATE_CONTINUOUS + False + 0.10000000149 0 1 0.00999999977648 0.10000000149 0 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + Reloaded + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + veejay-icon.png + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + True + False + 0 + + + + True + + + + True + _GVeejay + True + + + + + + + True + Sample + True + + + + True + button_loop.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _New from file + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Copy + True + + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Delete + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + Stream + True + + + + True + icon_stream.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _New + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _New Solid + True + + + + + True + icon_color.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Delete + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _MIDI + True + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _learn MIDI + True + False + + + + + + + True + _MIDI enable + True + False + midilearn + + + + + + + True + + + + + + True + _Clear MIDI layout + True + + + + + + + + + + + True + _Save + True + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + Save samplelist + True + + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save actionfile + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save MIDI layout + True + + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Load + True + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + Load samplelist + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load actionfile + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load MIDI layout + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load Calibration + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + + + + + + True + gtk-quit + True + + + + + + + + + + + True + + + + + + True + _View + True + + + + + + + True + Preferences + True + + + + + True + gtk-preferences + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + Image Calibration + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + VIMS _Bundles + True + + + + + True + icon_bundle.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Help + True + + + + + + + True + About Reloaded + True + + + + + True + icon_question.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Report a problem + True + + + + + True + icon_bug.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + Enable or disable selected FX + True + + True + GTK_RELIEF_HALF + True + True + False + True + + + + 0 + False + False + + + + + + + + + + 36 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 19 1 0 0 + + + + 0 + False + True + + + + + + True + True + True + True + 0 + + True + * + False + 15 + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p0</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 146 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p1</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 201 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p2</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 255 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p3</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p4</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p5</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 86 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + + + True + <b>p6</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 126 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + + 0 + False + False + + + + + + + + True + <b>p7</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Mixing effects + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Image effects + True + GTK_RELIEF_HALF + True + False + False + True + mixing_effects + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + False + GTK_POS_RIGHT + False + False + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + video effects + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 270 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + image effects + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 270 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>FX list</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + + True + False + 0 + + + + + + + 0 + True + True + + + + + + + + + False + True + + + + + + True + <b>mixing sources</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_NONE + + + + True + False + True + + + + + + + False + True + + + + + + True + <b>RGB control</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + + + True + <b>FX controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>FX</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + <b>current control:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + P0 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + True + False + + + + + + True + Toggle keyframing for this chain entry + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_keyframe.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + 0 + + + + True + Apply this keyframe + True + GTK_RELIEF_HALF + True + + + + + True + icon_apply.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + Start keyframing + True + GTK_RELIEF_HALF + True + False + False + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Reset + True + GTK_RELIEF_HALF + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 1 + 8 + False + 0 + 0 + + + + True + True + 0 + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + 2 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + True + 3 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + 4 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 4 + 5 + 0 + 1 + fill + + + + + + + True + True + 5 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 5 + 6 + 0 + 1 + fill + + + + + + + True + True + 6 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 6 + 7 + 0 + 1 + fill + + + + + + + True + True + 7 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 7 + 8 + 0 + 1 + fill + + + + + + + True + True + 1 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 1 + 2 + 0 + 1 + fill + + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + 0 + 1 + 0 + 1 + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + Linear + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Spline + True + GTK_RELIEF_HALF + True + False + False + True + curve_typelinear + + + + 0 + False + False + + + + + + True + True + Freehand + True + GTK_RELIEF_HALF + True + False + False + True + curve_typelinear + + + + 0 + False + False + + + + + + + + True + <b>Curve drawing method</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 2 + 5 + False + 0 + 0 + + + + True + startframe + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 1 + 2 + 0 + 1 + + + + + + + True + endframe + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 3 + 4 + 0 + 1 + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 0 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.490000009537 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 0 + False + 0 + + + 3 + 4 + 1 + 2 + fill + + + + + + + Update start/end + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_refresh.png + 0.5 + 0.5 + 0 + 0 + + + + + 4 + 5 + 1 + 2 + fill + + + + + + + + + True + <b>timeline</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>FX Anim</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 4 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Play and repeat sample grid + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Play and record this sequence to a new sample + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Stop recording from this sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 30 + 0 + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + + + 0 + True + True + + + + + + + + + + True + <b>SEQ record to new sample</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + + + + + + + + 0 + True + True + + + + + + True + Click an empty slot to place current selected sample. + SHIFT-Click a slot to remove the sample. + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + True + <b>Sample Grid</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + + False + True + + + + + + True + <b>SEQ</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Add Track + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close Track + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + False + False + + + + + + True + False + 0 + + + + + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_reverse.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_pause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_skip.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_dec.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_inc.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_prev.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + + + + + True + <b>Sync controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + sync start! + True + GTK_RELIEF_NORMAL + True + + + + + True + sync.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>MT</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + New SRT Sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_text.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + 25 + True + 1 +2 +3 +4 +5 + False + True + True + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 6 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + 0 + + + + True + Delete this SRT Sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + button_skull.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Apply Text and Start/End position + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_apply.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Load SRT file + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + Save SRT file + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + + + + 0 + False + False + GTK_PACK_END + + + + + + + + True + Select a SRT sequence or create new + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + True + Edit subtitle + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 3 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + 75 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 0 + False + True + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + End + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + 75 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 0 0 + + + + 0 + False + True + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + + + + + True + Change frame start and frame end position + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 5 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 6 + 0 + 12 + 0 + + + + True + False + 0 + + + + 100 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Veejay Font + False + True + True + + + + + + + True + Font face + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100 1 0 0 + + + + + + + True + Size + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + <b>X</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1000 1 0 0 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + <b>Y</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1000 1 0 0 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + True + Position + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + + + + + True + Change font face, size and position + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 5 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 5 + 0 + 12 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Outline + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Border + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this foreground color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Foreground color + True + FG + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this background color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Background color + True + BG + True + GTK_RELIEF_NORMAL + True + False + False + True + textcolorfg + + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this line color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Line color + True + LC + True + GTK_RELIEF_NORMAL + True + False + False + True + textcolorfg + + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 17 + 0 + 4 + 4 + + + + True + 4 + 5 + False + 0 + 0 + + + + 24 + 24 + True + + + 1 + 2 + 0 + 1 + fill + + + + + + 24 + 24 + True + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + 24 + 24 + True + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 0 + 1 + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 1 + 2 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 2 + 3 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 255 1 10 0 + + + + 2 + 5 + 3 + 4 + fill + fill + + + + + + True + <b>R</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + 4 + fill + + + + + + + True + <b>G</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + 4 + fill + + + + + + + True + <b>B</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + 4 + fill + + + + + + + True + <b>A</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + 4 + fill + + + + + + + + 0 + True + True + + + + + + + + + + + + True + Change foreground,background and linecolor + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + + + + False + True + + + + + + True + <b>SRT</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + False + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 2 + + + + True + False + 0 + + + + True + False + 0 + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + True + + + + + + True + Enable/disable effectchain + True + GTK_RELIEF_HALF + True + True + False + True + + + + + True + Effect chain enabled + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + True + GTK_PACK_END + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 6 + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 7 + False + 0 + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 20 + 0 + + + + True + False + 0 + + + + True + True + Loops + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Frames + True + GTK_RELIEF_HALF + True + True + False + True + sample_mulloop + + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + + + + + + + + + True + <b>Timecode</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 0 0 + + + + + + + True + <b>Duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + VJ20 (YUV 4:2:0 Planar) +VJ22 (YUV 4:2:2 Planar) +MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YV16 (YCbCr 4:2:2 Planar) +I420 (YCbCr 4:2:0 Planar) +Quicktime-DV +Quicktime-MJPEG +MLZO +YUV (current) + False + True + True + + + + + + True + <b>Codec</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_HALF + True + + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Cancel recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + Auto play sample after recording + True + Autoplay + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + False + False + + + + + 0 + False + True + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + + + + True + <b>Recording Progress</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>Record to Disk</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 15 + 0 + 12 + 51 + + + + True + False + 0 + + + + True + True + True + True + 0 + Untitled + True + * + False + + + 0 + False + False + + + + + + True + True + Change title + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + True + + + + + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 8 + False + False + + + + + + True + End position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Playback speed + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 8 + False + False + + + + + + True + Slow motion multiplier + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 0 0 + + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 0 0 + + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 -25 25 1 0 0 + + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 1 12 1 0 0 + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + + + + True + + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + False + True + + + + + + True + <b>Properties</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Create sample from selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save EditList + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Add Videofiles to EditList + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + 2 + 3 + False + 0 + 0 + + + + True + 00000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + Positon + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + Total frames + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + 000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + True + 3 + 2 + False + 0 + 5 + + + + True + <i>Starting position</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + <i>Duration:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + <i>Ending position:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 0 + 1 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 2 + 3 + + + + + + 0 + False + True + + + + + + True + 2 + 2 + False + 0 + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 0 0 + + + + 1 + 2 + 1 + 2 + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 0 0 + + + + 1 + 2 + 0 + 1 + + + + + + True + Take current position as starting position + True + Set start + True + GTK_RELIEF_HALF + True + + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Take current position as ending position + True + Set end + True + GTK_RELIEF_HALF + True + + + + 0 + 1 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + Cut selection to buffer + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_cut.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy selection to buffer + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Paste from buffer into editlist at current position + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selection (without buffer) + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_trash.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Crop to selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_crop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Paste at this position + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 0 0 + + + 0 + True + True + + + + + + True + Paste buffer at position + True + GTK_RELIEF_HALF + True + + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>EditList</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Frames: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 50 0 999999 1 0 0 + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 0 + False + False + + + + + + True + True + Effect chain enabled + True + GTK_RELIEF_HALF + True + True + False + True + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 8 + False + 0 + + + + + + True + <b>Timecode</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 0 0 + + + + + + + True + <b>Duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + 120 + True + VJ20 (YUV 4:2:0 Planar 0-255/0-255) +VJ22 (YUV 4:2:2 Planar 0-255/0-255) +MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YV16 (YCbCr 4:2:2 Planar, 16-235/16-240) +I420 (YCbCr 4:2:0 Planar, 16-235/16-240) +Quicktime-DV +Quicktime-MJPEG +MLZO +YUV (current) + False + True + True + + + + + + True + <b>Codec</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + False + False + True + + + + True + Autoplay + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + + PANGO_ELLIPSIZE_NONE + + + + + + + + + + True + <b>Recording progress</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>Record to Disk</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + True + + + + False + True + + + + + + True + <b>Solid Stream</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + True + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 6 + 2 + False + 0 + 0 + + + + True + Brightness + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Contrast + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 4 + 5 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 0 + 1 + fill + + + + + + True + Color + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 5 + 6 + fill + fill + + + + + + True + Hue + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + True + White + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + Saturation + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 3 + 4 + fill + fill + + + + + + + + + + True + <b>capture card controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + <b>Video4Linux</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + Stream + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 7 + 2 + True + 0 + 0 + + + + True + Interlacing + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + Top First + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + Norm + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + PAL + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 3 + 4 + fill + + + + + + + True + Audio bits + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + 16 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 4 + 5 + fill + + + + + + + True + Audio Channels + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + 2 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 5 + 6 + fill + + + + + + + True + Audio rate + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 6 + 7 + fill + + + + + + + True + 44000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 6 + 7 + fill + + + + + + + True + Resolution + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + 25 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + 352x288 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + FPS + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + + + + False + True + + + + + + True + Plain + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + False + True + + + + + + True + <b>Sample</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + liveview on/off + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + gray + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + Very low quality preview + True + 1/8 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + Low quality preview + True + 1/4 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + Medium quality preview + True + 1/2 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + High quality preview + True + 1/1 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + 3 + False + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + veejay-logo.png + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 2 + 6 + True + 0 + 0 + + + + True + Length: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 7 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 1 + 2 + 0 + 1 + + + + + + + True + 00000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 5 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + Time: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + + + + + + + True + Frame: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 3 + 4 + 0 + 1 + + + + + + + True + 00000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 3 + 4 + 1 + 2 + + + + + + + True + M: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + 5 + 0 + 1 + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 5 + 6 + 0 + 1 + + + + + + + True + hint + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 5 + 6 + 1 + 2 + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_fbw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_reverse.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_pause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_ffw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_prev.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_skip.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + False + False + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Change Playback Mode + True + GTK_RELIEF_HALF + True + + + + + True + icon_playmode.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Mark current position as start of a new sample + True + [... + True + GTK_RELIEF_HALF + True + + + + 0 + False + False + + + + + + True + Mark current position as sample end and create new sample + True + ...] + True + GTK_RELIEF_HALF + True + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Toggle Bezerk Mode + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_berserk.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Take Background Mask(diff overlay) + True + GTK_RELIEF_HALF + True + + + + + True + icon_mask.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + 0 + False + True + GTK_PACK_END + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 2 + 0 + 0 + 2 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Normal Loop + True + GTK_RELIEF_HALF + True + True + False + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_loop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Random Frame + True + GTK_RELIEF_HALF + True + False + False + True + loop_normal + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_bounce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 0 + 1 + 0 + 2 + 0 + 32 + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + Play once + True + GTK_RELIEF_NORMAL + True + False + False + True + loop_normal + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_looponce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + 0 + False + False + + + + + + True + Random Frame + True + GTK_RELIEF_HALF + True + False + False + True + loop_normal + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_rand.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + 50 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 0 0 0 0 + + + + 0 + True + True + + + + + + 50 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 1 0 13 0 0 0 + + + + 0 + True + True + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + GTK_RELIEF_NONE + True + + + + + True + button_back.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + Active bank: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100 1 0 0 + + + + 0 + True + True + + + + + + + + + 0 + True + False + + + + + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + GTK_RELIEF_NONE + True + + + + + True + button_next.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + + + + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>Samplebank</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_ALWAYS + GTK_SHADOW_ETCHED_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + 1 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Fade in FX Chain + True + GTK_RELIEF_HALF + True + + + + + True + icon_fadein.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Fade Out FX Chain + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_fadeout.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 6 + False + False + + + + + 0 + False + True + + + + + + True + Toggle logarithmic scale + True + Log + True + GTK_RELIEF_HALF + True + False + False + True + + + 1 + False + False + + + + + + 82 + True + True + False + GTK_POS_LEFT + 1 + GTK_UPDATE_CONTINUOUS + True + 0 0 255 1 10 0 + + + + 0 + True + True + + + + + + True + Switch to sample #B after completing fade. + True + GTK_RELIEF_HALF + True + False + False + True + + + + + True + icon_follow.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Create bundle + True + GTK_RELIEF_HALF + True + + + + + True + icon_bundle.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Clear Entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Cut entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_cut.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Copy entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Paste entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Enable/Disable all keyframes + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_keyframe.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Clear Chain + True + GTK_RELIEF_HALF + True + + + + + True + icon_clearall.png + 0.5 + 0.5 + 0 + 0 + + + + + 100 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + FX Chain Fade duration in frames + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0.949999999255 0 1 0.0500000007451 0 0 + + + + 0 + True + True + + + + + 0 + False + False + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>FX Chain</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Take Screenshot + True + GTK_RELIEF_HALF + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + + localhost:3490 + True + GTK_RELIEF_HALF + True + + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + Disconnect + True + GTK_RELIEF_HALF + True + + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Display Debug + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_bug.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Enable jack + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_jack.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Display OSD status + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_osd.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Enable/Disable EDL Cache (see veejay console) + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_cache.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Drop audio/video frames and keep in sync (by default enabled) + True + Sync + True + GTK_RELIEF_NORMAL + True + True + False + + + + 0 + False + False + + + + + + + + + + + + + + True + <b>Actions</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + 150 + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + * + False + + + + 3 + True + True + + + + + + True + Send VIMS to veejay + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + _Clear + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + repeat + True + GTK_RELIEF_NORMAL + True + False + False + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + True + <b>VIMS messenger</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>Veejay</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Refresh Veejay's Working Directory + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + True + False + False + False + + + + + 0 + True + True + + + + + + + + + 0 + True + True + + + + + + True + Listing of Veejay's working directory. Doube click a row to add it as a Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>Media</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Add a video or image file as a new sample + True + GTK_RELIEF_HALF + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create a new stream (v4l, dv, network ...) + True + GTK_RELIEF_HALF + True + + + + + True + icon_stream.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create a new solid colored stream + True + GTK_RELIEF_HALF + True + + + + + True + icon_color.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Open Samplelist + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Samplelist + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy sample to new + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selected slot + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Switch to property panel + True + GTK_RELIEF_HALF + True + + + + + True + gtk-preferences + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + Randomize sample duration, free cut-off + True + Free Style + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + False + True + + + + + + True + Start / Stop randomizer + True + GTK_RELIEF_HALF + True + False + False + + + + + 20 + 20 + True + button_rand.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Pause event playback + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + + True + icon_macropause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Start recording events (keyboard and user interface) + True + GTK_RELIEF_NORMAL + True + False + False + True + macrostop + + + + + True + icon_macrorec.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Start playing recorded events + True + GTK_RELIEF_NORMAL + True + False + False + True + macrostop + + + + + True + icon_macroplay.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Clear recorded events + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_macroclear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + 24 + 24 + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + 24 + 24 + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + 150 + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 25 1 100 1 10 0 + + + + 0 + False + True + + + + + + True + Fallback to default framerate + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_refresh.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + 400 + True + False + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + [hostname] + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 12 + False + False + + + + + + True + [port] + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + 110 + True + cpumeter + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 70 + True + cache filled + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + 109 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + + + Image Calibration + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + + True + False + 0 + + + + True + Please select a source to calibrate + False + False + GTK_JUSTIFY_LEFT + False + False + 0.0399999991059 + 0.5 + 0 + 4 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + Calibrate Stream + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + True + <b>Select a Source</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + Source + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.97000002861 + 0.5 + 0 + 1 + 0 + 0 + 12 + 0 + + + + True + True + View DarkFrame + True + GTK_RELIEF_NORMAL + True + + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + 352 + 288 + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Dark Frame + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.97000002861 + 0.5 + 0 + 1 + 0 + 0 + 12 + 0 + + + + True + True + View LightFrame + True + GTK_RELIEF_NORMAL + True + + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Light Frame + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.97000002861 + 0.5 + 0 + 1 + 0 + 0 + 12 + 0 + + + + True + True + View FlatFrame + True + GTK_RELIEF_NORMAL + True + + + + + + + + 0 + False + True + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_IN + + + + True + 0.5 + 0.5 + 0 + 0 + + + + + + + 0 + True + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + Flat Frame + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + Frames + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 10 0 10000 1 10 10 + + + 0 + False + True + + + + + + + + + + True + <b>Duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 8 + 8 + 8 + + + + True + False + 0 + + + + True + Method + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + 0 + 0 + GTK_SHADOW_NONE + + + + True + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + Median + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + True + Average + True + GTK_RELIEF_NORMAL + True + True + False + True + cali_method_median + + + 0 + False + False + + + + + + + + + + True + + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0 + 1 + 0.439999997616 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 64 1 10 10 + + + 0 + True + True + + + + + + True + Kernel Size + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + + + True + <b>Combine</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + Stream + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + True + Global + True + GTK_RELIEF_NORMAL + True + False + False + True + radiobutton6 + + + 0 + False + False + + + + + + + + + + True + <b>Run configuration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0 + 0.00999999977648 + 1 + 1 + 0 + 0 + 133 + 132 + + + + True + False + 58 + + + + True + True + Reset + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + True + Take Black Frames + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + False + True + Save + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + + + + 8 + False + True + + + + + 0 + False + True + + + + + + + diff --git a/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.gladep b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.gladep new file mode 100644 index 00000000..183077ba --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.gladep @@ -0,0 +1,8 @@ + + + + + + + FALSE + diff --git a/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.gladep.bak b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.gladep.bak new file mode 100644 index 00000000..183077ba --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/gveejay.reloaded.gladep.bak @@ -0,0 +1,8 @@ + + + + + + + FALSE + diff --git a/branches/V-1.5.3/veejay-client/share/high_contrast.rc b/branches/V-1.5.3/veejay-client/share/high_contrast.rc new file mode 100644 index 00000000..56e9763a --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/high_contrast.rc @@ -0,0 +1,118 @@ +# Edit these colors and fonts however you like. +style "default" +{ + engine "hcengine" {} + xthickness = 1 + ythickness = 1 + GtkWidget::shadow_type = GTK_SHADOW_ETCHED_OUT + #GtkWidget::interior_focus = 0 + #GtkWidget::focus_padding = 0 + #GtkWidget::default_border = {0, 0, 0, 0} + #GtkWidget::default_outside_border = {0, 0, 0, 0} + GtkWidget::default_spacing = 0 + GtkScale::stepper_size = 8 + GtkRange::through-width = 4 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 10 + + font_name = "Sans 8" + + fg[NORMAL] = "#000000" # borders etc. + fg[PRELIGHT] = "#ffffff" + fg[ACTIVE] = "#000000" # ook borders, van sliders en notebook + fg[SELECTED] = "#ffffff" + fg[INSENSITIVE] = "#c0c0c0" + + bg[NORMAL] = "#ffffff" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#c0c0c0" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#00ff00" + bg[INSENSITIVE] = "#ffffff" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#050505" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#c0c0c0" + base[PRELIGHT] = "#00fff0" # achtergrond van lists, status bars + base[ACTIVE] = "#0000ff" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + +style "text" +{ + font_name = "Sans 8" + + fg[NORMAL] = "#ffffff" # borders etc. + fg[PRELIGHT] = "#ffffff" + fg[ACTIVE] = "#ffffff" # ook borders, van sliders en notebook + fg[SELECTED] = "#ffffff" + fg[INSENSITIVE] = "#ffffff" + + bg[NORMAL] = "#27282F" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#454f60" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + + +style "buttons" +{ + + font_name = "Sans 8" + + fg[NORMAL] = "#888888" + fg[PRELIGHT] = "#888888" + fg[ACTIVE] = "#888888" + fg[SELECTED] = "#888888" + fg[INSENSITIVE] = "#888888" + + bg[NORMAL] = "#27282F" + bg[PRELIGHT] = "#aaacc1" + bg[ACTIVE] = "#454f60" + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + + + +class "GtkButton" style "default" +class "GtkSpinButton" style "default" +class "GtkToggleButton" style "default" +class "GtkCheckBox" style "default" + +class "GtkLabel" style "default" + +class "GtkWidget" style "default" diff --git a/branches/V-1.5.3/veejay-client/share/icon_apply.png b/branches/V-1.5.3/veejay-client/share/icon_apply.png new file mode 100644 index 00000000..cb075f1f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_apply.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_berserk.png b/branches/V-1.5.3/veejay-client/share/icon_berserk.png new file mode 100644 index 00000000..6270ece0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_berserk.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_bezerk.png b/branches/V-1.5.3/veejay-client/share/icon_bezerk.png new file mode 100644 index 00000000..6270ece0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_bezerk.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_bounce.png b/branches/V-1.5.3/veejay-client/share/icon_bounce.png new file mode 100644 index 00000000..82bbce6a Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_bounce.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_bug.png b/branches/V-1.5.3/veejay-client/share/icon_bug.png new file mode 100644 index 00000000..a6582fe7 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_bug.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_bundle.png b/branches/V-1.5.3/veejay-client/share/icon_bundle.png new file mode 100644 index 00000000..ffd2d178 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_bundle.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_cache.png b/branches/V-1.5.3/veejay-client/share/icon_cache.png new file mode 100644 index 00000000..e4d90492 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_cache.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_clear.png b/branches/V-1.5.3/veejay-client/share/icon_clear.png new file mode 100644 index 00000000..512b6623 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_clear.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_clearall.png b/branches/V-1.5.3/veejay-client/share/icon_clearall.png new file mode 100644 index 00000000..709fdeb8 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_clearall.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_color.png b/branches/V-1.5.3/veejay-client/share/icon_color.png new file mode 100644 index 00000000..291ccf01 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_color.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_connect.png b/branches/V-1.5.3/veejay-client/share/icon_connect.png new file mode 100644 index 00000000..49cb2217 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_connect.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_copy.png b/branches/V-1.5.3/veejay-client/share/icon_copy.png new file mode 100644 index 00000000..9d14bc7e Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_copy.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_crop.png b/branches/V-1.5.3/veejay-client/share/icon_crop.png new file mode 100644 index 00000000..5b35f81a Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_crop.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_cut.png b/branches/V-1.5.3/veejay-client/share/icon_cut.png new file mode 100644 index 00000000..05fe1a0c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_cut.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_disconnect.png b/branches/V-1.5.3/veejay-client/share/icon_disconnect.png new file mode 100644 index 00000000..84217c10 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_disconnect.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_fadein.png b/branches/V-1.5.3/veejay-client/share/icon_fadein.png new file mode 100644 index 00000000..797fe2fe Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_fadein.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_fadeout.png b/branches/V-1.5.3/veejay-client/share/icon_fadeout.png new file mode 100644 index 00000000..78f8946d Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_fadeout.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_follow.png b/branches/V-1.5.3/veejay-client/share/icon_follow.png new file mode 100644 index 00000000..59fb755a Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_follow.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_jack.png b/branches/V-1.5.3/veejay-client/share/icon_jack.png new file mode 100644 index 00000000..cf2fe3fb Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_jack.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_keybind.png b/branches/V-1.5.3/veejay-client/share/icon_keybind.png new file mode 100644 index 00000000..fd7b0994 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_keybind.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_keydetach.png b/branches/V-1.5.3/veejay-client/share/icon_keydetach.png new file mode 100644 index 00000000..c3ce1b77 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_keydetach.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_keyframe.png b/branches/V-1.5.3/veejay-client/share/icon_keyframe.png new file mode 100644 index 00000000..498668a0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_keyframe.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_launch.png b/branches/V-1.5.3/veejay-client/share/icon_launch.png new file mode 100644 index 00000000..49cb2217 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_launch.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_loop.png b/branches/V-1.5.3/veejay-client/share/icon_loop.png new file mode 100644 index 00000000..aacf503f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_loop.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_looponce.png b/branches/V-1.5.3/veejay-client/share/icon_looponce.png new file mode 100644 index 00000000..08475a7d Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_looponce.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_macroclear.png b/branches/V-1.5.3/veejay-client/share/icon_macroclear.png new file mode 100644 index 00000000..c1f61079 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_macroclear.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_macropause.png b/branches/V-1.5.3/veejay-client/share/icon_macropause.png new file mode 100644 index 00000000..a06f6f7c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_macropause.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_macroplay.png b/branches/V-1.5.3/veejay-client/share/icon_macroplay.png new file mode 100644 index 00000000..db42baa9 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_macroplay.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_macrorec.png b/branches/V-1.5.3/veejay-client/share/icon_macrorec.png new file mode 100644 index 00000000..5e304b50 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_macrorec.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_mask.png b/branches/V-1.5.3/veejay-client/share/icon_mask.png new file mode 100644 index 00000000..8b7fbec5 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_mask.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_minus.png b/branches/V-1.5.3/veejay-client/share/icon_minus.png new file mode 100644 index 00000000..03059371 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_minus.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_new.png b/branches/V-1.5.3/veejay-client/share/icon_new.png new file mode 100644 index 00000000..c553eb00 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_new.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_noloop.png b/branches/V-1.5.3/veejay-client/share/icon_noloop.png new file mode 100644 index 00000000..fef7bfcf Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_noloop.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_open.png b/branches/V-1.5.3/veejay-client/share/icon_open.png new file mode 100644 index 00000000..4df40ebc Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_open.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_openlist.png b/branches/V-1.5.3/veejay-client/share/icon_openlist.png new file mode 100644 index 00000000..a7487645 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_openlist.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_openstream.png b/branches/V-1.5.3/veejay-client/share/icon_openstream.png new file mode 100644 index 00000000..3f0bc34d Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_openstream.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_osd.png b/branches/V-1.5.3/veejay-client/share/icon_osd.png new file mode 100644 index 00000000..e195c9ad Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_osd.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_paste.png b/branches/V-1.5.3/veejay-client/share/icon_paste.png new file mode 100644 index 00000000..337df33c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_paste.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_plarge.png b/branches/V-1.5.3/veejay-client/share/icon_plarge.png new file mode 100644 index 00000000..f1116bfd Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_plarge.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_playmode.png b/branches/V-1.5.3/veejay-client/share/icon_playmode.png new file mode 100644 index 00000000..efe2350f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_playmode.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_plus.png b/branches/V-1.5.3/veejay-client/share/icon_plus.png new file mode 100644 index 00000000..830a8024 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_plus.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_psmall.png b/branches/V-1.5.3/veejay-client/share/icon_psmall.png new file mode 100644 index 00000000..ec2e287a Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_psmall.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_question.png b/branches/V-1.5.3/veejay-client/share/icon_question.png new file mode 100644 index 00000000..dab7e54f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_question.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_record.png b/branches/V-1.5.3/veejay-client/share/icon_record.png new file mode 100644 index 00000000..80d7747b Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_record.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_recordstop.png b/branches/V-1.5.3/veejay-client/share/icon_recordstop.png new file mode 100644 index 00000000..924b1085 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_recordstop.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_recstop.png b/branches/V-1.5.3/veejay-client/share/icon_recstop.png new file mode 100644 index 00000000..c2e2d09c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_recstop.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_refresh.png b/branches/V-1.5.3/veejay-client/share/icon_refresh.png new file mode 100644 index 00000000..5d141530 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_refresh.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_render.png b/branches/V-1.5.3/veejay-client/share/icon_render.png new file mode 100644 index 00000000..d3dc9659 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_render.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_save.png b/branches/V-1.5.3/veejay-client/share/icon_save.png new file mode 100644 index 00000000..cd1e9455 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_save.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_saveas.png b/branches/V-1.5.3/veejay-client/share/icon_saveas.png new file mode 100644 index 00000000..514ef83c Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_saveas.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_screenshot.png b/branches/V-1.5.3/veejay-client/share/icon_screenshot.png new file mode 100644 index 00000000..dba2ed23 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_screenshot.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_send.png b/branches/V-1.5.3/veejay-client/share/icon_send.png new file mode 100644 index 00000000..3ccdfc88 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_send.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_skull.png b/branches/V-1.5.3/veejay-client/share/icon_skull.png new file mode 100644 index 00000000..a9de432f Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_skull.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_stream.png b/branches/V-1.5.3/veejay-client/share/icon_stream.png new file mode 100644 index 00000000..cdc841b0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_stream.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_trash.png b/branches/V-1.5.3/veejay-client/share/icon_trash.png new file mode 100644 index 00000000..6b3933ce Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_trash.png differ diff --git a/branches/V-1.5.3/veejay-client/share/icon_video.png b/branches/V-1.5.3/veejay-client/share/icon_video.png new file mode 100644 index 00000000..cdc841b0 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/icon_video.png differ diff --git a/branches/V-1.5.3/veejay-client/share/knob.png b/branches/V-1.5.3/veejay-client/share/knob.png new file mode 100644 index 00000000..af1ac70a Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/knob.png differ diff --git a/branches/V-1.5.3/veejay-client/share/reloaded_classic.glade b/branches/V-1.5.3/veejay-client/share/reloaded_classic.glade new file mode 100644 index 00000000..a61514df --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/reloaded_classic.glade @@ -0,0 +1,16209 @@ + + + + + + + Reloaded + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 900 + 640 + True + False + veejay-icon.png + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + True + False + 0 + + + + True + False + 0 + + + + True + + + + True + _GVeejay + True + + + + + + + True + Sample + True + + + + True + button_loop.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _New from file + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Copy + True + + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Delete + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + Stream + True + + + + True + icon_stream.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _New + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _New Solid + True + + + + + True + icon_color.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _Delete + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _MIDI + True + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + _learn MIDI + True + True + + + + + + + True + _MIDI enable + True + True + midilearn + + + + + + + + + + + True + _Save + True + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + Save samplelist + True + + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save actionfile + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save MIDI layout + True + + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Load + True + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + True + Load samplelist + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load actionfile + True + + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Load MIDI layout + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + + + + + + True + gtk-quit + True + + + + + + + + + + + True + + + + + + True + _View + True + + + + + + + True + Preferences + True + + + + + True + gtk-preferences + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + VIMS Console + True + + + + + True + gtk-dialog-info + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + VIMS _Bundles + True + + + + + True + icon_bundle.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Help + True + + + + + + + True + About Reloaded + True + + + + + True + icon_question.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Report a problem + True + + + + + True + icon_bug.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + True + True + + + + + + True + cpumeter + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 100 + True + cache filled + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + localhost:3490 + True + GTK_RELIEF_HALF + True + + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + Disconnect + True + GTK_RELIEF_HALF + True + + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Toggle Bezerk Mode + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_berserk.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Display Debug + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_bug.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Change Playback Mode + True + GTK_RELIEF_HALF + True + + + + + True + icon_playmode.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Take Background Mask(diff overlay) + True + GTK_RELIEF_HALF + True + + + + + True + icon_mask.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Enable jack + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_jack.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Take Screenshot + True + GTK_RELIEF_HALF + True + + + + + True + icon_screenshot.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Display OSD status + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_osd.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Enable/Disable EDL Cache (see veejay console) + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_cache.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Drop audio/video frames and keep in sync (by default enabled) + True + Sync + True + GTK_RELIEF_NORMAL + True + True + False + + + + 0 + False + False + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + False + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + Play once + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_looponce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Normal Loop + True + GTK_RELIEF_HALF + True + True + False + True + loop_none + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_loop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Pingpong loop + True + GTK_RELIEF_HALF + True + False + False + True + loop_none + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_bounce.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Random Frame + True + GTK_RELIEF_HALF + True + False + False + True + loop_none + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_rand.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + True + <b>loop controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + Loops + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + True + + + + + + True + True + Frames + True + GTK_RELIEF_HALF + True + True + False + True + sample_mulloop + + + + 0 + True + True + + + + + + True + 00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 7 + False + 0 + + + 0 + True + False + + + + + + + + + + True + <b>units</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 10 10 + + + + + + + True + <b>duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + 120 + True + MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YUV +Quicktime-DV +Quicktime-MJPEG +MLZO + False + True + True + + + + + + True + <b>codec</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_HALF + True + + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + True + + + + + + True + Cancel recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + Auto play sample after recording + True + Autoplay + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + + + + True + <b>progress</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>record</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 3 + 2 + False + 0 + 0 + + + + True + End position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Start position + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 25 25 + + + + 1 + 2 + 0 + 1 + fill + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 1000000000 1 25 25 + + + + 1 + 2 + 1 + 2 + fill + + + + + + True + Playback speed + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 -25 25 1 5 5 + + + + 1 + 2 + 2 + 3 + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + Slow motion multiplier + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 1 12 1 10 10 + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + Set title + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + True + True + True + 0 + Untitled + True + * + False + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + Enable/disable effectchain + True + GTK_RELIEF_HALF + True + True + False + True + + + + + True + Effect chain enabled + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + False + + + + + False + True + + + + + + True + <b>properties</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + False + 0 + + + + True + False + 0 + + + + True + True + True + False + False + True + False + False + False + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Create sample from selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save EditList + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Add Videofiles to EditList + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + 2 + 3 + False + 0 + 0 + + + + True + 00000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + Positon + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + Total frames + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + 000000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 11 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + True + 3 + 2 + False + 0 + 5 + + + + True + <i>Starting position</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + + + + + + + True + <i>Duration:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + + True + <i>Ending position:</i> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 0 + 1 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 1 + 2 + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 10 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + 1 + 2 + 2 + 3 + + + + + + 0 + False + True + + + + + + True + 2 + 2 + False + 0 + 0 + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 10 10 + + + + 1 + 2 + 1 + 2 + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 10 10 + + + + 1 + 2 + 0 + 1 + + + + + + True + Take current position as starting position + True + Set start + True + GTK_RELIEF_HALF + True + + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Take current position as ending position + True + Set end + True + GTK_RELIEF_HALF + True + + + + 0 + 1 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + Cut selection to buffer + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_cut.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy selection to buffer + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Paste from buffer into editlist at current position + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selection (without buffer) + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_trash.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Crop to selection + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_crop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Paste at this position + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100000000 1 10 10 + + + 0 + True + True + + + + + + True + Paste buffer at position + True + GTK_RELIEF_HALF + True + + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + True + <b>EditList Operations</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 3 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + <b>EDL</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 50 0 999999 1 10 10 + + + + + + + True + <b>Frames:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 10 + False + 0 + + + + + + True + <b>Timecode:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + + + True + <b>Ficticious length</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 8 + False + 0 + + + + + + True + <b>timecode</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 9999999 1 10 10 + + + + + + + True + <b>duration</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + 120 + True + MJPEG +DVVIDEO +MPEG4 +MSMPEG4V3 +YUV +Quicktime-DV +Quicktime-MJPEG +MLZO + False + True + True + + + + + + True + <b>codec</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Start recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel recording + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + False + False + True + + + + True + Autoplay + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + + PANGO_ELLIPSIZE_NONE + + + + + + True + <b>Recording progress</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>record</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + True + Effect chain enabled + True + GTK_RELIEF_HALF + True + True + False + True + + + + + + False + True + + + + + + True + <b>properties</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + True + + + + False + True + + + + + + True + <b>solid</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + True + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 6 + 2 + False + 0 + 0 + + + + True + Brightness + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Contrast + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 4 + 5 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 0 + 1 + fill + + + + + + True + Color + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 5 + 6 + fill + fill + + + + + + True + Hue + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + True + White + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + Saturation + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0 1 0.00999999977648 0.10000000149 0.10000000149 + + + + 1 + 2 + 3 + 4 + fill + fill + + + + + + + + True + Capture card settings + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + True + <b>capture card controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + False + True + + + + + + True + <b>v4l</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + Stream + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + 7 + 2 + False + 0 + 0 + + + + True + fps + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + 25 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + Interlacing + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + Top First + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + Norm + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + PAL + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 3 + 4 + fill + + + + + + + True + Audio bits + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 4 + 5 + fill + + + + + + + True + 16 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 4 + 5 + fill + + + + + + + True + Audio Channels + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 5 + 6 + fill + + + + + + + True + 2 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 5 + 6 + fill + + + + + + + True + Audio rate + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 6 + 7 + fill + + + + + + + True + 44000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 6 + 7 + fill + + + + + + + True + 352x288 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + Resolution + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + + + + + + False + True + + + + + + True + Plain + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + Enable or disable selected FX + True + + True + GTK_RELIEF_HALF + True + True + False + True + + + + 0 + False + False + + + + + + + + + + 36 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 19 1 10 10 + + + + 0 + False + True + + + + + + True + True + True + True + 0 + + True + * + False + 15 + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + + + True + <b>p0</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 146 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + + + True + <b>p1</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 201 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + + + True + <b>p2</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 0 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + + + True + <b>p3</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + + + True + <b>p4</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 96 0 255 0 0 0 + + + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + + + True + <b>p5</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 86 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + True + + + + + + + + True + <b>p6</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + GTK_POS_BOTTOM + 0 + GTK_UPDATE_CONTINUOUS + True + 126 0 255 0 0 0 + + + + 0 + True + True + + + + + + True + 0.5 + 0.5 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + + 0 + False + False + + + + + + + + True + <b>p7</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + <b>mixing sources</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Mixing effects + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Image effects + True + GTK_RELIEF_HALF + True + False + False + True + mixing_effects + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + False + GTK_POS_RIGHT + False + False + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + video effects + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 270 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + False + True + + + + + + True + image effects + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 270 + + + tab + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>FX list</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_NONE + + + + True + False + True + + + + + + + False + True + + + + + + True + <b>RGB control</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + + + True + <b>FX controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + 352 + 288 + True + veejay-logo.png + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + True + <b>preview</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + enable + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + grayscale + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + True + False + + + + + + True + False + 0 + + + + True + Quality + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + Very low quality preview + True + 1/8 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + Low quality preview + True + 1/4 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + Medium quality preview + True + 1/2 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + High quality preview + True + 1/1 + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + True + <b>preview settings</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + 0 + True + True + + + + + + True + False + 0 + + + + 82 + True + True + False + GTK_POS_LEFT + 1 + GTK_UPDATE_CONTINUOUS + True + 0 0 255 1 10 0 + + + + 0 + True + True + + + + + + True + Toggle logarithmic scale + True + Log + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + + + True + <b>effects chain</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + Create bundle + True + GTK_RELIEF_HALF + True + + + + + True + icon_bundle.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Clear Entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Cut entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_cut.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Copy entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Paste entry + True + GTK_RELIEF_HALF + True + + + + + True + icon_paste.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Enable/Disable all keyframes + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_keyframe.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + Clear Chain + True + GTK_RELIEF_HALF + True + + + + + True + icon_clearall.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Set fade duration + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1 0.0500000007451 0.10000000149 0.10000000149 + + + + 0 + True + True + + + + + + True + Fade In + True + GTK_RELIEF_HALF + True + + + + + True + icon_fadein.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Fade Out + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_fadeout.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + True + <b>Auto chain fade</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 3 + 5 + False + 0 + 0 + + + + True + L: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + T: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + 0:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + 00000000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 3 + 4 + 1 + 2 + fill + + + + + + + True + F: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + + True + 00000 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 5 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + Sample + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 7 + False + 0 + + + 0 + 1 + 1 + 2 + shrink + shrink + + + + + + True + M: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 12 + False + 0 + + + 1 + 2 + 2 + 3 + fill + + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 3 + 4 + 2 + 3 + fill + + + + + + + True + PM: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 2 + 3 + fill + + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 4 + 5 + 2 + 3 + fill + + + + + + + + + True + <b>status</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Pause event playback + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + + True + icon_macropause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Start recording events (keyboard and user interface) + True + GTK_RELIEF_NORMAL + True + False + False + True + macrostop + + + + + True + icon_macrorec.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Start playing recorded events + True + GTK_RELIEF_NORMAL + True + False + False + True + macrostop + + + + + True + icon_macroplay.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Clear recorded events + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_macroclear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + True + <b>keystroke recorder</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + 60 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 0 0 0 0 + + + + 0 + True + True + + + + + + 60 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 0 0 0 0 + + + + 0 + True + True + + + + + + + + + + True + <b>playback speed</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + 24 + 24 + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_decrement.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + 24 + 24 + True + True + GTK_RELIEF_HALF + True + + + + + True + button_mini_increment.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + 100 + True + True + True + GTK_POS_LEFT + 2 + GTK_UPDATE_CONTINUOUS + False + 25 1 100 1 10 0 + + + + 0 + True + True + + + + + + True + Fallback to default framerate + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_refresh.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + + True + <b>veejay framerate</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_fbw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_reverse.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_pause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_ffw.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + False + False + + + + + + + + + + True + True + 0 + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_prev.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + button_skip.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Mark current position as start of a new sample + True + [... + True + GTK_RELIEF_HALF + True + + + + 0 + True + True + + + + + + True + Mark current position as sample end and create new sample + True + ...] + True + GTK_RELIEF_HALF + True + + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + True + True + True + GTK_POS_TOP + False + False + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + << + True + GTK_RELIEF_NONE + True + + + + 0 + True + True + + + + + + True + Active bank: + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100 1 10 10 + + + + 0 + False + True + + + + + + True + True + >> + True + GTK_RELIEF_NONE + True + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + + + + + + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Add a video or image file as a new sample + True + GTK_RELIEF_HALF + True + + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create a new stream (v4l, dv, network ...) + True + GTK_RELIEF_HALF + True + + + + + True + icon_stream.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Create a new solid colored stream + True + GTK_RELIEF_HALF + True + + + + + True + icon_color.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + Open Samplelist + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_openlist.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Samplelist + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Copy sample to new + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_copy.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selected slot + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Switch to property panel + True + GTK_RELIEF_HALF + True + + + + + True + gtk-preferences + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Randomize sample duration + True + Free Style + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + True + True + + + + + + True + Start / Stop randomizer + True + GTK_RELIEF_HALF + True + False + False + + + + + 20 + 20 + True + button_rand.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + True + <b>Sample randomizer</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>banks</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_NONE + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Play and repeat sample grid + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + True + Play and record this sequence to a new sample + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_record.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Stop recording from this sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_recordstop.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + 0 + False + False + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + + + + + + + + 0 + True + True + + + + + + True + Click an empty slot to place current selected sample. + SHIFT-Click a slot to remove the sample. + False + False + GTK_JUSTIFY_CENTER + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + True + <b>Sample Grid</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + + False + True + + + + + + True + <b>SEQ</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Add Track + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close Track + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + False + False + + + + + + True + False + 0 + + + + + + + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_reverse.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_pause.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_skip.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_dec.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_inc.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_prev.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + 0 + False + True + + + + + 0 + True + True + + + + + + True + sync start! + True + GTK_RELIEF_NORMAL + True + + + + + True + sync.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + + True + <b>Sync controls</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>MT</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + New SRT Sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + button_text.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + 25 + True + 1 +2 +3 +4 +5 + False + True + True + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + 0 + + + + True + Delete this SRT Sequence + True + GTK_RELIEF_NORMAL + True + + + + + True + button_skull.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Apply Text and Start/End position + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_apply.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Load SRT file + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + Save SRT file + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_save.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + 75 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 10 10 + + + + 0 + False + True + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + True + <b>start</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + 75 + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 10 10 + + + + 0 + False + True + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + True + <b>end</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + 100 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Veejay Font + False + True + True + + + + + + + True + <b>face</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 100 1 10 10 + + + + + + + True + <b>Size</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + <b>X</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1000 1 10 10 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + <b>Y</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 1000 1 10 10 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + True + <b>Position</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + False + + + + + + + + True + <b>font</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + True + Outline + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Border + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + False + False + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this foreground color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Foreground color + True + FG + True + GTK_RELIEF_NORMAL + True + True + False + True + + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this background color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Background color + True + BG + True + GTK_RELIEF_NORMAL + True + False + False + True + textcolorfg + + + + label_item + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + Set this line color + True + GTK_RELIEF_NORMAL + True + + + + + 24 + 24 + True + + + + + + + + True + Line color + True + LC + True + GTK_RELIEF_NORMAL + True + False + False + True + textcolorfg + + + + label_item + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + 0.5 + 0.5 + 1 + 1 + 17 + 0 + 4 + 4 + + + + True + 4 + 5 + False + 0 + 0 + + + + 24 + 24 + True + + + 1 + 2 + 0 + 1 + fill + + + + + + 24 + 24 + True + + + 1 + 2 + 1 + 2 + fill + fill + + + + + + 24 + 24 + True + + + 1 + 2 + 2 + 3 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 0 + 1 + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 1 + 2 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 255 0 255 1 10 0 + + + + 2 + 5 + 2 + 3 + fill + fill + + + + + + 100 + True + True + True + GTK_POS_RIGHT + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 255 1 10 0 + + + + 2 + 5 + 3 + 4 + fill + fill + + + + + + True + <b>R</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + 4 + fill + + + + + + + True + <b>G</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + 4 + fill + + + + + + + True + <b>B</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + 4 + fill + + + + + + + True + <b>A</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 3 + 4 + 4 + fill + + + + + + + + 0 + True + True + + + + + + + + True + <b>Color</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + + + True + <b>Text</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + + False + True + + + + + + True + <b>SRT</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + 150 + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + * + False + + + + 3 + True + True + + + + + + True + Send VIMS to veejay + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + True + _Clear + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotostart.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + GTK_RELIEF_NORMAL + True + + + + + True + button_gotoend.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + repeat + True + GTK_RELIEF_NORMAL + True + False + False + + + 0 + False + False + + + + + 0 + False + True + + + + + + + + True + <b>VIMS messenger</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + False + True + + + + + + True + <b>VIMS</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + False + 0 + + + + True + <b>current control:</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + P0 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + True + False + + + + + + True + Toggle keyframing for this chain entry + True + GTK_RELIEF_HALF + True + False + False + + + + + True + icon_keyframe.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + True + True + 0 + + + + True + Apply this keyframe + True + GTK_RELIEF_HALF + True + + + + + True + icon_apply.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + Start keyframing + True + GTK_RELIEF_HALF + True + False + False + + + + + True + button_play.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + + True + Reset + True + GTK_RELIEF_HALF + True + + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 1 + 8 + False + 0 + 0 + + + + True + True + 0 + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + 2 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + True + 3 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + 4 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 4 + 5 + 0 + 1 + fill + + + + + + + True + True + 5 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 5 + 6 + 0 + 1 + fill + + + + + + + True + True + 6 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 6 + 7 + 0 + 1 + fill + + + + + + + True + True + 7 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 7 + 8 + 0 + 1 + fill + + + + + + + True + True + 1 + True + GTK_RELIEF_HALF + True + False + False + True + kf_p0 + + + + 1 + 2 + 0 + 1 + fill + + + + + + 0 + True + True + + + + + + + + True + <b>animate FX</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 1 + 0 + 1 + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + Linear + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + True + Spline + True + GTK_RELIEF_HALF + True + False + False + True + curve_typelinear + + + + 0 + False + False + + + + + + True + True + Freehand + True + GTK_RELIEF_HALF + True + False + False + True + curve_typelinear + + + + 0 + False + False + + + + + + + + True + <b>Curve drawing method</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 2 + 5 + False + 0 + 0 + + + + True + startframe + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 10 10 + + + + 1 + 2 + 0 + 1 + + + + + + + True + endframe + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 100 1 10 10 + + + + 3 + 4 + 0 + 1 + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 0 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + 00:00:00:00 + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.490000009537 + 0 + 0 + PANGO_ELLIPSIZE_NONE + 0 + False + 0 + + + 3 + 4 + 1 + 2 + fill + + + + + + + Update start/end + True + GTK_RELIEF_NORMAL + True + + + + + True + icon_refresh.png + 0.5 + 0.5 + 0 + 0 + + + + + 4 + 5 + 1 + 2 + fill + + + + + + + + + True + <b>timeline</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + False + True + + + + + + True + <b>FX anim</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + tab + + + + + 0 + True + True + + + + + + 32 + True + False + 0 + + + + + + + 0 + False + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + False + + + 0 + True + True + + + + + + True + [hostname] + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + [port] + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + False + False + + + + + + + + True + Connect to Veejay + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ALWAYS + False + 356 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + Reloaded Launcher + + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + GTK_RELIEF_HALF + True + 0 + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_connect.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Connect + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + False + GTK_PACK_END + + + + + + True + False + 3 + + + + 352 + 288 + True + veejay-logo.png + 0.5 + 0.5 + 0 + 0 + + + 0 + True + True + + + + + + True + ver.3144 + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + * + False + + + + 0 + True + True + + + + + + True + Open EditList/Videofile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Open advanced properties dialog + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + gtk-preferences + 4 + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + True + <b>Video File</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + Hostname/IP address + False + False + GTK_JUSTIFY_LEFT + False + False + 1 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + localhost + True + * + False + + + + + 0 + True + True + + + + + + True + Port + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 3490 1024 65535 1 4 4 + + + 0 + True + True + + + + + + + + True + <b>Connection settings</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + 0 + False + True + + + + + + True + GTK_PROGRESS_LEFT_TO_RIGHT + 0 + 0.10000000149 + PANGO_ELLIPSIZE_NONE + + + 0 + False + False + GTK_PACK_END + + + + + + + + VIMS Bundles + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + 600 + 550 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + + + + True + True + 0 + + + + True + New + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_new.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Load Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Write Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_saveas.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Set/Change Key + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keybind.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Delete selected bundle + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Deatach Key from selected event + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_keydetach.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + 0 + False + True + + + + + + True + True + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + False + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + False + False + False + + + + + True + True + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + False + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + True + 0 + + + + True + Apply changes to this bundle + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + + True + Clear text + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_clear.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + True + True + + + + + 0 + False + True + + + + + 1 + False + True + + + + + + + + True + <b>Edit VIMS message contents </b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + + GVeejay Reloaded - Preferences + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + True + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + True + + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-close + True + GTK_RELIEF_HALF + True + -7 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 2 + 4 + False + 2 + 5 + + + + True + Width + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Image format + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 2 + 1 + 2 + fill + + + + + + + True + Height + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 4096 1 10 10 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 0 0 4096 1 10 10 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + Type extension to select image format (jpeg, png, ...) + True + True + True + 12 + jpeg + True + * + False + 5 + + + 2 + 4 + 1 + 2 + fill + + + + + + 0 + False + True + + + + + + + + + + True + <b>Screenshot</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + False + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + 3 + 4 + False + 2 + 5 + + + + True + Width: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Height: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 176 1 800 1 10 10 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 144 1 800 1 10 10 + + + + 1 + 2 + 1 + 2 + fill + + + + + + + Frame delay + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 1 100 1 10 10 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + Keep 4:3 aspect + True + GTK_RELIEF_HALF + True + True + False + True + + + 2 + 4 + 1 + 2 + fill + + + + + + + True + FPS + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + False + 0 + + + + True + True + False + GTK_POS_TOP + 2 + GTK_UPDATE_CONTINUOUS + False + 0 0.019999999553 1 0.019999999553 0 0 + + + + 0 + True + True + + + + + 1 + 3 + 2 + 3 + fill + fill + + + + + + True + + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 3 + 4 + 2 + 3 + fill + + + + + + + + + + + True + <b>Video preview</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 3 + True + True + + + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 1 + + + + True + True + Record video from Viewport + True + GTK_RELIEF_NORMAL + True + False + False + True + + + + 0 + True + False + + + + + + True + Configure Viewport + True + GTK_RELIEF_NORMAL + True + + + 0 + False + False + + + + + + + + + + True + <b>Viewport settings</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + 2 + 4 + False + 2 + 5 + + + + True + Width: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Height: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + X offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 0 + 1 + fill + + + + + + + True + Y offset: + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 2 + 3 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 2 0 4096 1 10 10 + + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 10 10 + + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 10 10 + + + 3 + 4 + 0 + 1 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 1 0 4096 1 10 10 + + + 3 + 4 + 1 + 2 + fill + + + + + + 0 + True + True + + + + + + True + True + Keep 4:3 aspect + True + GTK_RELIEF_HALF + True + True + False + True + + + 0 + False + False + + + + + + True + True + Fullscreen (CTRL-F = window) + True + GTK_RELIEF_HALF + True + False + False + True + + + + 0 + False + False + + + + + + True + GTK_BUTTONBOX_START + 10 + + + + True + Apply changes to primary output settings + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-execute + 2 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Apply + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-close + 2 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + + 0 + True + True + + + + + + + + + + True + <b>Primary Video Window (SDL)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 2 + True + True + + + + + 0 + True + True + + + + + 3 + True + True + + + + + + + + GVeejay Reloaded - New input stream + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_CENTER_ON_PARENT + False + 400 + 400 + True + False + icon_stream.png + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + + + + + 340 + True + 0 + 0.5 + GTK_SHADOW_NONE + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + True + 0 + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + Double click to active, single click column for changing settings + True + True + False + False + True + False + False + False + + + + + + + + True + <b>Device</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + True + True + + + + + + True + True + False + 0 + + + + True + 2 + 4 + False + 0 + 4 + + + + True + True + True + True + 200 + localhost + True + * + False + + + 2 + 3 + 0 + 1 + + + + + + + True + Remote + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + Use multicast + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Port Number + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 1 + 2 + fill + + + + + + + True + True + 1 + 0 + False + GTK_UPDATE_ALWAYS + False + False + 4490 1 65535 1 10 10 + + + 2 + 3 + 1 + 2 + + + + + + + True + True + Try + True + GTK_RELIEF_HALF + True + + + + 3 + 4 + 1 + 2 + + + + + + + + + True + <b>Network</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + False + 0 + + + + True + 2 + 5 + False + 0 + 4 + + + + True + Filename + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 1 + 2 + 0 + 1 + fill + + + + + + + True + True + use YUV4MPEG + True + GTK_RELIEF_HALF + True + False + False + True + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + True + use FFmpeg + True + GTK_RELIEF_HALF + True + False + False + True + inputstream_filey4m + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + True + True + True + 0 + + True + * + False + + + 2 + 4 + 0 + 1 + + + + + + + True + True + Try + True + GTK_RELIEF_HALF + True + + + 4 + 5 + 1 + 2 + fill + + + + + + + True + Load Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_open.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 4 + 5 + 0 + 1 + fill + + + + + + + + + True + <b>File</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + 0 + False + True + + + + + + True + 1 + 4 + False + 0 + 0 + + + + True + Close this window + True + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-close + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + Close + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + 3 + 4 + 0 + 1 + shrink + shrink + + + + + 0 + False + False + + + + + + + + + + True + <b>Stream types</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + + + + + False + ladida + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + + + + True + False + 0 + + + + True + False + 0 + + + + True + 0 + 0 + GTK_SHADOW_NONE + + + + + + + 0 + True + True + + + + + + True + False + 0 + + + + True + Open Veejay Liveset / Action file + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + bg_red.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Save Veejay Liveset / Actionfile + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 0 + 0 + + + + True + bg_yellow.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + True + Cancel + True + GTK_RELIEF_HALF + True + + + + + True + icon_disconnect.png + 0.5 + 0.5 + 0 + 0 + + + + + 0 + False + False + + + + + + + + + + + + + + True + Play selected slot + True + GTK_RELIEF_HALF + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + icon_send.png + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + 0 + False + False + + + + + + + + + + True + True + button119 + True + GTK_RELIEF_HALF + True + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + False + GTK_POS_TOP + 0 + GTK_UPDATE_CONTINUOUS + False + 0.10000000149 0 1 0.00999999977648 0.10000000149 0 + + + + 0 + True + True + + + + + 0 + True + True + + + + + + + diff --git a/branches/V-1.5.3/veejay-client/share/smooth.rc b/branches/V-1.5.3/veejay-client/share/smooth.rc new file mode 100644 index 00000000..2c7fe55b --- /dev/null +++ b/branches/V-1.5.3/veejay-client/share/smooth.rc @@ -0,0 +1,118 @@ +# Edit these colors and fonts however you like. +style "default" +{ + engine "hcengine" {} + xthickness = 1 + ythickness = 1 + GtkWidget::shadow_type = GTK_SHADOW_ETCHED_OUT + #GtkWidget::interior_focus = 0 + #GtkWidget::focus_padding = 0 + #GtkWidget::default_border = {0, 0, 0, 0} + #GtkWidget::default_outside_border = {0, 0, 0, 0} + GtkWidget::default_spacing = 0 + GtkScale::stepper_size = 8 + GtkRange::through-width = 4 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 10 + + font_name = "Trebuchet MS 8" + + fg[NORMAL] = "#000000" # borders etc. + fg[PRELIGHT] = "#ffffff" + fg[ACTIVE] = "#000000" # ook borders, van sliders en notebook + fg[SELECTED] = "#ffffff" + fg[INSENSITIVE] = "#c0c0c0" + + bg[NORMAL] = "#ffffff" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#c0c0c0" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#00ff00" + bg[INSENSITIVE] = "#ffffff" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#050505" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#c0c0c0" + base[PRELIGHT] = "#00fff0" # achtergrond van lists, status bars + base[ACTIVE] = "#0000ff" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + +style "text" +{ + font_name = "Sans 8" + + fg[NORMAL] = "#ffffff" # borders etc. + fg[PRELIGHT] = "#ffffff" + fg[ACTIVE] = "#ffffff" # ook borders, van sliders en notebook + fg[SELECTED] = "#ffffff" + fg[INSENSITIVE] = "#ffffff" + + bg[NORMAL] = "#27282F" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#454f60" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + + +style "buttons" +{ + + font_name = "Sans 8" + + fg[NORMAL] = "#888888" + fg[PRELIGHT] = "#888888" + fg[ACTIVE] = "#888888" + fg[SELECTED] = "#888888" + fg[INSENSITIVE] = "#888888" + + bg[NORMAL] = "#27282F" + bg[PRELIGHT] = "#aaacc1" + bg[ACTIVE] = "#454f60" + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + + + +class "GtkButton" style "default" +class "GtkSpinButton" style "default" +class "GtkToggleButton" style "default" +class "GtkCheckBox" style "default" + +class "GtkLabel" style "default" + +class "GtkWidget" style "default" diff --git a/branches/V-1.5.3/veejay-client/share/sync.png b/branches/V-1.5.3/veejay-client/share/sync.png new file mode 100644 index 00000000..471b269b Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/sync.png differ diff --git a/branches/V-1.5.3/veejay-client/share/veejay-icon.png b/branches/V-1.5.3/veejay-client/share/veejay-icon.png new file mode 100644 index 00000000..c925fd92 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/veejay-icon.png differ diff --git a/branches/V-1.5.3/veejay-client/share/veejay-logo-small.png b/branches/V-1.5.3/veejay-client/share/veejay-logo-small.png new file mode 100644 index 00000000..457745d1 Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/veejay-logo-small.png differ diff --git a/branches/V-1.5.3/veejay-client/share/veejay-logo.png b/branches/V-1.5.3/veejay-client/share/veejay-logo.png new file mode 100644 index 00000000..34f421dd Binary files /dev/null and b/branches/V-1.5.3/veejay-client/share/veejay-logo.png differ diff --git a/branches/V-1.5.3/veejay-client/src/Makefile.am b/branches/V-1.5.3/veejay-client/src/Makefile.am new file mode 100644 index 00000000..3999dd91 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/Makefile.am @@ -0,0 +1,15 @@ +## Process this file with automake to produce Makefile.in +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src $(VEEJAY_CFLAGS ) $(GTK_CFLAGS) \ + $(GLIB_CFLAGS) $(FFMPEG_CFLAGS) $(GLADE_CFLAGS) -DGNOMELOCALEDIR=\""$(datadir)/locale"\" -DRELOADED_DATADIR=\""$(reloaded_datadir)"\" + +RELOADED_BIN=reloaded +reloaded_SOURCES = gtkcolorsel.c gtkknob.c cellrendererspin.c gtktimeselection.c vj-midi.c curve.c utils.c tracksources.c gveejay.c keyboard.c sequence.c multitrack.c vj-api.c mjpeg_logging.c mpegconsts.c mpegtimecode.c yuv4mpeg.c yuv4mpeg_ratio.c ${reloaded_headers} + +bin_PROGRAMS = $(RELOADED_BIN) +EXTRA_DIST = common.h curve.h fastintfns.h format_codes.h keyboard.h mjpeg_logging.h mjpeg_types.h mpegconsts.h mpegtimecode.h multitrack.h sequence.h tracksources.h utils.h videodev_mjpeg.h vj-api.h vmidi.h yuv4mpeg.h yuv4mpeg_intern.h cellrendererspin.h gtkcolorsel.h gtkhsv.h gtkknob.h gtktimeselection.h callback.c + +reloaded_LDFLAGS = $(VEEJAY_LIBS) $(GTK_LIBS) $(GLIB_LIBS) \ +$(GLADE_LIBS) $(FFMPEG_LIBS) $(ALSA_LIBS) -lgthread-2.0 -export-dynamic + diff --git a/branches/V-1.5.3/veejay-client/src/callback.c b/branches/V-1.5.3/veejay-client/src/callback.c new file mode 100644 index 00000000..a75afe07 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/callback.c @@ -0,0 +1,3882 @@ +/* gveejay - Linux VeeJay - GVeejay GTK+-2/Glade User Interface + * (C) 2002-2005 Niels Elburg + * (C) 2006 Matthijs van Henten + * + * + * 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 +static int config_file_status = 0; +static gchar *config_file = NULL; +static int srt_locked_ = 0; +static int srt_seq_ = 0; + +static int bg_[4]; +static int fg_[4]; +static int ln_[4]; + +static int sample_calctime(); + +static void change_box_color_rgb( GtkWidget *box, int r, int g, int b,int a, int fill ); + +void text_defaults() +{ + bg_[0] = 255; bg_[1] = 255; bg_[2] = 255; bg_[3] = 0; + fg_[0] = 0; fg_[1] = 0; fg_[2] = 0; fg_[3] = 0; + ln_[0] = 200; ln_[1] = 255; ln_[1] = 255; ln_[3] = 0; + srt_seq_ = 0; +} + +void on_no_caching_clicked( GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_NO_CACHING ); +} + +void on_report_a_bug1_activate(GtkWidget *w, gpointer user_data ) +{ + reportbug(); +} + +void on_button_085_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims(VIMS_VIDEO_SKIP_SECOND); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_SKIP_SECOND ); +} +void on_button_086_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims(VIMS_VIDEO_PREV_SECOND ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_PREV_SECOND ); + +} +void on_button_080_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims(VIMS_VIDEO_PLAY_FORWARD); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_PLAY_FORWARD ); + +} +void on_button_081_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims(VIMS_VIDEO_PLAY_BACKWARD); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_PLAY_BACKWARD ); +} +void on_button_082_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_VIDEO_PLAY_STOP ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_PLAY_STOP ); +} +void on_button_083_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_VIDEO_SKIP_FRAME ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_SKIP_FRAME ); +} +void on_button_084_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_VIDEO_PREV_FRAME ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_PREV_FRAME ); +} +void on_button_087_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_VIDEO_GOTO_START ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_GOTO_START ); +} +void on_button_088_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_VIDEO_GOTO_END); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_VIDEO_GOTO_END ); +} + +void on_videobar_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + gdouble slider_val = GTK_ADJUSTMENT(GTK_RANGE(widget)->adjustment)->value; + gint val = 0; + switch(info->status_tokens[PLAY_MODE]) + { + case MODE_PLAIN: + val = slider_val * info->status_tokens[TOTAL_FRAMES]; + break; + case MODE_SAMPLE: + val = slider_val * (info->status_tokens[SAMPLE_END] - info->status_tokens[SAMPLE_START]); + val += info->status_tokens[SAMPLE_START]; + break; + default: + return; + } + multi_vims( VIMS_VIDEO_SET_FRAME, "%d", val ); + + vj_midi_learning_vims_simple( info->midi, "videobar", VIMS_VIDEO_SET_FRAME ); + } +} + +void on_button_001_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_SET_PLAIN_MODE ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_SET_PLAIN_MODE ); +} + +void on_fx_followfade_toggled( GtkWidget *widget, gpointer data ) +{ + int val = is_button_toggled( "fx_followfade" ) ? 1:0; + multi_vims( VIMS_CHAIN_FOLLOW_FADE,"%d", val ); +} + +void on_button_252_clicked( GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_DEBUG_LEVEL ); + if(is_button_toggled( "button_252" )) + vims_verbosity = 1; + else + vims_verbosity = 0; + vj_msg(VEEJAY_MSG_INFO, "%s debug information", + vims_verbosity ? "Displaying" : "Not displaying" ); +} + +void on_button_251_clicked( GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_BEZERK ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_BEZERK ); + vj_msg(VEEJAY_MSG_INFO, "Bezerk mode toggled"); +} + +void on_entry_samplename_button_clicked( GtkWidget *widget, gpointer user_data ) +{ + gchar *title = get_text( "entry_samplename" ); + multi_vims( VIMS_SAMPLE_SET_DESCRIPTION, "%d %s", 0,title ); + + //@ dont reload sample, print info to samplebank + int i,j; + for( i= 0; i < NUM_BANKS; i ++ ) + { + for( j = 0; j < NUM_SAMPLES_PER_PAGE ; j ++ ) + { + if( (info->sample_banks[i]->slot[j]->sample_id == + info->status_tokens[CURRENT_ID]) ) + { + gtk_frame_set_label( GTK_FRAME( info->sample_banks[i]->gui_slot[j]->frame ) , title ); + return; + } + } + } +} + +void on_button_054_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *ext = get_text( "screenshotformat" ); + if(ext) + { + gchar filename[100]; + sprintf(filename, "frame-%d.%s", info->status_tokens[FRAME_NUM] + 1 , ext); + gint w = get_nums("screenshot_width"); + gint h = get_nums("screenshot_height"); + multi_vims( VIMS_SCREENSHOT,"%d %d %s",w,h,filename ); + vj_msg(VEEJAY_MSG_INFO, "Requested screenshot '%s' of frame %d", + filename, info->status_tokens[FRAME_NUM] + 1 ); + } +} +void on_button_200_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_EFFECT_SET_BG ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_EFFECT_SET_BG ); + vj_msg(VEEJAY_MSG_INFO, + "Requested background mask of frame %d", + info->status_tokens[FRAME_NUM] + 1 ); +} +void on_button_5_4_clicked(GtkWidget *widget, gpointer user_data) +{ + if( is_button_toggled("button_5_4") ) + { + single_vims( VIMS_AUDIO_ENABLE ); + vj_msg(VEEJAY_MSG_INFO, "Audio is enabled"); + vj_midi_learning_vims_simple(info->midi, NULL, VIMS_AUDIO_ENABLE ); + } + else + { + single_vims( VIMS_AUDIO_DISABLE ); + vj_msg(VEEJAY_MSG_INFO, "Audio is disabled"); + vj_midi_learning_vims_simple(info->midi, NULL, VIMS_AUDIO_DISABLE ); + } + +} +void on_button_samplestart_clicked(GtkWidget *widget, gpointer user_data) +{ + info->sample[0] = info->status_tokens[FRAME_NUM]; + vj_msg(VEEJAY_MSG_INFO, "New sample startings position is %d", + info->sample[0] ); +} +void on_button_sampleend_clicked(GtkWidget *widget, gpointer user_data) +{ + info->sample[1] = info->status_tokens[FRAME_NUM]; + multi_vims( VIMS_SAMPLE_NEW, "%d %d", info->sample[0],info->sample[1]); + vj_msg(VEEJAY_MSG_INFO, "New sample from EditList %d - %d", + info->sample[0], info->sample[1]); + gveejay_new_slot(MODE_SAMPLE); +} + +void on_button_veejay_clicked(GtkWidget *widget, gpointer user_data) +{ +#ifdef STRICT_CHECKING + assert( info->watch.state == STATE_WAIT_FOR_USER ); +#endif + info->watch.state = STATE_CONNECT; +} +void on_button_sendvims_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *text = get_text("vimsmessage"); + if(strncasecmp( text, "600:;",5 ) == 0) + veejay_quit(); + vj_msg(VEEJAY_MSG_INFO, "User defined VIMS message sent '%s'",text ); + msg_vims( text ); +} +void on_vimsmessage_activate(GtkWidget *widget, gpointer user_data) +{ + msg_vims( get_text( "vimsmessage") ); + vj_midi_learning_vims( info->midi, NULL, get_text("vimsmessage"),0); + vj_msg(VEEJAY_MSG_INFO, "User defined VIMS message sent '%s'", get_text("vimsmessage")); +} + +void on_button_fadedur_value_changed(GtkWidget *widget, gpointer user_data) +{ + +} + +void on_button_fadeout_clicked(GtkWidget *w, gpointer user_data) +{ + gint num = (gint)get_numd( "button_fadedur"); + gchar *timenow = format_time( num, info->el.fps ); + multi_vims( VIMS_CHAIN_FADE_OUT, "0 %d", num ); + vj_midi_learning_vims_complex( info->midi, "button_fadedur", VIMS_CHAIN_FADE_OUT, 0,2 ); + vj_msg(VEEJAY_MSG_INFO, "Fade out duration %s (frames %d)", + timenow, + num ); + if(timenow) g_free(timenow); +} + +void on_button_fadein_clicked(GtkWidget *w, gpointer user_data) +{ + gint num = (gint)get_numd( "button_fadedur"); + gchar *timenow = format_time( num, info->el.fps ); + multi_vims( VIMS_CHAIN_FADE_IN, "0 %d", num ); + vj_midi_learning_vims_complex( info->midi, "button_fadedur", VIMS_CHAIN_FADE_IN, 0,2 ); + + vj_msg(VEEJAY_MSG_INFO, "Fade in duration %s (frames %d)", + timenow, + num ); + if(timenow) g_free(timenow); + +} + +void on_manualopacity_value_changed(GtkWidget *w, gpointer user_data) +{ + if(info->status_lock) + return; + + gdouble val = GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value; + + if( is_button_toggled( "loglinear" )) + { + double v = val; + if( v > 0.0 ) + v = 255.0/v; + if( v > 0.0 ) + v = log( val / 0.01 ) / log( 1.0 / 0.01 ); + val = 255.0 * v; + } + + multi_vims( VIMS_CHAIN_MANUAL_FADE, "0 %d", + (int)(val)); + + vj_midi_learning_vims_complex( info->midi, "loglinear", VIMS_CHAIN_FADE_IN, 0,1 ); + + vj_msg(VEEJAY_MSG_INFO, "FX Opacity set to %1.2f", val ); +} + +static void el_selection_update() +{ + gchar *text = format_selection_time(info->selection[0], info->selection[1]); + update_label_str( "label_el_selection", text ); + vj_msg( VEEJAY_MSG_INFO, "Updated EditList selection %d - %d Timecode: %s", + info->selection[0], info->selection[1], text ); + g_free(text); +} + +void on_button_el_selstart_value_changed(GtkWidget *w, gpointer user_data) +{ + info->selection[0] = get_nums("button_el_selstart"); + if( info->selection[0] > info->selection[1]) + update_spin_value( "button_el_selend", info->selection[0]); + gchar *text = format_time( info->selection[0], info->el.fps ); + update_label_str( "label_el_startpos", text); + g_free(text); + el_selection_update(); +} + +void on_button_el_selend_value_changed(GtkWidget *w, gpointer user_data) +{ + info->selection[1] = get_nums( "button_el_selend" ); + if(info->selection[1] < info->selection[0]) + update_spin_value( "button_el_selstart", info->selection[1]); + gchar *text = format_time( info->selection[1], info->el.fps); + update_label_str( "label_el_endpos", text); + g_free(text); + el_selection_update(); +} + +static gboolean verify_selection() +{ + if( (info->selection[1] - info->selection[0] ) <= 0) + { + vj_msg(VEEJAY_MSG_ERROR, "Invalid EditList selection %d - %d", + info->selection[0], info->selection[1]); + return FALSE; + } + return TRUE; +} + +void on_button_el_cut_clicked(GtkWidget *w, gpointer *user_data) +{ + if(verify_selection()) + { multi_vims( VIMS_EDITLIST_CUT, "%d %d", + info->selection[0], info->selection[1]); + gchar *time1 = format_time( info->selection[0], info->el.fps ); + gchar *time2 = format_time( info->selection[1], info->el.fps ); + vj_msg(VEEJAY_MSG_INFO, "Cut %s - %s from EditList to buffer", + time1, time2 ); + g_free(time1); + g_free(time2); + info->uc.reload_hint[HINT_EL] = 1; + } +} +void on_button_el_del_clicked(GtkWidget *w, gpointer *user_data) +{ + if(verify_selection()) + { + multi_vims( VIMS_EDITLIST_DEL, "%d %d", + info->selection[0], info->selection[1]); + gchar *time1 = format_time( info->selection[0],info->el.fps ); + gchar *time2 = format_time( info->selection[1],info->el.fps ); + vj_msg(VEEJAY_MSG_INFO, "Delete %s - %s from EditList", + time1, time2 ); + g_free(time1); + g_free(time2); + update_spin_value( "button_el_selstart", 0 ); + update_spin_value( "button_el_selend", 0); + } +} +void on_button_el_crop_clicked(GtkWidget *w, gpointer *user_data) +{ + if(verify_selection()) + { + multi_vims( VIMS_EDITLIST_CROP, "%d %d", + info->selection[0], info->selection[1]); + gchar *total = format_time( info->status_tokens[TOTAL_FRAMES],info->el.fps ); + gchar *time2 = format_time( info->selection[1],info->el.fps ); + gchar *time1 = format_time( info->selection[0],info->el.fps ); + vj_msg(VEEJAY_MSG_INFO, "Delete 00:00:00 - %s and %s - %s from EditList", + time1, time2, total ); + g_free(time1); + g_free(time2); + g_free(total); + + } +} +void on_button_el_copy_clicked(GtkWidget *w, gpointer *user_data) +{ + if(verify_selection()) + { + multi_vims( VIMS_EDITLIST_COPY, "%d %d", + info->selection[0], info->selection[1] ); + gchar *time1 = format_time( info->selection[0],info->el.fps ); + gchar *time2 = format_time( info->selection[1],info->el.fps ); + vj_msg(VEEJAY_MSG_INFO, "Copy %s - %s to buffer", + time1,time2); + g_free(time1); + g_free(time2); + } +} + +void on_button_el_newclip_clicked(GtkWidget *w, gpointer *user) +{ + if(verify_selection()) + { + multi_vims( VIMS_SAMPLE_NEW, "%d %d", + info->selection[0], info->selection[1] ); + vj_msg(VEEJAY_MSG_INFO, "New sample from EditList %d - %d" , + info->selection[0], info->selection[1] ); + gveejay_new_slot(MODE_SAMPLE); + } + + +} + +void on_button_el_pasteat_clicked(GtkWidget *w, gpointer *user_data) +{ + gint val = get_nums( "button_el_selpaste" ); + info->selection[2] = val; + multi_vims( VIMS_EDITLIST_PASTE_AT, "%d", + info->selection[2]); + gchar *time1 = format_time( info->selection[2],info->el.fps ); + vj_msg(VEEJAY_MSG_INFO, "Paste contents from buffer to frame %d (timecode %s)", + info->selection[2], time1); + g_free(time1); + info->uc.reload_hint[HINT_EL] = 1; + +} +void on_button_el_save_clicked(GtkWidget *w, gpointer *user_data) +{ + gchar *filename = dialog_save_file( "Save EditList" ); + if(filename) + { + multi_vims( VIMS_EDITLIST_SAVE, "%s %d %d", + filename, 0, info->el.num_frames ); + vj_msg(VEEJAY_MSG_INFO, "Saved EditList to %s", filename); + g_free(filename); + } +} +void on_button_el_savesel_clicked(GtkWidget *w, gpointer *user_data) +{ + gchar *filename = dialog_save_file( "Save EditList Selection" ); + if(filename) + { + gint start = get_nums( "button_el_selstart" ); + gint end = get_nums( "button_el_selend" ); + multi_vims( VIMS_EDITLIST_SAVE, "%s %d %d", + filename, start, end ); + vj_msg(VEEJAY_MSG_INFO,"Save EditList selection to %s", filename); + g_free(filename); + } +} + +void on_button_el_add_clicked(GtkWidget *w, gpointer *user_data) +{ + gchar *filename = dialog_open_file( "Append videofile to EditList",0 ); + if(filename) + { + multi_vims( VIMS_EDITLIST_ADD, "%s", + filename ); + vj_msg(VEEJAY_MSG_INFO, "Try to add file '%s' to EditList", filename); + g_free(filename); + } +} +void on_button_el_addsample_clicked(GtkWidget *w, gpointer *user_data) +{ + gchar *filename = dialog_open_file( "Append videofile (and create sample)",0); + if( !filename ) + return; + + int sample_id = 0; + int result_len = 0; + multi_vims( VIMS_EDITLIST_ADD_SAMPLE, "%d %s", 0, filename ); + + gchar *result = recv_vims( 3, &result_len ); + if( result <= 0||result == NULL ) + { + gveejay_popup_err( "Error" , "Unable to load video file. Please check Veejay's console to find out why."); + } + else + { + sscanf( result, "%5d", &sample_id ); + + if(sample_id <= 0 ) + gveejay_popup_err( "Error", "Unable to load video file. Please check Veejay's console to find out why."); + else + vj_msg(VEEJAY_MSG_INFO, "Created new sample %d from file %s", sample_id, filename); + g_free(result); + } + g_free(filename ); +} +void on_button_el_delfile_clicked(GtkWidget *w, gpointer *user_data) +{ + int frame = _el_ref_start_frame( info->uc.selected_el_entry ); + int first_frame = frame; + int last_frame = _el_ref_end_frame( info->uc.selected_el_entry ); + multi_vims( VIMS_EDITLIST_DEL, "%d %d", first_frame, last_frame ); + gchar *time1 = format_time( first_frame,info->el.fps ); + gchar *time2 = format_time( last_frame,info->el.fps ); + vj_msg(VEEJAY_MSG_INFO, "Delete %s - %s", + time1,time2); + g_free(time1); + g_free(time2); +} +void on_button_fx_clearchain_clicked(GtkWidget *w, gpointer user_data) +{ + multi_vims( VIMS_CHAIN_CLEAR, "%d",0); + info->uc.reload_hint[HINT_CHAIN] = 1; + info->uc.reload_hint[HINT_ENTRY] = 1; + vj_midi_learning_vims_msg( info->midi, NULL, VIMS_CHAIN_CLEAR,0 ); + vj_msg(VEEJAY_MSG_INFO, "Clear FX Chain"); +} + +void on_button_entry_toggle_clicked(GtkWidget *w, gpointer user_data) +{ + if(!info->status_lock) + { + gint val = is_button_toggled( "button_entry_toggle" ); + int vims_id = VIMS_CHAIN_ENTRY_SET_VIDEO_OFF; + if(val) + vims_id = VIMS_CHAIN_ENTRY_SET_VIDEO_ON; + multi_vims( vims_id,"%d %d", 0, info->uc.selected_chain_entry ); + + vj_midi_learning_vims_msg2( info->midi, NULL, vims_id, 0, info->uc.selected_chain_entry ); + vj_msg(VEEJAY_MSG_INFO, "Chain Entry %d is %s", + info->uc.selected_chain_entry, + (val ? "Enabled" : "Disabled" )); + info->uc.reload_hint[HINT_ENTRY] = 1; + } +} + +void on_button_fx_entry_value_changed(GtkWidget *w, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_CHAIN_SET_ENTRY, "%d", + (gint) gtk_spin_button_get_value( GTK_SPIN_BUTTON(w)) + ); + vj_midi_learning_vims_spin( info->midi, "fx_entry", VIMS_CHAIN_SET_ENTRY ); + } +} + +void on_button_fx_del_clicked(GtkWidget *w, gpointer user_data) +{ + multi_vims( VIMS_CHAIN_ENTRY_CLEAR, "%d %d", 0, + info->uc.selected_chain_entry ); + info->uc.reload_hint[HINT_ENTRY] = 1; + info->uc.reload_hint[HINT_CHAIN] = 1; + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_CHAIN_ENTRY_CLEAR, 0, info->uc.selected_chain_entry ); + vj_msg(VEEJAY_MSG_INFO, "Clear Effect from Entry %d", + info->uc.selected_chain_entry); +} + +#define slider_changed( arg_num, value ) \ +{\ +if(!info->status_lock && !info->parameter_lock)\ + {\ +info->parameter_lock = 1;\ +multi_vims( VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", 0, info->uc.selected_chain_entry,arg_num, value );\ +vj_midi_learning_vims_fx( info->midi, arg_num, VIMS_CHAIN_ENTRY_SET_ARG_VAL, 0,info->uc.selected_chain_entry, arg_num,1 );\ +if(info->uc.selected_rgbkey) update_rgbkey_from_slider(); \ +info->parameter_lock = 0;\ +}\ +} + +#define param_changed( arg_num, fraction, name ) \ +{\ +if(!info->status_lock && !info->parameter_lock)\ +{\ +info->parameter_lock = 1;\ +multi_vims( VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", 0, info->uc.selected_chain_entry,arg_num, (get_slider_val(name) + fraction) );\ +update_slider_value( name, (get_slider_val(name) + fraction), 0 );\ +vj_midi_learning_vims_fx( info->midi, arg_num, VIMS_CHAIN_ENTRY_SET_ARG_VAL, 0, info->uc.selected_chain_entry,arg_num,2 );\ +if(info->uc.selected_rgbkey) update_rgbkey_from_slider(); \ +info->parameter_lock = 0;\ +}\ +} + + +#define kf_changed( arg_num ) \ +{\ +if(!info->status_lock && arg_num != info->uc.selected_parameter_id)\ +{\ +vj_kf_select_parameter(arg_num);\ +}\ +} + +void on_slider_p0_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 0, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} +void on_slider_p1_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 1, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} +void on_slider_p2_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 2, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} + +void on_slider_p3_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 3, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} +void on_slider_p4_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 4, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} + +void on_slider_p5_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 5, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} +void on_slider_p6_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 6, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} + +void on_slider_p7_value_changed(GtkWidget *w, gpointer user_data) +{ + slider_changed( 7, (gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value ); +} + +void on_inc_p0_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 0, 1 , "slider_p0" ); +} +void on_dec_p0_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 0, -1, "slider_p0"); +} +void on_inc_p1_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 1, 1 , "slider_p1" ); +} +void on_dec_p1_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 1, -1, "slider_p1"); + +} +void on_inc_p2_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 2, 1 , "slider_p2" ); +} +void on_dec_p2_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 2, -1, "slider_p2"); +} +void on_inc_p3_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 3, 1 , "slider_p3" ); +} + void on_dec_p3_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 3, -1, "slider_p3"); +} +void on_inc_p4_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed(4, 1 , "slider_p4" ); +} +void on_dec_p4_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 4, -1, "slider_p4"); +} + +void on_inc_p5_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed(5, 1 , "slider_p5" ); +} +void on_dec_p5_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 5, -1, "slider_p5"); +} + +void on_inc_p6_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed(6, 1 , "slider_p6" ); +} +void on_dec_p6_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 6, -1, "slider_p6"); +} + +void on_inc_p7_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed(7, 1 , "slider_p7" ); +} +void on_dec_p7_clicked(GtkWidget *w, gpointer user_data) +{ + param_changed( 7, -1, "slider_p7"); +} + + + +void on_button_stoplaunch_clicked(GtkWidget *widget, gpointer user_data) +{ + if( info->watch.state == STATE_PLAYING) + { + info->watch.state = STATE_DISCONNECT; + } +} + +void on_button_sample_play_clicked(GtkWidget *widget, gpointer user_data) +{ + if(info->selection_slot) + { + multi_vims( VIMS_SET_MODE_AND_GO , "%d %d" , + info->selection_slot->sample_type, + info->selection_slot->sample_id ); + + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SET_MODE_AND_GO, info->selection_slot->sample_type, + info->selection_slot->sample_id ); + } +} +void on_button_sample_del_clicked(GtkWidget *widget, gpointer user_data) +{ + if( info->selection_slot ) + remove_sample_from_slot(); +} +void on_button_samplelist_load_clicked(GtkWidget *widget, gpointer user_data) +{ + gint erase_all = 0; + if(info->status_tokens[TOTAL_SLOTS] > 0 ) + { + if(prompt_dialog("Load samplelist", + "Loading a samplelist will delete any existing samples" ) == GTK_RESPONSE_REJECT) + return; + else + erase_all = 1; + } + + gchar *filename = dialog_open_file( "Open samplelist",1); + if(filename) + { + if(erase_all) + { + single_vims( VIMS_SET_PLAIN_MODE ); + single_vims( VIMS_SAMPLE_DEL_ALL ); + } + multi_vims( VIMS_SAMPLE_LOAD_SAMPLELIST, "%s", filename ); + g_free(filename ); + } +} +void on_button_samplelist_save_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *filename = dialog_save_file( "Save samplelist"); + if(filename) + { + multi_vims( VIMS_SAMPLE_SAVE_SAMPLELIST, "%s", filename ); + vj_msg(VEEJAY_MSG_INFO, "Saved samples to %s", filename); + g_free(filename); + } +} + +void on_spin_samplestart_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + gint value = (gint) gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) ); + gchar *time1 = format_time(value,info->el.fps); + multi_vims(VIMS_SAMPLE_SET_START, "%d %d",0, value ); + vj_msg(VEEJAY_MSG_INFO, "Set sample's starting position to %d (timecode %s)", + value, time1); + g_free(time1); + } +} + +void on_spin_sampleend_value_changed( GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + gint value = (gint) gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) ); + gchar *time1 = format_time(value,info->el.fps); + + multi_vims(VIMS_SAMPLE_SET_END, "%d %d", 0, value ); + vj_msg(VEEJAY_MSG_INFO, "Set sample's ending position to %d (timecode %s)", + value, time1); + g_free(time1); + + } +} + +void on_slow_slider_value_changed( GtkWidget *widget, gpointer user_data ) +{ + if(!info->status_lock) { + gint value = (gint) get_slider_val("slow_slider"); + multi_vims(VIMS_VIDEO_SET_SLOW, "%d", value ); + value ++; + vj_msg(VEEJAY_MSG_INFO, "Slow video to %2.2f fps", + info->el.fps / (float) value ); + vj_midi_learning_vims_simple(info->midi, "slow_slider",VIMS_VIDEO_SET_SLOW); + } +} + + +void on_speed_slider_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + gint value = (gint) get_slider_val( "speed_slider" ); + // value *= info->play_direction; + multi_vims( VIMS_VIDEO_SET_SPEED, "%d", value ); + vj_msg(VEEJAY_MSG_INFO, "Change video playback speed to %d", + value ); + vj_midi_learning_vims_simple( info->midi, "speed_slider", VIMS_VIDEO_SET_SPEED ); + } +} + +void on_spin_samplespeed_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + gint value = (gint) gtk_spin_button_get_value( GTK_SPIN_BUTTON(widget) ); + value *= info->play_direction; + multi_vims( VIMS_SAMPLE_SET_SPEED, "%d %d",0, value ); + vj_midi_learning_vims_spin( info->midi, "samplespeed", VIMS_SAMPLE_SET_SPEED ); + vj_msg(VEEJAY_MSG_INFO, "Change video playback speed to %d", + value ); + } +} + +void on_v4l_brightness_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_STREAM_SET_BRIGHTNESS, "%d %d", + info->selected_slot->sample_id, + (gint) (GTK_ADJUSTMENT(GTK_RANGE(widget)->adjustment)->value * 65535.0) ); + vj_midi_learning_vims_complex( info->midi, "v4l_brightness", VIMS_STREAM_SET_BRIGHTNESS, info->selected_slot->sample_id, + 1 ); + } +} + +void on_v4l_contrast_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_STREAM_SET_CONTRAST, "%d %d", + info->selected_slot->sample_id, + (gint) (GTK_ADJUSTMENT(GTK_RANGE(widget)->adjustment)->value * 65535.0 ) ); + vj_midi_learning_vims_complex( info->midi, "v4l_contrast", VIMS_STREAM_SET_CONTRAST, info->selected_slot->sample_id, + 1 ); + + } +} + +void on_v4l_hue_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_STREAM_SET_HUE, "%d %d", + info->selected_slot->sample_id, + (gint) (GTK_ADJUSTMENT(GTK_RANGE(widget)->adjustment)->value * 65535.0 ) ); + vj_midi_learning_vims_complex( info->midi, "v4l_hue", VIMS_STREAM_SET_HUE, info->selected_slot->sample_id, + 1 ); + + } +} + +void on_v4l_white_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_STREAM_SET_WHITE, "%d %d", + info->selected_slot->sample_id, + (gint) (GTK_ADJUSTMENT(GTK_RANGE(widget)->adjustment)->value * 65535.0 ) ); + vj_midi_learning_vims_complex( info->midi, "v4l_white", VIMS_STREAM_SET_WHITE, info->selected_slot->sample_id, + 1 ); + + } +} + +void on_v4l_color_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_STREAM_SET_COLOR, "%d %d", + info->selected_slot->sample_id, + (gint) (GTK_ADJUSTMENT(GTK_RANGE(widget)->adjustment)->value * 65535.0) ); + vj_midi_learning_vims_complex( info->midi, "v4l_color", VIMS_STREAM_SET_COLOR, info->selected_slot->sample_id, + 1 ); + + } +} +void on_v4l_saturation_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_STREAM_SET_SATURATION, "%d %d", + info->selected_slot->sample_id, + (gint) (GTK_ADJUSTMENT(GTK_RANGE(widget)->adjustment)->value * 65535.0) ); + vj_midi_learning_vims_complex( info->midi, "v4l_saturation", VIMS_STREAM_SET_SATURATION, info->selected_slot->sample_id, + 1 ); + + } +} +#ifndef HAVE_GTK2_6 +static gchar *my_gtk_combo_box_get_active_text(GtkComboBox *combo ) +{ + GtkTreeIter _iter = { 0 }; + gchar *_format = NULL; + GtkTreeModel *_model=NULL; + g_return_val_if_fail( GTK_IS_COMBO_BOX(combo),NULL); + _model = gtk_combo_box_get_model(combo); +g_return_val_if_fail( GTK_IS_LIST_STORE(_model),NULL); + if(gtk_combo_box_get_active_iter(combo,&_iter)) + gtk_tree_model_get(_model, &_iter,0,&_format,-1); + return _format; +} +#define gtk_combo_box_get_active_text( combo ) my_gtk_combo_box_get_active_text(combo) +#endif + +void on_seq_rec_stop_clicked( GtkWidget *w, gpointer data ) +{ + single_vims( VIMS_SAMPLE_REC_STOP ); +} + +void on_rec_seq_start_clicked( GtkWidget *w, gpointer data ) +{ + GtkComboBox *combo = GTK_COMBO_BOX( GTK_WIDGET(glade_xml_get_widget(info->main_window,"combo_samplecodec"))); + gchar *gformat = (gchar*)gtk_combo_box_get_active_text(combo) ; + gchar *format = gformat; + if(format != NULL && strlen(format) > 2) + { + multi_vims( VIMS_RECORD_DATAFORMAT,"%s", + format ); + } + else + { + format = NULL; + } + + multi_vims( VIMS_SAMPLE_REC_START, + "%d %d", + 0, + 0 ); + + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SAMPLE_REC_START, 0, 0 ); +} + +void on_stream_recordstart_clicked(GtkWidget *widget, gpointer user_data) +{ + + gint nframes = get_nums( "spin_streamduration"); + gint autoplay = is_button_toggled("button_stream_autoplay"); + GtkComboBox *combo = GTK_COMBO_BOX( GTK_WIDGET(glade_xml_get_widget(info->main_window,"combo_streamcodec"))); + gchar *gformat = (gchar*)gtk_combo_box_get_active_text(combo) ; + gchar *format = gformat; + if(format != NULL && strlen(format) > 2) + { + multi_vims( VIMS_RECORD_DATAFORMAT,"%s", + format ); + } + else + { + format = NULL; + } + + multi_vims( VIMS_STREAM_REC_START, + "%d %d", + nframes, + autoplay ); + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_STREAM_REC_START, nframes, autoplay ); + + gchar *time1 = format_time( nframes,info->el.fps ); + if(format) + vj_msg(VEEJAY_MSG_INFO, "Record in %s, duration: %s",format, time1); + else + vj_msg(VEEJAY_MSG_INFO, "Recording in default format (MJPEG) , duration: %s", time1); + + g_free(time1); + g_free(format); +} + +void on_stream_recordstop_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_STREAM_REC_STOP ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_STREAM_REC_STOP ); + vj_msg(VEEJAY_MSG_INFO, "Stream record stop"); +} + +void on_spin_streamduration_value_changed(GtkWidget *widget , gpointer user_data) +{ + gint n_frames = get_nums( "spin_streamduration" ); + gchar *time = format_time(n_frames,info->el.fps); + update_label_str( "label_streamrecord_duration", time ); + g_free(time); +} + + +void on_button_sample_recordstart_clicked(GtkWidget *widget, gpointer user_data) +{ + + gint autoplay = is_button_toggled("button_sample_autoplay"); + GtkComboBox *combo = GTK_COMBO_BOX( GTK_WIDGET(glade_xml_get_widget(info->main_window,"combo_samplecodec"))); + + gchar *format = (gchar*) gtk_combo_box_get_active_text(combo); + gint n_frames = 0; + + gint dur_val = get_nums( "spin_sampleduration" ); + if( is_button_toggled( "sample_mulloop" ) ) + { + int base = sample_calctime(); + n_frames = base * dur_val; + } + else + { + n_frames = dur_val; + } + + if(format != NULL) + { + multi_vims( VIMS_RECORD_DATAFORMAT,"%s", + format ); + } + + multi_vims( VIMS_SAMPLE_REC_START, + "%d %d", + n_frames, + autoplay ); + + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SAMPLE_REC_START, n_frames, autoplay ); + + gchar *time1 = format_time(n_frames,info->el.fps); + if( autoplay ) { + vj_msg(VEEJAY_MSG_INFO, "Recording %s from current sample, autoplaying new sample when finished.",time1); + } else { + vj_msg(VEEJAY_MSG_INFO,"Recording %s from current sample",time1); + } + g_free(time1); + g_free(format); +} + +void on_button_sample_recordstop_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_SAMPLE_REC_STOP ); + vj_midi_learning_vims_simple( info->midi, NULL, VIMS_SAMPLE_REC_STOP ); + vj_msg(VEEJAY_MSG_INFO, "Sample record stop"); +} + +static int sample_calctime() +{ + int n_frames = info->status_tokens[SAMPLE_END] - info->status_tokens[SAMPLE_START]; + if( info->status_tokens[SAMPLE_LOOP] == 2 ) + n_frames *= 2; + if( info->status_tokens[FRAME_DUP] > 0 ) + n_frames *= info->status_tokens[FRAME_DUP]; + return n_frames; +} + +void on_spin_sampleduration_value_changed(GtkWidget *widget , gpointer user_data) +{ + // get num and display label_samplerecord_duration + gint n_frames = sample_calctime(); + if( is_button_toggled( "sample_mulloop" )) + n_frames *= get_nums( "spin_sampleduration" ); + else + n_frames = get_nums( "spin_sampleduration" ); + gchar *time = format_time( n_frames,info->el.fps ); + update_label_str( "label_samplerecord_duration", time ); + g_free(time); +} + +void on_sample_mulloop_clicked(GtkWidget *w, gpointer user_data) +{ + gint n_frames = sample_calctime(); + if( is_button_toggled( "sample_mulloop" )) + n_frames *= get_nums( "spin_sampleduration"); + gchar *time = format_time( n_frames,info->el.fps ); + update_label_str( "label_samplerecord_duration", time ); + g_free(time); +} + +void on_sample_mulframes_clicked(GtkWidget *w, gpointer user_data) +{ + gint n_frames = get_nums( "spin_sampleduration" ); + gchar *time = format_time( n_frames,info->el.fps ); + update_label_str( "label_samplerecord_duration", time ); + g_free(time); +} + +void on_spin_mudplay_value_changed(GtkWidget *widget, gpointer user_data) +{ +} +void on_check_samplefx_clicked(GtkWidget *widget , gpointer user_data) +{ + if(!info->status_lock) + { + int vims_id = VIMS_SAMPLE_CHAIN_DISABLE; + + if( is_button_toggled( "check_samplefx" ) ) + vims_id = VIMS_SAMPLE_CHAIN_ENABLE; + multi_vims( vims_id, "%d", 0 ); + + vj_midi_learning_vims_msg( info->midi, NULL, vims_id, 0 ); + } +} +void on_check_streamfx_clicked(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + int vims_id = VIMS_STREAM_CHAIN_DISABLE; + if( is_button_toggled( "check_streamfx")) + vims_id = VIMS_STREAM_CHAIN_ENABLE; + multi_vims( VIMS_STREAM_CHAIN_DISABLE, "%d", 0 ); + vj_midi_learning_vims_msg( info->midi, NULL, vims_id, 0 ); + } +} + +void on_loop_none_clicked(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_SAMPLE_SET_LOOPTYPE, + "%d %d", 0, 0 ); + vj_midi_learning_vims_msg2(info->midi,NULL,VIMS_SAMPLE_SET_LOOPTYPE,0,0 ); + } +} + +void on_loop_normal_clicked(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_SAMPLE_SET_LOOPTYPE, + "%d %d", 0, 1 ); + vj_midi_learning_vims_msg2(info->midi,NULL,VIMS_SAMPLE_SET_LOOPTYPE,0,1 ); + } +} +void on_loop_random_clicked(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + multi_vims( VIMS_SAMPLE_SET_LOOPTYPE, + "%d %d", 0,3 ); + vj_midi_learning_vims_msg2(info->midi,NULL,VIMS_SAMPLE_SET_LOOPTYPE,0,3 ); + + } +} + +void on_loop_pingpong_clicked(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { multi_vims( VIMS_SAMPLE_SET_LOOPTYPE, + "%d %d", 0,2 ); + vj_midi_learning_vims_msg2(info->midi,NULL,VIMS_SAMPLE_SET_LOOPTYPE,0,2 ); + + } +} +/* +void on_check_marker_bind_clicked(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + timeline_set_bind( info->tl, is_button_toggled("check_marker_bind")); +}*/ + +void on_button_clearmarker_clicked(GtkWidget *widget, gpointer user_data) +{ + multi_vims( VIMS_SAMPLE_CLEAR_MARKER, "%d", 0 ); + vj_midi_learning_vims_msg( info->midi, NULL, VIMS_SAMPLE_CLEAR_MARKER, 0 ); + gchar *dur = format_time( 0,info->el.fps ); + update_label_str( "label_markerduration", dur ); + g_free(dur); +} + + +void on_check_audio_mute_clicked(GtkWidget *widget, gpointer user_data) +{ +} +void on_button_samplelist_open_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *filename = dialog_open_file("Load samplelist",1); + if( filename ) + { + multi_vims( VIMS_SAMPLE_LOAD_SAMPLELIST, "%s", filename ); + vj_msg(VEEJAY_MSG_INFO, "Try to load sample list %s", filename); + g_free(filename); + } +} +void on_veejay_expander_activate(GtkWidget *exp, gpointer user_data) +{ +} +void on_veejay_ctrl_expander_activate(GtkWidget *exp, gpointer user_data) +{ + gint width= 0; + gint height = 0; + + GtkWindow *window = GTK_WINDOW( glade_xml_get_widget_( info->main_window, "gveejay_window")); + + gtk_window_get_size( window, &width, &height ); + + if(!gtk_expander_get_expanded(GTK_EXPANDER(exp))) + { + gtk_widget_set_size_request( + glade_xml_get_widget_(info->main_window, "veejaypanel" ), + width, + 400 ); + + gtk_window_resize( window, width, 600 ); + + } + else + { + gtk_widget_set_size_request( + glade_xml_get_widget_(info->main_window, "veejaypanel" ), + width, + 0 ); + gtk_window_resize( window, width, 100 ); + } +} + +void on_button_el_takestart_clicked(GtkWidget *widget, gpointer user_data) +{ + update_spin_value( "button_el_selstart", + info->status_tokens[FRAME_NUM] ); + vj_msg(VEEJAY_MSG_INFO, "Set current frame %d as editlist starting position", + info->status_tokens[FRAME_NUM]); +} +void on_button_el_takeend_clicked(GtkWidget *widget, gpointer user_data) +{ + update_spin_value ("button_el_selend", + info->status_tokens[FRAME_NUM] ); + vj_msg(VEEJAY_MSG_INFO, "Set current frame %d as editlist ending position", + info->status_tokens[FRAME_NUM]); +} +void on_button_el_paste_clicked(GtkWidget *widget, gpointer user_data) +{ + multi_vims( VIMS_EDITLIST_PASTE_AT, "%d", + info->status_tokens[FRAME_NUM] ); + gchar *time1 = format_time( info->status_tokens[FRAME_NUM],info->el.fps ); + vj_msg(VEEJAY_MSG_INFO, "Paste contents of buffer at Frame %d (Tiemcode %s)", + info->status_tokens[FRAME_NUM], time1); + g_free(time1); +} +void on_new_colorstream_clicked(GtkWidget *widget, gpointer user_data) +{ + GdkColor current_color; + GtkWidget *colorsel = glade_xml_get_widget(info->main_window, + "colorselection" ); + gtk_color_selection_get_current_color( + GTK_COLOR_SELECTION( colorsel ), + ¤t_color ); + + // scale to 0 - 255 + gint red = current_color.red / 256.0; +gint green = current_color.green / 256.0; + gint blue = current_color.blue / 256.0; + multi_vims( VIMS_STREAM_NEW_COLOR, "%d %d %d", + red,green,blue ); + + gveejay_new_slot(MODE_STREAM); +} + +#define atom_aspect_ratio(name,type) {\ +info->uc.priout_lock=1;\ +gint value = (type == 0 ? resize_primary_ratio_x() : resize_primary_ratio_y() );\ +update_spin_value(name, value);\ +info->uc.priout_lock=0;\ +} +void on_priout_width_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock && !info->uc.priout_lock) + if( is_button_toggled( "priout_ratio" )) + atom_aspect_ratio( "priout_height", 1 ); +} +void on_priout_height_value_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock && !info->uc.priout_lock) + if( is_button_toggled( "priout_ratio" )) + atom_aspect_ratio( "priout_width", 0 ); +} +void on_priout_apply_clicked(GtkWidget *widget, gpointer user_data) +{ + gint width = get_nums( "priout_width" ); + gint height = get_nums( "priout_height" ); + gint x = get_nums("priout_x" ); + gint y = get_nums("priout_y" ); + + if( width > 0 && height > 0 ) + { + multi_vims( VIMS_RESIZE_SDL_SCREEN, "%d %d %d %d", + width,height,x , y ); + vj_msg(VEEJAY_MSG_INFO, "Resize Video Window to %dx%d", width,height); + } + +} + + +void on_vims_take_clicked(GtkWidget *widget, gpointer user_data) +{ + single_vims( VIMS_BUNDLE_CAPTURE ); + info->uc.reload_hint[HINT_BUNDLES] = 1; + vj_msg(VEEJAY_MSG_INFO, "Create a new bundle from FX Chain. See View -> VIMS Bundles"); +} +void on_button_key_detach_clicked(GtkWidget *widget, gpointer user) +{ + int key_val = info->uc.pressed_key; + int key_mod = info->uc.pressed_mod; + + if( key_val > 0 ) + { + multi_vims( + VIMS_BUNDLE_ATTACH_KEY, + "1 %d %d %s", + key_val, key_mod, "dummy" ); + info->uc.reload_hint[HINT_BUNDLES] = 1; + char *strmod = sdlmod_by_id( key_mod ); + char *strkey = sdlkey_by_id( key_val); + if(key_mod) + vj_msg(VEEJAY_MSG_INFO, "Key binding %s + %s released",strmod,strkey); + else + vj_msg(VEEJAY_MSG_INFO, "Key binding %s released", strkey ); + } +} + +void on_vims_key_clicked( GtkWidget *widget, gpointer user_data) +{ + char which_vims[128]; + sprintf(which_vims, "Press a key to bind VIMS %03d", + info->uc.selected_vims_entry ); + + int n = prompt_keydialog( + which_vims, + "Key combination" ); + + if( n == GTK_RESPONSE_ACCEPT ) + { + int event_id = info->uc.selected_vims_entry; + int key_val = info->uc.pressed_key; + int mod = info->uc.pressed_mod; + char *buf = info->uc.selected_vims_args; + + if( event_id > 0 && key_val > 0 ) + { + multi_vims( + VIMS_BUNDLE_ATTACH_KEY, + "%d %d %d %s", + event_id, key_val, mod, buf ? buf : "dummy" ); + info->uc.reload_hint[HINT_BUNDLES] = 1; + char *strmod = sdlmod_by_id( mod ); + if(strmod) + vj_msg(VEEJAY_MSG_INFO, "VIMS %d attached to key combination %s + %s", + event_id, strmod, sdlkey_by_id( key_val)); + else + vj_msg(VEEJAY_MSG_INFO, "VIMS %d attached to key %s", + event_id, sdlkey_by_id(key_val) ); + } + } +} + + +void on_button_vimsupdate_clicked(GtkWidget *widget, gpointer user_data) +{ + if(count_textview_buffer( "vimsview" ) > 0 ) + { + gchar *buf = get_textview_buffer( "vimsview" ); + + if( info->uc.selected_vims_type == 0 ) + { + multi_vims( VIMS_BUNDLE_ADD, "%d %s", + info->uc.selected_vims_entry, buf ); + } + else + { + multi_vims( + VIMS_BUNDLE_ATTACH_KEY, + "2 %d %d %s", + info->uc.selected_vims_accel[1], + info->uc.selected_vims_accel[0], + info->uc.selected_vims_args ); + } + info->uc.reload_hint[HINT_BUNDLES] = 1; + } + +} + +void on_vims_clear_clicked(GtkWidget *widget, gpointer user_data) +{ + clear_textview_buffer( "vimsview" ); +} + +void on_vims_delete_clicked(GtkWidget *widget, gpointer user_data) +{ + if( info->uc.selected_vims_entry >= VIMS_BUNDLE_START && + info->uc.selected_vims_entry < VIMS_BUNDLE_END ) + { + multi_vims( VIMS_BUNDLE_DEL, "%d", info->uc.selected_vims_entry ); + info->uc.reload_hint[HINT_BUNDLES] = 1; + vj_msg(VEEJAY_MSG_INFO, "Delete bundle %d from VIMS event list", + info->uc.selected_vims_entry ); + } + else + { + vj_msg(VEEJAY_MSG_ERROR, "VIMS %d is not a bundle.", info->uc.selected_vims_entry ); + } +} + +void on_button_saveactionfile_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *filename = dialog_save_file( "Save Bundles"); + if(filename) + { + multi_vims( VIMS_BUNDLE_SAVE, "%d %s",0, filename ); + vj_msg(VEEJAY_MSG_INFO, "Save Bundles and Keybindings to %s", filename ); + g_free(filename); + } +} + +void on_button_loadconfigfile_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *filename = dialog_open_file( "Load liveset / configfile",2); + + if(!filename) + return; + + if( info->run_state == RUN_STATE_REMOTE ) + { + multi_vims( VIMS_BUNDLE_FILE, "%s", filename ); + } + else + { + if(config_file) + g_free(config_file); + config_file = g_strdup( filename ); + config_file_status = 1; + vj_msg(VEEJAY_MSG_INFO, "You can launch Veejay now"); + } +} + +void on_button_saveconfigfile_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *filename = dialog_save_file( "Save liveset / configfile"); + if(filename) + { + multi_vims( VIMS_BUNDLE_SAVE, "%d %s", 1, filename ); + g_free(filename); + } +} + + +void on_button_newbundle_clicked(GtkWidget *widget, gpointer user_data) +{ + if(count_textview_buffer( "vimsview" ) > 0 ) + { + gchar *buf = get_textview_buffer( "vimsview" ); + multi_vims( VIMS_BUNDLE_ADD, "%d %s", 0, buf ); + info->uc.reload_hint[HINT_BUNDLES] = 1; + vj_msg(VEEJAY_MSG_INFO, "If your VIMS document was valid,you'll find it in the list."); + } + else + { + vj_msg(VEEJAY_MSG_ERROR, "VIMS document is empty, type text first."); + } +} + +void on_button_openactionfile_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *filename = dialog_open_file( "Load Bundles",2 ); + if(filename) + { + multi_vims( VIMS_BUNDLE_FILE, "%s", filename ); + g_free( filename ); + info->uc.reload_hint[HINT_BUNDLES] = 1; + vj_msg(VEEJAY_MSG_INFO ,"Tried to load '%s'",filename); + } +} + +static void load_server_files(char *buf, int len) +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "server_files"); + GtkTreeIter iter; + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); + GtkListStore *store = GTK_LIST_STORE(model); +#ifdef STRICT_CHECKING + assert(tree != NULL ); +#endif + int i = 0; + int idx = 0; + char *ptr = buf; + while( i < len ) { + int filelen = 0; + char name[1024]; + char header[5]; + memset(header,0,sizeof(header)); + memset(name, 0,sizeof(name)); + strncpy(header,ptr, 4 ); + if(sscanf(header,"%04d", &filelen)==1) { + strncpy( name, ptr+4, filelen); + gchar *filename = _utf8str( name ); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0,filename,-1); + gtk_tree_view_set_model(GTK_TREE_VIEW(tree), + GTK_TREE_MODEL(store)); + idx ++; + ptr += filelen; + } + ptr += 4; + i+=4; + i+=filelen; + } +} + +void on_button_browse_clicked(GtkWidget *widget, gpointer user_data) +{ + // open file browser for launcher +/* gchar *filename = dialog_open_file( "Open Videofile or EditList",0 ); + if(filename) + { + put_text( "entry_filename", filename ); + g_free(filename); + }*/ + single_vims(VIMS_WORKINGDIR); + + gint len = 0; + gchar *test = recv_vims( 8, &len ); + + if(!test || len <= 0 ) { + return ; + } + + reset_tree( "server_files"); + + load_server_files( test,len); +free(test); +} + +void on_button_clipcopy_clicked(GtkWidget *widget, gpointer user_data) +{ + if(info->selection_slot) + { + multi_vims( VIMS_SAMPLE_COPY , "%d", + info->selected_slot->sample_id ); + gveejay_new_slot(MODE_SAMPLE); + } +} + +void on_check_priout_fullscreen_clicked( + GtkWidget *widget, gpointer user_data) +{ + gint on = 0; + if(is_button_toggled( "check_priout_fullscreen" ) ) + on = 1; + multi_vims ( VIMS_FULLSCREEN, "%d", on ); +} + + +void on_inputstream_button_clicked(GtkWidget *widget, gpointer user_data) +{ + gint mcast = is_button_toggled( "inputstream_networktype" ); + gchar *remote_ = get_text( "inputstream_remote" ); + gint port = get_nums( "inputstream_portnum" ); + + gsize bw = 0; + gsize br = 0; + + if(!remote_) + { + error_dialog("Error", "Not a valid hostname. Try 'localhost' or '127.0.0.1'"); + GtkWidget *dialog = glade_xml_get_widget_( info->main_window, "inputstream_window" ); + gtk_widget_hide( dialog ); + return; + } + + gchar *remote = g_locale_from_utf8( + remote_ , -1, &br, &bw, NULL ); + + if( !remote || strlen(remote) <= 1 ) + { + GtkWidget *dialog = glade_xml_get_widget_( info->main_window, "inputstream_window" ); + gtk_widget_hide( dialog ); + error_dialog("Error", "Not a valid hostname. Try 'localhost' or '127.0.0.1'"); + return; + } + + remote[strlen(remote)] = '\0'; + + if(bw == 0 || br == 0 || port <= 0 ) + { + GtkWidget *dialog = glade_xml_get_widget_( info->main_window, "inputstream_window" ); + gtk_widget_hide( dialog ); + error_dialog("Error", "You must enter a valid remote address and/or port number"); + return; + } + + + if(mcast) + multi_vims( VIMS_STREAM_NEW_MCAST,"%d %s", port, remote ); + else + multi_vims( VIMS_STREAM_NEW_UNICAST, "%d %s", port, remote ); + + + gveejay_new_slot(MODE_STREAM); + + if(remote) g_free(remote); + + GtkWidget *dialog = glade_xml_get_widget_( info->main_window, "inputstream_window" ); + gtk_widget_hide( dialog ); + +} + +void on_inputstream_filebrowse_clicked(GtkWidget *w, gpointer user_data) +{ + gchar *filename = dialog_open_file( "Open new input stream",3 ); + if(filename) + { + put_text( "inputstream_filename", filename ); + g_free(filename); + } +} +/* +void on_inputstream_file_button_clicked(GtkWidget *w, gpointer user_data) +{ + gint use_y4m = is_button_toggled( "inputstream_filey4m" ); + gint use_ffmpeg = is_button_toggled( "inputstream_fileffmpeg"); + gint use_pic = is_button_toggled( "inputstream_filepixbuf"); + + + gchar *file = get_text( "inputstream_filename" ); + gint br = 0; + gint bw = 0; + gchar *filename = g_locale_from_utf8( file, -1, &br , &bw, NULL ); + if( br == 0 || bw == 0 ) + { + error_dialog("Error", "Please enter a filename"); + return; + } + if(use_y4m) + multi_vims( VIMS_STREAM_NEW_Y4M, "%s", filename ); + if(use_ffmpeg) + multi_vims( VIMS_STREAM_NEW_AVFORMAT, "%s", filename ); +#ifdef USE_GDK_PIXBUF + if(use_pic) + multi_vims( VIMS_STREAM_NEW_PICTURE, "%s", filename); +#endif + + gveejay_new_slot(MODE_STREAM); + + if(filename) g_free( filename ); +}*/ + +void on_samplerand_toggled(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + int arg = is_button_toggled( "freestyle" ); + int start = is_button_toggled( "samplerand" ); + + int vims_id = VIMS_SAMPLE_RAND_START; + if( start == 0 ) + vims_id = VIMS_SAMPLE_RAND_STOP; + + if( vims_id == VIMS_SAMPLE_RAND_START ) + { + multi_vims( vims_id,"%d", arg ); + vj_midi_learning_vims_msg( info->midi,NULL, vims_id, arg ); + } + else + { + single_vims( vims_id ); + vj_midi_learning_vims_simple(info->midi, NULL, vims_id ); + } + + vj_msg(VEEJAY_MSG_INFO, "You should restart the sample randomizer now."); + + } +} + + + +/* + * Handler to open the veejay_connection-dialog via menu + */ +void on_openConnection_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + if(!info->status_lock) + { + GtkWidget *veejay_conncection_window = glade_xml_get_widget(info->main_window, "veejay_connection"); + gtk_widget_show(veejay_conncection_window); + } +} + + +/* + * Handler to close the veejay_connection-dialog + */ +void on_veejay_connection_close (GtkDialog *dialog, + gpointer user_data) +{ + if( info->watch.state == STATE_PLAYING) + { + info->watch.state = STATE_DISCONNECT; + + GtkWidget *w = glade_xml_get_widget_(info->main_window, "veejay_connection" ); + gtk_widget_show( w ); + } + else + gveejay_quit(NULL,NULL); +} + + +/* + * Handler to show the video_settings-dialog via menu + */ +void on_VideoSettings_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + if(!info->status_lock) + { + GtkWidget *veejay_settings_window = glade_xml_get_widget(info->main_window, "video_options"); + gtk_widget_show(veejay_settings_window); + } +} + + +void on_image_calibration1_activate (GtkMenuItem *menuitem, gpointer data) +{ + GtkWidget *win = glade_xml_get_widget(info->main_window,"calibration_window" ); + gtk_widget_show(win); + cali_onoff = 1; +} + +/* + * Handler to close the video_settings-dialog + */ +void on_video_options_close (GtkDialog *dialog, + gpointer user_data) +{ + if(!info->status_lock) + { + GtkWidget *veejay_settings_window = glade_xml_get_widget(info->main_window, "video_options"); + gtk_widget_hide(veejay_settings_window); + } +} + + +/* + * Handler to apply the settings of the video_settings-dialog + */ +void on_video_options_apply_clicked (GtkButton *button, + gpointer user_data) +{ + gint width = get_nums( "priout_width" ); + gint height = get_nums( "priout_height" ); + gint x = get_nums("priout_x" ); + gint y = get_nums("priout_y" ); + + if( width > 0 && height > 0 ) + { + multi_vims( VIMS_RESIZE_SDL_SCREEN, "%d %d %d %d", + width,height,x , y ); + vj_msg(VEEJAY_MSG_INFO, "Resize Video Window to %dx%d", width,height); + } +} + +void on_cali_save_button_clicked( GtkButton *button, gpointer user_data) +{ + gchar *filename = dialog_save_file( "Save calibration to file"); + if( filename ) { + multi_vims( VIMS_V4L_CALI, "%s", filename ); + } +} + +void on_load_calibration1_activate( GtkMenuItem *menuitem, + gpointer user_data) +{ + gchar *filename = dialog_open_file("Select calibration file to load",0); + if(filename) + { + multi_vims( VIMS_STREAM_NEW_CALI, "%s", filename ); + vj_msg(VEEJAY_MSG_INFO ,"Loaded calibration file %s",filename); + } + gveejay_new_slot(MODE_STREAM); +} + +void on_cali_take_button_clicked( GtkButton *button, gpointer data ) +{ + gint method = 0; + gint kernel = 0; + + if( info->uc.cali_stage == 1 ) + method = 1; + + if( info->uc.cali_duration > 0 ) { + error_dialog( "Error", "Already taking calibration images"); + return; + } + + if( is_button_toggled( "cali_method_median" )) + { + kernel = get_nums( "cali_kernelsize_spin"); + } + gint duration=get_nums( "cali_duration_spin" ); + + if( cali_stream_id <= 0 ) { + if(info->status_tokens[STREAM_TYPE] == STREAM_VIDEO4LINUX ) + cali_stream_id = + info->status_tokens[CURRENT_ID]; + } + + if( cali_stream_id <= 0 ) { + error_dialog( "Error", "No source selected to calibrate. Play a Live stream or double click one in the List"); + + return; + } + + multi_vims( VIMS_V4L_BLACKFRAME, "%d %d %d %d", + cali_stream_id, + duration, + kernel, + method ); + + info->uc.cali_duration = duration; + + //@ substract duration in status pipe + +} + +void on_cali_darkframe_clicked( GtkButton *button, gpointer data ) +{ + get_and_draw_frame( 0, "image_darkframe" ); +} + +void on_cali_lightframe_clicked( GtkButton *button, gpointer data ) +{ + get_and_draw_frame( 1, "image_lightframe" ); +} + +void on_cali_flatframe_clicked( GtkButton *button, gpointer data ) +{ + get_and_draw_frame( 2, "image_flatframe" ); +} + +void on_cali_image_clicked( GtkButton *button, gpointer data ) +{ + +// get_and_draw_frame( 0, "image_darkframe" ); +// get_and_draw_frame( 1, "image_lightframe"); +// get_and_draw_frame( 2, "image_flatframe"); + +} + +void on_cali_reset_button_clicked( GtkButton *button, gpointer data ) +{ + if( cali_stream_id <= 0 ) { + if(info->status_tokens[STREAM_TYPE] == STREAM_VIDEO4LINUX ) + cali_stream_id = + info->status_tokens[CURRENT_ID]; + } + + if( cali_stream_id <= 0 ) { + error_dialog( "Error", "No source selected to calibrate. Play a Live stream or double click one in the List"); + + return; + } + + info->uc.cali_stage = 0; + update_label_str("current_step_label","Please take an image with the cap on the lens."); + + multi_vims( VIMS_V4L_BLACKFRAME, "%d 0 0 0", cali_stream_id ); + + reset_cali_images(0, "image_darkframe"); + reset_cali_images(1, "image_lightframe"); + reset_cali_images(2, "image_flatframe"); + + GtkWidget *tb = glade_xml_get_widget_( info->main_window, "cali_take_button"); + gtk_button_set_label( tb, "Take Black Frames"); + + disable_widget( "cali_save_button" ); + +} + +/* + * Handler to show the VIMS_Bundles-dialog + */ +void on_vims_bundles_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *vims_bundles_window = glade_xml_get_widget(info->main_window, "vims_bundles"); + gtk_widget_show(vims_bundles_window); +} + + +/* + * Handler to close the VIMS_Bundles-dialog + */ +void on_vims_bundles_close (GtkDialog *dialog, + gpointer user_data) +{ + GtkWidget *vims_bundles_window = glade_xml_get_widget(info->main_window, "vims_bundles"); + gtk_widget_hide(vims_bundles_window); +} + +/* Menu entries */ +void on_quit1_activate( GtkWidget *w, gpointer user_data ) +{ + gveejay_quit(NULL,NULL); +} +/* depending on the state, we either load an action file or a sample list !*/ +void on_open2_activate( GtkWidget *w, gpointer user_data) +{ + gchar *filename = NULL; + switch( info->watch.state ) + { + case STATE_STOPPED: + filename = dialog_open_file( "Open Action file / Liveset",2 ); + if(filename) + { + if(config_file) + g_free(config_file); + config_file = g_strdup( filename ); + config_file_status = 1; + g_free(filename); + } + break; + case STATE_PLAYING: + filename = dialog_open_file( "Open Samplelist ",1); + if(filename) + { + single_vims( VIMS_SET_PLAIN_MODE ); + single_vims( VIMS_SAMPLE_DEL_ALL ); + multi_vims( VIMS_SAMPLE_LOAD_SAMPLELIST, "%s", filename); + g_free(filename); + } + break; + default: + vj_msg(VEEJAY_MSG_INFO, "Invalid state !"); + break; + } +} +void on_save1_activate( GtkWidget *w, gpointer user_data ) +{ + if(info->watch.state == STATE_PLAYING) + on_button_samplelist_save_clicked( NULL, NULL ); + else + vj_msg(VEEJAY_MSG_ERROR, "Nothing to save (start or connect to veejay first)"); +} +void on_about1_activate(GtkWidget *widget, gpointer user_data) +{ + about_dialog(); +} +void on_new_input_stream1_activate(GtkWidget *widget, gpointer user_data) +{ + GtkWidget *dialog = glade_xml_get_widget_( info->main_window, "inputdialog" ); + gtk_dialog_run( GTK_DIALOG( dialog )); + gtk_widget_hide( dialog ); +} + +void on_istream_cancel_clicked(GtkWidget *widget, gpointer user_data) +{ + GtkWidget *dialog = glade_xml_get_widget_( info->main_window, "inputdialog" ); + gtk_widget_hide( dialog ); +} + +void on_curve_togglerun_toggled(GtkWidget *widget , gpointer user_data) +{ +} + +void on_stream_length_value_changed( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + multi_vims( VIMS_STREAM_SET_LENGTH, "%d", get_nums("stream_length") ); +} + +int on_curve_buttontime_clicked() +{ + return 1; +} + + +void on_framerate_inc_clicked( GtkWidget *w, gpointer data ) +{ + double cur = get_slider_val( "framerate" ); + cur += 1.0; + update_slider_value( "framerate", (int) cur, 0 ); +} + +void on_framerate_dec_clicked( GtkWidget *w, gpointer data ) +{ + double cur = get_slider_val( "framerate" ); + cur -= 1.0; + update_slider_value( "framerate", (int) cur, 0 ); +} + + +void on_frameratenormal_clicked( GtkWidget *w, gpointer data ) +{ + update_slider_value( "framerate", (int) info->el.fps,0 ); +} + +void on_framerate_value_changed( GtkWidget *w, gpointer data ) +{ + if(info->status_lock) + return; + + gdouble slider_val = GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value; + int value = (int)(100.0 * slider_val); + multi_vims( VIMS_FRAMERATE, "%d", value ); + vj_midi_learning_vims_simple( info->midi, "framerate", VIMS_FRAMERATE ); +} + +void on_sync_correction_clicked( GtkWidget *w, gpointer data ) +{ + int status = is_button_toggled( "sync_correction" ); + + multi_vims( VIMS_SYNC_CORRECTION, "%d", status ); + vj_midi_learning_vims_msg( info->midi, NULL, VIMS_SYNC_CORRECTION, status ); +} + +void on_curve_buttonstore_clicked(GtkWidget *widget, gpointer user_data ) +{ + int i = info->uc.selected_chain_entry; + int j = info->uc.selected_parameter_id; + int id = info->uc.entry_tokens[ENTRY_FXID]; + + int end = get_nums( "curve_spinend" ); + int start = get_nums( "curve_spinstart" ); + + + if( (end - start) <= 0 || id <= 0 ) + { + if( id <= 0 ) + vj_msg(VEEJAY_MSG_INFO, "No FX set on entry %d",i); + else + vj_msg(VEEJAY_MSG_INFO, "Length of animation is 0"); + return; + } + + GtkWidget *curve = glade_xml_get_widget_( info->main_window, "curve"); + + int type = 0; + if( is_button_toggled( "curve_typelinear" ) ) { + type = GTK_CURVE_TYPE_LINEAR; + } else if ( is_button_toggled( "curve_typespline" ) ) { + type = GTK_CURVE_TYPE_SPLINE; + } else if ( is_button_toggled( "curve_typefreehand" ) ) { + type = GTK_CURVE_TYPE_FREE; + } + + int len = end - start; + float *data = (float*) vj_calloc(sizeof(float) * len ); + int *values = (int*) vj_calloc(sizeof(int) * len ); + unsigned char *kf = (unsigned char*) vj_calloc( (len*4)+25); + int min=0,max=0; + + _effect_get_minmax( id, &min,&max,j ); + + int k; + + get_points_from_curve( curve, len, data ); + for( k = 0 ; k < len ; k++ ) + values[k] = ( (int) ( data[k] * max )); + + int total_len = 25 + (4 * len); + sprintf( (char*)kf, "key%02d%02d%08d%08d%02d",i,j,start,end,type ); + unsigned char *ptr = kf + 25; + for( k = 0; k < len; k ++ ) + { + unsigned char *p = ptr + (k*4); + p[0] = values[k] & 0xff; + p[1] = (values[k] >> 8) & 0xff; + p[2] = (values[k] >> 16) & 0xff; + p[3] = (values[k] >> 24) & 0xff; + } + + free(values); + free(data); + + vj_client_send_bufX( info->client, V_CMD, kf,total_len ); + free(kf); + + vj_msg( VEEJAY_MSG_INFO, "Saved new animation for parameter %d on entry %d, start at frame %d and end at frame %d",j,i,start,end ); + + +} + +void on_curve_buttonclear_clicked(GtkWidget *widget, gpointer user_data) +{ + gint id = info->status_tokens[ENTRY_FXID]; + if( id < 0 ) + id = 0; + int i = info->uc.selected_chain_entry; + GtkWidget *curve = glade_xml_get_widget_( info->main_window, "curve"); + reset_curve( curve ); + + multi_vims( VIMS_SAMPLE_KF_RESET, "%d", i ); +} + +void on_curve_typelinear_toggled(GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("curve_typelinear")) + { + sample_slot_t *s = info->selected_slot; + if(!s) + return; + GtkWidget *curve = glade_xml_get_widget_( info->main_window, "curve"); + set_points_in_curve( GTK_CURVE_TYPE_LINEAR, curve ); + } +} +void on_curve_typespline_toggled(GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("curve_typespline")) + { + sample_slot_t *s = info->selected_slot; + if(!s) + return; + GtkWidget *curve = glade_xml_get_widget_( info->main_window, "curve"); + set_points_in_curve( GTK_CURVE_TYPE_SPLINE, curve ); + } +} +void on_curve_typefreehand_toggled(GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + if( is_button_toggled("curve_typefreehand")) + { + sample_slot_t *s = info->selected_slot; + if(!s) + return; + GtkWidget *curve = glade_xml_get_widget_( info->main_window, "curve"); + set_points_in_curve( GTK_CURVE_TYPE_FREE, curve ); + } + +} + +void on_curve_toggleentry_toggled( GtkWidget *widget, gpointer user_data) +{ + int k = is_button_toggled( "curve_toggleentry" ); + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(glade_xml_get_widget_( + info->main_window, "tree_chain") )); + + gtk_tree_model_foreach( + model, + chain_update_row, (gpointer*) info ); + + info->uc.reload_hint[HINT_ENTRY] = 1; + if(info->status_lock) + return; + + int i = info->uc.selected_chain_entry; + multi_vims( VIMS_SAMPLE_KF_STATUS, "%d %d", i, k ); +} + +void on_kf_p0_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + if(is_button_toggled("kf_p0")) + kf_changed( 0 ); +} +void on_kf_p1_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("kf_p1")) + kf_changed( 1 ); +} +void on_kf_p2_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("kf_p2")) + kf_changed( 2 ); +} +void on_kf_p3_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("kf_p3")) + kf_changed( 3 ); +} +void on_kf_p4_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("kf_p4")) + kf_changed( 4 ); +} +void on_kf_p5_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("kf_p5")) + kf_changed( 5 ); +} +void on_kf_p6_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("kf_p6")) + kf_changed( 6 ); +} +void on_kf_p7_toggled( GtkWidget *widget, gpointer user_data) +{ + if(info->status_lock) + return; + + if( is_button_toggled("kf_p7")) + kf_changed( 7 ); +} + +void on_curve_toggleglobal_toggled(GtkWidget *widget, gpointer user_data) +{ +} +void on_button_videobook_clicked(GtkWidget *widget, gpointer user_data) +{ + GtkWidget *n = glade_xml_get_widget_( info->main_window, "videobook" ); + // set page 1 from notebook panels + gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK(n) ); + if(page == 1 ) + gtk_notebook_prev_page(GTK_NOTEBOOK(n) ); + if(info->selected_slot) + { + /* Only if we are not playing it */ + if(info->status_tokens[PLAY_MODE] != + info->selected_slot->sample_type && + info->status_tokens[CURRENT_ID] != + info->selected_slot->sample_id ) + multi_vims( VIMS_SET_MODE_AND_GO, "%d %d", + info->selected_slot->sample_type, + info->selected_slot->sample_id ); + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SET_MODE_AND_GO, + info->selected_slot->sample_type, + info->selected_slot->sample_id ); + } +} + +void on_samplepage_clicked(GtkWidget *widget, gpointer user_data) +{ + GtkWidget *m = glade_xml_get_widget_(info->main_window , "notebook18"); + gtk_notebook_set_page( GTK_NOTEBOOK(m), 5 ); + + GtkWidget *n = glade_xml_get_widget_( info->main_window, "panels" ); + + gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK(n) ); + + gint page_needed = 2; + + switch( info->status_tokens[PLAY_MODE] ) + { + case MODE_SAMPLE: + page_needed =0 ; break; + case MODE_STREAM: + page_needed = 1; break; + case MODE_PLAIN: + page_needed = 2; break; + default: + break; + } + + if( page_needed != page ) + gtk_notebook_set_page( + GTK_NOTEBOOK(n), + page_needed ); +} + +void on_timeline_cleared(GtkWidget *widget, gpointer user_data) +{ + multi_vims( VIMS_SAMPLE_CLEAR_MARKER, "%d", 0 ); + vj_midi_learning_vims_msg( info->midi, NULL, VIMS_SAMPLE_CLEAR_MARKER, 0 ); +} + +void on_timeline_bind_toggled( GtkWidget *widget, gpointer user_data) +{ +// gboolean toggled = timeline_get_bind( TIMELINE_SELECTION(widget)) ; +// set_toggle_button( "check_marker_bind", (toggled ? 1 :0) ); +} + +void on_timeline_value_changed( GtkWidget *widget, gpointer user_data ) +{ + if(!info->status_lock) + { + gdouble pos = timeline_get_pos( TIMELINE_SELECTION(widget) ); + multi_vims( VIMS_VIDEO_SET_FRAME, "%d", (gint)pos ); + } +} + +void on_timeline_out_point_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + + gdouble pos1 = timeline_get_in_point( TIMELINE_SELECTION(widget) ); + gdouble pos2 = timeline_get_out_point( TIMELINE_SELECTION(widget) ); + pos1 *= info->status_tokens[TOTAL_FRAMES]; + pos2 *= info->status_tokens[TOTAL_FRAMES]; + if(pos2 > pos1 ) + { + multi_vims( VIMS_SAMPLE_SET_MARKER , "%d %d %d", 0,(gint) pos1, (gint) pos2 ); + gchar *dur = format_time( pos2 - pos1,info->el.fps ); + update_label_str( "label_markerduration", dur ); + g_free(dur); + } + else + vj_msg(VEEJAY_MSG_INFO, "Set Out point after In point !"); + + + } +} + +void on_timeline_in_point_changed(GtkWidget *widget, gpointer user_data) +{ + if(!info->status_lock) + { + gdouble pos1 = timeline_get_in_point( TIMELINE_SELECTION(widget) ); + gdouble pos2 = timeline_get_out_point( TIMELINE_SELECTION(widget) ); + pos1 *= info->status_tokens[TOTAL_FRAMES]; + pos2 *= info->status_tokens[TOTAL_FRAMES]; + if(pos1 < pos2 ) + { + multi_vims( VIMS_SAMPLE_SET_MARKER , "%d %d %d", 0, (gint) pos1, (gint) pos2 ); + gchar *dur = format_time( pos2 - pos1,info->el.fps ); + update_label_str( "label_markerduration", dur ); + g_free(dur); + } + else + vj_msg(VEEJAY_MSG_INFO,"Set In Point before Out Point !"); + } +} + +void on_sampleadd_clicked(GtkWidget *widget, gpointer user_data) +{ + gchar *filename = dialog_open_file( "Add videofile as new sample",0 ); + if(filename) + { + int sample_id = 0; // new sample + int result_len = 0; + multi_vims( VIMS_EDITLIST_ADD_SAMPLE, "%d %s", 0, filename ); + + gchar *result = recv_vims( 3, &result_len ); + if( result <= 0||result == NULL ) + { + gveejay_popup_err( "Error", "Cannot open video file. Please check Veejay's console to find out why"); + } + else + { + sscanf( result, "%5d", &sample_id ); + if(sample_id <= 0) + gveejay_popup_err( "Error", "Cannot open video file. Please check Veejay's console to find out why"); + else + vj_msg(VEEJAY_MSG_INFO, "Created new sample %d from file %s", sample_id, filename); + g_free(result); + } + g_free(filename ); + } +} + +void on_streamnew_clicked(GtkWidget *widget, gpointer user_data) +{ + // inputstream_window + GtkWidget *w = glade_xml_get_widget(info->main_window, "inputstream_window"); + scan_devices( "tree_v4ldevices" ); + gtk_widget_show(w); + +} + +void on_inputstream_close_clicked(GtkWidget *w, gpointer user_data) +{ + GtkWidget *wid = glade_xml_get_widget(info->main_window, "inputstream_window"); + gtk_widget_hide(wid); +} + +void on_button_sdlclose_clicked(GtkWidget *w, gpointer user_data) +{ + multi_vims( VIMS_RESIZE_SDL_SCREEN, "%d %d %d %d", + 0,0,0,0 ); + +} + + +void on_quicklaunch_clicked(GtkWidget *widget, gpointer user_data) +{ +/* if( info->watch.state == STATE_STOPPED ) + { + vj_fork_or_connect_veejay( config_file ); + } +*/ +} + +static void _update_vs() +{ + if( info->config.norm == 0 ) + { + update_spin_value( "vs_size0", 720 ); + update_spin_value( "vs_size1", 576 ); + gtk_spin_button_set_value ( + GTK_SPIN_BUTTON( glade_xml_get_widget_( info->main_window, "vs_fps" ) ), 25.0 ); + } + else + { + update_spin_value( "vs_size0", 720 ); + update_spin_value( "vs_size1", 480 ); + gtk_spin_button_set_value ( + GTK_SPIN_BUTTON( glade_xml_get_widget_( info->main_window, "vs_fps" ) ), 29.97 ); + } + set_toggle_button( "vs_custom", 0 ); +} + +void on_vs_pal_toggled( GtkWidget *w, gpointer user_data ) +{ + info->config.norm = is_button_toggled( "vs_pal" ) ? 0 : 1; + _update_vs(); +} +void on_vs_ntsc_toggled( GtkWidget *w , gpointer user_data) +{ + info->config.norm = is_button_toggled( "vs_ntsc" ) ? 1 :0; + _update_vs(); +} +void on_vs_custom_toggled( GtkWidget *w, gpointer user_data) +{ + if(is_button_toggled( "vs_custom" )) + enable_widget( "vs_frame"); + else + disable_widget( "vs_frame"); +} + +static void _rgroup_audio(void) +{ + if(is_button_toggled( "vs_noaudio")) + info->config.audio_rate = 0; + else + { + if(is_button_toggled("vs_audio44") ) + info->config.audio_rate = 48000; + else + info->config.audio_rate = 44000; + } +} + +void on_vs_audio48_toggled(GtkWidget *w, gpointer user_data) +{ + _rgroup_audio(); +} + +void on_vs_audio44_toggled(GtkWidget *w, gpointer user_data) +{ + _rgroup_audio(); +} +void on_vs_noaudio_toggled(GtkWidget *w, gpointer user_data) +{ + _rgroup_audio(); +} +void on_vs_avsync_toggled(GtkWidget *w, gpointer user_data) +{ + info->config.sync = is_button_toggled( "vs_avsync" ); +} +void on_vs_avtimer_toggled(GtkWidget *w, gpointer user_data) +{ + info->config.timer = is_button_toggled( "vs_avtimer" ); +} +void on_vs_deinter_toggled(GtkWidget *w, gpointer user_data) +{ + info->config.deinter = is_button_toggled( "vs_deinter" ); +} +void on_vs_yuv420_toggled( GtkWidget *w , gpointer user_data) +{ + if( is_button_toggled( "vs_yuv420" )) + info->config.pixel_format = 0; +} +void on_vs_yuv422_toggled( GtkWidget *w, gpointer user_data) +{ + if( is_button_toggled("vs_yuv422") ) + info->config.pixel_format = 1; +} +void on_vs_sample0_toggled( GtkWidget *w , gpointer user_data) +{ + if( is_button_toggled("vs_sample0")) + info->config.sampling = 1; +} +void on_vs_sample1_toggled( GtkWidget *w, gpointer user_data) +{ + if( is_button_toggled("vs_sample1")) + info->config.sampling = 0; +} +void on_vs_size0_value_changed(GtkWidget *w, gpointer user_data) +{ + info->config.w = get_nums( "vs_size0"); +} +void on_vs_size1_value_changed(GtkWidget *w, gpointer user_data) +{ + info->config.h = get_nums( "vs_size1"); +} +void on_vs_fps_value_changed(GtkWidget *w, gpointer user_data) +{ + info->config.fps = get_numd( "vs_fps"); +} +void on_vs_close_clicked( GtkWidget *w, gpointer user_data) +{ + GtkWidget *vs = glade_xml_get_widget(info->main_window, "vs"); + gtk_widget_hide(vs); +} + +void on_vs_mcastosc_toggle_toggled( GtkWidget *w, gpointer user_data) +{ + info->config.osc = is_button_toggled( "vs_mcastosc_toggle" ); + if(info->config.osc) + { + if(info->config.mcast_osc) + g_free( info->config.mcast_osc ); + info->config.mcast_osc = get_text( "vs_mcastvims" ); + } + +} +void on_vs_mcastvims_toggle_toggled(GtkWidget *w, gpointer user_data) +{ + info->config.vims = is_button_toggled( "vs_mcastvims_toggle" ); + if(info->config.vims) + { + if(info->config.mcast_vims) + g_free( info->config.mcast_vims ); + info->config.mcast_vims = get_text( "vs_mcastvims" ); + } +} + +void on_vs_mcastosc_changed( GtkWidget *w, gpointer user_data) +{ +// if(info->config.mcast_osc) +// g_free(info->config.mcast_osc); +// info->config.mcast_osc = get_text( "vs_mcastosc" ); +} +void on_vs_mcastvims_changed( GtkWidget *w, gpointer user_data) +{ +// if(info->config.mcast_vims) +// g_free(info->config.mcast_vims); +// info->config.mcast_vims = get_text( "vs_mcastvims" ); +} + +void on_inputstream_window_delete_event(GtkWidget *w, gpointer user_data) +{ + GtkWidget *vs = glade_xml_get_widget(info->main_window, "inputstream_window"); + gtk_widget_hide(vs); +} + +void on_calibration_window_delete_event(GtkWidget *w,gpointer data) +{ + GtkWidget *win = glade_xml_get_widget(info->main_window, "calibration_window"); + cali_onoff = 0; + gtk_widget_hide(win); +} + + +void on_vs_delete_event( GtkWidget *w, gpointer user_data) +{ + GtkWidget *vs = glade_xml_get_widget(info->main_window, "vs"); + gtk_widget_hide(vs); +} +void on_configure1_activate( GtkWidget *w, gpointer user_data) +{ + GtkWidget *vs = glade_xml_get_widget(info->main_window, "vs"); +/* load options from config */ + + update_spin_value( "vs_size0", info->config.w ); + update_spin_value( "vs_size1", info->config.h ); + update_spin_value( "vs_fps", info->config.fps ); + + set_toggle_button( "vs_avsync", info->config.sync ); + set_toggle_button( "vs_avtimer", info->config.timer ); + set_toggle_button( "vs_deinter", info->config.deinter ); + if(info->config.pixel_format == 0) + set_toggle_button( "vs_yuv420", 1 ); + else + set_toggle_button( "vs_yuv422", 1 ); + + if(info->config.sampling == 1 ) + set_toggle_button( "vs_sample0", 1 ); + else + set_toggle_button( "vs_sample1", 1 ); + if(info->config.norm == 0 && info->config.w == 720 && info->config.h == 576 ) + set_toggle_button( "vs_pal", 1 ); + else + { + if(info->config.norm == 1 && info->config.w == 720 && info->config.h == 480 ) + set_toggle_button( "vs_ntsc", 1 ); + else + set_toggle_button( "vs_custom", 1 ); + } + + if( is_button_toggled( "vs_custom" )) + enable_widget( "vs_frame" ); + else + disable_widget( "vs_frame" ); + + if( info->config.audio_rate == 0 ) + set_toggle_button( "vs_noaudio" , 1 ); + else + { + if( info->config.audio_rate == 44000 ) + set_toggle_button( "vs_audio44" , 1 ); + else + set_toggle_button( "vs_audio48", 1 ); + } + + /* set osc , vims mcast */ + if(info->config.mcast_osc) + put_text( "vs_mcastosc", info->config.mcast_osc ); + if(info->config.mcast_vims) + put_text( "vs_mcastvims", info->config.mcast_vims ); + set_toggle_button( "vs_mcastosc_toggle", info->config.osc ); + set_toggle_button( "vs_mcastvims_toggle", info->config.vims ); + + gtk_widget_show(vs); +} + +void on_quit_veejay1_activate( GtkWidget *w, gpointer user_data) +{ + veejay_quit(); +} + +void on_curve_spinend_value_changed(GtkWidget *w, gpointer user_data) +{ + int end_pos = get_nums( "curve_spinend" ); + gchar *end_time = format_time( + end_pos,info->el.fps ); + update_label_str( "curve_endtime", end_time ); + g_free(end_time); +} + +void on_curve_spinstart_value_changed(GtkWidget *w, gpointer user_data) +{ + int start_pos = get_nums( "curve_spinstart" ); + + gchar *start_time = format_time( + start_pos,info->el.fps ); + update_label_str( "curve_endtime", start_time ); + g_free(start_time); +} + +void on_veejayevent_enter_notify_event(GtkWidget *w, gpointer user_data) +{ + info->key_now = TRUE; +} +void on_veejayevent_leave_notify_event(GtkWidget *w , gpointer user_data) +{ + info->key_now = FALSE; +} + +void on_spin_framedelay_value_changed(GtkWidget *w, gpointer user_data) +{ + if( info->status_lock ) + return; + + multi_vims(VIMS_VIDEO_SET_SLOW, "%d", get_nums("spin_framedelay")); + + vj_midi_learning_vims_spin( info->midi, "framedelay", VIMS_VIDEO_SET_SLOW ); +} + +void on_mixing_effects_toggled(GtkWidget *w, gpointer user_data) +{ + GtkWidget *n = glade_xml_get_widget_( info->main_window, "effectspanel" ); + gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK(n) ); + if(page == 1) + gtk_notebook_prev_page( GTK_NOTEBOOK(n) ); + +} + +void on_image_effects_toggled(GtkWidget *w, gpointer user_data) +{ + GtkWidget *n = glade_xml_get_widget_( info->main_window, "effectspanel" ); + gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK(n) ); + if(page == 0) + gtk_notebook_next_page( GTK_NOTEBOOK(n) ); + +} + +void on_console1_activate(GtkWidget *w, gpointer user_data) +{ + GtkWidget *n = glade_xml_get_widget_( info->main_window, "panels" ); + gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK( n ) ); + + if( page == MODE_PLAIN ) + gtk_notebook_set_page( GTK_NOTEBOOK(n), + info->status_tokens[PLAY_MODE] ); + else + gtk_notebook_set_page( GTK_NOTEBOOK(n), + MODE_PLAIN ); +} + +gboolean on_entry_hostname_focus_in_event( GtkWidget *w, gpointer user_data) +{ + update_label_str( "runlabel", "Connect"); + return FALSE; +} + +gboolean on_entry_hostname_focus_out_event( GtkWidget *w, gpointer user_data) +{ +// update_label_str( "runlabel", "Run" ); + return FALSE; +} + + +gboolean on_entry_filename_focus_in_event( GtkWidget *w, gpointer user_data) +{ +// update_label_str( "runlabel", "Run" ); + return FALSE; +} + +void on_previewbw_toggled( GtkWidget *w , gpointer user_data) +{ + single_vims( VIMS_PREVIEW_BW ); + vj_midi_learning_vims_simple(info->midi,NULL,VIMS_PREVIEW_BW); +} + +void on_previewtoggle_toggled(GtkWidget *w, gpointer user_data) +{ + if(!info->preview_locked) + { + multitrack_toggle_preview( info->mt, -1, is_button_toggled("previewtoggle"), + glade_xml_get_widget(info->main_window, "imageA") ); + } + multitrack_set_quality( info->mt, info->quality ); + +/* multitrack_toggle_preview( info->mt, + -1, + 1, + glade_xml_get_widget(info->main_window,"imageA")); + */ //@ enable + +// setup_samplebank( NUM_SAMPLES_PER_COL, NUM_SAMPLES_PER_ROW ); +} + +void on_previewspeed_value_changed( GtkWidget *widget, gpointer user_data) +{ +} + +void on_previewscale_value_changed( GtkWidget *widget, gpointer user_data) +{ +} + +void on_preview_width_value_changed( GtkWidget *w, gpointer user_data) +{ +} +void on_preview_height_value_changed( GtkWidget *w, gpointer user_data) +{ +} + +void on_mt_new_activate( GtkWidget *w, gpointer user_data) +{ + multitrack_add_track( info->mt ); +} + +void on_mt_delete_activate( GtkWidget *w, gpointer user_data) +{ + multitrack_close_track( info->mt ); +} + + + +void on_mt_sync_start_clicked( GtkWidget *w, gpointer user_data) +{ + multitrack_sync_start( info->mt ); +} + +void on_mt_sync_stop_clicked( GtkWidget *w , gpointer user_data) +{ + multitrack_sync_simple_cmd( info->mt, VIMS_VIDEO_PLAY_STOP,0 ); +} +void on_mt_sync_play_clicked( GtkWidget *w, gpointer user_data) +{ + multitrack_sync_simple_cmd( info->mt, VIMS_VIDEO_PLAY_FORWARD,0 ); +} +void on_mt_sync_backward_clicked( GtkWidget *w, gpointer user_data) +{ + multitrack_sync_simple_cmd( info->mt, VIMS_VIDEO_PLAY_BACKWARD,0); +} +void on_mt_sync_gotostart_clicked( GtkWidget *w, gpointer user_data) +{ + multitrack_sync_simple_cmd( info->mt, VIMS_VIDEO_GOTO_START,0 ); +} +void on_mt_sync_gotoend_clicked( GtkWidget *w, gpointer user_data) +{ + multitrack_sync_simple_cmd( info->mt, VIMS_VIDEO_GOTO_END,0 ); +} +void on_mt_sync_decspeed_clicked( GtkWidget *w, gpointer user_data) +{ + int n = info->status_tokens[SAMPLE_SPEED]; + if( n < 0 ) n += 1; + if( n > 0 ) n -= 1; + multitrack_sync_simple_cmd2( info->mt, VIMS_VIDEO_SET_SPEED, n ); + +} +void on_mt_sync_incspeed_clicked( GtkWidget *w, gpointer user_data) +{ + int n = info->status_tokens[SAMPLE_SPEED]; + if( n < 0 ) n -= 1; + if( n > 0 ) n += 1; + multitrack_sync_simple_cmd2( info->mt, VIMS_VIDEO_SET_SPEED, n ); +} +void on_mt_sync_prev_clicked( GtkWidget *w , gpointer user_data) +{ + multitrack_sync_simple_cmd( info->mt, VIMS_VIDEO_PREV_FRAME ,0 ); +} +void on_mt_sync_next_clicked( GtkWidget *w, gpointer user_data) +{ + multitrack_sync_simple_cmd( info->mt, VIMS_VIDEO_SKIP_FRAME, 0 ); +} + +void on_delete1_activate(GtkWidget *w, gpointer user_data) +{ +} +void on_new_source1_activate( GtkWidget *w , gpointer data ) +{ +} +void on_add_file1_activate(GtkWidget *w, gpointer user_data) +{ +} +void on_colorselection_color_changed( GtkWidget *w, gpointer user_data) +{ +} +static +gchar *get_clipboard_fx_buffer() +{ + int len = 0; + int p[16]; + int i; + for(i=0; i <16;i++) + p[i] = 0; + multi_vims( VIMS_CHAIN_GET_ENTRY, "%d %d", 0, + info->uc.selected_chain_entry ); + + gchar *answer = recv_vims(3,&len); + if(len <= 0 || answer == NULL ) + { + gveejay_popup_err( "Error", "Nothing in FX clipboard"); + + if(answer) g_free(answer); + return NULL; + } + + i = sscanf( answer, "%d %d %d %d %d %d %d %d %d %d %d", + &p[0], //fx id + &p[1], //2 video + &p[2], //n params + &p[3], //p0 + &p[4], //p1 + &p[5], //p2 + &p[6], //p3 + &p[7],//p4 + &p[8],//p5 + &p[9],//p6 + &p[10] //p7 + ); + + char preset[512]; + sprintf(preset, "%d", p[0]); + for(i=0; i < p[2] ;i++) + { + char tmp[10]; + sprintf(tmp, " %d", p[3+i] ); + strcat( preset,tmp); + } + g_free(answer); + return strdup(preset); +} + +static gchar* last_fx_buf = NULL; +void on_button_fx_cut_clicked( GtkWidget *w, gpointer user_data) +{ + if(last_fx_buf) + free(last_fx_buf); + + last_fx_buf = get_clipboard_fx_buffer(); + + on_button_fx_del_clicked( NULL,NULL ); +} + +void on_button_fx_paste_clicked( GtkWidget *w, gpointer user_data) +{ + int i = info->uc.selected_chain_entry; + sample_slot_t *s = info->selected_slot; + + if( last_fx_buf && s) + { + char msg[256]; + sprintf( msg, "%03d:%d %d %s;", + VIMS_CHAIN_ENTRY_SET_PRESET, + s->sample_id, + i, + last_fx_buf ); + msg_vims(msg); + info->uc.reload_hint[HINT_ENTRY]=1; + } + + +} +void on_button_fx_copy_clicked(GtkWidget *w, gpointer user_data) +{ + if(last_fx_buf) + free(last_fx_buf); + + last_fx_buf = get_clipboard_fx_buffer(); +} +void on_copy1_activate( GtkWidget *w, gpointer user_data) +{ +} +void on_new_color1_activate(GtkWidget *w , gpointer user_data) +{ +} +void on_delete2_activate( GtkWidget *w, gpointer user_data) +{ +} +void +on_spin_samplebank_select_value_changed + (GtkSpinButton *spinbutton, + gpointer user_data) +{ + GtkNotebook *samplebank = GTK_NOTEBOOK( info->sample_bank_pad ); + + gint max_page = gtk_notebook_get_n_pages(samplebank); + + gint page = gtk_spin_button_get_value_as_int(spinbutton); + + if(page >= max_page){ /* @mvh I know this is not pretty but why make it difficult */ + page = 0; + gtk_spin_button_set_value(spinbutton, page); + } else if( page < 0 ) { + page = max_page; + gtk_spin_button_set_value(spinbutton,page); + } + gtk_notebook_set_current_page_(GTK_WIDGET(samplebank), page); +} +void +on_button_samplebank_prev_clicked (GtkButton *button, + gpointer user_data) +{ + GtkNotebook *samplebank = GTK_NOTEBOOK( info->sample_bank_pad ); + gtk_notebook_prev_page(samplebank); +} + + +void +on_button_samplebank_next_clicked (GtkButton *button, + gpointer user_data) +{ + GtkNotebook *samplebank = GTK_NOTEBOOK( info->sample_bank_pad ); + gtk_notebook_next_page(samplebank); +} + +void +on_vims_messenger_rewind_clicked( GtkButton *togglebutton, gpointer user_data) +{ + info->vims_line = 0; +} + +void +on_vims_messenger_clear_clicked( GtkButton *togglebutton, gpointer user_data) +{ + clear_textview_buffer( "vims_messenger_textview"); +} + +void +on_vims_messenger_single_clicked( void ) +{ + GtkTextView *t= GTK_TEXT_VIEW(GTK_WIDGET( + glade_xml_get_widget( + info->main_window, + "vims_messenger_textview")) + ); + + GtkTextBuffer* buffer = gtk_text_view_get_buffer(t); + int lc = gtk_text_buffer_get_line_count(buffer); + + if(info->vims_line > lc ) + info->vims_line = 0; + + while(info->vims_line < lc ) + { + GtkTextIter start, end; + gtk_text_buffer_get_iter_at_line(buffer, &start, info->vims_line); + + end = start; + + gtk_text_iter_forward_sentence_end(&end); + gchar *str = gtk_text_buffer_get_text (buffer, &start, &end, TRUE); + + info->vims_line++; + + if(str[0] != '+') + { + vj_msg(VEEJAY_MSG_INFO, "User defined VIMS message sent '%s'",str ); + msg_vims( str ); + break; + } + } +} + +static gint srt_load_subtitle(int sid) +{ + gint len = 0; + gint seq_id = 0; + gint tc1l=0; + gint tc2l=0; + char tc1[20]; + char tc2[20]; + char tmp[1000]; + gint tlen=0; + gint ln[4]; + gint fg[4]; + gint bg[4]; + gint use_bg = 0; + gint outline = 0; + gint size = 0; + gint font = 0; + gint x =0; + gint y = 0; + + multi_vims( VIMS_SRT_INFO, "%d", sid ); + gchar *text = recv_vims( 6,&len ); + veejay_memset(tmp,0,sizeof(tmp)); + veejay_memset(tc1,0,sizeof(tc1)); + veejay_memset(tc2,0,sizeof(tc2)); + + clear_textview_buffer( "textview_text" ); + int s1=0,s2=0; + int n = 0; + if(text && len > 0 ) + { + sscanf( text,"%5d%9d%9d%2d", &seq_id ,&s1,&s2,&tc1l ); + strncpy( tc1, text+7+18,tc1l ); + sscanf( text+7+18+tc1l,"%2d", &tc2l ); + strncpy( tc2, text+7+18+tc1l + 2, tc2l ); + sscanf( text+7+18+tc1l+2+tc2l, "%3d", &tlen ); + strncpy( tmp, text + 7 + 18 + tc1l + 2 + tc2l + 3, tlen ); + n = sscanf( text+7+18 + tc1l+2+tc2l+3+tlen,"%04d%04d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d", + &x,&y, &font, &size, &bg[0],&bg[1],&bg[2],&fg[0],&fg[1],&fg[2],&use_bg,&outline,&ln[0],&ln[1], + &ln[2],&bg[3],&fg[3],&ln[3] ); +#ifdef STRICT_CHECKING + assert( n == 18 ); +#endif + } + + srt_locked_ = 1; + + update_spin_range( "spin_text_start",0, get_total_frames(),s1); + update_spin_range( "spin_text_end",0, get_total_frames(),s2); + + set_textview_buffer( "textview_text", tmp ); + + update_spin_value( "spin_text_start" ,s1); + update_spin_value( "spin_text_end", s2 ); + + change_box_color_rgb( + glade_xml_get_widget(info->main_window, "boxbg" ), + bg[0],bg[1],bg[2],bg[3], (is_button_toggled( "textcolorbg" ) ? 1 : 0 ) ); + + change_box_color_rgb( + glade_xml_get_widget(info->main_window, "boxtext" ), + fg[0],fg[1],fg[2],fg[3], (is_button_toggled( "textcolorfg" ) ? 1: 0) ); + + + change_box_color_rgb( + glade_xml_get_widget( info->main_window, "boxln" ), + ln[0],ln[1],ln[2],ln[3], (is_button_toggled( "textcolorln" ) ? 1: 0) ); + + memcpy( bg_, bg, sizeof(bg_)); + memcpy( fg_, fg, sizeof(fg_)); + memcpy( ln_, ln, sizeof(ln_)); + + set_toggle_button( "use_bg", use_bg ); + set_toggle_button( "use_outline", outline); + update_spin_value( "spin_text_size", size ); + update_spin_value( "spin_text_x", x ); + update_spin_value( "spin_text_y", y ); + + if(is_button_toggled( "textcolorfg") ) + { + update_slider_value( "textcolorred", fg_[0],0 ); + update_slider_value( "textcolorblue",fg_[2],0 ); + update_slider_value( "textcolorgreen",fg_[1],0); + update_slider_value( "textcoloralpha", fg_[3],0); + } + else if( is_button_toggled( "textcolorbg") ) + { + update_slider_value( "textcolorred", bg_[0],0 ); + update_slider_value( "textcolorblue",bg_[2],0 ); + update_slider_value( "textcolorgreen",bg_[1],0); + update_slider_value( "textcoloralpha",bg_[3],0); + } + else if ( is_button_toggled( "textcolorln" )) + { + update_slider_value( "textcolorred", ln_[0],0 ); + update_slider_value( "textcolorblue",ln_[2],0 ); + update_slider_value( "textcolorgreen",ln_[1],0); + update_slider_value( "textcoloralpha", ln_[3],0); + } + GtkWidget *combo = glade_xml_get_widget( info->main_window, "combobox_fonts" ); + gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), font ); + + +// glade_xml_get_widget( info->main_window, "combobox_textsrt" ); +// gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), seq_id-1 ); + +// if(len > 0 ) +// enable_widget( "SRTframe"); + + + srt_locked_ = 0; + + if(text) free(text); + + return seq_id; +} + +void on_button_text_new_clicked( GtkWidget *w, gpointer data ) +{ + gint x = get_nums( "spin_text_x" ); + gint y = get_nums( "spin_text_y" ); + gint s1 = 0; + gint s2 = 0; + if( info->status_tokens[PLAY_MODE] == MODE_SAMPLE ) + { + s1 = info->status_tokens[SAMPLE_START]; + s2 = info->status_tokens[SAMPLE_END]; + } + else + { + s1 = 0; + s2 = get_nums("stream_length"); + } + + gchar *text = strdup(" "); + + multi_vims( VIMS_SRT_ADD, "%d %d %d %d %d %s", + 0,s1,s2,x,y,text ); + + int tmp = 0; + gchar *new_srt_id = recv_vims( 5, &tmp ); + int id = 0; + if(new_srt_id && tmp > 0) + { + sscanf( new_srt_id, "%d", &id ); + if(id > 0 ) + srt_seq_ = id; + } + if( new_srt_id ) + free(new_srt_id); + + free(text); + if( id > 0 ) + info->uc.reload_hint[HINT_HISTORY] = 1; + +} + +void on_button_text_del_clicked( GtkWidget *w, gpointer data ) +{ + multi_vims( VIMS_SRT_DEL, "%d", srt_seq_ ); + info->uc.reload_hint[HINT_HISTORY] = 1; +} + +void on_spin_text_start_value_changed( GtkWidget *w, gpointer data ) +{ + gint start = get_nums( "spin_text_end"); + char *text = format_time( start, info->el.fps ); + update_label_str( "labeltextstart", text ); + free(text); +} + +void on_spin_text_end_value_changed( GtkWidget *w, gpointer data ) +{ + gint end = get_nums( "spin_text_end" ); + char *text = format_time( end, info->el.fps ); + update_label_str( "labeltextend", text ); + free(text); +} +void on_spin_text_x_value_changed( GtkWidget *w, gpointer data ) +{ + if( srt_locked_) + return; + + gint x = get_nums( "spin_text_x" ); + gint y = get_nums( "spin_text_y"); + multi_vims( VIMS_FONT_POS,"%d %d", x,y ); +} +void on_spin_text_y_value_changed( GtkWidget *w, gpointer data ) +{ + if( srt_locked_) + return; + + gint x = get_nums( "spin_text_x" ); + gint y = get_nums( "spin_text_y"); + multi_vims( VIMS_FONT_POS,"%d %d", x,y ); +} +void on_button_srt_save_clicked( GtkWidget *w, gpointer data ) +{ + gchar *filename = dialog_save_file("Save SRT file"); + if( filename ) + { + multi_vims( VIMS_SRT_SAVE, "%s", filename ); + g_free(filename); + } +} +void on_button_srt_load_clicked( GtkWidget *w, gpointer data ) +{ + gchar *filename = dialog_open_file("Load SRT file",4); + if( filename ) + { + multi_vims( VIMS_SRT_LOAD, "%s", filename ); + g_free(filename); + } +} + + +void on_combobox_fonts_changed( GtkWidget *w, gpointer data ) +{ + if(srt_locked_) + return; + gint font = gtk_combo_box_get_active( GTK_COMBO_BOX( w ) ); + gint size = get_nums( "spin_text_size" ); + + multi_vims( VIMS_FONT_SIZE_FONT, "%d %d", font , size ); +} +void on_spin_text_size_value_changed( GtkWidget *w, gpointer data ) +{ + if( srt_locked_) + return; + GtkWidget *ww = glade_xml_get_widget( info->main_window, + "combobox_fonts" ); + gint font = gtk_combo_box_get_active( GTK_COMBO_BOX( ww ) ); + gint size = get_nums( "spin_text_size" ); + + multi_vims( VIMS_FONT_SIZE_FONT, "%d %d", font , size ); +} + +void on_button_text_update_clicked(GtkWidget *w, gpointer data) +{ + gint s1 = get_nums( "spin_text_start" ); + gint s2 = get_nums( "spin_text_end" ); + gchar *text = get_textview_buffer( "textview_text" ); + if(text) + multi_vims( VIMS_SRT_UPDATE, "%d %d %d %s", srt_seq_, s1,s2,text ); +} + +static void change_box_color_rgb( GtkWidget *box, int r, int g, int b,int a, int fill ) +{ + GdkGC *gc = gdk_gc_new( box->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + col.red = 255.0 * r; + col.green = 255.0 * g; + col.blue = 255.0 * b; + + if(fill) + { + update_slider_value( "textcolorred", r ,0); + update_slider_value( "textcolorgreen",g,0 ); + update_slider_value( "textcolorblue",b,0); + update_slider_value( "textcoloralpha",a,0); + } + gdk_color_alloc( gtk_widget_get_colormap( box ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + box->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); +} + +void on_combobox_textsrt_changed( GtkWidget *w, gpointer data) +{ + if(info->status_lock) + return; + + gchar *k = gtk_combo_box_get_active_text( GTK_COMBO_BOX(w) ); + int sid = atoi(k); + if( sid > 0) + { + multi_vims( VIMS_SRT_SELECT, "%d", sid ); + srt_seq_ = sid; + gint res = srt_load_subtitle(sid); + char text[32]; + sprintf(text, "Edit SRT %d", res ); + update_label_str( "srtid_label", text ); + } +} + + +static void change_box_color( GtkWidget *box, double val, int plane, int fill ) +{ + GdkGC *gc = gdk_gc_new( box->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + double v = (1.0 / 255.0) * val; + + int r = get_slider_val( "textcolorred" ); + int b = get_slider_val( "textcolorgreen" ); + int g = get_slider_val( "textcolorblue" ); + int a = get_slider_val("textcoloralpha" ); + + if(plane==0) + { + col.red = 65535.0 * v; + switch(fill) + { + case 0: fg_[0] = r; break; + case 1: bg_[0] = r; break; + case 2: ln_[0] = r; break; + } + } + if(plane==1) + { + col.green = 65535 * v; + switch(fill) + { + case 0: fg_[1] = g; break; + case 1: bg_[1] = g; break; + case 2: ln_[1] = g; break; + } + } + if(plane==2) + { + col.blue = 65535 * v; + switch(fill) + { + case 0: fg_[2] = b; break; + case 1: bg_[2] = b; break; + case 2: ln_[2] = b; break; + } + + } + if(plane==-1) + { + col.red = 255.0 * r; + col.green = 255.0 * g; + col.blue = 255.0 * b; + switch(fill) + { + case 0: fg_[0] = r; fg_[1] = g; fg_[2] = b; fg_[3] = a; break; + case 1: bg_[0] = r; bg_[1] = g; bg_[2] = b; bg_[3] = a; break; + case 2: ln_[0] = r; ln_[1] = g; ln_[2] = b; ln_[3] = a; break; + } + + } + + + gdk_color_alloc( gtk_widget_get_colormap( box ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + box->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); +} + +static void colbox( const char *name1,const char *name2, int plane ) +{ + int fg = is_button_toggled("textcolorfg"); + int bg = is_button_toggled("textcolorbg"); + int ln = is_button_toggled("textcolorln"); + + int v = get_slider_val( name2 ); + change_box_color( + glade_xml_get_widget( info->main_window,name1 ) , + v, + plane, + -1 ); //green + + if(fg) + change_box_color( + glade_xml_get_widget( info->main_window, "boxtext" ), + 0.0, + -1, + 0 ); + if(bg) + change_box_color( + glade_xml_get_widget( info->main_window, "boxbg" ), + 0.0, + -1, + 1 ); + + if(ln) + change_box_color( + glade_xml_get_widget( info->main_window, "boxln" ), + 0.0, + -1, + 2 ); + +} + +void on_textcoloralpha_value_changed(GtkWidget *w, gpointer data ) +{ + if(info->status_lock || srt_locked_) + return; + + int fg = is_button_toggled("textcolorfg"); + int bg = is_button_toggled("textcolorbg"); + int ln = is_button_toggled("textcolorln"); + gint r = get_slider_val( "textcolorred" ); + gint g = get_slider_val( "textcolorgreen" ); + gint b = get_slider_val( "textcolorblue" ); + gint a = get_slider_val( "textcoloralpha" ); + + int m = 0; + if( fg ) + { + fg_[3] = a; + m = 1; + } + if( bg ) + { + bg_[3] = a; + m = 2; + } + if( ln ) + { + ln_[3] = a; + m = 3; + } + + multi_vims( VIMS_FONT_COL, "%d %d %d %d %d", r,g,b,a, m ); +} + +void on_textcolorred_value_changed(GtkWidget *w , gpointer data ) +{ + colbox( "boxred", "textcolorred", 0 ); +} + + +void on_textcolorgreen_value_changed(GtkWidget *w , gpointer data ) +{ + colbox( "boxgreen", "textcolorgreen", 1 ); +} + +void on_textcolorblue_value_changed(GtkWidget *w , gpointer data ) +{ + colbox( "boxblue", "textcolorblue", 2 ); +} + +void on_textcolorfg_toggled( GtkWidget *w, gpointer data ) +{ + if( is_button_toggled( "textcolorfg" ) ) + { + update_slider_value( "textcolorred", fg_[0],0 ); + update_slider_value( "textcolorgreen", fg_[1],0 ); + update_slider_value( "textcolorblue", fg_[2],0); + update_slider_value( "textcoloralpha", fg_[3],0); + } +} +void on_textcolorbg_toggled( GtkWidget *w, gpointer data ) +{ + if( is_button_toggled( "textcolorbg" ) ) + { + update_slider_value( "textcolorred", bg_[0],0 ); + update_slider_value( "textcolorgreen", bg_[1],0 ); + update_slider_value( "textcolorblue", bg_[2],0); + update_slider_value( "textcoloralpha", bg_[3],0); + } +} +void on_textcolorln_toggled( GtkWidget *w, gpointer data ) +{ + if( is_button_toggled( "textcolorln" ) ) + { + update_slider_value( "textcolorred", ln_[0],0 ); + update_slider_value( "textcolorgreen", ln_[1],0 ); + update_slider_value( "textcolorblue", ln_[2],0); + update_slider_value( "textcoloralpha", ln_[3],0); + } +} + +void on_use_bg_toggled( GtkWidget *w , gpointer data) +{ + if(srt_locked_ || info->status_lock) + return; + + multi_vims( VIMS_FONT_COL, "%d %d %d %d %d", + is_button_toggled("use_outline"), + is_button_toggled("use_bg"), + 0, + 0, + 0 ); +} + +void on_use_outline_toggled( GtkWidget *w, gpointer data) +{ + if(srt_locked_ || info->status_lock) + return; + + multi_vims( VIMS_FONT_COL, "%d %d %d %d %d", + is_button_toggled("use_outline"), + is_button_toggled("use_bg"), + 0, + 0, + 0 ); + +} + +void on_buttonfg_clicked( GtkWidget *w, gpointer data ) +{ + gint r = get_slider_val( "textcolorred" ); + gint g = get_slider_val( "textcolorgreen" ); + gint b = get_slider_val( "textcolorblue" ); + gint a = get_slider_val( "textcoloralpha"); + fg_[0] = r; + fg_[1] = g; + fg_[2] = b; + fg_[3] = a; + + multi_vims( VIMS_FONT_COL, "%d %d %d %d %d", r,g,b,a, 1 ); +} +void on_buttonbg_clicked( GtkWidget *w, gpointer data ) +{ + gint r = get_slider_val( "textcolorred" ); + gint g = get_slider_val( "textcolorgreen" ); + gint b = get_slider_val( "textcolorblue" ); + gint a = get_slider_val( "textcoloralpha" ); + + bg_[0] = r; + bg_[1] = g; + bg_[2] = b; + bg_[3] = a; + + multi_vims( VIMS_FONT_COL, "%d %d %d %d %d", r,g,b,a, 2 ); +} +void on_buttonln_clicked( GtkWidget *w, gpointer data ) +{ + gint r = get_slider_val( "textcolorred" ); + gint g = get_slider_val( "textcolorgreen" ); + gint b = get_slider_val( "textcolorblue" ); + gint a = get_slider_val( "textcoloralpha" ); + + ln_[0] = r; + ln_[1] = g; + ln_[2] = b; + ln_[3] = a; + + multi_vims( VIMS_FONT_COL, "%d %d %d %d %d", r,g,b,a, 3 ); +} + +gboolean boxfg_expose_event(GtkWidget *w, + GdkEventExpose *event, gpointer data ) +{ + gdk_window_clear_area( w->window, + event->area.x, event->area.y, + event->area.width,event->area.height ); + + + GdkGC *gc = gdk_gc_new( w->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + col.red = 255.0 * fg_[0]; + col.green = 255.0 * fg_[1]; + col.blue = 255.0 * fg_[2]; + + gdk_color_alloc( gtk_widget_get_colormap( w ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + w->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); + + return TRUE; +} + +gboolean boxbg_expose_event(GtkWidget *w, + GdkEventExpose *event, gpointer data ) +{ + gdk_window_clear_area( w->window, + event->area.x, event->area.y, + event->area.width,event->area.height ); + + + GdkGC *gc = gdk_gc_new( w->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + col.red = 255.0 * bg_[0]; + col.green = 255.0 * bg_[1]; + col.blue = 255.0 * bg_[2]; + + gdk_color_alloc( gtk_widget_get_colormap( w ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + w->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); + + return TRUE; +} + +gboolean boxln_expose_event(GtkWidget *w, + GdkEventExpose *event, gpointer data ) +{ + gdk_window_clear_area( w->window, + event->area.x, event->area.y, + event->area.width,event->area.height ); + + + GdkGC *gc = gdk_gc_new( w->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + col.red = 255.0 * ln_[0]; + col.green = 255.0 * ln_[1]; + col.blue = 255.0 * ln_[2]; + + gdk_color_alloc( gtk_widget_get_colormap( w ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + w->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); + + return TRUE; +} + +gboolean boxred_expose_event(GtkWidget *w, + GdkEventExpose *event, gpointer data ) +{ + gdk_window_clear_area( w->window, + event->area.x, event->area.y, + event->area.width,event->area.height ); + + + GdkGC *gc = gdk_gc_new( w->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + col.red = 255 * get_slider_val( "textcolorred" ); + + gdk_color_alloc( gtk_widget_get_colormap( w ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + w->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); + + return TRUE; +} + + +gboolean boxgreen_expose_event(GtkWidget *w, + GdkEventExpose *event, gpointer data ) +{ + gdk_window_clear_area( w->window, + event->area.x, event->area.y, + event->area.width,event->area.height ); + + + GdkGC *gc = gdk_gc_new( w->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + col.green = 0xff * get_slider_val( "textcolorgreen" ); + + gdk_color_alloc( gtk_widget_get_colormap( w ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + w->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); + + return TRUE; +} +gboolean boxblue_expose_event(GtkWidget *w, + GdkEventExpose *event, gpointer data ) +{ + gdk_window_clear_area( w->window, + event->area.x, event->area.y, + event->area.width,event->area.height ); + + + GdkGC *gc = gdk_gc_new( w->window ); + GdkColor col; + + memset( &col,0, sizeof( GdkColor ) ); + col.blue = 255 * get_slider_val( "textcolorblue" ); + + gdk_color_alloc( gtk_widget_get_colormap( w ), &col ); + + gdk_gc_set_foreground( gc, &col ); + + gdk_draw_rectangle( + w->window, + gc, + TRUE, + 0, + 0, + 24, + 24 ); + + gdk_gc_unref( gc ); + + return TRUE; +} + + +void on_osdbutton_clicked(GtkWidget *w, gpointer data ) +{ + single_vims(VIMS_OSD); +} + +void on_seqactive_toggled( GtkWidget *w, gpointer data ) +{ + if(info->status_lock) + return; + multi_vims( VIMS_SEQUENCE_STATUS, "%d" , is_button_toggled("seqactive" ) ? 1 : 0 ); + vj_midi_learning_vims_msg(info->midi,NULL, VIMS_SEQUENCE_STATUS, is_button_toggled("seqactive")); +} +void on_bq_button_clicked( GtkWidget *w, gpointer data ) +{ + info->quality = 2; + multitrack_set_quality( info->mt, 2 ); + set_toggle_button( "previewtoggle", 1 ); +} + +void on_hqbutton_clicked( GtkWidget *w, gpointer data ) +{ + info->quality = 1; + multitrack_set_quality( info->mt, 1 ); + set_toggle_button( "previewtoggle", 1 ); + +} +void on_lqbutton_clicked( GtkWidget *w, gpointer data ) +{ + info->quality = 0; + multitrack_set_quality( info->mt, 0 ); + set_toggle_button( "previewtoggle", 1 ); + +} +void on_uq_button_clicked( GtkWidget *w, gpointer data ) +{ + info->quality = 3; + multitrack_set_quality( info->mt, 3 ); + if(!is_button_toggled( "previewtoggle" )) + set_toggle_button( "previewtoggle", 1 ); + +} + +void on_record_vp_clicked( GtkWidget *w, gpointer data ) +{ + single_vims( VIMS_RECVIEWPORT ); +} + +void on_macroplay_toggled( GtkWidget *w, gpointer data ) +{ + if(info->status_lock) + return; + if( is_button_toggled( "macroplay" )) + { + multi_vims( VIMS_MACRO, "%d %d", 2,1 ); + vj_midi_learning_vims_msg2( info->midi,NULL,VIMS_MACRO,2,1 ); + } +} + +void on_macrorecord_toggled( GtkWidget *w, gpointer data ) +{ + if(info->status_lock) + return; + if( is_button_toggled( "macrorecord")) + { + multi_vims( VIMS_MACRO, "%d %d", 1, 1 ); + vj_midi_learning_vims_msg2( info->midi,NULL,VIMS_MACRO,1,1 ); + } +} + +void on_macrostop_toggled( GtkWidget *w, gpointer data ) +{ + if(info->status_lock) + return; + if( is_button_toggled( "macrostop")) + { + multi_vims( VIMS_MACRO, "%d %d", 0 , 1 ); + vj_midi_learning_vims_msg2( info->midi,NULL,VIMS_MACRO,0,1 ); + } +} + +void on_macroclear_clicked( GtkWidget *w, gpointer data ) +{ + if(info->status_lock) + return; + + multi_vims( VIMS_MACRO, "%d %d", 0, 0 ); + vj_midi_learning_vims_msg2( info->midi,NULL, VIMS_MACRO, 0, 0); +} + +void on_midilearn_toggled( GtkWidget *w, gpointer data ) +{ + vj_midi_learn( info->midi); +} + +void on_midievent_toggled( GtkWidget *w, gpointer data ) +{ + vj_midi_play( info->midi ); +} + + +void on_load_midi_layout1_activate( GtkWidget *w , gpointer data ) +{ + gchar *filename = dialog_open_file( "Select MIDI configuration file to load",0); + if( filename ) + vj_midi_load( info->midi, filename ); +} +void on_save_midi_layout1_activate( GtkWidget *w, gpointer data ) +{ + gchar *filename = dialog_save_file( "Save MIDI configuration to file"); + if(filename) + vj_midi_save( info->midi, filename ); +} + +void on_clear_midi_layout1_activate( GtkWidget *w, gpointer data ) +{ + vj_midi_reset(info->midi); +} diff --git a/branches/V-1.5.3/veejay-client/src/cellrendererspin.c b/branches/V-1.5.3/veejay-client/src/cellrendererspin.c new file mode 100644 index 00000000..e4635222 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/cellrendererspin.c @@ -0,0 +1,358 @@ +/*************************************************************************** + cellrendererspin.c + ------------------ + begin : Tue Oct 21 2003 + copyright : (C) 2003 by Tim-Philipp Müller + email : t.i.m at orange dot net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 is a dirty 15-minute hack that tries to + * make editable cells with spin buttons instead + * of the text entry widget. + * + * Modify how you please. At the moment you need + * to hook up your own cell data function to make + * sure that the number of digits is the same in + * editing mode as it is in non-editing mode. + * + * The parameters passed to _new() should probably + * be properties, and probably we don't need most + * of them anyway. Also, it would be good if there + * was a better method to ensure that the number + * of digits is the same without this. + * + * Maybe one should just rip out the whole _render + * stuff from GtkCellRendererText and make a + * whole new specialised GtkCellRenderFloat + * or something. + * + * If anyone ever completes this code to sth useful, + * or achieves sth similar in another way, or has + * any comments on it, please drop me a mail. + */ + +#include "cellrendererspin.h" +#include +#include +#include + +#define GUI_CELL_RENDERER_SPIN_PATH "gui-cell-renderer-spin-path" +#define GUI_CELL_RENDERER_SPIN_INFO "gui-cell-renderer-spin-info" + +/* Some boring function declarations: GObject type system stuff */ + +static void gui_cell_renderer_spin_init (GuiCellRendererSpin *cellspin); + +static void gui_cell_renderer_spin_class_init (GuiCellRendererSpinClass *klass); + +static void gui_cell_renderer_spin_finalize (GObject *gobject); + + +static gpointer parent_class; + + +static GtkCellEditable *gui_cell_renderer_spin_start_editing (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags); + +struct _GCRSpinInfo +{ + gulong focus_out_id; +}; + +typedef struct _GCRSpinInfo GCRSpinInfo; + +/*************************************************************************** + * + * gui_cell_renderer_spin_get_type + * + * Here we register our type with the GObject type system if we + * haven't done so yet. Everything else is done in the callbacks. + * + ***************************************************************************/ + +GType +gui_cell_renderer_spin_get_type (void) +{ + static GType cell_spin_type = 0; + + if (cell_spin_type) + return cell_spin_type; + + if (1) + { + static const GTypeInfo cell_spin_info = + { + sizeof (GuiCellRendererSpinClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gui_cell_renderer_spin_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GuiCellRendererSpin), + 0, /* n_preallocs */ + (GInstanceInitFunc) gui_cell_renderer_spin_init, + }; + + /* Derive from GtkCellRenderer */ + cell_spin_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, + "GuiCellRendererSpin", + &cell_spin_info, + 0); + } + + return cell_spin_type; +} + +/*************************************************************************** + * + * gui_cell_renderer_spin_init + * + * Set some default properties of the parent (GtkCellRendererText). + * + ***************************************************************************/ + +static void +gui_cell_renderer_spin_init (GuiCellRendererSpin *cellrendererspin) +{ + return; +} + + +/*************************************************************************** + * + * gui_cell_renderer_spin_class_init: + * + ***************************************************************************/ + +static void +gui_cell_renderer_spin_class_init (GuiCellRendererSpinClass *klass) +{ + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS(klass); + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + parent_class = g_type_class_peek_parent (klass); + object_class->finalize = gui_cell_renderer_spin_finalize; + + /* Override the cell renderer's edit-related methods */ + cell_class->start_editing = gui_cell_renderer_spin_start_editing; +} + + +/*************************************************************************** + * + * gui_cell_renderer_spin_finalize: free any resources here + * + ***************************************************************************/ + +static void +gui_cell_renderer_spin_finalize (GObject *object) +{ +/* + GuiCellRendererSpin *cellrendererspin = GUI_CELL_RENDERER_SPIN(object); +*/ + + /* Free any dynamically allocated resources here */ + + + /* chain up to parent class to make sure + * they release all their memory as well */ + + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + + +/*************************************************************************** + * + * gui_cell_renderer_spin_new + * + * return a new cell renderer instance + * (all the parameters should really be properties) + * + * Not sure which of all these values are really + * relevant for the spin button - needs checking! + * + ***************************************************************************/ + +GtkCellRenderer * +gui_cell_renderer_spin_new (gdouble lower, + gdouble upper, + gdouble step_inc, + gdouble page_inc, + gdouble page_size, + gdouble climb_rate, + guint digits) +{ + GtkCellRenderer *cell; + GuiCellRendererSpin *spincell; + + cell = g_object_new(GUI_TYPE_CELL_RENDERER_SPIN, NULL); + + spincell = GUI_CELL_RENDERER_SPIN(cell); + + spincell->lower = lower; + spincell->upper = upper; + spincell->step_inc = step_inc; + spincell->page_inc = page_inc; + spincell->page_size = page_size; + spincell->climb_rate = climb_rate; + spincell->digits = digits; + + return cell; +} + + +/*************************************************************************** + * + * gui_cell_renderer_spin_editing_done + * + ***************************************************************************/ + +static void +gui_cell_renderer_spin_editing_done (GtkCellEditable *spinbutton, + gpointer data) +{ + const gchar *path; + const gchar *new_text; + GCRSpinInfo *info; + + info = g_object_get_data (G_OBJECT (data), GUI_CELL_RENDERER_SPIN_INFO); + + if (info->focus_out_id > 0) + { + g_signal_handler_disconnect (spinbutton, info->focus_out_id); + info->focus_out_id = 0; + } + + if (GTK_ENTRY(spinbutton)->editing_canceled) + return; + + path = g_object_get_data (G_OBJECT (spinbutton), GUI_CELL_RENDERER_SPIN_PATH); + new_text = gtk_entry_get_text (GTK_ENTRY(spinbutton)); + + g_signal_emit_by_name(data, "edited", path, new_text); +} + + +/*************************************************************************** + * + * gui_cell_renderer_spin_focus_out_event + * + ***************************************************************************/ + +static gboolean +gui_cell_renderer_spin_focus_out_event (GtkWidget *spinbutton, + GdkEvent *event, + gpointer data) +{ + gui_cell_renderer_spin_editing_done (GTK_CELL_EDITABLE (spinbutton), data); + + /* entry needs focus-out-event */ + return FALSE; +} + +/*************************************************************************** + * + * gui_cell_renderer_spin_start_editing + * + ***************************************************************************/ + +static gboolean +onButtonPress (GtkWidget *spinbutton, GdkEventButton *bevent, gpointer data) +{ + if ((bevent->button == 1 && bevent->type == GDK_2BUTTON_PRESS) || bevent->type == GDK_3BUTTON_PRESS) + { + g_print ("double or triple click caught and ignored.\n"); + return TRUE; /* don't invoke other handlers */ + } + + return FALSE; +} + + +/*************************************************************************** + * + * gui_cell_renderer_spin_start_editing + * + ***************************************************************************/ + +static GtkCellEditable * +gui_cell_renderer_spin_start_editing (GtkCellRenderer *cell, + GdkEvent *event, + GtkWidget *widget, + const gchar *path, + GdkRectangle *background_area, + GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + GtkCellRendererText *celltext; + GuiCellRendererSpin *spincell; + GtkAdjustment *adj; + GtkWidget *spinbutton; + GCRSpinInfo *info; + gdouble curval = 0.0; + + celltext = GTK_CELL_RENDERER_TEXT(cell); + spincell = GUI_CELL_RENDERER_SPIN(cell); + + /* If the cell isn't editable we return NULL. */ + if (celltext->editable == FALSE) + return NULL; + + spinbutton = g_object_new (GTK_TYPE_SPIN_BUTTON, "has_frame", FALSE, "numeric", TRUE, NULL); + + /* dirty */ + if (celltext->text) + curval = atof(celltext->text); + + adj = GTK_ADJUSTMENT(gtk_adjustment_new(curval, + spincell->lower, + spincell->upper, + spincell->step_inc, + spincell->page_inc, + spincell->page_size)); + + gtk_spin_button_configure(GTK_SPIN_BUTTON(spinbutton), adj, spincell->climb_rate, spincell->digits); + + g_object_set_data_full (G_OBJECT(spinbutton), GUI_CELL_RENDERER_SPIN_PATH, g_strdup (path), g_free); + + gtk_editable_select_region (GTK_EDITABLE (spinbutton), 0, -1); + + gtk_widget_show (spinbutton); + + g_signal_connect (spinbutton, "editing_done", + G_CALLBACK (gui_cell_renderer_spin_editing_done), + celltext); + + /* hack trying to catch the quite annoying effect + * a double click has while editing */ + + g_signal_connect (spinbutton, "button_press_event", + G_CALLBACK (onButtonPress), + NULL); + + info = g_new0(GCRSpinInfo, 1); + + info->focus_out_id = g_signal_connect (spinbutton, "focus_out_event", + G_CALLBACK (gui_cell_renderer_spin_focus_out_event), + celltext); + + g_object_set_data_full (G_OBJECT (cell), GUI_CELL_RENDERER_SPIN_INFO, info, g_free); + + return GTK_CELL_EDITABLE (spinbutton); +} diff --git a/branches/V-1.5.3/veejay-client/src/cellrendererspin.h b/branches/V-1.5.3/veejay-client/src/cellrendererspin.h new file mode 100644 index 00000000..89f6aa74 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/cellrendererspin.h @@ -0,0 +1,68 @@ +/*************************************************************************** + cellrendererspin.h + ------------------ + begin : Tue Oct 21 2003 + copyright : (C) 2003 by Tim-Philipp Müller + email : t.i.m at orange dot net + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef _cellrendererspin_h_included_ +#define _cellrendererspin_h_included_ + +#include + +/* Some boilerplate GObject type check and type cast macros */ + +#define GUI_TYPE_CELL_RENDERER_SPIN (gui_cell_renderer_spin_get_type()) +#define GUI_CELL_RENDERER_SPIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GUI_TYPE_CELL_RENDERER_SPIN, GuiCellRendererSpin)) +#define GUI_CELL_RENDERER_SPIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GUI_TYPE_CELL_RENDERER_SPIN, GuiCellRendererSpinClass)) +#define GUI_IS_CELL_RENDERER_SPIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GUI_TYPE_CELL_RENDERER_SPIN)) +#define GUI_IS_CELL_RENDERER_SPIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GUI_TYPE_CELL_RENDERER_SPIN)) +#define GUI_CELL_RENDERER_SPIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GUI_TYPE_CELL_RENDERER_SPIN, GuiCellRendererSpinClass)) + + + +typedef struct _GuiCellRendererSpin GuiCellRendererSpin; +typedef struct _GuiCellRendererSpinClass GuiCellRendererSpinClass; + + +struct _GuiCellRendererSpin +{ + GtkCellRendererText parent; + + gdouble lower; + gdouble upper; + gdouble step_inc; + gdouble page_inc; + gdouble page_size; + gdouble climb_rate; + guint digits; +}; + +struct _GuiCellRendererSpinClass +{ + GtkCellRendererTextClass parent_class; +}; + +GType gui_cell_renderer_spin_get_type (void); + +GtkCellRenderer *gui_cell_renderer_spin_new (gdouble lower, + gdouble upper, + gdouble step_inc, + gdouble page_inc, + gdouble page_size, + gdouble climb_rate, + guint digits); + + +#endif /* _spinbar_renderer_h_included_ */ + diff --git a/branches/V-1.5.3/veejay-client/src/common.h b/branches/V-1.5.3/veejay-client/src/common.h new file mode 100644 index 00000000..1b3ece1c --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/common.h @@ -0,0 +1,62 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ +#ifndef GVRCOMMON_H +#define GVRCOMMON_H +#define STATUS_BYTES 150 +#define STATUS_TOKENS 26 //@ previous 23 +#define VEEJAY_CODENAME VERSION +/* Status bytes */ + +#define ELAPSED_TIME 0 +#define PLAY_MODE 2 +#define CURRENT_ID 3 +#define SAMPLE_FX 4 +#define SAMPLE_START 5 +#define SAMPLE_END 6 +#define SAMPLE_SPEED 7 +#define SAMPLE_LOOP 8 +#define SAMPLE_MARKER_START 13 +#define STREAM_TYPE 13 +#define SAMPLE_MARKER_END 14 +#define FRAME_NUM 1 +#define TOTAL_FRAMES 6 +#define TOTAL_SLOTS 16 +#define TOTAL_MEM 17 +#define CURRENT_FPS 18 +#define CYCLE_LO 19 +#define CYCLE_HI 20 +#define SEQ_ACT 21 +#define SEQ_CUR 22 +#define CHAIN_FADE 23 +#define FRAME_DUP 24 +#define MACRO 25 +#define CURRENT_ENTRY 15 +#define MODE_PLAIN 2 +#define MODE_SAMPLE 0 +#define MODE_PATTERN 3 +#define MODE_STREAM 1 +#define STREAM_COL_R 5 +#define STREAM_COL_G 6 +#define STREAM_COL_B 7 + +#define STREAM_RECORDED 11 +#define STREAM_DURATION 10 +#define STREAM_RECORDING 9 + +#endif diff --git a/branches/V-1.5.3/veejay-client/src/curve.c b/branches/V-1.5.3/veejay-client/src/curve.c new file mode 100644 index 00000000..402b4e3f --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/curve.c @@ -0,0 +1,100 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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 "curve.h" +#ifdef STRICT_CHECKING +#include +#endif +void get_points_from_curve( GtkWidget *curve, int len, float *vec ) +{ + gtk_curve_get_vector( GTK_CURVE(curve), len, vec ); +} + +void reset_curve( GtkWidget *curve ) +{ + gtk_curve_reset(GTK_CURVE(curve)); + gtk_curve_set_range( GTK_CURVE(curve), 0.0, 1.0, 0.0, 1.0 ); +} + +void set_points_in_curve( int type, GtkWidget *curve) +{ + gtk_curve_set_curve_type( GTK_CURVE(curve), type ); +} + +int set_points_in_curve_ext( GtkWidget *curve, unsigned char *blob, int id, int fx_entry, int *lo, int *hi, int *curve_type) +{ + int parameter_id = 0; + int start = 0, end =0,type=0; + int entry = 0; + int n = sscanf( (char*) blob, "key%2d%2d%8d%8d%2d", &entry, ¶meter_id, &start, &end,&type ); + int len = end - start + 1; + int i; + int min = 0, max = 0; +#ifdef STRICT_CHECKING + assert( fx_entry == entry ); +#endif + + if( len <= 0 ) + return -1; + + if(n != 5 ) + { + veejay_msg(0, "Error parsing KF headeR"); + return -1; + } + + _effect_get_minmax(id, &min, &max, parameter_id ); + + unsigned int k = 0; + unsigned char *in = blob + 25; + float *vec = (float*) vj_calloc(sizeof(float) * len ); + for(i = start ; i < end; i ++ ) + { + unsigned char *ptr = in + (i * 4); + int value = + ( ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24) ); + + + float top = 1.0 / (float) max; + float val = (float)value * top; + + vec[k] = val; + k++; +#ifdef STRICT_CHECKING + assert( k < len ); +#endif + } + + gtk_curve_set_vector( GTK_CURVE( curve ), len, vec ); + gtk_curve_set_curve_type( GTK_CURVE(curve), type ); + + *lo = start; + *hi = end; + *curve_type = type; + + free(vec); + + return parameter_id; +} diff --git a/branches/V-1.5.3/veejay-client/src/curve.h b/branches/V-1.5.3/veejay-client/src/curve.h new file mode 100644 index 00000000..f93512ed --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/curve.h @@ -0,0 +1,34 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + +#ifndef VJCURVE_H +#define VJCURVE_H +#include +#include +#include +#define MAX_PARAMETERS 8 +#define MAX_CHAIN_LEN 20 + + +int set_points_in_curve_ext( GtkWidget *curve, unsigned char *blob, int id, int fx_entry, int *lo, int *hi, int *ct); +void set_points_in_curve( int type, GtkWidget *curve); +void reset_curve( GtkWidget *curve ); +void get_points_from_curve( GtkWidget *curve, int len, float *v ); + +#endif diff --git a/branches/V-1.5.3/veejay-client/src/fastintfns.h b/branches/V-1.5.3/veejay-client/src/fastintfns.h new file mode 100644 index 00000000..41c611c9 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/fastintfns.h @@ -0,0 +1,18 @@ +/* fast int primitives. min,max,rnddiv2 + * + * WARNING: Assumes 2's complement arithmetic. + */ +static inline int intmax( register int x, register int y ) +{ + return x < y ? y : x; +} + +static inline int intmin( register int x, register int y ) +{ + return x < y ? x : y; +} + +static inline int rnddiv2( int x ) +{ + return (x+(x>0))>>1; +} diff --git a/branches/V-1.5.3/veejay-client/src/format_codes.h b/branches/V-1.5.3/veejay-client/src/format_codes.h new file mode 100644 index 00000000..2c958f04 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/format_codes.h @@ -0,0 +1,46 @@ +/* + $Id: format_codes.h,v 1.10 2005/12/09 23:07:56 wackston2 Exp $ + + Copyright (C) 2001 Andrew Stevens + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __FORMAT_CODES_H__ +#define __FORMAT_CODES_H__ + +#define MPEG_FORMAT_MPEG1 0 +#define MPEG_FORMAT_VCD 1 +#define MPEG_FORMAT_VCD_NSR 2 +#define MPEG_FORMAT_MPEG2 3 +#define MPEG_FORMAT_SVCD 4 +#define MPEG_FORMAT_SVCD_NSR 5 +#define MPEG_FORMAT_VCD_STILL 6 +#define MPEG_FORMAT_SVCD_STILL 7 +#define MPEG_FORMAT_DVD_NAV 8 +#define MPEG_FORMAT_DVD 9 +#define MPEG_FORMAT_ATSC480i 10 +#define MPEG_FORMAT_ATSC480p 11 +#define MPEG_FORMAT_ATSC720p 12 +#define MPEG_FORMAT_ATSC1080i 13 + +#define MPEG_FORMAT_FIRST 0 +#define MPEG_FORMAT_LAST MPEG_FORMAT_ATSC1080i + +#define MPEG_STILLS_FORMAT(x) ((x)==MPEG_FORMAT_VCD_STILL||(x)==MPEG_FORMAT_SVCD_STILL) +#define MPEG_ATSC_FORMAT(x) ((x)>=MPEG_FORMAT_ATSC480i && (x)<=MPEG_FORMAT_ATSC1080i) +#define MPEG_HDTV_FORMAT(x) MPEG_ATSC_FORMAT(x) +#define MPEG_SDTV_FORMAT(x) (!MPEG_HDTV_FORMAT(x)) +#endif /* __FORMAT_CODES_H__ */ diff --git a/branches/V-1.5.3/veejay-client/src/gtkcolorsel.c b/branches/V-1.5.3/veejay-client/src/gtkcolorsel.c new file mode 100644 index 00000000..73e1d9f5 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtkcolorsel.c @@ -0,0 +1,2873 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2000 Red Hat, Inc. + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2001. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gtkcolorsel.h" +#include "gtkhsv.h" + +#ifdef GDK_WINDOWING_X11 +#include +#include +#elif defined GDK_WINDOWING_WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +/* Number of elements in the custom palatte */ +#define GTK_CUSTOM_PALETTE_WIDTH 5 +#define GTK_CUSTOM_PALETTE_HEIGHT 4 + +/* Conversion between 0->1 double and and guint16. See + * scale_round() below for more general conversions + */ +#define SCALE(i) (i / 65535.) +#define UNSCALE(d) ((guint16)(d * 65535 + 0.5)) + + +enum { + COLOR_CHANGED, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_HAS_PALETTE, + PROP_HAS_OPACITY_CONTROL, + PROP_CURRENT_COLOR, + PROP_CURRENT_ALPHA +}; + +enum { + COLORSEL_RED = 0, + COLORSEL_GREEN = 1, + COLORSEL_BLUE = 2, + COLORSEL_OPACITY = 3, + COLORSEL_HUE, + COLORSEL_SATURATION, + COLORSEL_VALUE, + COLORSEL_NUM_CHANNELS +}; + +typedef struct _ColorSelectionPrivate ColorSelectionPrivate; + +struct _ColorSelectionPrivate +{ + guint has_opacity : 1; + guint has_palette : 1; + guint changing : 1; + guint default_set : 1; + guint default_alpha_set : 1; + + gdouble color[COLORSEL_NUM_CHANNELS]; + gdouble old_color[COLORSEL_NUM_CHANNELS]; + + GtkWidget *triangle_colorsel; + GtkWidget *hue_spinbutton; + GtkWidget *sat_spinbutton; + GtkWidget *val_spinbutton; + GtkWidget *red_spinbutton; + GtkWidget *green_spinbutton; + GtkWidget *blue_spinbutton; + GtkWidget *opacity_slider; + GtkWidget *opacity_label; + GtkWidget *opacity_entry; + GtkWidget *palette_frame; + GtkWidget *hex_entry; + + /* The Palette code */ + GtkWidget *custom_palette [GTK_CUSTOM_PALETTE_WIDTH][GTK_CUSTOM_PALETTE_HEIGHT]; + + /* The color_sample stuff */ + GtkWidget *sample_area; + GtkWidget *old_sample; + GtkWidget *cur_sample; + GtkWidget *colorsel; + + /* Tooltips group */ + GtkTooltips *tooltips; + + /* Window for grabbing on */ + GtkWidget *dropper_grab_widget; + + /* Connection to settings */ + gulong settings_connection; +}; + + +static void gtk_color_selection_init (GtkColorSelection *colorsel); +static void gtk_color_selection_class_init (GtkColorSelectionClass *klass); +static void gtk_color_selection_destroy (GtkObject *object); +static void gtk_color_selection_finalize (GObject *object); +static void update_color (GtkColorSelection *colorsel); +static void gtk_color_selection_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gtk_color_selection_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void gtk_color_selection_realize (GtkWidget *widget); +static void gtk_color_selection_unrealize (GtkWidget *widget); +static void gtk_color_selection_show_all (GtkWidget *widget); + +static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel, + gint index, + GdkColor *color); +static GdkGC *get_focus_gc (GtkWidget *drawing_area, + gint *focus_width); +static void default_noscreen_change_palette_func (const GdkColor *colors, + gint n_colors); +static void default_change_palette_func (GdkScreen *screen, + const GdkColor *colors, + gint n_colors); +static void make_control_relations (AtkObject *atk_obj, + GtkWidget *widget); +static void make_all_relations (AtkObject *atk_obj, + ColorSelectionPrivate *priv); + +static gpointer parent_class = NULL; +static guint color_selection_signals[LAST_SIGNAL] = { 0 }; + +static const gchar default_colors[] = "black:white:gray50:red:purple:blue:light blue:green:yellow:orange:lavender:brown:goldenrod4:dodger blue:pink:light green:gray10:gray30:gray75:gray90"; + +static GtkColorSelectionChangePaletteFunc noscreen_change_palette_hook = default_noscreen_change_palette_func; +static GtkColorSelectionChangePaletteWithScreenFunc change_palette_hook = default_change_palette_func; + +/* The cursor for the dropper */ +#define DROPPER_WIDTH 17 +#define DROPPER_HEIGHT 17 +#define DROPPER_X_HOT 2 +#define DROPPER_Y_HOT 16 + + +static const guchar dropper_bits[] = { + 0xff, 0x8f, 0x01, 0xff, 0x77, 0x01, 0xff, 0xfb, 0x00, 0xff, 0xf8, 0x00, + 0x7f, 0xff, 0x00, 0xff, 0x7e, 0x01, 0xff, 0x9d, 0x01, 0xff, 0xd8, 0x01, + 0x7f, 0xd4, 0x01, 0x3f, 0xee, 0x01, 0x1f, 0xff, 0x01, 0x8f, 0xff, 0x01, + 0xc7, 0xff, 0x01, 0xe3, 0xff, 0x01, 0xf3, 0xff, 0x01, 0xfd, 0xff, 0x01, + 0xff, 0xff, 0x01, }; + +static const guchar dropper_mask[] = { + 0x00, 0x70, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xff, 0x01, + 0x80, 0xff, 0x01, 0x00, 0xff, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x3f, 0x00, + 0xc0, 0x3f, 0x00, 0xe0, 0x13, 0x00, 0xf0, 0x01, 0x00, 0xf8, 0x00, 0x00, + 0x7c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0d, 0x00, 0x00, + 0x02, 0x00, 0x00, }; + + +/* + * + * The Sample Color + * + */ +#define SAMPLE_WIDTH 64 +#define SAMPLE_HEIGHT 28 + +static void color_sample_draw_sample (GtkColorSelection *colorsel, int which); +static void color_sample_draw_samples (GtkColorSelection *colorsel); + +static void +set_color_internal (GtkColorSelection *colorsel, + gdouble *color) +{ + ColorSelectionPrivate *priv; + gint i; + + priv = colorsel->private_data; + priv->changing = TRUE; + priv->color[COLORSEL_RED] = color[0]; + priv->color[COLORSEL_GREEN] = color[1]; + priv->color[COLORSEL_BLUE] = color[2]; + priv->color[COLORSEL_OPACITY] = color[3]; + gtk_rgb_to_hsv (priv->color[COLORSEL_RED], + priv->color[COLORSEL_GREEN], + priv->color[COLORSEL_BLUE], + &priv->color[COLORSEL_HUE], + &priv->color[COLORSEL_SATURATION], + &priv->color[COLORSEL_VALUE]); + if (priv->default_set == FALSE) + { + for (i = 0; i < COLORSEL_NUM_CHANNELS; i++) + priv->old_color[i] = priv->color[i]; + } + priv->default_set = TRUE; + priv->default_alpha_set = TRUE; + update_color (colorsel); +} + +static void +set_color_icon (GdkDragContext *context, + gdouble *colors) +{ + GdkPixbuf *pixbuf; + guint32 pixel; + + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, + 8, 48, 32); + + pixel = (((UNSCALE (colors[COLORSEL_RED]) & 0xff00) << 16) | + ((UNSCALE (colors[COLORSEL_GREEN]) & 0xff00) << 8) | + ((UNSCALE (colors[COLORSEL_BLUE]) & 0xff00))); + + gdk_pixbuf_fill (pixbuf, pixel); + + gtk_drag_set_icon_pixbuf (context, pixbuf, -2, -2); + g_object_unref (pixbuf); +} + +static void +color_sample_drag_begin (GtkWidget *widget, + GdkDragContext *context, + gpointer data) +{ + GtkColorSelection *colorsel = data; + ColorSelectionPrivate *priv; + gdouble *colsrc; + + priv = colorsel->private_data; + + if (widget == priv->old_sample) + colsrc = priv->old_color; + else + colsrc = priv->color; + + set_color_icon (context, colsrc); +} + +static void +color_sample_drag_end (GtkWidget *widget, + GdkDragContext *context, + gpointer data) +{ + g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL); +} + +static void +color_sample_drop_handle (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer data) +{ + GtkColorSelection *colorsel = data; + ColorSelectionPrivate *priv; + guint16 *vals; + gdouble color[4]; + priv = colorsel->private_data; + + /* This is currently a guint16 array of the format: + * R + * G + * B + * opacity + */ + + if (selection_data->length < 0) + return; + + /* We accept drops with the wrong format, since the KDE color + * chooser incorrectly drops application/x-color with format 8. + */ + if (selection_data->length != 8) + { + g_warning ("Received invalid color data\n"); + return; + } + + vals = (guint16 *)selection_data->data; + + if (widget == priv->cur_sample) + { + color[0] = (gdouble)vals[0] / 0xffff; + color[1] = (gdouble)vals[1] / 0xffff; + color[2] = (gdouble)vals[2] / 0xffff; + color[3] = (gdouble)vals[3] / 0xffff; + + set_color_internal (colorsel, color); + } +} + +static void +color_sample_drag_handle (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer data) +{ + GtkColorSelection *colorsel = data; + ColorSelectionPrivate *priv; + guint16 vals[4]; + gdouble *colsrc; + + priv = colorsel->private_data; + + if (widget == priv->old_sample) + colsrc = priv->old_color; + else + colsrc = priv->color; + + vals[0] = colsrc[COLORSEL_RED] * 0xffff; + vals[1] = colsrc[COLORSEL_GREEN] * 0xffff; + vals[2] = colsrc[COLORSEL_BLUE] * 0xffff; + vals[3] = priv->has_opacity ? colsrc[COLORSEL_OPACITY] * 0xffff : 0xffff; + + gtk_selection_data_set (selection_data, + gdk_atom_intern ("application/x-color", FALSE), + 16, (guchar *)vals, 8); +} + +/* which = 0 means draw old sample, which = 1 means draw new */ +static void +color_sample_draw_sample (GtkColorSelection *colorsel, int which) +{ + GtkWidget *da; + gint x, y, i, wid, heig, f, n, goff; + guchar c[3 * 2], cc[3 * 4], *cp = c; + gdouble o; + guchar *buf; + ColorSelectionPrivate *priv; + + g_return_if_fail (colorsel != NULL); + priv = colorsel->private_data; + + g_return_if_fail (priv->sample_area != NULL); + if (!GTK_WIDGET_DRAWABLE (priv->sample_area)) + return; + + if (which == 0) + { + da = priv->old_sample; + for (n = 0, i = COLORSEL_RED; n < 3; n++, i++) + c[n] = (guchar) (UNSCALE (priv->old_color[i]) >> 8); + goff = 0; + } + else + { + da = priv->cur_sample; + for (n = 0, i = COLORSEL_RED; n < 3; n++, i++) + c[n] = (guchar) (UNSCALE (priv->color[i]) >> 8); + goff = priv->old_sample->allocation.width % 32; + } + + wid = da->allocation.width; + heig = da->allocation.height; + + buf = g_new (guchar, 3 * wid * heig); + +#if 0 + i = COLORSEL_RED; + for (n = 0; n < 3; n++) + { + c[n] = (guchar) (255.0 * priv->old_color[i]); + c[n + 3] = (guchar) (255.0 * priv->color[i++]); + } +#endif + + if (priv->has_opacity) + { + o = (which) ? priv->color[COLORSEL_OPACITY] : priv->old_color[COLORSEL_OPACITY]; + + for (n = 0; n < 3; n++) + { + cc[n] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n])); + cc[n + 3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n])); + } + cp = cc; + } + + i = 0; + for (y = 0; y < heig; y++) + { + for (x = 0; x < wid; x++) + { + if (priv->has_opacity) + f = 3 * ((((goff + x) % 32) < 16) ^ ((y % 32) < 16)); + else + f = 0; + + for (n = 0; n < 3; n++) + buf[i++] = cp[n + f]; + } + } + + gdk_draw_rgb_image (da->window, + da->style->black_gc, + 0, 0, + wid, heig, + GDK_RGB_DITHER_NORMAL, + buf, + 3*wid); + + + g_free (buf); +} + + +static void +color_sample_draw_samples (GtkColorSelection *colorsel) +{ + color_sample_draw_sample (colorsel, 0); + color_sample_draw_sample (colorsel, 1); +} + +static gboolean +color_old_sample_expose (GtkWidget *da, + GdkEventExpose *event, + GtkColorSelection *colorsel) +{ + color_sample_draw_sample (colorsel, 0); + return FALSE; +} + + +static gboolean +color_cur_sample_expose (GtkWidget *da, + GdkEventExpose *event, + GtkColorSelection *colorsel) +{ + color_sample_draw_sample (colorsel, 1); + return FALSE; +} + +static void +color_sample_setup_dnd (GtkColorSelection *colorsel, GtkWidget *sample) +{ + static const GtkTargetEntry targets[] = { + { "application/x-color", 0 } + }; + ColorSelectionPrivate *priv; + priv = colorsel->private_data; + + gtk_drag_source_set (sample, + GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, + targets, 1, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + + g_signal_connect (sample, + "drag_begin", + G_CALLBACK (color_sample_drag_begin), + colorsel); + if (sample == priv->cur_sample) + { + + gtk_drag_dest_set (sample, + GTK_DEST_DEFAULT_HIGHLIGHT | + GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_DROP, + targets, 1, + GDK_ACTION_COPY); + + g_signal_connect (sample, + "drag_end", + G_CALLBACK (color_sample_drag_end), + colorsel); + } + + g_signal_connect (sample, + "drag_data_get", + G_CALLBACK (color_sample_drag_handle), + colorsel); + g_signal_connect (sample, + "drag_data_received", + G_CALLBACK (color_sample_drop_handle), + colorsel); + +} + + +static void +color_sample_new (GtkColorSelection *colorsel) +{ + ColorSelectionPrivate *priv; + + priv = colorsel->private_data; + + priv->sample_area = gtk_hbox_new (FALSE, 0); + priv->old_sample = gtk_drawing_area_new (); + priv->cur_sample = gtk_drawing_area_new (); + + /* We need enter/leave to do tooltips */ + gtk_widget_add_events (priv->old_sample, + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_widget_add_events (priv->cur_sample, + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + + gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->old_sample, + TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (priv->sample_area), priv->cur_sample, + TRUE, TRUE, 0); + + g_signal_connect (priv->old_sample, "expose_event", + G_CALLBACK (color_old_sample_expose), + colorsel); + g_signal_connect (priv->cur_sample, "expose_event", + G_CALLBACK (color_cur_sample_expose), + colorsel); + + color_sample_setup_dnd (colorsel, priv->old_sample); + color_sample_setup_dnd (colorsel, priv->cur_sample); + + gtk_tooltips_set_tip (priv->tooltips, + priv->old_sample, + _("The previously-selected color, for comparison to the color you're selecting now. You can drag this color to a palette entry, or select this color as current by dragging it to the other color swatch alongside."), NULL); + + + gtk_tooltips_set_tip (priv->tooltips, + priv->cur_sample, + _("The color you've chosen. You can drag this color to a palette entry to save it for use in the future."), NULL); + + gtk_widget_show_all (priv->sample_area); +} + + +/* + * + * The palette area code + * + */ +#define CUSTOM_PALETTE_ENTRY_WIDTH 20 +#define CUSTOM_PALETTE_ENTRY_HEIGHT 20 + +static void +palette_get_color (GtkWidget *drawing_area, gdouble *color) +{ + gdouble *color_val; + + g_return_if_fail (color != NULL); + + color_val = g_object_get_data (G_OBJECT (drawing_area), "color_val"); + if (color_val == NULL) + { + /* Default to white for no good reason */ + color[0] = 1.0; + color[1] = 1.0; + color[2] = 1.0; + color[3] = 1.0; + return; + } + + color[0] = color_val[0]; + color[1] = color_val[1]; + color[2] = color_val[2]; + color[3] = 1.0; +} + +#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) +static void +palette_paint (GtkWidget *drawing_area, + GdkRectangle *area, + gpointer data) +{ + if (drawing_area->window == NULL) + return; + + gdk_draw_rectangle (drawing_area->window, + drawing_area->style->bg_gc[GTK_STATE_NORMAL], + TRUE, + area->x, area->y, area->width, area->height); + + if (GTK_WIDGET_HAS_FOCUS (drawing_area)) + { + gint focus_width; + GdkGC *gc = get_focus_gc (drawing_area, &focus_width); + gdk_draw_rectangle (drawing_area->window, + gc, FALSE, focus_width / 2, focus_width / 2, + drawing_area->allocation.width - focus_width, + drawing_area->allocation.height - focus_width); + g_object_unref (gc); + } +} + +static GdkGC * +get_focus_gc (GtkWidget *drawing_area, + gint *focus_width) +{ + GdkGC *gc = gdk_gc_new (drawing_area->window); + gdouble color[4]; + gint8 *dash_list; + + gtk_widget_style_get (drawing_area, + "focus-line-width", focus_width, + "focus-line-pattern", (gchar *)&dash_list, + NULL); + + palette_get_color (drawing_area, color); + + if (INTENSITY (color[0], color[1], color[2]) > 0.5) + gdk_gc_copy (gc, drawing_area->style->black_gc); + else + gdk_gc_copy (gc, drawing_area->style->white_gc); + + gdk_gc_set_line_attributes (gc, *focus_width, + dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID, + GDK_CAP_BUTT, GDK_JOIN_MITER); + + if (dash_list[0]) + gdk_gc_set_dashes (gc, 0, dash_list, strlen ((char *)dash_list)); + + g_free (dash_list); + + return gc; +} + +static void +palette_drag_begin (GtkWidget *widget, + GdkDragContext *context, + gpointer data) +{ + gdouble colors[4]; + + palette_get_color (widget, colors); + set_color_icon (context, colors); +} + +static void +palette_drag_handle (GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer data) +{ + guint16 vals[4]; + gdouble colsrc[4]; + + palette_get_color (widget, colsrc); + + vals[0] = colsrc[COLORSEL_RED] * 0xffff; + vals[1] = colsrc[COLORSEL_GREEN] * 0xffff; + vals[2] = colsrc[COLORSEL_BLUE] * 0xffff; + vals[3] = 0xffff; + + gtk_selection_data_set (selection_data, + gdk_atom_intern ("application/x-color", FALSE), + 16, (guchar *)vals, 8); +} + +static void +palette_drag_end (GtkWidget *widget, + GdkDragContext *context, + gpointer data) +{ + g_object_set_data (G_OBJECT (widget), "gtk-color-selection-drag-window", NULL); +} + +static GdkColor * +get_current_colors (GtkColorSelection *colorsel) +{ + GtkSettings *settings; + GdkColor *colors = NULL; + gint n_colors = 0; + gchar *palette; + + settings = gtk_widget_get_settings (GTK_WIDGET (colorsel)); + g_object_get (settings, + "gtk-color-palette", &palette, + NULL); + + if (!gtk_color_selection_palette_from_string (palette, &colors, &n_colors)) + { + gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors); + } + else + { + /* If there are less colors provided than the number of slots in the + * color selection, we fill in the rest from the defaults. + */ + if (n_colors < (GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT)) + { + GdkColor *tmp_colors = colors; + gint tmp_n_colors = n_colors; + + gtk_color_selection_palette_from_string (default_colors, &colors, &n_colors); + memcpy (colors, tmp_colors, sizeof (GdkColor) * tmp_n_colors); + + g_free (tmp_colors); + } + } + + g_assert (n_colors >= GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT); + g_free (palette); + + return colors; +} + +/* Changes the model color */ +static void +palette_change_color (GtkWidget *drawing_area, + GtkColorSelection *colorsel, + gdouble *color) +{ + gint x, y; + ColorSelectionPrivate *priv; + GdkColor gdk_color; + GdkColor *current_colors; + GdkScreen *screen; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + g_return_if_fail (GTK_IS_DRAWING_AREA (drawing_area)); + + priv = colorsel->private_data; + + gdk_color.red = UNSCALE (color[0]); + gdk_color.green = UNSCALE (color[1]); + gdk_color.blue = UNSCALE (color[2]); + + x = 0; + y = 0; /* Quiet GCC */ + while (x < GTK_CUSTOM_PALETTE_WIDTH) + { + y = 0; + while (y < GTK_CUSTOM_PALETTE_HEIGHT) + { + if (priv->custom_palette[x][y] == drawing_area) + goto out; + + ++y; + } + + ++x; + } + + out: + + g_assert (x < GTK_CUSTOM_PALETTE_WIDTH || y < GTK_CUSTOM_PALETTE_HEIGHT); + + current_colors = get_current_colors (colorsel); + current_colors[y * GTK_CUSTOM_PALETTE_WIDTH + x] = gdk_color; + + screen = gtk_widget_get_screen (GTK_WIDGET (colorsel)); + if (change_palette_hook != default_change_palette_func) + (* change_palette_hook) (screen, current_colors, + GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT); + else if (noscreen_change_palette_hook != default_noscreen_change_palette_func) + { + if (screen != gdk_screen_get_default ()) + g_warning ("gtk_color_selection_set_change_palette_hook used by widget is not on the default screen."); + (* noscreen_change_palette_hook) (current_colors, + GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT); + } + else + (* change_palette_hook) (screen, current_colors, + GTK_CUSTOM_PALETTE_WIDTH * GTK_CUSTOM_PALETTE_HEIGHT); + + g_free (current_colors); +} + +/* Changes the view color */ +static void +palette_set_color (GtkWidget *drawing_area, + GtkColorSelection *colorsel, + gdouble *color) +{ + gdouble *new_color = g_new (double, 4); + GdkColor gdk_color; + + gdk_color.red = UNSCALE (color[0]); + gdk_color.green = UNSCALE (color[1]); + gdk_color.blue = UNSCALE (color[2]); + + gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &gdk_color); + + if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) == 0) + { + static const GtkTargetEntry targets[] = { + { "application/x-color", 0 } + }; + gtk_drag_source_set (drawing_area, + GDK_BUTTON1_MASK | GDK_BUTTON3_MASK, + targets, 1, + GDK_ACTION_COPY | GDK_ACTION_MOVE); + + g_signal_connect (drawing_area, + "drag_begin", + G_CALLBACK (palette_drag_begin), + colorsel); + g_signal_connect (drawing_area, + "drag_data_get", + G_CALLBACK (palette_drag_handle), + colorsel); + + g_object_set_data (G_OBJECT (drawing_area), "color_set", + GINT_TO_POINTER (1)); + } + + new_color[0] = color[0]; + new_color[1] = color[1]; + new_color[2] = color[2]; + new_color[3] = 1.0; + + g_object_set_data_full (G_OBJECT (drawing_area), "color_val", new_color, (GDestroyNotify)g_free); +} + +static gboolean +palette_expose (GtkWidget *drawing_area, + GdkEventExpose *event, + gpointer data) +{ + if (drawing_area->window == NULL) + return FALSE; + + palette_paint (drawing_area, &(event->area), data); + + return FALSE; +} + +static void +popup_position_func (GtkMenu *menu, + gint *x, + gint *y, + gboolean *push_in, + gpointer user_data) +{ + GtkWidget *widget; + GtkRequisition req; + gint root_x, root_y; + GdkScreen *screen; + + widget = GTK_WIDGET (user_data); + + g_return_if_fail (GTK_WIDGET_REALIZED (widget)); + + gdk_window_get_origin (widget->window, &root_x, &root_y); + + gtk_widget_size_request (GTK_WIDGET (menu), &req); + + /* Put corner of menu centered on color cell */ + *x = root_x + widget->allocation.width / 2; + *y = root_y + widget->allocation.height / 2; + + /* Ensure sanity */ + screen = gtk_widget_get_screen (widget); + *x = CLAMP (*x, 0, MAX (0, gdk_screen_get_width (screen) - req.width)); + *y = CLAMP (*y, 0, MAX (0, gdk_screen_get_height (screen) - req.height)); +} + +static void +save_color_selected (GtkWidget *menuitem, + gpointer data) +{ + GtkColorSelection *colorsel; + GtkWidget *drawing_area; + ColorSelectionPrivate *priv; + + drawing_area = GTK_WIDGET (data); + + colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (drawing_area), + "gtk-color-sel")); + + priv = colorsel->private_data; + + palette_change_color (drawing_area, colorsel, priv->color); +} + +static void +do_popup (GtkColorSelection *colorsel, + GtkWidget *drawing_area, + guint32 timestamp) +{ + GtkWidget *menu; + GtkWidget *mi; + + g_object_set_data (G_OBJECT (drawing_area), + "gtk-color-sel", + colorsel); + + menu = gtk_menu_new (); + + mi = gtk_menu_item_new_with_mnemonic (_("_Save color here")); + + g_signal_connect (mi, "activate", + G_CALLBACK (save_color_selected), + drawing_area); + + gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi); + + gtk_widget_show_all (mi); + + gtk_menu_popup (GTK_MENU (menu), NULL, NULL, + popup_position_func, drawing_area, + 3, timestamp); +} + + +static gboolean +palette_enter (GtkWidget *drawing_area, + GdkEventCrossing *event, + gpointer data) +{ + g_object_set_data (G_OBJECT (drawing_area), + "gtk-colorsel-have-pointer", + GUINT_TO_POINTER (TRUE)); + + return FALSE; +} + +static gboolean +palette_leave (GtkWidget *drawing_area, + GdkEventCrossing *event, + gpointer data) +{ + g_object_set_data (G_OBJECT (drawing_area), + "gtk-colorsel-have-pointer", + NULL); + + return FALSE; +} + +static gboolean +palette_press (GtkWidget *drawing_area, + GdkEventButton *event, + gpointer data) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); + + gtk_widget_grab_focus (drawing_area); + + if (event->button == 3 && + event->type == GDK_BUTTON_PRESS) + { + do_popup (colorsel, drawing_area, event->time); + return TRUE; + } + + return FALSE; +} + +static gboolean +palette_release (GtkWidget *drawing_area, + GdkEventButton *event, + gpointer data) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); + + gtk_widget_grab_focus (drawing_area); + + if (event->button == 1 && + g_object_get_data (G_OBJECT (drawing_area), + "gtk-colorsel-have-pointer") != NULL) + { + if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (drawing_area), "color_set")) != 0) + { + gdouble color[4]; + palette_get_color (drawing_area, color); + set_color_internal (colorsel, color); + } + } + + return FALSE; +} + +static void +palette_drop_handle (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time, + gpointer data) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); + guint16 *vals; + gdouble color[4]; + + if (selection_data->length < 0) + return; + + /* We accept drops with the wrong format, since the KDE color + * chooser incorrectly drops application/x-color with format 8. + */ + if (selection_data->length != 8) + { + g_warning ("Received invalid color data\n"); + return; + } + + vals = (guint16 *)selection_data->data; + + color[0] = (gdouble)vals[0] / 0xffff; + color[1] = (gdouble)vals[1] / 0xffff; + color[2] = (gdouble)vals[2] / 0xffff; + color[3] = (gdouble)vals[3] / 0xffff; + palette_change_color (widget, colorsel, color); + set_color_internal (colorsel, color); +} + +static gint +palette_activate (GtkWidget *widget, + GdkEventKey *event, + gpointer data) +{ + /* should have a drawing area subclass with an activate signal */ + if ((event->keyval == GDK_space) || + (event->keyval == GDK_Return) || + (event->keyval == GDK_KP_Enter) || + (event->keyval == GDK_KP_Space)) + { + if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "color_set")) != 0) + { + gdouble color[4]; + palette_get_color (widget, color); + set_color_internal (GTK_COLOR_SELECTION (data), color); + } + return TRUE; + } + + return FALSE; +} + +static gboolean +palette_popup (GtkWidget *widget, + gpointer data) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (data); + + do_popup (colorsel, widget, GDK_CURRENT_TIME); + return TRUE; +} + + +static GtkWidget* +palette_new (GtkColorSelection *colorsel) +{ + GtkWidget *retval; + ColorSelectionPrivate *priv; + + static const GtkTargetEntry targets[] = { + { "application/x-color", 0 } + }; + + priv = colorsel->private_data; + + retval = gtk_drawing_area_new (); + + GTK_WIDGET_SET_FLAGS (retval, GTK_CAN_FOCUS); + + g_object_set_data (G_OBJECT (retval), "color_set", GINT_TO_POINTER (0)); + gtk_widget_set_events (retval, GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_EXPOSURE_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK); + + g_signal_connect (retval, "expose_event", + G_CALLBACK (palette_expose), colorsel); + g_signal_connect (retval, "button_press_event", + G_CALLBACK (palette_press), colorsel); + g_signal_connect (retval, "button_release_event", + G_CALLBACK (palette_release), colorsel); + g_signal_connect (retval, "enter_notify_event", + G_CALLBACK (palette_enter), colorsel); + g_signal_connect (retval, "leave_notify_event", + G_CALLBACK (palette_leave), colorsel); + g_signal_connect (retval, "key_press_event", + G_CALLBACK (palette_activate), colorsel); + g_signal_connect (retval, "popup_menu", + G_CALLBACK (palette_popup), colorsel); + + gtk_drag_dest_set (retval, + GTK_DEST_DEFAULT_HIGHLIGHT | + GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_DROP, + targets, 1, + GDK_ACTION_COPY); + + g_signal_connect (retval, "drag_end", + G_CALLBACK (palette_drag_end), NULL); + g_signal_connect (retval, "drag_data_received", + G_CALLBACK (palette_drop_handle), colorsel); + + gtk_tooltips_set_tip (priv->tooltips, + retval, + _("Click this palette entry to make it the current color. To change this entry, drag a color swatch here or right-click it and select \"Save color here.\""), + NULL); + return retval; +} + + +/* + * + * The actual GtkColorSelection widget + * + */ + +static GdkCursor * +make_picker_cursor (GdkScreen *screen) +{ + GdkCursor *cursor; + GdkColor bg = { 0, 0xffff, 0xffff, 0xffff }; + GdkColor fg = { 0, 0x0000, 0x0000, 0x0000 }; + GdkWindow *window = gdk_screen_get_root_window (screen); + + GdkPixmap *pixmap = + gdk_bitmap_create_from_data (window, (gchar *) dropper_bits, + DROPPER_WIDTH, DROPPER_HEIGHT); + + GdkPixmap *mask = + gdk_bitmap_create_from_data (window, (gchar *) dropper_mask, + DROPPER_WIDTH, DROPPER_HEIGHT); + + cursor = gdk_cursor_new_from_pixmap (pixmap, mask, &fg, &bg, + DROPPER_X_HOT, DROPPER_Y_HOT); + + g_object_unref (pixmap); + g_object_unref (mask); + + return cursor; +} + +static void +grab_color_at_mouse (GdkScreen *screen, + gint x_root, + gint y_root, + gpointer data) +{ + GdkImage *image; + guint32 pixel; + GtkColorSelection *colorsel = data; + ColorSelectionPrivate *priv; + GdkColor color; + GdkColormap *colormap = gdk_screen_get_system_colormap (screen); + GdkWindow *root_window = gdk_screen_get_root_window (screen); + + priv = colorsel->private_data; + + image = gdk_drawable_get_image (root_window, x_root, y_root, 1, 1); + pixel = gdk_image_get_pixel (image, 0, 0); + g_object_unref (image); + + gdk_colormap_query_color (colormap, pixel, &color); + + priv->color[COLORSEL_RED] = SCALE (color.red); + priv->color[COLORSEL_GREEN] = SCALE (color.green); + priv->color[COLORSEL_BLUE] = SCALE (color.blue); + + gtk_rgb_to_hsv (priv->color[COLORSEL_RED], + priv->color[COLORSEL_GREEN], + priv->color[COLORSEL_BLUE], + &priv->color[COLORSEL_HUE], + &priv->color[COLORSEL_SATURATION], + &priv->color[COLORSEL_VALUE]); + + update_color (colorsel); +} + +static void +shutdown_eyedropper (GtkWidget *widget) +{ + GtkColorSelection *colorsel; + ColorSelectionPrivate *priv; + GdkDisplay *display = gtk_widget_get_display (widget); + guint32 time = gtk_get_current_event_time (); + + colorsel = GTK_COLOR_SELECTION (widget); + priv = colorsel->private_data; + + gdk_display_keyboard_ungrab (display, time); + gdk_display_pointer_ungrab (display, time); + gtk_grab_remove (priv->dropper_grab_widget); +} + +static void +mouse_motion (GtkWidget *invisible, + GdkEventMotion *event, + gpointer data) +{ + grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event), + event->x_root, event->y_root, data); +} + +static gboolean +mouse_release (GtkWidget *invisible, + GdkEventButton *event, + gpointer data) +{ + GtkColorSelection *colorsel = data; + ColorSelectionPrivate *priv; + priv = colorsel->private_data; + + if (event->button != 1) + return FALSE; + + grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event), + event->x_root, event->y_root, data); + + shutdown_eyedropper (GTK_WIDGET (data)); + + g_signal_handlers_disconnect_by_func (invisible, + mouse_motion, + data); + g_signal_handlers_disconnect_by_func (invisible, + mouse_release, + data); + + return TRUE; +} + +/* Helper Functions */ + +static gboolean mouse_press (GtkWidget *invisible, + GdkEventButton *event, + gpointer data); + +#define BIG_STEP 20 + +static gboolean +key_press (GtkWidget *invisible, + GdkEventKey *event, + gpointer data) +{ + GdkDisplay *display = gtk_widget_get_display (invisible); + guint state = event->state & gtk_accelerator_get_default_mod_mask (); + gint x, y; + gint dx, dy; + + dx = 0; + dy = 0; + + switch (event->keyval) + { + case GDK_space: + case GDK_Return: + case GDK_KP_Enter: + case GDK_KP_Space: + gdk_display_get_pointer (display, + NULL, &x, &y, NULL); + grab_color_at_mouse (gdk_event_get_screen ((GdkEvent *)event), + x, y, data); + /* fall through */ + + case GDK_Escape: + shutdown_eyedropper (data); + + g_signal_handlers_disconnect_by_func (invisible, + mouse_press, + data); + g_signal_handlers_disconnect_by_func (invisible, + key_press, + data); + + return TRUE; + +#if defined GDK_WINDOWING_X11 || defined GDK_WINDOWING_WIN32 + case GDK_Up: + case GDK_KP_Up: + dy = state == GDK_MOD1_MASK ? -BIG_STEP : -1; + break; + + case GDK_Down: + case GDK_KP_Down: + dy = state == GDK_MOD1_MASK ? BIG_STEP : 1; + break; + + case GDK_Left: + case GDK_KP_Left: + dx = state == GDK_MOD1_MASK ? -BIG_STEP : -1; + break; + + case GDK_Right: + case GDK_KP_Right: + dx = state == GDK_MOD1_MASK ? BIG_STEP : 1; + break; +#endif + + default: + return FALSE; + } + +#ifdef GDK_WINDOWING_X11 + XWarpPointer (gdk_x11_display_get_xdisplay (display), + None, None, 0, 0, 0, 0, dx, dy); +#elif defined GDK_WINDOWING_WIN32 + { + POINT point; + if (GetCursorPos (&point)) + SetCursorPos (point.x + dx, point.y + dy); + } +#endif + + return TRUE; + +} + +static gboolean +mouse_press (GtkWidget *invisible, + GdkEventButton *event, + gpointer data) +{ + GtkColorSelection *colorsel = data; + ColorSelectionPrivate *priv; + priv = colorsel->private_data; + + if (event->type == GDK_BUTTON_PRESS && + event->button == 1) + { + g_signal_connect (invisible, "motion_notify_event", + G_CALLBACK (mouse_motion), + data); + g_signal_connect (invisible, "button_release_event", + G_CALLBACK (mouse_release), + data); + g_signal_handlers_disconnect_by_func (invisible, + mouse_press, + data); + g_signal_handlers_disconnect_by_func (invisible, + key_press, + data); + return TRUE; + } + + return FALSE; +} + +/* when the button is clicked */ +static void +get_screen_color (GtkWidget *button) +{ + GtkColorSelection *colorsel = g_object_get_data (G_OBJECT (button), "COLORSEL"); + ColorSelectionPrivate *priv = colorsel->private_data; + GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (button)); + GdkCursor *picker_cursor; + GdkGrabStatus grab_status; + + if (priv->dropper_grab_widget == NULL) + { + priv->dropper_grab_widget = gtk_invisible_new_for_screen (screen); + + gtk_widget_add_events (priv->dropper_grab_widget, + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK); + + gtk_widget_show (priv->dropper_grab_widget); + } + + if (gdk_keyboard_grab (priv->dropper_grab_widget->window, + FALSE, + gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS) + return; + + picker_cursor = make_picker_cursor (screen); + grab_status = gdk_pointer_grab (priv->dropper_grab_widget->window, + FALSE, + GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK, + NULL, + picker_cursor, + gtk_get_current_event_time ()); + gdk_cursor_unref (picker_cursor); + + if (grab_status != GDK_GRAB_SUCCESS) + { + gdk_display_keyboard_ungrab (gtk_widget_get_display (button), GDK_CURRENT_TIME); + return; + } + + gtk_grab_add (priv->dropper_grab_widget); + + g_signal_connect (priv->dropper_grab_widget, "button_press_event", + G_CALLBACK (mouse_press), colorsel); + g_signal_connect (priv->dropper_grab_widget, "key_press_event", + G_CALLBACK (key_press), colorsel); +} + +static void +hex_changed (GtkWidget *hex_entry, + gpointer data) +{ + GtkColorSelection *colorsel; + ColorSelectionPrivate *priv; + GdkColor color; + gchar *text; + + colorsel = GTK_COLOR_SELECTION (data); + priv = colorsel->private_data; + + if (priv->changing) + return; + + text = gtk_editable_get_chars (GTK_EDITABLE (priv->hex_entry), 0, -1); + if (gdk_color_parse (text, &color)) + { + priv->color[COLORSEL_RED] = CLAMP (color.red/65535.0, 0.0, 1.0); + priv->color[COLORSEL_GREEN] = CLAMP (color.green/65535.0, 0.0, 1.0); + priv->color[COLORSEL_BLUE] = CLAMP (color.blue/65535.0, 0.0, 1.0); + gtk_rgb_to_hsv (priv->color[COLORSEL_RED], + priv->color[COLORSEL_GREEN], + priv->color[COLORSEL_BLUE], + &priv->color[COLORSEL_HUE], + &priv->color[COLORSEL_SATURATION], + &priv->color[COLORSEL_VALUE]); + update_color (colorsel); + } + g_free (text); +} + +static gboolean +hex_focus_out (GtkWidget *hex_entry, + GdkEventFocus *event, + gpointer data) +{ + hex_changed (hex_entry, data); + + return FALSE; +} + +static void +hsv_changed (GtkWidget *hsv, + gpointer data) +{ + GtkColorSelection *colorsel; + ColorSelectionPrivate *priv; + + colorsel = GTK_COLOR_SELECTION (data); + priv = colorsel->private_data; + + if (priv->changing) + return; + + gtk_hsv_get_color (GTK_HSV (hsv), + &priv->color[COLORSEL_HUE], + &priv->color[COLORSEL_SATURATION], + &priv->color[COLORSEL_VALUE]); + gtk_hsv_to_rgb (priv->color[COLORSEL_HUE], + priv->color[COLORSEL_SATURATION], + priv->color[COLORSEL_VALUE], + &priv->color[COLORSEL_RED], + &priv->color[COLORSEL_GREEN], + &priv->color[COLORSEL_BLUE]); + update_color (colorsel); +} + +static void +adjustment_changed (GtkAdjustment *adjustment, + gpointer data) +{ + GtkColorSelection *colorsel; + ColorSelectionPrivate *priv; + + colorsel = GTK_COLOR_SELECTION (g_object_get_data (G_OBJECT (adjustment), "COLORSEL")); + priv = colorsel->private_data; + + if (priv->changing) + return; + + switch (GPOINTER_TO_INT (data)) + { + case COLORSEL_SATURATION: + case COLORSEL_VALUE: + priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 100; + gtk_hsv_to_rgb (priv->color[COLORSEL_HUE], + priv->color[COLORSEL_SATURATION], + priv->color[COLORSEL_VALUE], + &priv->color[COLORSEL_RED], + &priv->color[COLORSEL_GREEN], + &priv->color[COLORSEL_BLUE]); + break; + case COLORSEL_HUE: + priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 360; + gtk_hsv_to_rgb (priv->color[COLORSEL_HUE], + priv->color[COLORSEL_SATURATION], + priv->color[COLORSEL_VALUE], + &priv->color[COLORSEL_RED], + &priv->color[COLORSEL_GREEN], + &priv->color[COLORSEL_BLUE]); + break; + case COLORSEL_RED: + case COLORSEL_GREEN: + case COLORSEL_BLUE: + priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255; + + gtk_rgb_to_hsv (priv->color[COLORSEL_RED], + priv->color[COLORSEL_GREEN], + priv->color[COLORSEL_BLUE], + &priv->color[COLORSEL_HUE], + &priv->color[COLORSEL_SATURATION], + &priv->color[COLORSEL_VALUE]); + break; + default: + priv->color[GPOINTER_TO_INT (data)] = adjustment->value / 255; + break; + } + update_color (colorsel); +} + +static void +opacity_entry_changed (GtkWidget *opacity_entry, + gpointer data) +{ + GtkColorSelection *colorsel; + ColorSelectionPrivate *priv; + GtkAdjustment *adj; + gchar *text; + + colorsel = GTK_COLOR_SELECTION (data); + priv = colorsel->private_data; + + if (priv->changing) + return; + + text = gtk_editable_get_chars (GTK_EDITABLE (priv->opacity_entry), 0, -1); + adj = gtk_range_get_adjustment (GTK_RANGE (priv->opacity_slider)); + gtk_adjustment_set_value (adj, g_strtod (text, NULL)); + + update_color (colorsel); + + g_free (text); +} + +static void +make_label_spinbutton (GtkColorSelection *colorsel, + GtkWidget **spinbutton, + gchar *text, + GtkWidget *table, + gint i, + gint j, + gint channel_type, + const gchar *tooltip) +{ + GtkWidget *hbox; + GtkWidget *label; + GtkAdjustment *adjust; + ColorSelectionPrivate *priv = colorsel->private_data; + + if (channel_type == COLORSEL_HUE) + { + adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 360.0, 1.0, 1.0, 1.0)); + } + else if (channel_type == COLORSEL_SATURATION || + channel_type == COLORSEL_VALUE) + { + adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 1.0, 1.0)); + } + else + { + adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 1.0)); + } + g_object_set_data (G_OBJECT (adjust), "COLORSEL", colorsel); + *spinbutton = gtk_spin_button_new (adjust, 10.0, 0); + gtk_widget_set_size_request(*spinbutton,42,-1); + + gtk_tooltips_set_tip (priv->tooltips, *spinbutton, tooltip, NULL); + + g_signal_connect (adjust, "value_changed", + G_CALLBACK (adjustment_changed), + GINT_TO_POINTER (channel_type)); + label = gtk_label_new_with_mnemonic (text); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), *spinbutton); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + + // create hbox with 2 placeholders and add the hbox to one table element + hbox = gtk_hbox_new(FALSE,1); + gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(label),FALSE,FALSE,0); + gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(*spinbutton),TRUE,TRUE,0); + gtk_table_attach(GTK_TABLE (table),hbox,i, i+1, j, j+1,GTK_FILL,GTK_FILL,0,0); +} + +static void +make_palette_frame (GtkColorSelection *colorsel, + GtkWidget *table, + gint i, + gint j) +{ + GtkWidget *frame; + ColorSelectionPrivate *priv; + + priv = colorsel->private_data; + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + priv->custom_palette[i][j] = palette_new (colorsel); + gtk_widget_set_size_request (priv->custom_palette[i][j], CUSTOM_PALETTE_ENTRY_WIDTH, 0.75*CUSTOM_PALETTE_ENTRY_HEIGHT); + gtk_container_add (GTK_CONTAINER (frame), priv->custom_palette[i][j]); + gtk_table_attach_defaults(GTK_TABLE (table), frame, i, i+1, j, j+1); +} + +/* Set the palette entry [x][y] to be the currently selected one. */ +static void +set_selected_palette (GtkColorSelection *colorsel, int x, int y) +{ + ColorSelectionPrivate *priv = colorsel->private_data; + + gtk_widget_grab_focus (priv->custom_palette[x][y]); +} + +static double +scale_round (double val, double factor) +{ + val = floor (val * factor + 0.5); + val = MAX (val, 0); + val = MIN (val, factor); + return val; +} + +static void +update_color (GtkColorSelection *colorsel) +{ + ColorSelectionPrivate *priv = colorsel->private_data; + gchar entryval[12]; + gchar opacity_text[32]; + gchar *ptr; + + priv->changing = TRUE; + color_sample_draw_samples (colorsel); + + gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel), + priv->color[COLORSEL_HUE], + priv->color[COLORSEL_SATURATION], + priv->color[COLORSEL_VALUE]); + gtk_adjustment_set_value (gtk_spin_button_get_adjustment + (GTK_SPIN_BUTTON (priv->hue_spinbutton)), + scale_round (priv->color[COLORSEL_HUE], 360)); + gtk_adjustment_set_value (gtk_spin_button_get_adjustment + (GTK_SPIN_BUTTON (priv->sat_spinbutton)), + scale_round (priv->color[COLORSEL_SATURATION], 100)); + gtk_adjustment_set_value (gtk_spin_button_get_adjustment + (GTK_SPIN_BUTTON (priv->val_spinbutton)), + scale_round (priv->color[COLORSEL_VALUE], 100)); + gtk_adjustment_set_value (gtk_spin_button_get_adjustment + (GTK_SPIN_BUTTON (priv->red_spinbutton)), + scale_round (priv->color[COLORSEL_RED], 255)); + gtk_adjustment_set_value (gtk_spin_button_get_adjustment + (GTK_SPIN_BUTTON (priv->green_spinbutton)), + scale_round (priv->color[COLORSEL_GREEN], 255)); + gtk_adjustment_set_value (gtk_spin_button_get_adjustment + (GTK_SPIN_BUTTON (priv->blue_spinbutton)), + scale_round (priv->color[COLORSEL_BLUE], 255)); + gtk_adjustment_set_value (gtk_range_get_adjustment + (GTK_RANGE (priv->opacity_slider)), + scale_round (priv->color[COLORSEL_OPACITY], 255)); + + g_snprintf (opacity_text, 32, "%.0f", scale_round (priv->color[COLORSEL_OPACITY], 255)); + gtk_entry_set_text (GTK_ENTRY (priv->opacity_entry), opacity_text); + + g_snprintf (entryval, 11, "#%2X%2X%2X", + (guint) (scale_round (priv->color[COLORSEL_RED], 255)), + (guint) (scale_round (priv->color[COLORSEL_GREEN], 255)), + (guint) (scale_round (priv->color[COLORSEL_BLUE], 255))); + + for (ptr = entryval; *ptr; ptr++) + if (*ptr == ' ') + *ptr = '0'; + gtk_entry_set_text (GTK_ENTRY (priv->hex_entry), entryval); + priv->changing = FALSE; + + g_object_ref (colorsel); + + g_signal_emit (colorsel, color_selection_signals[COLOR_CHANGED], 0); + + g_object_freeze_notify (G_OBJECT (colorsel)); + g_object_notify (G_OBJECT (colorsel), "current_color"); + g_object_notify (G_OBJECT (colorsel), "current_alpha"); + g_object_thaw_notify (G_OBJECT (colorsel)); + + g_object_unref (colorsel); +} + +static void +update_palette (GtkColorSelection *colorsel) +{ + GdkColor *current_colors; + gint i, j; + + current_colors = get_current_colors (colorsel); + + for (i = 0; i < GTK_CUSTOM_PALETTE_HEIGHT; i++) + { + for (j = 0; j < GTK_CUSTOM_PALETTE_WIDTH; j++) + { + gint index; + + index = i * GTK_CUSTOM_PALETTE_WIDTH + j; + + gtk_color_selection_set_palette_color (colorsel, + index, + ¤t_colors[index]); + } + } + + g_free (current_colors); +} + +static void +palette_change_notify_instance (GObject *object, + GParamSpec *pspec, + gpointer data) +{ + update_palette (GTK_COLOR_SELECTION (data)); +} + +static void +default_noscreen_change_palette_func (const GdkColor *colors, + gint n_colors) +{ + default_change_palette_func (gdk_screen_get_default (), colors, n_colors); +} + +static void +default_change_palette_func (GdkScreen *screen, + const GdkColor *colors, + gint n_colors) +{ + gchar *str; + + str = gtk_color_selection_palette_to_string (colors, n_colors); + + gtk_settings_set_string_property (gtk_settings_get_for_screen (screen), + "gtk-color-palette", + str, + "gtk_color_selection_palette_to_string"); + + g_free (str); +} + +GType +gtk_color_selection_get_type (void) +{ + static GType color_selection_type = 0; + + if (!color_selection_type) + { + static const GTypeInfo color_selection_info = + { + sizeof (GtkColorSelectionClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_color_selection_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkColorSelection), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_color_selection_init, + }; + + color_selection_type = + g_type_register_static (GTK_TYPE_VBOX, "GtkColorSelection", + &color_selection_info, 0); + } + + return color_selection_type; +} + +static void +gtk_color_selection_class_init (GtkColorSelectionClass *klass) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + gobject_class = G_OBJECT_CLASS (klass); + object_class = GTK_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->destroy = gtk_color_selection_destroy; + gobject_class->finalize = gtk_color_selection_finalize; + + gobject_class->set_property = gtk_color_selection_set_property; + gobject_class->get_property = gtk_color_selection_get_property; + + widget_class->realize = gtk_color_selection_realize; + widget_class->unrealize = gtk_color_selection_unrealize; + widget_class->show_all = gtk_color_selection_show_all; + + g_object_class_install_property (gobject_class, + PROP_HAS_OPACITY_CONTROL, + g_param_spec_boolean ("has_opacity_control", + P_("Has Opacity Control"), + P_("Whether the color selector should allow setting opacity"), + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_HAS_PALETTE, + g_param_spec_boolean ("has_palette", + P_("Has palette"), + P_("Whether a palette should be used"), + FALSE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_CURRENT_COLOR, + g_param_spec_boxed ("current_color", + P_("Current Color"), + P_("The current color"), + GDK_TYPE_COLOR, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, + PROP_CURRENT_ALPHA, + g_param_spec_uint ("current_alpha", + P_("Current Alpha"), + P_("The current opacity value (0 fully transparent, 65535 fully opaque)"), + 0, 65535, 65535, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + color_selection_signals[COLOR_CHANGED] = + g_signal_new ("color_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkColorSelectionClass, color_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + gtk_settings_install_property (g_param_spec_string ("gtk-color-palette", + P_("Custom palette"), + P_("Palette to use in the color selector"), + default_colors, + G_PARAM_READWRITE)); +} + +/* widget functions */ + +static void +gtk_color_selection_init (GtkColorSelection *colorsel) +{ + GtkWidget *top_hbox; + GtkWidget *top_right_vbox; + GtkWidget *palette_table, *table, *label, *hbox, *frame, *vbox, *button; + GtkWidget *opacity_hbox; + GtkWidget *colorhexname_hbox; + GtkAdjustment *adjust; + GtkWidget *picker_image; + gint i, j; + ColorSelectionPrivate *priv; + AtkObject *atk_obj; + + gtk_widget_push_composite_child (); + + priv = colorsel->private_data = g_new0 (ColorSelectionPrivate, 1); + priv->changing = FALSE; + priv->default_set = FALSE; + priv->default_alpha_set = FALSE; + + priv->tooltips = gtk_tooltips_new (); + g_object_ref (priv->tooltips); + gtk_object_sink (GTK_OBJECT (priv->tooltips)); + + gtk_box_set_spacing (GTK_BOX (colorsel), 4); + top_hbox = gtk_vbox_new (FALSE, 8); + gtk_box_pack_start (GTK_BOX (colorsel), top_hbox, FALSE, FALSE, 0); + + vbox = gtk_vbox_new (FALSE, 4); + priv->triangle_colorsel = gtk_hsv_new (); + g_signal_connect (priv->triangle_colorsel, "changed", + G_CALLBACK (hsv_changed), colorsel); + gtk_hsv_set_metrics (GTK_HSV (priv->triangle_colorsel), 145, 15); + gtk_box_pack_start (GTK_BOX (top_hbox), vbox, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), priv->triangle_colorsel, FALSE, FALSE, 0); + gtk_tooltips_set_tip (priv->tooltips, priv->triangle_colorsel, + _("Select the color you want from the outer ring. Select the darkness or lightness of that color using the inner triangle."), NULL); + + hbox = gtk_hbox_new (FALSE, 4); + gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + + frame = gtk_frame_new (NULL); + gtk_widget_set_size_request (frame, -1, 30); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + color_sample_new (colorsel); + gtk_container_add (GTK_CONTAINER (frame), priv->sample_area); + gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0); + + button = gtk_button_new (); + + gtk_widget_set_events (button, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); + g_object_set_data (G_OBJECT (button), "COLORSEL", colorsel); + g_signal_connect (button, "clicked", + G_CALLBACK (get_screen_color), NULL); + picker_image = gtk_image_new_from_stock (GTK_STOCK_COLOR_PICKER, GTK_ICON_SIZE_BUTTON); + gtk_container_add (GTK_CONTAINER (button), picker_image); + gtk_widget_show (GTK_WIDGET (picker_image)); + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + + gtk_tooltips_set_tip (priv->tooltips, + button, + _("Click the eyedropper, then click a color anywhere on your screen to select that color."), NULL); + + top_right_vbox = gtk_vbox_new (FALSE, 4); + gtk_box_pack_start (GTK_BOX (top_hbox), top_right_vbox, TRUE, TRUE, 0); + + table = gtk_table_new (6, 4, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 4); + gtk_table_set_col_spacings (GTK_TABLE (table), 4); + gtk_box_pack_start (GTK_BOX (top_right_vbox), table, TRUE, TRUE, 0); + + make_label_spinbutton (colorsel, &priv->hue_spinbutton, _("H:"), table, 0, 0, COLORSEL_HUE, + _("Position on the color wheel.")); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (priv->hue_spinbutton), TRUE); + make_label_spinbutton (colorsel, &priv->sat_spinbutton, _("S:"), table, 1, 0, COLORSEL_SATURATION, + _("\"Deepness\" of the color.")); + make_label_spinbutton (colorsel, &priv->val_spinbutton, _("V:"), table, 2, 0, COLORSEL_VALUE, + _("Brightness of the color.")); + make_label_spinbutton (colorsel, &priv->red_spinbutton, _("R:"), table, 0, 1, COLORSEL_RED, + _("Amount of red light in the color.")); + make_label_spinbutton (colorsel, &priv->green_spinbutton, _("G:"), table, 1, 1, COLORSEL_GREEN, + _("Amount of green light in the color.")); + make_label_spinbutton (colorsel, &priv->blue_spinbutton, _("B:"), table, 2, 1, COLORSEL_BLUE, + _("Amount of blue light in the color.")); + + + opacity_hbox = gtk_hbox_new(FALSE,1); + priv->opacity_label = gtk_label_new_with_mnemonic (_("Opacity:")); + gtk_misc_set_alignment (GTK_MISC (priv->opacity_label), 1.0, 0.5); + gtk_box_pack_start(GTK_BOX(opacity_hbox),GTK_WIDGET(priv->opacity_label),FALSE,FALSE,0); + adjust = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 255.0, 1.0, 1.0, 0.0)); + g_object_set_data (G_OBJECT (adjust), "COLORSEL", colorsel); + priv->opacity_slider = gtk_hscale_new (adjust); + gtk_tooltips_set_tip (priv->tooltips, + priv->opacity_slider, + _("Transparency of the color."), NULL); + gtk_label_set_mnemonic_widget (GTK_LABEL (priv->opacity_label), + priv->opacity_slider); + gtk_scale_set_draw_value (GTK_SCALE (priv->opacity_slider), FALSE); + g_signal_connect (adjust, "value_changed", + G_CALLBACK (adjustment_changed), + GINT_TO_POINTER (COLORSEL_OPACITY)); + gtk_box_pack_start(GTK_BOX(opacity_hbox),GTK_WIDGET(priv->opacity_slider),TRUE,TRUE,0); + priv->opacity_entry = gtk_entry_new (); + gtk_tooltips_set_tip (priv->tooltips, + priv->opacity_entry, + _("Transparency of the color."), NULL); + gtk_widget_set_size_request (priv->opacity_entry, 40, -1); + + g_signal_connect (priv->opacity_entry, "activate", + G_CALLBACK (opacity_entry_changed), colorsel); + gtk_box_pack_start(GTK_BOX(opacity_hbox),GTK_WIDGET(priv->opacity_entry),FALSE,FALSE,0); + gtk_table_attach(GTK_TABLE (table),opacity_hbox,0, 3, 2, 3,GTK_FILL,GTK_FILL,0,0); + + + colorhexname_hbox = gtk_hbox_new(FALSE,1); + label = gtk_label_new_with_mnemonic (_("Color Name:")); + gtk_box_pack_start(GTK_BOX(colorhexname_hbox),GTK_WIDGET(label),FALSE,FALSE,0); + gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5); + priv->hex_entry = gtk_entry_new (); + gtk_entry_set_text( GTK_ENTRY(priv->hex_entry),"#000000"); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), priv->hex_entry); + + g_signal_connect (priv->hex_entry, "activate", + G_CALLBACK (hex_changed), colorsel); + + g_signal_connect (priv->hex_entry, "focus_out_event", + G_CALLBACK (hex_focus_out), colorsel); + + gtk_tooltips_set_tip (priv->tooltips, + priv->hex_entry, + _("You can enter an HTML-style hexadecimal color value, or simply a color name such as 'orange' in this entry."), NULL); + + gtk_entry_set_width_chars (GTK_ENTRY (priv->hex_entry), 7); + gtk_table_set_col_spacing (GTK_TABLE (table), 3, 15); + gtk_box_pack_start(GTK_BOX(colorhexname_hbox),GTK_WIDGET(priv->hex_entry),TRUE,TRUE,0); + gtk_table_attach(GTK_TABLE (table),colorhexname_hbox,0, 3, 3, 4,GTK_FILL,GTK_FILL,0,0); + + palette_table = gtk_table_new (GTK_CUSTOM_PALETTE_HEIGHT, GTK_CUSTOM_PALETTE_WIDTH, TRUE); + gtk_table_set_row_spacings (GTK_TABLE (palette_table), 0); + gtk_table_set_col_spacings (GTK_TABLE (palette_table), 0); + for (i = 0; i < GTK_CUSTOM_PALETTE_WIDTH; i++) + { + for (j = 0; j < GTK_CUSTOM_PALETTE_HEIGHT; j++) + { + make_palette_frame (colorsel, palette_table, i, j); + } + } + set_selected_palette (colorsel, 0, 0); + priv->palette_frame = gtk_frame_new (NULL); + label = gtk_label_new_with_mnemonic (_("Palette")); + gtk_frame_set_label_widget (GTK_FRAME (priv->palette_frame), label); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), + priv->custom_palette[0][0]); + vbox = gtk_vbox_new (FALSE, 4); + gtk_container_add (GTK_CONTAINER (priv->palette_frame), vbox); + gtk_box_pack_start (GTK_BOX (vbox), palette_table, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 4); + gtk_table_attach(GTK_TABLE (table),priv->palette_frame,0, 3, 4, 5,GTK_FILL,GTK_FILL,0,0); + + gtk_widget_show_all (top_hbox); + + gtk_widget_hide( priv->palette_frame ); + gtk_widget_hide( colorhexname_hbox); + gtk_widget_hide( palette_table ); + gtk_widget_hide( vbox ); + gtk_widget_hide( label ); + gtk_widget_hide( opacity_hbox ); + gtk_widget_hide( top_right_vbox ); + gtk_widget_hide( hbox ); + if (priv->has_opacity == FALSE) + { + gtk_widget_hide (priv->opacity_label); + gtk_widget_hide (priv->opacity_slider); + gtk_widget_hide (priv->opacity_entry); + } + + if (priv->has_palette == FALSE) + { + gtk_widget_hide (priv->palette_frame); + } + + atk_obj = gtk_widget_get_accessible (priv->triangle_colorsel); + if (GTK_IS_ACCESSIBLE (atk_obj)) + { + atk_object_set_name (atk_obj, _("Color Wheel")); + atk_object_set_role (gtk_widget_get_accessible (GTK_WIDGET (colorsel)), ATK_ROLE_COLOR_CHOOSER); + make_all_relations (atk_obj, priv); + } + + gtk_widget_pop_composite_child (); +} + +static void +gtk_color_selection_destroy (GtkObject *object) +{ + GtkColorSelection *cselection = GTK_COLOR_SELECTION (object); + ColorSelectionPrivate *priv = cselection->private_data; + + if (priv->dropper_grab_widget) + { + gtk_widget_destroy (priv->dropper_grab_widget); + priv->dropper_grab_widget = NULL; + } + + if (priv->tooltips) + { + g_object_unref (priv->tooltips); + priv->tooltips = NULL; + } + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +gtk_color_selection_finalize (GObject *object) +{ + GtkColorSelection *cselection = GTK_COLOR_SELECTION (object); + + if (cselection->private_data) + { + g_free (cselection->private_data); + cselection->private_data = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gtk_color_selection_realize (GtkWidget *widget) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget); + ColorSelectionPrivate *priv = colorsel->private_data; + GtkSettings *settings = gtk_widget_get_settings (widget); + + priv->settings_connection = g_signal_connect (settings, + "notify::gtk-color-palette", + G_CALLBACK (palette_change_notify_instance), + widget); + update_palette (colorsel); + + GTK_WIDGET_CLASS (parent_class)->realize (widget); +} + +static void +gtk_color_selection_unrealize (GtkWidget *widget) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (widget); + ColorSelectionPrivate *priv = colorsel->private_data; + GtkSettings *settings = gtk_widget_get_settings (widget); + + g_signal_handler_disconnect (settings, priv->settings_connection); + + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + +/* We override show-all since we have internal widgets that + * shouldn't be shown when you call show_all(), like the + * palette and opacity sliders. + */ +static void +gtk_color_selection_show_all (GtkWidget *widget) +{ + gtk_widget_show (widget); +} + +/** + * gtk_color_selection_new: + * + * Creates a new GtkColorSelection. + * + * Return value: a new #GtkColorSelection + **/ +GtkWidget * +gtk_color_selection_new (void) +{ + GtkColorSelection *colorsel; + ColorSelectionPrivate *priv; + gdouble color[4]; + color[0] = 1.0; + color[1] = 1.0; + color[2] = 1.0; + color[3] = 1.0; + + colorsel = g_object_new (GTK_TYPE_COLOR_SELECTION, NULL); + priv = colorsel->private_data; + set_color_internal (colorsel, color); + gtk_color_selection_set_has_opacity_control (colorsel, TRUE); + + /* We want to make sure that default_set is FALSE */ + /* This way the user can still set it */ + priv->default_set = FALSE; + priv->default_alpha_set = FALSE; + priv->has_palette = 0; + priv->has_opacity=0; + return GTK_WIDGET (colorsel); +} + + +void +gtk_color_selection_set_update_policy (GtkColorSelection *colorsel, + GtkUpdateType policy) +{ + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); +} + +/** + * gtk_color_selection_get_has_opacity_control: + * @colorsel: a #GtkColorSelection. + * + * Determines whether the colorsel has an opacity control. + * + * Return value: %TRUE if the @colorsel has an opacity control. %FALSE if it does't. + **/ +gboolean +gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel) +{ + ColorSelectionPrivate *priv; + + g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE); + + priv = colorsel->private_data; + + return priv->has_opacity; +} + +/** + * gtk_color_selection_set_has_opacity_control: + * @colorsel: a #GtkColorSelection. + * @has_opacity: %TRUE if @colorsel can set the opacity, %FALSE otherwise. + * + * Sets the @colorsel to use or not use opacity. + * + **/ +void +gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel, + gboolean has_opacity) +{ + ColorSelectionPrivate *priv; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + + priv = colorsel->private_data; + has_opacity = has_opacity != FALSE; + + if (priv->has_opacity != has_opacity) + { + priv->has_opacity = has_opacity; + if (has_opacity) + { + gtk_widget_show (priv->opacity_slider); + gtk_widget_show (priv->opacity_label); + gtk_widget_show (priv->opacity_entry); + } + else + { + gtk_widget_hide (priv->opacity_slider); + gtk_widget_hide (priv->opacity_label); + gtk_widget_hide (priv->opacity_entry); + } + color_sample_draw_samples (colorsel); + + g_object_notify (G_OBJECT (colorsel), "has_opacity_control"); + } +} + +/** + * gtk_color_selection_get_has_palette: + * @colorsel: a #GtkColorSelection. + * + * Determines whether the color selector has a color palette. + * + * Return value: %TRUE if the selector has a palette. %FALSE if it hasn't. + **/ +gboolean +gtk_color_selection_get_has_palette (GtkColorSelection *colorsel) +{ + ColorSelectionPrivate *priv; + + g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE); + + priv = colorsel->private_data; + + return priv->has_palette; +} + +/** + * gtk_color_selection_set_has_palette: + * @colorsel: a #GtkColorSelection. + * @has_palette: %TRUE if palette is to be visible, %FALSE otherwise. + * + * Shows and hides the palette based upon the value of @has_palette. + * + **/ +void +gtk_color_selection_set_has_palette (GtkColorSelection *colorsel, + gboolean has_palette) +{ + ColorSelectionPrivate *priv; + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + + priv = colorsel->private_data; + has_palette = has_palette != FALSE; + + if (priv->has_palette != has_palette) + { + priv->has_palette = has_palette; + if (has_palette) + gtk_widget_show (priv->palette_frame); + else + gtk_widget_hide (priv->palette_frame); + + g_object_notify (G_OBJECT (colorsel), "has_palette"); + } +} + +/** + * gtk_color_selection_set_current_color: + * @colorsel: a #GtkColorSelection. + * @color: A #GdkColor to set the current color with. + * + * Sets the current color to be @color. The first time this is called, it will + * also set the original color to be @color too. + **/ +void +gtk_color_selection_set_current_color (GtkColorSelection *colorsel, + const GdkColor *color) +{ + ColorSelectionPrivate *priv; + gint i; + gboolean previous_changed; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + g_return_if_fail (color != NULL); + + priv = colorsel->private_data; + priv->changing = TRUE; + priv->color[COLORSEL_RED] = SCALE (color->red); + priv->color[COLORSEL_GREEN] = SCALE (color->green); + priv->color[COLORSEL_BLUE] = SCALE (color->blue); + gtk_rgb_to_hsv (priv->color[COLORSEL_RED], + priv->color[COLORSEL_GREEN], + priv->color[COLORSEL_BLUE], + &priv->color[COLORSEL_HUE], + &priv->color[COLORSEL_SATURATION], + &priv->color[COLORSEL_VALUE]); + if (priv->default_set == FALSE) + { + previous_changed = TRUE; + for (i = 0; i < COLORSEL_NUM_CHANNELS; i++) + priv->old_color[i] = priv->color[i]; + } + priv->default_set = TRUE; + update_color (colorsel); +} + +/** + * gtk_color_selection_set_current_alpha: + * @colorsel: a #GtkColorSelection. + * @alpha: an integer between 0 and 65535. + * + * Sets the current opacity to be @alpha. The first time this is called, it will + * also set the original opacity to be @alpha too. + **/ +void +gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel, + guint16 alpha) +{ + ColorSelectionPrivate *priv; + gint i; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + + priv = colorsel->private_data; + priv->changing = TRUE; + priv->color[COLORSEL_OPACITY] = SCALE (alpha); + if (priv->default_alpha_set == FALSE) + { + for (i = 0; i < COLORSEL_NUM_CHANNELS; i++) + priv->old_color[i] = priv->color[i]; + } + priv->default_alpha_set = TRUE; + update_color (colorsel); +} + +/** + * gtk_color_selection_set_color: + * @colorsel: a #GtkColorSelection. + * @color: an array of 4 doubles specifying the red, green, blue and opacity + * to set the current color to. + * + * Sets the current color to be @color. The first time this is called, it will + * also set the original color to be @color too. + * + * Deprecated: Use gtk_color_selection_set_current_color() instead. + **/ +void +gtk_color_selection_set_color (GtkColorSelection *colorsel, + gdouble *color) +{ + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + + set_color_internal (colorsel, color); +} + +/** + * gtk_color_selection_get_current_color: + * @colorsel: a #GtkColorSelection. + * @color: a #GdkColor to fill in with the current color. + * + * Sets @color to be the current color in the GtkColorSelection widget. + **/ +void +gtk_color_selection_get_current_color (GtkColorSelection *colorsel, + GdkColor *color) +{ + ColorSelectionPrivate *priv; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + g_return_if_fail (color != NULL); + + priv = colorsel->private_data; + color->red = UNSCALE (priv->color[COLORSEL_RED]); + color->green = UNSCALE (priv->color[COLORSEL_GREEN]); + color->blue = UNSCALE (priv->color[COLORSEL_BLUE]); +} + +/** + * gtk_color_selection_get_current_alpha: + * @colorsel: a #GtkColorSelection. + * + * Returns the current alpha value. + * + * Return value: an integer between 0 and 65535. + **/ +guint16 +gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel) +{ + ColorSelectionPrivate *priv; + + g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0); + + priv = colorsel->private_data; + return priv->has_opacity ? UNSCALE (priv->color[COLORSEL_OPACITY]) : 65535; +} + +/** + * gtk_color_selection_get_color: + * @colorsel: a #GtkColorSelection. + * @color: an array of 4 #gdouble to fill in with the current color. + * + * Sets @color to be the current color in the GtkColorSelection widget. + * + * This function is deprecated, use gtk_color_selection_get_current_color() instead. + **/ +void +gtk_color_selection_get_color (GtkColorSelection *colorsel, + gdouble *color) +{ + ColorSelectionPrivate *priv; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + + priv = colorsel->private_data; + color[0] = priv->color[COLORSEL_RED]; + color[1] = priv->color[COLORSEL_GREEN]; + color[2] = priv->color[COLORSEL_BLUE]; + color[3] = priv->has_opacity ? priv->color[COLORSEL_OPACITY] : 65535; +} + +/** + * gtk_color_selection_set_previous_color: + * @colorsel: a #GtkColorSelection. + * @color: a #GdkColor to set the previous color with. + * + * Sets the 'previous' color to be @color. This function should be called with + * some hesitations, as it might seem confusing to have that color change. + * Calling gtk_color_selection_set_current_color() will also set this color the first + * time it is called. + **/ +void +gtk_color_selection_set_previous_color (GtkColorSelection *colorsel, + const GdkColor *color) +{ + ColorSelectionPrivate *priv; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + g_return_if_fail (color != NULL); + + priv = colorsel->private_data; + priv->changing = TRUE; + priv->old_color[COLORSEL_RED] = SCALE (color->red); + priv->old_color[COLORSEL_GREEN] = SCALE (color->green); + priv->old_color[COLORSEL_BLUE] = SCALE (color->blue); + gtk_rgb_to_hsv (priv->old_color[COLORSEL_RED], + priv->old_color[COLORSEL_GREEN], + priv->old_color[COLORSEL_BLUE], + &priv->old_color[COLORSEL_HUE], + &priv->old_color[COLORSEL_SATURATION], + &priv->old_color[COLORSEL_VALUE]); + color_sample_draw_samples (colorsel); + priv->default_set = TRUE; + priv->changing = FALSE; +} + +/** + * gtk_color_selection_set_previous_alpha: + * @colorsel: a #GtkColorSelection. + * @alpha: an integer between 0 and 65535. + * + * Sets the 'previous' alpha to be @alpha. This function should be called with + * some hesitations, as it might seem confusing to have that alpha change. + **/ +void +gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel, + guint16 alpha) +{ + ColorSelectionPrivate *priv; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + + priv = colorsel->private_data; + priv->changing = TRUE; + priv->old_color[COLORSEL_OPACITY] = SCALE (alpha); + color_sample_draw_samples (colorsel); + priv->default_alpha_set = TRUE; + priv->changing = FALSE; +} + + +/** + * gtk_color_selection_get_previous_color: + * @colorsel: a #GtkColorSelection. + * @color: a #GdkColor to fill in with the original color value. + * + * Fills @color in with the original color value. + **/ +void +gtk_color_selection_get_previous_color (GtkColorSelection *colorsel, + GdkColor *color) +{ + ColorSelectionPrivate *priv; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + g_return_if_fail (color != NULL); + + priv = colorsel->private_data; + color->red = UNSCALE (priv->old_color[COLORSEL_RED]); + color->green = UNSCALE (priv->old_color[COLORSEL_GREEN]); + color->blue = UNSCALE (priv->old_color[COLORSEL_BLUE]); +} + +/** + * gtk_color_selection_get_previous_alpha: + * @colorsel: a #GtkColorSelection. + * + * Returns the previous alpha value. + * + * Return value: an integer between 0 and 65535. + **/ +guint16 +gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel) +{ + ColorSelectionPrivate *priv; + + g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), 0); + + priv = colorsel->private_data; + return priv->has_opacity ? UNSCALE (priv->old_color[COLORSEL_OPACITY]) : 65535; +} + +/** + * gtk_color_selection_set_palette_color: + * @colorsel: a #GtkColorSelection. + * @index: the color index of the palette. + * @color: A #GdkColor to set the palette with. + * + * Sets the palette located at @index to have @color as its color. + * + **/ +static void +gtk_color_selection_set_palette_color (GtkColorSelection *colorsel, + gint index, + GdkColor *color) +{ + ColorSelectionPrivate *priv; + gint x, y; + gdouble col[3]; + + g_return_if_fail (GTK_IS_COLOR_SELECTION (colorsel)); + g_return_if_fail (index >= 0 && index < GTK_CUSTOM_PALETTE_WIDTH*GTK_CUSTOM_PALETTE_HEIGHT); + + x = index % GTK_CUSTOM_PALETTE_WIDTH; + y = index / GTK_CUSTOM_PALETTE_WIDTH; + + priv = colorsel->private_data; + col[0] = SCALE (color->red); + col[1] = SCALE (color->green); + col[2] = SCALE (color->blue); + + palette_set_color (priv->custom_palette[x][y], colorsel, col); +} + +/** + * gtk_color_selection_is_adjusting: + * @colorsel: a #GtkColorSelection. + * + * Gets the current state of the @colorsel. + * + * Return value: %TRUE if the user is currently dragging a color around, and %FALSE + * if the selection has stopped. + **/ +gboolean +gtk_color_selection_is_adjusting (GtkColorSelection *colorsel) +{ + ColorSelectionPrivate *priv; + + g_return_val_if_fail (GTK_IS_COLOR_SELECTION (colorsel), FALSE); + + priv = colorsel->private_data; + + return (gtk_hsv_is_adjusting (GTK_HSV (priv->triangle_colorsel))); +} + +static void +gtk_color_selection_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object); + + switch (prop_id) + { + case PROP_HAS_OPACITY_CONTROL: + gtk_color_selection_set_has_opacity_control (colorsel, + g_value_get_boolean (value)); + break; + case PROP_HAS_PALETTE: + gtk_color_selection_set_has_palette (colorsel, + g_value_get_boolean (value)); + break; + case PROP_CURRENT_COLOR: + gtk_color_selection_set_current_color (colorsel, g_value_get_boxed (value)); + break; + case PROP_CURRENT_ALPHA: + gtk_color_selection_set_current_alpha (colorsel, g_value_get_uint (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + +} + +static void +gtk_color_selection_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GtkColorSelection *colorsel = GTK_COLOR_SELECTION (object); + GdkColor color; + + switch (prop_id) + { + case PROP_HAS_OPACITY_CONTROL: + g_value_set_boolean (value, gtk_color_selection_get_has_opacity_control (colorsel)); + break; + case PROP_HAS_PALETTE: + g_value_set_boolean (value, gtk_color_selection_get_has_palette (colorsel)); + break; + case PROP_CURRENT_COLOR: + gtk_color_selection_get_current_color (colorsel, &color); + g_value_set_boxed (value, &color); + break; + case PROP_CURRENT_ALPHA: + g_value_set_uint (value, gtk_color_selection_get_current_alpha (colorsel)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/** + * gtk_color_selection_palette_from_string: + * @str: a string encoding a color palette. + * @colors: return location for allocated array of #GdkColor. + * @n_colors: return location for length of array. + * + * Parses a color palette string; the string is a colon-separated + * list of color names readable by gdk_color_parse(). + * + * Return value: %TRUE if a palette was successfully parsed. + **/ +gboolean +gtk_color_selection_palette_from_string (const gchar *str, + GdkColor **colors, + gint *n_colors) +{ + GdkColor *retval; + gint count; + gchar *p; + gchar *start; + gchar *copy; + + count = 0; + retval = NULL; + copy = g_strdup (str); + + start = copy; + p = copy; + while (TRUE) + { + if (*p == ':' || *p == '\0') + { + gboolean done = TRUE; + + if (start == p) + { + goto failed; /* empty entry */ + } + + if (*p) + { + *p = '\0'; + done = FALSE; + } + + retval = g_renew (GdkColor, retval, count + 1); + if (!gdk_color_parse (start, retval + count)) + { + goto failed; + } + + ++count; + + if (done) + break; + else + start = p + 1; + } + + ++p; + } + + g_free (copy); + + if (colors) + *colors = retval; + else + g_free (retval); + + if (n_colors) + *n_colors = count; + + return TRUE; + + failed: + g_free (copy); + g_free (retval); + + if (colors) + *colors = NULL; + if (n_colors) + *n_colors = 0; + + return FALSE; +} + +/** + * gtk_color_selection_palette_to_string: + * @colors: an array of colors. + * @n_colors: length of the array. + * + * Encodes a palette as a string, useful for persistent storage. + * + * Return value: allocated string encoding the palette. + **/ +gchar* +gtk_color_selection_palette_to_string (const GdkColor *colors, + gint n_colors) +{ + gint i; + gchar **strs = NULL; + gchar *retval; + + if (n_colors == 0) + return g_strdup (""); + + strs = g_new0 (gchar*, n_colors + 1); + + i = 0; + while (i < n_colors) + { + gchar *ptr; + + strs[i] = + g_strdup_printf ("#%2X%2X%2X", + colors[i].red / 256, + colors[i].green / 256, + colors[i].blue / 256); + + for (ptr = strs[i]; *ptr; ptr++) + if (*ptr == ' ') + *ptr = '0'; + + ++i; + } + + retval = g_strjoinv (":", strs); + + g_strfreev (strs); + + return retval; +} + +/** + * gtk_color_selection_set_change_palette_hook: + * @func: a function to call when the custom palette needs saving. + * + * Installs a global function to be called whenever the user tries to + * modify the palette in a color selection. This function should save + * the new palette contents, and update the GtkSettings property + * "gtk-color-palette" so all GtkColorSelection widgets will be modified. + * + * Return value: the previous change palette hook (that was replaced). + * + * Deprecated: This function is deprecated in favor of + * gtk_color_selection_set_change_palette_with_screen_hook(), and does + * not work in multihead environments. + * + **/ +GtkColorSelectionChangePaletteFunc +gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func) +{ + GtkColorSelectionChangePaletteFunc old; + + old = noscreen_change_palette_hook; + + noscreen_change_palette_hook = func; + + return old; +} + +/** + * gtk_color_selection_set_change_palette_with_screen_hook: + * @func: a function to call when the custom palette needs saving. + * + * Installs a global function to be called whenever the user tries to + * modify the palette in a color selection. This function should save + * the new palette contents, and update the GtkSettings property + * "gtk-color-palette" so all GtkColorSelection widgets will be modified. + * + * Return value: the previous change palette hook (that was replaced). + * + * Since: 2.2 + **/ +GtkColorSelectionChangePaletteWithScreenFunc +gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func) +{ + GtkColorSelectionChangePaletteWithScreenFunc old; + + old = change_palette_hook; + + change_palette_hook = func; + + return old; +} + +static void +make_control_relations (AtkObject *atk_obj, + GtkWidget *widget) +{ + AtkObject *obj; + + obj = gtk_widget_get_accessible (widget); + atk_object_add_relationship (atk_obj, ATK_RELATION_CONTROLLED_BY, obj); + atk_object_add_relationship (obj, ATK_RELATION_CONTROLLER_FOR, atk_obj); +} + +static void +make_all_relations (AtkObject *atk_obj, + ColorSelectionPrivate *priv) +{ + make_control_relations (atk_obj, priv->hue_spinbutton); + make_control_relations (atk_obj, priv->sat_spinbutton); + make_control_relations (atk_obj, priv->val_spinbutton); + make_control_relations (atk_obj, priv->red_spinbutton); + make_control_relations (atk_obj, priv->green_spinbutton); + make_control_relations (atk_obj, priv->blue_spinbutton); +} diff --git a/branches/V-1.5.3/veejay-client/src/gtkcolorsel.h b/branches/V-1.5.3/veejay-client/src/gtkcolorsel.h new file mode 100644 index 00000000..bb46c826 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtkcolorsel.h @@ -0,0 +1,141 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 2000 Red Hat, Inc. + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ +#ifndef __GTK_COLOR_SELECTION_H__ +#define __GTK_COLOR_SELECTION_H__ + +// bad hack ... this parts are taken from different Header-Files of the gtk-sources +// that are normally needed for compiling the colorselection dialog +#define P_(String) (String) +#define _ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GTK_TYPE_COLOR_SELECTION (gtk_color_selection_get_type ()) +#define GTK_COLOR_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_COLOR_SELECTION, GtkColorSelection)) +#define GTK_COLOR_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_COLOR_SELECTION, GtkColorSelectionClass)) +#define GTK_IS_COLOR_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_COLOR_SELECTION)) +#define GTK_IS_COLOR_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_COLOR_SELECTION)) +#define GTK_COLOR_SELECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_COLOR_SELECTION, GtkColorSelectionClass)) + + +typedef struct _GtkColorSelection GtkColorSelection; +typedef struct _GtkColorSelectionClass GtkColorSelectionClass; + + +typedef void (* GtkColorSelectionChangePaletteFunc) (const GdkColor *colors, + gint n_colors); +typedef void (* GtkColorSelectionChangePaletteWithScreenFunc) (GdkScreen *screen, + const GdkColor *colors, + gint n_colors); + +struct _GtkColorSelection +{ + GtkVBox parent_instance; + + /* < private_data > */ + gpointer private_data; +}; + +struct _GtkColorSelectionClass +{ + GtkVBoxClass parent_class; + + void (*color_changed) (GtkColorSelection *color_selection); + + /* Padding for future expansion */ + void (*_gtk_reserved1) (void); + void (*_gtk_reserved2) (void); + void (*_gtk_reserved3) (void); + void (*_gtk_reserved4) (void); +}; + + +/* ColorSelection */ + +GType gtk_color_selection_get_type (void) G_GNUC_CONST; +GtkWidget *gtk_color_selection_new (void); +gboolean gtk_color_selection_get_has_opacity_control (GtkColorSelection *colorsel); +void gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel, + gboolean has_opacity); +gboolean gtk_color_selection_get_has_palette (GtkColorSelection *colorsel); +void gtk_color_selection_set_has_palette (GtkColorSelection *colorsel, + gboolean has_palette); + + +void gtk_color_selection_set_current_color (GtkColorSelection *colorsel, + const GdkColor *color); +void gtk_color_selection_set_current_alpha (GtkColorSelection *colorsel, + guint16 alpha); +void gtk_color_selection_get_current_color (GtkColorSelection *colorsel, + GdkColor *color); +guint16 gtk_color_selection_get_current_alpha (GtkColorSelection *colorsel); +void gtk_color_selection_set_previous_color (GtkColorSelection *colorsel, + const GdkColor *color); +void gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel, + guint16 alpha); +void gtk_color_selection_get_previous_color (GtkColorSelection *colorsel, + GdkColor *color); +guint16 gtk_color_selection_get_previous_alpha (GtkColorSelection *colorsel); + +gboolean gtk_color_selection_is_adjusting (GtkColorSelection *colorsel); + +gboolean gtk_color_selection_palette_from_string (const gchar *str, + GdkColor **colors, + gint *n_colors); +gchar* gtk_color_selection_palette_to_string (const GdkColor *colors, + gint n_colors); + +#ifndef GTK_DISABLE_DEPRECATED +#ifndef GDK_MULTIHEAD_SAFE +GtkColorSelectionChangePaletteFunc gtk_color_selection_set_change_palette_hook (GtkColorSelectionChangePaletteFunc func); +#endif +#endif + +GtkColorSelectionChangePaletteWithScreenFunc gtk_color_selection_set_change_palette_with_screen_hook (GtkColorSelectionChangePaletteWithScreenFunc func); + +#ifndef GTK_DISABLE_DEPRECATED +/* Deprecated calls: */ +void gtk_color_selection_set_color (GtkColorSelection *colorsel, + gdouble *color); +void gtk_color_selection_get_color (GtkColorSelection *colorsel, + gdouble *color); +void gtk_color_selection_set_update_policy (GtkColorSelection *colorsel, + GtkUpdateType policy); +#endif /* GTK_DISABLE_DEPRECATED */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_COLOR_SELECTION_H__ */ diff --git a/branches/V-1.5.3/veejay-client/src/gtkhsv.c b/branches/V-1.5.3/veejay-client/src/gtkhsv.c new file mode 100644 index 00000000..cb73ecd8 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtkhsv.c @@ -0,0 +1,1779 @@ +/* HSV color selector for GTK+ + * + * Copyright (C) 1999 The Free Software Foundation + * + * Authors: Simon Budig (original code) + * Federico Mena-Quintero (cleanup for GTK+) + * Jonathan Blandford (cleanup for GTK+) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "gtkalias.h" +#include "gtkhsv.h" +#include "gdk/gdkkeysyms.h" +#include "gtkbindings.h" +#include "gtkcontainer.h" +#include "gtkmarshalers.h" + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* Default width/height */ +#define DEFAULT_SIZE 100 + +/* Default ring width */ +#define DEFAULT_RING_WIDTH 10 + + +/* Dragging modes */ +typedef enum { + DRAG_NONE, + DRAG_H, + DRAG_SV +} DragMode; + +/* Private part of the GtkHSV structure */ +typedef struct { + /* Color value */ + double h; + double s; + double v; + + /* Size and ring width */ + int size; + int ring_width; + + /* Window for capturing events */ + GdkWindow *window; + + /* GC for drawing */ + GdkGC *gc; + + /* Dragging mode */ + DragMode mode; + + guint focus_on_ring : 1; + +} HSVPrivate; + + + +/* Signal IDs */ + +enum { + CHANGED, + MOVE, + LAST_SIGNAL +}; + +static void gtk_hsv_class_init (GtkHSVClass *class); +static void gtk_hsv_init (GtkHSV *hsv); +static void gtk_hsv_destroy (GtkObject *object); +static void gtk_hsv_map (GtkWidget *widget); +static void gtk_hsv_unmap (GtkWidget *widget); +static void gtk_hsv_realize (GtkWidget *widget); +static void gtk_hsv_unrealize (GtkWidget *widget); +static void gtk_hsv_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_hsv_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static gint gtk_hsv_button_press (GtkWidget *widget, + GdkEventButton *event); +static gint gtk_hsv_button_release (GtkWidget *widget, + GdkEventButton *event); +static gint gtk_hsv_motion (GtkWidget *widget, + GdkEventMotion *event); +static gint gtk_hsv_expose (GtkWidget *widget, + GdkEventExpose *event); +static gboolean gtk_hsv_focus (GtkWidget *widget, + GtkDirectionType direction); +static void gtk_hsv_move (GtkHSV *hsv, + GtkDirectionType dir); + +static guint hsv_signals[LAST_SIGNAL]; +static GtkWidgetClass *parent_class; + + +/** + * gtk_hsv_get_type: + * @void: + * + * Registers the &GtkHSV class if necessary, and returns the type ID associated + * to it. + * + * Return value: The type ID of the &GtkHSV class. + **/ +GType +gtk_hsv_get_type (void) +{ + static GType hsv_type = 0; + + if (!hsv_type) { + static const GTypeInfo hsv_info = { + sizeof (GtkHSVClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gtk_hsv_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GtkHSV), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_hsv_init, + }; + + hsv_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkHSV", + &hsv_info, 0); + } + + return hsv_type; +} + +/* Class initialization function for the HSV color selector */ +static void +gtk_hsv_class_init (GtkHSVClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkHSVClass *hsv_class; + GtkBindingSet *binding_set; + + object_class = (GtkObjectClass *) class; + widget_class = (GtkWidgetClass *) class; + hsv_class = GTK_HSV_CLASS (class); + + parent_class = g_type_class_peek_parent (class); + + object_class->destroy = gtk_hsv_destroy; + + widget_class->map = gtk_hsv_map; + widget_class->unmap = gtk_hsv_unmap; + widget_class->realize = gtk_hsv_realize; + widget_class->unrealize = gtk_hsv_unrealize; + widget_class->size_request = gtk_hsv_size_request; + widget_class->size_allocate = gtk_hsv_size_allocate; + widget_class->button_press_event = gtk_hsv_button_press; + widget_class->button_release_event = gtk_hsv_button_release; + widget_class->motion_notify_event = gtk_hsv_motion; + widget_class->expose_event = gtk_hsv_expose; + widget_class->focus = gtk_hsv_focus; + + hsv_class->move = gtk_hsv_move; + + hsv_signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GtkHSVClass, changed), + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + hsv_signals[MOVE] = + g_signal_new ("move", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkHSVClass, move), + NULL, NULL, + _gtk_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_DIRECTION_TYPE); + + binding_set = gtk_binding_set_by_class (class); + + gtk_binding_entry_add_signal (binding_set, GDK_Up, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_UP); + gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_UP); + + gtk_binding_entry_add_signal (binding_set, GDK_Down, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_DOWN); + gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_DOWN); + + + gtk_binding_entry_add_signal (binding_set, GDK_Right, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_RIGHT); + gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_RIGHT); + + gtk_binding_entry_add_signal (binding_set, GDK_Left, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_LEFT); + gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0, + "move", 1, + G_TYPE_ENUM, GTK_DIR_LEFT); +} + +/* Object initialization function for the HSV color selector */ +static void +gtk_hsv_init (GtkHSV *hsv) +{ + HSVPrivate *priv; + + priv = g_new0 (HSVPrivate, 1); + hsv->priv = priv; + + GTK_WIDGET_SET_FLAGS (hsv, GTK_NO_WINDOW); + GTK_WIDGET_SET_FLAGS (hsv, GTK_CAN_FOCUS); + + priv->h = 0.0; + priv->s = 0.0; + priv->v = 0.0; + + priv->size = DEFAULT_SIZE; + priv->ring_width = DEFAULT_RING_WIDTH; +} + +/* Destroy handler for the HSV color selector */ +static void +gtk_hsv_destroy (GtkObject *object) +{ + GtkHSV *hsv; + + g_return_if_fail (GTK_IS_HSV (object)); + + hsv = GTK_HSV (object); + + if (hsv->priv) + { + g_free (hsv->priv); + hsv->priv = NULL; + } + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +/* Default signal handlers */ + + +/* Map handler for the HSV color selector */ + +static void +gtk_hsv_map (GtkWidget *widget) +{ + GtkHSV *hsv; + HSVPrivate *priv; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + GTK_WIDGET_CLASS (parent_class)->map (widget); + + gdk_window_show (priv->window); +} + +/* Unmap handler for the HSV color selector */ + +static void +gtk_hsv_unmap (GtkWidget *widget) +{ + GtkHSV *hsv; + HSVPrivate *priv; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + gdk_window_hide (priv->window); + + GTK_WIDGET_CLASS (parent_class)->unmap (widget); +} + +/* Realize handler for the HSV color selector */ +static void +gtk_hsv_realize (GtkWidget *widget) +{ + GtkHSV *hsv; + HSVPrivate *priv; + GdkWindowAttr attr; + int attr_mask; + GdkWindow *parent_window; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + /* Create window */ + + attr.window_type = GDK_WINDOW_CHILD; + attr.x = widget->allocation.x; + attr.y = widget->allocation.y; + attr.width = widget->allocation.width; + attr.height = widget->allocation.height; + attr.wclass = GDK_INPUT_ONLY; + attr.event_mask = gtk_widget_get_events (widget); + attr.event_mask |= (GDK_KEY_PRESS_MASK + | GDK_BUTTON_PRESS_MASK + | GDK_BUTTON_RELEASE_MASK + | GDK_POINTER_MOTION_MASK + | GDK_ENTER_NOTIFY_MASK + | GDK_LEAVE_NOTIFY_MASK); + + attr_mask = GDK_WA_X | GDK_WA_Y; + + parent_window = gtk_widget_get_parent_window (widget); + + widget->window = parent_window; + g_object_ref (widget->window); + + priv->window = gdk_window_new (parent_window, &attr, attr_mask); + gdk_window_set_user_data (priv->window, hsv); + + widget->style = gtk_style_attach (widget->style, widget->window); + + /* Create GC */ + + priv->gc = gdk_gc_new (parent_window); +} + +/* Unrealize handler for the HSV color selector */ +static void +gtk_hsv_unrealize (GtkWidget *widget) +{ + GtkHSV *hsv; + HSVPrivate *priv; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + gdk_window_set_user_data (priv->window, NULL); + gdk_window_destroy (priv->window); + priv->window = NULL; + + g_object_unref (priv->gc); + priv->gc = NULL; + + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + GTK_WIDGET_CLASS (parent_class)->unrealize (widget); +} + +/* Size_request handler for the HSV color selector */ +static void +gtk_hsv_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkHSV *hsv = GTK_HSV (widget); + HSVPrivate *priv = hsv->priv; + gint focus_width; + gint focus_pad; + + gtk_widget_style_get (widget, + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, + NULL); + + requisition->width = priv->size + 2 * (focus_width + focus_pad); + requisition->height = priv->size + 2 * (focus_width + focus_pad); +} + +/* Size_allocate handler for the HSV color selector */ +static void +gtk_hsv_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkHSV *hsv; + HSVPrivate *priv; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED (widget)) + gdk_window_move_resize (priv->window, + allocation->x, + allocation->y, + allocation->width, + allocation->height); +} + + +/* Utility functions */ + +#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) + +/* Converts from HSV to RGB */ +static void +hsv_to_rgb (gdouble *h, + gdouble *s, + gdouble *v) +{ + gdouble hue, saturation, value; + gdouble f, p, q, t; + + if (*s == 0.0) + { + *h = *v; + *s = *v; + *v = *v; /* heh */ + } + else + { + hue = *h * 6.0; + saturation = *s; + value = *v; + + if (hue == 6.0) + hue = 0.0; + + f = hue - (int) hue; + p = value * (1.0 - saturation); + q = value * (1.0 - saturation * f); + t = value * (1.0 - saturation * (1.0 - f)); + + switch ((int) hue) + { + case 0: + *h = value; + *s = t; + *v = p; + break; + + case 1: + *h = q; + *s = value; + *v = p; + break; + + case 2: + *h = p; + *s = value; + *v = t; + break; + + case 3: + *h = p; + *s = q; + *v = value; + break; + + case 4: + *h = t; + *s = p; + *v = value; + break; + + case 5: + *h = value; + *s = p; + *v = q; + break; + + default: + g_assert_not_reached (); + } + } +} + +/* Converts from RGB to HSV */ +static void +rgb_to_hsv (gdouble *r, + gdouble *g, + gdouble *b) +{ + gdouble red, green, blue; + gdouble h, s, v; + gdouble min, max; + gdouble delta; + + red = *r; + green = *g; + blue = *b; + + h = 0.0; + + if (red > green) + { + if (red > blue) + max = red; + else + max = blue; + + if (green < blue) + min = green; + else + min = blue; + } + else + { + if (green > blue) + max = green; + else + max = blue; + + if (red < blue) + min = red; + else + min = blue; + } + + v = max; + + if (max != 0.0) + s = (max - min) / max; + else + s = 0.0; + + if (s == 0.0) + h = 0.0; + else + { + delta = max - min; + + if (red == max) + h = (green - blue) / delta; + else if (green == max) + h = 2 + (blue - red) / delta; + else if (blue == max) + h = 4 + (red - green) / delta; + + h /= 6.0; + + if (h < 0.0) + h += 1.0; + else if (h > 1.0) + h -= 1.0; + } + + *r = h; + *g = s; + *b = v; +} + +/* Computes the vertices of the saturation/value triangle */ +static void +compute_triangle (GtkHSV *hsv, + gint *hx, + gint *hy, + gint *sx, + gint *sy, + gint *vx, + gint *vy) +{ + HSVPrivate *priv; + gdouble center; + gdouble inner, outer; + gdouble angle; + + priv = hsv->priv; + + center = GTK_WIDGET (hsv)->requisition.width / 2.0; + outer = priv->size / 2.0; + inner = outer - priv->ring_width; + angle = priv->h * 2.0 * G_PI; + + *hx = floor (center + cos (angle) * inner + 0.5); + *hy = floor (center - sin (angle) * inner + 0.5); + *sx = floor (center + cos (angle + 2.0 * G_PI / 3.0) * inner + 0.5); + *sy = floor (center - sin (angle + 2.0 * G_PI / 3.0) * inner + 0.5); + *vx = floor (center + cos (angle + 4.0 * G_PI / 3.0) * inner + 0.5); + *vy = floor (center - sin (angle + 4.0 * G_PI / 3.0) * inner + 0.5); +} + +/* Computes whether a point is inside the hue ring */ +static gboolean +is_in_ring (GtkHSV *hsv, + gdouble x, + gdouble y) +{ + HSVPrivate *priv; + gdouble dx, dy, dist; + gdouble center, inner, outer; + + priv = hsv->priv; + + center = priv->size / 2.0; + outer = priv->size / 2.0; + inner = outer - priv->ring_width; + + dx = x - center; + dy = center - y; + dist = dx * dx + dy * dy; + + return (dist >= inner * inner && dist <= outer * outer); +} + +/* Computes a saturation/value pair based on the mouse coordinates */ +static void +compute_sv (GtkHSV *hsv, + gdouble x, + gdouble y, + gdouble *s, + gdouble *v) +{ + HSVPrivate *priv; + int ihx, ihy, isx, isy, ivx, ivy; + double hx, hy, sx, sy, vx, vy; + double center; + + priv = hsv->priv; + + compute_triangle (hsv, &ihx, &ihy, &isx, &isy, &ivx, &ivy); + center = GTK_WIDGET (hsv)->requisition.width / 2.0; + hx = ihx - center; + hy = center - ihy; + sx = isx - center; + sy = center - isy; + vx = ivx - center; + vy = center - ivy; + x -= center; + y = center - y; + + if (vx * (x - sx) + vy * (y - sy) < 0.0) + { + *s = 1.0; + *v = (((x - sx) * (hx - sx) + (y - sy) * (hy-sy)) + / ((hx - sx) * (hx - sx) + (hy - sy) * (hy - sy))); + + if (*v < 0.0) + *v = 0.0; + else if (*v > 1.0) + *v = 1.0; + } + else if (hx * (x - sx) + hy * (y - sy) < 0.0) + { + *s = 0.0; + *v = (((x - sx) * (vx - sx) + (y - sy) * (vy - sy)) + / ((vx - sx) * (vx - sx) + (vy - sy) * (vy - sy))); + + if (*v < 0.0) + *v = 0.0; + else if (*v > 1.0) + *v = 1.0; + } + else if (sx * (x - hx) + sy * (y - hy) < 0.0) + { + *v = 1.0; + *s = (((x - vx) * (hx - vx) + (y - vy) * (hy - vy)) / + ((hx - vx) * (hx - vx) + (hy - vy) * (hy - vy))); + + if (*s < 0.0) + *s = 0.0; + else if (*s > 1.0) + *s = 1.0; + } + else + { + *v = (((x - sx) * (hy - vy) - (y - sy) * (hx - vx)) + / ((vx - sx) * (hy - vy) - (vy - sy) * (hx - vx))); + + if (*v<= 0.0) + { + *v = 0.0; + *s = 0.0; + } + else + { + if (*v > 1.0) + *v = 1.0; + + if (fabs (hy - vy) < fabs (hx - vx)) + *s = (x - sx - *v * (vx - sx)) / (*v * (hx - vx)); + else + *s = (y - sy - *v * (vy - sy)) / (*v * (hy - vy)); + + if (*s < 0.0) + *s = 0.0; + else if (*s > 1.0) + *s = 1.0; + } + } +} + +/* Computes whether a point is inside the saturation/value triangle */ +static gboolean +is_in_triangle (GtkHSV *hsv, + gdouble x, + gdouble y) +{ + int hx, hy, sx, sy, vx, vy; + double det, s, v; + + compute_triangle (hsv, &hx, &hy, &sx, &sy, &vx, &vy); + + det = (vx - sx) * (hy - sy) - (vy - sy) * (hx - sx); + + s = ((x - sx) * (hy - sy) - (y - sy) * (hx - sx)) / det; + v = ((vx - sx) * (y - sy) - (vy - sy) * (x - sx)) / det; + + return (s >= 0.0 && v >= 0.0 && s + v <= 1.0); +} + +/* Computes a value based on the mouse coordinates */ +static double +compute_v (GtkHSV *hsv, + gdouble x, + gdouble y) +{ + HSVPrivate *priv; + double center; + double dx, dy; + double angle; + + priv = hsv->priv; + + center = GTK_WIDGET (hsv)->requisition.width / 2.0; + dx = x - center; + dy = center - y; + + angle = atan2 (dy, dx); + if (angle < 0.0) + angle += 2.0 * G_PI; + + return angle / (2.0 * G_PI); +} + +/* Event handlers */ + +static void +set_cross_grab (GtkHSV *hsv, + guint32 time) +{ + HSVPrivate *priv; + GdkCursor *cursor; + + priv = hsv->priv; + + cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (hsv)), + GDK_CROSSHAIR); + gdk_pointer_grab (priv->window, FALSE, + (GDK_POINTER_MOTION_MASK + | GDK_POINTER_MOTION_HINT_MASK + | GDK_BUTTON_RELEASE_MASK), + NULL, + cursor, + time); + gdk_cursor_unref (cursor); +} + +/* Button_press_event handler for the HSV color selector */ +static gint +gtk_hsv_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + GtkHSV *hsv; + HSVPrivate *priv; + double x, y; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + if (priv->mode != DRAG_NONE || event->button != 1) + return FALSE; + + x = event->x; + y = event->y; + + if (is_in_ring (hsv, x, y)) + { + priv->mode = DRAG_H; + set_cross_grab (hsv, event->time); + + gtk_hsv_set_color (hsv, + compute_v (hsv, x, y), + priv->s, + priv->v); + + gtk_widget_grab_focus (widget); + priv->focus_on_ring = TRUE; + + return TRUE; + } + + if (is_in_triangle (hsv, x, y)) + { + gdouble s, v; + + priv->mode = DRAG_SV; + set_cross_grab (hsv, event->time); + + compute_sv (hsv, x, y, &s, &v); + gtk_hsv_set_color (hsv, priv->h, s, v); + + gtk_widget_grab_focus (widget); + priv->focus_on_ring = FALSE; + + return TRUE; + } + + return FALSE; +} + +/* Button_release_event handler for the HSV color selector */ +static gint +gtk_hsv_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + GtkHSV *hsv; + HSVPrivate *priv; + DragMode mode; + gdouble x, y; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + if (priv->mode == DRAG_NONE || event->button != 1) + return FALSE; + + /* Set the drag mode to DRAG_NONE so that signal handlers for "catched" + * can see that this is the final color state. + */ + + mode = priv->mode; + priv->mode = DRAG_NONE; + + x = event->x; + y = event->y; + + if (mode == DRAG_H) + gtk_hsv_set_color (hsv, compute_v (hsv, x, y), priv->s, priv->v); + else if (mode == DRAG_SV) { + double s, v; + + compute_sv (hsv, x, y, &s, &v); + gtk_hsv_set_color (hsv, priv->h, s, v); + } else + g_assert_not_reached (); + + gdk_display_pointer_ungrab (gdk_drawable_get_display (event->window), + event->time); + return TRUE; +} + +/* Motion_notify_event handler for the HSV color selector */ +static gint +gtk_hsv_motion (GtkWidget *widget, + GdkEventMotion *event) +{ + GtkHSV *hsv; + HSVPrivate *priv; + double x, y; + gint ix, iy; + GdkModifierType mods; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + if (priv->mode == DRAG_NONE) + return FALSE; + + if (event->is_hint) + { + gdk_window_get_pointer (priv->window, &ix, &iy, &mods); + x = ix; + y = iy; + } + else + { + x = event->x; + y = event->y; + } + + if (priv->mode == DRAG_H) + { + gtk_hsv_set_color (hsv, compute_v (hsv, x, y), priv->s, priv->v); + return TRUE; + } + else if (priv->mode == DRAG_SV) + { + double s, v; + + compute_sv (hsv, x, y, &s, &v); + gtk_hsv_set_color (hsv, priv->h, s, v); + return TRUE; + } + + g_assert_not_reached (); + return FALSE; +} + + +/* Redrawing */ + +/* Paints the hue ring */ +static void +paint_ring (GtkHSV *hsv, + GdkDrawable *drawable, + gint x, + gint y, + gint width, + gint height) +{ + GtkWidget *widget = GTK_WIDGET (hsv); + HSVPrivate *priv; + int xx, yy; + gdouble dx, dy, dist; + gdouble center; + gdouble inner, outer; + guchar *buf, *p; + gdouble angle; + gdouble hue; + gdouble r, g, b; + GdkBitmap *mask; + GdkGC *gc; + GdkColor color; + gint focus_width; + gint focus_pad; + + gtk_widget_style_get (widget, + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, + NULL); + + priv = hsv->priv; + + center = widget->requisition.width / 2.0; + + outer = priv->size / 2.0; + inner = outer - priv->ring_width; + + /* Paint the ring */ + + buf = g_new (guchar, width * height * 3); + + for (yy = 0; yy < height; yy++) + { + p = buf + yy * width * 3; + + dy = -(yy + y - center); + + for (xx = 0; xx < width; xx++) + { + dx = xx + x - center; + + dist = dx * dx + dy * dy; + if (dist < ((inner-1) * (inner-1)) || dist > ((outer+1) * (outer+1))) + { + *p++ = 0; + *p++ = 0; + *p++ = 0; + continue; + } + + angle = atan2 (dy, dx); + if (angle < 0.0) + angle += 2.0 * G_PI; + + hue = angle / (2.0 * G_PI); + + r = hue; + g = 1.0; + b = 1.0; + hsv_to_rgb (&r, &g, &b); + + *p++ = floor (r * 255 + 0.5); + *p++ = floor (g * 255 + 0.5); + *p++ = floor (b * 255 + 0.5); + } + } + + /* Create clipping mask */ + + mask = gdk_pixmap_new (widget->window, width, height, 1); + + gc = gdk_gc_new (mask); + + color.pixel = 0; + gdk_gc_set_foreground (gc, &color); + gdk_draw_rectangle (mask, gc, TRUE, + 0, 0, width, height); + + + color.pixel = 1; + gdk_gc_set_foreground (gc, &color); + gdk_draw_arc (mask, gc, TRUE, + focus_width + focus_pad - x, + focus_width + focus_pad - y, + priv->size - 1, priv->size - 1, + 0, 360 * 64); + + color.pixel = 0; + gdk_gc_set_foreground (gc, &color); + gdk_draw_arc (mask, gc, TRUE, + focus_width + focus_pad - x + priv->ring_width - 1, + focus_width + focus_pad - y + priv->ring_width - 1, + priv->size - 2 * priv->ring_width + 1, priv->size - 2 * priv->ring_width + 1, + 0, 360 * 64); + + g_object_unref (gc); + + gdk_gc_set_clip_mask (priv->gc, mask); + gdk_gc_set_clip_origin (priv->gc, 0, 0); + + /* Draw ring */ + + gdk_draw_rgb_image_dithalign (drawable, priv->gc, 0, 0, width, height, + GDK_RGB_DITHER_MAX, + buf, + width * 3, + x, y); + + /* Draw value marker */ + + r = priv->h; + g = 1.0; + b = 1.0; + hsv_to_rgb (&r, &g, &b); + + if (INTENSITY (r, g, b) > 0.5) + { + color.red = 0x0000; + color.green = 0x0000; + color.blue = 0x0000; + } + else + { + color.red = 0xffff; + color.green = 0xffff; + color.blue = 0xffff; + } + + gdk_gc_set_rgb_fg_color (priv->gc, &color); + + gdk_draw_line (drawable, priv->gc, + -x + center, -y + center, + -x + center + cos (priv->h * 2.0 * G_PI) * center, + -y + center - sin (priv->h * 2.0 * G_PI) * center); + + gdk_gc_set_clip_mask (priv->gc, NULL); + g_object_unref (mask); + + g_free (buf); + + /* Draw ring outline */ +} + +/* Converts an HSV triplet to an integer RGB triplet */ +static void +get_color (gdouble h, + gdouble s, + gdouble v, + gint *r, + gint *g, + gint *b) +{ + hsv_to_rgb (&h, &s, &v); + + *r = floor (h * 255 + 0.5); + *g = floor (s * 255 + 0.5); + *b = floor (v * 255 + 0.5); +} + +#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) + +#define LERP(a, b, v1, v2, i) (((v2) - (v1) != 0) \ + ? ((a) + ((b) - (a)) * ((i) - (v1)) / ((v2) - (v1))) \ + : (a)) + +/* Paints the HSV triangle */ +static void +paint_triangle (GtkHSV *hsv, + GdkDrawable *drawable, + gint x, + gint y, + gint width, + gint height) +{ + GtkWidget *widget = GTK_WIDGET (hsv); + HSVPrivate *priv; + gint hx, hy, sx, sy, vx, vy; /* HSV vertices */ + gint x1, y1, r1, g1, b1; /* First vertex in scanline order */ + gint x2, y2, r2, g2, b2; /* Second vertex */ + gint x3, y3, r3, g3, b3; /* Third vertex */ + gint t; + guchar *buf, *p; + gint xl, xr, rl, rr, gl, gr, bl, br; /* Scanline data */ + gint xx, yy; + GdkBitmap *mask; + GdkGC *gc; + GdkColor color; + GdkPoint points[3]; + gdouble r, g, b; + gchar *detail; + + priv = hsv->priv; + + /* Compute triangle's vertices */ + + compute_triangle (hsv, &hx, &hy, &sx, &sy, &vx, &vy); + + x1 = hx; + y1 = hy; + get_color (priv->h, 1.0, 1.0, &r1, &g1, &b1); + + x2 = sx; + y2 = sy; + get_color (priv->h, 1.0, 0.0, &r2, &g2, &b2); + + x3 = vx; + y3 = vy; + get_color (priv->h, 0.0, 1.0, &r3, &g3, &b3); + + if (y2 > y3) + { + SWAP (x2, x3, t); + SWAP (y2, y3, t); + SWAP (r2, r3, t); + SWAP (g2, g3, t); + SWAP (b2, b3, t); + } + + if (y1 > y3) + { + SWAP (x1, x3, t); + SWAP (y1, y3, t); + SWAP (r1, r3, t); + SWAP (g1, g3, t); + SWAP (b1, b3, t); + } + + if (y1 > y2) + { + SWAP (x1, x2, t); + SWAP (y1, y2, t); + SWAP (r1, r2, t); + SWAP (g1, g2, t); + SWAP (b1, b2, t); + } + + /* Shade the triangle */ + + buf = g_new (guchar, width * height * 3); + + for (yy = 0; yy < height; yy++) + { + p = buf + yy * width * 3; + + if (yy + y < y1 || yy + y > y3) + for (xx = 0; xx < width; xx++) + { + *p++ = 0; + *p++ = 0; + *p++ = 0; + } + else { + if (yy + y < y2) + { + xl = LERP (x1, x2, y1, y2, yy + y); + + rl = LERP (r1, r2, y1, y2, yy + y); + gl = LERP (g1, g2, y1, y2, yy + y); + bl = LERP (b1, b2, y1, y2, yy + y); + } + else + { + xl = LERP (x2, x3, y2, y3, yy + y); + + rl = LERP (r2, r3, y2, y3, yy + y); + gl = LERP (g2, g3, y2, y3, yy + y); + bl = LERP (b2, b3, y2, y3, yy + y); + } + + xr = LERP (x1, x3, y1, y3, yy + y); + + rr = LERP (r1, r3, y1, y3, yy + y); + gr = LERP (g1, g3, y1, y3, yy + y); + br = LERP (b1, b3, y1, y3, yy + y); + + if (xl > xr) + { + SWAP (xl, xr, t); + SWAP (rl, rr, t); + SWAP (gl, gr, t); + SWAP (bl, br, t); + } + + for (xx = 0; xx < width; xx++) + { + if (xx + x < xl || xx + x > xr) + { + *p++ = 0; + *p++ = 0; + *p++ = 0; + } + else + { + *p++ = LERP (rl, rr, xl, xr, xx + x); + *p++ = LERP (gl, gr, xl, xr, xx + x); + *p++ = LERP (bl, br, xl, xr, xx + x); + } + } + } + } + + /* Create clipping mask */ + + mask = gdk_pixmap_new (widget->window, width, height, 1); + + gc = gdk_gc_new (mask); + + color.pixel = 0; + gdk_gc_set_foreground (gc, &color); + gdk_draw_rectangle (mask, gc, TRUE, + 0, 0, width, height); + + color.pixel = 1; + gdk_gc_set_foreground (gc, &color); + + points[0].x = x1 - x; + points[0].y = y1 - y; + points[1].x = x2 - x; + points[1].y = y2 - y; + points[2].x = x3 - x; + points[2].y = y3 - y; + gdk_draw_polygon (mask, gc, TRUE, points, 3); + + g_object_unref (gc); + + gdk_gc_set_clip_mask (priv->gc, mask); + gdk_gc_set_clip_origin (priv->gc, 0, 0); + + /* Draw triangle */ + + gdk_draw_rgb_image_dithalign (drawable, priv->gc, 0, 0, width, height, + GDK_RGB_DITHER_MAX, + buf, + width * 3, + x, y); + + gdk_gc_set_clip_mask (priv->gc, NULL); + g_object_unref (mask); + + g_free (buf); + + /* Draw value marker */ + + xx = floor (sx + (vx - sx) * priv->v + (hx - vx) * priv->s * priv->v + 0.5) - x; + yy = floor (sy + (vy - sy) * priv->v + (hy - vy) * priv->s * priv->v + 0.5) - y; + + r = priv->h; + g = priv->s; + b = priv->v; + hsv_to_rgb (&r, &g, &b); + + if (INTENSITY (r, g, b) > 0.5) + { + detail = "colorwheel_light"; + color.red = 0x0000; + color.green = 0x0000; + color.blue = 0x0000; + } + else + { + detail = "colorwheel_dark"; + color.red = 0xffff; + color.green = 0xffff; + color.blue = 0xffff; + } + + gdk_gc_set_rgb_fg_color (priv->gc, &color); + +#define OUTER_RADIUS 4 +#define INNER_RADIUS 3 +#define FOCUS_RADIUS 6 + + gdk_draw_arc (drawable, priv->gc, FALSE, + xx - OUTER_RADIUS, yy - OUTER_RADIUS, + OUTER_RADIUS * 2, OUTER_RADIUS * 2, + 0, 360 * 64); + gdk_draw_arc (drawable, priv->gc, FALSE, + xx - INNER_RADIUS, yy - INNER_RADIUS, + INNER_RADIUS * 2, INNER_RADIUS * 2, + 0, 360 * 64); + + /* Draw focus outline */ + + if (GTK_WIDGET_HAS_FOCUS (hsv) && + !priv->focus_on_ring) + { + gint focus_width; + gint focus_pad; + + gtk_widget_style_get (widget, + "focus-line-width", &focus_width, + "focus-padding", &focus_pad, + NULL); + + gtk_paint_focus (widget->style, drawable, + GTK_WIDGET_STATE (widget), + NULL, widget, detail, + xx - FOCUS_RADIUS - focus_width - focus_pad, + yy - FOCUS_RADIUS - focus_width - focus_pad, + 2 * (FOCUS_RADIUS + focus_width + focus_pad), + 2 * (FOCUS_RADIUS + focus_width + focus_pad)); + } + +} + +/* Paints the contents of the HSV color selector */ +static void +paint (GtkHSV *hsv, + GdkDrawable *drawable, + gint x, + gint y, + gint width, + gint height) +{ + paint_ring (hsv, drawable, x, y, width, height); + paint_triangle (hsv, drawable, x, y, width, height); +} + +/* Expose_event handler for the HSV color selector */ +static gint +gtk_hsv_expose (GtkWidget *widget, + GdkEventExpose *event) +{ + GtkHSV *hsv; + HSVPrivate *priv; + GdkRectangle rect, dest; + GdkPixmap *pixmap; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + if (!(GTK_WIDGET_DRAWABLE (widget) && event->window == widget->window)) + return FALSE; + + rect.x = widget->allocation.x; + rect.y = widget->allocation.y; + rect.width = widget->allocation.width; + rect.height = widget->allocation.height; + + if (!gdk_rectangle_intersect (&event->area, &rect, &dest)) + return FALSE; + + pixmap = gdk_pixmap_new (widget->window, dest.width, dest.height, + gtk_widget_get_visual (widget)->depth); + + rect = dest; + rect.x = 0; + rect.y = 0; + + gdk_draw_rectangle (pixmap, + widget->style->bg_gc[GTK_WIDGET_STATE (widget)], + TRUE, + 0, 0, dest.width, dest.height); + paint (hsv, pixmap, + dest.x - widget->allocation.x, dest.y - widget->allocation.y, + dest.width, dest.height); + + gdk_draw_drawable (widget->window, + priv->gc, + pixmap, + 0, 0, + dest.x, + dest.y, + event->area.width, event->area.height); + + if (GTK_WIDGET_HAS_FOCUS (hsv) && priv->focus_on_ring) + gtk_paint_focus (widget->style, widget->window, + GTK_WIDGET_STATE (widget), + &event->area, widget, NULL, + widget->allocation.x, + widget->allocation.y, + widget->allocation.width, + widget->allocation.height); + + g_object_unref (pixmap); + + return FALSE; +} + +static gboolean +gtk_hsv_focus (GtkWidget *widget, + GtkDirectionType dir) +{ + GtkHSV *hsv; + HSVPrivate *priv; + + hsv = GTK_HSV (widget); + priv = hsv->priv; + + if (!GTK_WIDGET_HAS_FOCUS (hsv)) + { + if (dir == GTK_DIR_TAB_BACKWARD) + priv->focus_on_ring = FALSE; + else + priv->focus_on_ring = TRUE; + + gtk_widget_grab_focus (GTK_WIDGET (hsv)); + return TRUE; + } + + switch (dir) + { + case GTK_DIR_UP: + if (priv->focus_on_ring) + return FALSE; + else + priv->focus_on_ring = TRUE; + break; + + case GTK_DIR_DOWN: + if (priv->focus_on_ring) + priv->focus_on_ring = FALSE; + else + return FALSE; + break; + + case GTK_DIR_LEFT: + case GTK_DIR_TAB_BACKWARD: + if (priv->focus_on_ring) + return FALSE; + else + priv->focus_on_ring = TRUE; + break; + + case GTK_DIR_RIGHT: + case GTK_DIR_TAB_FORWARD: + if (priv->focus_on_ring) + priv->focus_on_ring = FALSE; + else + return FALSE; + break; + } + + gtk_widget_queue_draw (GTK_WIDGET (hsv)); + + return TRUE; +} + +/** + * gtk_hsv_new: + * @void: + * + * Creates a new HSV color selector. + * + * Return value: A newly-created HSV color selector. + **/ +GtkWidget* +gtk_hsv_new (void) +{ + return g_object_new (GTK_TYPE_HSV, NULL); +} + +/** + * gtk_hsv_set_color: + * @hsv: An HSV color selector. + * @h: Hue. + * @s: Saturation. + * @v: Value. + * + * Sets the current color in an HSV color selector. Color component values must + * be in the [0.0, 1.0] range. + **/ +void +gtk_hsv_set_color (GtkHSV *hsv, + gdouble h, + gdouble s, + gdouble v) +{ + HSVPrivate *priv; + + g_return_if_fail (hsv != NULL); + g_return_if_fail (GTK_IS_HSV (hsv)); + g_return_if_fail (h >= 0.0 && h <= 1.0); + g_return_if_fail (s >= 0.0 && s <= 1.0); + g_return_if_fail (v >= 0.0 && v <= 1.0); + + priv = hsv->priv; + + priv->h = h; + priv->s = s; + priv->v = v; + + g_signal_emit (hsv, hsv_signals[CHANGED], 0); + + gtk_widget_queue_draw (GTK_WIDGET (hsv)); +} + +/** + * gtk_hsv_get_color: + * @hsv: An HSV color selector. + * @h: Return value for the hue. + * @s: Return value for the saturation. + * @v: Return value for the value. + * + * Queries the current color in an HSV color selector. Returned values will be + * in the [0.0, 1.0] range. + **/ +void +gtk_hsv_get_color (GtkHSV *hsv, double *h, double *s, double *v) +{ + HSVPrivate *priv; + + g_return_if_fail (GTK_IS_HSV (hsv)); + + priv = hsv->priv; + + if (h) + *h = priv->h; + + if (s) + *s = priv->s; + + if (v) + *v = priv->v; +} + +/** + * gtk_hsv_set_metrics: + * @hsv: An HSV color selector. + * @size: Diameter for the hue ring. + * @ring_width: Width of the hue ring. + * + * Sets the size and ring width of an HSV color selector. + **/ +void +gtk_hsv_set_metrics (GtkHSV *hsv, + gint size, + gint ring_width) +{ + HSVPrivate *priv; + int same_size; + + g_return_if_fail (GTK_IS_HSV (hsv)); + g_return_if_fail (size > 0); + g_return_if_fail (ring_width > 0); + g_return_if_fail (2 * ring_width + 1 <= size); + + priv = hsv->priv; + + same_size = (priv->size == size); + + priv->size = size; + priv->ring_width = ring_width; + + if (same_size) + gtk_widget_queue_draw (GTK_WIDGET (hsv)); + else + gtk_widget_queue_resize (GTK_WIDGET (hsv)); +} + +/** + * gtk_hsv_get_metrics: + * @hsv: An HSV color selector. + * @size: Return value for the diameter of the hue ring. + * @ring_width: Return value for the width of the hue ring. + * + * Queries the size and ring width of an HSV color selector. + **/ +void +gtk_hsv_get_metrics (GtkHSV *hsv, + gint *size, + gint *ring_width) +{ + HSVPrivate *priv; + + g_return_if_fail (GTK_IS_HSV (hsv)); + + priv = hsv->priv; + + if (size) + *size = priv->size; + + if (ring_width) + *ring_width = priv->ring_width; +} + +/** + * gtk_hsv_is_adjusting: + * @hsv: + * + * An HSV color selector can be said to be adjusting if multiple rapid changes + * are being made to its value, for example, when the user is adjusting the + * value with the mouse. This function queries whether the HSV color selector + * is being adjusted or not. + * + * Return value: TRUE if clients can ignore changes to the color value, since + * they may be transitory, or FALSE if they should consider the color value + * status to be final. + **/ +gboolean +gtk_hsv_is_adjusting (GtkHSV *hsv) +{ + HSVPrivate *priv; + + g_return_val_if_fail (GTK_IS_HSV (hsv), FALSE); + + priv = hsv->priv; + + return priv->mode != DRAG_NONE; +} + +/** + * gtk_hsv_to_rgb: + * @h: Hue. + * @s: Saturation. + * @v: Value. + * @r: Return value for the red component. + * @g: Return value for the green component. + * @b: Return value for the blue component. + * + * Converts a color from HSV space to RGB. Input values must be in the + * [0.0, 1.0] range; output values will be in the same range. + **/ +void +gtk_hsv_to_rgb (gdouble h, + gdouble s, + gdouble v, + gdouble *r, + gdouble *g, + gdouble *b) +{ + g_return_if_fail (h >= 0.0 && h <= 1.0); + g_return_if_fail (s >= 0.0 && s <= 1.0); + g_return_if_fail (v >= 0.0 && v <= 1.0); + + hsv_to_rgb (&h, &s, &v); + + if (r) + *r = h; + + if (g) + *g = s; + + if (b) + *b = v; +} + +/** + * gtk_hsv_to_rgb: + * @r: Red. + * @g: Green. + * @b: Blue. + * @h: Return value for the hue component. + * @s: Return value for the saturation component. + * @v: Return value for the value component. + * + * Converts a color from RGB space to HSV. Input values must be in the + * [0.0, 1.0] range; output values will be in the same range. + **/ +void +gtk_rgb_to_hsv (gdouble r, + gdouble g, + gdouble b, + gdouble *h, + gdouble *s, + gdouble *v) +{ + g_return_if_fail (r >= 0.0 && r <= 1.0); + g_return_if_fail (g >= 0.0 && g <= 1.0); + g_return_if_fail (b >= 0.0 && b <= 1.0); + + rgb_to_hsv (&r, &g, &b); + + if (h) + *h = r; + + if (s) + *s = g; + + if (v) + *v = b; +} + +static void +gtk_hsv_move (GtkHSV *hsv, + GtkDirectionType dir) +{ + HSVPrivate *priv; + gdouble hue, sat, val; + gint hx, hy, sx, sy, vx, vy; /* HSV vertices */ + gint x, y; /* position in triangle */ + + priv = hsv->priv; + + hue = priv->h; + sat = priv->s; + val = priv->v; + + compute_triangle (hsv, &hx, &hy, &sx, &sy, &vx, &vy); + + x = floor (sx + (vx - sx) * priv->v + (hx - vx) * priv->s * priv->v + 0.5); + y = floor (sy + (vy - sy) * priv->v + (hy - vy) * priv->s * priv->v + 0.5); + +#define HUE_DELTA 0.002 + switch (dir) + { + case GTK_DIR_UP: + if (priv->focus_on_ring) + hue += HUE_DELTA; + else + { + y -= 1; + compute_sv (hsv, x, y, &sat, &val); + } + break; + + case GTK_DIR_DOWN: + if (priv->focus_on_ring) + hue -= HUE_DELTA; + else + { + y += 1; + compute_sv (hsv, x, y, &sat, &val); + } + break; + + case GTK_DIR_LEFT: + if (priv->focus_on_ring) + hue += HUE_DELTA; + else + { + x -= 1; + compute_sv (hsv, x, y, &sat, &val); + } + break; + + case GTK_DIR_RIGHT: + if (priv->focus_on_ring) + hue -= HUE_DELTA + ; + else + { + x += 1; + compute_sv (hsv, x, y, &sat, &val); + } + break; + + default: + /* we don't care about the tab directions */ + break; + } + + /* Wrap */ + if (hue < 0.0) + hue = 1.0; + else if (hue > 1.0) + hue = 0.0; + + gtk_hsv_set_color (hsv, hue, sat, val); +} diff --git a/branches/V-1.5.3/veejay-client/src/gtkhsv.h b/branches/V-1.5.3/veejay-client/src/gtkhsv.h new file mode 100644 index 00000000..c8dac795 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtkhsv.h @@ -0,0 +1,108 @@ +/* HSV color selector for GTK+ + * + * Copyright (C) 1999 The Free Software Foundation + * + * Authors: Simon Budig (original code) + * Federico Mena-Quintero (cleanup for GTK+) + * Jonathan Blandford (cleanup for GTK+) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __GTK_HSV_H__ +#define __GTK_HSV_H__ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define GTK_TYPE_HSV (gtk_hsv_get_type ()) +#define GTK_HSV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_HSV, GtkHSV)) +#define GTK_HSV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_HSV, GtkHSVClass)) +#define GTK_IS_HSV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_HSV)) +#define GTK_IS_HSV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_HSV)) +#define GTK_HSV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_HSV, GtkHSVClass)) + + +typedef struct _GtkHSV GtkHSV; +typedef struct _GtkHSVClass GtkHSVClass; + +struct _GtkHSV +{ + GtkWidget parent_instance; + + /* Private data */ + gpointer priv; +}; + +struct _GtkHSVClass +{ + GtkWidgetClass parent_class; + + /* Notification signals */ + + void (*changed) (GtkHSV *hsv); + + /* Keybindings */ + void (* move) (GtkHSV *hsv, + GtkDirectionType type); +}; + + +GType gtk_hsv_get_type (void) G_GNUC_CONST; +GtkWidget* gtk_hsv_new (void); +void gtk_hsv_set_color (GtkHSV *hsv, + double h, + double s, + double v); +void gtk_hsv_get_color (GtkHSV *hsv, + gdouble *h, + gdouble *s, + gdouble *v); +void gtk_hsv_set_metrics (GtkHSV *hsv, + gint size, + gint ring_width); +void gtk_hsv_get_metrics (GtkHSV *hsv, + gint *size, + gint *ring_width); +gboolean gtk_hsv_is_adjusting (GtkHSV *hsv); +void gtk_hsv_to_rgb (gdouble h, + gdouble s, + gdouble v, + gdouble *r, + gdouble *g, + gdouble *b); +void gtk_rgb_to_hsv (gdouble r, + gdouble g, + gdouble b, + gdouble *h, + gdouble *s, + gdouble *v); + + +#ifdef __cplusplus +} +#endif + +#endif /* __GTK_HSV_H__ */ diff --git a/branches/V-1.5.3/veejay-client/src/gtkknob.c b/branches/V-1.5.3/veejay-client/src/gtkknob.c new file mode 100644 index 00000000..406a6933 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtkknob.c @@ -0,0 +1,569 @@ +/* gAlan - Graphical Audio Language + * Copyright (C) 1999 Tony Garnock-Jones + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include "gtkknob.h" + +#ifndef M_PI +# define M_PI 3.14159265358979323846 /* pi */ +#endif + +#define SCROLL_DELAY_LENGTH 300 +#define KNOB_SIZE 32 + +#define STATE_IDLE 0 +#define STATE_PRESSED 1 +#define STATE_DRAGGING 2 + + +/* Forward declarations */ + +static void gtk_knob_class_init(GtkKnobClass *klass); +static void gtk_knob_init(GtkKnob *knob); +static void gtk_knob_destroy(GtkObject *object); +static void gtk_knob_realize(GtkWidget *widget); +static void gtk_knob_size_request(GtkWidget *widget, GtkRequisition *requisition); +static void gtk_knob_size_allocate(GtkWidget *widget, GtkAllocation *allocation); +static gint gtk_knob_expose(GtkWidget *widget, GdkEventExpose *event); +static gint gtk_knob_button_press(GtkWidget *widget, GdkEventButton *event); +static gint gtk_knob_button_release(GtkWidget *widget, GdkEventButton *event); +static gint gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event); +static gint gtk_knob_timer(GtkKnob *knob); + +static void gtk_knob_update_mouse_update(GtkKnob *knob); +static void gtk_knob_update_mouse(GtkKnob *knob, gint x, gint y); +static void gtk_knob_update_mouse_abs(GtkKnob *knob, gint x, gint y); +static void gtk_knob_update(GtkKnob *knob); +static void gtk_knob_adjustment_changed(GtkAdjustment *adjustment, gpointer data); +static void gtk_knob_adjustment_value_changed(GtkAdjustment *adjustment, gpointer data); + +/* Local data */ + +static GtkWidgetClass *parent_class = NULL; +static GList *animation = NULL; + +static GList *get_anim_list( char *name ) { + + GError *err = NULL; + GdkPixbuf *animation; + GList *retval = NULL; + int x, w; + fprintf(stderr, "Load pixpbuf %s\n", name ); + animation = gdk_pixbuf_new_from_file( name, &err ); + w = gdk_pixbuf_get_width( animation ); + + for(x=0; xpath ); + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + + parent_class = gtk_type_class(gtk_widget_get_type()); + + object_class->destroy = gtk_knob_destroy; + + widget_class->realize = gtk_knob_realize; + widget_class->expose_event = gtk_knob_expose; + widget_class->size_request = gtk_knob_size_request; + widget_class->size_allocate = gtk_knob_size_allocate; + widget_class->button_press_event = gtk_knob_button_press; + widget_class->button_release_event = gtk_knob_button_release; + widget_class->motion_notify_event = gtk_knob_motion_notify; +} + +static void gtk_knob_init (GtkKnob *knob) { + knob->policy = GTK_UPDATE_CONTINUOUS; + knob->state = STATE_IDLE; + knob->saved_x = knob->saved_y = 0; + knob->timer = 0; + knob->pixbuf = NULL; + knob->anim_list = animation; + knob->old_value = 0.0; + knob->old_lower = 0.0; + knob->old_upper = 0.0; + knob->adjustment = NULL; +} + + + + + +GtkWidget *gtk_knob_new(GtkAdjustment *adjustment, const char *path) { + GtkKnob *knob; + + knob = gtk_type_new(gtk_knob_get_type()); + knob->path = g_strdup( path ); + + animation = get_anim_list( knob->path ); + + if (!adjustment) + adjustment = (GtkAdjustment*) gtk_adjustment_new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0); + + gtk_knob_set_adjustment(knob, adjustment); + + return GTK_WIDGET(knob); +} + +static void gtk_knob_destroy(GtkObject *object) { + GtkKnob *knob; + + g_return_if_fail(object != NULL); + g_return_if_fail(GTK_IS_KNOB(object)); + + knob = GTK_KNOB(object); + + if (knob->adjustment) { + gtk_object_unref(GTK_OBJECT(knob->adjustment)); + knob->adjustment = NULL; + } + + if (knob->pixbuf) { + gdk_pixbuf_unref(knob->pixbuf); + knob->pixbuf = NULL; + } + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + (*GTK_OBJECT_CLASS(parent_class)->destroy)(object); +} + +GtkAdjustment* gtk_knob_get_adjustment(GtkKnob *knob) { + g_return_val_if_fail(knob != NULL, NULL); + g_return_val_if_fail(GTK_IS_KNOB(knob), NULL); + + return knob->adjustment; +} + +void gtk_knob_set_update_policy(GtkKnob *knob, GtkUpdateType policy) { + g_return_if_fail (knob != NULL); + g_return_if_fail (GTK_IS_KNOB (knob)); + + knob->policy = policy; +} + +void gtk_knob_set_adjustment(GtkKnob *knob, GtkAdjustment *adjustment) { + g_return_if_fail (knob != NULL); + g_return_if_fail (GTK_IS_KNOB (knob)); + + if (knob->adjustment) { + gtk_signal_disconnect_by_data(GTK_OBJECT(knob->adjustment), (gpointer)knob); + gtk_object_unref(GTK_OBJECT(knob->adjustment)); + } + + knob->adjustment = adjustment; + gtk_object_ref(GTK_OBJECT(knob->adjustment)); + gtk_object_sink(GTK_OBJECT( knob->adjustment ) ); + + gtk_signal_connect(GTK_OBJECT(adjustment), "changed", + GTK_SIGNAL_FUNC(gtk_knob_adjustment_changed), (gpointer) knob); + gtk_signal_connect(GTK_OBJECT(adjustment), "value_changed", + GTK_SIGNAL_FUNC(gtk_knob_adjustment_value_changed), (gpointer) knob); + + knob->old_value = adjustment->value; + knob->old_lower = adjustment->lower; + knob->old_upper = adjustment->upper; + + gtk_knob_update(knob); +} + +static void gtk_knob_realize(GtkWidget *widget) { + GtkKnob *knob; + GdkWindowAttr attributes; + gint attributes_mask; + + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_KNOB(widget)); + + GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED); + knob = GTK_KNOB(widget); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = + gtk_widget_get_events (widget) | + GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK; + attributes.visual = gtk_widget_get_visual(widget); + attributes.colormap = gtk_widget_get_colormap(widget); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + widget->window = gdk_window_new(widget->parent->window, &attributes, attributes_mask); + + widget->style = gtk_style_attach(widget->parent->style, widget->window); + + gdk_window_set_user_data(widget->window, widget); + + + gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL); +} + +static void gtk_knob_size_request (GtkWidget *widget, GtkRequisition *requisition) { + requisition->width = KNOB_SIZE; + requisition->height = KNOB_SIZE; +} + +static void gtk_knob_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { + GtkKnob *knob; + + g_return_if_fail(widget != NULL); + g_return_if_fail(GTK_IS_KNOB(widget)); + g_return_if_fail(allocation != NULL); + + widget->allocation = *allocation; + knob = GTK_KNOB(widget); + + if (GTK_WIDGET_REALIZED(widget)) { + gdk_window_move_resize(widget->window, + allocation->x, allocation->y, + allocation->width, allocation->height); + } +} + +static gint gtk_knob_expose(GtkWidget *widget, GdkEventExpose *event) { + GtkKnob *knob; + gfloat dx, dy; + GList *framelist; + + g_return_val_if_fail(widget != NULL, FALSE); + g_return_val_if_fail(GTK_IS_KNOB(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + if (event->count > 0) + return FALSE; + + knob = GTK_KNOB(widget); + + gdk_window_clear_area(widget->window, 0, 0, widget->allocation.width, widget->allocation.height); + + dx = knob->adjustment->value - knob->adjustment->lower; + dy = knob->adjustment->upper - knob->adjustment->lower; + framelist = knob->anim_list; + + if (dy != 0) { + GdkPixbuf *pixbuf; + + dx = MIN(MAX(dx / dy, 0), 1); + //dx = (1-dx) * (g_list_length( framelist )-0.5) * 0.75 + 0.125 * g_list_length( framelist ); + dx = (dx) * (g_list_length( framelist ) - 1 ); + + pixbuf = g_list_nth_data( framelist, (int) dx); + + gdk_pixbuf_render_to_drawable_alpha( pixbuf, widget->window, + 0, 0, 0, 0, gdk_pixbuf_get_width( pixbuf ), gdk_pixbuf_get_height( pixbuf ), GDK_PIXBUF_ALPHA_FULL, 0, 0,0,0 ); + } + + + + + return FALSE; +} + +static gint gtk_knob_button_press(GtkWidget *widget, GdkEventButton *event) { + GtkKnob *knob; + + g_return_val_if_fail(widget != NULL, FALSE); + g_return_val_if_fail(GTK_IS_KNOB(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + knob = GTK_KNOB(widget); + + switch (knob->state) { + case STATE_IDLE: + switch (event->button) { +#if 0 + case 3: + gtk_knob_update_mouse_abs(knob, event->x, event->y); + /* FALL THROUGH */ +#endif + + case 1: + case 3: + gtk_grab_add(widget); + knob->state = STATE_PRESSED; + knob->saved_x = event->x; + knob->saved_y = event->y; + break; + + default: + break; + } + break; + + default: + break; + } + + return FALSE; +} + +static gint gtk_knob_button_release(GtkWidget *widget, GdkEventButton *event) { + GtkKnob *knob; + + g_return_val_if_fail(widget != NULL, FALSE); + g_return_val_if_fail(GTK_IS_KNOB(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + knob = GTK_KNOB(widget); + + switch (knob->state) { + case STATE_PRESSED: + gtk_grab_remove(widget); + knob->state = STATE_IDLE; + + switch (event->button) { + case 1: + knob->adjustment->value -= knob->adjustment->page_increment; + gtk_signal_emit_by_name(GTK_OBJECT(knob->adjustment), "value_changed"); + break; + + case 3: + knob->adjustment->value += knob->adjustment->page_increment; + gtk_signal_emit_by_name(GTK_OBJECT(knob->adjustment), "value_changed"); + break; + + default: + break; + } + break; + + case STATE_DRAGGING: + gtk_grab_remove(widget); + knob->state = STATE_IDLE; + + if (knob->policy != GTK_UPDATE_CONTINUOUS && knob->old_value != knob->adjustment->value) + gtk_signal_emit_by_name(GTK_OBJECT(knob->adjustment), "value_changed"); + + break; + + default: + break; + } + + return FALSE; +} + +static gint gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event) { + GtkKnob *knob; + GdkModifierType mods; + gint x, y; + + g_return_val_if_fail(widget != NULL, FALSE); + g_return_val_if_fail(GTK_IS_KNOB(widget), FALSE); + g_return_val_if_fail(event != NULL, FALSE); + + knob = GTK_KNOB(widget); + + x = event->x; + y = event->y; + + if (event->is_hint || (event->window != widget->window)) + gdk_window_get_pointer(widget->window, &x, &y, &mods); + + switch (knob->state) { + case STATE_PRESSED: + knob->state = STATE_DRAGGING; + /* fall through */ + + case STATE_DRAGGING: + if (mods & GDK_BUTTON1_MASK) { + gtk_knob_update_mouse(knob, x, y); + return TRUE; + } else if (mods & GDK_BUTTON3_MASK) { + gtk_knob_update_mouse_abs(knob, x, y); + return TRUE; + } + break; + + default: + break; + } + + return FALSE; +} + +static gint gtk_knob_timer(GtkKnob *knob) { + g_return_val_if_fail(knob != NULL, FALSE); + g_return_val_if_fail(GTK_IS_KNOB(knob), FALSE); + + if (knob->policy == GTK_UPDATE_DELAYED) + gtk_signal_emit_by_name(GTK_OBJECT(knob->adjustment), "value_changed"); + + return FALSE; /* don't keep running this timer */ +} + +static void gtk_knob_update_mouse_update(GtkKnob *knob) { + if (knob->policy == GTK_UPDATE_CONTINUOUS) + gtk_signal_emit_by_name(GTK_OBJECT(knob->adjustment), "value_changed"); + else { + gtk_widget_draw(GTK_WIDGET(knob), NULL); + + if (knob->policy == GTK_UPDATE_DELAYED) { + if (knob->timer) + gtk_timeout_remove(knob->timer); + + knob->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH, (GtkFunction) gtk_knob_timer, + (gpointer) knob); + } + } +} + +static void gtk_knob_update_mouse(GtkKnob *knob, gint x, gint y) { + gfloat old_value; + gfloat dv; + + g_return_if_fail(knob != NULL); + g_return_if_fail(GTK_IS_KNOB(knob)); + + old_value = knob->adjustment->value; + + dv = (knob->saved_y - y) * knob->adjustment->step_increment; + knob->saved_x = x; + knob->saved_y = y; + + knob->adjustment->value += dv; + + if (knob->adjustment->value != old_value) + gtk_knob_update_mouse_update(knob); +} + +static void gtk_knob_update_mouse_abs(GtkKnob *knob, gint x, gint y) { + gfloat old_value; + gdouble angle; + + g_return_if_fail(knob != NULL); + g_return_if_fail(GTK_IS_KNOB(knob)); + + old_value = knob->adjustment->value; + + x -= KNOB_SIZE>>1; + y -= KNOB_SIZE>>1; + y = -y; /* inverted cartesian graphics coordinate system */ + + angle = atan2(y, x) / M_PI; + if (angle < -0.5) + angle += 2; + + angle = -(2.0/3.0) * (angle - 1.25); /* map [1.25pi, -0.25pi] onto [0, 1] */ + angle *= knob->adjustment->upper - knob->adjustment->lower; + angle += knob->adjustment->lower; + + knob->adjustment->value = angle; + + if (knob->adjustment->value != old_value) + gtk_knob_update_mouse_update(knob); +} + +static void gtk_knob_update(GtkKnob *knob) { + gfloat new_value; + + g_return_if_fail(knob != NULL); + g_return_if_fail(GTK_IS_KNOB (knob)); + + new_value = knob->adjustment->value; + + if (new_value < knob->adjustment->lower) + new_value = knob->adjustment->lower; + + if (new_value > knob->adjustment->upper) + new_value = knob->adjustment->upper; + + if (new_value != knob->adjustment->value) { + knob->adjustment->value = new_value; + gtk_signal_emit_by_name(GTK_OBJECT(knob->adjustment), "value_changed"); + } + + gtk_widget_draw(GTK_WIDGET(knob), NULL); +} + +static void gtk_knob_adjustment_changed(GtkAdjustment *adjustment, gpointer data) { + GtkKnob *knob; + + g_return_if_fail(adjustment != NULL); + g_return_if_fail(data != NULL); + + knob = GTK_KNOB(data); + + if ((knob->old_value != adjustment->value) || + (knob->old_lower != adjustment->lower) || + (knob->old_upper != adjustment->upper)) { + gtk_knob_update (knob); + + knob->old_value = adjustment->value; + knob->old_lower = adjustment->lower; + knob->old_upper = adjustment->upper; + } +} + +static void gtk_knob_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data) { + GtkKnob *knob; + + g_return_if_fail(adjustment != NULL); + g_return_if_fail(data != NULL); + + knob = GTK_KNOB(data); + + if (knob->old_value != adjustment->value) { + gtk_knob_update (knob); + + knob->old_value = adjustment->value; + } +} diff --git a/branches/V-1.5.3/veejay-client/src/gtkknob.h b/branches/V-1.5.3/veejay-client/src/gtkknob.h new file mode 100644 index 00000000..1c79b198 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtkknob.h @@ -0,0 +1,86 @@ +/* gAlan - Graphical Audio Language + * Copyright (C) 1999 Tony Garnock-Jones + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GTK_KNOB_H__ +#define __GTK_KNOB_H__ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PIXMAPDIRIFY(filename) \ + (SITE_PKGDATA_DIR G_DIR_SEPARATOR_S "pixmaps" G_DIR_SEPARATOR_S filename) + +#define GTK_KNOB(obj) GTK_CHECK_CAST(obj, gtk_knob_get_type(), GtkKnob) +#define GTK_KNOB_CLASS(klass) GTK_CHECK_CLASS_CAST(klass, gtk_knob_get_type(), GtkKnobClass) +#define GTK_IS_KNOB(obj) GTK_CHECK_TYPE(obj, gtk_knob_get_type()) + +typedef struct _GtkKnob GtkKnob; +typedef struct _GtkKnobClass GtkKnobClass; + +struct _GtkKnob { + GtkWidget widget; + + /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */ + guint policy : 2; + + /* State of widget (to do with user interaction) */ + guint8 state; + gint saved_x, saved_y; + + /* ID of update timer, or 0 if none */ + guint32 timer; + + /* Pixmap for knob */ + GdkPixbuf *pixbuf; + /* Animation for knob... from animated gif */ + GList *anim_list; + + /* Old values from adjustment stored so we know when something changes */ + gfloat old_value; + gfloat old_lower; + gfloat old_upper; + + /* The adjustment object that stores the data for this knob */ + GtkAdjustment *adjustment; + char *path; +}; + +struct _GtkKnobClass +{ + GtkWidgetClass parent_class; +}; + +extern GtkWidget *gtk_knob_new(GtkAdjustment *adjustment, const char *path); +extern guint gtk_knob_get_type(void); + +extern GtkAdjustment *gtk_knob_get_adjustment(GtkKnob *knob); +extern void gtk_knob_set_update_policy(GtkKnob *knob, GtkUpdateType policy); + +extern void gtk_knob_set_adjustment(GtkKnob *knob, GtkAdjustment *adjustment); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/branches/V-1.5.3/veejay-client/src/gtktimeselection.c b/branches/V-1.5.3/veejay-client/src/gtktimeselection.c new file mode 100644 index 00000000..0c62275f --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtktimeselection.c @@ -0,0 +1,872 @@ +/* veejay - Linux VeeJay + * (C) 2002-2008 Niels Elburg + * + * + * 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. + */ + +/* + Implements a new slider type widget with selection markers + + */ + +#include +#include +#include +#include + +#include "gtktimeselection.h" + +//G_DEFINE_TYPE(TimelineSelectionClass, timeline, GTK_TYPE_DRAWING_AREA ); + +enum +{ + POS_CHANGED, + IN_CHANGED, + OUT_CHANGED, + BIND_CHANGED, + CLEAR_CHANGED, + SELECTION_CHANGED_SIGNAL, + LAST_SIGNAL +}; + +enum +{ + MIN = 1, + MAX = 2, + POS = 3, + LENGTH = 4, + IN_POINT = 5, + OUT_POINT = 6, + SEL = 7, + BIND = 8, + CLEARED = 9, +}; + +typedef enum { + MOUSE_OUTSIDE, + MOUSE_STEPPER, + MOUSE_SELECTION, + MOUSE_WIDGET /* inside widget but not in any of the above */ +} mouse_location; + + +/* Slider with 2 bars + + + +*/ + +typedef enum TimelineAction +{ + action_none = 0, + action_in_point, + action_out_point, + action_pos, + action_atomic, +} TimelineAction; + +#define POINT_IN_RECT(xcoord, ycoord, rect) \ + ((xcoord) >= (rect).x && \ + (xcoord) < ((rect).x + (rect).width) && \ + (ycoord) >= (rect).y && \ + (ycoord) < ((rect).y + (rect).height)) + +struct _TimelineSelection +{ + GtkDrawingArea cr; + GtkWidget *widget; + gdouble min; + gdouble max; + gdouble value; + gdouble frame_num; + gdouble num_video_frames; + gdouble in; + gdouble out; + gboolean bind; + gint grab_button; + TimelineAction action; + mouse_location grab_location; + mouse_location current_location; + GdkRectangle stepper; + GdkRectangle selection; + gboolean has_stepper; + gboolean clear; + gdouble stepper_size; /* size of triangle */ + gdouble stepper_draw_size; + gdouble stepper_length; /* length from top to bottom */ + gint step_size; /* step frames 1,2,4,8,16, ... */ + gdouble frame_width; + gdouble frame_height; + gdouble font_line; + gboolean has_selection; /* use in/out points for selection */ + gdouble move_x; +}; + +static void get_property( GObject *object, + guint id, GValue *value , GParamSpec *pspec ); + +static void set_property (GObject *object, + guint id, GValue * value, GParamSpec *pspec); + +static gboolean event_press (GtkWidget *widget, GdkEventButton *bev, gpointer user_data); + +static gboolean event_release (GtkWidget *widget, GdkEventButton *bev, gpointer user_data); + +static gboolean event_motion (GtkWidget *widget, GdkEventMotion *mev, gpointer user_data); + +static gboolean event_scroll (GtkWidget *widget, GdkEventScroll *mev, gpointer user_data); + +static void timeline_class_init( TimelineSelectionClass *class ); + +static void timeline_init(TimelineSelection *te ); + +static gboolean timeline_expose(GtkWidget *widget, GdkEventExpose *event ); + +static GObjectClass *parent_class = NULL; +static gint timeline_signals[LAST_SIGNAL] = { 0 }; + +struct _TimelineSelectionClass +{ + GtkWidgetClass parent_class; + void (*pos_changed) (TimelineSelection *te); + void (*in_point_changed) (TimelineSelection *te); + void (*out_point_changed) (TimelineSelection *te); + void (*bind_toggled) (TimelineSelection *te); + void (*cleared) (TimelineSelection *te); +}; +static void set_property (GObject *object, + guint id, GValue *value, GParamSpec *pspec) +{ + TimelineSelection *te = TIMELINE_SELECTION(object); + switch(id) + { + case MIN: + if(te->min != g_value_get_double(value)) + { + te->min = g_value_get_double(value); + } + break; + case MAX: + if(te->max != g_value_get_double(value)) + { + te->min = g_value_get_double(value); + } + break; + case POS: + if(te->frame_num != g_value_get_double(value)) + { + te->frame_num = g_value_get_double(value); + } + break; + case LENGTH: + if(te->num_video_frames != g_value_get_double(value)) + { + te->num_video_frames = g_value_get_double(value); + } + break; + case IN_POINT: + if(te->in != g_value_get_double(value)) + { + if( g_value_get_double(value) < te->out ) + te->in = g_value_get_double(value); + } + break; + case OUT_POINT: + if(te->out != g_value_get_double(value)) + { + if( g_value_get_double(value) > te->in ) + te->out = g_value_get_double(value); + } + break; + case SEL: + if(te->has_selection != g_value_get_boolean(value)) + { + te->has_selection = g_value_get_boolean(value); + } + break; + case BIND: + if(te->bind != g_value_get_boolean(value)) + { + te->bind = g_value_get_boolean(value); + } + break; + case CLEARED: + if(te->clear != g_value_get_boolean(value)) + { + te->clear = g_value_get_boolean(value); + } + break; + default: + g_assert(FALSE); + break; + } + gtk_widget_queue_draw( GTK_WIDGET( te )); + +} + +static void get_property( GObject *object, + guint id, GValue *value , GParamSpec *pspec ) +{ + TimelineSelection *te = TIMELINE_SELECTION(object); + switch( id ) + { + case MIN: g_value_set_double( value, te->min );break; + case MAX: g_value_set_double( value, te->max );break; + case POS: g_value_set_double( value, te->frame_num ); break; + case LENGTH: g_value_set_double( value, te->num_video_frames ); break; + case IN_POINT: g_value_set_double( value, te->in ); break; + case OUT_POINT: g_value_set_double( value, te->out ); break; + case SEL: g_value_set_boolean(value, te->has_selection) ; break; + case BIND: g_value_set_boolean(value, te->bind ); break; + case CLEARED: g_value_set_boolean(value,te->clear );break; + } +} + +static void finalize (GObject *object) +{ + parent_class->finalize( object ); +} + +static void timeline_class_init( TimelineSelectionClass *class ) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(class); + widget_class->expose_event = timeline_expose; + + GObjectClass *gobject_class; + gobject_class = G_OBJECT_CLASS( class ); + parent_class = g_type_class_peek( GTK_TYPE_DRAWING_AREA ); + gobject_class->finalize = finalize; + gobject_class->get_property = get_property; + gobject_class->set_property = set_property; + + g_object_class_install_property( gobject_class, + MIN, + g_param_spec_double( "min", + "left", "left", 0.0, 1.0, 0.0, G_PARAM_READWRITE )); + + g_object_class_install_property( gobject_class, + MAX, + g_param_spec_double( "max", + "right", "right", 0.0, 1.0, 1.0, G_PARAM_READWRITE )); + + g_object_class_install_property( gobject_class, + POS, + g_param_spec_double( "pos", + "current position", "current position", 0.0,9999999.0, 0.0, + G_PARAM_READWRITE )); + + g_object_class_install_property( gobject_class, + LENGTH, + g_param_spec_double( "length", + "Length (in frames)", "Length (in frames) ",0.0,9999999.0, 1.0, + G_PARAM_READWRITE )); + + + g_object_class_install_property( gobject_class, + IN_POINT, + g_param_spec_double( "in", + "In point", "(in frames) ",0.0,1.0, 0.0, + G_PARAM_READWRITE )); + + + g_object_class_install_property( gobject_class, + OUT_POINT, + g_param_spec_double( "out", + "Out point", "(in frames) ",0.0,1.0, 1.0, + G_PARAM_READWRITE )); + + g_object_class_install_property( gobject_class, + SEL, + g_param_spec_boolean( "selection", + "Marker", "(in frames) ",FALSE, + G_PARAM_READWRITE )); + + g_object_class_install_property( gobject_class, + BIND, + g_param_spec_boolean( "bind", "Bind marker", "Bind In/Out points", FALSE, G_PARAM_READWRITE)); + + g_object_class_install_property( gobject_class, + CLEARED, + g_param_spec_boolean( "clear", "Clear marker", "Clear in/out points", FALSE, G_PARAM_READWRITE )); + + timeline_signals[ SELECTION_CHANGED_SIGNAL ] = + g_signal_new( "selection_changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_FIRST,0,NULL,NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 , NULL ); + + timeline_signals[ POS_CHANGED ] = + g_signal_new( "pos_changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET( TimelineSelectionClass, pos_changed ), + NULL,NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, NULL); + + timeline_signals[ IN_CHANGED ] = + g_signal_new( "in_point_changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET( TimelineSelectionClass, in_point_changed ), + NULL,NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, NULL); + + timeline_signals[ OUT_CHANGED ] = + g_signal_new( "out_point_changed", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET( TimelineSelectionClass, out_point_changed ), + NULL,NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, NULL); + + timeline_signals[ CLEAR_CHANGED ] = + g_signal_new( "cleared", G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET( TimelineSelectionClass, cleared ), + NULL,NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, NULL ); + + timeline_signals[ BIND_CHANGED ] = + g_signal_new( "bind_toggled", + G_TYPE_FROM_CLASS(gobject_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET( TimelineSelectionClass, bind_toggled ), + NULL,NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, NULL ); + +} + +static int default_theme_ = 1; + +void timeline_theme_colors( int inverse ) +{ + default_theme_ = inverse; +} + +static void timeline_init( TimelineSelection *te ) +{ + te->min = 0.0; + te->max = 0.0; + te->action = action_none; + te->in = 0.0; + te->out = 1.0; + te->num_video_frames = 1.0; + te->frame_num = 0.0; + te->grab_location = MOUSE_OUTSIDE; + te->current_location = MOUSE_OUTSIDE; + te->grab_button = 0; + te->has_stepper = TRUE; + te->has_selection = FALSE; + te->stepper_size = 16; // 8 x 8 pixels + te->stepper_draw_size = 12; + te->stepper_length = 0; + te->frame_height = 10; + te->font_line = 12; + te->move_x = 0; +} + +GType timeline_get_type(void) +{ + static GType gtype = 0; + if(!gtype) + { + static const GTypeInfo ginfo = { + sizeof( TimelineSelectionClass), + NULL, + NULL, + (GClassInitFunc) timeline_class_init, + NULL, + NULL, + sizeof(TimelineSelection), + 0, + (GInstanceInitFunc) timeline_init, + NULL + }; + gtype = g_type_register_static( GTK_TYPE_DRAWING_AREA, "Timeline", &ginfo, 0 ); + } + return gtype; +} + + + +gdouble timeline_get_in_point( TimelineSelection *te ) +{ + gdouble result = 0.0; + g_object_get( G_OBJECT(te), "in", &result, NULL ); + return result; +} + +gdouble timeline_get_out_point( TimelineSelection *te ) +{ + gdouble result = 0.0; + g_object_get( G_OBJECT(te), "out", &result, NULL ); + return result; +} + +gboolean timeline_get_selection( TimelineSelection *te ) +{ + gboolean result = FALSE; + g_object_get( G_OBJECT(te), "selection", &result, NULL ); + return result; +} + +gboolean timeline_get_bind( TimelineSelection *te ) +{ + gboolean result = FALSE; + g_object_get( G_OBJECT(te), "bind", &result, NULL ); + return result; +} + +void timeline_set_bind(GtkWidget *widget, gboolean active) +{ + TimelineSelection *te = TIMELINE_SELECTION(widget); + g_object_set( G_OBJECT(te), "bind", active, NULL ); + g_signal_emit( te->widget, timeline_signals[BIND_CHANGED], 0); +} + +void timeline_set_out_point( GtkWidget *widget, gdouble pos ) +{ + TimelineSelection *te = TIMELINE_SELECTION(widget); + if( pos < 0.0 ) pos = 0.0; else if (pos > 1.0 ) pos = 1.0; + g_object_set( G_OBJECT(te), "out", pos, NULL ); + g_signal_emit(te->widget, timeline_signals[OUT_CHANGED], 0); + gtk_widget_queue_draw( GTK_WIDGET(te->widget) ); +} + +void timeline_clear_points( GtkWidget *widget ) +{ + gboolean cleared = TRUE; + gdouble pos = 0.0; + gdouble pos2 = 1.0; + TimelineSelection *te = TIMELINE_SELECTION(widget); + g_object_set( G_OBJECT(te), "clear", cleared, NULL ); + g_object_set( G_OBJECT(te), "in", pos, NULL ); + g_object_set( G_OBJECT(te), "out", pos2, NULL ); + g_signal_emit(te->widget, timeline_signals[CLEAR_CHANGED], 0 ); + gtk_widget_queue_draw(GTK_WIDGET(te->widget) ); +} + +void timeline_set_in_point( GtkWidget *widget, gdouble pos ) +{ + TimelineSelection *te = TIMELINE_SELECTION(widget); + if( pos < 0.0 ) pos = 0.0; else if (pos > 1.0 ) pos = 1.0; + g_object_set( G_OBJECT(te), "in", pos, NULL ); + g_signal_emit(te->widget, timeline_signals[IN_CHANGED], 0); + gtk_widget_queue_draw( GTK_WIDGET(te->widget) ); +} + +void timeline_set_selection( GtkWidget *widget, gboolean active) +{ + TimelineSelection *te = TIMELINE_SELECTION(widget); + g_object_set( G_OBJECT(te), "selection", active, NULL ); + gtk_widget_queue_draw( GTK_WIDGET(te->widget) ); +} + +void timeline_set_length( GtkWidget *widget, gdouble length, gdouble pos) +{ + TimelineSelection *te = TIMELINE_SELECTION( widget ); + if( pos < 0.0 ) pos = 0.0; + g_object_set( G_OBJECT(te), "length", length, NULL ); + timeline_set_pos( GTK_WIDGET(te->widget), pos ); +} + +void timeline_set_pos( GtkWidget *widget,gdouble pos) +{ + TimelineSelection *te = TIMELINE_SELECTION( widget ); + if( pos < 0.0 ) pos = 0.0; + g_object_set( G_OBJECT(te), "pos", pos, NULL ); + g_signal_emit( te->widget, timeline_signals[POS_CHANGED], 0); + gtk_widget_queue_draw( GTK_WIDGET(te->widget) ); +} + +gdouble timeline_get_pos( TimelineSelection *te ) +{ + gdouble result = 0.0; + g_object_get( G_OBJECT(te), "pos", &result, NULL ); + return result; +} + +gdouble timeline_get_length( TimelineSelection *te ) +{ + gdouble result = 0.0; + g_object_get( G_OBJECT(te), "length", &result, NULL ); + return result; +} + +static void move_selection( GtkWidget *widget, gdouble x, gdouble width ) +{ + TimelineSelection *te = TIMELINE_SELECTION( widget ); + + gdouble dx3 = (0.5 * (te->out - te->in)) * width; + + gdouble dx1 = x - dx3; + gdouble dx2 = x + dx3; + + te->in = (1.0/width) * dx1; + te->out = (1.0/width ) * dx2; + + timeline_set_out_point(widget, te->out ); + timeline_set_in_point(widget, te->in ); + te->move_x = x; + +} + +static gboolean +event_scroll (GtkWidget *widget, GdkEventScroll *ev, gpointer user_data) +{ + TimelineSelection *te = TIMELINE_SELECTION (widget); + gdouble width = (gdouble) widget->allocation.width; + gint x,y; + GdkModifierType state; + gdk_window_get_pointer( ev->window, &x,&y,&state ); + + if( ev->direction == GDK_SCROLL_UP ) { + gdouble cur_pos = timeline_get_pos(widget); + timeline_set_pos( widget, cur_pos + 1 ); + } + else if(ev->direction == GDK_SCROLL_DOWN ) { + gdouble cur_pos = timeline_get_pos(widget); + timeline_set_pos( widget, cur_pos - 1 ); + } + + gtk_widget_queue_draw( widget ); + + return FALSE; +} + + +static gboolean event_press(GtkWidget *widget, GdkEventButton *ev, gpointer user_data) +{ + TimelineSelection *te = TIMELINE_SELECTION( widget ); + gdouble width = widget->allocation.width; + + te->grab_button = ev->button; + te->current_location = MOUSE_WIDGET; + + + if( ev->type == GDK_2BUTTON_PRESS && te->grab_button == 1 ) + { + timeline_clear_points( widget ); + return FALSE; + } + + if(te->grab_button == 1 && POINT_IN_RECT( ev->x, ev->y, te->stepper ) ) + { + if(te->has_stepper) + { + te->current_location = MOUSE_STEPPER; + te->action = action_pos; + } + return FALSE; + } + + if(te->grab_button == 1 && te->has_selection) + { + if( POINT_IN_RECT( ev->x, ev->y, te->selection ) && te->bind ) + { + te->current_location = MOUSE_SELECTION; + } + if(!te->bind) + { + gdouble val = (1.0 / width) * ev->x; + timeline_set_in_point( widget, val ); + } + } + else if(te->grab_button == 3 && te->has_selection ) + { + if( POINT_IN_RECT( ev->x, ev->y, te->selection ) && te->bind ) + { + te->current_location = MOUSE_SELECTION; + } + if(!te->bind) + { + gdouble val = (1.0/width) * ev->x; + timeline_set_out_point( widget, val ); + } + } + else if(te->grab_button == 2 && te->has_selection) + { + gint dx = ev->x; + gint dy = ev->y; + if( POINT_IN_RECT( dx, dy, te->selection ) ) + { + timeline_set_bind( widget, (te->bind ? FALSE: TRUE )); + te->move_x = (gdouble) ev->x; + } + } + + + gtk_widget_queue_draw( widget ); + + return FALSE; +} +static gboolean event_release (GtkWidget *widget, GdkEventButton *ev, gpointer user_data) +{ + TimelineSelection *te = TIMELINE_SELECTION (widget); + te->action = action_none; + te->current_location = MOUSE_WIDGET; +// te->grab_button = 0; +// te->move_x = 0; + return FALSE; +} + +static gboolean +event_motion (GtkWidget *widget, GdkEventMotion *ev, gpointer user_data) +{ + TimelineSelection *te = TIMELINE_SELECTION (widget); + gdouble width = (gdouble) widget->allocation.width; + gint x,y; + GdkModifierType state; + gdk_window_get_pointer( ev->window, &x,&y,&state ); + + + if( te->has_stepper && te->current_location == MOUSE_STEPPER && ev->state & GDK_BUTTON1_MASK) + { + gdouble rel_pos = ((gdouble)ev->x / width) * te->num_video_frames; + gdouble new_pos = (gdouble) ((gint) rel_pos ); + + timeline_set_pos( widget, new_pos ); + return FALSE; + } + + if( te->has_selection && te->current_location != MOUSE_STEPPER) + { + if(!te->bind) + { + gdouble gx = (1.0 / width) * x; + if(te->grab_button == 1 && ev->state & GDK_BUTTON1_MASK) + timeline_set_in_point(widget, gx ); + else if(te->grab_button == 3 && ev->state & GDK_BUTTON3_MASK) + timeline_set_out_point( widget, gx ); + } + } + + if(te->has_selection && te->bind && te->grab_button == 2 ) + move_selection( widget, x, width ); + + gtk_widget_queue_draw( widget ); + + return FALSE; +} +/* draw a rounded rectangle */ +void +cairo_rectangle_round (cairo_t * cr, + double x0, + double y0, double width, double height, double radius) +{ + double x1, y1; + + x1 = x0 + width; + y1 = y0 + height; + if (width <= 0.001 || height <= 0.001) + return; + if (width / 2 < radius) + { + if (height / 2 < radius) + { + cairo_move_to (cr, x0, (y0 + y1) / 2); + cairo_curve_to (cr, x0, y0, x0, y0, (x0 + x1) / 2, y0); + cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1) / 2); + cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0) / 2, y1); + cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1) / 2); + } + else + { + cairo_move_to (cr, x0, y0 + radius); + cairo_curve_to (cr, x0, y0, x0, y0, (x0 + x1) / 2, y0); + cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius); + cairo_line_to (cr, x1, y1 - radius); + cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0) / 2, y1); + cairo_curve_to (cr, x0, y1, x0, y1, x0, y1 - radius); + } + } + else +{ + if (height / 2 < radius) + { + cairo_move_to (cr, x0, (y0 + y1) / 2); + cairo_curve_to (cr, x0, y0, x0, y0, x0 + radius, y0); + cairo_line_to (cr, x1 - radius, y0); + cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1) / 2); + cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1); + cairo_line_to (cr, x0 + radius, y1); + cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1) / 2); + } + else + { + cairo_move_to (cr, x0, y0 + radius); + cairo_curve_to (cr, x0, y0, x0, y0, x0 + radius, y0); + cairo_line_to (cr, x1 - radius, y0); + cairo_curve_to (cr, x1, y0, x1, y0, x1, y0 + radius); + cairo_line_to (cr, x1, y1 - radius); + cairo_curve_to (cr, x1, y1, x1, y1, x1 - radius, y1); + cairo_line_to (cr, x0 + radius, y1); + cairo_curve_to (cr, x0, y1, x0, y1, x0, y1 - radius); + } + } + cairo_close_path (cr); +} + +static gboolean timeline_expose (GtkWidget *widget, GdkEventExpose *event ) +{ + cairo_t *cr; + cr = gdk_cairo_create( widget->window ); + + TimelineSelection *te = TIMELINE_SELECTION( widget ); + double width = widget->allocation.width; + double height = widget->allocation.height; + + gdouble marker_width = width/ te->num_video_frames; +// gdouble marker_height = height / te->num_video_frames; + gdouble marker_height = te->frame_height; + + te->frame_width = marker_width; + + cairo_save(cr); + cairo_identity_matrix(cr); + +/* Draw stepper */ + if( te->has_stepper ) + { + cairo_set_source_rgba( cr, 1.0,0.0,0.0,1.0); + double x1 = marker_width * te->frame_num; + te->stepper.x = x1 - 8; + te->stepper.y = 0; + te->stepper.width = te->stepper_size + 8; + te->stepper.height = te->stepper_size + 2; + + cairo_move_to( cr, x1 - te->stepper_draw_size, 0.0 * height ); + cairo_rel_line_to( cr, te->stepper_draw_size, te->stepper_draw_size ); + cairo_rel_line_to( cr, te->stepper_draw_size, -te->stepper_draw_size ); + cairo_rel_line_to( cr, -2.0 * te->stepper_draw_size, 0 ); + cairo_set_line_join( cr, CAIRO_LINE_JOIN_MITER); + cairo_move_to(cr, x1, te->stepper_draw_size ); + cairo_rel_line_to( cr, 0.0, te->stepper_length ); + cairo_stroke(cr); + if( te->grab_button == 1 && te->current_location == MOUSE_STEPPER ) + { + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD ); + + cairo_move_to(cr, x1 + (te->stepper_size * 0.5),te->font_line ); + gchar text[40]; + sprintf(text, "%d", (gint)te->frame_num ); + cairo_text_path( cr, text ); + cairo_set_font_size( cr, 0.2 ); + double v = ( default_theme_ ? 1.0 : 0.0 ); + cairo_set_source_rgba( cr, v,v,v,0.7 ); + cairo_fill(cr); + } + } +/* Draw selection */ + if( te->has_selection ) + { + gdouble in = te->in * width; + gdouble out = te->out * width; + gdouble v = (default_theme_ ? 1.0: 0.0); + + /* If user is editing in_point */ + if( te->grab_button == 1 && te->current_location != MOUSE_STEPPER ) + { + gdouble f = te->in * te->num_video_frames; + cairo_set_source_rgba( cr, 0.0, v,v,0.3 ); + cairo_move_to( cr, in, 0.0 ); + cairo_rel_line_to( cr, 0.0 , te->stepper_length ); + cairo_stroke(cr); + + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD ); + + cairo_move_to(cr, in , te->font_line ); + gchar text[40]; + sprintf(text, "%d",(gint) f ); + cairo_text_path( cr, text ); + cairo_set_font_size( cr, 0.2 ); + cairo_set_source_rgba( cr, v,v,v,0.7 ); + cairo_fill(cr); + + } + if( te->grab_button == 3 && te->current_location != MOUSE_STEPPER ) + { + gdouble f = te->out * te->num_video_frames; + cairo_set_source_rgba( cr, 0.0, v,v,0.3 ); + cairo_move_to( cr, out , 0.0 ); + cairo_rel_line_to( cr, 0.0 , te->stepper_length ); + cairo_stroke(cr); + + cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_BOLD ); + + cairo_move_to(cr, out ,te->font_line ); + gchar text[40]; + sprintf(text, "%d", (gint) f ); + cairo_text_path( cr, text ); + cairo_set_font_size( cr, 0.2 ); + cairo_set_source_rgba( cr, v,v,v,0.7 ); + cairo_fill(cr); + + } + + cairo_set_source_rgba( cr, v, v, v, 0.3 ); + cairo_rectangle_round(cr, in, + 0.095 * height, + (out - in), + marker_height, + 10); + te->selection.x = in; + te->selection.y = 0; + te->selection.width = out; + te->selection.height = te->font_line; + cairo_fill_preserve(cr); + } + cairo_restore(cr); + + cairo_destroy(cr); + return FALSE; +} + +GtkWidget *timeline_new(void) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new( timeline_get_type(), NULL )); + TimelineSelection *te = TIMELINE_SELECTION( widget ); + + gtk_widget_set_size_request(widget, 200,16 ); + + gtk_widget_set_events( widget, + GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_POINTER_MOTION_MASK | + GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_BUTTON3_MOTION_MASK | GDK_2BUTTON_PRESS | GDK_SCROLL_MASK ); + + g_signal_connect( G_OBJECT(widget), "expose_event", G_CALLBACK(timeline_expose), NULL ); + g_signal_connect( G_OBJECT(widget), "motion_notify_event", + G_CALLBACK(event_motion), NULL ); + g_signal_connect( G_OBJECT(widget), "button_press_event", + G_CALLBACK(event_press), NULL ); + g_signal_connect( G_OBJECT(widget), "button_release_event", + G_CALLBACK(event_release), NULL ); + g_signal_connect( G_OBJECT(widget), "scroll_event", + G_CALLBACK( event_scroll ), NULL ); + + te->widget = widget; + + return widget; +} diff --git a/branches/V-1.5.3/veejay-client/src/gtktimeselection.h b/branches/V-1.5.3/veejay-client/src/gtktimeselection.h new file mode 100644 index 00000000..b146932e --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gtktimeselection.h @@ -0,0 +1,68 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef GTKTIMESELECTION_H +#define GTKTIMESELECTION_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define TIMELINE_SELECTION(obj) GTK_CHECK_CAST(obj, timeline_get_type(), TimelineSelection ) + +#define TIMELINE_SELECTION_CLASS(klass) GTK_CHECK_CLASS_CAST( klass, timeline_get_type(), TimelineSelectionClass ) + +#define IS_TIMELINE_SELECTION(obj) GTK_CHECK_TYPE( obj, timeline_get_type() ) + +typedef struct _TimelineSelection TimelineSelection; +typedef struct _TimelineSelectionClass TimelineSelectionClass; + +GtkType timeline_get_type (void); +GtkWidget* timeline_new (void); + +gdouble timeline_get_length (TimelineSelection *te); +gdouble timeline_get_pos (TimelineSelection *te); +gdouble timeline_get_in_point (TimelineSelection *te ); +gdouble timeline_get_out_point (TimelineSelection *te ); +gboolean timeline_get_selection (TimelineSelection *te ); +gboolean timeline_get_bind (TimelineSelection *te ); + +void timeline_set_pos (GtkWidget *widget, gdouble pos ); + +void timeline_set_in_point (GtkWidget *widget, gdouble pos); +void timeline_set_out_point (GtkWidget *widget, gdouble pos); + +void timeline_set_length (GtkWidget *widget, gdouble length, gdouble pos); + +void timeline_set_bind (GtkWidget *widget, gboolean active); + + +void timeline_clear_points( GtkWidget *widget ); + +void timeline_set_selection( GtkWidget *widget, gboolean active); +void timeline_theme_colors( int inverse ); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/branches/V-1.5.3/veejay-client/src/gveejay.c b/branches/V-1.5.3/veejay-client/src/gveejay.c new file mode 100644 index 00000000..ae553f19 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/gveejay.c @@ -0,0 +1,270 @@ +/* gveejay - Linux VeeJay - GVeejay GTK+-2/Glade User Interface + * (C) 2002-2005 Niels Elburg + * + * + * 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 + +static int selected_skin = 0; +extern int mt_get_max_tracks(); + +static int port_num = 3490; +static char hostname[255]; +static int gveejay_theme = 1; +static int verbosity = 0; +static int col = 0; +static int row = 0; +static int n_tracks = 4; +static int launcher = 0; +static int pw = 176; +static int ph = 144; +static int preview = 0; // off +static int use_threads = 0; +static struct +{ + char *file; +} skins[] = { + { "gveejay.reloaded.glade" }, + { "reloaded_classic.glade" }, + { NULL } +}; + +extern void reloaded_launcher( char *h, int p ); + +static void usage(char *progname) +{ + printf( "Usage: %s \n",progname); + printf( "where options are:\n"); + printf( "-h\t\tVeejay host to connect to (defaults to localhost) \n"); + printf( "-p\t\tVeejay port to connect to (defaults to 3490) \n"); + printf( "-t\t\tDont load gveejay's GTK theme\n"); + printf( "-n\t\tDont use colored text\n"); + printf( "-v\t\tBe extra verbose (usefull for debugging)\n"); + printf( "-s\t\tSet bank resolution (row X columns)\n"); + printf( "-P\t\tStart with preview enabled (1=1/1,2=1/2,3=1/4,4=1/8)\n"); + printf( "-X\t\tSet number of tracks\n"); + printf( "-l\t\tChoose layout (0=large screen, 1=small screens)\n"); + printf( "-V\t\tShow version, data directory and exit.\n"); + printf( "\n\n"); + exit(-1); +} +static int set_option( const char *name, char *value ) +{ + int err = 0; + if( strcmp(name, "h") == 0 || strcmp(name, "hostname") == 0 ) + { + strcpy( hostname, optarg ); + launcher ++; + } + else if( strcmp(name, "p") == 0 || strcmp(name ,"port") == 0 ) + { + if(sscanf( optarg, "%d", &port_num )) + launcher++; + } + else if (strcmp(name, "l" ) == 0 ) { + selected_skin = atoi( optarg); + } + else if (strcmp(name, "n") == 0 ) + { + veejay_set_colors(0); + } + else if (strcmp(name, "X") == 0 ) + { + n_tracks = atoi(optarg); + if( n_tracks < 1 || n_tracks > mt_get_max_tracks() ) + n_tracks = 1; + } + else if( strcmp(name, "t") == 0 || strcmp(name, "no-theme") == 0) + { + gveejay_theme = 0; + } + else if( strcmp(name, "v") == 0 || strcmp(name, "verbose") == 0) + { + verbosity = 1; + } + else if (strcmp(name, "s") == 0 || strcmp(name, "size") == 0) + { + if(sscanf( (char*) optarg, "%dx%d", + &row, &col ) != 2 ) + { + fprintf(stderr, "--size parameter requires NxN argument"); + err++; + } + } + else if (strcmp(name, "V") == 0 ) + { + fprintf(stdout, "version: %s\n", PACKAGE_VERSION); + fprintf(stdout, "data directory: %s\n", get_gveejay_dir()); + exit(0); + } + else if (strcmp(name, "P" ) == 0 || strcmp(name, "preview" ) == 0 ) + { + preview = atoi(optarg); + if(preview <= 0 || preview > 4 ) + { + fprintf(stderr, "--preview [0-4]\n"); + err++; + } + } + else + err++; + return err; +} +static volatile gulong g_trap_free_size = 0; +static struct timeval time_last_; + +static char **cargv = NULL; + + +gboolean gveejay_idle(gpointer data) +{ + if(gveejay_running()) + { + int sync = 0; + if( is_alive(&sync) == FALSE ) { + //@ restart reloaded + veejay_msg(VEEJAY_MSG_WARNING, + "No connection with veejay, attempting restart."); + reloaded_restart(); + } + if( sync ) { + if( gveejay_time_to_sync( get_ui_info() ) ) + { + veejay_update_multitrack( get_ui_info() ); + update_gveejay(); + } + } else { + gveejay_sleep( get_ui_info() ); + } + + } + + if( gveejay_restart() ) + { + //@ reinvoke + if( execvp( cargv[0], cargv ) == -1 ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to restart"); + } + + return TRUE; +} + +static void clone_args( char *argv[], int argc ) +{ + int i = 0; + if( argc <= 0 ) + return; + + cargv = (char**) malloc(sizeof(char*) * (argc+1) ); + memset( cargv, 0, sizeof(char*) * (argc+1)); + for( i = 0; i < argc ; i ++ ) + cargv[i] = strdup( argv[i] ); + +} + +int main(int argc, char *argv[]) { + char option[2]; + int n; + int err=0; + + if(!argc) usage(argv[0]); + + clone_args( argv, argc ); + + // default host to connect to + sprintf(hostname, "127.0.0.1"); + + while( ( n = getopt( argc, argv, "s:h:p:tnvHf:X:P:Vl:T:")) != EOF ) + { + sprintf(option, "%c", n ); + err += set_option( option, optarg); + if(err) usage(argv[0]); + } + if( optind > argc ) + err ++; + + if( err ) usage(argv[0]); +/* + if( !g_thread_supported() ) + { + veejay_msg(2, "Initializing GDK threads"); + g_thread_init(NULL); + gdk_threads_init(); // Called to initialize internal mutex "gdk_threads_mutex". + }*/ + + gtk_init( NULL,NULL ); + glade_init(); + +// g_mem_set_vtable( glib_mem_profiler_table ); + + vj_mem_init(); + + vevo_strict_init(); + + find_user_themes(gveejay_theme); + + vj_gui_set_debug_level( verbosity , n_tracks,pw,ph); + set_skin( selected_skin ); + + default_bank_values( &col, &row ); + gui_load_theme(); + + register_signals(); + + vj_gui_init( skins[selected_skin].file, launcher, hostname, port_num, use_threads ); + vj_gui_style_setup(); + + + if( preview ) + { + veejay_msg(VEEJAY_MSG_INFO, "Starting with preview enabled"); + gveejay_preview(preview); + } + + + if( launcher ) + { + reloaded_launcher( hostname, port_num ); + } + + memset( &time_last_, 0, sizeof(struct timeval)); + + while(gveejay_running()) { + gveejay_idle(NULL); + while( gtk_events_pending() ) + gtk_main_iteration(); + + } + + + return 0; +} + + diff --git a/branches/V-1.5.3/veejay-client/src/keyboard.c b/branches/V-1.5.3/veejay-client/src/keyboard.c new file mode 100644 index 00000000..8dbd1192 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/keyboard.c @@ -0,0 +1,330 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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 "keyboard.h" +static struct +{ + const int sdl_mod; + const int gdk_mod; + const gchar *title; +} modifier_translation_table_t[] = +{ + { 0, 0, " " }, + { 0, 16, " " }, + { 3, 1, "shift" }, + { 3, 17, "shift" }, + { 1, 8, "alt" }, + { 1, 24, "alt" }, + { 1, 44, "alt" }, + { 2, 4, "ctrl" }, + { 2, 20, "ctrl" }, + { 0, 0, NULL }, +}; +/* fixme: introduce keyboard mapping functionality + 1. attach VIMS events/VIMS BUNDLES to keys (with arguments) + 2. save/load VIMS keyboard mapping +*/ +static struct +{ + const int gdk_sym; // GDK key + const int sdl_sym; // SDL key + const gchar *title; // plain text +} key_translation_table_t[] = +{ + +{ GDK_space, SDLK_SPACE, "Space" }, +{ GDK_exclam, SDLK_EXCLAIM, "Exclaim" }, +{ GDK_quotedbl, SDLK_QUOTEDBL, "Double quote" }, +{ GDK_numbersign, SDLK_HASH, "Hash" }, +{ GDK_dollar, SDLK_DOLLAR, "Dollar" }, +{ GDK_percent, SDLK_PAUSE, "Percent" }, +{ GDK_parenleft, SDLK_LEFTPAREN, "Leftparen" }, +{ GDK_parenright, SDLK_RIGHTPAREN, "Rightparen" }, +{ GDK_asciicircum,SDLK_CARET, "Caret" }, +{ GDK_ampersand, SDLK_AMPERSAND, "Ampersand" }, +{ GDK_underscore, SDLK_UNDERSCORE, "Underscore" }, +{ GDK_braceright, 123, "Rightbrace" }, +{ GDK_braceleft, 125, "Leftbrace" }, +{ GDK_grave, SDLK_BACKQUOTE, "Aphostrophe" }, +{ GDK_asciitilde, 126, "Tilde" }, +{ GDK_asterisk, SDLK_ASTERISK, "Asterisk" }, +{ GDK_plus, SDLK_PLUS, "Plus" }, +{ GDK_comma, SDLK_COMMA, "Comma" }, +{ GDK_minus, SDLK_MINUS, "Minus" }, +{ GDK_period, SDLK_PERIOD, "Period" }, +{ GDK_slash, SDLK_SLASH, "Slash" }, +{ GDK_Home, SDLK_HOME, "Home" }, +{ GDK_End, SDLK_END, "End" }, +{ GDK_Page_Up, SDLK_PAGEUP, "PageUp" }, +{ GDK_Page_Down, SDLK_PAGEDOWN, "PageDown" }, +{ GDK_Insert, SDLK_INSERT, "Insert" }, +{ GDK_Up, SDLK_UP, "Up" }, +{ GDK_Down, SDLK_DOWN, "Down" }, +{ GDK_Left, SDLK_LEFT, "Left" }, +{ GDK_Right, SDLK_RIGHT, "Right" }, +{ GDK_Tab, SDLK_TAB, "TAB" }, +{ GDK_BackSpace, SDLK_BACKSPACE, "Backspace" }, +{ GDK_Escape, SDLK_ESCAPE, "Escape" }, +{ GDK_Delete, SDLK_DELETE, "Delete" }, +{ GDK_F1, SDLK_F1, "F1" }, +{ GDK_F2, SDLK_F2, "F2" }, +{ GDK_F3, SDLK_F3, "F3" }, +{ GDK_F4, SDLK_F4, "F4" }, +{ GDK_F5, SDLK_F5, "F5" }, +{ GDK_F6, SDLK_F6, "F6" }, +{ GDK_F7, SDLK_F7, "F7" }, +{ GDK_F8, SDLK_F8, "F8" }, +{ GDK_F9, SDLK_F9, "F9" }, +{ GDK_F10, SDLK_F10, "F10" }, +{ GDK_F11, SDLK_F11, "F11" }, +{ GDK_F12, SDLK_F12, "F12" }, +{ GDK_EuroSign, SDLK_EURO, "Euro" }, +{ GDK_KP_0, SDLK_KP0, "keypad 0" }, +{ GDK_KP_1, SDLK_KP1, "keypad 1" }, +{ GDK_KP_2, SDLK_KP2, "keypad 2" }, +{ GDK_KP_3, SDLK_KP3, "keypad 3" }, +{ GDK_KP_4, SDLK_KP4, "keypad 4" }, +{ GDK_KP_5, SDLK_KP5, "keypad 5" }, +{ GDK_KP_6, SDLK_KP6, "keypad 6" }, +{ GDK_KP_7, SDLK_KP7, "keypad 7" }, +{ GDK_KP_8, SDLK_KP8, "keypad 8" }, +{ GDK_KP_9, SDLK_KP9, "keypad 9" }, +{ GDK_KP_Divide, SDLK_KP_DIVIDE, "keypad /" }, +{ GDK_KP_Multiply,SDLK_KP_MULTIPLY, "keypad *" }, +{ GDK_KP_Subtract,SDLK_KP_MINUS, "keypad -" }, +{ GDK_KP_Add, SDLK_KP_PLUS, "keypad +" }, +{ GDK_KP_Equal, SDLK_KP_EQUALS, "keypad =" }, +{ GDK_KP_Enter, SDLK_KP_ENTER, "keypad ENTER" }, +{ GDK_ISO_Enter, SDLK_RETURN, "ENTER" }, +{ GDK_3270_Enter, SDLK_RETURN, "ENTER" }, + +/* GDK_KP doesnt word on all systems ... */ +{ 0xff9f, SDLK_KP0, "keypad 0" }, +{ 0xff9c, SDLK_KP1, "keypad 1" }, +{ 0xff99, SDLK_KP2, "keypad 2" }, +{ 0xff9b, SDLK_KP3, "keypad 3" }, +{ 0xff96, SDLK_KP4, "keypad 4" }, +{ 0xff9d, SDLK_KP5, "keypad 5" }, +{ 0xff98, SDLK_KP6, "keypad 6" }, +{ 0xff95, SDLK_KP7, "keypad 7" }, +{ 0xff97, SDLK_KP8, "keypad 8" }, +{ 0xff9a, SDLK_KP9, "keypad 9" }, +{ 0xff9f, SDLK_KP_PERIOD, "keypad ." }, + + +{ GDK_0, SDLK_0, "0" }, +{ GDK_1, SDLK_1, "1" }, +{ GDK_2, SDLK_2, "2" }, +{ GDK_3, SDLK_3, "3" }, +{ GDK_4, SDLK_4, "4" }, +{ GDK_5, SDLK_5, "5" }, +{ GDK_6, SDLK_6, "6" }, +{ GDK_7, SDLK_7, "7" }, +{ GDK_8, SDLK_8, "8" }, +{ GDK_9, SDLK_9, "9" }, +{ GDK_colon, SDLK_COLON, "colon" }, +{ GDK_semicolon, SDLK_SEMICOLON, "semicolon" }, +{ GDK_less, SDLK_LESS, "less" }, +{ GDK_equal, SDLK_EQUALS, "equals" }, +{ GDK_greater, SDLK_GREATER, "greater" }, +{ GDK_question, SDLK_QUESTION, "question" }, +{ GDK_at, SDLK_AT, "at" }, +{ GDK_bracketleft,SDLK_LEFTBRACKET, "left bracket" }, +{ GDK_backslash, SDLK_BACKSLASH, "backslash" }, +{ GDK_bracketright,SDLK_RIGHTBRACKET, "right bracket" }, +{ GDK_underscore, SDLK_UNDERSCORE, "underscore" }, +{ GDK_A, SDLK_a, "A" }, +{ GDK_B, SDLK_b, "B" }, +{ GDK_C, SDLK_c, "C" }, +{ GDK_D, SDLK_d, "D" }, +{ GDK_E, SDLK_e, "E" }, +{ GDK_F, SDLK_f, "F" }, +{ GDK_G, SDLK_g, "G" }, +{ GDK_H, SDLK_h, "H" }, +{ GDK_I, SDLK_i, "I" }, +{ GDK_J, SDLK_j, "J" }, +{ GDK_K, SDLK_k, "K" }, +{ GDK_L, SDLK_l, "L" }, +{ GDK_M, SDLK_m, "M" }, +{ GDK_N, SDLK_n, "N" }, +{ GDK_O, SDLK_o, "O" }, +{ GDK_P, SDLK_p, "P" }, +{ GDK_Q, SDLK_q, "Q" }, +{ GDK_R, SDLK_r, "R" }, +{ GDK_S, SDLK_s, "S" }, +{ GDK_T, SDLK_t, "T" }, +{ GDK_U, SDLK_u, "U" }, +{ GDK_V, SDLK_v, "V" }, +{ GDK_W, SDLK_w, "W" }, +{ GDK_X, SDLK_y, "Y" }, +{ GDK_Z, SDLK_z, "Z" }, +{ GDK_a, SDLK_a, "a" }, +{ GDK_b, SDLK_b, "b" }, +{ GDK_c, SDLK_c, "c" }, +{ GDK_d, SDLK_d, "d" }, +{ GDK_e, SDLK_e, "e" }, +{ GDK_f, SDLK_f, "f" }, +{ GDK_g, SDLK_g, "g" }, +{ GDK_h, SDLK_h, "h" }, +{ GDK_i, SDLK_i, "i" }, +{ GDK_j, SDLK_j, "j" }, +{ GDK_k, SDLK_k, "k" }, +{ GDK_l, SDLK_l, "l" }, +{ GDK_m, SDLK_m, "m" }, +{ GDK_n, SDLK_n, "n" }, +{ GDK_o, SDLK_o, "o" }, +{ GDK_p, SDLK_p, "p" }, +{ GDK_q, SDLK_q, "q" }, +{ GDK_r, SDLK_r, "r" }, +{ GDK_s, SDLK_s, "s" }, +{ GDK_t, SDLK_t, "t" }, +{ GDK_u, SDLK_u, "u" }, +{ GDK_v, SDLK_v, "v" }, +{ GDK_w, SDLK_w, "w" }, +{ GDK_x, SDLK_x, "x" }, +{ GDK_y, SDLK_y, "y" }, +{ GDK_z, SDLK_z, "z" }, +{ 0, 0, NULL }, + +}; + + +int sdl2gdk_key(int sdl_key) +{ + return 0; +} + +int gdk2sdl_key(int gdk_key) +{ + int i; + for ( i = 0; key_translation_table_t[i].title != NULL ; i ++ ) + { + if( gdk_key == key_translation_table_t[i].gdk_sym ) + return key_translation_table_t[i].sdl_sym; + } + return 0; +} + +int gdk2sdl_mod( int gdk_mod ) +{ + int i; + for ( i = 0; modifier_translation_table_t[i].title != NULL ; i ++ ) + { + if( gdk_mod == modifier_translation_table_t[i].gdk_mod ) + return modifier_translation_table_t[i].sdl_mod; + } + return 0; +} + +int sdlmod_by_name( gchar *name ) +{ + int i; + if(!name) + return 0; + + for ( i = 0; modifier_translation_table_t[i].title != NULL ; i ++ ) + { + if( g_utf8_collate(name, + modifier_translation_table_t[i].title) == 0) + return modifier_translation_table_t[i].sdl_mod; + } + + return 0; +} + +int sdlkey_by_name( gchar *name ) +{ + int i; + if(!name) + return 0; + for ( i = 0; key_translation_table_t[i].title != NULL ; i ++ ) + { + if( g_utf8_collate(name, + key_translation_table_t[i].title) == 0) + return key_translation_table_t[i].sdl_sym; + } + return 0; +} + +gchar *sdlkey_by_id( int sdl_key ) +{ + int i; + gchar *ret = NULL; + for ( i = 0; key_translation_table_t[i].title != NULL ; i ++ ) + { + if( sdl_key == key_translation_table_t[i].sdl_sym ) + return (gchar*)key_translation_table_t[i].title; + } + return ret; +} + +gchar *sdlmod_by_id( int sdl_mod ) +{ + int i; + gchar *ret = NULL; + for ( i = 0; modifier_translation_table_t[i].title != NULL ; i ++ ) + { + if( sdl_mod == modifier_translation_table_t[i].sdl_mod ) + return (gchar*)modifier_translation_table_t[i].title; + } + return ret; +} +gchar *gdkmod_by_id( int gdk_mod ) +{ + int i; + for( i = 0; modifier_translation_table_t[i].title != NULL ; i ++ ) + { + if( gdk_mod == modifier_translation_table_t[i].gdk_mod || + gdk_mod & modifier_translation_table_t[i].gdk_mod ) + return (gchar*)modifier_translation_table_t[i].title; + } + return NULL; +} + +gchar *gdkkey_by_id( int gdk_key ) +{ + int i; + for( i = 0; key_translation_table_t[i].title != NULL ; i ++ ) + { + if( gdk_key == key_translation_table_t[i].gdk_sym ) + return (gchar*)key_translation_table_t[i].title; + } + return NULL; +} + +static void key_func(gboolean pressed, guint16 unicode, guint16 keymod) +{ + + +} +/* +Key snooper functions are called before normal event delivery. +They can be used to implement custom key event handling. +grab_widgetż: the widget to which the event will be delivered. +eventż: the key event. +func_dataż: the func_data supplied to gtk_key_snooper_install(). +Returnsż: TRUE to stop further processing of event, FALSE to continue. +*/ + +gboolean key_snooper(GtkWidget *w, GdkEventKey *event, gpointer user_data) +{ + return FALSE; +} +// gtk_key_snooper_install diff --git a/branches/V-1.5.3/veejay-client/src/keyboard.h b/branches/V-1.5.3/veejay-client/src/keyboard.h new file mode 100644 index 00000000..c6f05b1c --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/keyboard.h @@ -0,0 +1,41 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + +#ifndef GDKSDL +#define GDKSDL + +#include +#include +#include +#include + +int sdl2gdk_key( int sdl_key ); +int gdk2sdl_key( int gdk_key ); +int gdk2sdl_mod( int gdk_mod ); +gchar *sdlkey_by_id( int sdl_key ); +gchar *sdlmod_by_id( int sdk_mod ); +gchar *gdkkey_by_id( int gdk_key ); +gchar *gdkmod_by_id(int gdkmod); +int sdlmod_by_name( gchar *name ); +int sdlkey_by_name( gchar *name ); +int gdk2sdl_mod( int gdk_mod ); + +gboolean key_snooper(GtkWidget *w, GdkEventKey *event, gpointer user_data); + +#endif diff --git a/branches/V-1.5.3/veejay-client/src/mjpeg_logging.c b/branches/V-1.5.3/veejay-client/src/mjpeg_logging.c new file mode 100644 index 00000000..3d43fd8d --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/mjpeg_logging.c @@ -0,0 +1,230 @@ +/* + $Id: mjpeg_logging.c,v 1.16 2007/04/01 18:06:06 sms00 Exp $ + + Copyright (C) 2000 Herbert Valerio Riedel + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "mjpeg_logging.h" + +#ifdef HAVE___PROGNAME +extern const char *__progname; +#endif + +/* + * Put these here and NOT in the exported header file mjpeg_logging.h + * + * since ALL program use of these should use the API below (mjpeg_warn, + * mjpeg_error,etc) these symbols do not need to be exported and possibly + * conflict with syslog.h +*/ + +#define LOG_DEBUG 1 +#define LOG_INFO 2 +#define LOG_WARN 3 +#define LOG_ERROR 4 + +static log_level_t mjpeg_log_verbosity = 0; +static char *default_handler_id = NULL; + +static int default_mjpeg_log_filter( log_level_t level ) +{ + int verb_from_env; + if( mjpeg_log_verbosity == 0 ) + { + char *mjpeg_verb_env = getenv("MJPEG_VERBOSITY"); + if( mjpeg_verb_env != NULL ) + { + verb_from_env = LOG_WARN-atoi(mjpeg_verb_env); + if( verb_from_env >= LOG_DEBUG && verb_from_env <= LOG_ERROR ) + mjpeg_log_verbosity = (log_level_t)verb_from_env; + } + } + return (level < LOG_WARN && level < mjpeg_log_verbosity); +} + +static mjpeg_log_filter_t _filter = default_mjpeg_log_filter; + +static void +default_mjpeg_log_handler(log_level_t level, const char message[]) +{ + const char *ids; + + if( (*_filter)( level ) ) + return; + if (default_handler_id != NULL) { + ids = default_handler_id; + } else { +#ifdef HAVE___PROGNAME + ids = __progname; +#else + ids = "???"; +#endif + } + switch(level) { + case LOG_ERROR: + fprintf(stderr, "**ERROR: [%s] %s\n", ids, message); + break; + case LOG_DEBUG: + fprintf(stderr, "--DEBUG: [%s] %s\n", ids, message); + break; + case LOG_WARN: + fprintf(stderr, "++ WARN: [%s] %s\n", ids, message); + break; + case LOG_INFO: + fprintf(stderr, " INFO: [%s] %s\n", ids, message); + break; + default: + assert(0); + } +} + +static mjpeg_log_handler_t _handler = default_mjpeg_log_handler; + + +mjpeg_log_handler_t +mjpeg_log_set_handler(mjpeg_log_handler_t new_handler) +{ + mjpeg_log_handler_t old_handler = _handler; + + _handler = new_handler; + return old_handler; +} + +/*************** + * Set default log handlers degree of verboseity. + * 0 = quiet, 1 = info, 2 = debug + *************/ + +int +mjpeg_default_handler_verbosity(int verbosity) +{ + int prev_verb = mjpeg_log_verbosity; + mjpeg_log_verbosity = (log_level_t)(LOG_WARN - verbosity); + return prev_verb; +} + +/* + * Set identifier string used by default handler + */ +int +mjpeg_default_handler_identifier(const char *new_id) +{ + const char *s; + if (new_id == NULL) { + if (default_handler_id != NULL) + free(default_handler_id); + default_handler_id = NULL; + return 0; + } + /* find basename of new_id (remove any directory prefix) */ + if ((s = strrchr(new_id, '/')) == NULL) + s = new_id; + else + s = s + 1; + default_handler_id = strdup(s); + return 0; +} + +static void +mjpeg_logv(log_level_t level, const char format[], va_list args) +{ + char buf[1024] = { 0, }; + + /* TODO: Original had a re-entrancy error trap to assist bug + finding. To make this work with multi-threaded applications a + lock is needed hence delete. + */ + + vsnprintf(buf, sizeof(buf)-1, format, args); + _handler(level, buf); +} + +void +mjpeg_log(log_level_t level, const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(level, format, args); + va_end (args); +} + +void +mjpeg_debug(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_DEBUG, format, args); + va_end (args); +} + +void +mjpeg_info(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_INFO, format, args); + va_end (args); +} + +void +mjpeg_warn(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_WARN, format, args); + va_end (args); +} + +void +mjpeg_error(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_ERROR, format, args); + va_end (args); +} + +void +mjpeg_error_exit1(const char format[], ...) +{ + va_list args; + va_start( args, format ); + mjpeg_logv( LOG_ERROR, format, args); + va_end(args); + exit(EXIT_FAILURE); +} + +log_level_t +mjpeg_loglev_t(const char *level) +{ + if (strcasecmp("debug", level) == 0) return(LOG_DEBUG); + else if (strcasecmp("info", level) == 0) return(LOG_INFO); + else if (strcasecmp("warn", level) == 0) return(LOG_WARN); + else if (strcasecmp("error", level) == 0) return(LOG_ERROR); + return(0); +} diff --git a/branches/V-1.5.3/veejay-client/src/mjpeg_logging.h b/branches/V-1.5.3/veejay-client/src/mjpeg_logging.h new file mode 100644 index 00000000..9918af48 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/mjpeg_logging.h @@ -0,0 +1,77 @@ +/* + $Id: mjpeg_logging.h,v 1.11 2007/04/01 18:06:06 sms00 Exp $ + + Copyright (C) 2000 Herbert Valerio Riedel + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __MJPEG_LOGGING_H__ +#define __MJPEG_LOGGING_H__ + +#include + +/* to avoid changing all the places log_level_t is used */ +typedef int log_level_t; + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((format (printf, format_idx, arg_idx))) +#else /* !__GNUC__ */ +#define GNUC_PRINTF( format_idx, arg_idx ) +#endif /* !__GNUC__ */ + +#ifdef __cplusplus +extern "C" { +#endif +void +mjpeg_log(log_level_t level, const char format[], ...) GNUC_PRINTF(2, 3); + +typedef int(*mjpeg_log_filter_t)(log_level_t level); + +typedef void(*mjpeg_log_handler_t)(log_level_t level, const char message[]); + +mjpeg_log_handler_t +mjpeg_log_set_handler(mjpeg_log_handler_t new_handler); + +int +mjpeg_default_handler_identifier(const char *new_id); + +int +mjpeg_default_handler_verbosity(int verbosity); + +void +mjpeg_debug(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_info(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_warn(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_error(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_error_exit1(const char format[], ...) GNUC_PRINTF(1,2); + +log_level_t +mjpeg_loglev_t(const char *str); + +#ifdef __cplusplus +} +#endif + +#endif /* __MJPEG_LOGGING_H__ */ diff --git a/branches/V-1.5.3/veejay-client/src/mjpeg_types.h b/branches/V-1.5.3/veejay-client/src/mjpeg_types.h new file mode 100644 index 00000000..88b461c1 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/mjpeg_types.h @@ -0,0 +1,28 @@ +/* + $Id: mjpeg_types.h,v 1.16 2006/05/18 18:19:05 sms00 Exp $ + + Copyright (C) 2000 Herbert Valerio Riedel + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __MJPEG_TYPES_H__ +#define __MJPEG_TYPES_H__ + +#include /* FreeBSD, others - ssize_t */ +#include +#include + +#endif /* __MJPEG_TYPES_H__ */ diff --git a/branches/V-1.5.3/veejay-client/src/mpegconsts.c b/branches/V-1.5.3/veejay-client/src/mpegconsts.c new file mode 100644 index 00000000..43072156 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/mpegconsts.c @@ -0,0 +1,512 @@ + +/* + * mpegconsts.c: Video format constants for MPEG and utilities for display + * and conversion to format used for yuv4mpeg + * + * Copyright (C) 2001 Andrew Stevens + * Copyright (C) 2001 Matthew Marjanovic + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "mpegconsts.h" +#include "yuv4mpeg.h" +#include "yuv4mpeg_intern.h" +#include "format_codes.h" + +static y4m_ratio_t +mpeg_framerates[] = { + Y4M_FPS_UNKNOWN, + Y4M_FPS_NTSC_FILM, + Y4M_FPS_FILM, + Y4M_FPS_PAL, + Y4M_FPS_NTSC, + Y4M_FPS_30, + Y4M_FPS_PAL_FIELD, + Y4M_FPS_NTSC_FIELD, + Y4M_FPS_60 +}; + + +#define MPEG_NUM_RATES (sizeof(mpeg_framerates)/sizeof(mpeg_framerates[0])) +static const mpeg_framerate_code_t mpeg_num_framerates = MPEG_NUM_RATES; + +static const char * +framerate_definitions[MPEG_NUM_RATES] = +{ + "illegal", + "24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)", + "24.0 (NATIVE FILM)", + "25.0 (PAL/SECAM VIDEO / converted FILM)", + "30000.0/1001.0 (NTSC VIDEO)", + "30.0", + "50.0 (PAL FIELD RATE)", + "60000.0/1001.0 (NTSC FIELD RATE)", + "60.0" +}; + + +static const char *mpeg1_aspect_ratio_definitions[] = +{ + "illegal", + "1:1 (square pixels)", + "1:0.6735", + "1:0.7031 (16:9 Anamorphic PAL/SECAM for 720x578/352x288 images)", + "1:0.7615", + "1:0.8055", + "1:0.8437 (16:9 Anamorphic NTSC for 720x480/352x240 images)", + "1:0.8935", + "1:0.9375 (4:3 PAL/SECAM for 720x578/352x288 images)", + "1:0.9815", + "1:1.0255", + "1:1:0695", + "1:1.1250 (4:3 NTSC for 720x480/352x240 images)", + "1:1.1575", + "1:1.2015" +}; + +static const y4m_ratio_t mpeg1_aspect_ratios[] = +{ + Y4M_SAR_UNKNOWN, + Y4M_SAR_MPEG1_1, + Y4M_SAR_MPEG1_2, + Y4M_SAR_MPEG1_3, /* Anamorphic 16:9 PAL */ + Y4M_SAR_MPEG1_4, + Y4M_SAR_MPEG1_5, + Y4M_SAR_MPEG1_6, /* Anamorphic 16:9 NTSC */ + Y4M_SAR_MPEG1_7, + Y4M_SAR_MPEG1_8, /* PAL/SECAM 4:3 */ + Y4M_SAR_MPEG1_9, + Y4M_SAR_MPEG1_10, + Y4M_SAR_MPEG1_11, + Y4M_SAR_MPEG1_12, /* NTSC 4:3 */ + Y4M_SAR_MPEG1_13, + Y4M_SAR_MPEG1_14, +}; + +static const char *mpeg2_aspect_ratio_definitions[] = +{ + "illegal", + "1:1 pixels", + "4:3 display", + "16:9 display", + "2.21:1 display" +}; + + +static const y4m_ratio_t mpeg2_aspect_ratios[] = +{ + Y4M_DAR_UNKNOWN, + Y4M_DAR_MPEG2_1, + Y4M_DAR_MPEG2_2, + Y4M_DAR_MPEG2_3, + Y4M_DAR_MPEG2_4 +}; + +static const char **aspect_ratio_definitions[2] = +{ + mpeg1_aspect_ratio_definitions, + mpeg2_aspect_ratio_definitions +}; + +static const y4m_ratio_t *mpeg_aspect_ratios[2] = +{ + mpeg1_aspect_ratios, + mpeg2_aspect_ratios +}; + +static const mpeg_aspect_code_t mpeg_num_aspect_ratios[2] = +{ + sizeof(mpeg1_aspect_ratios)/sizeof(mpeg1_aspect_ratios[0]), + sizeof(mpeg2_aspect_ratios)/sizeof(mpeg2_aspect_ratios[0]) +}; + +static const char *mjpegtools_format_code_definitions[MPEG_FORMAT_LAST+1] = +{ + "Generic MPEG1", + "Standard VCD", + "Stretched VCD", + "Generic MPEG2", + "Standard SVCD", + "Stretched SVCD", + "VCD Still", + "SVCD Still", + "DVD with dummy navigation packets", + "Standard DVD", + "ATSC 480i", + "ATSC 480p", + "ATSC 720p", + "ATSC 1080i" +}; + +/* + * Is code a valid MPEG framerate code? + */ + +int +mpeg_valid_framerate_code( mpeg_framerate_code_t code ) +{ + return ((code > 0) && (code < mpeg_num_framerates)) ? 1 : 0; +} + + +/* + * Convert MPEG frame-rate code to corresponding frame-rate + */ + +y4m_ratio_t +mpeg_framerate( mpeg_framerate_code_t code ) +{ + if ((code > 0) && (code < mpeg_num_framerates)) + return mpeg_framerates[code]; + else + return y4m_fps_UNKNOWN; +} + +/* + * Look-up MPEG frame rate code for a (exact) frame rate. + */ + + +mpeg_framerate_code_t +mpeg_framerate_code( y4m_ratio_t framerate ) +{ + mpeg_framerate_code_t i; + + y4m_ratio_reduce(&framerate); + /* start at '1', because 0 is unknown/illegal */ + for (i = 1; i < mpeg_num_framerates; ++i) { + if (Y4M_RATIO_EQL(framerate, mpeg_framerates[i])) + return i; + } + return 0; +} + + +/* small enough to distinguish 1/1000 from 1/1001 */ +#define MPEG_FPS_TOLERANCE 0.0001 + +y4m_ratio_t +mpeg_conform_framerate( double fps ) +{ + mpeg_framerate_code_t i; + y4m_ratio_t result; + + /* try to match it to a standard frame rate */ + /* (start at '1', because 0 is unknown/illegal) */ + for (i = 1; i < mpeg_num_framerates; i++) + { + double deviation = 1.0 - (Y4M_RATIO_DBL(mpeg_framerates[i]) / fps); + if ( (deviation > -MPEG_FPS_TOLERANCE) && + (deviation < +MPEG_FPS_TOLERANCE) ) + return mpeg_framerates[i]; + } + /* no luck? just turn it into a ratio (8 decimal place accuracy) */ + result.n = (int)((fps * 100000000.0) + 0.5); + result.d = 100000000; + y4m_ratio_reduce(&result); + return result; +} + + + +/* + * Is code a valid MPEG aspect-ratio code? + */ + +int +mpeg_valid_aspect_code( int version, mpeg_framerate_code_t c ) +{ + if ((version == 1) || (version == 2)) + return ((c > 0) && (c < mpeg_num_aspect_ratios[version-1])) ? 1 : 0; + else + return 0; +} + + +/* + * Convert MPEG aspect-ratio code to corresponding aspect-ratio + */ + +y4m_ratio_t +mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code ) +{ + y4m_ratio_t ratio; + if ((mpeg_version >= 1) && (mpeg_version <= 2) && + (code > 0) && (code < mpeg_num_aspect_ratios[mpeg_version-1])) + { + ratio = mpeg_aspect_ratios[mpeg_version-1][code]; + y4m_ratio_reduce(&ratio); + return ratio; + } + else + return y4m_sar_UNKNOWN; +} + + + +/* + * Look-up corresponding MPEG aspect ratio code given an exact aspect ratio. + * + * WARNING: The semantics of aspect ratio coding *changed* between + * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In + * MPEG2 it is the (far more sensible) aspect ratio of the eventual + * display. + * + */ + +mpeg_aspect_code_t +mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio ) +{ + mpeg_aspect_code_t i; + y4m_ratio_t red_ratio = aspect_ratio; + y4m_ratio_reduce( &red_ratio ); + if( mpeg_version < 1 || mpeg_version > 2 ) + return 0; + /* (start at '1', because 0 is unknown/illegal) */ + for( i = 1; i < mpeg_num_aspect_ratios[mpeg_version-1]; ++i ) + { + y4m_ratio_t red_entry = mpeg_aspect_ratios[mpeg_version-1][i]; + y4m_ratio_reduce( &red_entry ); + if( Y4M_RATIO_EQL( red_entry, red_ratio) ) + return i; + } + + return 0; + +} + + + +/* + * Guess the correct MPEG aspect ratio code, + * given the true sample aspect ratio and frame size of a video stream + * (and the MPEG version, 1 or 2). + * + * Returns 0 if it has no good guess. + * + */ + + +/* this is big enough to accommodate the difference between 720 and 704 */ +#define GUESS_ASPECT_TOLERANCE 0.03 + +mpeg_aspect_code_t +mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect, + int frame_width, int frame_height) +{ + if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_UNKNOWN)) + { + return 0; + } + switch (mpeg_version) { + case 1: + if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE)) + { + return 1; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_CCIR601)) + { + return 12; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_16_9)) + { + return 6; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_CCIR601)) + { + return 8; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_16_9)) + { + return 3; + } + return 0; + break; + case 2: + if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE)) + { + return 1; /* '1' means square *pixels* in MPEG-2; go figure. */ + } + else + { + int i; + double true_far; /* true frame aspect ratio */ + true_far = + (double)(sampleaspect.n * frame_width) / + (double)(sampleaspect.d * frame_height); + /* start at '2'... */ + for (i = 2; i < (int)(mpeg_num_aspect_ratios[mpeg_version-1]); i++) + { + double ratio = + true_far / Y4M_RATIO_DBL(mpeg_aspect_ratios[mpeg_version-1][i]); + if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && + (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) ) + return i; + } + return 0; + } + break; + default: + return 0; + break; + } +} + + + + +/* + * Guess the true sample aspect ratio of a video stream, + * given the MPEG aspect ratio code and the actual frame size + * (and the MPEG version, 1 or 2). + * + * Returns y4m_sar_UNKNOWN if it has no good guess. + * + */ +y4m_ratio_t +mpeg_guess_sample_aspect_ratio(int mpeg_version, + mpeg_aspect_code_t code, + int frame_width, int frame_height) +{ + switch (mpeg_version) + { + case 1: + /* MPEG-1 codes turn into SAR's, just not quite the right ones. + For the common/known values, we provide the ratio used in practice, + otherwise say we don't know.*/ + switch (code) + { + case 1: return y4m_sar_SQUARE; break; + case 3: return y4m_sar_PAL_16_9; break; + case 6: return y4m_sar_NTSC_16_9; break; + case 8: return y4m_sar_PAL_CCIR601; break; + case 12: return y4m_sar_NTSC_CCIR601; break; + default: + return y4m_sar_UNKNOWN; break; + } + break; + case 2: + /* MPEG-2 codes turn into Display Aspect Ratios, though not exactly the + DAR's used in practice. For common/standard frame sizes, we provide + the original SAR; otherwise, we say we don't know. */ + if (code == 1) + { + return y4m_sar_SQUARE; /* '1' means square *pixels* in MPEG-2 */ + } + else if ((code >= 2) && (code <= 4)) + { + return y4m_guess_sar(frame_width, frame_height, + mpeg2_aspect_ratios[code]); + } + else + { + return y4m_sar_UNKNOWN; + } + break; + default: + return y4m_sar_UNKNOWN; + break; + } +} + + + + + +/* + * Look-up MPEG explanatory definition string for frame rate code + * + */ + + +const char * +mpeg_framerate_code_definition( mpeg_framerate_code_t code ) +{ + if( code == 0 || code >= mpeg_num_framerates ) + return "UNDEFINED: illegal/reserved frame-rate ratio code"; + + return framerate_definitions[code]; +} + +/* + * Look-up MPEG explanatory definition string aspect ratio code for an + * aspect ratio code + * + */ + +const char * +mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code ) +{ + if( mpeg_version < 1 || mpeg_version > 2 ) + return "UNDEFINED: illegal MPEG version"; + + if( code < 1 || code >= mpeg_num_aspect_ratios[mpeg_version-1] ) + return "UNDEFINED: illegal aspect ratio code"; + + return aspect_ratio_definitions[mpeg_version-1][code]; +} + + +/* + * Look-up explanatory definition of interlace field order code + * + */ + +const char * +mpeg_interlace_code_definition( int yuv4m_interlace_code ) +{ + const char *def; + switch( yuv4m_interlace_code ) + { + case Y4M_UNKNOWN : + def = "unknown"; + break; + case Y4M_ILACE_NONE : + def = "none/progressive"; + break; + case Y4M_ILACE_TOP_FIRST : + def = "top-field-first"; + break; + case Y4M_ILACE_BOTTOM_FIRST : + def = "bottom-field-first"; + break; + default : + def = "UNDEFINED: illegal video interlacing type-code!"; + break; + } + return def; +} + +/* + * Look-up explanatory definition of mjepgtools preset format code + * + */ +const char *mpeg_format_code_defintion( int format_code ) +{ + if(format_code >= MPEG_FORMAT_FIRST && format_code <= MPEG_FORMAT_LAST ) + return mjpegtools_format_code_definitions[format_code]; + else + return "UNDEFINED: illegal format code!"; +}; + +/* + * Local variables: + * c-file-style: "stroustrup" + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/branches/V-1.5.3/veejay-client/src/mpegconsts.h b/branches/V-1.5.3/veejay-client/src/mpegconsts.h new file mode 100644 index 00000000..3e9543d1 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/mpegconsts.h @@ -0,0 +1,170 @@ + +/* + * mpegconsts.c: Video format constants for MPEG and utilities for display + * and conversion to format used for yuv4mpeg + * + * Copyright (C) 2001 Andrew Stevens + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __MPEGCONSTS_H__ +#define __MPEGCONSTS_H__ + +#include + +typedef unsigned int mpeg_framerate_code_t; +typedef unsigned int mpeg_aspect_code_t; + +#ifdef __cplusplus +#define START_CPP_WRAP extern "C" { +#define END_CPP_WRAP }; +#else +#define START_CPP_WRAP +#define END_CPP_WRAP +#endif + +START_CPP_WRAP + + +/* + * Convert MPEG frame-rate code to corresponding frame-rate + * y4m_fps_UNKNOWN = { 0, 0 } = Undefined/resrerved code. + */ + +y4m_ratio_t +mpeg_framerate( mpeg_framerate_code_t code ); + + +/* + * Is code a valid MPEG frame-rate code? + * Return 1 if true; 0 otherwise. + */ + +int +mpeg_valid_framerate_code( mpeg_framerate_code_t code ); + + +/* + * Look-up MPEG frame rate code for a (exact) frame rate. + * 0 = No MPEG code defined for frame-rate + */ + +mpeg_framerate_code_t +mpeg_framerate_code( y4m_ratio_t framerate ); + + +/* + * Convert floating-point framerate to an exact ratio. + * Uses a standard MPEG rate, if it finds one within MPEG_FPS_TOLERANCE + * (see mpegconsts.c), otherwise uses "fps:1000000" as the ratio. + */ + +y4m_ratio_t +mpeg_conform_framerate( double fps ); + +/* + * Convert MPEG aspect ratio code to corresponding aspect ratio + * + * WARNING: The semantics of aspect ratio coding *changed* between + * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In + * MPEG2 it is the (far more sensible) aspect ratio of the eventual + * display. + * + */ + +y4m_ratio_t +mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code ); + + +/* + * Is code a valid MPEG(1,2) aspect-ratio code? + * Return 1 if true; 0 otherwise. + */ + +int +mpeg_valid_aspect_code( int mpeg_version, mpeg_aspect_code_t code ); + + +/* + * Look-up MPEG aspect ratio code for an aspect ratio - tolerance + * is Y4M_ASPECT_MULT used by YUV4MPEG (see yuv4mpeg_intern.h) + * + * WARNING: The semantics of aspect ratio coding *changed* between + * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In + * MPEG2 it is the (far more sensible) aspect ratio of the eventual + * display. + * + */ + +mpeg_aspect_code_t +mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio ); + +/* + * Look-up MPEG explanatory definition string aspect ratio code for an + * aspect ratio code + * + */ + +const char * +mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code ); + +/* + * Look-up MPEG explanatory definition string aspect ratio code for an + * frame rate code + * + */ + +const char * +mpeg_framerate_code_definition( mpeg_framerate_code_t code ); + +const char * +mpeg_interlace_code_definition( int yuv4m_interlace_code ); + + +/* + * Guess the correct MPEG aspect ratio code, + * given the true sample aspect ratio and frame size of a video stream + * (and the MPEG version, 1 or 2). + * + * Returns 0 if it has no good answer. + * + */ +mpeg_aspect_code_t +mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect, + int frame_width, int frame_height); + +/* + * Guess the true sample aspect ratio of a video stream, + * given the MPEG aspect ratio code and the actual frame size + * (and the MPEG version, 1 or 2). + * + * Returns y4m_sar_UNKNOWN if it has no good answer. + * + */ +y4m_ratio_t +mpeg_guess_sample_aspect_ratio(int mpeg_version, + mpeg_aspect_code_t code, + int frame_width, int frame_height); + +/* + * Look-up MJPEGTOOLS MPEG preset format code explanatory definition string a + * + */ +const char *mpeg_format_code_defintion( int format_code ); + +END_CPP_WRAP + +#endif /* __MPEGCONSTS_H__ */ diff --git a/branches/V-1.5.3/veejay-client/src/mpegtimecode.c b/branches/V-1.5.3/veejay-client/src/mpegtimecode.c new file mode 100644 index 00000000..09986739 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/mpegtimecode.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2001 Kawamata/Hitoshi + * + * 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 "mpegtimecode.h" + +/************************************************************** + * // NTSC DROP FRAME TIMECODE / 29.97fps (SMTPE) + * // hh:mm:ss:ff + * // hh: 0.. + * // mm: 0..59 + * // ss: 0..59 + * // ff: 0..29 # ss != 0 || mm % 10 == 0 + * // 2..29 # ss == 0 && mm % 10 != 0 + * // + * // 00:00:00:00 00:00:00:01 00:00:00:02 ... 00:00:00:29 + * // 00:00:01:00 00:00:01:01 00:00:01:02 ... 00:00:01:29 + * // : + * // 00:00:59:00 00:00:59:01 00:00:59:02 ... 00:00:59:29 + * // 00:01:00:02 ... 00:01:00:29 + * // 00:01:01:00 00:01:01:01 00:01:01:02 ... 00:01:00:29 + * // : + * // 00:01:59:00 00:01:59:01 00:01:59:02 ... 00:01:59:29 + * // 00:02:00:02 ... 00:02:00:29 + * // 00:02:01:00 00:02:01:01 00:02:01:02 ... 00:02:00:29 + * // : + * // : + * // 00:09:59:00 00:09:59:01 00:09:59:02 ... 00:09:59:29 + * // 00:10:00:00 00:10:00:01 00:10:00:02 ... 00:10:00:29 + * // 00:10:01:00 00:10:01:01 00:10:01:02 ... 00:10:01:29 + * // : + * // 00:10:59:00 00:10:59:01 00:10:59:02 ... 00:10:59:29 + * // 00:11:00:02 ... 00:11:00:29 + * // 00:11:01:00 00:11:01:01 00:11:01:02 ... 00:11:00:29 + * // : + * // : + * // DROP FRAME / 59.94fps (no any standard) + * // DROP FRAME / 23.976fps (no any standard) + ***************************************************************/ + +int dropframetimecode = -1; + +/* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */ +int +mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps) +{ + static const int ifpss[] = { 0, 24, 24, 25, 30, 30, 50, 60, 60, }; + int h, m, s; + + if (dropframetimecode < 0) { + char *env = getenv("MJPEG_DROP_FRAME_TIME_CODE"); + dropframetimecode = (env && *env != '0' && *env != 'n' && *env != 'N'); + } + if (dropframetimecode && + 0 < fpscode && fpscode + 1 < sizeof ifpss / sizeof ifpss[0] && + ifpss[fpscode] == ifpss[fpscode + 1]) { + int topinmin = 0, k = (30*4) / ifpss[fpscode]; + f *= k; /* frame# when 119.88fps */ + h = (f / ((10*60*30-18)*4)); /* # of 10min. */ + f %= ((10*60*30-18)*4); /* frame# in 10min. */ + f -= (2*4); /* frame# in 10min. - (2*4) */ + m = (f / ((60*30-2)*4)); /* min. in 10min. */ + topinmin = ((f - k) / ((60*30-2)*4) < m); + m += (h % 6 * 10); /* min. */ + h /= 6; /* hour */ + f %= ((60*30-2)*4); /* frame# in min. - (2*4)*/ + f += (2*4); /* frame# in min. */ + s = f / (30*4); /* sec. */ + f %= (30*4); /* frame# in sec. */ + f /= k; /* frame# in sec. on original fps */ + tc->f = f; + if (topinmin) + f = -f; + } else { + int ifps = ((0 < fpscode && fpscode < sizeof ifpss / sizeof ifpss[0])? + ifpss[fpscode]: (int)(fps + .5)); + s = f / ifps; + f %= ifps; + m = s / 60; + s %= 60; + h = m / 60; + m %= 60; + tc->f = f; + } + tc->s = s; + tc->m = m; + tc->h = h; + return f; +} diff --git a/branches/V-1.5.3/veejay-client/src/mpegtimecode.h b/branches/V-1.5.3/veejay-client/src/mpegtimecode.h new file mode 100644 index 00000000..e702a9b7 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/mpegtimecode.h @@ -0,0 +1,39 @@ +/* -*- mode:C -*- */ +/* + * Copyright (C) 2001 Kawamata/Hitoshi + * + * 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. + */ + +#ifndef __MPEGTIMECODE_H__ +#define __MPEGTIMECODE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char h, m, s, f; +} MPEG_timecode_t; + +extern int dropframetimecode; +extern int mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps); +/* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/branches/V-1.5.3/veejay-client/src/multitrack.c b/branches/V-1.5.3/veejay-client/src/multitrack.c new file mode 100644 index 00000000..38244da4 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/multitrack.c @@ -0,0 +1,1141 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2006 Niels Elburg + * + * + * 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 +#include +#include "sequence.h" +#include "tracksources.h" + +#define SEQ_BUTTON_CLOSE 0 +#define SEQ_BUTTON_RULE 1 + +#ifdef STRICT_CHECKING +#include +#endif +#include +#include +#include +#include +#include +#define __MAX_TRACKS 64 +typedef struct +{ + GtkWidget *event_box; + GtkWidget *frame; + GtkWidget *main_vbox; + GtkWidget *panel; + GtkWidget *hbox; + GtkWidget *area; + GtkWidget *sub_frame; + GtkWidget *sub_hbox; + GtkWidget *toggle; + GtkWidget *buttons[8]; + GtkWidget *icons[8]; + GtkWidget *button_box; + GtkWidget *timeline_; + GtkWidget *labels_[4]; + GtkWidget *sliders_[4]; + GtkWidget *button_box2; + GtkWidget *buttons2[8]; + void *tracks; + gint dim[2]; + int num; + int status_lock; + void *backlink; + int status_cache[32]; + int history[4][32]; +} sequence_view_t; + +typedef struct +{ + sequence_view_t **view; + void *preview; + GtkWidget *main_window; + GtkWidget *main_box; + GtkWidget *status_bar; + GtkWidget *scroll; + void *data; + int selected; + int sensitive; + float fps; + float aspect_ratio; + int width; + int height; + int master_track; + GdkPixbuf *logo; + GtkWidget *preview_toggle; + int pw; + int ph; +} multitracker_t; + +static volatile int MAX_TRACKS = 2; +static void *parent__ = NULL; + +static int mt_new_connection_dialog(multitracker_t *mt, char *hostname,int len, int *port_num); +static void add_buttons( sequence_view_t *p, sequence_view_t *seqv , GtkWidget *w); +static void add_buttons2( sequence_view_t *p, sequence_view_t *seqv , GtkWidget *w); +static sequence_view_t *new_sequence_view( void *vp, int num ); +static void update_pos( void *data, gint total, gint current ); +static gboolean seqv_mouse_press_event ( GtkWidget *w, GdkEventButton *event, gpointer user_data); + + +extern GdkPixbuf *vj_gdk_pixbuf_scale_simple( GdkPixbuf *src, int dw, int dh, GdkInterpType inter_type ); +extern void gtk_widget_set_size_request__( GtkWidget *w, gint iw, gint h, const char *f, int line ); + +#ifndef STRICT_CHECKING +#define gtk_widget_set_size_request_(a,b,c) gtk_widget_set_size_request(a,b,c) +#else +#define gtk_widget_set_size_request_(a,b,c) gtk_widget_set_size_request__(a,b,c,__FUNCTION__,__LINE__) +#endif + +int mt_get_max_tracks() +{ + return __MAX_TRACKS; +} + + + +static void gtk_image_set_from_pixbuf__( GtkImage *w, GdkPixbuf *p, const char *f, int l ) +{ + gtk_image_set_from_pixbuf(w, p); +} + + +static void gtk_widget_set_sensitive__( GtkWidget *w, gboolean state, const char *f, int l ) +{ +#ifdef STRICT_CHECKING + if( !GTK_IS_WIDGET(w) ) + veejay_msg(0, "Invalid widget '%s', %d", f, l ); + assert( GTK_IS_WIDGET(w) ); +#endif + gtk_widget_set_sensitive(w, state ); +} + +#ifdef STRICT_CHECKING +#define gtk_image_set_from_pixbuf_(w,p) gtk_image_set_from_pixbuf__( w,p, __FUNCTION__,__LINE__ ); +#define gtk_widget_set_sensitive_( w,p ) gtk_widget_set_sensitive__( w,p,__FUNCTION__,__LINE__ ) +#else +#define gtk_image_set_from_pixbuf_(w,p) gtk_image_set_from_pixbuf(w,p) +#define gtk_widget_set_sensitive_( w,p ) gtk_widget_set_sensitive(w,p) +#endif +static void status_print(multitracker_t *mt, const char format[], ... ) +{ + char buf[1024]; + va_list args; + va_start(args,format); + vsnprintf( buf,sizeof(buf), format, args ); + gsize nr,nw; + gchar *text = g_locale_to_utf8( buf, -1, &nr, &nw, NULL ); + text[strlen(text)-1] = '\0'; + gtk_statusbar_push( GTK_STATUSBAR(mt->status_bar), 0, text); + g_free(text); + va_end(args); +} + +static GdkPixbuf *load_logo_image(int dw, int dh ) +{ + char path[1024]; + veejay_memset(path,0,sizeof(path)); + get_gd(path,NULL, "veejay-logo.png"); + return gdk_pixbuf_new_from_file( path,NULL ); +} + +int multitrack_get_sequence_view_id( void *data ) +{ + sequence_view_t *s = (sequence_view_t*) data; + return s->num; +} + +void multitrack_sync_start(void *data) +{ + multitracker_t *mt = (multitracker_t*)data; + gvr_queue_vims( mt->preview,-1,VIMS_VIDEO_PLAY_STOP ); + gvr_queue_vims( mt->preview,-1,VIMS_VIDEO_GOTO_START ); + gvr_queue_vims( mt->preview,-1,VIMS_VIDEO_PLAY_FORWARD ); +} + +void multitrack_sync_simple_cmd( void *data, int vims, int arg ) +{ + multitracker_t *mt = (multitracker_t*)data; + gvr_queue_vims(mt->preview,-1, vims); +} + +void multitrack_sync_simple_cmd2( void *data, int vims, int arg ) +{ + multitracker_t *mt = (multitracker_t*)data; + gvr_queue_mvims(mt->preview,-1, vims, arg); +} + + +static void seq_gotostart(GtkWidget *w, gpointer data ) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gvr_queue_vims( mt->preview, v->num ,VIMS_VIDEO_GOTO_START ); +} + +static void seq_reverse(GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gvr_queue_vims( mt->preview, v->num ,VIMS_VIDEO_PLAY_BACKWARD ); +} + +static void seq_pause(GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gvr_queue_vims( mt->preview, v->num ,VIMS_VIDEO_PLAY_STOP ); +} + +static void seq_play( GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gvr_queue_vims( mt->preview, v->num ,VIMS_VIDEO_PLAY_FORWARD ); +} + +static void seq_gotoend(GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gvr_queue_vims( mt->preview, v->num ,VIMS_VIDEO_GOTO_END ); +} + +static void seq_speeddown(GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gint n = v->status_cache[ SAMPLE_SPEED ]; + + if( n < 0 ) n += 1; + if( n > 0 ) n -= 1; + gvr_queue_mvims( mt->preview, v->num ,VIMS_VIDEO_SET_SPEED , n ); +} + +static void seq_speedup(GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gint n = v->status_cache[ SAMPLE_SPEED ]; + + if( n < 0 ) n -= 1; + if( n > 0 ) n += 1; + gvr_queue_mvims( mt->preview, v->num ,VIMS_VIDEO_SET_SPEED , n ); +} + +static void seq_prevframe(GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gvr_queue_vims( mt->preview, v->num ,VIMS_VIDEO_PREV_FRAME ); + +} + +static void seq_nextframe(GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = (multitracker_t*)v->backlink; + + gvr_queue_vims( mt->preview, v->num ,VIMS_VIDEO_SKIP_FRAME ); +} + +static void seq_speed( GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = v->backlink; + if(v->status_lock) + return; + gdouble value = GTK_ADJUSTMENT( GTK_RANGE(w)->adjustment )->value; + gint speed = (gint) value; + gvr_queue_mvims( mt->preview, v->num ,VIMS_VIDEO_SET_SPEED , speed ); +} + +static void seq_opacity( GtkWidget *w, gpointer data) +{ + sequence_view_t *v = (sequence_view_t*) data; + multitracker_t *mt = v->backlink; + + if(v->status_lock) + return; + + gdouble value = GTK_ADJUSTMENT( GTK_RANGE(w)->adjustment )->value; + gint opacity = (gint)( value * 255.0); + gvr_queue_mmvims( mt->preview, v->num ,VIMS_CHAIN_MANUAL_FADE, 0, opacity ); +} + + +static void update_pos( void *user_data, gint total, gint current ) +{ + sequence_view_t *v = (sequence_view_t*) user_data; + multitracker_t *mt = v->backlink; + if(v->status_lock) + return; + + gtk_adjustment_set_value( + GTK_ADJUSTMENT(GTK_RANGE(v->timeline_)->adjustment), 1.0 / (gdouble) total * current ); + + gchar *now = format_time( current , mt->fps); + gtk_label_set_text( GTK_LABEL(v->labels_[0]), now ); + g_free(now); +} + +static void update_speed( void *user_data, gint speed ) +{ + sequence_view_t *v = (sequence_view_t*) user_data; + if(v->status_lock) + return; + + gtk_adjustment_set_value( GTK_ADJUSTMENT( GTK_RANGE( v->sliders_[0] )->adjustment), (gdouble) speed ); +} + +#define FIRST_ROW_END 5 +static struct +{ + const char *name; + int vims_id; + const char *file; + void (*f)(); +} button_template_t[] = +{ + { "button_gotostart", VIMS_VIDEO_GOTO_START, "button_gotostart.png", seq_gotostart }, + { "button_reverse", VIMS_VIDEO_PLAY_BACKWARD, "button_reverse.png" , seq_reverse }, + { "button_pauseplay", VIMS_VIDEO_PLAY_STOP, "button_pause.png", seq_pause}, + { "button_play", VIMS_VIDEO_PLAY_FORWARD, "button_play.png", seq_play }, + { "button_gotoend", VIMS_VIDEO_GOTO_END, "button_gotoend.png",seq_gotoend }, + + { "button_speeddown", VIMS_VIDEO_SET_SPEED, "button_down.png", seq_speeddown }, + { "button_speedup", VIMS_VIDEO_SET_SPEED, "button_up.png", seq_speedup }, + { "button_prevframe", VIMS_VIDEO_PREV_FRAME, "button_prev.png", seq_prevframe }, + { "button_nextframe", VIMS_VIDEO_SKIP_FRAME, "button_skip.png", seq_nextframe }, + { NULL , 0 , NULL }, +}; + +static void add_buttons( sequence_view_t *p, sequence_view_t *seqv , GtkWidget *w) +{ + int i; + for( i = 0; i < FIRST_ROW_END;i ++ ) + { + char path[1024]; + veejay_memset(path,0,sizeof(path)); + get_gd(path,NULL, button_template_t[i].file ); + seqv->icons[i] = gtk_image_new_from_file( path ); + seqv->buttons[i] = gtk_button_new_with_label(" "); + gtk_widget_set_size_request_( seqv->icons[i],24,20 ); + gtk_button_set_image( GTK_BUTTON(seqv->buttons[i]), seqv->icons[i] ); + gtk_widget_set_size_request_( seqv->buttons[i],24,20 ); + gtk_box_pack_start( GTK_BOX(w), seqv->buttons[i], TRUE,TRUE, 0 ); + g_signal_connect( G_OBJECT( seqv->buttons[i] ), "clicked", G_CALLBACK( button_template_t[i].f), + (gpointer)p ); + gtk_widget_show( seqv->buttons[i] ); + + } +} + +static void add_buttons2( sequence_view_t *p, sequence_view_t *seqv , GtkWidget *w) +{ + int i; + for( i = FIRST_ROW_END; button_template_t[i].name != NULL ;i ++ ) + { + char path[1024]; + veejay_memset(path,0,sizeof(path)); + get_gd(path,NULL, button_template_t[i].file ); + seqv->icons[i] = gtk_image_new_from_file( path ); + seqv->buttons2[i] = gtk_button_new_with_label(" "); + gtk_widget_set_size_request_( seqv->icons[i],24,20 ); + + gtk_button_set_image( GTK_BUTTON(seqv->buttons2[i]), seqv->icons[i] ); + gtk_widget_set_size_request_( seqv->buttons2[i],24,20 ); + gtk_box_pack_start( GTK_BOX(w), seqv->buttons2[i], TRUE,TRUE, 0 ); + g_signal_connect( G_OBJECT( seqv->buttons2[i] ), "clicked", G_CALLBACK( button_template_t[i].f), + (gpointer*)p ); + gtk_widget_show( seqv->buttons2[i] ); + + } +} + + + +static void playmode_sensitivity( sequence_view_t *p, gint pm ) +{ + int i; +#ifdef STRICT_CHECKING + assert( p != NULL ); +#endif + if( pm == MODE_STREAM || MODE_PLAIN || MODE_SAMPLE ) + { + if(p->num > 0) + gtk_widget_set_sensitive_( GTK_WIDGET( p->toggle ), TRUE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->panel ), TRUE ); + + } + + if( pm == MODE_STREAM ) + { + gtk_widget_set_sensitive_( GTK_WIDGET( p->button_box2 ), FALSE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->button_box ), FALSE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->sliders_[0] ), FALSE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->timeline_ ), FALSE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->sliders_[1] ), TRUE ); + for( i = 0; i < FIRST_ROW_END;i ++ ) + { + gtk_widget_set_sensitive_( GTK_WIDGET( p->buttons[i] ), FALSE ); + + } + } + else + { + if( pm == MODE_SAMPLE || pm == MODE_PLAIN ) + { + gtk_widget_set_sensitive_( GTK_WIDGET( p->button_box2 ), TRUE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->button_box ), TRUE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->sliders_[0] ), TRUE ); + gtk_widget_set_sensitive_( GTK_WIDGET( p->timeline_ ), TRUE ); + for( i = 0; i < FIRST_ROW_END;i ++ ) + { + gtk_widget_set_sensitive_( GTK_WIDGET( p->buttons[i] ), TRUE ); + } + + } + if( pm == MODE_SAMPLE ) + gtk_widget_set_sensitive_( GTK_WIDGET( p->sliders_[1] ), TRUE ); + else + gtk_widget_set_sensitive_( GTK_WIDGET( p->sliders_[1] ), FALSE ); + } +} + + +static void update_widgets(int *status, sequence_view_t *p, int pm) +{ + multitracker_t *mt = (multitracker_t*) p->backlink; + int *h = p->history[pm]; + if( h[PLAY_MODE] != pm ) + playmode_sensitivity( p, pm ); + + if( pm == MODE_STREAM ) + { + update_pos( p, status[TOTAL_FRAMES], 0 ); + update_speed( p, 1 ); + } + else + if( pm == MODE_SAMPLE || pm == MODE_PLAIN ) + { + if( h[FRAME_NUM] != status[FRAME_NUM] ) + update_pos( p, status[TOTAL_FRAMES],status[FRAME_NUM] ); + if( h[SAMPLE_SPEED] != status[SAMPLE_SPEED] ) + update_speed( p, status[SAMPLE_SPEED] ); + } + + if( h[TOTAL_SLOTS] != status[TOTAL_SLOTS]) + { + gvr_need_track_list( mt->preview, p->num ); + update_track_view( MAX_TRACKS, get_track_tree( p->tracks ), (void*)p ); + } +} + + +int update_multitrack_widgets( void *data, int *array, int track ) +{ + multitracker_t *mt = (multitracker_t*) data; + sequence_view_t *p = mt->view[ track ]; + + p->status_lock = 1; + int pm = array[PLAY_MODE]; + int i; + for( i = 0; i < 20; i ++ ) + p->status_cache[i] = array[i]; + update_widgets(array, p, pm); + + int *his = p->history[ pm ]; + for( i = 0; i < 20; i ++ ) + his[i] = array[i]; + p->status_lock = 0; + return 1; +} + +static void sequence_preview_size(multitracker_t *mt, int track_num) +{ + float ratio = mt->width / (float)mt->height; + int w = 80; + int h = ( (int)( (float)w/ratio ))/16*16; + + if(!gvr_track_configure( mt->preview, track_num,w,h ) ) + { + veejay_msg(0, "Unable to configure preview %d x %d",w , h ); + } + +} + +static void sequence_preview_cb(GtkWidget *widget, gpointer user_data) +{ + sequence_view_t *v = (sequence_view_t*) user_data; + multitracker_t *mt = v->backlink; + int status = 0; + + if(v->status_lock) + return; + + if(v->num != mt->master_track ) + { + status = (gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ) == TRUE ? 1 : 0 ); + + gvr_track_toggle_preview( mt->preview, v->num,status ); + + sequence_preview_size( mt, v->num ); + + if( !status ) + gtk_image_clear( GTK_IMAGE(v->area ) ); + } +} + +static void sequence_set_current_frame(GtkWidget *w, gpointer user_data) +{ + + sequence_view_t *v = (sequence_view_t*) user_data; + multitracker_t *mt = v->backlink; + if(v->status_lock) + return; + + gdouble pos = GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value; + gint frame = pos * v->status_cache[TOTAL_FRAMES]; + + gvr_queue_mvims( mt->preview, v->num, VIMS_VIDEO_SET_FRAME, frame ); +} + +static sequence_view_t *new_sequence_view( void *vp, int num ) +{ + sequence_view_t *seqv = (sequence_view_t*) vj_calloc(sizeof(sequence_view_t)); + + seqv->num = num; + seqv->backlink = vp; + + seqv->event_box = gtk_event_box_new(); + gtk_event_box_set_visible_window( GTK_EVENT_BOX(seqv->event_box), TRUE ); + GTK_WIDGET_SET_FLAGS( seqv->event_box, GTK_CAN_FOCUS ); + + g_signal_connect( G_OBJECT( seqv->event_box ), + "button_press_event", + G_CALLBACK( seqv_mouse_press_event ), + (gpointer*) seqv ); + gtk_widget_show( GTK_WIDGET( seqv->event_box ) ); + + + gchar *track_title = g_new0( gchar, 20 ); + sprintf(track_title, "Track %d", num ); + seqv->frame = gtk_frame_new( track_title ); + g_free(track_title); + + gtk_container_set_border_width( GTK_CONTAINER( seqv->frame) , 1 ); + gtk_widget_show( GTK_WIDGET( seqv->frame ) ); + gtk_container_add( GTK_CONTAINER( seqv->event_box), seqv->frame ); + + seqv->main_vbox = gtk_vbox_new(FALSE,0); + gtk_container_add( GTK_CONTAINER( seqv->frame ), seqv->main_vbox ); + gtk_widget_show( GTK_WIDGET( seqv->main_vbox ) ); + + seqv->area = gtk_image_new(); + + + gtk_box_pack_start( GTK_BOX(seqv->main_vbox),GTK_WIDGET( seqv->area), FALSE,FALSE,0); + gtk_widget_set_size_request_( seqv->area, 176,144 ); //FIXME + seqv->panel = gtk_frame_new(NULL); + + seqv->toggle = gtk_toggle_button_new_with_label( "preview" ); + + if(num>0) { + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(seqv->toggle), FALSE ); + g_signal_connect( G_OBJECT( seqv->toggle ), "toggled", G_CALLBACK(sequence_preview_cb), + (gpointer)seqv ); + gtk_box_pack_start( GTK_BOX(seqv->main_vbox), seqv->toggle,FALSE,FALSE, 0 ); + + gtk_widget_set_sensitive_( GTK_WIDGET( seqv->toggle ), FALSE ); + + gtk_widget_show( seqv->toggle ); + } else { + gtk_box_pack_start( GTK_BOX(seqv->main_vbox), seqv->toggle,FALSE,FALSE, 0 ); + gtk_widget_show( seqv->toggle ); + gtk_widget_set_sensitive_( GTK_WIDGET( seqv->toggle ), FALSE ); + } + + GtkWidget *vvbox = gtk_vbox_new(FALSE, 0); + seqv->button_box = gtk_hbox_new(FALSE,0); + gtk_box_pack_start( GTK_BOX(vvbox), seqv->button_box ,FALSE,FALSE, 0 ); + add_buttons( seqv,seqv,seqv->button_box ); + + gtk_widget_show( seqv->button_box ); + gtk_container_add( GTK_CONTAINER( seqv->main_vbox ), seqv->panel ); + + seqv->button_box2 = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start( GTK_BOX(vvbox), seqv->button_box2, FALSE,FALSE, 0 ); + add_buttons2( seqv,seqv,seqv->button_box2 ); + gtk_widget_show( seqv->button_box2 ); + gtk_container_add( GTK_CONTAINER( seqv->panel ), vvbox ); + gtk_widget_show(vvbox); + + GtkWidget *box = gtk_vbox_new(FALSE,0); + seqv->timeline_ = gtk_hscale_new_with_range( 0.0,1.0,0.1 ); + gtk_scale_set_draw_value( GTK_SCALE(seqv->timeline_), FALSE ); + //gtk_widget_set_size_request_( seqv->panel,180 ,180); + gtk_adjustment_set_value( + GTK_ADJUSTMENT(GTK_RANGE(seqv->timeline_)->adjustment), 0.0 ); + gtk_widget_show( seqv->panel ); + gtk_box_pack_start( GTK_BOX( box ), seqv->timeline_, FALSE,FALSE, 0 ); + gtk_box_pack_start( GTK_BOX( vvbox ), box , FALSE,FALSE,0); + gtk_widget_show(seqv->timeline_); + g_signal_connect( seqv->timeline_, "value_changed", + (GCallback) sequence_set_current_frame, (gpointer*) seqv ); + + GtkWidget *scroll = gtk_scrolled_window_new(NULL,NULL); + gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_ETCHED_IN ); + gtk_widget_set_size_request_(scroll,30,70); + gtk_container_set_border_width(GTK_CONTAINER(scroll),0); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scroll),GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC ); + GtkWidget *vvvbox = gtk_hbox_new(FALSE,0); + seqv->tracks = create_track_view(seqv->num, MAX_TRACKS, (void*) seqv ); + gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( get_track_tree(seqv->tracks)) , FALSE ); + gtk_widget_set_size_request_( get_track_tree(seqv->tracks),20,80 ); + gtk_widget_show(scroll); + + gtk_scrolled_window_add_with_viewport( + GTK_SCROLLED_WINDOW( scroll ), get_track_tree(seqv->tracks) ); + gtk_widget_show( get_track_tree(seqv->tracks)); + gtk_box_pack_start( GTK_BOX(vvvbox), scroll, TRUE,TRUE, 0); + + GtkWidget *hhbox = gtk_hbox_new(FALSE,0); + + seqv->sliders_[0] = gtk_vscale_new_with_range( -12.0,12.0,1.0 ); + seqv->sliders_[1] = gtk_vscale_new_with_range( 0.0, 1.0, 0.01 ); + + gtk_adjustment_set_value( + GTK_ADJUSTMENT(GTK_RANGE(seqv->sliders_[0])->adjustment), 1.0 ); + gtk_adjustment_set_value( + GTK_ADJUSTMENT(GTK_RANGE(seqv->sliders_[1])->adjustment), 0.0 ); + + + gtk_scale_set_digits( GTK_SCALE(seqv->sliders_[1]), 2 ); + g_signal_connect( G_OBJECT( seqv->sliders_[0] ), "value_changed", G_CALLBACK( seq_speed ), + (gpointer*)seqv ); + g_signal_connect( G_OBJECT( seqv->sliders_[1] ), "value_changed", G_CALLBACK( seq_opacity ), + (gpointer*)seqv ); + + gtk_box_pack_start( GTK_BOX( hhbox ), seqv->sliders_[0], TRUE, TRUE, 0 ); + gtk_box_pack_start( GTK_BOX( hhbox ), seqv->sliders_[1], TRUE, TRUE, 0 ); + gtk_widget_show( seqv->sliders_[0] ); + gtk_widget_show( seqv->sliders_[1] ); + gtk_box_pack_start( GTK_BOX(vvvbox), hhbox, TRUE,TRUE, 0 ); + gtk_widget_show( hhbox ); + gtk_container_add( GTK_CONTAINER( box ), vvvbox ); + gtk_widget_show( vvvbox ); + gtk_widget_show( box ); + + + GtkWidget *hbox = gtk_hbox_new(FALSE,0); + gtk_box_set_spacing( GTK_BOX(hbox), 10 ); + seqv->labels_[0] = gtk_label_new( "00:00:00:00" ); + seqv->labels_[1] = gtk_label_new( "00:00:00:00" ); + gtk_box_pack_start( GTK_BOX( hbox ), seqv->labels_[0], FALSE, FALSE, 0 ); + gtk_box_pack_start( GTK_BOX( hbox ), seqv->labels_[1], FALSE, FALSE, 0 ); + gtk_widget_show( seqv->labels_[0] ); + gtk_widget_show( seqv->labels_[1] ); + gtk_box_pack_start( GTK_BOX(seqv->main_vbox), hbox, FALSE,FALSE, 0 ); + gtk_widget_show( hbox ); + + + gtk_widget_set_sensitive_(GTK_WIDGET(seqv->panel), FALSE ); + + gtk_widget_show( GTK_WIDGET( seqv->area ) ); + + return seqv; +} + + +static int vt__[16]; +static int vt___ = 0; +void *multitrack_sync( void * mt ) +{ + multitracker_t *m = (multitracker_t*) mt; + sync_info *s = gvr_sync( m->preview ); + if(!s) + return NULL; + + if(!vt___) + { + veejay_memset(vt__,0,sizeof(vt__)); + vt___ = 1; + } + + int i; + for( i =0; i < MAX_TRACKS ;i ++ ) + { + if(!vt__[i] && s->status_list[i] == NULL ) + { + //gtk_widget_set_sensitive_(GTK_WIDGET(m->view[i]), FALSE ); + vt__[i] = 1; + } + else if( s->status_list[i] && vt__[i] ) + { + //gtk_widget_set_sensitive_(GTK_WIDGET(m->view[i]), TRUE ); + vt__[i] = 0; + } + } + s->master = m->master_track; + return (void*)s; +} + +static int mt_new_connection_dialog(multitracker_t *mt, char *hostname,int len, int *port_num) +{ + GtkWidget *dialog = gtk_dialog_new_with_buttons( + "Connect to a Veejay", + GTK_WINDOW( mt->main_window ), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + GTK_STOCK_OK, + GTK_RESPONSE_ACCEPT, + NULL ); + + + GtkWidget *text_entry = gtk_entry_new(); + gtk_entry_set_text( GTK_ENTRY(text_entry), "localhost" ); + gtk_editable_set_editable( GTK_EDITABLE(text_entry), TRUE ); + gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT ); + gtk_window_set_resizable( GTK_WINDOW( dialog ), FALSE ); + + gint base = 3490; + + gint p = (1000 * (mt->selected)) + base; + + GtkObject *adj = gtk_adjustment_new( p,1024,65535,5,10,0); + GtkWidget *num_entry = gtk_spin_button_new( GTK_ADJUSTMENT(adj), 5.0, 0 ); + + GtkWidget *text_label = gtk_label_new( "Hostname" ); + GtkWidget *num_label = gtk_label_new( "Port" ); + g_signal_connect( G_OBJECT(dialog), "response", + G_CALLBACK( gtk_widget_hide ), G_OBJECT( dialog ) ); + + GtkWidget *vbox = gtk_vbox_new( FALSE, 4 ); + gtk_container_add( GTK_CONTAINER( vbox ), text_label ); + gtk_container_add( GTK_CONTAINER( vbox ), text_entry ); + gtk_container_add( GTK_CONTAINER( vbox ), num_label ); + gtk_container_add( GTK_CONTAINER( vbox ), num_entry ); + gtk_container_add( GTK_CONTAINER( GTK_DIALOG(dialog)->vbox), vbox ); + gtk_widget_show_all( dialog ); + + gint res = gtk_dialog_run( GTK_DIALOG(dialog) ); + + if( res == GTK_RESPONSE_ACCEPT ) + { + const gchar *host = gtk_entry_get_text( GTK_ENTRY( text_entry ) ); + gint port = gtk_spin_button_get_value( GTK_SPIN_BUTTON(num_entry )); + strncpy( hostname, host, len ); + *port_num = port; + } + + gtk_widget_destroy( dialog ); + + return res; +} + +void multitrack_resize( void *m , int w, int h ) +{ + multitracker_t *mt = (multitracker_t*) m; +// gtk_widget_set_size_request( mt->scroll, w, h ); +} + +void *multitrack_new( + void (*f)(int,char*,int), + int (*g)(GdkPixbuf *, GdkPixbuf *, GtkImage *), + GtkWidget *win, + GtkWidget *box, + GtkWidget *msg, + GtkWidget *preview_toggle, + gint max_w, + gint max_h, + GtkWidget *main_preview_area, + void *infog, + int threads, + int num_tracks) +{ + multitracker_t *mt = NULL; +#ifdef STRICT_CHECKING + assert( max_w > 0 ); + assert( max_h > 0 ); + assert( num_tracks > 0 ); +#endif + + MAX_TRACKS = num_tracks; + + mt = (multitracker_t*) vj_calloc(sizeof(multitracker_t)); + mt->view = (sequence_view_t**) vj_calloc(sizeof(sequence_view_t*) * MAX_TRACKS ); + mt->preview = NULL; + mt->main_window = win; + mt->main_box = box; + mt->status_bar = msg; + mt->logo = load_logo_image(vj_get_preview_box_w(), vj_get_preview_box_h()); + mt->preview_toggle = preview_toggle; + mt->scroll = gtk_scrolled_window_new(NULL,NULL); +// gtk_widget_set_size_request(mt->scroll,50+max_w*2, max_h); + gtk_container_set_border_width(GTK_CONTAINER(mt->scroll),1); + gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(mt->scroll),GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); + GtkWidget *table = gtk_table_new( 1, MAX_TRACKS, FALSE ); + gtk_box_pack_start( GTK_BOX( mt->main_box ), mt->scroll , TRUE,TRUE, 0 ); + gtk_widget_show(mt->scroll); + int c = 0; + for( c = 0; c < MAX_TRACKS; c ++ ) + { + mt->view[c] = new_sequence_view( mt, c ); + gtk_table_attach_defaults( GTK_TABLE(table), mt->view[c]->event_box, c, c+1, 0, 1 ); + } + + gtk_scrolled_window_add_with_viewport( + GTK_SCROLLED_WINDOW( mt->scroll ), table ); + + gtk_widget_show(table); + + mt->master_track = 0; + + mt->preview = gvr_preview_init( MAX_TRACKS, threads ); +// gvr_set_master( mt->preview, mt->master_track ); + + + parent__ = infog; + + return (void*) mt; +} + + +int multitrack_add_track( void *data ) +{ + multitracker_t *mt = (multitracker_t*) data; + int res = 0; + char *hostname = vj_calloc( 100 ); + int port_num = 0; + + if( mt_new_connection_dialog( mt, hostname, 100, &port_num ) == GTK_RESPONSE_ACCEPT ) + { + int track = 0; + + if( gvr_track_connect( mt->preview, hostname, port_num, &track ) ) + { + status_print( mt, "Connection established with veejay runnning on %s port %d", + hostname, port_num ); + if( gveejay_user_preview() ) + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mt->view[track]->toggle), TRUE ); + gtk_widget_set_sensitive_(GTK_WIDGET(mt->view[track]->panel), TRUE ); + gtk_widget_set_sensitive_(GTK_WIDGET(mt->view[track]->toggle), TRUE ); + + res = 1; + } + else + { + status_print( mt, "Unable to open connection with %s : %d", hostname, port_num ); + } + } + + free( hostname ); + + return res; +} + +void multitrack_close_track( void *data ) +{ + multitracker_t *mt = (multitracker_t*) data; + + if( mt->selected > 0 && mt->selected < MAX_TRACKS ) + { + gvr_track_disconnect( mt->preview, mt->selected ); + mt->view[mt->selected]->status_lock = 1; + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(mt->view[mt->selected]->toggle), FALSE ); + gtk_widget_set_sensitive_(GTK_WIDGET(mt->view[mt->selected]->panel), FALSE ); + gtk_widget_set_sensitive_(GTK_WIDGET(mt->view[mt->selected]->toggle), FALSE ); + gtk_image_clear( GTK_IMAGE(mt->view[mt->selected]->area ) ); + mt->view[mt->selected]->status_lock = 0; + + } + +} + +int multrack_audoadd( void *data, char *hostname, int port_num ) +{ + multitracker_t *mt = (multitracker_t*) data; + + int track = 0; + + if(!gvr_track_connect( mt->preview, hostname, port_num, &track ) ) + { + if(!gvr_track_already_open( mt->preview, hostname,port_num)) + return -1; + } + + if(mt->pw > 0 && mt->ph > 0 ) + { + //sequence_preview_size( mt, mt->master_track ); + + /* configure master preview size */ + if(!gvr_track_configure( mt->preview, track, mt->pw,mt->ph) ) + { + veejay_msg(0, "Unable to configure preview %d x %d",mt->pw , mt->ph ); + } + + + int preview = gvr_get_preview_status( mt->preview, mt->master_track ); + + /* set status of preview toggle button in trackview */ + if( track == 0 ) + { + // mt->view[track]->status_lock=1; + // gtk_toggle_button_set_active( + // GTK_TOGGLE_BUTTON( mt->preview_toggle), (preview ? TRUE: FALSE ) ); + // mt->view[track]->status_lock=0; + } + else + { + mt->view[track]->status_lock=1; + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON( mt->view[track]->toggle ), (preview ? TRUE: FALSE ) ); + mt->view[track]->status_lock=0; + + } + } + +// mt->master_track = track; + gvr_set_master( mt->preview, track ); + + gtk_widget_set_sensitive_(GTK_WIDGET(mt->view[track]->panel), TRUE ); + + + return track; +} + +int multitrack_locked( void *data) +{ + multitracker_t *mt = (multitracker_t*) data; + + return mt->view[mt->master_track]->status_lock; +} + +#define RUP8(num)(num/8*8) + +void multitrack_configure( void *data, float fps, int video_width, int video_height, int *box_w, int *box_h ) +{ + multitracker_t *mt = (multitracker_t*) data; + mt->fps = fps; + mt->width = video_width; + mt->height = video_height; + float r = (float)mt->width / (float) mt->height; + mt->aspect_ratio = r; + + if( mt->height > 300 ) { + mt->height = DEFAULT_PREVIEW_HEIGHT; + mt->width = (int) ( (float) mt->height * r ); + } + if( mt->width > 360 ) { + mt->width = DEFAULT_PREVIEW_WIDTH; + mt->height = mt->width / r; + } + + mt->width = RUP8(mt->width); + mt->height = RUP8(mt->height); + + *box_w = mt->width; + *box_h = mt->height; + + veejay_msg(VEEJAY_MSG_DEBUG, "Multitrack %d x %d, %2.2f, ratio %f", mt->width,mt->height,mt->fps,r); +} + +void multitrack_set_quality( void *data , int quality ) +{ + multitracker_t *mt = (multitracker_t*) data; + + int w = 0; + int h = 0; + switch( quality ) + { + case 1: + w = mt->width; + h = (float) w / mt->aspect_ratio; + break; + case 0: + w = mt->width >> 1; + h = (float)w / mt->aspect_ratio; + break; + case 2: + w = mt->width >> 2; + h = (float)w/ mt->aspect_ratio; + break; + case 3: + w = mt->width >> 3; + h = (float)w / mt->aspect_ratio; + break; + } + + if( w > 16 && h > 16 ) + { + w = RUP8(w); + h = RUP8(h); + } + else + { + w = RUP8(mt->width); + h = RUP8(mt->height); + } + + veejay_msg(VEEJAY_MSG_DEBUG, + "Preview image dimensions set to %d x %d",w,h); + + if(!gvr_track_configure( mt->preview, mt->master_track,w,h ) ) + { + veejay_msg(0, "Unable to configure preview %d x %d",w , h ); + } + + mt->pw = w; + mt->ph = h; +} + +void multitrack_set_logo(void *data , GtkWidget *img) +{ + multitracker_t *mt = (multitracker_t*) data; + gtk_image_set_from_pixbuf_( GTK_IMAGE(img), mt->logo ); +} + +void multitrack_toggle_preview( void *data, int track_id, int status, GtkWidget *img ) +{ + multitracker_t *mt = (multitracker_t*) data; + if(track_id == -1 ) + { + gvr_track_toggle_preview( mt->preview, mt->master_track, status ); + veejay_msg(2, "VeejayGrabber: master preview %s", (status ? "enabled" : "disabled") ); + } +} + +void multitrack_release_track(void *data, int id, int release_this ) +{ + multitracker_t *mt = (multitracker_t*) data; + int stream_id = 0; + + //release this: track um + + stream_id = gvr_get_stream_id( mt->preview, release_this ); + if(stream_id > 0) + gvr_queue_mvims( mt->preview, id, VIMS_STREAM_DELETE,stream_id ); +} + +void multitrack_bind_track( void *data, int id, int bind_this ) +{ + multitracker_t *mt = (multitracker_t*) data; + + if( bind_this < 0 || bind_this > MAX_TRACKS ) + return; + + if( id < 0 || id > MAX_TRACKS ) + return; + + char *host = gvr_track_get_hostname( mt->preview, bind_this ); + int port = gvr_track_get_portnum ( mt->preview, bind_this ); + + if( host != NULL && port > 0 ) + gvr_queue_cxvims( mt->preview, id, VIMS_STREAM_NEW_UNICAST, port, (unsigned char*)host ); +} + +void multitrack_update_sequence_image( void *data , int track, GdkPixbuf *img ) +{ + multitracker_t *mt = (multitracker_t*) data; + + float ratio = mt->width / (float) mt->height; + int w = 160; + int h = ((int) (float )w / ratio )/16 *16; + + GdkPixbuf *scaled = vj_gdk_pixbuf_scale_simple( img, w, h, GDK_INTERP_BILINEAR ); + gtk_image_set_from_pixbuf( GTK_IMAGE(mt->view[track]->area), scaled); + + gdk_pixbuf_unref( scaled ); +} + + +static gboolean seqv_mouse_press_event ( GtkWidget *w, GdkEventButton *event, gpointer user_data) +{ + sequence_view_t *v = (sequence_view_t*) user_data; + multitracker_t *mt = v->backlink; + + if(event->type == GDK_BUTTON_PRESS) + { + if( !gvr_track_test( mt->preview , v->num ) ) + return FALSE; + + mt->selected = v->num; + + vj_gui_disable(); + + // hostname, port_num from gvr + char *host = gvr_track_get_hostname( mt->preview, v->num ); + int port = gvr_track_get_portnum ( mt->preview, v->num ); + + if(!host || port <= 0 ) + { + vj_gui_enable(); + return FALSE; + } + + vj_gui_cb( 0, host, port ); + + gvr_set_master( mt->preview, v->num ); + if(!gvr_track_configure( mt->preview, v->num, mt->pw,mt->ph) ) + { + veejay_msg(0, "Unable to configure preview %d x %d",mt->pw , mt->ph ); + } + veejay_msg(VEEJAY_MSG_INFO, "Set master to track %d", mt->master_track ); + mt->master_track = v->num; + + vj_gui_enable(); + } + + if( event->type == GDK_BUTTON_PRESS ) + { + mt->selected = v->num; + } + + return FALSE; +} + + + + + diff --git a/branches/V-1.5.3/veejay-client/src/multitrack.h b/branches/V-1.5.3/veejay-client/src/multitrack.h new file mode 100644 index 00000000..0875406a --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/multitrack.h @@ -0,0 +1,59 @@ +#ifndef MTRACK_H +#define MTRACK_H + +#define DEFAULT_PREVIEW_WIDTH (int)(352.0f*0.85f) +#define DEFAULT_PREVIEW_HEIGHT (int)(288.0f*0.85f) + +void *multitrack_new( + void (*f)(int,char*,int), + int (*g)(GdkPixbuf *, GdkPixbuf *, GtkImage *), + GtkWidget *win, + GtkWidget *box, + GtkWidget *msg, + GtkWidget *button, + gint max_w, + gint max_h, + GtkWidget *main_preview_area, + void *gui, + int threads, + int max_tracks); + + +void multitrack_set_logo(void *data , GtkWidget *img); + +int multitrack_add_track( void *data ); + +void multitrack_close_track( void *data ); + +int multrack_audoadd( void *data, char *hostname, int port_num ); + +void multitrack_release_track(void *data, int id, int release_this ); + +void multitrack_bind_track( void *data, int id, int bind_this ); + +void multitrack_sync_simple_cmd2( void *data, int vims, int arg ); + + +void *multitrack_sync( void * mt ); + +void multitrack_configure( void *data, float fps, int video_width, int video_height, int *bw, int *bh ); + + +void multitrack_update_sequence_image( void *data , int track, GdkPixbuf *img ); + +int update_multitrack_widgets( void *data, int *array, int track ); + +int multitrack_locked( void *data); + +void multitrack_toggle_preview( void *data, int track_id, int status, GtkWidget *img ); + +void multitrack_set_quality( void *data , int quality ); + +void multitrack_sync_start(void *data); + +void multitrack_sync_simple_cmd( void *data, int vims, int arg ); + +void multitrack_resize( void *m , int w, int h ); + +#endif + diff --git a/branches/V-1.5.3/veejay-client/src/sequence.c b/branches/V-1.5.3/veejay-client/src/sequence.c new file mode 100644 index 00000000..cacf954b --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/sequence.c @@ -0,0 +1,1157 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2006 Niels Elburg + * + * + * 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 +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +extern void reloaded_schedule_restart(); +typedef struct +{ + uint8_t *image_data[16]; + int *status_tokens[16]; + int widths[16]; + int heights[16]; + int active_list[16]; + int frame_list[16]; +} track_sync_t; + +typedef struct +{ + char *hostname; + int port_num; + vj_client *fd; + uint8_t *data_buffer; + uint8_t *tmp_buffer; + uint8_t *status_buffer; + int track_list[16]; + int track_items; //shared + int status_tokens[32]; //shared + int active; + int have_frame; + int grey_scale; + int preview; + int width; + int height; + int prevwidth; + int prevheight; + int prevmode; + int need_track_list; + unsigned char *queue[16]; + int n_queued; + int bw; + int is_master; +} veejay_track_t; + +typedef struct +{ + void *lzo; + veejay_track_t **tracks; + int n_tracks; + int state; + track_sync_t *track_sync; +#ifdef STRICT_CHECKING + int locked; + char **locklist[256]; +#endif +} veejay_preview_t; + +static int sendvims( veejay_track_t *v, int vims_id, const char format[], ... ); +static int recvvims( veejay_track_t *v, gint header_len, gint *payload, guchar *buffer ); +static int veejay_get_image_data(veejay_preview_t *vp, veejay_track_t *v ); +static int track_find( veejay_preview_t *vp ); +static int veejay_process_status( veejay_preview_t *vp, veejay_track_t *v ); +static int gvr_preview_process_image( veejay_preview_t *vp, veejay_track_t *v ); +static int track_exists( veejay_preview_t *vp, const char *hostname, int port_num, int *at ); +static int gvr_preview_process_status( veejay_preview_t *vp, veejay_track_t *v ); + +static GStaticRecMutex mutex_ = G_STATIC_REC_MUTEX_INIT; + +void gvr_veejay_grabber_step( void *data ); + +static float get_ratio(int w, int h) +{ + return ( (float) w / (float) h); +} + + + +void *gvr_preview_init(int max_tracks, int use_threads) +{ + veejay_preview_t *vp = (veejay_preview_t*) vj_calloc(sizeof( veejay_preview_t )); + GError *err = NULL; + //vp->mutex = g_mutex_new(); + vp->tracks = (veejay_track_t**) vj_calloc(sizeof( veejay_track_t*) * max_tracks ); + vp->track_sync = (track_sync_t*) vj_calloc(sizeof( track_sync_t )); + int i; + for( i = 0; i < max_tracks; i++ ) + vp->track_sync->status_tokens[i] = (int*) vj_calloc(sizeof(int) * 32); + + vp->n_tracks = max_tracks; + + yuv_init_lib(0,0,0); + + return (void*) vp; +} + +static void gvr_close_connection( veejay_track_t *v ) +{ + if(v) + { + veejay_msg(VEEJAY_MSG_WARNING, "Stopping VeejayGrabber to %s:%d", + v->hostname,v->port_num ); + vj_client_close(v->fd); + vj_client_free(v->fd); + if(v->hostname) free(v->hostname); + if(v->status_buffer) free(v->status_buffer); + if(v->data_buffer) free(v->data_buffer); + if(v->tmp_buffer) free(v->tmp_buffer); + + free(v); + v= NULL; + } +} + +static int sendvims( veejay_track_t *v, int vims_id, const char format[], ... ) +{ + gchar block[255]; + gchar tmp[255]; + va_list args; + gint n; + if( format == NULL ) + { + g_snprintf( block, sizeof(block)-1, "%03d:;", vims_id ); + n = vj_client_send( v->fd, V_CMD, block ); + if( n <= 0 ) { + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + return 0; + } + return 0; + } + + va_start( args, format ); + vsnprintf( tmp, sizeof(tmp)-1, format, args ); + g_snprintf( block,sizeof(block)-1, "%03d:%s;", vims_id, tmp ); + va_end( args ); + + n = vj_client_send( v->fd, V_CMD, block ); + if( n <= 0 ) { + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + } + return 1; +} + +static int recvvims( veejay_track_t *v, gint header_len, gint *payload, guchar *buffer ) +{ + gint tmp_len = header_len + 1; + unsigned char *tmp = vj_calloc( tmp_len ); + gint len = 0; + gint n = vj_client_read_no_wait( v->fd, V_CMD, tmp, header_len ); + + if( n<= 0 ) + { + if( n == -1 && v->is_master) + reloaded_schedule_restart(); + veejay_msg(0,"Reading header of %d bytes: %d", header_len,n ); + free(tmp); + return n; + } + + if( sscanf( (char*)tmp, "%6d%1d", &len,&(v->grey_scale) )<=0) + { + veejay_msg(0, "Can't parse header (datastream polluted)"); + free(tmp); + return 0; + } + + if( len <= 0 ) + { + free(tmp); + veejay_msg(0, "Frame is empty"); + return 0; + } + + gint bw = 0; + gint bytes_read = len; + unsigned char *buf_ptr = buffer; + + *payload = 0; + + while( bw < len ) + { + n = vj_client_read_no_wait( v->fd, V_CMD, buf_ptr, bytes_read ); + if ( n <= 0 ) + { + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + veejay_msg(0, "Received %d out of %d bytes", bw,len); + free(tmp); + *payload = 0; + return n; + } + bw += n; + + bytes_read -= n; + buf_ptr += bw; + } + *payload = bw; + + free(tmp); + return 1; +} + + +static unsigned char *vims_track_list( veejay_track_t *v, int slen, int *bytes_written ) +{ + unsigned char message[10]; + int tmp_len = slen + 1; + unsigned char *tmp = vj_calloc( tmp_len ); + + sprintf(message, "%03d:;", VIMS_TRACK_LIST ); + int ret = vj_client_send( v->fd, V_CMD, message ); + if( ret <= 0) + { + if( ret == -1 && v->is_master ) + reloaded_schedule_restart(); + free(tmp); + return NULL; + } + + ret = vj_client_read( v->fd, V_CMD, tmp, slen ); + if( ret <= 0 ) + { + + if( ret == -1 && v->is_master ) + reloaded_schedule_restart(); + free(tmp); + return NULL; + } + + int len = 0; + sscanf( (char*) tmp, "%d", &len ); + unsigned char *result = NULL; + + if( len <= 0 || slen <= 0) + { + free(tmp); + return result; + } + + result = (unsigned char*) vj_calloc(sizeof( unsigned char) * (len + 1) ); + int bytes_left = len; + *bytes_written = 0; + + while( bytes_left > 0) + { + int n = vj_client_read( v->fd, V_CMD, result + (*bytes_written), bytes_left ); + if( n <= 0 ) + { + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + bytes_left = 0; + break; + } + if( n > 0 ) + { + *bytes_written +=n; + bytes_left -= n; + } + } + free(tmp); + + if( bytes_left ) { + free(result); + return NULL; + } + + return result; +} + + +static int veejay_process_status( veejay_preview_t *vp, veejay_track_t *v ) +{ + + unsigned char status_len[6]; + veejay_memset( status_len, 0, sizeof(status_len) ); + int k = -1; + int n = 0; + while( (k = vj_client_poll( v->fd, V_STATUS )) ) // is there a more recent message? + { + veejay_memset( status_len, 0, sizeof( status_len ) ); + n = vj_client_read(v->fd, V_STATUS, status_len, 5 ); + int bytes= 0; +#ifdef STRICT_CHECKING + assert( status_len[0] == 'V' ); +#endif + + if( status_len[0] != 'V' ) { + n = -1; + k = -1; + break; + } + + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + + if( sscanf( status_len+1, "%03d", &bytes ) != 1 ) { + veejay_msg(0, "Invalid status message."); + bytes = 0; + reloaded_schedule_restart(); + } + + if(bytes > 0 ) + { + n = vj_client_read( v->fd, V_STATUS, v->status_buffer, bytes ); + if( n <= 0 ) { + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + + break; + } + } + } + if( k == -1 && v->is_master ) + reloaded_schedule_restart(); + + veejay_memset( v->status_tokens,0, sizeof(sizeof(int) * 32)); + status_to_arr( v->status_buffer, v->status_tokens ); +/* + + + gint n = vj_client_read( v->fd, V_STATUS, status_len, 5 ); + + if( n <= 0 && v->is_master ) + reloaded_schedule_restart(); + +#ifdef STRICT_CHECKING + assert( status_len[0] == 'V' ); +#endif + + if( status_len[0] == 'V' ) + { + gint bytes = 0; + sscanf( status_len + 1, "%03d", &bytes ); + if( bytes > 0 ) + { + veejay_memset( v->status_buffer,0, sizeof(v->status_buffer)); + n = vj_client_read( v->fd, V_STATUS, v->status_buffer, bytes ); + veejay_msg(0, " --> [%s]", v->status_buffer ); + if( n <= 0 ) + { + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + veejay_msg(0, "Status message corrupted."); + return 0; + } + int k = -1; + while( (k = vj_client_poll( v->fd, V_STATUS )) ) // is there a more recent message? + { + veejay_msg(0,"More in buffer!"); + veejay_memset( status_len, 0, sizeof( status_len ) ); + n = vj_client_read(v->fd, V_STATUS, status_len, 5 ); + veejay_msg(0, "FLUSH %d [%s]",n,status_len ); + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + sscanf( status_len+1, "%03d", &bytes ); + if(bytes > 0 ) + { + n = vj_client_read( v->fd, V_STATUS, v->status_buffer, bytes ); + veejay_msg(0, "FLUSH --> [%s]", v->status_buffer ); + if( n <= 0 ) { + if( n == -1 && v->is_master ) + reloaded_schedule_restart(); + + break; + } + } + } + if( k == -1 && v->is_master ) + + reloaded_schedule_restart(); + veejay_memset( v->status_tokens,0, sizeof(sizeof(int) * 32)); + status_to_arr( v->status_buffer, v->status_tokens ); + return 1; + } +#ifdef STRICT_CHECKING + else { + assert(0); + } +#endif + } + else + { + veejay_msg(0, "FATAL! cannot parse status message."); + assert(0); + int err = 0; + + while( ( n = vj_client_poll( v->fd, V_STATUS ))) + { + char trashcan[100]; + int k = vj_client_read( v->fd, V_STATUS, trashcan,sizeof(trashcan)); +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Flushing %d bytes '%s'",k,trashcan); +#endif + if( k <= 0 && v->is_master) + err = -1; + } + + if( n <= 0 && v->is_master ) + err = -1; + + if( err == -1) + reloaded_schedule_restart(); + }*/ + return 1; +} +extern int is_button_toggled(const char *name); +#define RUP8(num)(((num)+8)&~8) + +static int veejay_get_image_data(veejay_preview_t *vp, veejay_track_t *v ) +{ + if(!v->have_frame && (v->width <= 0 || v->height <= 0) ) + return 1; + gint res = sendvims( v, VIMS_RGB24_IMAGE, "%d %d", v->width,v->height ); + if( res <= 0 ) + { + v->have_frame = 0; + return res; + } + gint bw = 0; + + res = recvvims( v, 7, &bw, v->data_buffer ); + if( res <= 0 || bw <= 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Can't get a preview image! Only got %d bytes", bw); + v->have_frame = 0; + return res; + } + + int expected_len = (v->width * v->height) + (v->width*v->height/2); + + if( bw != (v->width * v->height) && bw != expected_len ) + { +//@ try to fallback to a different resolution + veejay_msg(VEEJAY_MSG_WARNING, "Corrupted image. Should be %dx%d but have %d bytes %s", + v->width,v->height,abs(bw - expected_len),( (bw-expected_len<0)? "too few" : "too many") ); + v->have_frame = 0; +#ifdef STRICT_CHECKING + assert(0); +#endif + return 0; + } + + uint8_t *in = v->data_buffer; + uint8_t *out = v->tmp_buffer; +#ifdef STRICT_CHECKING + if( v->grey_scale ) + assert( bw == (v->width * v->height)); + else + assert( bw == ( (v->width*v->height) + (v->width*v->height)/2 ) ); +#endif + v->bw = 0; + + VJFrame *src1 = NULL; + if( v->grey_scale == 0 ) + src1 = yuv_yuv_template( in, in + (v->width * v->height), + in + (v->width * v->height) + (v->width*v->height)/4 , + v->width,v->height, PIX_FMT_YUV420P ); + else + src1 = yuv_yuv_template( in, in, in, v->width,v->height, PIX_FMT_GRAY8 ); + + + if( (v->prevwidth != v->width) || (v->prevheight != v->height) || (v->prevmode != v->grey_scale ) ) { + v->prevwidth = v->width; + v->prevheight = v->height; + v->prevmode = v->grey_scale; + veejay_memset( in, 0, v->width*v->height); + if(!v->grey_scale) { + veejay_memset( in + (v->width*v->height), 128, ((v->width*v->height)/4)); + veejay_memset( in + (v->width*v->height) + ((v->width*v->height)/4),128,((v->width*v->height)/4)); + } + } + + VJFrame *dst1 = NULL; + + dst1 = yuv_rgb_template( out, v->width,v->height, PIX_FMT_BGR24 ); + + yuv_convert_any_ac( src1, dst1, src1->format, dst1->format ); + v->have_frame = 1; + + free(src1); + free(dst1); + + return bw; +} + + +static int gvr_preview_process_status( veejay_preview_t *vp, veejay_track_t *v ) +{ + if(!v) + return 0; + int tmp1 = 0; + tmp1 = vj_client_poll( v->fd , V_STATUS ); + if(tmp1) + { + int k = veejay_process_status( vp, v ); + if( k == -1 && v->is_master) + reloaded_schedule_restart(); + } + else if( tmp1 == -1 ) + { + if(v->is_master) + reloaded_schedule_restart(); + else + gvr_close_connection(v); + } + return 0; +} + +static int fail_connection = 0; +static int continue_anyway = 0; +static int gvr_preview_process_image( veejay_preview_t *vp, veejay_track_t *v ) +{ + int n = veejay_get_image_data( vp, v ); + + if(n == 0 ) { + //@ settle + fail_connection ++; + if( fail_connection > 2 ) { + fail_connection = 0; //@ fail 2 out of 10 images and we break connection + return 0; + } + return 1; + } if( n == -1 ) { + return 0; + } else { + continue_anyway = (continue_anyway + 1) % 10; + if(continue_anyway == 0) + fail_connection = 0; + } + + return 1; +} + +void gvr_set_master(void *data, int master_track ) +{ + veejay_preview_t *vp = (veejay_preview_t*) data; + int i; + for( i = 0; i < vp->n_tracks; i ++ ) + if( vp->tracks[i] ) + vp->tracks[i]->is_master = 0; + vp->tracks[master_track]->is_master = 1; +} + +static int track_exists( veejay_preview_t *vp, const char *hostname, int port_num, int *at_track ) +{ + int i; + + for( i = 0; i < vp->n_tracks ; i++ ) + { + if( vp->tracks[i] ) + { + veejay_track_t *v = vp->tracks[i]; + if( strcasecmp( hostname, v->hostname ) == 0 && v->port_num == port_num ) + { + if( at_track ) + *at_track = i; + return 1; + } + } + } + return 0; +} + +int gvr_track_test( void *preview, int track_id ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + if( track_id < 0 || track_id > vp->n_tracks ) + return 0; + return (vp->tracks[track_id] ? 1:0); +} + +static int track_find( veejay_preview_t *vp ) +{ + int i; + int res = -1; + for( i = 0;i < vp->n_tracks ;i ++ ) + { + if( !vp->tracks[i] ) + { + res = i; + break; + } + } + return res; +} + +char* gvr_track_get_hostname( void *preview , int num ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + + if( vp->tracks[num] ) + return vp->tracks[num]->hostname; + return NULL; +} + +int gvr_track_get_portnum( void *preview, int num) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + + if( vp->tracks[num] ) + return vp->tracks[num]->port_num; + return 0; +} + +int gvr_track_already_open( void *preview, const char *hostname, + int port ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + + if(track_exists( vp, hostname, port, NULL ) ) + return 1; + return 0; +} + +int gvr_track_connect( void *preview, const char *hostname, int port_num, int *new_track ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int track_num = track_find( vp ); + + if(track_num == -1) + { + vj_msg(0, "All tracks used."); + return 0; + } + if(track_exists( vp, hostname, port_num, new_track ) ) + { + vj_msg(VEEJAY_MSG_WARNING, "Veejay '%s':%d already in track %d", hostname, port_num, *new_track ); + return 0; + } + vj_client *fd = vj_client_alloc(0,0,0); + if(!vj_client_connect( fd, hostname, NULL, port_num ) ) + { + vj_msg(VEEJAY_MSG_ERROR, "Unable to connect to %s:%d", hostname, port_num ); + vj_client_free( fd ); + return 0; + } + + veejay_track_t *vt = (veejay_track_t*) vj_calloc( sizeof(veejay_track_t)); + vt->hostname = strdup(hostname); + vt->port_num = port_num; + vt->active = 1; + vt->fd = fd; + vt->preview = is_button_toggled( "previewtoggle" ); + + vt->status_buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * 256); + vt->data_buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * 512 * 512 * 3 ); + vt->tmp_buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * 512 * 512 * 3 ); + + *new_track = track_num; + + vp->tracks[ track_num ] = vt; + vp->track_sync->active_list[ track_num ] = 1; + return 1; +} + + +static void gvr_single_queue_vims( veejay_track_t *v, int vims_id ) +{ + char message[10]; + + sprintf(message, "%03d:;", vims_id ); + + if( v->n_queued < 16 ) + { + v->queue[ v->n_queued ] = strdup( message ); + v->n_queued ++; + } +} + +static void gvr_multi_queue_vims( veejay_track_t *v, int vims_id, int val ) +{ + char message[10]; + + sprintf(message, "%03d:%d;", vims_id,val ); + + if( v->n_queued < 16 ) + { + v->queue[ v->n_queued ] = strdup( message ); + v->n_queued ++; + } +} +static void gvr_multivx_queue_vims( veejay_track_t *v, int vims_id, int val1,unsigned char *val2 ) +{ + char message[300]; + + sprintf(message, "%03d:%d %s;", vims_id,val1,val2 ); + + if( v->n_queued < 16 ) + { + v->queue[ v->n_queued ] = strdup( message ); + v->n_queued ++; + } +} + +static void gvr_multiv_queue_vims( veejay_track_t *v, int vims_id, int val1,int val2 ) +{ + char message[10]; + + sprintf(message, "%03d:%d %d;", vims_id,val1,val2 ); + + if( v->n_queued < 16 ) + { + v->queue[ v->n_queued ] = strdup( message ); + v->n_queued ++; + } +} +void gvr_queue_cxvims( void *preview, int track_id, int vims_id, int val1,unsigned char *val2 ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int i; + + if( track_id == -1 ) + { + for( i = 0; i < vp->n_tracks; i ++ ) + if( vp->tracks[i] && vp->tracks[i]->active ) + gvr_multivx_queue_vims( vp->tracks[i], vims_id,val1,val2 ); + } + else + { + if( vp->tracks[track_id] && vp->tracks[track_id]->active) + gvr_multivx_queue_vims( vp->tracks[track_id], vims_id,val1,val2 ); + } +} + +void gvr_queue_vims( void *preview, int track_id, int vims_id ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int i; + + if( track_id == -1 ) + { + for( i = 0; i < vp->n_tracks; i ++ ) + if( vp->tracks[i] && vp->tracks[i]->active ) + gvr_single_queue_vims( vp->tracks[i], vims_id ); + } + else + { + if( vp->tracks[track_id] && vp->tracks[track_id]->active) + gvr_single_queue_vims( vp->tracks[track_id], vims_id ); + } +} + +void gvr_queue_mvims( void *preview, int track_id, int vims_id, int val ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int i; + + if( track_id == -1 ) + { + for( i = 0; i < vp->n_tracks ; i ++ ) + if( vp->tracks[i] && vp->tracks[i]->active ) + gvr_multi_queue_vims( vp->tracks[i], vims_id,val ); + } + else + { + if( vp->tracks[track_id] && vp->tracks[track_id]->active ) + gvr_multi_queue_vims( vp->tracks[track_id], vims_id,val ); + } +} + +void gvr_need_track_list( void *preview, int track_id ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + veejay_track_t *v = vp->tracks[track_id]; + if(v) + v->need_track_list = 1; +} + +void gvr_queue_mmvims( void *preview, int track_id, int vims_id, int val1,int val2 ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int i; + + if( track_id == -1 ) + { + for( i = 0; i < vp->n_tracks; i ++ ) + if( vp->tracks[i] && vp->tracks[i]->active ) + gvr_multiv_queue_vims( vp->tracks[i], vims_id,val1,val2 ); + } + else + { + if( vp->tracks[track_id] && vp->tracks[track_id]->active) + gvr_multiv_queue_vims( vp->tracks[track_id], vims_id,val1,val2 ); + } +} + +void gvr_track_disconnect( void *preview, int track_num ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + + veejay_track_t *v = vp->tracks[ track_num ]; + if(v) + gvr_close_connection( v ); + vp->tracks[ track_num ] = NULL; + vp->track_sync->active_list[ track_num ] = 0; + +} + +int gvr_track_configure( void *preview, int track_num, int w, int h ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + if( vp->tracks[track_num] ) + { + vp->tracks[ track_num ]->width = w; + vp->tracks[ track_num ]->height = h; + } + + veejay_msg(VEEJAY_MSG_INFO, "VeejayGrabber to %s:%d started on Track %d in %dx%d", + vp->tracks[ track_num ]->hostname, + vp->tracks[ track_num ]->port_num, + track_num, + w,h); + + vp->track_sync->widths[track_num] = w; + vp->track_sync->heights[track_num] = h; + + return 1; +} + +int gvr_get_preview_status( void *preview, int track_num ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + if(!vp->tracks[track_num] ) + return 0; + return vp->tracks[track_num]->preview; +} + + +int gvr_track_toggle_preview( void *preview, int track_num, int status ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + vp->tracks[ track_num ]->preview = status; + + vj_msg(VEEJAY_MSG_INFO, "VeejayGrabber to %s:%d on Track %d %s", + vp->tracks[ track_num ]->hostname, + vp->tracks[ track_num ]->port_num, + track_num, + (status ? "starts loading images" : "stops loading images") ); + return status; +} + + + +static GdkPixbuf **gvr_grab_images(void *preview) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + GdkPixbuf **list = (GdkPixbuf**) vj_calloc( sizeof(GdkPixbuf*) * vp->n_tracks ); + if(!list) + return NULL; + + int i; + + for( i = 0; i < vp->n_tracks; i ++ ) + { + if( vp->tracks[i] && vp->tracks[i]->active && vp->track_sync->widths[i] > 0) + { +#ifdef STRICT_CHECKING + assert( vp->track_sync->widths[i] > 0 ); + assert( vp->track_sync->heights[i] > 0 ); +#endif + veejay_track_t *v = vp->tracks[i]; +//@FIXME HERE + list[i] =gdk_pixbuf_new_from_data(vp->tracks[i]->tmp_buffer,GDK_COLORSPACE_RGB,FALSE, + 8,vp->tracks[i]->width,vp->tracks[i]->height, + vp->tracks[i]->width*3,NULL,NULL ); + + } + } + + return list; +} + +static int *int_dup( int *status ) +{ + int *res = (int*) vj_calloc( sizeof(int) * 32 ); + int i; + for(i =0; i < 32 ; i ++ ) + res[i] = status[i]; + return res; +} + +static int **gvr_grab_stati( void *preview ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int **list = (int**) vj_calloc( sizeof(int*) * vp->n_tracks ); + if(!list) + return NULL; + + int i; + + for( i = 0; i < vp->n_tracks; i ++ ) + if( vp->tracks[i] && vp->tracks[i]->active) + list[i] = int_dup( vp->tracks[i]->status_tokens ); + return list; +} + +static int *gvr_grab_widths( void *preview ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int *list = (int**) vj_calloc( sizeof(int) * vp->n_tracks ); + if(!list) + return NULL; + + int i; + for( i = 0; i < vp->n_tracks; i ++ ) + if( vp->tracks[i] && vp->tracks[i]->active ) + list[i] = vp->track_sync->widths[i]; + + return list; +} +static int *gvr_grab_heights( void *preview ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + int *list = (GdkPixbuf**) vj_calloc( sizeof(int) * vp->n_tracks ); + if(!list) + return NULL; + + int i; + for( i = 0; i < vp->n_tracks; i ++ ) + if( vp->tracks[i] && vp->tracks[i]->active ) + list[i] = vp->track_sync->widths[i]; + + return list; +} + +sync_info *gvr_sync( void *preview ) +{ + veejay_preview_t *vp = (veejay_preview_t*) preview; + sync_info *s = (sync_info*) vj_calloc(sizeof(sync_info)); + + gvr_veejay_grabber_step( preview ); + + s->status_list = gvr_grab_stati( preview ); + s->tracks = vp->n_tracks; + s->widths = gvr_grab_widths( preview ); + s->heights = gvr_grab_heights( preview); + s->img_list = gvr_grab_images( preview ); + + return s; +} + + +static void gvr_parse_track_list( veejay_preview_t *vp, veejay_track_t *v, unsigned char *tmp, int len ) +{ + int i = 0; + int items = 0; + unsigned char *ptr = tmp; + + unsigned char **z = vj_calloc( sizeof( unsigned char * ) * vp->n_tracks ); + + while( i < len ) + { + int k = 0; + unsigned char k_str[4]; + strncpy( (char*) k_str,(char*) ptr, 3 ); + if( k > 0 ) + { + ptr += 3; + z[items] = strndup( (char*) ptr, k ); + items ++; + ptr += k; + } + i += ( 3 + k ); + } + + if( items > 0 ) + { + for( i = 0; i < items ; i ++ ) + { + int k; + int in_track = -1; + for( k = 0; k < vp->n_tracks ; k ++ ) + { + veejay_track_t *t = vp->tracks[k]; + if(t) + { + char hostname[255]; + int port = 0; + int stream_id = 0; + veejay_memset(hostname,0,255 ); + if( sscanf( (char*) z[i], "%s %d %d", hostname, &port, &stream_id )) + { + if( strcasecmp( hostname, t->hostname ) == 0 && + port == t->port_num ) + in_track = k; + } + } + } + + v->track_list[i] = in_track; + + free( z[i] ); + } + v->track_items = items; + } + + free( z ); +} + +int gvr_get_stream_id( void *data, int id ) +{ + veejay_preview_t *vp = (veejay_preview_t*) data; + + veejay_track_t *v = vp->tracks[id]; + + if(v) + return v->track_list[id]; + return 0; +} + +static void gvr_parse_queue( veejay_track_t *v ) +{ + int i; + + for( i = 0; i < v->n_queued ; i ++ ) + { + if( vj_client_send( v->fd, V_CMD, v->queue[i] ) == -1 && + v->is_master ) + reloaded_schedule_restart(); + free( v->queue[i] ); + v->queue[i] = NULL; + } + v->n_queued = 0; +} +static int gvr_veejay( veejay_preview_t *vp , veejay_track_t *v, int track_num ) +{ + int score = 0; + if( v->need_track_list || v->n_queued > 0 ) + { + if( v->need_track_list ) + { + int bw = 0; + unsigned char *tmp = vims_track_list( v, 5, &bw ); + gvr_parse_track_list( vp, v, tmp, bw ); + v->need_track_list = 0; + } + if( v->n_queued > 0 ) + { + gvr_parse_queue( v ); + } + score ++; + } + + if( v->preview ) + { + if( gvr_preview_process_image( vp,v )) + score++; + else + { + v->preview = 0; + vj_client_close(v->fd); + int ok = vj_client_connect( v->fd, v->hostname, NULL, v->port_num ); + if( ok <= 0 ) + { + veejay_msg(0, "VeejayGrabber: Unable to reconnect to %s, Destroying Track %d", + (v->hostname ? v->hostname : ""), + track_num ); + vj_client_free(v->fd); + if(v->hostname) free(v->hostname); + if(v->status_buffer) free(v->status_buffer); + if(v->data_buffer) free(v->data_buffer); + if(v->tmp_buffer) free(v->tmp_buffer); + vp->tracks[track_num] = NULL; + if( v->is_master ) + reloaded_schedule_restart(); + free(v); + } + else + { + vj_client_setup_timeout( v->fd,V_CMD,1); + + v->preview = is_button_toggled( "previewtoggle"); + v->active = 1; + vj_msg(VEEJAY_MSG_WARNING, "VeejayGrabber: connected with %s:%d on Track %d %d x %d", + v->hostname, v->port_num, track_num, v->width,v->height); + } + } + + } + + return score; +} +#define MS_TO_NANO(a) (a *= 1000000) +static void net_delay(long nsec ) +{ + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = MS_TO_NANO( nsec); + nanosleep( &ts, NULL ); +} + +void gvr_veejay_grabber_step( void *data ) +{ + veejay_preview_t *vp = (veejay_preview_t*) data; + int i; + + int ac = 1; + int try_picture = 0; + + for( i = 0; i < vp->n_tracks ; i ++ ) + { + if( vp->tracks[i] && vp->tracks[i]->active) { + if(gvr_preview_process_status( vp, vp->tracks[i] )) + { + if( gvr_get_preview_status( vp, i ) ) + try_picture ++; + } + } + } + + long ttw = 0; + for( i = 0; i < vp->n_tracks ; i ++ ) + { + if( vp->tracks[i] && vp->tracks[i]->active) + { + if( vp->tracks[i] ) + ttw += gvr_veejay( vp, vp->tracks[i],i ); + } + } + +} + + diff --git a/branches/V-1.5.3/veejay-client/src/sequence.h b/branches/V-1.5.3/veejay-client/src/sequence.h new file mode 100644 index 00000000..42f8f2c7 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/sequence.h @@ -0,0 +1,63 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2006 Niels Elburg + * + * + * 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. + */ + +#ifndef PREVIEWH +#define PREVIEWH +typedef struct +{ + int tracks; + int master; + int *widths; + int *heights; + int **status_list; + GdkPixbuf **img_list; +} sync_info; + +void *gvr_preview_init(int max_tracks, int use_thread); +int gvr_track_connect( void *preview, const char *hostname, int port_num, int *track_num ); +void gvr_track_disconnect( void *preview, int track_num ); +int gvr_track_configure( void *preview, int track_num, int w, int h); +int gvr_track_toggle_preview( void *preview, int track_num, int status ); +void gvr_need_track_list( void *preview, int track_id ); + +int gvr_get_stream_id( void *data, int id ); +void gvr_set_master( void *preview, int master_track ); +//format and queue vims messages from extern + +void gvr_queue_mmvims( void *preview, int track_id, int vims_id, int val1,int val2 ); +void gvr_queue_mvims( void *preview, int track_id, int vims_id, int val ); +void gvr_queue_vims( void *preview, int track_id, int vims_id ); + +void gvr_queue_cxvims( void *preview, int track_id, int vims_id, int val1,unsigned char *val2 ); + +int gvr_track_already_open( void *preview, const char *hostname, int port ); + +int gvr_get_preview_status( void *preview, int track_num ); + +char* gvr_track_get_hostname( void *preview , int num ); + +int gvr_track_get_portnum( void *preview, int num); + +int gvr_track_test( void *preview, int track_id ); + +sync_info *gvr_sync( void *preview ); + +#endif + + diff --git a/branches/V-1.5.3/veejay-client/src/tracksources.c b/branches/V-1.5.3/veejay-client/src/tracksources.c new file mode 100644 index 00000000..8d474948 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/tracksources.c @@ -0,0 +1,202 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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 +extern void veejay_release_track(int id, int release_this); +extern void veejay_bind_track( int id, int bind_this ); +extern int multitrack_get_sequence_view_id( void *data ); +extern gchar *_utf8str( const char *c_str ); +extern void set_widget_color( GtkWidget *widget , int red, int green, int blue, int def ); +typedef struct +{ + int track_id; + GtkWidget *view; +} track_view_t; + +static void cell_data_func( + GtkTreeViewColumn *col, GtkCellRenderer *renderer, + GtkTreeModel *model, GtkTreeIter *iter, + gpointer user_data) +{ + gint state; + gtk_tree_model_get(model, iter, 1, &state, -1 ); + + if(state==1) + g_object_set(renderer, "active", TRUE, NULL ); + else + g_object_set(renderer, "active", FALSE, NULL ); + g_object_set( renderer, "activatable", TRUE, NULL ); +} + +static void cell_toggled_callback( GtkCellRenderer *cell, gchar *path_string, gpointer user_data ) +{ + track_view_t *v = (track_view_t*) user_data; + GtkWidget *view = v->view; + GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); + GtkTreePath *path = gtk_tree_path_new_from_string( path_string ); + GtkTreeIter iter; + + gtk_tree_model_get_iter( model, &iter, path ); + gchar *data = NULL; + gtk_tree_model_get( model, &iter,0, &data, -1 ); + + int id_data = -1; // invalid + char junk[32]; + if(sscanf( data, "%d", &id_data ) == 1 ) + { + if( gtk_cell_renderer_toggle_get_active( GTK_CELL_RENDERER_TOGGLE( cell) ) ) + { + veejay_release_track( v->track_id, id_data); +// set_widget_color( v->view, 0,255,0,0); + } + else + { + veejay_bind_track( v->track_id, id_data ); +// set_widget_color( v->view, 0,0,0,1 ); + } + g_free(data); + } + gtk_tree_path_free( path ); +} + +extern int *sequence_get_track_status(void *priv ); + +void update_track_view( int n_tracks, GtkWidget *widget, void *user_data ) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreeModel *model = gtk_tree_view_get_model( view ); + GtkListStore *store = GTK_LIST_STORE( model ); + GtkTreeIter iter; + + gtk_list_store_clear( GTK_LIST_STORE( model ) ); + + int i; + int id = multitrack_get_sequence_view_id( user_data ); + for( i = 0; i < n_tracks; i ++ ) + { + if(id != i) + { + char name[12]; + sprintf(name,"%d", i); + gchar *uname = _utf8str( name ); + gtk_list_store_append( store, &iter ); + gtk_list_store_set( + store, &iter, + 0, uname, + 1, 0, + -1 ); + g_free( uname ); + } + } + + + gtk_tree_view_set_model( GTK_TREE_VIEW( widget ), model ); + +} + +GtkWidget *get_track_tree( void *data) +{ + track_view_t *t = (track_view_t*) data; + return t->view; +} + +void *create_track_view(int track_id, int ref_tracks, void *user_data) +{ + GtkCellRenderer *renderer, *wrenderer; + GtkTreeModel *model; + GtkWidget *view; + view = gtk_tree_view_new(); + renderer = gtk_cell_renderer_text_new(); + wrenderer = gtk_cell_renderer_toggle_new(); + + track_view_t *my_view = (track_view_t*) vj_calloc(sizeof(track_view_t)); + + gtk_cell_renderer_toggle_set_active( GTK_CELL_RENDERER_TOGGLE(wrenderer) , FALSE ); + + gtk_tree_view_insert_column_with_attributes( + GTK_TREE_VIEW( view ), + -1, + "T", + renderer, + "text", + 0, + NULL ); + gtk_tree_view_insert_column_with_attributes( + GTK_TREE_VIEW( view ), + -1, + "-", + wrenderer, + "activatable", + 1, + NULL); + +// GtkWidget *col = gtk_tree_view_get_column( GTK_TREE_VIEW(view) , 0 ); + GtkTreeViewColumn *col = gtk_tree_view_get_column( GTK_TREE_VIEW(view),0); + gtk_tree_view_column_set_fixed_width( col , 5 ); + + col = gtk_tree_view_get_column( GTK_TREE_VIEW( view ), 1 ); + gtk_tree_view_column_set_clickable( col , TRUE ); + gtk_tree_view_column_set_fixed_width( col , 20 ); + + gtk_tree_view_column_set_cell_data_func( col, + wrenderer, cell_data_func, NULL,NULL); + + /* build model */ + GtkListStore *store; + GtkTreeIter iter; + + store = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT ); + int i; + for( i = 0; i < ref_tracks ; i ++ ) + { + if( i != track_id ) + { + char str[16]; + sprintf(str,"%d",i); + gchar *ustr = _utf8str( str ); + gtk_list_store_append( store, &iter ); + gtk_list_store_set( store, &iter, + 0, ustr, + 1, 0, + -1); + g_free(ustr); + } + } + + GtkTreeSelection *selection; + selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( view ) ); + gtk_tree_selection_set_mode( selection, GTK_SELECTION_NONE ); + my_view->track_id = track_id; + my_view->view = view; + + g_assert( GTK_IS_TREE_VIEW( view ) ); + + model = GTK_TREE_MODEL( store ); + gtk_tree_view_set_model ( GTK_TREE_VIEW( view ), model ); + g_signal_connect( wrenderer, "toggled", + (GCallback) cell_toggled_callback, (gpointer*) my_view); + + + g_object_unref( model ); + + return (void*) my_view; +} diff --git a/branches/V-1.5.3/veejay-client/src/tracksources.h b/branches/V-1.5.3/veejay-client/src/tracksources.h new file mode 100644 index 00000000..36c86555 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/tracksources.h @@ -0,0 +1,28 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + +#ifndef TRACCKSOURCES_H +#define TRACCKSOURCES_H + +GtkWidget *get_track_tree( void *data); + +void *create_track_view( int id, int ref, void *data ); + +void update_track_view( int n_tracks, GtkWidget *widget, void *user_data ); +#endif diff --git a/branches/V-1.5.3/veejay-client/src/utils.c b/branches/V-1.5.3/veejay-client/src/utils.c new file mode 100644 index 00000000..ed2fcf7a --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/utils.c @@ -0,0 +1,71 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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 "yuv4mpeg_intern.h" +#include "yuv4mpeg.h" +#include "mpegconsts.h" +#include "mpegtimecode.h" + +#include +#include + +int status_to_arr( char *status, int *array ) +{ + int n = sscanf(status, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + array + 0, + array + 1, + array + 2, + array + 3, + array + 4, + array + 5, + array + 6, + array + 7, + array + 8, + array + 9, + array + 10, + array + 11, + array + 12, + array + 13, + array + 14, + array + 15, + array + 16, + array + 17, + array + 18, + array + 19, + array + 20, + array + 21, + array + 22 ); + return n; +} + + +char *format_time(int pos, double fps) +{ + static char temp[256]; + MPEG_timecode_t tc; + y4m_ratio_t r = mpeg_conform_framerate(fps); + mpeg_timecode(&tc, + pos, + mpeg_framerate_code(r), + fps ); + sprintf(temp, "%d:%2.2d:%2.2d:%2.2d",tc.h, tc.m, tc.s, tc.f ); + return strdup(temp); +} + diff --git a/branches/V-1.5.3/veejay-client/src/utils.h b/branches/V-1.5.3/veejay-client/src/utils.h new file mode 100644 index 00000000..3caa2745 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/utils.h @@ -0,0 +1,25 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + +#ifndef GVRUTILS +#define GVRUTILS +int status_to_arr( char *status, int *array ); +char *format_time( int pos , double fps); +#endif + diff --git a/branches/V-1.5.3/veejay-client/src/videodev_mjpeg.h b/branches/V-1.5.3/veejay-client/src/videodev_mjpeg.h new file mode 100644 index 00000000..68fd79c5 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/videodev_mjpeg.h @@ -0,0 +1,118 @@ +/* These are the MJPEG API extensions for the Video4Linux API, + first introduced by the Iomega Buz driver by Rainer Johanni + +*/ + +/* This is identical with the mgavideo internal params struct, + please tell me if you change this struct here ! top-field-first */ + + int APPn; /* Number of APP segment to be written, must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + unsigned long jpeg_markers; /* Which markers should go into the JPEG output. + Unless you exactly know what you do, leave them untouched. + Inluding less markers will make the resulting code + smaller, but there will be fewer aplications + which can read it. + The presence of the APP and COM marker is + influenced by APP0_len and COM_len ONLY! */ +#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ + + int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. + If this flag is turned on and JPEG decompressing + is going to the screen, the decompress process + is stopped every time the Video Fifo is full. + This enables a smooth decompress to the screen + but the video output signal will get scrambled */ + + /* Misc */ + + char reserved[312]; /* Makes 512 bytes for this structure */ +}; + +struct mjpeg_requestbuffers +{ + unsigned long count; /* Number of buffers for MJPEG grabbing */ + unsigned long size; /* Size PER BUFFER in bytes */ +}; + +struct mjpeg_sync +{ + unsigned long frame; /* Frame (0 - n) for double buffer */ + unsigned long length; /* number of code bytes in buffer (capture only) */ + unsigned long seq; /* frame sequence number */ + struct timeval timestamp; /* timestamp */ +}; + +struct mjpeg_status +{ + int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ + int signal; /* Returned: 1 if valid video signal detected */ + int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ + int color; /* Returned: 1 if color signal detected */ +}; + +/* +Private IOCTL to set up for displaying MJPEG +*/ +#define MJPIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct mjpeg_params) +#define MJPIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct mjpeg_params) +#define MJPIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct mjpeg_requestbuffers) +#define MJPIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) +#define MJPIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) +#define MJPIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct mjpeg_sync) +#define MJPIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct mjpeg_status) diff --git a/branches/V-1.5.3/veejay-client/src/vj-api.c b/branches/V-1.5.3/veejay-client/src/vj-api.c new file mode 100644 index 00000000..da6831d4 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/vj-api.c @@ -0,0 +1,8279 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2004 Niels Elburg + * with contributions by Thomas Rheinhold (2005) + * (initial sampledeck representation in GTK) + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mpegconsts.h" +#include "mpegtimecode.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//if gtk2_6 is not defined, 2.4 is assumed. +#ifdef GTK_CHECK_VERSION +#if GTK_MINOR_VERSION >= 6 + #define HAVE_GTK2_6 1 +#endif +#if GTK_MINOR_VERSION >= 8 + #define HAVE_GTK2_8 1 +#endif +#endif +#ifdef STRICT_CHECKING +#include +#endif +static int ui_skin_ = 0; +static struct +{ + const int id; + const char *name; + const int page; +} crappy_design[] = +{ + { 1,"notebook18", 3 }, // On which notebook page is the multitrack view + { 0,"vjdeck", 2 }, + { 0,NULL, 0 } +}; + +#define MAX_SLOW 100 + +static struct +{ + const char *text; +} tooltips[] = +{ + {"Mouse left: Set in point, Mouse right: Set out point, Double click: Clear selected, Mouse middle: Drag selection"}, + {"Mouse left/right: Play slot, Shift + Mouse left: Put sample in slot. You can also put selected samples."}, + {"Mouse left click: Select slot (sample in slot), Mouse double click: Play sample in slot, Mouse left + SHIFT: Set slot as mixing current mixing channel"}, + {"Select a SRT sequence to edit"}, + {NULL}, +}; + +enum { + TOOLTIP_TIMELINE = 0, + TOOLTIP_QUICKSELECT = 1, + TOOLTIP_SAMPLESLOT = 2, + TOOLTIP_SRTSELECT = 3 +}; + +enum +{ + STREAM_NO_STREAM = 0, + STREAM_RED = 9, + STREAM_GREEN = 8, + STREAM_YELLOW = 7, + STREAM_CALI = 6, + STREAM_WHITE = 4, + STREAM_VIDEO4LINUX = 2, + STREAM_DV1394 = 17, + STREAM_NETWORK = 13, + STREAM_MCAST = 14, + STREAM_YUV4MPEG = 1, + STREAM_AVFORMAT = 12, + STREAM_PICTURE = 5 +}; + +enum +{ + COLUMN_INT = 0, + COLUMN_STRING0, + COLUMN_STRINGA , + COLUMN_STRINGB, + COLUMN_STRINGC, + N_COLUMNS +}; +enum +{ + ENTRY_FXID = 0, + ENTRY_ISVIDEO = 1, + ENTRY_NUM_PARAMETERS = 2, + ENTRY_P0 = 3, + ENTRY_P1 = 4, + ENTRY_P2 = 5, + ENTRY_P3 = 6, + ENTRY_P4 = 7, + ENTRY_P5 = 8, + ENTRY_P6 = 9, + ENTRY_P7 = 10, + ENTRY_UNUSED = 11, + ENTRY_FXSTATUS = 12, + ENTRY_UNUSED2 = 13, + ENTRY_SOURCE = 14, + ENTRY_CHANNEL = 15 +}; + +enum +{ + SL_ID = 0, + SL_DESCR = 1, + SL_TIMECODE = 2 +}; + +enum +{ + HINT_CHAIN = 0, + HINT_EL = 1, + HINT_MIXLIST = 2, + HINT_SAMPLELIST = 3, + HINT_ENTRY = 4, + HINT_SAMPLE = 5, + HINT_SLIST = 6, + HINT_V4L = 7, + HINT_RECORDING = 8, + HINT_RGBSOLID = 9, + HINT_BUNDLES = 10, + HINT_HISTORY = 11, + HINT_MARKER = 12, + HINT_KF = 13, + HINT_SEQ_ACT = 14, + HINT_SEQ_CUR = 15, + NUM_HINTS = 16 +}; + +enum +{ + PAGE_CONSOLE =0, + PAGE_FX = 3, + PAGE_EL = 1, + PAGE_SAMPLEEDIT = 2, +}; + +typedef struct +{ + int channel; + int dev; +} stream_templ_t; + +enum +{ + V4L_DEVICE=0, + DV1394_DEVICE=1, +}; + +typedef struct +{ + int selected_chain_entry; + int selected_el_entry; + int selected_vims_entry; + int selected_vims_accel[2]; + int render_record; + int entry_tokens[21]; + int iterator; + int selected_effect_id; + int reload_hint[NUM_HINTS]; + gboolean reload_force_avoid; + int playmode; + int sample_rec_duration; + int streams[4096]; + int recording[2]; + int selected_mix_sample_id; + int selected_mix_stream_id; + int selected_rgbkey; + int priout_lock; + int pressed_key; + int pressed_mod; + int keysnoop; + int randplayer; + int expected_slots; + stream_templ_t strtmpl[2]; // v4l, dv1394 + int selected_parameter_id; // current kf + int selected_vims_type; + char *selected_vims_args; + int cali_duration; + int cali_stage; +} veejay_user_ctrl_t; + +typedef struct +{ + float fps; + float ratio; + int num_files; + int *offsets; + int num_frames; + int width; + int height; +} veejay_el_t; + +enum +{ + RUN_STATE_LOCAL = 1, + RUN_STATE_REMOTE = 2, +}; + +typedef struct +{ + gint event_id; + gint params; + gchar *format; + gchar *descr; + gchar *args; +} vims_t; + +typedef struct +{ + gint keyval; + gint state; + gchar *args; + gchar *vims; + gint event_id; +} vims_keys_t; + +static int user_preview = 0; +static int NUM_BANKS = 50; +static int NUM_SAMPLES_PER_PAGE = 12; +static int NUM_SAMPLES_PER_COL = 6; +static int NUM_SAMPLES_PER_ROW = 2; + +#define MOD_OFFSET 200 +#define SEQUENCE_LENGTH 1024 +#define MEM_SLOT_SIZE 32 + +static vims_t vj_event_list[VIMS_MAX]; +static vims_keys_t vims_keys_list[VIMS_MAX]; +static int vims_verbosity = 0; +#define livido_port_t vevo_port_t +static int cali_stream_id = 0; +static int cali_onoff = 0; + +static vevo_port_t *fx_list_ = NULL; + +typedef struct +{ + GtkWidget *title; + GtkWidget *timecode; + GtkWidget *hotkey; +// GtkWidget *edit_button; + GtkTooltips *tips; + GtkWidget *image; + GtkWidget *frame; + GtkWidget *event_box; + GtkWidget *main_vbox; + GtkWidget *upper_hbox; + GtkWidget *upper_vbox; +} sample_gui_slot_t; + +typedef struct +{ + gint w; + gint h; + gdouble fps; + gint pixel_format; + gint sampling; + gint audio_rate; + gint norm; + gint sync; + gint timer; + gint deinter; + gchar *mcast_osc; + gchar *mcast_vims; + gint osc; + gint vims; +} config_settings_t; + +typedef struct +{ + GtkWidget *frame; + GtkWidget *image; + GtkWidget *event_box; + GtkWidget *main_vbox; + GdkPixbuf *pixbuf_ref; + gint sample_id; + gint sample_type; +} sequence_gui_slot_t; + +typedef struct +{ + gint slot_number; + gint sample_id; + gint sample_type; + gchar *title; + gchar *timecode; + gint refresh_image; + GdkPixbuf *pixbuf; + guchar *rawdata; +} sample_slot_t; + +typedef struct +{ + gint seq_start; + gint seq_end; + gint w; + gint h; + sequence_gui_slot_t **gui_slot; + sample_slot_t *selected; + gint envelope_size; +} sequence_envelope; + +typedef struct +{ + sample_slot_t *sample; +} sequence_slot_t; + + +typedef struct +{ + gint bank_number; + gint page_num; + sample_slot_t **slot; + sample_gui_slot_t **gui_slot; +} sample_bank_t; + +typedef struct +{ + char *hostname; + int port_num; + int state; // IDLE, PLAYING, RECONNECT, STOPPED + struct timeval p_time; + int w_state; // watchdog state + int w_delay; +} watchdog_t; + +typedef struct +{ + GladeXML *main_window; + vj_client *client; + int status_tokens[32]; /* current status tokens */ + int *history_tokens[4]; /* list last known status tokens */ + int status_passed; + int status_lock; + int slider_lock; + int parameter_lock; + int entry_lock; + int sample[2]; + int selection[3]; + gint status_pipe; + int sensitive; + int launch_sensitive; + struct timeval alarm; + struct timeval timer; +// GIOChannel *channel; + GdkColormap *color_map; + gint connecting; +// gint logging; + gint streamrecording; + gint samplerecording; +// gint cpumeter; + gint cachemeter; + gint image_w; + gint image_h; + veejay_el_t el; + veejay_user_ctrl_t uc; + GList *effect_info; + GList *devlist; + GList *chalist; + GList *editlist; + GList *elref; + long window_id; + int run_state; + int play_direction; + int load_image_slot; + GtkWidget *sample_bank_pad; + GtkWidget *quick_select; + GtkWidget *sample_sequencer; + sample_bank_t **sample_banks; + sample_slot_t *selected_slot; + sample_slot_t *selection_slot; + sample_gui_slot_t *selected_gui_slot; + sample_gui_slot_t *selection_gui_slot; + sequence_envelope *sequence_view; + sequence_envelope *sequencer_view; + int sequence_playing; + gint current_sequence_slot; +// GtkKnob *audiovolume_knob; +// GtkKnob *speed_knob; + int image_dimensions[2]; +// guchar *rawdata; + int prev_mode; + GtkWidget *tl; + config_settings_t config; + int status_frame; + int key_id; + GdkColor *fg_; + gboolean key_now; + void *mt; + watchdog_t watch; + int vims_line; + int quality; + int preview_locked; + void *midi; + struct timeval time_last; + uint8_t *cali_buffer; +} vj_gui_t; + +enum +{ + STATE_STOPPED = 0, + STATE_RECONNECT = 1, + STATE_PLAYING = 2, + STATE_CONNECT = 3, + STATE_DISCONNECT = 4, + STATE_BUSY = 5, + STATE_LOADING = 6, + STATE_WAIT_FOR_USER = 7, + STATE_QUIT = 8, +}; + +enum +{ + FXC_ID = 0, + FXC_FXID = 1, + FXC_FXSTATUS = 2, + FXC_KF =3, + FXC_N_COLS, +}; + +enum +{ + V4L_NUM=0, + V4L_NAME=1, + V4L_SPINBOX=2, + V4L_LOCATION=3, +}; + +enum +{ + VIMS_ID=0, + VIMS_DESCR=1, + VIMS_KEY=2, + VIMS_MOD=3, + VIMS_PARAMS=4, + VIMS_FORMAT=5, + VIMS_CONTENTS=6, +}; + +#define MAX_PATH_LEN 1024 +#define VEEJAY_MSG_OUTPUT 4 + +static vj_gui_t *info = NULL; +void reloaded_restart(); +void *get_ui_info() { return (void*) info; } +void reloaded_schedule_restart(); +/* global pointer to the sample-bank */ + +/* global pointer to the effects-source-list */ +static GtkWidget *effect_sources_tree = NULL; +static GtkListStore *effect_sources_store = NULL; +static GtkTreeModel *effect_sources_model = NULL; + + +static GtkWidget *cali_sourcetree = NULL; +static GtkListStore *cali_sourcestore = NULL; +static GtkTreeModel *cali_sourcemodel = NULL; + +static int num_tracks_ = 2; +static int default_preview_width_ = 176; +static int default_preview_height_ = 144; +/* global pointer to the editlist-tree */ +static GtkWidget *editlist_tree = NULL; +static GtkListStore *editlist_store = NULL; +static GtkTreeModel *editlist_model = NULL; +//void gtk_configure_window_cb( GtkWidget *w, GdkEventConfigure *ev, gpointer data ); +static int get_slider_val(const char *name); +void vj_msg(int type, const char format[], ...); +//static void vj_msg_detail(int type, const char format[], ...); +void msg_vims(char *message); +static void multi_vims(int id, const char format[],...); +static void single_vims(int id); +static gdouble get_numd(const char *name); +static void vj_kf_select_parameter(int id); +static int get_nums(const char *name); +static gchar *get_text(const char *name); +static void put_text(const char *name, char *text); +static void set_toggle_button(const char *name, int status); +static void update_slider_gvalue(const char *name, gdouble value ); +static void update_slider_value(const char *name, gint value, gint scale); +static void update_slider_range(const char *name, gint min, gint max, gint value, gint scaled); +//static void update_knob_range( GtkWidget *w, gdouble min, gdouble max, gdouble value, gint scaled ); +static void update_spin_range(const char *name, gint min, gint max, gint val); +static void update_spin_incr(const char *name, gdouble step, gdouble page); +//static void update_knob_value(GtkWidget *w, gdouble value, gdouble scale ); +static void update_spin_value(const char *name, gint value); +static void update_label_i(const char *name, int num, int prefix); +static void update_label_f(const char *name, float val); +static void update_label_str(const char *name, gchar *text); +static void update_globalinfo(int *his, int p, int k); +static gint load_parameter_info(); +static void load_v4l_info(); +static void reload_editlist_contents(); +static void load_effectchain_info(); +static void load_effectlist_info(); +static void load_sequence_list(); +static void load_samplelist_info(gboolean with_reset_slotselection); +static void load_editlist_info(); +static void set_pm_page_label(int sample_id, int type); +#ifndef STRICT_CHECKING +static void disable_widget_( const char *name ); +static void enable_widget_(const char *name ); +#define enable_widget(a) enable_widget_(a) +#define disable_widget(a) disable_widget_(a) +#else +static void disable_widget_( const char *name, const char *function, int line ); +static void enable_widget_(const char *name, const char *function, int line ); +#define enable_widget(a) enable_widget_(a,__FUNCTION__,__LINE__ ) +#define disable_widget(a) disable_widget_(a,__FUNCTION__,__LINE__) +#endif +static void setup_tree_spin_column(const char *tree_name, int type, const char *title); +static void setup_tree_text_column( const char *tree_name, int type, const char *title, int expand ); +static void setup_tree_pixmap_column( const char *tree_name, int type, const char *title ); +gchar *_utf8str( const char *c_str ); +static gchar *recv_vims(int len, int *bytes_written); +static GdkPixbuf * update_pixmap_kf( int status ); +static GdkPixbuf * update_pixmap_entry( int status ); +static gboolean +chain_update_row(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, + gpointer data); +int resize_primary_ratio_y(); +int resize_primary_ratio_x(); +static void update_rgbkey(); +static int count_textview_buffer(const char *name); +static void clear_textview_buffer(const char *name); +static void init_recorder(int total_frames, gint mode); +static void reload_bundles(); +static void update_rgbkey_from_slider(); +static gchar *get_textview_buffer(const char *name); +static void create_slot(gint bank_nr, gint slot_nr, gint w, gint h); +static void setup_samplebank(gint c, gint r, GtkWidget *pad, gint *image_w, gint *image_h); +static int add_sample_to_sample_banks( int bank_page,sample_slot_t *slot ); +static void update_sample_slot_data(int bank_num, int slot_num, int id, gint sample_type, gchar *title, gchar *timecode); +static gboolean on_slot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data); +static sample_slot_t *vj_gui_get_sample_info(gint which_one, gint mode ); +static void add_sample_to_effect_sources_list(gint id, gint type, gchar *title, gchar *timecode); +static void set_activation_of_slot_in_samplebank(gboolean activate); +int gveejay_new_slot(int stream); +static int bank_exists( int bank_page, int slot_num ); +static int find_bank_by_sample(int sample_id, int sample_type, int *slot ); +static int add_bank( gint bank_num ); +static void set_selection_of_slot_in_samplebank(gboolean active); +static void remove_sample_from_slot(); +static void create_ref_slots(int envelope_size); +static void create_sequencer_slots(int x, int y); +//void setup_knobs(); +void free_samplebank(void); +void reset_samplebank(void); +int verify_bank_capacity(int *bank_page_, int *slot_, int sample_id, int sample_type ); +static void widget_get_rect_in_screen (GtkWidget *widget, GdkRectangle *r); +static void update_curve_widget(const char *name); +static void update_curve_accessibility(const char *name); +static void reset_tree(const char *name); +static void reload_srt(); +static void reload_fontlist(); +static void indicate_sequence( gboolean active, sequence_gui_slot_t *slot ); +static void set_textview_buffer(const char *name, gchar *utf8text); +void interrupt_cb(); +//static gboolean update_log(gpointer data); + +GtkWidget *glade_xml_get_widget_( GladeXML *m, const char *name ) +{ + GtkWidget *widget = glade_xml_get_widget( m , name ); + if(!widget) + { +#ifdef STRICT_CHECKING + veejay_msg(0,"Missing widget: %s %s ",__FUNCTION__,name); +#endif + return NULL; + } +#ifdef STRICT_CHECKING + assert( widget != NULL ); +#endif + return widget; +} +void gtk_notebook_set_current_page__( GtkWidget *w, gint num, const char *f, int line ) +{ +#ifdef STRICT_CHECKING + veejay_msg(0, "%s: %d from %s:%d", __FUNCTION__, num,f,line); +#endif + gtk_notebook_set_current_page( GTK_NOTEBOOK(w), num ); +} + + +void gtk_widget_set_size_request__( GtkWidget *w, gint iw, gint h, const char *f, int line ) +{ +#ifdef STRICT_CHECKING +// veejay_msg(0, "%s: %dx%d from %s:%d", __FUNCTION__, iw,h,f,line); +#endif + gtk_widget_set_size_request(w, iw, h ); +} + +#ifndef STRICT_CHECKING +#define gtk_widget_set_size_request_(a,b,c) gtk_widget_set_size_request(a,b,c) +#define gtk_notebook_set_current_page_(a,b) gtk_notebook_set_current_page(a,b) +#else +#define gtk_widget_set_size_request_(a,b,c) gtk_widget_set_size_request__(a,b,c,__FUNCTION__,__LINE__) +#define gtk_notebook_set_current_page_(a,b) gtk_notebook_set_current_page__(a,b,__FUNCTION__,__LINE__) +#endif + +static struct +{ + gchar *text; +} text_msg_[] = +{ + { "Running realtime" }, + { NULL }, +}; + +enum { + TEXT_REALTIME = 0 +}; + +static struct +{ + const char *name; +} capt_card_set[] = +{ + { "v4l_expander" }, + { "v4l_brightness" }, + { "v4l_contrast" }, + { "v4l_hue" }, + { "v4l_saturation" }, + { "v4l_color" }, + { "v4l_white" }, + { NULL }, +}; + +static int preview_box_w_ = DEFAULT_PREVIEW_WIDTH; +static int preview_box_h_ = DEFAULT_PREVIEW_HEIGHT; + + +static void *bankport_ = NULL; + +int vj_get_preview_box_w() +{ + return preview_box_w_; +} + +int vj_get_preview_box_h() +{ + return preview_box_h_; +} + +static void gtk_image_set_from_pixbuf__( GtkImage *w, GdkPixbuf *p, const char *f, int l ) +{ +#ifdef STRICT_CHECKING + assert( GTK_IS_IMAGE(w) ); +#endif + gtk_image_set_from_pixbuf(w, p); +} + +static void gtk_widget_set_sensitive___( GtkWidget *w, gboolean state, const char *f, int l ) +{ +#ifdef STRICT_CHECKING + assert( GTK_IS_WIDGET(w) ); +#endif + gtk_widget_set_sensitive(w, state ); +} + +static void select_slot_(int pm, const char *f, int line); +static void select_slot__(int pm); + +#ifdef STRICT_CHECKING +#define gtk_widget_set_sensitive_( w,p ) gtk_widget_set_sensitive___( w,p,__FUNCTION__,__LINE__ ) +#define gtk_image_set_from_pixbuf_(w,p) gtk_image_set_from_pixbuf__( w,p, __FUNCTION__,__LINE__ ) +#define select_slot(a) select_slot_(a,__FUNCTION__,__LINE__ ) +#else +#define gtk_widget_set_sensitive_( w,p ) gtk_widget_set_sensitive( w,p ) +#define gtk_image_set_from_pixbuf_(w,p) gtk_image_set_from_pixbuf( w,p ) +#define select_slot(a) select_slot__(a) +#endif + +static struct +{ + const char *name; +} uiwidgets[] = +{ + {"veejay_box"}, + {NULL} +}; + +static struct +{ + const char *name; +} plainwidgets[] = +{ + {"video_navigation_buttons"}, + {"button_084"}, + {"button_083"}, + {"button_samplestart"}, + {"button_sampleend"}, + {"speed_slider"}, + {"slow_slider"}, + {"vjframerate"}, + {"markerframe"}, + {NULL} +}; + +static struct +{ + const char *name; +} samplewidgets[] = +{ + {"sample_loop_box"}, + {"button_084"}, + {"button_083"}, + {"video_navigation_buttons"}, + {"button_samplestart"}, + {"button_sampleend"}, + {"speed_slider"}, + {"slow_slider"}, + {"button_200"}, // mask button + {"frame_fxtree"}, + {"frame_fxtree3"}, + {"fxpanel"}, + {"panels"}, + {"vjframerate"}, + {"scrolledwindow49"}, // srt stuff + {"samplegrid_frame"}, + {"markerframe"}, + {NULL} +}; + +static struct +{ + const char *name; +} streamwidgets[] = +{ + {"button_200"}, // mask button + {"frame_fxtree"}, + {"frame_fxtree3"}, + {"fxpanel"}, + {"panels"}, + {"scrolledwindow49"}, // srt stuff + {NULL}, +}; + +enum +{ + TC_SAMPLE_L = 0, + TC_SAMPLE_F = 1, + TC_SAMPLE_S = 2, + TC_SAMPLE_M = 3, + TC_SAMPLE_H = 4, + TC_STREAM_F = 5, + TC_STREAM_M = 6, + TC_STREAM_H = 7 +}; + +static sample_slot_t *find_slot_by_sample( int sample_id , int sample_type ); +static sample_gui_slot_t *find_gui_slot_by_sample( int sample_id , int sample_type ); + +gchar *_utf8str(const char *c_str) +{ + gsize bytes_read = 0; + gsize bytes_written = 0; + GError *error = NULL; + if(!c_str) + return NULL; + char *result = (char*) g_locale_to_utf8( c_str, -1, &bytes_read, &bytes_written, &error ); + + if(error) + { + g_free(error); + if( result ) + g_free(result); + result = NULL; + } + + return result; +} + +GdkColor *widget_get_fg(GtkWidget *w ) +{ + if(!w) + return NULL; + GdkColor *c = (GdkColor*)vj_calloc(sizeof(GdkColor)); + GtkStyle *s = gtk_widget_get_style( w); + c->red = s->fg[0].red; + c->green = s->fg[0].green; + c->blue = s->fg[0].blue; + return c; +} + +static void scan_devices( const char *name) +{ + GtkWidget *tree = glade_xml_get_widget_(info->main_window,name); + GtkListStore *store; + GtkTreeIter iter; + + reset_tree(name); + gint len = 0; + single_vims( VIMS_DEVICE_LIST ); + gchar *text = recv_vims(6,&len); + if(len <= 0|| !text ) + { + veejay_msg(VEEJAY_MSG_WARNING, "No capture devices found on veejay server"); + return; + } + GtkTreeModel *model = gtk_tree_view_get_model + (GTK_TREE_VIEW(tree)); + + store = GTK_LIST_STORE(model); + + gint offset =0; + gint i = 0; + gchar *ptr = text + offset; + while( offset < len ) + { + char tmp[4]; + + gchar *name = NULL; + gdouble gchannel = 1.0; + gchar *loca = NULL; + + gint name_len=0; + gint loc_len=0; + + strncpy(tmp,ptr+offset,3); + tmp[3] = '\0'; + offset += 3; + name_len = atoi( tmp ); + if(name_len <= 0 ) + { + veejay_msg(0, "Reading name of capture device: '%s'",ptr+offset ); + return; + } + name = strndup( ptr + offset, name_len ); + offset += name_len; + strncpy( tmp, ptr + offset, 3 ); + tmp[3] = '\0'; + offset += 3; + + loc_len = atoi( tmp ); + if( loc_len <= 0 ) + { + veejay_msg(0, "Reading location of capture device"); + return; + } + loca = strndup( ptr + offset, loc_len ); + offset += loc_len; + gchar *thename = _utf8str( name ); + gchar *theloca = _utf8str( loca ); + + gtk_list_store_append( store, &iter); + gtk_list_store_set( + store, &iter, + V4L_NUM, i, + V4L_NAME, thename, + V4L_SPINBOX, gchannel, + V4L_LOCATION, theloca, + -1); + + g_free(thename); + g_free(theloca); + + free(loca); + free(name); + i ++; + } + free(text); + + gtk_tree_view_set_model(GTK_TREE_VIEW(tree), model ); +} + +static void set_tooltip_by_widget(GtkWidget *w, const char *text) +{ + gtk_widget_set_tooltip_text( w,text ); +} + +static void set_tooltip(const char *name, const char *text) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window,name); + if(!w) { +#ifdef STRICT_CHECKING + veejay_msg(0, "Widget '%s' not found",name); +#endif + return; + } + gtk_widget_set_tooltip_text( w,text ); +} +void on_devicelist_row_activated(GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_tree_view_get_model(treeview); + if(gtk_tree_model_get_iter(model,&iter,path)) + { + gint channel = info->uc.strtmpl[0].channel; + gint num = info->uc.strtmpl[0].dev; + + multi_vims( VIMS_STREAM_NEW_V4L,"%d %d", + num, + channel + ); + gveejay_new_slot(MODE_STREAM); + + } +} + +gboolean device_selection_func( GtkTreeSelection *sel, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer userdata ) +{ + GtkTreeIter iter; + GValue val = { 0, }; + if( gtk_tree_model_get_iter( model, &iter, path ) ) + { + gint num = 0; + //gtk_tree_model_get(model, &iter, V4L_NUM,&num, -1 ); + gchar *file = NULL; + gtk_tree_model_get( model, &iter, V4L_LOCATION, &file, -1 ); + sscanf( file, "/dev/video%d", &num ); + if(! path_currently_selected ) + { + gtk_tree_model_get_value(model, &iter, V4L_SPINBOX, &val); + info->uc.strtmpl[0].dev = num; + info->uc.strtmpl[0].channel = (int) g_value_get_float(&val); + } + g_free(file); + } + return TRUE; +} + +static void setup_v4l_devices() +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_v4ldevices"); + GtkListStore *store = gtk_list_store_new( 4, G_TYPE_INT, G_TYPE_STRING, G_TYPE_FLOAT, + G_TYPE_STRING ); + + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + GtkTreeSelection *sel = gtk_tree_view_get_selection( GTK_TREE_VIEW( tree ) ); + gtk_tree_selection_set_mode( sel, GTK_SELECTION_SINGLE ); + gtk_tree_selection_set_select_function( sel, device_selection_func, NULL,NULL ); + +// gtk_tree_view_set_fixed_height_mode( GTK_TREE_VIEW(tree), TRUE ); + + g_object_unref( G_OBJECT( store )); + setup_tree_text_column( "tree_v4ldevices", V4L_NUM, "#",0 ); + setup_tree_text_column( "tree_v4ldevices", V4L_NAME, "Device Name",0); + setup_tree_spin_column( "tree_v4ldevices", V4L_SPINBOX, "Channel"); + setup_tree_text_column( "tree_v4ldevices", V4L_LOCATION, "Location",0); + + g_signal_connect( tree, "row-activated", + (GCallback) on_devicelist_row_activated, NULL ); + + + + + //scan_devices( "tree_v4ldevices" ); + + +} + + + +static gchar* format_selection_time(int start, int end); + +typedef struct +{ + int id; + int nl; + long n1; + long n2; + int tf; +} el_ref; + +typedef struct +{ + int pos; + char *filename; + char *fourcc; + int num_frames; +} el_constr; + +typedef struct { + int defaults[10]; + int min[10]; + int max[10]; + char description[150]; + char *param_description[10]; + int id; + int is_video; + int num_arg; + int has_rgb; +} effect_constr; + +int _effect_get_mix(int effect_id) +{ + int n = g_list_length(info->effect_info); + int i; + if(effect_id < 0) return -1; + for(i=0; i <= n; i++) + { + effect_constr *ec = g_list_nth_data( info->effect_info, i ); + if(ec != NULL) + { + if(ec->id == effect_id) return ec->is_video; + } + } + return 0; +} + +int _effect_get_rgb(int effect_id) +{ + int n = g_list_length(info->effect_info); + int i; + if(effect_id < 0) return -1; + for(i=0; i <= n; i++) + { + effect_constr *ec = g_list_nth_data( info->effect_info, i ); + if(ec != NULL) + { + if(ec->id == effect_id) return ec->has_rgb; + } + } + return 0; + +} + +int _effect_get_np(int effect_id) +{ + int n = g_list_length(info->effect_info); + int i; + if(effect_id < 0) return -1; + for(i=0; i <= n; i++) + { + effect_constr *ec = g_list_nth_data( info->effect_info, i ); + if(ec != NULL) + { + if(ec->id == effect_id) return ec->num_arg; + } + } + return 0; +} + +int _effect_get_minmax( int effect_id, int *min, int *max, int index ) +{ + int n = g_list_length(info->effect_info); + int i; + if(effect_id < 0) return 0; + for(i=0; i <= n; i++) + { + effect_constr *ec = g_list_nth_data( info->effect_info, i ); + if(ec != NULL) + { + if(ec->id == effect_id) + { + if( index > ec->num_arg ) + return 0; + *min = ec->min[index]; + *max = ec->max[index]; + return 1; + } + } + } + return 0; + +} + +char *_effect_get_param_description(int effect_id, int param) +{ + int n = g_list_length( info->effect_info ); + int i; + for(i = 0;i <= n ; i++) + { + effect_constr *ec = g_list_nth_data(info->effect_info, i); + if(ec != NULL) + { + if(effect_id == ec->id ) + return ec->param_description[param]; + } + } + return ""; +} + + + +char *_effect_get_description(int effect_id) +{ + int n = g_list_length( info->effect_info ); + int i; + for(i = 0;i <= n ; i++) + { + effect_constr *ec = g_list_nth_data(info->effect_info, i); + if(ec != NULL) + { + if(effect_id == ec->id ) + return ec->description; + } + } + return ""; +} + +el_constr *_el_entry_new( int pos, char *file, int nf , char *fourcc) +{ + el_constr *el = g_new( el_constr , 1 ); + el->filename = strdup( file ); + el->num_frames = nf; + el->pos = pos; + el->fourcc = strdup(fourcc); + return el; +} + +void _el_entry_free( el_constr *entry ) +{ + if(entry) + { + if(entry->filename) free(entry->filename); + if(entry->fourcc) free(entry->fourcc); + free(entry); + } +} + +void _el_entry_reset( ) +{ + if(info->editlist != NULL) + { + int n = g_list_length( info->editlist ); + int i; + for( i = 0; i <= n ; i ++) + _el_entry_free( g_list_nth_data( info->editlist, i ) ); + g_list_free(info->editlist); + info->editlist=NULL; + } +} + +int _el_get_nframes( int pos ) +{ + int n = g_list_length( info->editlist ); + int i; + for( i = 0; i <= n ; i ++) + { + el_constr *el = g_list_nth_data( info->editlist, i ); + if(!el) return 0; + if(el->pos == pos) + return el->num_frames; + } + return 0; +} + +el_ref *_el_ref_new( int row_num,int nl, long n1, long n2, int tf) +{ + el_ref *el = vj_malloc(sizeof(el_ref)); + el->id = row_num; + el->nl = nl; + el->n1 = n1; + el->n2 = n2; + el->tf = tf; + return el; +} + +void _el_ref_free( el_ref *entry ) +{ + if(entry) free(entry); +} + +void _el_ref_reset() +{ + if(info->elref != NULL) + { + int n = g_list_length( info->elref ); + int i; + for(i = 0; i < n; i ++ ) + { + el_ref *edl = g_list_nth_data(info->elref, i ); + if(edl) + free(edl); + } + g_list_free(info->elref); + info->elref = NULL; + } +} + +int _el_ref_end_frame( int row_num ) +{ + int n = g_list_length( info->elref ); + int i; + for ( i = 0 ; i <= n; i ++ ) + { + el_ref *el = g_list_nth_data( info->elref, i ); + if(el->id == row_num ) + { +// int offset = info->el.offsets[ el->nl ]; +// return (offset + el->n1 + el->n2 ); + return (el->tf + el->n2 - el->n1); + } + } + return 0; +} +int _el_ref_start_frame( int row_num ) +{ + int n = g_list_length( info->elref ); + int i; + for ( i = 0 ; i <= n; i ++ ) + { + el_ref *el = g_list_nth_data( info->elref, i ); + if(el->id == row_num ) + { +// int offset = info->el.offsets[ el->nl ]; +// return (offset + el->n1 ); +// printf("Start pos of row %d : %d = n1, %d = n2, %d = tf\n", +// row_num,el->n1,el->n2, el->tf ); + return (el->tf); + } + } + return 0; +} + + +char *_el_get_fourcc( int pos ) +{ + int n = g_list_length( info->editlist ); + int i; + for( i = 0; i <= n; i ++ ) + { + el_constr *el = g_list_nth_data( info->editlist, i ); + if(el->pos == pos) + return el->fourcc; + } + return NULL; +} + + +char *_el_get_filename( int pos ) +{ + int n = g_list_length( info->editlist ); + int i; + for( i = 0; i <= n; i ++ ) + { + el_constr *el = g_list_nth_data( info->editlist, i ); + if(el->pos == pos) + return el->filename; + } + return NULL; +} + +effect_constr* _effect_new( char *effect_line ) +{ + effect_constr *ec; + int descr_len = 0; + int p; + int tokens = 0; + char len[4]; + //char line[100]; + int offset = 0; + + veejay_memset(len,0,sizeof(len)); + + if(!effect_line) return NULL; + + strncpy(len, effect_line, 3); + sscanf(len, "%03d", &descr_len); + if(descr_len <= 0) return NULL; + + ec = g_new( effect_constr, 1); + veejay_memset(ec->description,0,sizeof(ec->description)); + strncpy( ec->description, effect_line+3, descr_len ); + tokens = sscanf(effect_line+(descr_len+3), "%03d%1d%1d%02d", &(ec->id),&(ec->is_video), + &(ec->has_rgb), &(ec->num_arg)); + offset = descr_len + 10; + for(p=0; p < ec->num_arg; p++) + { + int len = 0; + sscanf(effect_line+offset,"%06d%06d%06d%03d", + &(ec->min[p]), &(ec->max[p]),&(ec->defaults[p]),&len ); +#ifdef STRICT_CHECKING + assert(len>0); +#endif + ec->param_description[p] = (char*) vj_calloc(sizeof(char) * (len+1) ); + strncpy( ec->param_description[p], effect_line + offset + 6 + 6 + 6 + 3, len ); + + offset += 3; + offset += len; + offset+=18; + } + return ec; +} + +void _effect_free( effect_constr *effect ) +{ + if(effect) + { + free(effect); + } + +} +void _effect_reset(void) +{ + if( info->effect_info != NULL) + { + int n = g_list_length(info->effect_info); + int i; + for( i = 0; i <=n ; i ++ ) + _effect_free( g_list_nth_data( info->effect_info , i ) ); + g_list_free( info->effect_info ); + info->effect_info = NULL; + } +} + +static gchar *get_relative_path(char *path) +{ + return _utf8str( basename( path )); +} + +gchar *dialog_save_file(const char *title ) +{ + GtkWidget *parent_window = glade_xml_get_widget_( + info->main_window, "gveejay_window" ); + GtkWidget *dialog = + gtk_file_chooser_dialog_new( title, + GTK_WINDOW(parent_window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); +#ifdef HAVE_GTK2_8 + gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE ); +#endif + gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(dialog), "veejay-samplelist.sl" ); + + if( gtk_dialog_run( GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + gchar *file = gtk_file_chooser_get_filename( + GTK_FILE_CHOOSER(dialog) ); + + gtk_widget_destroy(dialog); + return file; + } + + gtk_widget_destroy(dialog); + return NULL; +} + +static void clear_progress_bar( const char *name, gdouble val ) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), val ); +} + +static struct +{ + const char *descr; + const char *filter; +} content_file_filters[] = { + { "AVI Files (*.avi)", "*.avi", }, + { "Digital Video Files (*.dv)", "*.dv" }, + { "Edit Decision List Files (*.edl)", "*.edl" }, + { "PNG (Portable Network Graphics) (*.png)", "*.png" }, + { "JPG (Joint Photographic Experts Group) (*.jpg)", "*.jpg" }, + { NULL, NULL }, + +}; + +static void add_file_filters(GtkWidget *dialog, int type ) +{ + GtkFileFilter *filter = NULL; + + if(type == 0 ) + { + int i; + for( i = 0; content_file_filters[i].descr != NULL ; i ++ ) + { + filter = gtk_file_filter_new(); + gtk_file_filter_set_name( filter, content_file_filters[i].descr); + gtk_file_filter_add_pattern( filter, content_file_filters[i].filter); + gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter ); + } + } + if(type == 1 ) + { + filter = gtk_file_filter_new(); + gtk_file_filter_set_name( filter, "Sample List Files (*.sl)"); + gtk_file_filter_add_pattern( filter, "*.sl"); + gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); + } + if(type == 2 ) + { + filter = gtk_file_filter_new(); + gtk_file_filter_set_name( filter, "Action Files (*.xml)"); + gtk_file_filter_add_pattern( filter, "*.xml"); + gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); + } + if(type == 3 ) + { + //ffmpeg + } + + filter = gtk_file_filter_new(); + gtk_file_filter_set_name( filter, "All Files (*.*)"); + gtk_file_filter_add_pattern( filter, "*"); + gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter); +} + + +gchar *dialog_open_file(const char *title, int type) +{ + static gchar *_file_path = NULL; + + + GtkWidget *parent_window = glade_xml_get_widget_( + info->main_window, "gveejay_window" ); + GtkWidget *dialog = + gtk_file_chooser_dialog_new( title, + GTK_WINDOW(parent_window), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + add_file_filters(dialog, type ); + gchar *file = NULL; + if( _file_path ) + { + gtk_file_chooser_set_current_folder_uri(GTK_FILE_CHOOSER(dialog), _file_path); + g_free(_file_path); + _file_path = NULL; + } + + if( gtk_dialog_run( GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + { + file = gtk_file_chooser_get_filename( + GTK_FILE_CHOOSER(dialog) ); + _file_path = gtk_file_chooser_get_current_folder_uri(GTK_FILE_CHOOSER(dialog)); + } + gtk_widget_destroy(GTK_WIDGET(dialog)); + return file; +} + +static char * produce_os_str() +{ + char os_str[512]; + char cpu_type[32]; + char *simd = vj_calloc( 128 ); +#ifdef ARCH_X86 + sprintf(cpu_type,"x86"); +#endif +#ifdef ARCH_X86_64 + sprintf(cpu_type, "x86-64"); +#endif +#ifdef ARCH_PPC + sprintf(cpu_type, "ppc"); +#endif +#ifdef ARCH_MIPS + sprintf(cpu_type, "mips"); +#endif +#ifdef HAVE_ASM_MMX + strcat( simd, "MMX "); +#endif +#ifdef HAVE_ASM_MMX2 + strcat( simd, "MMX2 "); +#endif +#ifdef HAVE_ASM_SSE + strcat( simd, "SSE " ); +#endif +#ifdef HAVE_ASM_SSE2 + strcat( simd, "SSE2" ); +#endif +#ifdef HAVE_ASM_CMOV + strcat( simd, "cmov" ); +#endif +#ifdef HAVE_ASM_3DNOW + strcat( simd, "3DNow"); +#endif +#ifdef ARCH_PPC +#ifdef HAVE_ALTIVEC + strcat( simd, "altivec"); +#else + strcat( simd, "no optimizations"); +#endif +#endif +#ifdef ARCH_MIPS + strcat( simd, "no optimizations"); +#endif + sprintf(os_str,"Arch: %s with %s", + cpu_type, simd ); + + return strdup( os_str ); +} + +void about_dialog() +{ + const gchar *artists[] = { + "Matthijs v. Henten (glade, pixmaps) ", + "Dursun Koca (V-logo)", + NULL + }; + + const gchar *authors[] = { + "Developed by:", + "Matthijs v. Henten ", + "Dursun Koca", + "Niels Elburg ", + "\n", + "Contributions by:", + "Thomas Reinhold ", + "Toni ", + NULL + }; + + const gchar *web = { + "http://www.veejayhq.net | http://veejay.dyne.org" + }; + + char blob[1024]; + char *os_str = produce_os_str(); + sprintf(blob, "Veejay - A visual instrument and realtime video sampler for GNU/Linux\n%s", os_str ); + free(os_str); + + const gchar *license = + { + "This program is Free Software; You can redistribute it and/or modify\n" \ + "under the terms of the GNU General Public License as published by\n" \ + "the Free Software Foundation; either version 2, or (at your option)\n"\ + "any later version.\n\n"\ + "This program is distributed in the hope it will be useful,\n"\ + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"\ + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"\ + "See the GNU General Public License for more details.\n\n"\ + "For more information , see also: http://www.gnu.org\n" + }; + +#ifdef HAVE_GTK2_6 + char path[MAX_PATH_LEN]; + veejay_memset( path,0, sizeof(path)); + get_gd( path, NULL, "veejay-logo.png" ); + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file + ( path, NULL ); + GtkWidget *about = g_object_new( + GTK_TYPE_ABOUT_DIALOG, + "program_name", "reloaded", + "name", VEEJAY_CODENAME, + "version", VERSION, + "copyright", "(C) 2004 - 2008 N. Elburg et all.", + "comments", "The graphical interface for Veejay", + "website", web, + "authors", authors, + "artists", artists, + "comments", blob, + "license", license, + "logo", pixbuf, NULL ); + g_object_unref(pixbuf); + + g_signal_connect( about , "response", G_CALLBACK( gtk_widget_destroy),NULL); + gtk_window_present( GTK_WINDOW( about ) ); +#endif + +} + +gboolean dialogkey_snooper( GtkWidget *w, GdkEventKey *event, gpointer user_data) +{ + GtkWidget *entry = (GtkWidget*) user_data; + + if( !gtk_widget_is_focus( entry ) ) + { + return FALSE; + } + if(event->type == GDK_KEY_PRESS) + { + gchar tmp[100]; + info->uc.pressed_key = gdk2sdl_key( event->keyval ); + info->uc.pressed_mod = gdk2sdl_mod( event->state ); + gchar *text = gdkkey_by_id( event->keyval ); + gchar *mod = gdkmod_by_id( event->state ); + + if( text ) + { + if(!mod || strncmp(mod, " ", 1 ) == 0 ) + sprintf(tmp, "%s", text ); + else + sprintf(tmp, "%s + %s", mod,text); + + gchar *utf8_text = _utf8str( tmp ); + gtk_entry_set_text( GTK_ENTRY(entry), utf8_text); + g_free(utf8_text); + } + } + + return FALSE; +} + +gboolean key_handler( GtkWidget *w, GdkEventKey *event, gpointer user_data) +{ + if(event->type != GDK_KEY_PRESS) + return FALSE; + + int gdk_keyval = gdk2sdl_key( event->keyval ); + int gdk_state = gdk2sdl_mod( event->state ); + if( gdk_keyval >= 0 && gdk_state >= 0 ) + { + char *message = vims_keys_list[(gdk_state * MOD_OFFSET)+gdk_keyval].vims; + if(message) + msg_vims(message); + } + return FALSE; +} + +static int check_format_string( char *args, char *format ) +{ + if(!format || !args ) + return 0; + char dirty[128]; + int n = sscanf( args, format, &dirty,&dirty, &dirty,&dirty, &dirty,&dirty, &dirty,&dirty, &dirty,&dirty ); + return n; +} + +int +prompt_keydialog(const char *title, char *msg) +{ + if(!info->uc.selected_vims_entry ) + return 0; + info->uc.pressed_mod = 0; + info->uc.pressed_key = 0; + + char pixmap[1024]; + veejay_memset(pixmap,0,sizeof(pixmap)); + get_gd( pixmap, NULL, "icon_keybind.png"); + + GtkWidget *mainw = glade_xml_get_widget_(info->main_window, "gveejay_window"); + GtkWidget *dialog = gtk_dialog_new_with_buttons( title, + GTK_WINDOW( mainw ), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + GTK_STOCK_OK, + GTK_RESPONSE_ACCEPT, + NULL); + + GtkWidget *keyentry = gtk_entry_new(); + gtk_entry_set_text( GTK_ENTRY(keyentry), ""); + gtk_editable_set_editable( GTK_EDITABLE(keyentry), FALSE ); + gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT ); + gtk_window_set_resizable( GTK_WINDOW(dialog), FALSE ); + + g_signal_connect( G_OBJECT(dialog), "response", + G_CALLBACK( gtk_widget_hide ), G_OBJECT(dialog ) ); + + GtkWidget *hbox1 = gtk_hbox_new( FALSE, 12 ); + gtk_container_set_border_width( GTK_CONTAINER( hbox1 ), 6 ); + GtkWidget *hbox2 = gtk_hbox_new( FALSE, 12 ); + gtk_container_set_border_width( GTK_CONTAINER( hbox2 ), 6 ); + + GtkWidget *icon = gtk_image_new_from_file( pixmap ); + + GtkWidget *label = gtk_label_new( msg ); + gtk_container_add( GTK_CONTAINER( hbox1 ), icon ); + gtk_container_add( GTK_CONTAINER( hbox1 ), label ); + gtk_container_add( GTK_CONTAINER( hbox1 ), keyentry ); + + GtkWidget *pentry = NULL; + + if(vj_event_list[ info->uc.selected_vims_entry ].params) + { + //@ put in default args + char *arg_str = vj_event_list[ info->uc.selected_vims_entry ].args; + pentry = gtk_entry_new(); + GtkWidget *arglabel = gtk_label_new("Arguments:"); + + if(arg_str) + gtk_entry_set_text( GTK_ENTRY(pentry), arg_str ); + gtk_editable_set_editable( GTK_EDITABLE(pentry), TRUE ); + gtk_container_add( GTK_CONTAINER(hbox1), arglabel ); + gtk_container_add( GTK_CONTAINER(hbox1), pentry ); + } + + if( info->uc.selected_vims_entry ) + { + char tmp[100]; + char *str_mod = sdlmod_by_id( info->uc.pressed_mod ); + char *str_key = sdlkey_by_id( info->uc.pressed_key ); + int key_combo_ok = 0; + + if(str_mod && str_key ) { + snprintf(tmp,100,"VIMS %d : %s + %s", + info->uc.selected_vims_entry, str_mod, str_key ); + key_combo_ok = 1; + } else if ( str_key ) { + snprintf(tmp, 100,"VIMS %d: %s", info->uc.selected_vims_entry,str_key); + key_combo_ok = 1; + } + + if( key_combo_ok ) + { + gtk_entry_set_text( GTK_ENTRY(keyentry), tmp ); + } + } + + + gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), hbox1 ); + gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), hbox2 ); + + gtk_widget_show_all( dialog ); + + int id = gtk_key_snooper_install( dialogkey_snooper, keyentry); + int n = gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_key_snooper_remove( id ); + + if(pentry) + { + gchar *args = (gchar*) gtk_entry_get_text( GTK_ENTRY(pentry)); + int np = check_format_string( args, vj_event_list[ info->uc.selected_vims_entry ].format ); + + if( np == vj_event_list[ info->uc.selected_vims_entry ].params ) + { + if(info->uc.selected_vims_args ) + free(info->uc.selected_vims_args ); + + info->uc.selected_vims_args = strdup( args ); + } + } + + gtk_widget_destroy(dialog); + + + return n; +} + +void +message_dialog( const char *title, char *msg ) +{ + GtkWidget *mainw = glade_xml_get_widget_(info->main_window, "gveejay_window"); + GtkWidget *dialog = gtk_dialog_new_with_buttons( title, + GTK_WINDOW( mainw ), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, + GTK_RESPONSE_NONE, + NULL); + GtkWidget *label = gtk_label_new( msg ); + g_signal_connect_swapped( dialog, "response", + G_CALLBACK(gtk_widget_destroy),dialog); + gtk_container_add( GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), + label ); + gtk_widget_show_all(dialog); +} + + +int +prompt_dialog(const char *title, char *msg) +{ + GtkWidget *mainw = glade_xml_get_widget_(info->main_window, "gveejay_window"); + GtkWidget *dialog = gtk_dialog_new_with_buttons( title, + GTK_WINDOW( mainw ), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_NO, + GTK_RESPONSE_REJECT, + GTK_STOCK_YES, + GTK_RESPONSE_ACCEPT, + NULL); + gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_REJECT ); + gtk_window_set_resizable( GTK_WINDOW(dialog), FALSE ); + g_signal_connect( G_OBJECT(dialog), "response", + G_CALLBACK( gtk_widget_hide ), G_OBJECT(dialog ) ); + GtkWidget *hbox1 = gtk_hbox_new( FALSE, 12 ); + gtk_container_set_border_width( GTK_CONTAINER( hbox1 ), 6 ); + GtkWidget *icon = gtk_image_new_from_stock( GTK_STOCK_DIALOG_QUESTION, + GTK_ICON_SIZE_DIALOG ); + GtkWidget *label = gtk_label_new( msg ); + gtk_container_add( GTK_CONTAINER( hbox1 ), icon ); + gtk_container_add( GTK_CONTAINER( hbox1 ), label ); + gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), hbox1 ); + gtk_widget_show_all( dialog ); + + int n = gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(dialog); + + return n; +} + + +int +error_dialog(const char *title, char *msg) +{ + GtkWidget *mainw = glade_xml_get_widget_(info->main_window, "gveejay_window"); + GtkWidget *dialog = gtk_dialog_new_with_buttons( title, + GTK_WINDOW( mainw ), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_STOCK_OK, + GTK_RESPONSE_OK, + NULL); + gtk_dialog_set_default_response( GTK_DIALOG(dialog), GTK_RESPONSE_OK ); + gtk_window_set_resizable( GTK_WINDOW(dialog), FALSE ); + g_signal_connect( G_OBJECT(dialog), "response", + G_CALLBACK( gtk_widget_hide ), G_OBJECT(dialog ) ); + GtkWidget *hbox1 = gtk_hbox_new( FALSE, 12 ); + gtk_container_set_border_width( GTK_CONTAINER( hbox1 ), 6 ); + GtkWidget *icon = gtk_image_new_from_stock( GTK_STOCK_DIALOG_ERROR, + GTK_ICON_SIZE_DIALOG ); + GtkWidget *label = gtk_label_new( msg ); + gtk_container_add( GTK_CONTAINER( hbox1 ), icon ); + gtk_container_add( GTK_CONTAINER( hbox1 ), label ); + gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), hbox1 ); + gtk_widget_show_all( dialog ); + + int n = gtk_dialog_run(GTK_DIALOG(dialog)); + + gtk_widget_destroy(dialog); + + return n; +} + +void veejay_quit( ) +{ + if( prompt_dialog("Quit veejay", "Close Veejay ? All unsaved work will be lost." ) + == GTK_RESPONSE_REJECT ) + return; + single_vims( 600 ); + +// clear_progress_bar( "cpumeter",0.0 ); + clear_progress_bar( "connecting",0.0 ); + clear_progress_bar( "samplerecord_progress",0.0 ); + clear_progress_bar( "streamrecord_progress",0.0 ); + clear_progress_bar( "seq_rec_progress",0.0); + exit(0); +} + +static int running_g_ = 1; +static int restart_ = 0; + +int gveejay_restart() +{ + return restart_; +} + +gboolean gveejay_running() +{ + if(!running_g_) + return FALSE; + return TRUE; +} + +gboolean gveejay_quit( GtkWidget *widget, gpointer user_data) +{ + if(!running_g_) + return FALSE; + + if( info->watch.state == STATE_PLAYING) + { + if( prompt_dialog("Quit Reloaded", "Are you sure?" ) == GTK_RESPONSE_REJECT) + return TRUE; + } + + running_g_ = 0; + info->watch.state = STATE_QUIT; + + return FALSE; +} + +/* Free the slot */ +static void free_slot( sample_slot_t *slot ) +{ + if(slot) + { + if(slot->title) free(slot->title); + if(slot->timecode) free(slot->timecode); + free(slot); + } + slot = NULL; +} + +/* Allocate some memory and create a temporary slot */ +sample_slot_t *create_temporary_slot( gint slot_id, gint id, gint type, gchar *title, gchar *timecode ) +{ + sample_slot_t *slot = (sample_slot_t*) vj_calloc(sizeof(sample_slot_t)); + if(id>0) + { + slot->sample_id = id; + slot->sample_type = type; + slot->timecode = strdup(timecode); + slot->title = strdup(title); + slot->slot_number = slot_id; + } + return slot; +} + +int is_current_track(char *host, int port ) +{ + char *remote = get_text( "entry_hostname" ); + int num = get_nums( "button_portnum" ); + if( strncasecmp( remote, host, strlen(host)) == 0 && port == num ) + return 1; + return 0; +} + +static void gveejay_error_slot( int mode ) +{ + char message[255]; + sprintf(message, "Failed to create a new slot. Make sure to check the properties of the %s you are trying to load", + (mode == MODE_SAMPLE ? "sample" : (mode==MODE_STREAM ? "stream" : "sample/stream"))); + message_dialog( "Error", message ); +} + +/* Create a new slot in the sample bank, This function is called by + all VIMS commands that create a new stream or a new sample */ +int gveejay_new_slot(int mode) +{ + int id = 0; + int result_len = 0; + gchar *result = recv_vims( 3, &result_len ); +#ifdef STRICT_CHECKING + //@ err + assert( result_len >= 0 ); + assert( result != NULL ); +#endif + if(result_len <= 0 ) + { + veejay_msg(0, "No reply from veejay-server, but expected new sample/slot identifier"); + return 0; + } + + sscanf( result, "%d", &id ); + + free(result); + + if( id <= 0 ) + { + veejay_msg(0, "Error creating new sample slot"); + // gveejay_error_slot( mode ); + return 0; + } + + return id; +} + +void gveejay_popup_err( const char *type, char *msg ) +{ + message_dialog( type, msg ); +} + +void reportbug(); +void update_gui(); + +#include "callback.c" +enum +{ + COLOR_RED=0, + COLOR_BLUE=1, + COLOR_GREEN=2, + COLOR_BLACK=3, + COLOR_NUM +}; + +void vj_msg(int type, const char format[], ...) +{ + if( type == VEEJAY_MSG_DEBUG && vims_verbosity == 0 ) + return; + + char tmp[1024]; + char buf[1024]; + char prefix[20]; + va_list args; + + va_start( args,format ); + vsnprintf( tmp, sizeof(tmp), format, args ); + + switch(type) + { + case 2: sprintf(prefix,"Info : ");break; + case 1: sprintf(prefix,"Warning: ");break; + case 0: sprintf(prefix,"Error : ");break; + case 3: + sprintf(prefix,"Debug : ");break; + case 4: + sprintf(prefix, " ");break; + } + + snprintf(buf, sizeof(buf), "%s %s\n",prefix,tmp ); + gsize nr,nw; + gchar *text = g_locale_to_utf8( buf, -1, &nr, &nw, NULL); + text[strlen(text)-1] = '\0'; + + GtkWidget *sb = glade_xml_get_widget_( info->main_window, "statusbar"); + gtk_statusbar_push( GTK_STATUSBAR(sb),0, text ); + + g_free( text ); + va_end(args); +} + +void msg_vims(char *message) +{ + if(!info->client) + return; + int n = vj_client_send(info->client, V_CMD, message); + if( n <= 0 ) + reloaded_schedule_restart(); +} + +int get_loop_value() +{ + if( is_button_toggled( "loop_none" ) ) + { + return 0; + } + else + { + if( is_button_toggled( "loop_normal" )) + return 1; + else + if( is_button_toggled( "loop_pingpong" )) + return 2; + else if (is_button_toggled("loop_random")) + return 3; + } + return 1; +} + +static void multi_vims(int id, const char format[],...) +{ + char block[1024]; + char tmp[1024]; + va_list args; + if(!info->client) + return; + va_start(args, format); + vsnprintf(tmp, sizeof(tmp)-1, format, args ); + snprintf(block, sizeof(block)-1, "%03d:%s;",id,tmp); + va_end(args); + + if(vj_client_send( info->client, V_CMD, block)<=0 ) + reloaded_schedule_restart(); +} + +static void single_vims(int id) +{ + char block[10]; + if(!info->client) + return; + sprintf(block, "%03d:;",id); + if(vj_client_send( info->client, V_CMD, block)<=0 ) + reloaded_schedule_restart(); + +} + + +static gchar *recv_vims(int slen, int *bytes_written) +{ + int tmp_len = slen+1; + unsigned char tmp[tmp_len]; + veejay_memset(tmp,0,sizeof(tmp)); + int ret = vj_client_read( info->client, V_CMD, tmp, slen ); + if( ret == -1 ) + reloaded_schedule_restart(); + int len = 0; + if( sscanf( (char*)tmp, "%d", &len ) != 1 ) + return NULL; + unsigned char *result = NULL; + if( ret <= 0 || len <= 0 || slen <= 0) + return (gchar*)result; + result = (unsigned char*) vj_calloc(sizeof(unsigned char) * (len + 1) ); + *bytes_written = vj_client_read( info->client, V_CMD, result, len ); + if( *bytes_written == -1 ) + reloaded_schedule_restart(); + return (gchar*)result; +} + +static gdouble get_numd(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name); + if(!w) return 0; + return (gdouble) gtk_spin_button_get_value( GTK_SPIN_BUTTON( w ) ); +} + +static int get_slider_val(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) return 0; + return ((gint)GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment)->value); +} + +static void vj_kf_select_parameter(int num) +{ + sample_slot_t *s = info->selected_slot; + if(!s) return; + + info->uc.selected_parameter_id = num; + + GtkWidget *curve = glade_xml_get_widget_(info->main_window, "curve"); + + reset_curve( curve ); + + update_curve_accessibility("curve"); + update_curve_widget("curve"); + + char name[20]; + sprintf(name, "P%d", info->uc.selected_parameter_id); + update_label_str( "curve_parameter", name ); +} + +static void vj_kf_refresh() +{ + GtkWidget *curve = glade_xml_get_widget_(info->main_window, "curve"); + + + reset_curve( curve ); + + update_curve_accessibility("curve"); + update_curve_widget("curve"); + char name[20]; + sprintf(name, "P%d", info->uc.selected_parameter_id); + update_label_str( "curve_parameter", name ); + +} + +static void update_curve_widget(const char *name) +{ + GtkWidget *curve = glade_xml_get_widget_( info->main_window,name); + sample_slot_t *s = info->selected_slot; + if(!s ) return; + int i = info->uc.selected_chain_entry; /* chain entry */ + int id = info->uc.entry_tokens[ENTRY_FXID]; + int blen = 0; + int lo = 0, hi = 0, curve_type=0; + int p = -1; + multi_vims( VIMS_SAMPLE_KF_GET, "%d %d",i,info->uc.selected_parameter_id ); + + unsigned char *blob = (unsigned char*) recv_vims( 8, &blen ); + if( blob && blen > 0 ) + { + p = set_points_in_curve_ext( curve, blob,id,i, &lo,&hi, &curve_type ); + if( p >= 0 ) + { + char but[25]; + sprintf(but, "kf_p%d", p); + set_toggle_button( but, 1 ); + + info->uc.selected_parameter_id = p; + switch( curve_type ) + { + case GTK_CURVE_TYPE_LINEAR: set_toggle_button( "curve_typelinear", 1 ); break; + case GTK_CURVE_TYPE_SPLINE: set_toggle_button( "curve_typespline", 1 ); break; + case GTK_CURVE_TYPE_FREE: set_toggle_button( "curve_typefree",1 ); break; + default: + break; + } + } + } + + if( lo == hi && hi == 0 ) + { + if( info->status_tokens[PLAY_MODE] == MODE_SAMPLE ) + { + lo = info->status_tokens[SAMPLE_START]; + hi = info->status_tokens[SAMPLE_END]; + } + else + { + lo = 0; + hi = get_nums("stream_length"); + } + } + + update_spin_range( "curve_spinstart", lo, hi, lo ); + update_spin_range( "curve_spinend", lo, hi, hi ); + + + if(blob) free(blob); +} + +static void update_curve_accessibility(const char *name) +{ + sample_slot_t *s = info->selected_slot; + if(!s ) return; + + if( info->status_tokens[PLAY_MODE] == MODE_PLAIN ) + { + disable_widget( "frame_fxtree3" ); + } + else + { + enable_widget( "frame_fxtree3" ); + } +} + +static int get_nums(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name); + if(!w) { + veejay_msg(0, "No such widget (spin): '%s'",name); + return 0; + } + return (int) gtk_spin_button_get_value( GTK_SPIN_BUTTON( w ) ); +} + +static int count_textview_buffer(const char *name) +{ + GtkWidget *view = glade_xml_get_widget_( info->main_window, name ); + if(view) + { + GtkTextBuffer *tb = NULL; + tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(view) ); + return gtk_text_buffer_get_char_count( tb ); + } + return 0; +} + +static void clear_textview_buffer(const char *name) +{ + GtkWidget *view = glade_xml_get_widget_( info->main_window, name ); + if(!view) { + veejay_msg(0, "No such widget (textview): '%s'",name); + return; + } + if(view) + { + GtkTextBuffer *tb = NULL; + tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(view) ); + GtkTextIter iter1,iter2; + gtk_text_buffer_get_start_iter( tb, &iter1 ); + gtk_text_buffer_get_end_iter( tb, &iter2 ); + gtk_text_buffer_delete( tb, &iter1, &iter2 ); + } +} + +static gchar *get_textview_buffer(const char *name) +{ + GtkWidget *view = glade_xml_get_widget_( info->main_window,name ); + if(!view) { + veejay_msg(0, "No such widget (textview): '%s'",name); + return NULL; + } + if(view) + { + GtkTextBuffer *tb = NULL; + tb = gtk_text_view_get_buffer( GTK_TEXT_VIEW(view) ); + GtkTextIter iter1,iter2; + + gtk_text_buffer_get_start_iter(tb, &iter1); + gtk_text_buffer_get_end_iter( tb, &iter2); + gchar *res = gtk_text_buffer_get_text( tb, &iter1,&iter2 , TRUE ); + return res; + } + return NULL; +} + +static void set_textview_buffer(const char *name, gchar *utf8text) +{ + GtkWidget *view = glade_xml_get_widget_( info->main_window, name ); + if(!view) { + veejay_msg(0, "No such widget (textview): '%s'",name); + return; + } + if(view) + { + GtkTextBuffer *tb = gtk_text_view_get_buffer( + GTK_TEXT_VIEW(view) ); + gtk_text_buffer_set_text( tb, utf8text, -1 ); + } +} + +static gchar *get_text(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (text): '%s'",name); + return NULL; + } + return (gchar*) gtk_entry_get_text( GTK_ENTRY(w)); +} + +static void put_text(const char *name, char *text) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (text): '%s'",name); + return; + } + if(w) + { + gchar *utf8_text = _utf8str( text ); + gtk_entry_set_text( GTK_ENTRY(w), utf8_text ); + g_free(utf8_text); + } +} + +int is_button_toggled(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name); + if(!w) { + veejay_msg(0, "No such widget (togglebutton): '%s'",name); + return 0; + } + + if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(w) ) == TRUE ) + return 1; + return 0; +} +static void set_toggle_button(const char *name, int status) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (togglebutton): '%s'",name); + return; + } + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (status==1 ? TRUE: FALSE)); + +} + + +static void update_slider_gvalue(const char *name, gdouble value) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (slider): '%s'",name); + return; + } + gtk_adjustment_set_value( + GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment), value ); +} + +static void update_slider_value(const char *name, gint value, gint scale) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (slider): '%s'",name); + return; + } + gdouble gvalue; + if(scale) + gvalue = (gdouble) value / (gdouble) scale; + else + gvalue = (gdouble) value; + + gtk_adjustment_set_value( + GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment), gvalue ); +} +/* +static void update_knob_value(GtkWidget *w, gdouble value, gdouble scale) +{ + GtkAdjustment *adj = gtk_knob_get_adjustment(GTK_KNOB(w)); + gdouble gvalue; + + if(scale) gvalue = (gdouble) value / (gdouble) scale; + else gvalue = (gdouble) value; + + gtk_adjustment_set_value(adj, gvalue ); +}*/ + +/* +static void update_knob_range(GtkWidget *w, gdouble min, gdouble max, gdouble value, gint scaled) +{ + GtkAdjustment *adj = gtk_knob_get_adjustment(GTK_KNOB(w)); + + if(!scaled) + { + adj->lower = min; + adj->upper = max; + adj->value = value; + } + else + { + gdouble gmin =0.0; + gdouble gmax =100.0; + gdouble gval = gmax / value; + adj->lower = gmin; + adj->upper = gmax; + adj->value = gval; + } +}*/ +static void update_spin_incr( const char *name, gdouble step, gdouble page ) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (spin): '%s'",name); + return; + } +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "SpinButton: %s, step=%g,page=%g",name,step,page); +#endif + gtk_spin_button_set_increments(GTK_SPIN_BUTTON(w),step,page ); +} + +static void update_spin_range(const char *name, gint min, gint max, gint val) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (spin): '%s'",name); + return; + } + + gtk_spin_button_set_range( GTK_SPIN_BUTTON(w), (gdouble)min, (gdouble) max ); + gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), (gdouble)val); +} +/*static int get_mins(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) return 0; + GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(w) ); + return (int) adj->lower; +} + + +static int get_maxs(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) return 0; + GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(w) ); + return (int) adj->upper; +}*/ + +static void update_spin_value(const char *name, gint value ) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (spin): '%s'",name); + return; + } +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "SpinButton: %s, value=%d",name,value); +#endif + + gtk_spin_button_set_value( GTK_SPIN_BUTTON(w), (gdouble) value ); +} + +static void update_slider_range(const char *name, gint min, gint max, gint value, gint scaled) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, name ); + if(!w) { + veejay_msg(0, "No such widget (slider): '%s'",name); + return; + } + GtkRange *range = GTK_RANGE(w); + if(!scaled) + { + gtk_range_set_range(range, (gdouble) min, (gdouble) max ); + gtk_range_set_value(range, value ); + } + else + { + gdouble gmin =0.0; + gdouble gmax =100.0; + gdouble gval = gmax / value; + gtk_range_set_range(range, gmin, gmax); + gtk_range_set_value(range, gval ); + } + + gtk_range_set_adjustment(range, GTK_ADJUSTMENT(GTK_RANGE(w)->adjustment ) ); +} + +static void update_label_i(const char *name, int num, int prefix) +{ + GtkWidget *label = glade_xml_get_widget_( + info->main_window, name); + if(!label) { + veejay_msg(0, "No such widget (label): '%s'",name); + return; + } + char str[20]; + if(prefix) + g_snprintf( str,20, "%09d", num ); + else + g_snprintf( str,20, "%d", num ); + gchar *utf8_value = _utf8str( str ); + gtk_label_set_text( GTK_LABEL(label), utf8_value); + g_free( utf8_value ); +} +static void update_label_f(const char *name, float val ) +{ + GtkWidget *label = glade_xml_get_widget_( + info->main_window, name); + if(!label) { + veejay_msg(0, "No such widget (label): '%s'",name); + return; + } + char value[10]; + snprintf( value, sizeof(value)-1, "%2.2f", val ); + + gchar *utf8_value = _utf8str( value ); + gtk_label_set_text( GTK_LABEL(label), utf8_value ); + g_free(utf8_value); +} +static void update_label_str(const char *name, gchar *text) +{ + GtkWidget *label = glade_xml_get_widget_( + info->main_window, name); +#ifdef STRICT_CHECKING + if(!label) veejay_msg(0, "No such widget (label): '%s'",name); + assert( label != NULL ); +#else + if(!label ||!text) return; +#endif + gchar *utf8_text = _utf8str( text ); + if(!utf8_text) return; + gtk_label_set_text( GTK_LABEL(label), utf8_text); + g_free(utf8_text); +} + +static void selection_get_paths(GtkTreeModel *model, GtkTreePath *path, + GtkTreeIter *iter, gpointer data) +{ + GSList **paths = data; + + *paths = g_slist_prepend(*paths, gtk_tree_path_copy(path)); +} + + +GSList *gui_tree_selection_get_paths(GtkTreeView *view) +{ + GtkTreeSelection *sel; + GSList *paths; + + /* get paths of selected rows */ + paths = NULL; + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_selected_foreach(sel, selection_get_paths, &paths); + + return paths; +} + +static void update_colorselection() +{ + GtkWidget *colorsel = glade_xml_get_widget_( info->main_window, + "colorselection"); + GdkColor color; + + color.red = 255 * info->status_tokens[STREAM_COL_R]; + color.green = 255 * info->status_tokens[STREAM_COL_G]; + color.blue = 255 * info->status_tokens[STREAM_COL_B]; + + gtk_color_selection_set_current_color( + GTK_COLOR_SELECTION( colorsel ), + &color ); +} + +int resize_primary_ratio_y() +{ + float ratio = (float)info->el.width / (float)info->el.height; + float result = (float) get_nums( "priout_width" ) / ratio; + return (int) result; +} + +int resize_primary_ratio_x() +{ + float ratio = (float)info->el.height / (float)info->el.width; + float result = (float) get_nums( "priout_height" ) / ratio; + return (int) result; +} + +static void update_rgbkey() +{ + if(!info->entry_lock) + { + info->entry_lock =1; + GtkWidget *colorsel = glade_xml_get_widget_( info->main_window, + "rgbkey"); + GdkColor color; + /* update from entry tokens (delivered by GET_CHAIN_ENTRY */ + int *p = &(info->uc.entry_tokens[0]); + /* 0 = effect_id, 1 = has second input, 2 = num parameters, + 3 = p0 , 4 = p1, 5 = p2, 6 = p3 ... */ + + + color.red = 255 * p[3]; + color.green = 255 * p[4]; + color.blue = 255 * p[5]; + + gtk_color_selection_set_current_color( + GTK_COLOR_SELECTION( colorsel ), + &color ); + info->entry_lock = 0; + } +} + +static void update_rgbkey_from_slider() +{ + if(!info->entry_lock) + { + GtkWidget *colorsel = glade_xml_get_widget_( info->main_window, + "rgbkey"); + info->entry_lock = 1; + GdkColor color; + + color.red = 255 * ( get_slider_val( "slider_p1" ) ); + color.green = 255 * ( get_slider_val( "slider_p2" ) ); + color.blue = 255 * ( get_slider_val( "slider_p3" ) ); + + gtk_color_selection_set_current_color( + GTK_COLOR_SELECTION( colorsel ), + &color ); + info->entry_lock = 0; + } +} + +static void v4l_expander_toggle(int mode) +{ + // we can set the expanded of the ABC expander + GtkWidget *exp = glade_xml_get_widget_( + info->main_window, "v4l_expander"); + GtkExpander *e = GTK_EXPANDER(exp); + gtk_expander_set_expanded( e ,(mode==0 ? FALSE : TRUE) ); +} + +int update_gveejay() +{ + return vj_midi_handle_events( info->midi ); +} + +static GdkPixbuf *update_pixmap_kf( int status ) +{ + char path[MAX_PATH_LEN]; + char filename[MAX_PATH_LEN]; + veejay_memset( filename, 0,sizeof(filename)); + + sprintf(filename, "fx_entry_%s.png", ( status == 1 ? "on" : "off" )); + get_gd(path,NULL, filename); + + GError *error = NULL; + GdkPixbuf *toggle = gdk_pixbuf_new_from_file( path , &error); + if(error) + return NULL; + return toggle; +} +static GdkPixbuf *update_pixmap_entry( int status ) +{ + char path[MAX_PATH_LEN]; + char filename[MAX_PATH_LEN]; + veejay_memset( filename,0,sizeof(filename)); + + sprintf(filename, "fx_entry_%s.png", ( status == 1 ? "on" : "off" )); + get_gd(path,NULL, filename); + + GError *error = NULL; + GdkPixbuf *icon = gdk_pixbuf_new_from_file(path, &error); + if(error) + return 0; + return icon; +} + +static gboolean +chain_update_row(GtkTreeModel * model, GtkTreePath * path, GtkTreeIter * iter, + gpointer data) +{ + + vj_gui_t *gui = (vj_gui_t*) data; + if(!gui->selected_slot) + return FALSE; + int entry = info->uc.selected_chain_entry; + gint gentry = 0; + gtk_tree_model_get (model, iter, + FXC_ID, &gentry, -1); + + if(gentry == entry) + { + int effect_id = gui->uc.entry_tokens[ ENTRY_FXID ]; + if( effect_id <= 0 ) + { + gtk_list_store_set( GTK_LIST_STORE(model),iter, FXC_ID, entry, -1 ); + } + else + { + gchar *descr = _utf8str( _effect_get_description( effect_id )); + int on = gui->uc.entry_tokens[16]; + GdkPixbuf *toggle = update_pixmap_entry( gui->uc.entry_tokens[ENTRY_FXSTATUS] ); + GdkPixbuf *kf_toggle = update_pixmap_kf( on ); + gtk_list_store_set( GTK_LIST_STORE(model),iter, + FXC_ID, entry, + FXC_FXID, descr, + FXC_FXSTATUS, toggle, + FXC_KF, kf_toggle, -1 ); + g_free(descr); + g_object_unref( kf_toggle ); + g_object_unref( toggle ); + } + } + + return FALSE; +} + +/* Cut from global_info() + This function updates the sample/stream editor if the current playing stream/sample + matches with the selected sample slot */ + +static void update_record_tab(int pm) +{ + if(pm == MODE_STREAM) + { + update_spin_value( "spin_streamduration" , 1 ); + gint n_frames = get_nums( "spin_streamduration" ); + gchar *time = format_time(n_frames, (double) info->el.fps); + update_label_str( "label_streamrecord_duration", time ); + g_free(time); + } + if(pm == MODE_SAMPLE) + { + update_spin_value( "spin_sampleduration", 1 ); + // combo_samplecodec + gint n_frames = sample_calctime(); + gchar *time = format_time( n_frames,(double) info->el.fps ); + update_label_str( "label_samplerecord_duration", time ); + g_free(time); + } +} + +static void update_current_slot(int *history, int pm, int last_pm) +{ + gint update = 0; + + if( pm != last_pm || info->status_tokens[CURRENT_ID] != history[CURRENT_ID] ) + { + int k; + info->uc.reload_hint[HINT_ENTRY] = 1; + info->uc.reload_hint[HINT_CHAIN] = 1; + info->uc.reload_hint[HINT_KF] = 1; + update = 1; + update_record_tab( pm ); + + if( info->status_tokens[STREAM_TYPE] == STREAM_WHITE ) + { + enable_widget( "colorselection" ); + } + else + { + disable_widget( "colorselection" ); + } + + if( info->status_tokens[STREAM_TYPE] == STREAM_VIDEO4LINUX ) + { + info->uc.reload_hint[HINT_V4L] = 1; + for(k = 1; capt_card_set[k].name != NULL; k ++ ) + enable_widget( capt_card_set[k].name ); + v4l_expander_toggle(1); + } + else + { /* not v4l, disable capt card */ + for(k = 1; capt_card_set[k].name != NULL ; k ++ ) + disable_widget( capt_card_set[k].name ); + + v4l_expander_toggle(0); + } + + info->uc.reload_hint[HINT_HISTORY] = 1; + + put_text( "entry_samplename", "" ); + set_pm_page_label( info->status_tokens[CURRENT_ID], pm ); + + //HERE + + } + if( info->status_tokens[CURRENT_ENTRY] != history[CURRENT_ENTRY] || + info->uc.reload_hint[HINT_ENTRY] == 1 ) + { + info->uc.selected_chain_entry = info->status_tokens[CURRENT_ENTRY]; + if(info->uc.selected_chain_entry < 0 || info->uc.selected_chain_entry > 19 ) + info->uc.selected_chain_entry = 0; + info->uc.reload_hint[HINT_ENTRY] = 1; + load_parameter_info(); + info->uc.reload_hint[HINT_KF] = 1; + } + + /* Actions for stream */ + if( ( info->status_tokens[CURRENT_ID] != history[CURRENT_ID] || pm != last_pm ) && pm == MODE_STREAM ) + { + /* Is a solid color stream */ + if( info->status_tokens[STREAM_TYPE] == STREAM_WHITE ) + { + if( ( history[STREAM_COL_R] != info->status_tokens[STREAM_COL_R] ) || + ( history[STREAM_COL_G] != info->status_tokens[STREAM_COL_G] ) || + ( history[STREAM_COL_B] != info->status_tokens[STREAM_COL_B] ) ) + { + info->uc.reload_hint[HINT_RGBSOLID] = 1; + } + + } + + gchar *time = format_time( info->status_frame,(double)info->el.fps ); + update_label_str( "label_curtime", time ); + g_free(time); + + update_label_str( "playhint", "Streaming"); + } + + /* Actions for sample */ + if( ( info->status_tokens[CURRENT_ID] != history[CURRENT_ID] || last_pm != pm) && pm == MODE_SAMPLE ) + { + int marker_go = 0; + /* Update marker bounds */ + if( (history[SAMPLE_MARKER_START] != info->status_tokens[SAMPLE_MARKER_START]) ) + { + update = 1; + gint nm = info->status_tokens[SAMPLE_MARKER_START]; + if(nm >= 0) + { + gdouble in = (1.0 / (gdouble)info->status_tokens[TOTAL_FRAMES]) * nm; + timeline_set_in_point( info->tl, in ); + marker_go = 1; + } + else + { + if(pm == MODE_SAMPLE) + { + timeline_set_in_point( info->tl, 0.0 ); + marker_go = 1; + } + } + gchar *dur = format_time( info->status_tokens[SAMPLE_MARKER_END] - info->status_tokens[SAMPLE_MARKER_START], + (double)info->el.fps ); + update_label_str( "label_markerduration", dur ); + g_free(dur); + } + + if( (history[SAMPLE_MARKER_END] != info->status_tokens[SAMPLE_MARKER_END]) ) + { + gint nm = info->status_tokens[SAMPLE_MARKER_END]; + if(nm > 0 ) + { + gdouble out = (1.0/ (gdouble)info->status_tokens[TOTAL_FRAMES]) * nm; + + timeline_set_out_point( info->tl, out ); + marker_go = 1; + } + else + { + if(pm == MODE_SAMPLE) + { + timeline_set_out_point(info->tl, 1.0 ); + marker_go = 1; + } + } + update = 1; + } + + if( (history[SAMPLE_START] != info->status_tokens[SAMPLE_START] )) + { + update_spin_value( "spin_samplestart", info->status_tokens[SAMPLE_START] ); + update = 1; + } + if( (history[SAMPLE_END] != info->status_tokens[SAMPLE_END] )) + { + update_spin_value( "spin_sampleend", info->status_tokens[SAMPLE_END]); + update = 1; + } + + if( marker_go ) + { + info->uc.reload_hint[HINT_MARKER] = 1; + } + + if( history[SAMPLE_LOOP] != info->status_tokens[SAMPLE_LOOP]) + { + switch( info->status_tokens[SAMPLE_LOOP] ) + { + case 0: + set_toggle_button( "loop_none", 1 ); + break; + case 1: + set_toggle_button( "loop_normal", 1 ); + break; + case 2: + set_toggle_button("loop_pingpong", 1 ); + break; + case 3: + set_toggle_button("loop_random", 1 ); + break; + } + } + + gint speed = info->status_tokens[SAMPLE_SPEED]; + + + if( history[SAMPLE_SPEED] != info->status_tokens[SAMPLE_SPEED] ) + { + speed = info->status_tokens[SAMPLE_SPEED]; + update_slider_value( "speed_slider", speed, 0 ); + + if( speed < 0 ) info->play_direction = -1; else info->play_direction = 1; + if( speed < 0 ) speed *= -1; + update_spin_value( "spin_samplespeed", speed); + + if( pm == MODE_SAMPLE ) { + if( speed == 0 ) + update_label_str( "playhint", "Paused" ); + else + update_label_str( "playhint", "Playing"); + } + } + + if( history[FRAME_DUP] != info->status_tokens[FRAME_DUP] ) + { + update_spin_value( "spin_framedelay", info->status_tokens[FRAME_DUP]); + update_slider_value("slow_slider", info->status_tokens[FRAME_DUP],0); + } + + + if(update) + { + speed = info->status_tokens[SAMPLE_SPEED]; + if(speed < 0 ) info->play_direction = -1; else info->play_direction = 1; + + gint len = info->status_tokens[SAMPLE_END] - info->status_tokens[SAMPLE_START]; + + int speed = info->status_tokens[SAMPLE_SPEED]; + if(speed < 0 ) info->play_direction = -1; else info->play_direction = 1; + if(speed < 0 ) speed *= -1; + + update_spin_range( "spin_samplespeed", -1 * len, len, speed ); + + gchar *time = format_selection_time( 0, len ); + g_free(time); + + update_spin_value( "spin_samplestart", info->status_tokens[SAMPLE_START]); + update_spin_value( "spin_sampleend", info->status_tokens[SAMPLE_END]); + + gint n_frames = sample_calctime(); + + timeline_set_length( info->tl, + (gdouble) n_frames , info->status_tokens[FRAME_NUM]- info->status_tokens[SAMPLE_START] ); + + + update_spin_range( "spin_text_start", 0, n_frames ,0); + update_spin_range( "spin_text_end", 0, n_frames,n_frames ); + + info->uc.reload_hint[HINT_KF] = 1; + } + } + + + if( pm == MODE_SAMPLE|| pm == MODE_STREAM ) + if( history[CHAIN_FADE] != info->status_tokens[CHAIN_FADE] ) + { + double val = (double) info->status_tokens[CHAIN_FADE]; + update_slider_value( "manualopacity", val,0 ); + } + +} + + +static void +on_vims_messenger (void) +{ + GtkTextIter start, end; + GtkTextBuffer* buffer; + GtkTextView* t= NULL; + gchar *str = NULL; + static int wait = 0; + t = + GTK_TEXT_VIEW(GTK_WIDGET(glade_xml_get_widget(info->main_window,"vims_messenger_textview"))); + + buffer = gtk_text_view_get_buffer(t); + + if(info->vims_line >= gtk_text_buffer_get_line_count(buffer)){ + info->vims_line = 0; + if(!is_button_toggled( "vims_messenger_loop")) + { + set_toggle_button( "vims_messenger_play", 0 ); + return; + } + } + + if(is_button_toggled( "vims_messenger_play" )){ + if(wait){ + wait--; + } + else{ + gtk_text_buffer_get_iter_at_line(buffer, &start, info->vims_line); + end = start; + + gtk_text_iter_forward_sentence_end(&end); + str = gtk_text_buffer_get_text (buffer, &start, &end, TRUE); + + if(str[0] == '+'){ + str[0] = ' '; + g_strstrip(str); + wait = atoi(str); + } + else{ + vj_msg(VEEJAY_MSG_INFO, "User defined VIMS message sent '%s'",str ); + msg_vims( str ); + printf("\nSent VIMS: %s", str); + } + info->vims_line++; + } + } +} + +static int total_frames_ = 0; + +int get_total_frames() +{ + return total_frames_; +} +/* +static char *bugbuffer_ = NULL; +static int bugoffset_ = 0; + +gboolean capture_data (GIOChannel *source, GIOCondition condition, gpointer data ) +{ + int fd = g_io_channel_unix_get_fd( source ); + GIOStatus ret; + GError *err = NULL; + gchar *msg; + gsize len; + + if (condition & G_IO_HUP) + g_error ("Read end of pipe died!\n"); + + ret = g_io_channel_read_line (source, &msg, &len, NULL, &err); + if (ret == G_IO_STATUS_ERROR) + g_error ("Error reading: %s\n", err->message); + + memcpy( bugbuffer_ + (sizeof(char) * bugoffset_) , msg , len ); + + bugoffset_ += len; + + g_free (msg); + return TRUE; +} +*/ +void reportbug() +{ + char l[3] = { 'e','n', '\0'}; + char *lang = getenv("LANG"); + char URL[1024]; + + if(lang) { + l[0] = lang[0]; + l[1] = lang[1]; + } +/* char veejay_homedir[1024]; + char body[1024]; + char subj[100]; + gchar **argv = (gchar**) malloc ( sizeof(gchar*) * 5 ); + int i; + argv[0] = malloc( sizeof(char) * 100 ); + memset( argv[0], 0, sizeof(char) * 100 ); + argv[2] = NULL; + +// snprintf(subj,sizeof(subj),"reloaded %s has a problem", VERSION); + snprintf(veejay_homedir, sizeof(veejay_homedir),"%s/.veejay/", home ); + sprintf(argv[0], "%s/report_problem.sh" ,veejay_homedir); + argv[1] = strdup( veejay_homedir ); + + if( bugoffset_ > 0 ) { + free(bugbuffer_); + bugoffset_= 0; + bugbuffer_ = NULL; + } + +// GError error = NULL; + gint stdout_pipe = 0; + gint pid =0; + gboolean ret = g_spawn_async_with_pipes( + NULL, + argv, + NULL, + G_SPAWN_LEAVE_DESCRIPTORS_OPEN & G_SPAWN_STDERR_TO_DEV_NULL, + NULL, + NULL, + &pid, + NULL, + &stdout_pipe, + NULL, + NULL ); + if( !ret ) { + veejay_msg(0, "Error executing bug report tool"); + return; + } + + GIOChannel *chan = g_io_channel_unix_new( stdout_pipe ); + bugbuffer_ = (char*) malloc(sizeof(char) * 32000 ); + memset(bugbuffer_, 0, sizeof(char) * 32000); + guint retb = g_io_add_watch( chan, G_IO_IN, capture_data, NULL ); +*/ +// if( prompt_dialog("Report a problem", "" ) +// == GTK_RESPONSE_ACCEPT ) + snprintf(URL , sizeof(URL), + "firefox http://groups.google.com/group/veejay-discussion/post?hl=%s",l ); + + printf(URL); + + system(URL); +} + + +static void reset_tree(const char *name) +{ + GtkWidget *tree_widget = glade_xml_get_widget_( info->main_window,name ); + GtkTreeModel *tree_model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree_widget) ); + + gtk_list_store_clear( GTK_LIST_STORE( tree_model ) ); + +} + + +// load effect controls + +gboolean + view_entry_selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer userdata) + { + GtkTreeIter iter; + if (gtk_tree_model_get_iter(model, &iter, path)) + { + gint name = 0; + + gtk_tree_model_get(model, &iter, FXC_ID, &name, -1); + if (!path_currently_selected && name != info->uc.selected_chain_entry) + { + multi_vims( VIMS_CHAIN_SET_ENTRY, "%d", name ); + vj_midi_learning_vims_msg( info->midi, NULL, VIMS_CHAIN_SET_ENTRY, info->uc.selected_chain_entry ); + } + } + + return TRUE; /* allow selection state to change */ + } + +gboolean + cali_sources_selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer userdata) + { + GtkTreeIter iter; + if (gtk_tree_model_get_iter(model, &iter, path)) + { + gchar *name = NULL; + + if( info->uc.cali_stage != 0 ) { + veejay_msg(0, "%d", info->uc.cali_stage); + return TRUE; + } + + gtk_tree_model_get(model, &iter, FXC_ID, &name, -1); + + if (!path_currently_selected) + { + gint id = 0; + sscanf(name+1, "[ %d]", &id); + if(name[0] != 'S') + { + cali_stream_id = id; + update_label_str("current_step_label","Please take an image with the cap on the lens."); + GtkWidget *nb = glade_xml_get_widget_(info->main_window, "cali_notebook"); + gtk_notebook_next_page( GTK_NOTEBOOK(nb)); + } + if(name) g_free(name); + } + } + return TRUE; /* allow selection state to change */ +} + +gboolean + view_sources_selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer userdata) + { + GtkTreeIter iter; + if (gtk_tree_model_get_iter(model, &iter, path)) + { + gchar *name = NULL; + + gtk_tree_model_get(model, &iter, FXC_ID, &name, -1); + + if (!path_currently_selected) + { + gint id = 0; + sscanf(name+1, "[ %d]", &id); + if(name[0] == 'S') + { + info->uc.selected_mix_sample_id = id; + info->uc.selected_mix_stream_id = 0; + } + else + { + info->uc.selected_mix_sample_id = 0; + info->uc.selected_mix_stream_id = id; + } + } + + if(name) g_free(name); + } + + return TRUE; /* allow selection state to change */ + } + + +static void +cell_data_func_dev (GtkTreeViewColumn *col, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + gchar buf[32]; + GValue val = {0, }; + gtk_tree_model_get_value(model, iter, V4L_SPINBOX, &val); + g_snprintf(buf, sizeof(buf), "%.0f",g_value_get_float(&val)); + g_object_set(cell, "text", buf, NULL); +} + +static void +on_dev_edited (GtkCellRendererText *celltext, + const gchar *string_path, + const gchar *new_text, + gpointer data) +{ + GtkTreeModel *model = GTK_TREE_MODEL(data); + GtkTreeIter iter; + gfloat oldval = 0.0; + gfloat newval = 0.0; + + gtk_tree_model_get_iter_from_string(model, &iter, string_path); + + gtk_tree_model_get(model, &iter, V4L_SPINBOX, &oldval, -1); + if (sscanf(new_text, "%f", &newval) != 1) + g_warning("in %s: problem converting string '%s' into float.\n", __FUNCTION__, new_text); + + gtk_list_store_set(GTK_LIST_STORE(model), &iter, V4L_SPINBOX, newval, -1); + +} + + +static void setup_tree_spin_column( const char *tree_name, int type, const char *title) +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, tree_name ); + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + renderer = gui_cell_renderer_spin_new(0.0, 3.0 , 1.0, 1.0, 1.0, 1.0, 0.0); + column = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(column, title ); + gtk_tree_view_column_pack_start(column, renderer, TRUE); + gtk_tree_view_column_set_cell_data_func( column, renderer, + cell_data_func_dev, NULL,NULL ); + gtk_tree_view_append_column( GTK_TREE_VIEW(tree), column); + g_object_set(renderer, "editable", TRUE, NULL); + + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); + g_signal_connect(renderer, "edited", G_CALLBACK(on_dev_edited), model ); + +} + +static void setup_tree_text_column( const char *tree_name, int type, const char *title,int len ) +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, tree_name ); + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes( title, renderer, "text", type, NULL ); + gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); + + if(len) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Tree %s ,Title %s, width=%d", tree_name,title, len ); + gtk_tree_view_column_set_min_width( column, len); + } +} + +static void setup_tree_pixmap_column( const char *tree_name, int type, const char *title ) +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, tree_name ); + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + renderer = gtk_cell_renderer_pixbuf_new(); + column = gtk_tree_view_column_new_with_attributes( title, renderer, "pixbuf", type, NULL ); + gtk_tree_view_append_column( GTK_TREE_VIEW( tree ), column ); +} +void + server_files_selection_func (GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + model = gtk_tree_view_get_model(treeview); + + if(gtk_tree_model_get_iter(model,&iter,path)) + { + gchar *name = NULL; + gtk_tree_model_get(model, &iter, 0, &name, -1); + + multi_vims(VIMS_EDITLIST_ADD_SAMPLE, "0 %s" , name ); + vj_msg(VEEJAY_MSG_INFO, "Tried to open %s",name); + gveejay_new_slot(MODE_SAMPLE); + g_free(name); + + } + + } +static void setup_server_files(void) +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "server_files"); + GtkListStore *store = gtk_list_store_new( 1, G_TYPE_STRING ); + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + g_object_unref( G_OBJECT( store )); + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); + + setup_tree_text_column( "server_files", 0, "Filename",0 ); + // gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + // gtk_tree_selection_set_select_function(selection, server_files_selection_func, NULL, NULL); + + g_signal_connect( tree, "row-activated", (GCallback) server_files_selection_func, NULL); + +} + +static void setup_effectchain_info( void ) +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_chain"); + GtkListStore *store = gtk_list_store_new( 4, G_TYPE_INT, G_TYPE_STRING, GDK_TYPE_PIXBUF,GDK_TYPE_PIXBUF ); + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + g_object_unref( G_OBJECT( store )); + + setup_tree_text_column( "tree_chain", FXC_ID, "#",0 ); + setup_tree_text_column( "tree_chain", FXC_FXID, "Effect",0 ); //FIXME + setup_tree_pixmap_column( "tree_chain", FXC_FXSTATUS, "Run"); // todo: could be checkbox!! + setup_tree_pixmap_column( "tree_chain", FXC_KF , "Anim" ); // parameter interpolation on/off per entry + GtkTreeSelection *selection; + + tree = glade_xml_get_widget_( info->main_window, "tree_chain"); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + gtk_tree_selection_set_select_function(selection, view_entry_selection_func, NULL, NULL); +} + + + +static void load_v4l_info() +{ + int values[6]; + int len = 0; +/* multi_vims( VIMS_STREAM_GET_V4L, "%d", (info->selected_slot == NULL ? 0 : info->selected_slot->sample_id )); + gchar *answer = recv_vims(3, &len); + if(len > 0 ) + { + int res = sscanf( answer, "%05d%05d%05d%05d%05d%05d", + &values[0],&values[1],&values[2],&values[3],&values[4],&values[5]); + if(res == 6) + { + int i; + for(i = 1; i < 7; i ++ ) + { + update_slider_gvalue( capt_card_set[i].name, (gdouble)values[i-1]/65535.0 ); + } + } + g_free(answer); + }*/ +} + +static gint load_parameter_info() +{ + int *st = &(info->uc.entry_tokens[0]); + int len = 0; + int p[20]; + int i; + + veejay_memset( p, 0, sizeof(p)); + + multi_vims( VIMS_CHAIN_GET_ENTRY, "%d %d", 0, + info->uc.selected_chain_entry ); + + gchar *answer = recv_vims(3,&len); + if(len <= 0 || answer == NULL ) + { + if(answer) g_free(answer); + for( i = 0; i < 16; i ++ ) + st[i] = 0; + if(info->uc.selected_rgbkey ) + disable_widget("rgbkey"); + return 0; + } + int res = sscanf( answer, + "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + p+0,p+1,p+2,p+3,p+4,p+5,p+6,p+7,p+8,p+9,p+10, + p+11,p+12,p+13,p+14,p+15, p + 16, p+17,p+18,p+19); + + if( res <= 0 ) + { + for( i = 0; i < 20; i ++ ) + st[i] = 0; + return 0; + } + + info->uc.selected_rgbkey = _effect_get_rgb( p[0] ); + if(info->uc.selected_rgbkey) + { + enable_widget( "rgbkey"); + update_rgbkey(); + } + else + { + disable_widget( "rgbkey"); + info->uc.selected_rgbkey = 0; + } + + for( i = 0; i < 20; i ++ ) + st[i] = p[i]; + + set_toggle_button( "curve_toggleentry", p[16] ); + + if(info->status_tokens[PLAY_MODE] == MODE_SAMPLE ) + { + update_spin_range( "curve_spinstart", + info->status_tokens[SAMPLE_START], + info->status_tokens[SAMPLE_END], p[17] ); + update_spin_range( "curve_spinend", info->status_tokens[SAMPLE_START], + info->status_tokens[SAMPLE_END] ,p[18] ); + } + else + { + int nl = get_nums("stream_length") + 1 ; + update_spin_range( "curve_spinstart", 0, nl, p[17] ); + update_spin_range( "curve_spinend", 0,nl, p[18] ); + } + + switch( p[19] ) + { + case GTK_CURVE_TYPE_LINEAR: set_toggle_button( "curve_typelinear", 1 ); break; + case GTK_CURVE_TYPE_SPLINE: set_toggle_button( "curve_typespline", 1 ); break; + case GTK_CURVE_TYPE_FREE: set_toggle_button( "curve_typefree",1 ); break; + default: + break; + } + + + g_free(answer); + + return 1; +} + + +// load effect chain +static void load_effectchain_info() +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_chain"); + GtkListStore *store; + + GtkTreeIter iter; + gint offset=0; + + gint fxlen = 0; + multi_vims( VIMS_CHAIN_LIST,"%d",0 ); + gchar *fxtext = recv_vims(3,&fxlen); + + reset_tree( "tree_chain" ); + + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); + store = GTK_LIST_STORE(model); + + if(fxlen <= 0 ) + { + int i; + for( i = 0; i < 20; i ++ ) + { + gtk_list_store_append(store,&iter); + gtk_list_store_set(store,&iter, FXC_ID, i ,-1); + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + } + return; + } + + if(fxlen == 5 ) + offset = fxlen; + + gint last_index =0; + + while( offset < fxlen ) + { + gchar toggle[4]; + gchar kf_toggle[4]; + guint arr[6]; + veejay_memset(toggle,0,4); + veejay_memset(kf_toggle,0,4); + veejay_memset(arr,0,sizeof(arr)); + char line[12]; + veejay_memset(line,0,sizeof(line)); + strncpy( line, fxtext + offset, 8 ); + sscanf( line, "%02d%03d%1d%1d%1d", + &arr[0],&arr[1],&arr[2],&arr[3],&arr[4]); + + char *name = _effect_get_description( arr[1] ); + sprintf(toggle,"%s", + arr[3] == 1 ? "on" : "off" ); + + while( last_index < arr[0] ) + { + gtk_list_store_append( store, &iter ); + gtk_list_store_set( store, &iter, FXC_ID, last_index,-1); + last_index ++; + } + + if( last_index == arr[0]) + { + gchar *utf8_name = _utf8str( name ); + int on = info->uc.entry_tokens[16]; + gtk_list_store_append( store, &iter ); + GdkPixbuf *toggle = update_pixmap_entry( arr[3] ); + GdkPixbuf *kf_toggle = update_pixmap_kf( on ); + gtk_list_store_set( store, &iter, + FXC_ID, arr[0], + FXC_FXID, utf8_name, + FXC_FXSTATUS, toggle, + FXC_KF, kf_toggle, -1 ); + last_index ++; + g_free(utf8_name); + g_object_unref( toggle ); + g_object_unref( kf_toggle ); + } + offset += 8; + } + while( last_index < 20 ) + { + gtk_list_store_append( store, &iter ); + gtk_list_store_set( store, &iter, + FXC_ID, last_index , -1 ); + last_index ++; + } + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + g_free(fxtext); +} + +enum +{ +// FX_ID = 0, + FX_STRING = 0, + FX_NUM, +}; + +gboolean + view_fx_selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer userdata) + { + GtkTreeIter iter; + + if (gtk_tree_model_get_iter(model, &iter, path)) + { + // gint name; + gchar *name = NULL; + gtk_tree_model_get(model, &iter, FX_STRING, &name, -1); + + if (!path_currently_selected) + { + int value = 0; + vevo_property_get( fx_list_, name, 0, &value ); + if(value) info->uc.selected_effect_id = value; + } + g_free(name); + + } + + return TRUE; /* allow selection state to change */ + } +void +on_effectmixlist_row_activated(GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + model = gtk_tree_view_get_model(treeview); + if(gtk_tree_model_get_iter(model,&iter,path)) + { + gint gid =0; + gchar *name = NULL; + gtk_tree_model_get(model,&iter, FX_STRING, &name, -1); // FX_ID + + if(vevo_property_get( fx_list_, name, 0,&gid ) == 0 ) + { + multi_vims(VIMS_CHAIN_ENTRY_SET_EFFECT, "%d %d %d", + 0, info->uc.selected_chain_entry,gid ); + info->uc.reload_hint[HINT_ENTRY] = 1; + + char trip[100]; + snprintf(trip,sizeof(trip), "%03d:%d %d %d;", VIMS_CHAIN_ENTRY_SET_EFFECT,0,info->uc.selected_chain_entry, gid ); + vj_midi_learning_vims( info->midi, NULL, trip, 0 ); + } + g_free(name); + } +} +void +on_effectlist_row_activated(GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + model = gtk_tree_view_get_model(treeview); + + if(gtk_tree_model_get_iter(model,&iter,path)) + { + gint gid =0; + gchar *name = NULL; + gtk_tree_model_get(model,&iter, FX_STRING, &name, -1); + + if(vevo_property_get( fx_list_, name, 0, &gid ) == 0 ) + { + multi_vims(VIMS_CHAIN_ENTRY_SET_EFFECT, "%d %d %d", + 0, info->uc.selected_chain_entry,gid ); + info->uc.reload_hint[HINT_ENTRY] = 1; + char trip[100]; + snprintf(trip,sizeof(trip), "%03d:%d %d %d;", VIMS_CHAIN_ENTRY_SET_EFFECT,0,info->uc.selected_chain_entry, gid ); + vj_midi_learning_vims( info->midi, NULL, trip, 0 ); + + } + g_free(name); + } + +} +gint +sort_iter_compare_func( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, + gpointer userdata) +{ + gint sortcol = GPOINTER_TO_INT(userdata); + gint ret = 0; + + if(sortcol == FX_STRING) + { + gchar *name1=NULL; + gchar *name2=NULL; + gtk_tree_model_get(model,a, FX_STRING, &name1, -1 ); + gtk_tree_model_get(model,b, FX_STRING, &name2, -1 ); + if( name1 == NULL || name2 == NULL ) + { + if( name1==NULL && name2==NULL) + { + return 0; + } + ret = (name1 == NULL) ? -1 : 1; + } + else + { + ret = g_utf8_collate(name1,name2); + } + if(name1) g_free(name1); + if(name2) g_free(name2); + } + return ret; +} + + + +gint +sort_vims_func( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, + gpointer userdata) +{ + gint sortcol = GPOINTER_TO_INT(userdata); + gint ret = 0; + + if(sortcol == VIMS_ID) + { + gchar *name1 = NULL; + gchar *name2 = NULL; + + gtk_tree_model_get(model,a, VIMS_ID, &name1, -1 ); + gtk_tree_model_get(model,b, VIMS_ID, &name2, -1 ); + if( name1 == NULL || name2 == NULL ) + { + if( name1==NULL && name2== NULL) + { + return 0; + } + ret = (name1==NULL) ? -1 : 1; + } + else + { + ret = g_utf8_collate(name1,name2); + } + if(name1) g_free(name1); + if(name2) g_free(name2); + } + return ret; +} + +// load effectlist from veejay +void setup_effectlist_info() +{ + int i; + GtkWidget *trees[2]; + trees[0] = glade_xml_get_widget_( info->main_window, "tree_effectlist"); + trees[1] = glade_xml_get_widget_( info->main_window, "tree_effectmixlist"); + GtkListStore *stores[2]; + stores[0] = gtk_list_store_new( 1, G_TYPE_STRING ); + stores[1] = gtk_list_store_new( 1, G_TYPE_STRING ); + + + fx_list_ = (vevo_port_t*) vpn( 200 ); + + for(i = 0; i < 2; i ++ ) + { + GtkTreeSortable *sortable = GTK_TREE_SORTABLE(stores[i]); + gtk_tree_sortable_set_sort_func( + sortable, FX_STRING, sort_iter_compare_func, + GINT_TO_POINTER(FX_STRING),NULL); + + gtk_tree_sortable_set_sort_column_id( + sortable, FX_STRING, GTK_SORT_ASCENDING); + + gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(trees[i]), FALSE ); + + gtk_tree_view_set_model( GTK_TREE_VIEW(trees[i]), GTK_TREE_MODEL(stores[i])); + g_object_unref( G_OBJECT( stores[i] )); + } + + + setup_tree_text_column( "tree_effectlist", FX_STRING, "Effect",0 ); + + setup_tree_text_column( "tree_effectmixlist", FX_STRING, "Effect",0 ); + + g_signal_connect( trees[0], "row-activated", + (GCallback) on_effectlist_row_activated, NULL ); + + g_signal_connect( trees[1] ,"row-activated", + (GCallback) on_effectmixlist_row_activated, NULL ); + + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(trees[0])); + gtk_tree_selection_set_select_function(selection, view_fx_selection_func, NULL, NULL); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + + selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(trees[1] )); + gtk_tree_selection_set_select_function( selection, view_fx_selection_func, NULL,NULL ); + gtk_tree_selection_set_mode( selection, GTK_SELECTION_SINGLE ); + +} + + +void +on_effectlist_sources_row_activated(GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + model = gtk_tree_view_get_model(treeview); + + + if(gtk_tree_model_get_iter(model,&iter,path)) + { + gchar *idstr = NULL; + gtk_tree_model_get(model,&iter, SL_ID, &idstr, -1); + gint id = 0; + if( sscanf( idstr+1, "[ %d]", &id ) ) + { + // set source / channel + multi_vims( VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, + "%d %d %d %d", + 0, + info->uc.selected_chain_entry, + ( idstr[0] == 'T' ? 1 : 0 ), + id ); + vj_msg(VEEJAY_MSG_INFO, "Set source channel to %d, %d", info->uc.selected_chain_entry,id ); + + + char trip[100]; + snprintf(trip, sizeof(trip), "%03d:%d %d %d %d",VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, + 0, + info->uc.selected_chain_entry, + ( idstr[0] == 'T' ? 1 : 0 ), + id ); + vj_midi_learning_vims( info->midi, NULL, trip, 0 ); + } + if(idstr) g_free(idstr); + } +} + +/* Return a bank page and slot number to place sample in */ + +int verify_bank_capacity(int *bank_page_, int *slot_, int sample_id, int sample_type ) +{ + int poke_slot = 0; + int bank_page = find_bank_by_sample( sample_id, sample_type, &poke_slot ); + + if(bank_page == -1) { + veejay_msg(0, "No slot found for (%d,%d)",sample_id,sample_type); + return 0; + } + + if( !bank_exists(bank_page, poke_slot)) + add_bank( bank_page ); + + *bank_page_ = bank_page; + *slot_ = poke_slot; + +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "(type=%d,id=%d) needs new slot, suggesting page %d, slot %d", + sample_type, sample_id, bank_page, poke_slot ); + +// if( info->sample_banks[bank_page] ) +// assert( info->sample_banks[bank_page]->slot[poke_slot]->sample_id <= 0 ); + + +#endif + + return 1; +} + + +void setup_samplelist_info() +{ + effect_sources_tree = glade_xml_get_widget_( info->main_window, "tree_sources"); + effect_sources_store = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); + + gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(effect_sources_tree), FALSE ); + + gtk_tree_view_set_model( GTK_TREE_VIEW(effect_sources_tree), GTK_TREE_MODEL(effect_sources_store)); + g_object_unref( G_OBJECT( effect_sources_store )); + effect_sources_model = gtk_tree_view_get_model( GTK_TREE_VIEW(effect_sources_tree )); + effect_sources_store = GTK_LIST_STORE(effect_sources_model); + + setup_tree_text_column( "tree_sources", SL_ID, "Id",0 ); + setup_tree_text_column( "tree_sources", SL_TIMECODE, "Length" ,0); + + GtkTreeSelection *selection; + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(effect_sources_tree)); + gtk_tree_selection_set_select_function(selection, view_sources_selection_func, NULL, NULL); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + + g_signal_connect( effect_sources_tree, "row-activated", (GCallback) on_effectlist_sources_row_activated, (gpointer*)"tree_sources"); + + + + cali_sourcetree = glade_xml_get_widget_(info->main_window, "cali_sourcetree"); + cali_sourcestore= gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ); + + gtk_tree_view_set_headers_visible( GTK_TREE_VIEW( cali_sourcetree), FALSE ); + gtk_tree_view_set_model( GTK_TREE_VIEW(cali_sourcetree), GTK_TREE_MODEL(cali_sourcestore)); + g_object_unref( G_OBJECT(cali_sourcestore)); + + cali_sourcemodel = gtk_tree_view_get_model( GTK_TREE_VIEW(cali_sourcetree )); + cali_sourcestore = GTK_LIST_STORE(cali_sourcemodel); + + setup_tree_text_column( "cali_sourcetree", SL_ID, "Id",0 ); + setup_tree_text_column( "cali_sourcetree", SL_TIMECODE, "Length" ,0); + + GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(cali_sourcetree)); + gtk_tree_selection_set_select_function(sel, cali_sources_selection_func, NULL, NULL); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + +// g_signal_connect( cali_sourcetree, "row-activated", (GCallback) on_effectlist_sources_row_activated, (gpointer*)"tree_sources"); + + +} + +static uint8_t *ref_trashcan[3] = { NULL,NULL,NULL }; +static GdkPixbuf *pix_trashcan[3] = { NULL,NULL,NULL }; + +void reset_cali_images( int type, char *wid_name ) +{ + GtkWidget *dstImage = glade_xml_get_widget( + info->main_window, wid_name ); + + if( pix_trashcan[type] != NULL ) { + gdk_pixbuf_unref( pix_trashcan[type] ); + pix_trashcan[type] = NULL; + } + if( ref_trashcan[type] != NULL ) { + free( ref_trashcan[type] ); + ref_trashcan[type] = NULL; + } + gtk_image_clear( dstImage ); + +} + +int get_and_draw_frame(int type, char *wid_name) +{ + GtkWidget *dstImage = glade_xml_get_widget( + info->main_window, wid_name ); + if(dstImage == 0 ) { + veejay_msg(0, "No widget '%s'",wid_name); + return 0; + } + + multi_vims( VIMS_CALI_IMAGE, "%d %d", cali_stream_id,type); + + int bw = 0; + gchar *buf = recv_vims( 3, &bw ); + + if( bw <= 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to get calibration image."); + return 0; + } + + int len = 0; + int uvlen = 0; + int w = 0; + int h = 0; + int tlen = 0; + int n = sscanf(buf,"%08d%06d%06d%06d%06d",&tlen, &len, &uvlen,&w,&h); + + uint8_t *out = (uint8_t*) vj_malloc(sizeof(uint8_t) * (w*h*3)); + uint8_t *srcbuf = (uint8_t*) vj_malloc(sizeof(uint8_t) * len ); + + int res = vj_client_read(info->client, V_CMD, srcbuf, tlen ); + if( res <= 0 ) { + free(out); + free(srcbuf); + free(buf); + veejay_msg(0, "Error while receiving calibration image."); + return 0; + } + + VJFrame *src = yuv_yuv_template( srcbuf, + srcbuf, + srcbuf, + w, + h, + PIX_FMT_GRAY8 ); + + VJFrame *dst = yuv_rgb_template( out, w,h,PIX_FMT_BGR24 ); + + yuv_convert_any_ac( src,dst, src->format, dst->format ); + + GdkPixbuf *pix = gdk_pixbuf_new_from_data( + out, + GDK_COLORSPACE_RGB, + FALSE, + 8, + w, + h, + w*3, + NULL, + NULL ); + + if( ref_trashcan[type] != NULL ) { + free(ref_trashcan[type]); + ref_trashcan[type]=NULL; + } + if( pix_trashcan[type] != NULL ) { + gdk_pixbuf_unref( pix_trashcan[type] ); + pix_trashcan[type] = NULL; + } + + gtk_image_set_from_pixbuf_( GTK_IMAGE( dstImage ), pix ); + +// gdk_pixbuf_unref( pix ); + + free(src); + free(dst); + free(buf); +// free(out); + free(srcbuf); + + ref_trashcan[type] = out; + pix_trashcan[type] = pix; + + return 1; +} + +void load_effectlist_info() +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_effectlist"); + GtkWidget *tree2 = glade_xml_get_widget_( info->main_window, "tree_effectmixlist"); + GtkListStore *store,*store2; + + GtkTreeIter iter; + gint i,offset=0; + + + gint fxlen = 0; + single_vims( VIMS_EFFECT_LIST ); + gchar *fxtext = recv_vims(5,&fxlen); + _effect_reset(); + reset_tree( "tree_effectlist"); + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); + store = GTK_LIST_STORE(model); + + GtkTreeModel *model2 = gtk_tree_view_get_model( GTK_TREE_VIEW(tree2)); + store2 = GTK_LIST_STORE(model2); + while( offset < fxlen ) + { + char tmp_len[4]; + veejay_memset(tmp_len,0,sizeof(tmp_len)); + strncpy(tmp_len, fxtext + offset, 3 ); + int len = atoi(tmp_len); + offset += 3; + if(len > 0) + { + effect_constr *ec; + char line[255]; + veejay_memset( line,0,sizeof(line)); + strncpy( line, fxtext + offset, len ); + ec = _effect_new(line); + if(ec) info->effect_info = g_list_append( info->effect_info, ec ); + } + offset += len; + } + + fxlen = g_list_length( info->effect_info ); + for( i = 0; i < fxlen; i ++) + { + + effect_constr *ec = g_list_nth_data( info->effect_info, i ); + gchar *name = _utf8str( _effect_get_description( ec->id ) ); + if( name != NULL) + { + if( _effect_get_mix(ec->id) > 0 ) + { + gtk_list_store_append( store2, &iter ); + gtk_list_store_set( store2, &iter, FX_STRING, name, -1 ); + vevo_property_set( fx_list_, name, LIVIDO_ATOM_TYPE_INT, 1, &(ec->id)); + } + else + { + gtk_list_store_append( store, &iter ); + gtk_list_store_set( store, &iter, FX_STRING, name, -1 ); + vevo_property_set( fx_list_, name, LIVIDO_ATOM_TYPE_INT, 1, &(ec->id)); + } + + } + g_free(name); + } + + + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + gtk_tree_view_set_model( GTK_TREE_VIEW(tree2), GTK_TREE_MODEL(store2)); + g_free(fxtext); + +} + +static void select_slot__( int pm ) +{ + int *history = info->history_tokens[ pm ]; +#ifdef STRICT_CHECKING + assert( history != NULL ); +#endif + + if( pm == MODE_SAMPLE || pm == MODE_STREAM ) + { + int b = 0; int p = 0; + /* falsify activation */ + if(info->status_tokens[CURRENT_ID] > 0) + { + if(verify_bank_capacity( &b, &p, info->status_tokens[CURRENT_ID],pm )) + { + if( info->selected_slot ) { + if ( info->selected_slot->sample_type != pm || info->selected_slot->sample_id != + info->selected_slot->sample_id ) { + set_activation_of_slot_in_samplebank(FALSE); + } + } + info->selected_slot = info->sample_banks[b]->slot[p]; + info->selected_gui_slot = info->sample_banks[b]->gui_slot[p]; + set_activation_of_slot_in_samplebank(TRUE); + } + /*bank_page = find_bank_by_sample( info->status_tokens[CURRENT_ID], pm, &poke_slot ); + + info->selected_slot= info->sample_banks[bank_page]->slot[poke_slot]; + info->selected_gui_slot= info->sample_banks[bank_page]->gui_slot[poke_slot];*/ + + } + } + else { + set_activation_of_slot_in_samplebank(FALSE); + info->selected_slot = NULL; + info->selected_gui_slot = NULL; + } +} + +static void select_slot_(int pm, const char *f, int line) +{ + select_slot__(pm); +} + +static void load_sequence_list() +{ + single_vims( VIMS_SEQUENCE_LIST ); + gint len = 0; + gchar *text = recv_vims( 6, &len ); + if( len <= 0 || text == NULL ) + return; + + int playing=0; + int size =0; + int active=0; + + sscanf( text, "%04d%04d%4d",&playing,&size,&active ); + int nlen = len - 12; + int offset = 0; + int id = 0; + gchar *in = text + 12; + while( offset < nlen ) + { + int sample_id = 0; + char seqtext[32]; + sscanf( in + offset, "%04d", &sample_id ); + offset += 4; + if( sample_id > 0 ) + { + sprintf(seqtext,"%d",sample_id); + gtk_label_set_text( + GTK_LABEL(info->sequencer_view->gui_slot[id]->image), + seqtext ); + } + else + { + gtk_label_set_text( + GTK_LABEL(info->sequencer_view->gui_slot[id]->image), + NULL ); + } + + id ++; + } + g_free(text); + +} + +static void load_samplelist_info(gboolean with_reset_slotselection) +{ + gint offset=0; + int has_samples = 0; + int has_streams = 0; + int n_slots = 0; + reset_tree( "tree_sources" ); + if( cali_onoff == 1 ) + reset_tree( "cali_sourcetree"); + + if( with_reset_slotselection ) { + reset_samplebank(); + } + + char tmp[5]; + int slen = 1; + memset(tmp,0,sizeof(tmp)); + + multi_vims( VIMS_SAMPLE_LIST,"%d", 0 ); + gint fxlen = 0; +/* while(vj_client_read( info->client, V_CMD, tmp, slen )) { + + veejay_msg(0, "'%c'", tmp[0] ); + }*/ + + gchar *fxtext = recv_vims(8,&fxlen); + + if(fxlen > 0 && fxtext != NULL) + { + has_samples = 1; + while( offset < fxlen ) + { + char tmp_len[8]; + veejay_memset(tmp_len,0,sizeof(tmp_len)); + strncpy(tmp_len, fxtext + offset, 3 ); + int len = atoi(tmp_len); + offset += 3; + if(len > 0) + { + char line[300]; + char descr[255]; + veejay_memset( line,0,sizeof(line)); + veejay_memset( descr,0,sizeof(descr)); + strncpy( line, fxtext + offset, len ); + + int values[4]; +#ifdef STRICT_CHECKING + veejay_msg( VEEJAY_MSG_DEBUG, "[%s]", line); + int res = sscanf( line, "%05d%09d%09d%03d", + &values[0], &values[1], &values[2], &values[3]); + veejay_msg(VEEJAY_MSG_DEBUG, + "%d , %d, %d, %d res=%d",values[0],values[1], + values[2],values[3],res ); + assert( res == 4 ); +#else + sscanf( line, "%05d%09d%09d%03d", + &values[0], &values[1], &values[2], &values[3]); +#endif + strncpy( descr, line + 5 + 9 + 9 + 3 , values[3] ); + gchar *title = _utf8str( descr ); + gchar *timecode = format_selection_time( 0,(values[2]-values[1]) ); + int int_id = values[0]; + int poke_slot= 0; int bank_page = 0; + + verify_bank_capacity( &bank_page , &poke_slot, int_id, 0); + if(bank_page >= 0 ) + { + if( info->sample_banks[bank_page]->slot[poke_slot]->sample_id <= 0 ) + { + sample_slot_t *tmp_slot = create_temporary_slot(poke_slot,int_id,0, title,timecode ); + add_sample_to_sample_banks(bank_page, tmp_slot ); + free_slot(tmp_slot); + n_slots ++; + } + else + { + update_sample_slot_data( bank_page, poke_slot, int_id,0,title,timecode); + } + } + if( info->status_tokens[CURRENT_ID] == values[0] && info->status_tokens[PLAY_MODE] == 0 ) + put_text( "entry_samplename", title ); + g_free(timecode); + g_free(title); + } + offset += len; + } + offset = 0; + } + + if( fxtext ) g_free(fxtext); + fxlen = 0; + + multi_vims( VIMS_STREAM_LIST,"%d",0 ); + fxtext = recv_vims(5, &fxlen); + if( fxlen > 0 && fxtext != NULL) + { + has_streams = 1; + while( offset < fxlen ) + { + char tmp_len[4]; + veejay_memset(tmp_len,0,sizeof(tmp_len)); + strncpy(tmp_len, fxtext + offset, 3 ); + + int len = atoi(tmp_len); + offset += 3; + if(len > 0) + { + char line[300]; + char source[255]; + char descr[255]; + veejay_memset(line,0,sizeof(line)); + veejay_memset(descr,0,sizeof(descr)); + strncpy( line, fxtext + offset, len ); + + int values[10]; + + veejay_memset(values,0, sizeof(values)); + + sscanf( line, "%05d%02d%03d%03d%03d%03d%03d%03d", + &values[0], &values[1], &values[2], + &values[3], &values[4], &values[5], + &values[6], &values[7] + ); + strncpy( descr, line + 22, values[6] ); + switch( values[1] ) + { + case STREAM_CALI :sprintf(source,"calibrate %d",values[0]); + break; + case STREAM_VIDEO4LINUX :sprintf(source,"capture %d",values[0]);break; + case STREAM_WHITE :sprintf(source,"solid %d",values[0]); + break; + case STREAM_MCAST :sprintf(source,"multicast %d",values[0]);break; + case STREAM_NETWORK :sprintf(source,"unicast %d",values[0]);break; + case STREAM_YUV4MPEG :sprintf(source,"y4n %d",values[0]);break; + case STREAM_DV1394 :sprintf(source,"dv1394 %d",values[0]);break; + case STREAM_PICTURE :sprintf(source,"image %d",values[0]);break; + default: + sprintf(source,"??? %d", values[0]); + } + gchar *gsource = _utf8str( descr ); + gchar *gtype = _utf8str( source ); + + int bank_page = 0; + int poke_slot = 0; + + verify_bank_capacity( &bank_page , &poke_slot, values[0], 1); + + if(bank_page >= 0) + { + if( info->sample_banks[bank_page]->slot[poke_slot] <= 0 ) + { + sample_slot_t *tmp_slot = create_temporary_slot(poke_slot,values[0],1, gtype,gsource ); + add_sample_to_sample_banks(bank_page, tmp_slot ); n_slots ++; + free_slot(tmp_slot); + } + else + { + update_sample_slot_data( bank_page, poke_slot, values[0],1,gsource,gtype); + } + } + g_free(gsource); + g_free(gtype); + } + offset += len; + } + + } + + if(fxtext) g_free(fxtext); +} + +gboolean + view_el_selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer userdata) + { + GtkTreeIter iter; + + if (gtk_tree_model_get_iter(model, &iter, path)) + { + gint num = 0; + + gtk_tree_model_get(model, &iter, COLUMN_INT, &num, -1); + + if (!path_currently_selected) + { + info->uc.selected_el_entry = num; + gint frame_num =0; + frame_num = _el_ref_start_frame( num ); + update_spin_value( "button_el_selstart", + frame_num); + update_spin_value( "button_el_selend", + _el_ref_end_frame( num ) ); + } + + } + return TRUE; /* allow selection state to change */ + } + +void +on_vims_row_activated(GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + model = gtk_tree_view_get_model(treeview); + if(gtk_tree_model_get_iter(model,&iter,path)) + { + gchar *vimsid = NULL; + gint event_id =0; + gtk_tree_model_get(model,&iter, VIMS_ID, &vimsid, -1); + + if(sscanf( vimsid, "%d", &event_id )) + { + if(event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END) + { + multi_vims( VIMS_BUNDLE, "%d", event_id ); + info->uc.reload_hint[HINT_CHAIN] = 1; + } + else + { + gchar *args = NULL; + gchar *format = NULL; + gtk_tree_model_get(model,&iter, VIMS_FORMAT, &format, -1); + gtk_tree_model_get(model,&iter, VIMS_CONTENTS, &args, -1 ); + + if( event_id == VIMS_QUIT ) + { + if( prompt_dialog("Stop Veejay", "Are you sure ? (All unsaved work will be lost)" ) == + GTK_RESPONSE_REJECT ) + return; + } + if( (format == NULL||args==NULL) || (strlen(format) <= 0) ) + single_vims( event_id ); + else + { + if( args != NULL && strlen(args) > 0 ) + { + char msg[100]; + sprintf(msg, "%03d:%s;", event_id, args ); + msg_vims(msg); + } + } + } + } + if( vimsid ) g_free( vimsid ); + } +} + +gboolean + view_vims_selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + gpointer userdata) + { + GtkTreeIter iter; + if (gtk_tree_model_get_iter(model, &iter, path)) + { + gchar *vimsid = NULL; + gint event_id = 0; + gchar *text = NULL; + gint n_params = 0; + gtk_tree_model_get(model, &iter, VIMS_ID, &vimsid, -1); + gtk_tree_model_get(model, &iter, VIMS_CONTENTS, &text, -1 ); + gtk_tree_model_get(model, &iter, VIMS_PARAMS, &n_params, -1); + int k=0; + int m=0; + gchar *key = NULL; + gchar *mod = NULL; + + gtk_tree_model_get(model,&iter, VIMS_KEY, &key, -1); + gtk_tree_model_get(model,&iter, VIMS_MOD, &mod, -1); + + if(sscanf( vimsid, "%d", &event_id )) + { + k = sdlkey_by_name( key ); + m = sdlmod_by_name( mod ); + + info->uc.selected_vims_entry = event_id; + + if( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END ) + info->uc.selected_vims_type = 0; + else + info->uc.selected_vims_type = 1; + + if(info->uc.selected_vims_args ) + free(info->uc.selected_vims_args); + info->uc.selected_vims_args = NULL; + + if( n_params > 0 && text ) + info->uc.selected_vims_args = strdup( text ); + + info->uc.selected_vims_accel[0] = m; + info->uc.selected_vims_accel[1] = k; + + clear_textview_buffer( "vimsview" ); + if( info->uc.selected_vims_type == 1 && text) + set_textview_buffer( "vimsview", text ); + } + if(vimsid) g_free( vimsid ); + if(text) g_free( text ); + if(key) g_free( key ); + if(mod) g_free( mod ); + } + + return TRUE; /* allow selection state to change */ + } + +void +on_editlist_row_activated(GtkTreeView *treeview, + GtkTreePath *path, + GtkTreeViewColumn *col, + gpointer user_data) +{ + GtkTreeModel *model; + GtkTreeIter iter; + + model = gtk_tree_view_get_model(treeview); + if(gtk_tree_model_get_iter(model,&iter,path)) + { + gint num = 0; + gtk_tree_model_get(model,&iter, COLUMN_INT, &num, -1); + gint frame_num = _el_ref_start_frame( num ); + + multi_vims( VIMS_VIDEO_SET_FRAME, "%d", (int) frame_num ); + } +} + +void +on_stream_color_changed(GtkColorSelection *colorsel, gpointer user_data) +{ + if(!info->status_lock && info->selected_slot) + { + GdkColor current_color; + GtkWidget *colorsel = glade_xml_get_widget_(info->main_window, + "colorselection" ); + gtk_color_selection_get_current_color( + GTK_COLOR_SELECTION( colorsel ), + ¤t_color ); + + gint red = current_color.red / 256.0; + gint green = current_color.green / 256.0; + gint blue = current_color.blue / 256.0; + + multi_vims( VIMS_STREAM_COLOR, "%d %d %d %d", + info->selected_slot->sample_id, + red, + green, + blue + ); + } + +} + + + +static void setup_colorselection() +{ + GtkWidget *sel = glade_xml_get_widget_(info->main_window, "colorselection"); + g_signal_connect( sel, "color-changed", + (GCallback) on_stream_color_changed, NULL ); + +} + +void +on_rgbkey_color_changed(GtkColorSelection *colorsel, gpointer user_data) +{ + if(!info->entry_lock) + { + GdkColor current_color; + GtkWidget *colorsel = glade_xml_get_widget_(info->main_window, + "rgbkey" ); + gtk_color_selection_get_current_color( + GTK_COLOR_SELECTION( colorsel ), + ¤t_color ); + + // scale to 0 - 255 + gint red = current_color.red / 256.0; + gint green = current_color.green / 256.0; + gint blue = current_color.blue / 256.0; + + multi_vims( + VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", + 0, info->uc.selected_chain_entry, 1, red ); + multi_vims( + VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", + 0, info->uc.selected_chain_entry, 2, green ); + multi_vims( + VIMS_CHAIN_ENTRY_SET_ARG_VAL, "%d %d %d %d", + 0, info->uc.selected_chain_entry, 3, blue ); + + info->parameter_lock = 1; + update_slider_value( + "slider_p1", red, 0 ); + update_slider_value( + "slider_p2", green, 0 ); + update_slider_value( + "slider_p3", blue, 0 ); + + info->parameter_lock = 0; + } +} + + +static void setup_rgbkey() +{ + GtkWidget *sel = glade_xml_get_widget_(info->main_window, "rgbkey"); + g_signal_connect( sel, "color-changed", + (GCallback) on_rgbkey_color_changed, NULL ); + +} + +static void setup_vimslist() +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_vims"); + GtkListStore *store = gtk_list_store_new( 2,G_TYPE_STRING, G_TYPE_STRING); + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + g_object_unref( G_OBJECT( store )); + + setup_tree_text_column( "tree_vims", VIMS_ID, "VIMS ID",0); + setup_tree_text_column( "tree_vims", VIMS_DESCR, "Description",0 ); + + GtkTreeSortable *sortable = GTK_TREE_SORTABLE(store); + + gtk_tree_sortable_set_sort_func( + sortable, VIMS_ID, sort_vims_func, + GINT_TO_POINTER(VIMS_ID),NULL); + + gtk_tree_sortable_set_sort_column_id( + sortable, VIMS_ID, GTK_SORT_ASCENDING); +} + + +static void setup_bundles() +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_bundles"); + GtkListStore *store = gtk_list_store_new( 7,G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ,G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING); + + gtk_widget_set_size_request_( tree, 300, -1 ); + + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + GtkTreeSortable *sortable = GTK_TREE_SORTABLE(store); + + gtk_tree_sortable_set_sort_func( + sortable, VIMS_ID, sort_vims_func, + GINT_TO_POINTER(VIMS_ID),NULL); + + gtk_tree_sortable_set_sort_column_id( + sortable, VIMS_ID, GTK_SORT_ASCENDING); + + g_object_unref( G_OBJECT( store )); + + setup_tree_text_column( "tree_bundles", VIMS_ID, "VIMS",0); + setup_tree_text_column( "tree_bundles", VIMS_DESCR, "Description",0 ); + setup_tree_text_column( "tree_bundles", VIMS_KEY, "Key",0); + setup_tree_text_column( "tree_bundles", VIMS_MOD, "Mod",0); + setup_tree_text_column( "tree_bundles", VIMS_PARAMS, "Max args",0); + setup_tree_text_column( "tree_bundles", VIMS_FORMAT, "Format",0 ); + g_signal_connect( tree, "row-activated", + (GCallback) on_vims_row_activated, NULL ); + + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree)); + gtk_tree_selection_set_select_function(selection, view_vims_selection_func, NULL, NULL); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + + GtkWidget *tv = glade_xml_get_widget_( info->main_window, "vimsview" ); + gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(tv), GTK_WRAP_WORD_CHAR ); +} + +static void setup_editlist_info() +{ + editlist_tree = glade_xml_get_widget_( info->main_window, "editlisttree"); + editlist_store = gtk_list_store_new( 5,G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING ,G_TYPE_STRING); + gtk_tree_view_set_model( GTK_TREE_VIEW(editlist_tree), GTK_TREE_MODEL(editlist_store)); + g_object_unref( G_OBJECT( editlist_store )); + editlist_model = gtk_tree_view_get_model( GTK_TREE_VIEW(editlist_tree )); + editlist_store = GTK_LIST_STORE(editlist_model); + + setup_tree_text_column( "editlisttree", COLUMN_INT, "#",0); + setup_tree_text_column( "editlisttree", COLUMN_STRING0, "Timecode",0 ); + setup_tree_text_column( "editlisttree", COLUMN_STRINGA, "Filename",0); + setup_tree_text_column( "editlisttree", COLUMN_STRINGB, "Duration",0); + setup_tree_text_column( "editlisttree", COLUMN_STRINGC, "FOURCC",0); + + g_signal_connect( editlist_tree, "row-activated", + (GCallback) on_editlist_row_activated, NULL ); + + GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(editlist_tree)); + gtk_tree_selection_set_select_function(selection, view_el_selection_func, NULL, NULL); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); +} + +static void reload_keys() +{ + gint len = 0; + single_vims( VIMS_KEYLIST ); + gchar *text = recv_vims( 6, &len ); + gint offset = 0; + + if( len == 0 || text == NULL ) + return; + + gint k,index; + for( k = 0; k < VIMS_MAX ; k ++ ) + { + vims_keys_t *p = &vims_keys_list[k]; + if(p->vims) + free(p->vims); + p->keyval = 0; + p->state = 0; + p->event_id = 0; + p->vims = NULL; + } + + char *ptr = text; + + while( offset < len ) + { + int val[6]; + veejay_memset(val,0,sizeof(val)); + int n = sscanf( ptr + offset, "%04d%03d%03d%03d", &val[0],&val[1],&val[2],&val[3]); + if( n != 4 ) + { + free(text); + return; + } + + offset += 13; + char *message = strndup( ptr + offset , val[3] ); + + offset += val[3]; + + + index = (val[1] * MOD_OFFSET) + val[2]; + + vims_keys_list[ index ].keyval = val[2]; + vims_keys_list[ index ].state = val[1]; + vims_keys_list[ index ].event_id = val[0]; + vims_keys_list[ index ].vims = message; + } + free(text); +} + + +static void reload_bundles() +{ + reload_keys(); + + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_bundles"); + GtkListStore *store; + GtkTreeIter iter; + + gint len = 0; + single_vims( VIMS_BUNDLE_LIST ); + gchar *eltext = recv_vims(6,&len); // msg len + gint offset = 0; + + reset_tree("tree_bundles"); + + if(len == 0 || eltext == NULL ) + { +#ifdef STRICT_CHECKING + assert(eltext != NULL && len > 0); +#endif + return; + } + + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); + store = GTK_LIST_STORE(model); + + char *ptr = eltext; + + while( offset < len ) + { + char *message = NULL; + char *format = NULL; + char *args = NULL; + int val[6]; + + veejay_memset(val,0,sizeof(val)); + + int n = sscanf( ptr + offset, "%04d%03d%03d%04d", &val[0],&val[1],&val[2],&val[3]); + + offset += 14; + + message = strndup( ptr + offset , val[3] ); + offset += val[3]; + + n = sscanf( ptr + offset, "%03d%03d", &val[4], &val[5] ); + + offset += 6; + + if(val[4]) // format string + { + format = strndup( ptr + offset, val[4] ); + offset += val[4]; + } + + if(val[5]) // argument string + { + args = strndup( ptr + offset, val[5] ); + offset += val[5]; + } + + gchar *g_descr = NULL; + gchar *g_format = NULL; + gchar *g_content = NULL; + gchar *g_keyname = sdlkey_by_id( val[1] ); + gchar *g_keymod = sdlmod_by_id( val[2] ); + gchar *g_vims[5]; + + sprintf( (char*) g_vims, "%03d", val[0] ); + + if( val[0] >= VIMS_BUNDLE_START && val[0] < VIMS_BUNDLE_END ) + { + g_content = _utf8str( message ); + } + else + { + g_descr = _utf8str( message ); + if( format ) + g_format = _utf8str( format ); + if( args ) + { + g_content = _utf8str( args ); + //@ set default VIMS argument: + if(vj_event_list[val[0]].args ) + { + free(vj_event_list[val[0]].args ); + vj_event_list[val[0]].args = NULL; + } + vj_event_list[ val[0] ].args = strdup( args ); + } + + } + + gtk_list_store_append( store, &iter ); + gtk_list_store_set(store, &iter, + VIMS_ID, g_vims, + VIMS_DESCR, g_descr, + VIMS_KEY, g_keyname, + VIMS_MOD, g_keymod, + VIMS_PARAMS, vj_event_list[ val[0] ].params, + VIMS_FORMAT, g_format, + VIMS_CONTENTS, g_content, + -1 ); + + if(message) free(message); + if(format) free(format); + if(args) free(args); + + + if( g_descr ) g_free(g_descr ); + if( g_format ) g_free(g_format ); + if( g_content) g_free(g_content ); + + } + /* entry, start frame, end frame */ + + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + + g_free( eltext ); + +} + +static void reload_vimslist() +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "tree_vims"); + GtkListStore *store; + GtkTreeIter iter; + + gint len = 0; + single_vims( VIMS_VIMS_LIST ); + gchar *eltext = recv_vims(5,&len); // msg len + gint offset = 0; + reset_tree("tree_vims"); + + if(len == 0 || eltext == NULL ) + { +#ifdef STRICT_CHECKING + assert(eltext != NULL && len > 0); +#endif + return; + } + + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); + store = GTK_LIST_STORE(model); + + while( offset < len ) + { + char *format = NULL; + char *descr = NULL; + char *line = strndup( eltext + offset, + 14 ); + int val[4]; + sscanf( line, "%04d%02d%03d%03d", + &val[0],&val[1],&val[2],&val[3]); + + char vimsid[5]; + + offset += 12; + if(val[2] > 0) + { + format = strndup( eltext + offset, val[2] ); + offset += val[2]; + } + + if(val[3] > 0 ) + { + descr = strndup( eltext + offset, val[3] ); + offset += val[3]; + } + + + gchar *g_format = (format == NULL ? NULL :_utf8str( format )); + gchar *g_descr = (descr == NULL ? NULL :_utf8str( descr )); + + if(vj_event_list[val[0]].format ) + free(vj_event_list[val[0]].format); + if(vj_event_list[val[0]].descr ) + free(vj_event_list[val[0]].descr); + + gtk_list_store_append( store, &iter ); + + vj_event_list[ val[0] ].event_id = val[0]; + vj_event_list[ val[0] ].params = val[1]; + vj_event_list[ val[0] ].format = (format == NULL ? NULL :_utf8str( format )); + vj_event_list[ val[0] ].descr = (descr == NULL ? NULL : _utf8str( descr )); + + sprintf(vimsid, "%03d", val[0] ); + gtk_list_store_set( store, &iter, + VIMS_ID, vimsid, + VIMS_DESCR, g_descr,-1 ); + + + if(g_format) g_free(g_format); + if(g_descr) g_free(g_descr); + + if(format) free(format); + if(descr) free(descr); + + free( line ); + } + + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + g_free( eltext ); + +} +static void remove_all (GtkComboBox *combo_box) +{ + GtkTreeModel* model = gtk_combo_box_get_model (combo_box); + gtk_list_store_clear (GTK_LIST_STORE(model)); +} + +static char *tokenize_on_space( char *q ) +{ + int n = 0; + char *r = NULL; + char *p = q; + while( *p != '\0' && !isblank( *p ) && *p != ' ' && *p != 20) + { + (*p)++; + n++; + } + if( n <= 0 ) + return NULL; + r = vj_calloc( n+1 ); + strncpy( r, q, n ); + return r; +} + +static int have_srt_ = 0; +static void init_srt_editor() +{ + reload_fontlist(); + update_spin_range( "spin_text_x", 0, info->el.width-1 , 0 ); + update_spin_range( "spin_text_y", 0, info->el.height-1, 0 ); + update_spin_range( "spin_text_size", 10, 500, 40 ); + update_spin_range( "spin_text_start", 0, total_frames_, 0 ); +} + + +static void reload_fontlist() +{ + GtkWidget *box = glade_xml_get_widget( info->main_window, "combobox_fonts"); + remove_all( GTK_COMBO_BOX( box ) ); + single_vims( VIMS_FONT_LIST ); + gint len = 0; + gchar *srts = recv_vims(6,&len ); + gint i = 0; + gchar *p = srts; + + while( i < len ) + { + char tmp[4]; + veejay_memset(tmp,0,sizeof(tmp)); + strncpy(tmp, p, 3 ); + int slen = atoi(tmp); + p += 3; + gchar *seq_str = strndup( p, slen ); + gtk_combo_box_append_text( GTK_COMBO_BOX(box), seq_str ); + p += slen; + free(seq_str); + i += (slen + 3); + } + free(srts); +} + +static void reload_srt() +{ + if(!have_srt_) + { + init_srt_editor(); + have_srt_ = 1; + } + + GtkWidget *box = glade_xml_get_widget( info->main_window, "combobox_textsrt"); + remove_all( GTK_COMBO_BOX( box ) ); + + clear_textview_buffer( "textview_text"); + + single_vims( VIMS_SRT_LIST ); + gint i=0, len = 0; + + gchar *srts = recv_vims(6,&len ); + if( srts == NULL || len <= 0 ) + { + // disable_widget( "SRTframe" ); + return; + } + + gchar *p = srts; + gchar *token = NULL; + + while( i < len ) + { + token = tokenize_on_space( p ); + if(!token) + break; + if(token) + { + gtk_combo_box_append_text( GTK_COMBO_BOX(box),token ); + i += strlen(token) + 1; + free(token); + } + else + i++; + p = srts + i; + } + free(srts); +} +void _edl_reset(void) +{ + if( info->elref != NULL) + { + int n = g_list_length(info->elref); + int i; + for( i = 0; i <=n ; i ++ ) + { + void *ptr = g_list_nth_data( info->elref , i ); + if(ptr) + free(ptr); + } + g_list_free( info->elref ); + } +} + +static void reload_editlist_contents() +{ + GtkWidget *tree = glade_xml_get_widget_( info->main_window, "editlisttree"); + GtkListStore *store; + GtkTreeIter iter; + + gint i; + gint len = 0; + single_vims( VIMS_EDITLIST_LIST ); + gchar *eltext = recv_vims(6,&len); // msg len + gint offset = 0; + gint num_files=0; + reset_tree("editlisttree"); + _el_ref_reset(); + _el_entry_reset(); + _edl_reset(); + + if( eltext == NULL || len < 0 ) + { + return; + } + char str_nf[4]; + + strncpy( str_nf, eltext , sizeof(str_nf)); + sscanf( str_nf, "%04d", &num_files ); + + offset += 4; + int n = 0; + el_constr *el; + + for( i = 0; i < num_files ; i ++ ) + { + int itmp =0; + char *tmp1 = (char*) strndup( eltext+offset, 4 ); + int line_len = 0; + char fourcc[4]; + veejay_memset(fourcc,0,sizeof(fourcc)); + n = sscanf( tmp1, "%04d", &line_len ); // line len + if(line_len>0) + { + offset += 4; + char *line = (char*)strndup( eltext + offset, line_len ); + offset += line_len; + char *tmp = (char*) strndup( line, 3 ); + sscanf(tmp, "%03d",&itmp ); + char *file = strndup( line + 3, itmp ); + free(tmp); + tmp = (char*) strndup( line + 3 + itmp, 16 ); + int a,b,c; + int n = sscanf(tmp, "%04d%010d%02d", &a,&b,&c); + free(tmp); + if( n == 3 ) + { + strncpy(fourcc, line + 3 + itmp + 16, c ); + el = _el_entry_new( i, file, b, fourcc ); + info->editlist = g_list_append( info->editlist, el ); + } + free(line); + free(file); + } + free(tmp1); + } + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(tree )); + store = GTK_LIST_STORE(model); + + int total_frames = 0; // running total of frames + int row_num = 0; + while( offset < len ) + { + char *tmp = (char*)strndup( eltext + offset, (3*16) ); + offset += (3*16); + long nl=0, n1=0,n2=0; + + sscanf( tmp, "%016ld%016ld%016ld", + &nl,&n1,&n2 ); + + if(nl < 0 || nl >= num_files) + { + free(tmp); + g_free(eltext); + return; + } + int file_len = _el_get_nframes( nl ); + if(file_len <= 0) + { + free(tmp); + row_num++; + continue; + } + if(n1 < 0 ) + n1 = 0; + if(n2 >= file_len) + n2 = file_len; + + if(n2 <= n1 ) + { + free(tmp); + row_num++; + continue; + } + + info->elref = g_list_append( info->elref, _el_ref_new( row_num,(int) nl,n1,n2,total_frames ) ) ; + char *tmpname = _el_get_filename(nl); + gchar *fname = get_relative_path(tmpname); + gchar *timecode = format_selection_time( n1,n2 ); + gchar *gfourcc = _utf8str( _el_get_fourcc(nl) ); + gchar *timeline = format_selection_time( 0, total_frames ); + + gtk_list_store_append( store, &iter ); + gtk_list_store_set( store, &iter, + COLUMN_INT, (guint) row_num, + COLUMN_STRING0, timeline, + COLUMN_STRINGA, fname, + COLUMN_STRINGB, timecode, + COLUMN_STRINGC, gfourcc,-1 ); + + g_free(timecode); + g_free(gfourcc); + g_free(fname); + g_free(timeline); + free(tmp); + + total_frames = total_frames + (n2-n1) + 1; + row_num ++; + } + + gtk_tree_view_set_model( GTK_TREE_VIEW(tree), GTK_TREE_MODEL(store)); + + g_free( eltext ); + +} + +// execute after el change: +static void load_editlist_info() +{ + char norm; + float fps; + int values[10]; + long rate = 0; + long dum[2]; + veejay_memset(values, 0, sizeof(values)); + single_vims( VIMS_VIDEO_INFORMATION ); + int len = 0; + gchar *res = recv_vims(3,&len); + if( len <= 0 || res==NULL) + { +#ifdef STRICT_CHECKING + assert(len > 0 && res != NULL); +#endif + return; + } + sscanf( res, "%d %d %d %c %f %d %d %ld %d %ld %ld %d", + &values[0], &values[1], &values[2], &norm,&fps, + &values[4], &values[5], &rate, &values[7], + &dum[0], &dum[1], &values[8]); + char tmp[15]; + snprintf( tmp, sizeof(tmp)-1, "%dx%d", values[0],values[1]); + + info->el.width = values[0]; + info->el.height = values[1]; + info->el.num_frames = dum[1]; + update_label_str( "label_el_wh", tmp ); + snprintf( tmp, sizeof(tmp)-1, "%s", + (norm == 'p' ? "PAL" : "NTSC" ) ); + update_label_str( "label_el_norm", tmp); + update_label_f( "label_el_fps", fps ); + + update_spin_value( "screenshot_width", info->el.width ); + update_spin_value( "screenshot_height", info->el.height ); + + info->el.fps = fps; +#ifdef STRICT_CHECKING + assert( info->el.fps > 0 ); +#endif + info->el.num_files = dum[0]; + snprintf( tmp, sizeof(tmp)-1, "%s", + ( values[2] == 0 ? "progressive" : (values[2] == 1 ? "top first" : "bottom first" ) ) ); + update_label_str( "label_el_inter", tmp ); + update_label_i( "label_el_arate", (int)rate, 0); + update_label_i( "label_el_achans", values[7], 0); + update_label_i( "label_el_abits", values[5], 0); + +/* if( rate == 0 ) + { + enable_widget( "vjframerate" ); + } + else + { + disable_widget( "vjframerate"); + }*/ + + + info->el.ratio = (float)info->el.width / (float) info->el.height; + + if( values[4] == 0 ) + { + disable_widget( "button_5_4" ); + } + else + { + set_toggle_button( "button_5_4", values[8]); + enable_widget( "button_5_4" ); + } + + + g_free(res); +} + + + +#ifndef STRICT_CHECKING +static void disable_widget_(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window,name); + if(!w) { + veejay_msg(0, "Widget '%s' not found",name); + return; + } + gtk_widget_set_sensitive_( GTK_WIDGET(w), FALSE ); +} + +static void enable_widget_(const char *name) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window,name); + if(!w) { + veejay_msg(0, "Widget '%s' not found",name); + return; + } + gtk_widget_set_sensitive_( GTK_WIDGET(w), TRUE ); +} +#else +static void disable_widget_(const char *name, const char *s, int line) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window,name); + if(!w) { + veejay_msg(0, "Widget '%s' not found, caller is %s:%d",name,s,line); + return; + } + gtk_widget_set_sensitive_( GTK_WIDGET(w), FALSE ); +} + +static void enable_widget_(const char *name, const char *s, int line) +{ + GtkWidget *w = glade_xml_get_widget_(info->main_window,name); + if(!w) { + veejay_msg(0, "Widget '%s' not found, caller is %s:%d",name,s,line); + return; + } + gtk_widget_set_sensitive_( GTK_WIDGET(w), TRUE ); +} +#endif + + +static gchar *format_selection_time(int start, int end) +{ + double fps = (double) info->el.fps; + int pos = (end-start); + + return format_time( pos, fps ); +} + + +static gboolean update_cpumeter_timeout( gpointer data ) +{ + gdouble ms = (gdouble)info->status_tokens[ELAPSED_TIME]; + gdouble fs = (gdouble)get_slider_val( "framerate" ); + gdouble lim = (1.0f/fs)*1000.0; + + if( ms < lim ) { + update_label_str( "cpumeter", text_msg_[TEXT_REALTIME].text ); + } else { + char text[32]; + sprintf(text, "%2.2f FPS", ( 1.0f / ms ) * 1000.0 ); + + update_label_str( "cpumeter", text ); + } + return TRUE; +} +static gboolean update_cachemeter_timeout( gpointer data ) +{ + char text[32]; + gint v = info->status_tokens[TOTAL_MEM]; + sprintf(text,"%d MB cached",v); + update_label_str( "cachemeter", text ); + + return TRUE; +} + +static gboolean update_sample_record_timeout(gpointer data) +{ + if( info->uc.playmode == MODE_SAMPLE ) + { + GtkWidget *w; + if( is_button_toggled("seqactive" ) ) + { + w = glade_xml_get_widget_( info->main_window, + "rec_seq_progress" ); + } + else + { + w = glade_xml_get_widget_( info->main_window, + "samplerecord_progress" ); + + } + gdouble tf = info->status_tokens[STREAM_DURATION]; + gdouble cf = info->status_tokens[STREAM_RECORDED]; + + gdouble fraction = cf / tf; + + if(!info->status_tokens[STREAM_RECORDING] ) + { + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), 0.0); + info->samplerecording = 0; + info->uc.recording[MODE_SAMPLE] = 0; + if(info->uc.render_record) + { + info->uc.render_record = 0; // render list has private edl + } + else + { + info->uc.reload_hint[HINT_EL] = 1; + } + return FALSE; + } + else + { + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), + fraction ); + } + } + return TRUE; +} +static gboolean update_stream_record_timeout(gpointer data) +{ + GtkWidget *w = glade_xml_get_widget_( info->main_window, + "streamrecord_progress" ); + if( info->uc.playmode == MODE_STREAM ) + { + gdouble tf = info->status_tokens[STREAM_DURATION]; + gdouble cf = info->status_tokens[STREAM_RECORDED]; + + gdouble fraction = cf / tf; + if(!info->status_tokens[STREAM_RECORDING] ) + { + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), 0.0); + info->streamrecording = 0; + info->uc.recording[MODE_STREAM] = 0; + info->uc.reload_hint[HINT_EL] = 1; // recording finished, reload edl + return FALSE; + } + else + gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR(w), + fraction ); + + } + return TRUE; +} + +static void init_recorder(int total_frames, gint mode) +{ + if(mode == MODE_STREAM) + { + info->streamrecording = g_timeout_add(300, update_stream_record_timeout, (gpointer*) info ); + } + if(mode == MODE_SAMPLE) + { + info->samplerecording = g_timeout_add(300, update_sample_record_timeout, (gpointer*) info ); + } + info->uc.recording[mode] = 1; +} + +static char theme_path[1024]; +static char glade_path[1024]; +static char theme_file[1024]; +static char theme_dir[1024]; +static int use_default_theme_ = 0; +static char **theme_list = NULL; +GtkSettings *theme_settings = NULL; +static int select_f(const struct dirent *d ) +{ + if ((strcmp(d->d_name, ".") == 0) || + (strcmp(d->d_name, "..") == 0)) + return 0; + return 1; +} + +static void set_default_theme() +{ + sprintf( theme_path, "%s", RELOADED_DATADIR); + sprintf( theme_file, "%s/gveejay.rc", RELOADED_DATADIR ); + use_default_theme_ = 1; +} + +void find_user_themes(int theme) +{ + char *home = getenv("HOME"); + char data[1024]; + char location[1024]; + char path[1024]; + veejay_memset( theme_path, 0, sizeof(theme_path)); + veejay_memset( theme_file, 0, sizeof(theme_file)); + + theme_settings = gtk_settings_get_default(); +// snprintf( glade_path, sizeof(glade_path), "%s/gveejay.reloaded.glade",RELOADED_DATADIR); + + + if(!home) + { + if(theme) set_default_theme(); + return; + } + + if(!theme) + { + veejay_msg(VEEJAY_MSG_INFO,"Not loading veejay themes"); + return; + } + snprintf( path, sizeof(path),"%s/.veejay/theme/theme.config", home ); + + int sloppy = open( path,O_RDONLY ); + if( sloppy < 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Theme config '%s' not found, creating default.", path ); + veejay_msg(VEEJAY_MSG_WARNING, "Please setup symbolic links from %s/theme/", RELOADED_DATADIR ); + veejay_msg(VEEJAY_MSG_WARNING, " to %s/.veejay/theme/",home); + veejay_msg(VEEJAY_MSG_WARNING, "and set the name of the theme in theme.config" ); + set_default_theme(); + int wd= open( path, O_WRONLY ); + if(wd) + { + char text[7] = "Default"; + write(wd,text, sizeof(text)); + close(wd); + } + return; + } + + veejay_memset(data,0,sizeof(data)); + veejay_memset(location,0,sizeof(location)); + char *dst = location; + + if( read( sloppy, data, sizeof(data) ) > 0 ) + { + int str_len = strlen( data ); + int i; + for( i = 0; i < str_len ; i ++ ) + { + if( data[i] == '\0' || data[i] == '\n' ) break; + *dst = data[i]; + (*dst)++; + } + } + + if( sloppy ) + close( sloppy ); + + if( strcmp( location, "Default" ) == 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "Using default theme."); + set_default_theme(); + } + else + { + snprintf(theme_path, sizeof(theme_path), "%s/.veejay/theme/%s", home, location ); + snprintf(theme_file, sizeof(theme_file), "%s/gveejay.rc", theme_path ); + use_default_theme_ = 0; + veejay_msg(VEEJAY_MSG_INFO, "\tRC-style '%s'", theme_file ); + veejay_msg(VEEJAY_MSG_INFO, "\tTheme location: '%s'", theme_path); + } + + struct dirent **files = NULL; + struct stat sbuf; + snprintf(theme_dir,sizeof(theme_dir), "%s/.veejay/theme/", home ); + + veejay_memset( &sbuf,0,sizeof(struct stat)); + + int n_files = scandir( theme_dir, &files, select_f, alphasort ); + if( n_files <= 0 ) + { + veejay_msg(0, "No themes found in %s", theme_dir ); + return; + } + + theme_list = (char**) vj_calloc(sizeof(char*) * (n_files+2) ); + int i,k=0; + for( i = 0; i < n_files; i ++ ) + { + char *name = files[i]->d_name; + if( name && strcmp(name, "Default" ) != 0) + { + snprintf(location, sizeof(location), "%s/%s", theme_dir, name ); + veejay_memset( &sbuf,0, sizeof(struct stat )); + if( lstat( location, &sbuf ) == 0 ) + { + if( S_ISLNK( sbuf.st_mode )) + { + veejay_memset( &sbuf,0,sizeof(struct stat)); + stat(location, &sbuf); + } + if( S_ISDIR( sbuf.st_mode )) + { + //@ test for gveejay.rc + struct stat inf; + gchar *test_file = g_strdup_printf( "%s/%s/gveejay.rc",theme_dir,name ); + if( stat( test_file, &inf) == 0 && (S_ISREG(inf.st_mode) || S_ISLNK( inf.st_mode))) + { + theme_list[k] = strdup( name ); + k++; + } + else + { + veejay_msg(VEEJAY_MSG_WARNING, "%s/%s does not contain a gveejay.rc file", theme_dir,name); + } + g_free(test_file); + } + } + } + } + + if( k == 0 ) + { + free(theme_list); + theme_list = NULL; + return; + } + + theme_list[ k ] = strdup("Default"); + for( k = 0; theme_list[k] != NULL ; k ++ ) + veejay_msg(VEEJAY_MSG_INFO, "Added Theme #%d %s", k, theme_list[k]); +// veejay_msg(VEEJAY_MSG_INFO, "Loading %s", theme_file ); + + +} + +void gui_load_theme() +{ + gtk_rc_parse( theme_file ); +} + +char *get_glade_path() +{ + return glade_path; +} + +char *get_gveejay_dir() +{ + return RELOADED_DATADIR; +} + +void get_gd(char *buf, char *suf, const char *filename) +{ + const char *dir = RELOADED_DATADIR; + + if(filename !=NULL && suf != NULL) + sprintf(buf, "%s/%s/%s",dir,suf, filename ); + if(filename !=NULL && suf==NULL) + sprintf(buf, "%s/%s", dir, filename); + if(filename == NULL && suf != NULL) + sprintf(buf, "%s/%s/" , dir, suf); +} + +GdkPixbuf *vj_gdk_pixbuf_scale_simple( GdkPixbuf *src, int dw, int dh, GdkInterpType inter_type ) +{ +#ifdef STRICT_CHECKING + assert( GDK_IS_PIXBUF(src)); +#endif + return gdk_pixbuf_scale_simple( src,dw,dh,inter_type ); +/* + GdkPixbuf *res = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, dw, dh ); +#ifdef STRICT_CHECKING + assert( GDK_IS_PIXBUF( res ) ); +#endif + uint8_t *res_out = gdk_pixbuf_get_pixels( res ); + uint8_t *src_in = gdk_pixbuf_get_pixels( src ); + uint32_t src_w = gdk_pixbuf_get_width( src ); + uint32_t src_h = gdk_pixbuf_get_height( src ); + int dst_w = gdk_pixbuf_get_width( res ); + int dst_h = gdk_pixbuf_get_height( res ); + VJFrame *src1 = yuv_rgb_template( src_in, src_w, src_h, PIX_FMT_BGR24 ); + VJFrame *dst1 = yuv_rgb_template( res_out, dst_w, dst_h, PIX_FMT_BGR24 ); + + veejay_msg(0, "%s: %dx%d -> %dx%d", __FUNCTION__, src_w,src_h,dst_w,dst_h ); + + yuv_convert_any_ac( src1,dst1, src1->format, dst1->format ); + + free(src1); + free(dst1); + + return res;*/ +} + +void gveejay_sleep( void *u ) +{ + struct timespec nsecsleep; + nsecsleep.tv_nsec = 1000000 * 4; + nsecsleep.tv_sec = 0; + nanosleep( &nsecsleep, NULL ); +} + + +int gveejay_time_to_sync( vj_gui_t *ui ) +{ + struct timeval time_now; + gettimeofday( &time_now, 0 ); + + double diff = time_now.tv_sec - ui->time_last.tv_sec + + (time_now.tv_usec - ui->time_last.tv_usec ) * 1.e-6; + float fps = 0.0; + + struct timespec nsecsleep; + if ( ui->watch.state == STATE_PLAYING ) + { + fps = ui->el.fps; + float spvf = 1.0 / fps; + float ela = ( info->status_tokens[ELAPSED_TIME] / 1000.0 ); + spvf += ela; //@ add elapsed time + + if( diff > spvf ) { + ui->time_last.tv_sec = time_now.tv_sec; + ui->time_last.tv_usec = time_now.tv_usec; + return 1; + } + int usec = 0; + int uspf = (int)(1000000.0 / fps); + if( ela ) + uspf += (int)(1000000.0 / ela ); + usec = time_now.tv_usec - ui->time_last.tv_usec; + if( usec < 0 ) + usec += 1000000; + if( time_now.tv_sec > ui->time_last.tv_sec + 1 ) + usec = 1000000; + if( (uspf - usec) < (1000000 / 100)) { + return 0; + } + +//veejay_msg(0 , "%d", (uspf - usec - 1000000 / 100 ) * 1000); + nsecsleep.tv_nsec = 3200000; +// nsecsleep.tv_nsec =(uspf - usec - 1000000 / 100 ) * 1000; + nsecsleep.tv_sec = 0; + nanosleep( &nsecsleep, NULL ); + return 0; + } else if ( ui->watch.state == STATE_STOPPED ) + { + reloaded_restart(); + } + nsecsleep.tv_nsec = 1600000; + nsecsleep.tv_sec = 0; + nanosleep( &nsecsleep, NULL ); + return 0; +} + + +// skin 0: notebook18, page 3 +// skin 1: vjdeck , page 2 +int veejay_update_multitrack( void *data ) +{ + vj_gui_t *gui = (vj_gui_t*) data; + sync_info *s = multitrack_sync( gui->mt ); + + if( s->status_list[s->master] == NULL ) { + info->watch.w_state = STATE_STOPPED; + return 1; + } + + GtkWidget *maintrack = glade_xml_get_widget( info->main_window, "imageA"); + int i; + GtkWidget *ww = glade_xml_get_widget_( info->main_window, crappy_design[ui_skin_].name ); + int deckpage = gtk_notebook_get_current_page(GTK_NOTEBOOK(ww)); + +#ifdef STRICT_CHECKING + assert( s->status_list[s->master] != NULL ); +#endif + + int tmp = 0; + for ( i = 0; i < 32; i ++ ) + { + tmp += s->status_list[s->master][i]; + info->status_tokens[i] = s->status_list[s->master][i]; + } + if( tmp == 0 ) + { + free(s->status_list); + free(s->img_list ); + free(s->widths); + free(s->heights); + free(s); + return 0; + } + + info->status_lock = 1; + info->uc.playmode = gui->status_tokens[ PLAY_MODE ]; + update_gui(); + info->prev_mode = gui->status_tokens[ PLAY_MODE ]; + gui->status_lock = 0; + int pm = info->status_tokens[PLAY_MODE]; +#ifdef STRICT_CHECKING + assert( pm >= 0 && pm < 4 ); +#endif + int *history = info->history_tokens[pm]; + + for( i = 0; i < STATUS_TOKENS; i ++ ) + history[i] = info->status_tokens[i]; + + for( i = 0; i < s->tracks ; i ++ ) + { + if( s->status_list[i] ) + { + update_multitrack_widgets( info->mt, s->status_list[i], i ); + + free(s->status_list[i]); + } + if( s->img_list[i] ) + { + if( i == s->master ) + { +#ifdef STRICT_CHECKING + assert( s->widths[i] > 0 ); + assert( s->heights[i] > 0 ); + assert( GDK_IS_PIXBUF( s->img_list[i] ) ); +#endif + if( gdk_pixbuf_get_height(s->img_list[i]) >= 255 || + gdk_pixbuf_get_width(s->img_list[i]) >= 320 ) + gtk_image_set_from_pixbuf_( GTK_IMAGE( maintrack ), s->img_list[i] ); + else { + GdkPixbuf *result = vj_gdk_pixbuf_scale_simple( s->img_list[i],DEFAULT_PREVIEW_WIDTH,DEFAULT_PREVIEW_HEIGHT, GDK_INTERP_NEAREST ); + gtk_image_set_from_pixbuf_( GTK_IMAGE( maintrack ), result ); + gdk_pixbuf_unref(result); + + } + + + vj_img_cb( s->img_list[i] ); + } + + if(deckpage == crappy_design[ui_skin_].page) + multitrack_update_sequence_image( gui->mt, i, s->img_list[i] ); + + gdk_pixbuf_unref( s->img_list[i] ); + } else { + if( i == s->master ) { + multitrack_set_logo( gui->mt, maintrack ); + } + } + } + free(s->status_list); + free(s->img_list ); + free(s->widths); + free(s->heights); + free(s); + return 1; +} + +static void update_status_accessibility(int old_pm, int new_pm) +{ + int i; + + if( old_pm == new_pm ) + return; + + if( new_pm == MODE_STREAM ) + { + for(i=0; samplewidgets[i].name != NULL; i++) + disable_widget( samplewidgets[i].name); + for(i=0; plainwidgets[i].name != NULL; i++) + disable_widget( plainwidgets[i].name); + for(i=0; streamwidgets[i].name != NULL; i++) + enable_widget( streamwidgets[i].name); + + } + + if( new_pm == MODE_SAMPLE ) + { + for(i=0; streamwidgets[i].name != NULL; i++) + disable_widget( streamwidgets[i].name); + for(i=0; plainwidgets[i].name != NULL; i++) + disable_widget( plainwidgets[i].name); + for(i=0; samplewidgets[i].name != NULL; i++) + enable_widget( samplewidgets[i].name); + } + + if( new_pm == MODE_PLAIN) + { + for(i=0; streamwidgets[i].name != NULL; i++) + disable_widget( streamwidgets[i].name); + for(i=0; samplewidgets[i].name != NULL; i++) + disable_widget( samplewidgets[i].name); + for(i=0; plainwidgets[i].name != NULL; i++) + enable_widget( plainwidgets[i].name); + + } + GtkWidget *n = glade_xml_get_widget_( info->main_window, "panels" ); + int page_needed = 0; + switch( new_pm ) + { + + case MODE_SAMPLE: + page_needed =0 ; break; + case MODE_STREAM: + page_needed = 1; break; + case MODE_PLAIN: + page_needed = 2; break; + default: + break; + } + + gtk_notebook_set_page( GTK_NOTEBOOK(n), page_needed ); + +} + +static void set_pm_page_label(int sample_id, int type) +{ + gchar ostitle[100]; + switch(type) { + case 0: snprintf(ostitle, sizeof(ostitle), "Sample %d",sample_id);break; + case 1: snprintf(ostitle, sizeof(ostitle), "Stream %d",sample_id);break; + default: + snprintf(ostitle,sizeof(ostitle), "Plain");break; + } + gchar *title = _utf8str(ostitle); + update_label_str( "label_current_mode", title); + update_label_str( "label_currentsource", title ); + g_free(title); +} + +static void update_globalinfo(int *history, int pm, int last_pm) +{ + int i; + + if( last_pm != pm ) + update_status_accessibility( last_pm, pm); + + if( info->status_tokens[MACRO] != history[MACRO] ) + { + switch(info->status_tokens[MACRO]) + { + case 1: + set_toggle_button( "macrorecord",1); break; + case 2: + set_toggle_button( "macroplay",1 ); break; + default: + set_toggle_button( "macrostop",1); break; + } + + } + + if( info->status_tokens[CURRENT_ID] != history[CURRENT_ID] || last_pm != pm ) + { + // slot changed + if( pm == MODE_SAMPLE || pm == MODE_STREAM ) + { + info->uc.reload_hint[HINT_ENTRY] = 1; + info->uc.reload_hint[HINT_CHAIN] = 1; + } + + if( pm != MODE_STREAM ) + info->uc.reload_hint[HINT_EL] = 1; + if( pm != MODE_PLAIN ) + info->uc.reload_hint[HINT_KF] = 1; + + if( pm == MODE_SAMPLE ) + timeline_set_selection( info->tl, TRUE ); + else + timeline_set_selection( info->tl, FALSE ); + + select_slot( info->status_tokens[PLAY_MODE] ); + + +#ifdef STRICT_CHECKING + if( pm != MODE_PLAIN ) + assert( info->selected_slot != NULL ); +#endif + } + + if( info->status_tokens[TOTAL_SLOTS] != + history[TOTAL_SLOTS] + || info->status_tokens[TOTAL_SLOTS] != info->uc.expected_slots ) + { + info->uc.reload_hint[HINT_SLIST] = 1; + } + + if( info->status_tokens[SEQ_ACT] != history[SEQ_ACT] ) + { + info->uc.reload_hint[HINT_SEQ_ACT] = 1; + + if(info->status_tokens[SEQ_ACT]== 0 ) + set_toggle_button( "seqactive" , 0 ); + else + set_toggle_button( "seqactive", 1 ); + } + if( info->status_tokens[SEQ_CUR] != history[SEQ_CUR] ) + { + int in = info->status_tokens[SEQ_CUR]; + if(info->sequence_playing >= 0) + indicate_sequence( FALSE, info->sequencer_view->gui_slot[ info->sequence_playing ] ); + info->sequence_playing = in; + indicate_sequence( TRUE, info->sequencer_view->gui_slot[ info->sequence_playing ] ); + } + + + total_frames_ = (pm == MODE_STREAM ? info->status_tokens[SAMPLE_MARKER_END] : info->status_tokens[TOTAL_FRAMES] ); + gint history_frames_ = (pm == MODE_STREAM ? history[SAMPLE_MARKER_END] : history[TOTAL_FRAMES] ); + gint current_frame_ = info->status_tokens[FRAME_NUM]; + + if( total_frames_ != history_frames_ || total_frames_ != (int) timeline_get_length(TIMELINE_SELECTION(info->tl))) + { + gchar *time = format_time( total_frames_,(double) info->el.fps ); + if( pm == MODE_STREAM ) + { + update_spin_value( "stream_length", info->status_tokens[SAMPLE_MARKER_END] ); + update_label_str( "stream_length_label", time ); + } + update_spin_range("button_fadedur", 0, total_frames_, 0 ); + update_label_i( "label_totframes", total_frames_, 1 ); + update_label_str( "label_samplelength",time); + if( pm == MODE_PLAIN ) + { + for( i = 0; i < 3; i ++) + if(info->selection[i] > total_frames_ ) info->selection[i] = total_frames_; + update_spin_range( + "button_el_selstart", 0, total_frames_, info->selection[0]); + update_spin_range( + "button_el_selend", 0, total_frames_, info->selection[1]); + update_spin_range( + "button_el_selpaste", 0, total_frames_, info->selection[2]); + } + update_label_i( "label_totframes", total_frames_, 1 ); + update_label_str( "label_totaltime", time ); + if(pm == MODE_SAMPLE) + update_label_str( "sample_length_label", time ); + else + update_label_str( "sample_length_label", "0:00:00:00" ); + + + timeline_set_length( info->tl, + (gdouble) total_frames_ , current_frame_); + + if( pm != MODE_STREAM ) + info->uc.reload_hint[HINT_EL] = 1; + + g_free(time); + } + + info->status_frame = info->status_tokens[FRAME_NUM]; + timeline_set_pos( info->tl, (gdouble) info->status_frame ); + gchar *current_time_ = format_time( info->status_frame, (double) info->el.fps ); + update_label_i( "label_curframe", info->status_frame ,1 ); + update_label_str( "label_curtime", current_time_ ); + update_label_str( "label_sampleposition", current_time_); + g_free(current_time_); + + if( pm == MODE_SAMPLE ) + update_label_i( "label_samplepos", + info->status_frame , 1); + else + update_label_i( "label_samplepos" , 0 , 1 ); + + if( history[CURRENT_ID] != info->status_tokens[CURRENT_ID] ) + { + if(pm == MODE_SAMPLE || pm == MODE_STREAM) + update_label_i( "label_currentid", info->status_tokens[CURRENT_ID] ,0); + } + + if( history[STREAM_RECORDING] != info->status_tokens[STREAM_RECORDING] ) + { + if(pm == MODE_SAMPLE || pm == MODE_STREAM) + { + if( history[CURRENT_ID] == info->status_tokens[CURRENT_ID] ) + info->uc.reload_hint[HINT_RECORDING] = 1; + if( info->status_tokens[STREAM_RECORDING]) + vj_msg(VEEJAY_MSG_INFO, "Veejay is recording"); + else + vj_msg(VEEJAY_MSG_INFO, "Recording has stopped"); + } + } + + if( pm == MODE_PLAIN ) + { + if( history[SAMPLE_SPEED] != info->status_tokens[SAMPLE_SPEED] ) + { + int plainspeed = info->status_tokens[SAMPLE_SPEED]; + + update_slider_value( "speed_slider", plainspeed, 0); + if( plainspeed < 0 ) + info->play_direction = -1; + else + info->play_direction = 1; + if( plainspeed < 0 ) plainspeed *= -1; + if( plainspeed == 0 ) { + update_label_str( "playhint", "Paused"); + } else { + update_label_str( "playhint", "Playing"); + } + + } + } + + if( pm == MODE_STREAM ) { + if( info->status_tokens[STREAM_TYPE] == STREAM_VIDEO4LINUX ) { + if(info->uc.cali_duration > 0 ) { + GtkWidget *tb = glade_xml_get_widget_( info->main_window, "cali_take_button"); + info->uc.cali_duration--; + vj_msg(VEEJAY_MSG_INFO, "Calibrate step %d of %d", + info->uc.cali_duration, + info->uc.cali_stage); + if(info->uc.cali_duration == 0) { + info->uc.cali_stage ++; //@ cali_stage = 1, done capturing black frames + + switch(info->uc.cali_stage) { + case 1: //@ capturing black frames + update_label_str( "current_step_label", + "Please take an image of a uniformly lit area in placed in front of your lens."); + gtk_button_set_label( tb, "Take White Frames"); + break; + case 2: + case 3: + update_label_str( "current_step_label", + "Image calibrated. You may need to adjust brightness."); + enable_widget( "cali_save_button"); + break; + default: + update_label_str( "current_step_label","Image calibrated. You may need to adjust brightness."); + gtk_button_set_label( tb, "Take Black Frames"); + veejay_msg(0, "Warning, mem leak if not reset first."); + break; + + } + veejay_msg(0, "Label update for case %d", info->uc.cali_stage); + + if(info->uc.cali_stage >= 2 ) { + info->uc.cali_stage = 0; + } + } + } + } + + } + + update_current_slot(history, pm, last_pm); +// info->uc.playmode = pm; +} + + +static void process_reload_hints(int *history, int pm) +{ + int *entry_tokens = &(info->uc.entry_tokens[0]); + + if( pm == MODE_STREAM ) + { + if(info->uc.reload_hint[HINT_V4L]) + load_v4l_info(); + + if( info->uc.reload_hint[HINT_RGBSOLID]) + update_colorselection(); + + } + + if( info->uc.reload_hint[HINT_EL] ) + { + load_editlist_info(); + reload_editlist_contents(); + } + update_spin_range( + "spin_samplestart", 0, info->el.num_frames, info->status_tokens[SAMPLE_START] ); + update_spin_range( + "spin_sampleend", 0, info->el.num_frames , info->status_tokens[SAMPLE_END] ); + + if( info->uc.reload_hint[HINT_SLIST] ) + { + load_samplelist_info(FALSE); + info->uc.expected_slots = info->status_tokens[TOTAL_SLOTS]; + } + + if( info->uc.reload_hint[HINT_SEQ_ACT] == 1 ) + { + load_sequence_list(); + } + + + if( info->uc.reload_hint[HINT_RECORDING] == 1 && pm != MODE_PLAIN) + { + if(info->status_tokens[STREAM_RECORDING]) + { + if(!info->uc.recording[pm]) init_recorder( info->status_tokens[STREAM_DURATION], pm ); + } + } + + if(info->uc.reload_hint[HINT_BUNDLES] == 1 ) + reload_bundles(); + + if( info->selected_slot && info->selected_slot->sample_id == info->status_tokens[CURRENT_ID] && + info->selected_slot->sample_type == 0 && pm == MODE_PLAIN) + { + if( history[SAMPLE_FX] != info->status_tokens[SAMPLE_FX]) + { + //also for stream (index is equivalent) + if(pm == MODE_SAMPLE) + set_toggle_button( "check_samplefx", + info->status_tokens[SAMPLE_FX]); + if(pm == MODE_STREAM) + set_toggle_button( "check_streamfx", + info->status_tokens[SAMPLE_FX]); + } + } + if( info->uc.reload_hint[HINT_CHAIN] == 1 && pm != MODE_PLAIN) + { + load_effectchain_info(); + } + + + info->parameter_lock = 1; + if(info->uc.reload_hint[HINT_ENTRY] == 1 && pm != MODE_PLAIN) + { + char slider_name[10]; + char button_name[10]; + gint np = 0; + gint i; + /* update effect description */ + info->uc.reload_hint[HINT_KF] = 1; + if( entry_tokens[ENTRY_FXID] == 0) + { + put_text( "entry_effectname" ,"" ); + disable_widget( "frame_fxtree2" ); + disable_widget( "frame_fxtree4" ); + disable_widget( "tree_sources"); + disable_widget( "rgbkey"); + } + else + { + put_text( "entry_effectname", _effect_get_description( entry_tokens[ENTRY_FXID] )); + enable_widget( "frame_fxtree2"); + enable_widget( "frame_fxtree4"); + enable_widget( "tree_sources"); + enable_widget( "rgbkey" ); + set_toggle_button( "button_entry_toggle", entry_tokens[ENTRY_FXSTATUS] ); + np = _effect_get_np( entry_tokens[ENTRY_FXID] ); + for( i = 0; i < np ; i ++ ) + { + sprintf(slider_name, "slider_p%d",i); + enable_widget( slider_name ); + sprintf(button_name, "inc_p%d", i); + enable_widget( button_name ); + sprintf(button_name, "dec_p%d", i ); + + gchar *tt1 = _utf8str(_effect_get_param_description(entry_tokens[ENTRY_FXID],i)); + gtk_widget_set_tooltip_text( glade_xml_get_widget_(info->main_window, slider_name), tt1 ); + enable_widget( button_name ); + gint min,max,value; + value = entry_tokens[3 + i]; + if( _effect_get_minmax( entry_tokens[ENTRY_FXID], &min,&max, i )) + { + update_slider_range( slider_name,min,max, value, 0); + } + sprintf(button_name, "kf_p%d", i ); + enable_widget( button_name ); + set_tooltip( button_name, tt1 ); + g_free(tt1); + } + + } + update_spin_value( "button_fx_entry", info->uc.selected_chain_entry); + + for( i = np; i < 8 ; i ++ ) + { + sprintf(slider_name, "slider_p%d",i); + gint min = 0, max = 1, value = 0; + update_slider_range( slider_name, min,max, value, 0 ); + disable_widget( slider_name ); + sprintf( button_name, "inc_p%d", i); + disable_widget( button_name ); + sprintf( button_name, "dec_p%d", i); + disable_widget( button_name ); + sprintf( button_name, "kf_p%d", i ); + set_tooltip( button_name, NULL ); + disable_widget( button_name ); + gtk_widget_set_tooltip_text( glade_xml_get_widget_(info->main_window, slider_name), NULL ); + } + GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW(glade_xml_get_widget_( + info->main_window, "tree_chain") )); + + gtk_tree_model_foreach( + model, + chain_update_row, (gpointer*) info ); + } + info->parameter_lock = 0; + + /* Curve needs update (start/end changed, effect id changed */ + if ( info->uc.reload_hint[HINT_KF] ) + vj_kf_refresh(); + + if( info->uc.reload_hint[HINT_HISTORY] ) + reload_srt(); + + veejay_memset( info->uc.reload_hint, 0, sizeof(info->uc.reload_hint )); +} +void update_gui() +{ + int pm = info->status_tokens[PLAY_MODE]; + int last_pm = info->prev_mode; + + int *history = NULL; + + if( last_pm < 0 ) + history = info->history_tokens[0]; + else + history = info->history_tokens[ last_pm ]; + + if( info->uc.randplayer && pm != last_pm ) + { + info->uc.randplayer = 0; + set_toggle_button( "samplerand", 0 ); + } + + if( pm == MODE_PATTERN && last_pm != pm) + { + if(!info->uc.randplayer ) + { + info->uc.randplayer = 1; + set_toggle_button( "samplerand", 1 ); + } + info->status_tokens[PLAY_MODE] = MODE_SAMPLE; + pm = MODE_SAMPLE; + } + + update_globalinfo(history, pm, last_pm); + + process_reload_hints(history, pm); + on_vims_messenger(); + + update_cpumeter_timeout(NULL); + update_cachemeter_timeout(NULL); + +} +/* +void vj_fork_or_connect_veejay(char *configfile) +{ + char *files = get_text( "entry_filename" ); + int port = get_nums( "button_portnum" ); + gchar **args; + int n_args = 0; + char port_str[15]; + char config[512]; + char tmp[20]; + int i = 0; + + int arglen = vims_verbosity ? 15 :14 ; + arglen += (info->config.deinter); + arglen += (info->config.osc); + arglen += (info->config.vims); + args = g_new ( gchar *, arglen ); + + args[0] = g_strdup("veejay"); + + sprintf(port_str, "-p%d", port); + args[1] = g_strdup( port_str ); + + if(configfile) + sprintf(config, "-l%s", configfile); + + if( config_file_status == 0 ) + { + if(files == NULL || strlen(files)<= 0) + args[2] = g_strdup("-d"); + else + args[2] = g_strdup(files); + } + else + { + args[2] = g_strdup( config ); + } + + args[3] = g_strdup( "-O5" ); + sprintf(tmp, "-W%d", info->config.w ); + args[4] = g_strdup( tmp ); + sprintf(tmp, "-H%d", info->config.h ); + args[5] = g_strdup( tmp ); + sprintf(tmp, "-R%g", info->config.fps ); + args[6] = g_strdup( tmp ); + sprintf(tmp, "-N%d", info->config.norm ); + args[7] = g_strdup( tmp ); + sprintf(tmp, "-Y%d", info->config.pixel_format ); + args[8] = g_strdup( tmp ); + sprintf(tmp, "-m%d", info->config.sampling ); + args[9] = g_strdup( tmp ); + sprintf(tmp, "-c%d", info->config.sync ); + args[10] = g_strdup( tmp ); + sprintf(tmp, "-t%d", info->config.timer == 0 ? 0 : 2); + args[11] = g_strdup( tmp ); + sprintf(tmp, "-r%d", info->config.audio_rate ); + args[12] = g_strdup( tmp ); + args[13] = NULL; + int k=13; + while( k <= (arglen-1)) + args[k++] = NULL; + + if( vims_verbosity ) + args[13] = g_strdup( "-v" ); + + if( info->config.deinter ) + { + if(args[13]==NULL) + args[13] = g_strdup( "-I"); + else args[14] = g_strdup( "-I" ); + } + if( info->config.osc) + { + gchar osc_token[20]; + sprintf(osc_token , "-M %s", info->config.mcast_osc ); + int f = 13; + while(args[f] != NULL ) f ++; + args[f] = g_strdup( osc_token ); + } + if( info->config.vims) + { + gchar vims_token[20]; + sprintf(vims_token, "-V %s", info->config.mcast_vims ); + int f = 13; + while(args[f] != NULL) f++; + args[f] = g_strdup( vims_token ); + } + if( info->watch.state == STATE_STOPPED) + { + info->watch.state = STATE_CONNECT; + info->run_state = RUN_STATE_REMOTE; + } + + for( i = 0; i < n_args; i ++) + g_free(args[i]); +} +*/ +void vj_gui_free() +{ + if(info) + { + int i; + if(info->client) + vj_client_free(info->client); + + for( i = 0; i < 4; i ++ ) + { + if(info->history_tokens[i]) + free(info->history_tokens[i]); + } + free(info); + } + info = NULL; + + vevo_port_free( fx_list_ ); + vevo_port_free( bankport_ ); +} + +void vj_gui_style_setup() +{ + if(!info) return; + info->color_map = gdk_colormap_get_system(); +} + +void vj_gui_theme_setup(int default_theme) +{ + gtk_rc_parse(theme_file); +} + +void +send_refresh_signal(void) +{ + GdkEventClient event; + event.type = GDK_CLIENT_EVENT; + event.send_event = TRUE; + event.window = NULL; + event.message_type = gdk_atom_intern("_GTK_READ_RCFILES", FALSE); + event.data_format = 8; + gdk_event_send_clientmessage_toall((GdkEvent *)&event); +} + +gint +gui_client_event_signal(GtkWidget *widget, GdkEventClient *event, + void *data) +{ + static GdkAtom atom_rcfiles = GDK_NONE; + if(!atom_rcfiles) + atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE); + + if(event->message_type == atom_rcfiles) + { + gtk_rc_parse( theme_file ); + + gtk_widget_reset_rc_styles( + glade_xml_get_widget_(info->main_window, "gveejay_window") ); + + gtk_rc_reparse_all(); + + veejay_msg(VEEJAY_MSG_WARNING, + "Loaded GTK theme %s (catched _GTK_READ_RCFILES)", theme_file ); + veejay_msg(VEEJAY_MSG_INFO, + "If the new theme is using an engine that modifies the internal structure"); + veejay_msg(VEEJAY_MSG_INFO, + "of the widgets, there is no way for me to undo those changes and display"); + veejay_msg(VEEJAY_MSG_INFO, + "%s correctly", theme_file ); + return TRUE; + } + return FALSE; +} + +void vj_gui_set_debug_level(int level, int preview_p, int pw, int ph ) +{ + veejay_set_debug_level( level ); + + vims_verbosity = level; + num_tracks_ = preview_p; + default_preview_width_ = pw; + default_preview_height_ = ph; +} +int vj_gui_get_preview_priority(void) +{ + return 1; +} + +void default_bank_values(int *col, int *row ) +{ + int nsc = 2; + int nsy = 6; + if( ui_skin_ == 1 ) { + nsc = 5; + nsy = 4; + } + if( *col == 0 && *row == 0 ) + { + NUM_SAMPLES_PER_COL = nsc; + NUM_SAMPLES_PER_ROW = nsy; + } + else + { + NUM_SAMPLES_PER_ROW = *col; + NUM_SAMPLES_PER_COL = *row; + } + NUM_SAMPLES_PER_PAGE = NUM_SAMPLES_PER_COL * NUM_SAMPLES_PER_ROW; + NUM_BANKS = (4096 / NUM_SAMPLES_PER_PAGE ); +} + +void set_skin(int skin) +{ + ui_skin_ = skin; + timeline_theme_colors( 1 ); +} + +int vj_gui_sleep_time( void ) +{ + float f = (float) info->status_tokens[ELAPSED_TIME]; + float t = info->el.fps; + + if( t <= 0.0 || t>= 200.0 ) + t = 25.0; + float n = (1.0 / t) * 1000.0f; + + if( f < n ) + return (int)( n - f ); + return (int) n; +} + +int vj_img_cb(GdkPixbuf *img ) +{ + int i; + if( !info->selected_slot || !info->selected_gui_slot ) + { +//DM + return 0; + } + int sample_id = info->status_tokens[ CURRENT_ID ]; + int sample_type = info->status_tokens[ PLAY_MODE ]; + + if( info->selected_slot->sample_type != sample_type || info->selected_slot->sample_id != + sample_id ) { + return 0; + } + if( sample_type == MODE_SAMPLE || sample_type == MODE_STREAM ) + { + sample_slot_t *slot = find_slot_by_sample( sample_id, sample_type ); + sample_gui_slot_t *gui_slot = find_gui_slot_by_sample( sample_id, sample_type ); + + if( slot && gui_slot ) + { + slot->pixbuf = vj_gdk_pixbuf_scale_simple(img, + info->image_dimensions[0],info->image_dimensions[1], GDK_INTERP_NEAREST); + gtk_image_set_from_pixbuf_( GTK_IMAGE( gui_slot->image ), slot->pixbuf ); + gdk_pixbuf_unref( slot->pixbuf ); + } + + } + + for( i = 0; i < info->sequence_view->envelope_size; i ++ ) + { + sequence_gui_slot_t *g = info->sequence_view->gui_slot[i]; + sample_slot_t *s = info->selected_slot; + if(g->sample_id == info->selected_slot->sample_id && g->sample_type == info->selected_slot->sample_type && s->pixbuf) + { + g->pixbuf_ref = vj_gdk_pixbuf_scale_simple( + img, + info->sequence_view->w, + info->sequence_view->h, + GDK_INTERP_NEAREST ); + + gtk_image_set_from_pixbuf_( GTK_IMAGE( g->image ), g->pixbuf_ref ); + + gdk_pixbuf_unref( g->pixbuf_ref ); + + } + } + + return 1; +} + +void vj_gui_cb(int state, char *hostname, int port_num) +{ + info->watch.state = STATE_RECONNECT; + put_text( "entry_hostname", hostname ); + update_spin_value( "button_portnum", port_num ); + + //@ clear status + int i; + for( i = 0; i < 4; i ++ ) { + int *h = info->history_tokens[i]; + veejay_memset( h, 0, sizeof(int) * STATUS_TOKENS ); + } +} + +void vj_gui_setup_defaults( vj_gui_t *gui ) +{ + gui->config.w = DEFAULT_PREVIEW_WIDTH; + gui->config.h = DEFAULT_PREVIEW_HEIGHT; + gui->config.fps = 25.0; + gui->config.sampling = 1; + gui->config.pixel_format = 1; + gui->config.sync = 1; + gui->config.timer = 1; + gui->config.deinter = 1; + gui->config.norm = 0; + gui->config.audio_rate = 0; + gui->config.osc = 0; + gui->config.vims = 0; + gui->config.mcast_osc = g_strdup( "224.0.0.32" ); + gui->config.mcast_vims = g_strdup( "224.0.0.33" ); +} + +static void theme_response( gchar *string ) +{ + char theme_config[1024]; + snprintf(theme_config,sizeof(theme_config), "%stheme.config", theme_dir ); + snprintf(theme_file,sizeof(theme_file), "%s/%s/gveejay.rc", theme_dir, string ); + int fd = open( theme_config , O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); + if(fd > 0) + { + write( fd, string, strlen(string)); + close(fd); + vj_msg(VEEJAY_MSG_INFO, "Restart GveejayReloaded for changes to take effect"); + if( prompt_dialog("Restart GveejayReloaded", "For changes to take effect, you should restart now" ) == GTK_RESPONSE_ACCEPT) + { + info->watch.w_state = STATE_DISCONNECT; + running_g_ = 0; + restart_ = 1; + } + } + else + { + vj_msg(VEEJAY_MSG_ERROR, "Unable to write to %s", theme_config ); + } + +} +static void reloaded_sighandler(int x) +{ + veejay_msg(VEEJAY_MSG_WARNING, "Caught signal %x", x); + + if( x == SIGPIPE ) { + reloaded_schedule_restart(); + } + else if ( x == SIGINT || x == SIGABRT ) { + veejay_msg(VEEJAY_MSG_WARNING, "Stopping reloaded"); + exit(0); + } else if ( x == SIGSEGV ) { + veejay_msg(VEEJAY_MSG_ERROR, "Found Gremlins in your system."); + veejay_msg(VEEJAY_MSG_WARNING, "No fresh ale found in the fridge."); + veejay_msg(VEEJAY_MSG_INFO, "Running with sub-atomic precision..."); + veejay_msg(VEEJAY_MSG_ERROR, "Bugs compromised the system."); + exit(0); + } +} +static void sigsegfault_handler(void) { + struct sigaction sigst; + sigst.sa_sigaction = veejay_backtrace_handler; + sigemptyset(&sigst.sa_mask); + sigaddset(&sigst.sa_mask, SIGSEGV ); + sigst.sa_flags = SA_SIGINFO | SA_ONESHOT; + if( sigaction(SIGSEGV, &sigst, NULL == - 1) ) + veejay_msg(0,"sigaction"); +} + +void register_signals() +{ + signal( SIGINT, reloaded_sighandler ); + signal( SIGPIPE, reloaded_sighandler ); + signal( SIGQUIT, reloaded_sighandler ); +// signal( SIGSEGV, reloaded_sighandler ); + signal( SIGABRT, reloaded_sighandler ); + + sigsegfault_handler(); +} + + + + +void vj_gui_wipe() +{ + int i; + veejay_memset( info->status_tokens, 0, sizeof(int) * STATUS_TOKENS ); + veejay_memset( info->uc.entry_tokens,0, sizeof(int) * 21); + for( i = 0 ; i < 4; i ++ ) + { + veejay_memset(info->history_tokens[i],0, sizeof(int) * (STATUS_TOKENS+1)); + } + +} + +GtkWidget *new_bank_pad(GtkWidget *box, int type) +{ + GtkWidget *pad = info->sample_bank_pad = gtk_notebook_new(); + gtk_notebook_set_tab_pos( GTK_NOTEBOOK(pad), GTK_POS_BOTTOM ); + gtk_notebook_set_show_tabs( GTK_NOTEBOOK(pad ), FALSE ); + gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET(pad), TRUE, TRUE, 0); + + if( type == 0 ) { + setup_samplebank( NUM_SAMPLES_PER_COL, NUM_SAMPLES_PER_ROW, pad, &(info->image_dimensions[0]), + &(info->image_dimensions[1]) ); + } + + return pad; +} +static struct { + const char *text; +} slider_names_[] = +{ + { "slider_p0" }, + { "slider_p1" }, + { "slider_p2" }, + { "slider_p3" }, + { "slider_p4" }, + { "slider_p5" }, + { "slider_p6" }, + { "slider_p7" }, + { "slider_p8" }, + { NULL }, +}; + +gboolean slider_scroll_event( GtkWidget *widget, GdkEventScroll *ev, gpointer user_data) +{ + gint i = GPOINTER_TO_INT(user_data); + if(ev->direction == GDK_SCROLL_UP ) { + param_changed( i, 1, slider_names_[i].text ); + } else if (ev->direction == GDK_SCROLL_DOWN ) { + param_changed( i, -1, slider_names_[i].text ); + } + return FALSE; +} + +gboolean speed_scroll_event( GtkWidget *widget, GdkEventScroll *ev, gpointer user_data) +{ + int plainspeed = info->status_tokens[SAMPLE_SPEED]; + if(ev->direction == GDK_SCROLL_UP ) { + plainspeed = plainspeed + 1; + } else if (ev->direction == GDK_SCROLL_DOWN ) { + plainspeed = plainspeed - 1; + } + update_slider_value( "speed_slider", plainspeed, 0 ); + return FALSE; +} + +gboolean slow_scroll_event( GtkWidget *widget, GdkEventScroll *ev, gpointer user_data) +{ + int plainspeed = get_slider_val("slow_slider"); + if(ev->direction == GDK_SCROLL_DOWN ) { + plainspeed = plainspeed - 1; + } else if (ev->direction == GDK_SCROLL_UP ) { + plainspeed = plainspeed + 1; + } + if(plainspeed < 1 ) + plainspeed = 1; + update_slider_value("slow_slider",plainspeed,0); + vj_msg(VEEJAY_MSG_INFO, "Slow video to %2.2f fps", + info->el.fps / (float) plainspeed ); + return FALSE; +} + +static struct +{ + char *name; +} spinboxes[] = { +{ "button_portnum" }, +{ "screenshot_width" }, +{ "screenshot_height" }, +{ "preview_width" }, +{ "preview_height" }, +{ "preview_delay" }, +{ "priout_width" }, +{ "priout_height" }, +{ "priout_x" }, +{ "priout_y" }, +{ "inputstream_portnum" }, +{ "button_fx_entry" }, +{ "curve_spinstart" }, +{ "curve_spinend" }, +{ "spin_text_start" }, +{ "spin_text_end" }, +{ "spin_text_size" }, +{ "spin_text_x" }, +{ "spin_text_y" }, +{ "spin_sampleduration" }, +{ "spin_samplestart" }, +{ "spin_sampleend" }, +{ "spin_samplespeed" }, +{ "spin_framedelay" }, +{ "button_el_selend" }, +{ "button_el_selstart" }, +{ "button_el_selpaste" }, +{ "stream_length" }, +{ "spin_streamduration" }, +{ "spin_samplebank_select" }, +{ "button_fadedur" }, +{ NULL } +}; + +static void debug_spinboxes() +{ + int i; + for( i = 0; spinboxes[i].name != NULL ; i ++ ) { + GtkWidget *spin = glade_xml_get_widget_( info->main_window, spinboxes[i].name ); + GtkAdjustment *adj = gtk_spin_button_get_adjustment( GTK_SPIN_BUTTON(spin) ); + veejay_msg(VEEJAY_MSG_DEBUG, "%s: Lower=%g,Upper=%g,Value=%g,Step=%g,Page Incr=%g,Page Size=%g", + spinboxes[i].name, + adj->lower, + adj->upper, + adj->value, + adj->step_increment, + adj->page_increment, + adj->page_size ); + } +} + +void vj_gui_init(char *glade_file, int launcher, char *hostname, int port_num, int use_threads) +{ + int i; + char text[100]; + vj_gui_t *gui = (vj_gui_t*)vj_calloc(sizeof(vj_gui_t)); + if(!gui) + { + return; + } + snprintf( glade_path, sizeof(glade_path), "%s/%s",RELOADED_DATADIR,glade_file); + + + veejay_memset( gui->status_tokens, 0, sizeof(int) * STATUS_TOKENS ); + veejay_memset( gui->sample, 0, 2 ); + veejay_memset( gui->selection, 0, 3 ); + veejay_memset( &(gui->uc), 0, sizeof(veejay_user_ctrl_t)); + veejay_memset( gui->uc.entry_tokens,0, sizeof(int) * 21); + gui->prev_mode = -1; + veejay_memset( &(gui->el), 0, sizeof(veejay_el_t)); + gui->sample_banks = (sample_bank_t**) vj_calloc(sizeof(sample_bank_t*) * NUM_BANKS ); + + for( i = 0 ; i < 4; i ++ ) + { + gui->history_tokens[i] = (int*) vj_calloc(sizeof(int) * (STATUS_TOKENS+1)); + } + + gui->uc.reload_force_avoid = FALSE; + + veejay_memset( vj_event_list, 0, sizeof(vj_event_list)); + + gui->client = NULL; + gui->main_window = glade_xml_new(glade_path,NULL,NULL); + if(!gui->main_window) + { + free(gui); + } + info = gui; + + glade_xml_signal_autoconnect( gui->main_window ); + GtkWidget *frame = glade_xml_get_widget_( info->main_window, "markerframe" ); + info->tl = timeline_new(); + gtk_widget_set_size_request_(frame, 200,14 ); + + + set_tooltip_by_widget(info->tl, tooltips[TOOLTIP_TIMELINE].text ); + + g_signal_connect( info->tl, "pos_changed", + (GCallback) on_timeline_value_changed, NULL ); + g_signal_connect( info->tl, "in_point_changed", + (GCallback) on_timeline_in_point_changed, NULL ); + g_signal_connect( info->tl, "out_point_changed", + (GCallback) on_timeline_out_point_changed, NULL ); + g_signal_connect( info->tl, "bind_toggled", + (GCallback) on_timeline_bind_toggled, NULL ); + g_signal_connect( info->tl, "cleared", + (GCallback) on_timeline_cleared, NULL ); + + + bankport_ = vpn( VEVO_ANONYMOUS_PORT ); + + gtk_widget_show(frame); + gtk_container_add( GTK_CONTAINER(frame), info->tl ); + gtk_widget_show(info->tl); + + + GtkWidget *mainw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); + +#ifdef STRICT_CHECKING + debug_spinboxes(); +#endif + + sprintf(text, "Reloaded - version %s",VERSION); + gtk_label_set_text( GTK_LABEL(glade_xml_get_widget_(info->main_window, "build_revision")), text); + + g_signal_connect_after( GTK_OBJECT(mainw), "client_event", + GTK_SIGNAL_FUNC( G_CALLBACK(gui_client_event_signal) ), NULL ); + + g_signal_connect( GTK_OBJECT(mainw), "destroy", + G_CALLBACK( gveejay_quit ), + NULL ); + g_signal_connect( GTK_OBJECT(mainw), "delete-event", + G_CALLBACK( gveejay_quit ), + NULL ); + + GtkWidget *box = glade_xml_get_widget_( info->main_window, "sample_bank_hbox" ); + info->sample_bank_pad = new_bank_pad( box,0 ); + + //QuickSelect slots + create_ref_slots( 10 ); + + + //SEQ + create_sequencer_slots( 10,10 ); + + char slider_name[16]; + for( i = 0 ; i < 8 ; i ++ ) { + sprintf(slider_name, "slider_p%d",i); + GtkWidget *slider = glade_xml_get_widget( info->main_window, slider_name ); + g_signal_connect( GTK_OBJECT(slider), "scroll-event", G_CALLBACK(slider_scroll_event), (gpointer) i ); + } + + g_signal_connect( GTK_OBJECT( glade_xml_get_widget(info->main_window, "speed_slider") ), "scroll-event", + G_CALLBACK(speed_scroll_event), NULL ); + g_signal_connect( GTK_OBJECT( glade_xml_get_widget(info->main_window, "slow_slider") ), "scroll-event", + G_CALLBACK(slow_scroll_event), NULL ); + + + veejay_memset( vj_event_list, 0, sizeof( vj_event_list )); + veejay_memset( vims_keys_list, 0, sizeof( vims_keys_list) ); + + gtk_widget_show( info->sample_bank_pad ); + + info->elref = NULL; + info->effect_info = NULL; + info->devlist = NULL; + info->chalist = NULL; + info->editlist = NULL; + + vj_gui_setup_defaults(gui); + setup_vimslist(); + setup_effectchain_info(); + setup_effectlist_info(); + setup_editlist_info(); + setup_samplelist_info(); + setup_v4l_devices(); + setup_colorselection(); + setup_rgbkey(); + setup_bundles(); + setup_server_files(); + + text_defaults(); + + GtkWidget *fgb = glade_xml_get_widget( + info->main_window, "boxtext" ); + GtkWidget *bgb = glade_xml_get_widget( + info->main_window, "boxbg" ); + GtkWidget *rb = glade_xml_get_widget( + info->main_window, "boxred" ); + GtkWidget *gb = glade_xml_get_widget( + info->main_window, "boxgreen" ); + GtkWidget *bb = glade_xml_get_widget( + info->main_window, "boxblue" ); + GtkWidget *lnb = glade_xml_get_widget( + info->main_window,"boxln" ); + g_signal_connect( G_OBJECT( bgb ), "expose_event", + G_CALLBACK( boxbg_expose_event ), NULL); + g_signal_connect( G_OBJECT( fgb ), "expose_event", + G_CALLBACK( boxfg_expose_event ), NULL); + g_signal_connect( G_OBJECT( lnb ), "expose_event", + G_CALLBACK( boxln_expose_event ), NULL); + g_signal_connect( G_OBJECT( rb ), "expose_event", + G_CALLBACK( boxred_expose_event ), NULL); + g_signal_connect( G_OBJECT( gb ), "expose_event", + G_CALLBACK( boxgreen_expose_event ), NULL); + g_signal_connect( G_OBJECT( bb ), "expose_event", + G_CALLBACK( boxblue_expose_event ), NULL); + + + set_toggle_button( "button_252", vims_verbosity ); + + + int pw = default_preview_width_; + int ph = default_preview_height_; + + GtkWidget *img_wid = glade_xml_get_widget_( info->main_window, "imageA"); + + gui->mt = multitrack_new( + (void(*)(int,char*,int)) vj_gui_cb, + NULL, + glade_xml_get_widget_( info->main_window, "gveejay_window" ), + glade_xml_get_widget_( info->main_window, "mt_box" ), + glade_xml_get_widget_( info->main_window, "statusbar") , + glade_xml_get_widget_( info->main_window, "previewtoggle"), + pw, + ph, + img_wid, + (void*) gui, + use_threads, + num_tracks_); + + if( theme_list ) + { + GtkWidget *menu = gtk_menu_new(); + for( i = 0; theme_list[i] != NULL ; i ++ ) + { + GtkWidget *mi = gtk_menu_item_new_with_label( theme_list[i] ); + gtk_menu_shell_append( GTK_MENU_SHELL( menu ), mi ); + + g_signal_connect_swapped( G_OBJECT(mi), "activate", G_CALLBACK(theme_response), + (gpointer) g_strdup( theme_list[i] )); + + gtk_widget_show( mi ); + } + + GtkWidget *root_menu = gtk_menu_item_new_with_label( "Themes" ); + gtk_menu_item_set_submenu( GTK_MENU_ITEM( root_menu ), menu ); + + GtkWidget *menu_bar = glade_xml_get_widget_(info->main_window, "menubar1"); + gtk_menu_shell_append( GTK_MENU_SHELL(menu_bar), root_menu); + + gtk_widget_show( root_menu ); + + } + veejay_memset( &info->watch, 0, sizeof(watchdog_t)); + info->watch.state = STATE_WAIT_FOR_USER; // + veejay_memset(&(info->watch.p_time),0,sizeof(struct timeval)); + info->midi = vj_midi_new( info->main_window ); + gettimeofday( &(info->time_last) , 0 ); + + GtkWidget *srtbox = glade_xml_get_widget( info->main_window, "combobox_textsrt"); + set_tooltip_by_widget( srtbox, tooltips[TOOLTIP_SRTSELECT].text); + + + update_spin_range( "spin_framedelay", 1, MAX_SLOW, 0); + update_spin_range( "spin_samplespeed", -25,25,1); + update_slider_range( "speed_slider", -25,25,1,0); + update_slider_range( "slow_slider",1,MAX_SLOW,1,0); + +} + +void vj_gui_preview(void) +{ + gint w = info->el.width; + gint h = info->el.height; + + update_spin_value( "priout_width", w ); + update_spin_value( "priout_height", h ); + + if( w > DEFAULT_PREVIEW_WIDTH ) + w = DEFAULT_PREVIEW_WIDTH; + if( h > DEFAULT_PREVIEW_HEIGHT ) + h = DEFAULT_PREVIEW_HEIGHT; + + update_spin_range( "preview_width", 16, w, + (info->run_state == RUN_STATE_REMOTE ? (default_preview_width_==0 ? w/4: default_preview_width_) : w ) ); + update_spin_range( "preview_height", 16, h, + (info->run_state == RUN_STATE_REMOTE ? (default_preview_height_ == 0 ? h/4 : default_preview_height_) : h ) ); + + update_spin_incr( "preview_width", 16, 0 ); + update_spin_incr( "preview_height", 16, 0 ); + update_spin_incr( "priout_width", 16,0 ); + update_spin_incr( "priout_height", 16, 0 ); + + info->image_w = w; + info->image_h = h; + + GdkRectangle result; + widget_get_rect_in_screen( + glade_xml_get_widget_(info->main_window, "quickselect"), + &result + ); + gdouble ratio = (gdouble) h / (gdouble) w; + + gint image_width = 32; + gint image_height = 32 *ratio; + + info->sequence_view->w = image_width; + info->sequence_view->h = image_height; + gtk_widget_set_size_request_(info->quick_select, image_width, image_height ); +} + +void gveejay_preview( int p ) +{ + user_preview = p; +} + +int gveejay_user_preview() +{ + return user_preview; +} + +int vj_gui_reconnect(char *hostname,char *group_name, int port_num) +{ + int k = 0; + for( k = 0; k < 4; k ++ ) + veejay_memset( info->history_tokens[k] , 0, (sizeof(int) * STATUS_TOKENS) ); + + veejay_memset( info->status_tokens, 0, sizeof(int) * STATUS_TOKENS ); + + + if(!hostname && !group_name ) + { + veejay_msg(0,"Invalid host/group name given"); + return 0; + } + + if(info->client ) + { + error_dialog("Warning", "You should disconnect first"); + return 0; + } + + if(!info->client) + { + info->client = vj_client_alloc(0,0,0); + if(!info->client) + { + return 0; + } + } + + if(!vj_client_connect( info->client, hostname, group_name, port_num ) ) + { + if(info->client) + vj_client_free(info->client); + info->client = NULL; + return 0; + } + + + vj_msg(VEEJAY_MSG_INFO, "New connection with Veejay running on %s port %d", + (group_name == NULL ? hostname : group_name), port_num ); + + veejay_msg(VEEJAY_MSG_INFO, "Connection established with %s:%d (Track 0)",hostname,port_num); + + load_editlist_info(); + info->status_lock = 1; + + update_slider_value( "framerate", info->el.fps, 0 ); + + veejay_memset( vims_keys_list, 0 , sizeof(vims_keys_list)); + veejay_memset( vj_event_list, 0, sizeof( vj_event_list)); + + load_effectlist_info(); + reload_vimslist(); + reload_editlist_contents(); + reload_bundles(); + + GtkWidget *w = glade_xml_get_widget_(info->main_window, "gveejay_window" ); + gtk_widget_show( w ); + + +/* int speed = info->status_tokens[SAMPLE_SPEED]; + if( speed < 0 ) + info->play_direction = -1; else info->play_direction=1; + if( speed < 0 ) speed *= -1;*/ + update_label_str( "label_hostnamex", (hostname == NULL ? group_name: hostname ) ); + update_label_i( "label_portx",port_num,0); + + info->status_lock = 0; + + multitrack_configure( info->mt, + info->el.fps, info->el.width, info->el.height, &preview_box_w_, &preview_box_h_ ); + + vj_gui_preview(); + + info->uc.reload_hint[HINT_SLIST] = 1; + info->uc.reload_hint[HINT_CHAIN] = 1; + info->uc.reload_hint[HINT_ENTRY] = 1; + info->uc.reload_hint[HINT_SEQ_ACT] = 1; + info->uc.reload_hint[HINT_HISTORY] = 1; + + + return 1; +} + +static void veejay_stop_connecting(vj_gui_t *gui) +{ + GtkWidget *veejay_conncection_window; + + if(!gui->sensitive) + vj_gui_enable(); + + info->launch_sensitive = 0; + + veejay_conncection_window = glade_xml_get_widget(info->main_window, "veejay_connection"); + gtk_widget_hide(veejay_conncection_window); + GtkWidget *mw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); + + gtk_widget_show( mw ); +} + +void reloaded_launcher(char *hostname, int port_num) +{ + info->watch.state = STATE_RECONNECT; + put_text( "entry_hostname", hostname ); + update_spin_value( "button_portnum", port_num ); +} + + + +void reloaded_schedule_restart() +{ + info->watch.state = STATE_STOPPED; +} + +void reloaded_restart() +{ + GtkWidget *cd = glade_xml_get_widget_(info->main_window, "veejay_connection" ); + GtkWidget *mw = glade_xml_get_widget_(info->main_window,"gveejay_window" ); +#ifdef STRICT_CHECKING + assert( cd != NULL ); + assert( mw != NULL ); +#endif + // disable and hide mainwindow + if(info->sensitive) + vj_gui_disable(); + gtk_widget_hide( mw ); + + vj_gui_wipe(); + + //@ bring up the launcher window + gtk_widget_show( cd ); +// info->watch.state = STATE_CONNECT; + info->watch.state = STATE_WAIT_FOR_USER; + info->launch_sensitive = TRUE; + + veejay_msg(VEEJAY_MSG_INFO, "Ready to make a connection to a veejay server"); +} + +gboolean is_alive( int *do_sync ) +{ + void *data = info; + vj_gui_t *gui = (vj_gui_t*) data; + + if( gui->watch.state == STATE_PLAYING ) + { + *do_sync = 1; + return TRUE; + } + + if( gui->watch.state == STATE_RECONNECT ) + { + vj_gui_disconnect(); + gui->watch.state = STATE_CONNECT; + } + + if(gui->watch.state == STATE_DISCONNECT ) + { + gui->watch.state = STATE_STOPPED; + vj_gui_disconnect(); + return FALSE; + } + + if( gui->watch.state == STATE_STOPPED ) + { + if(info->client) + vj_gui_disconnect(); + // reloaded_schedule_restart(); + reloaded_restart(); + *do_sync = 0; + return TRUE; + // return FALSE; + } + + if( gui->watch.state == STATE_QUIT ) + { + if(info->client) vj_gui_disconnect(); + return FALSE; + } + + if( gui->watch.state == STATE_CONNECT ) + { + char *remote; + int port; + remote = get_text( "entry_hostname" ); + port = get_nums( "button_portnum" ); + + veejay_msg(VEEJAY_MSG_INFO, "Connecting to %s: %d", remote,port ); + if(!vj_gui_reconnect( remote, NULL, port )) + { + reloaded_schedule_restart(); + } + else + { + info->watch.state = STATE_PLAYING; + info->key_id = gtk_key_snooper_install( key_handler , NULL); + multrack_audoadd( info->mt, remote, port ); + *do_sync = 1; + if( user_preview ) { + info->preview_locked = 1; + multitrack_set_quality( info->mt, user_preview ); + set_toggle_button( "previewtoggle", 1 ); + info->preview_locked = 0; + } + veejay_stop_connecting(gui); + } + } + + if( gui->watch.state == STATE_WAIT_FOR_USER ) + { + *do_sync = 0; + } + + return TRUE; +} + + +void vj_gui_disconnect() +{ + if(info->key_id) + gtk_key_snooper_remove( info->key_id ); + free_samplebank(); + + if(info->client) + { + vj_client_close(info->client); + vj_client_free(info->client); + info->client = NULL; + } + /* reset all trees */ + reset_tree("tree_effectlist"); + reset_tree("tree_effectmixlist"); + reset_tree("tree_chain"); + reset_tree("tree_sources"); + reset_tree("editlisttree"); + + reloaded_schedule_restart(); +} + +void vj_gui_disable() +{ + + int i = 0; + + while( uiwidgets[i].name != NULL ) + { + disable_widget( uiwidgets[i].name ); + i++; + } + + info->sensitive = 0; +} + + + +void vj_gui_enable() +{ + int i =0; + while( uiwidgets[i].name != NULL) + { + enable_widget( uiwidgets[i].name ); + i++; + } + info->sensitive = 1; +} + +sample_slot_t *vj_gui_get_sample_info(gint which_one, gint mode ) +{ + sample_slot_t *tmp_slot = (sample_slot_t*) vj_calloc(sizeof(sample_slot_t)); + + multi_vims( VIMS_SAMPLE_INFO, "%d %d", which_one, mode ); + + gint sample_info_len = 0; + gchar *sample_info = recv_vims( 8, &sample_info_len); + gint descr_len = 0; + gchar *p = sample_info; + + if(sample_info_len <= 0 ) + { + if(sample_info) g_free(sample_info); + if(tmp_slot) free(tmp_slot); + return NULL; + } + + sscanf(sample_info, "%d",&descr_len ); + sample_info += 3; + tmp_slot->title = g_strndup( sample_info, descr_len ); + sample_info += descr_len; + + gint timecode_len = 0; + sscanf( sample_info,"%d", &timecode_len ); + sample_info += 3; + tmp_slot->timecode = g_strndup( sample_info, timecode_len ); + sample_info += timecode_len; + + tmp_slot->sample_id = which_one; + tmp_slot->sample_type = mode; + + if(p) g_free(p); + + return tmp_slot; +} + + +static void +widget_get_rect_in_screen (GtkWidget *widget, GdkRectangle *r) +{ +//GdkRectangle extents; +//GdkWindow *window; +//window = GDK_WINDOW(gtk_widget_get_parent_window(widget)); /* getting parent window */ +//gdk_window_get_root_origin(window, &x,&y); /* parent's left-top screen coordinates */ +//gdk_drawable_get_size(window, &w,&h); /* parent's width and height */ +//gdk_window_get_frame_extents(window, &extents); /* parent's extents (including decorations) */ +//r->x = x + (extents.width-w)/2 + widget->allocation.x; /* calculating x (assuming: left border size == right border size) */ +//r->y = y + (extents.height-h)-(extents.width-w)/2 + widget->allocation.y; /* calculating y (assuming: left border size == right border size == bottom border size) */ +r->x = 0; +r->y = 0; +r->width = widget->allocation.width; +r->height = widget->allocation.height; +} + + +/* -------------------------------------------------------------------------------------------------------------------------- + * Function that creates the sample-bank initially, just add the widget to the GUI and create references for the + * sample_banks-structure so that the widgets are easiely accessable + * The GUI componenets are in sample_bank[i]->gui_slot[j] + * + -------------------------------------------------------------------------------------------------------------------------- */ + +int power_of_2(int x) +{ + int p = 1; + while( p < x ) + p <<= 1; + return p; +} + +/* Add a page to the notebook and initialize slots */ +static int add_bank( gint bank_num ) +{ + gchar str_label[5]; + gchar frame_label[20]; + sprintf(str_label, "%d", bank_num ); + sprintf(frame_label, "Slots %d to %d", + (bank_num * NUM_SAMPLES_PER_PAGE), (bank_num * NUM_SAMPLES_PER_PAGE) + NUM_SAMPLES_PER_PAGE ); + + setup_samplebank( NUM_SAMPLES_PER_COL, NUM_SAMPLES_PER_ROW, info->sample_bank_pad, &(info->image_dimensions[0]), + &(info->image_dimensions[1]) ); + + info->sample_banks[bank_num] = (sample_bank_t*) vj_calloc(sizeof(sample_bank_t)); + info->sample_banks[bank_num]->bank_number = bank_num; + sample_slot_t **slot = (sample_slot_t**) vj_calloc(sizeof(sample_slot_t*) * NUM_SAMPLES_PER_PAGE); + sample_gui_slot_t **gui_slot = (sample_gui_slot_t**) vj_calloc(sizeof(sample_gui_slot_t*) * NUM_SAMPLES_PER_PAGE ); + + int j; + for(j = 0;j < NUM_SAMPLES_PER_PAGE; j ++ ) + { + slot[j] = (sample_slot_t*) vj_calloc(sizeof(sample_slot_t) ); + gui_slot[j] = (sample_gui_slot_t*) vj_calloc(sizeof(sample_gui_slot_t)); +// slot[j]->rawdata = (guchar*) vj_calloc(sizeof(guchar) * 3 * 128 * 128 ); + slot[j]->slot_number = j; + slot[j]->sample_id = -1; + slot[j]->sample_type = -1; + } + + info->sample_banks[bank_num]->slot = slot; + info->sample_banks[bank_num]->gui_slot = gui_slot; + + GtkWidget *sb = info->sample_bank_pad; + GtkWidget *frame = gtk_frame_new(frame_label); + GtkWidget *label = gtk_label_new( str_label ); + + gtk_container_set_border_width( GTK_CONTAINER( frame), 0 ); + + gtk_widget_show(frame); + info->sample_banks[bank_num]->page_num = gtk_notebook_append_page(GTK_NOTEBOOK(info->sample_bank_pad), frame, label); + + GtkWidget *table = gtk_table_new( NUM_SAMPLES_PER_COL, NUM_SAMPLES_PER_ROW, TRUE ); + gtk_container_add( GTK_CONTAINER(frame), table ); + gtk_widget_show(table); + gtk_widget_show(sb ); + + + gint col, row; + for( col = 0; col < NUM_SAMPLES_PER_COL; col ++ ) + { + for( row = 0; row < NUM_SAMPLES_PER_ROW; row ++ ) + { + int slot_nr = col * NUM_SAMPLES_PER_ROW + row; + if(slot_nr < NUM_SAMPLES_PER_PAGE) + { + create_slot( bank_num, slot_nr ,info->image_dimensions[0], info->image_dimensions[1]); + sample_gui_slot_t *gui_slot = info->sample_banks[bank_num]->gui_slot[slot_nr]; + gtk_table_attach_defaults ( GTK_TABLE(table), gui_slot->event_box, row, row+1, col, col+1); + set_tooltip_by_widget( gui_slot->frame, tooltips[TOOLTIP_SAMPLESLOT].text); + } + } + } + + + if(!info->fg_) + { + info->fg_ = widget_get_fg( GTK_WIDGET(info->sample_banks[bank_num]->gui_slot[0]->frame) ); + } + return bank_num; +} + + +void reset_samplebank(void) +{ + info->selection_slot = NULL; + info->selection_gui_slot = NULL; + info->selected_slot = NULL; + info->selected_gui_slot = NULL; + int i,j; + for( i = 0; i < NUM_BANKS; i ++ ) + { + if(info->sample_banks[i]) + { + /* clear memory in use */ + for(j = 0; j < NUM_SAMPLES_PER_PAGE ; j ++ ) + { + sample_slot_t *slot = info->sample_banks[i]->slot[j]; + + if(slot->sample_id) + { + if(slot->title) free(slot->title); + if(slot->timecode) free(slot->timecode); + if(slot->pixbuf) gdk_pixbuf_unref( slot->pixbuf ); + slot->title = NULL; + slot->timecode = NULL; + slot->sample_id = 0; + slot->sample_type = 0; + slot->pixbuf = NULL; + } + update_sample_slot_data( i,j, slot->sample_id,slot->sample_type,slot->title,slot->timecode); + } + } + } +} + +void free_samplebank(void) +{ + int i,j; + while( gtk_notebook_get_n_pages(GTK_NOTEBOOK(info->sample_bank_pad) ) > 0 ) + gtk_notebook_remove_page( GTK_NOTEBOOK(info->sample_bank_pad), -1 ); + + + info->selection_slot = NULL; + info->selection_gui_slot = NULL; + info->selected_slot = NULL; + info->selected_gui_slot = NULL; + + for( i = 0; i < NUM_BANKS; i ++ ) + { + + if(info->sample_banks[i]) + { + /* free memory in use */ + for(j = 0; j < NUM_SAMPLES_PER_PAGE ; j ++ ) + { + sample_slot_t *slot = info->sample_banks[i]->slot[j]; + sample_gui_slot_t *gslot = info->sample_banks[i]->gui_slot[j]; + if(slot->title) free(slot->title); + if(slot->timecode) free(slot->timecode); + if(slot->pixbuf) gdk_pixbuf_unref(slot->pixbuf); + // if(slot->rawdata) free(slot->rawdata); + free(slot); + free(gslot); + info->sample_banks[i]->slot[j] = NULL; + info->sample_banks[i]->gui_slot[j] = NULL; + } + free(info->sample_banks[i]); + info->sample_banks[i] = NULL; + + } + } + veejay_memset( info->sample_banks, 0, sizeof(sample_bank_t*) * NUM_BANKS ); +} +#define RUP8(num)(((num)+8)&~8) + + +//@ OK +void setup_samplebank(gint num_cols, gint num_rows, GtkWidget *pad, int *idx, int *idy) +{ + GdkRectangle result; + if(info->el.width <= 0 || info->el.height <= 0 ) { + *idx = 0; + *idy = 0; + return; + } + else { + widget_get_rect_in_screen( + pad, + &result + ); + result.width -= ( num_rows * 16); + result.height -= ( num_cols * 16); + gint image_width = result.width / num_rows; + gint image_height = result.height / num_cols; + + + float ratio = (float) info->el.height / (float) info->el.width; + image_height = image_width * ratio; + + gfloat w = image_width; + gfloat h = image_width * ratio; + + *idx = (int)w; + *idy = (int)h; + + } + veejay_msg(VEEJAY_MSG_INFO, "Sample bank image dimensions: %dx%d", *idx,*idy); +} + +/* -------------------------------------------------------------------------------------------------------------------------- + * Function that resets the visualized sample-informations of the samplebanks, it does this by going through all + * slots that allready used and resets them (which means cleaning the shown infos as well as set them free for further use) + * with_selection should be TRUE when the actual selection of a sample-bank-slot should also be reseted + * (what is for instance necessary when vj reconnected) + -------------------------------------------------------------------------------------------------------------------------- */ + +static int bank_exists( int bank_page, int slot_num ) +{ + + if(!info->sample_banks[bank_page]) + return 0; + return 1; +} + +static sample_slot_t *find_slot_by_sample( int sample_id , int sample_type ) +{ + char key[32]; + sprintf(key, "S%04d%02d",sample_id, sample_type ); + + void *slot = NULL; + vevo_property_get( bankport_, key, 0,&slot ); + if(!slot) + return NULL; + return (sample_slot_t*) slot; +} +static sample_gui_slot_t *find_gui_slot_by_sample( int sample_id , int sample_type ) +{ + char key[32]; + sprintf(key, "G%04d%02d",sample_id, sample_type ); + + void *slot = NULL; + vevo_property_get( bankport_, key, 0,&slot ); + if(!slot) + return NULL; + return (sample_gui_slot_t*) slot; +} + +static int find_bank_by_sample(int sample_id, int sample_type, int *slot ) +{ + int i,j; + + for( i = 0; i < NUM_BANKS; i ++ ) + { + if(!info->sample_banks[i]) { + continue; + } + + for( j = 0; j < NUM_SAMPLES_PER_PAGE; j ++ ) + { + if(info->sample_banks[i]->slot[j]->sample_id == sample_id && + info->sample_banks[i]->slot[j]->sample_type == sample_type) + { + *slot = j; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "using existing slot (%d,%d)", + sample_id,sample_type ); +#endif + return i; + } + } + } + + for( i = 0; i < NUM_BANKS; i ++ ) + { + if(!info->sample_banks[i]) { + *slot = 0; + return i; + } + + for( j = 0; j < NUM_SAMPLES_PER_PAGE; j ++ ) + { + if ( info->sample_banks[i]->slot[j]->sample_id <= 0) + { + *slot = j; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "using new slot (%d,%d)", + sample_id,sample_type); +#endif + return i; + } + } + } + + *slot = -1; + return -1; +} + +static int find_bank(int page_nr) +{ + int i = 0; + for ( i = 0 ; i < NUM_BANKS; i ++ ) + if( info->sample_banks[i] && info->sample_banks[i]->page_num == page_nr ) + { + return info->sample_banks[i]->bank_number; + } + return -1; +} + +static void set_activation_of_cache_slot_in_samplebank( sequence_gui_slot_t *gui_slot, gboolean activate) +{ + if (activate) + { + gtk_frame_set_shadow_type(GTK_FRAME(gui_slot->frame),GTK_SHADOW_IN); + } + else { + gtk_frame_set_shadow_type(GTK_FRAME(gui_slot->frame),GTK_SHADOW_ETCHED_IN); + } +} + +static gboolean on_sequencerslot_activated_by_mouse(GtkWidget *widget, GdkEventButton *event, gpointer user_data) +{ + gint slot_nr = GPOINTER_TO_INT(user_data); + + if( event->type == GDK_BUTTON_PRESS && (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK ) + { + multi_vims( VIMS_SEQUENCE_DEL, "%d", slot_nr ); + gtk_label_set_text( GTK_LABEL(info->sequencer_view->gui_slot[slot_nr]->image), + NULL ); + } + else + if(event->type == GDK_BUTTON_PRESS) + { + int id = info->status_tokens[CURRENT_ID]; + if( info->selection_slot ) + id = info->selection_slot->sample_id; + multi_vims( VIMS_SEQUENCE_ADD, "%d %d", slot_nr, id ); + info->uc.reload_hint[HINT_SEQ_ACT] = 1; + } + return FALSE; +} + +static gboolean on_cacheslot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data) +{ + gint slot_nr = -1; + if(info->status_tokens[PLAY_MODE] == MODE_PLAIN ) + return FALSE; + + slot_nr =GPOINTER_TO_INT( user_data ); + set_activation_of_cache_slot_in_samplebank( info->sequence_view->gui_slot[slot_nr], FALSE ); + + if( event->type == GDK_BUTTON_PRESS && (event->state & GDK_SHIFT_MASK) == GDK_SHIFT_MASK ) + { + info->current_sequence_slot = slot_nr; + sample_slot_t *s = info->selected_slot; + sequence_gui_slot_t *g = info->sequence_view->gui_slot[slot_nr]; +#ifdef STRICT_CHECKING + assert( s != NULL ); + assert( g != NULL ); +#endif + g->sample_id = s->sample_id; + g->sample_type = s->sample_type; + vj_msg(VEEJAY_MSG_INFO, "Placed %s %d in Memory slot %d", + (g->sample_type == 0 ? "Sample" : "Stream" ), g->sample_id, slot_nr ); + } + else + if(event->type == GDK_BUTTON_PRESS) + { + sequence_gui_slot_t *g = info->sequence_view->gui_slot[slot_nr]; + if(g->sample_id <= 0) + { + vj_msg(VEEJAY_MSG_ERROR, "Memory slot %d empty, put with SHIFT + mouse button1",slot_nr); + return FALSE; + + } + multi_vims(VIMS_SET_MODE_AND_GO, "%d %d", g->sample_type, g->sample_id ); + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SET_MODE_AND_GO, g->sample_type,g->sample_id ); + } + return FALSE; +} + + + +static void create_sequencer_slots(int nx, int ny) +{ + GtkWidget *vbox = glade_xml_get_widget_ (info->main_window, "SampleSequencerBox"); + info->sample_sequencer = gtk_frame_new(NULL); + gtk_box_pack_start( GTK_BOX( vbox ), GTK_WIDGET(info->sample_sequencer), TRUE, TRUE, 0); + gtk_widget_show(info->sample_sequencer); + + info->sequencer_view = (sequence_envelope*) vj_calloc(sizeof(sequence_envelope) ); + info->sequencer_view->gui_slot = (sequence_gui_slot_t**) vj_calloc(sizeof(sequence_gui_slot_t*) * ( nx * ny + 1 ) ); + + GtkWidget *table = gtk_table_new( nx, ny, TRUE ); + + gtk_container_add( GTK_CONTAINER(info->sample_sequencer), table ); + gtk_widget_show(table); + + gint col=0; + gint row=0; + gint k = 0; + for( col = 0; col < ny; col ++ ) + for( row = 0; row < nx; row ++ ) + { + sequence_gui_slot_t *gui_slot = (sequence_gui_slot_t*)vj_calloc(sizeof(sequence_gui_slot_t)); + info->sequencer_view->gui_slot[k] = gui_slot; + + gui_slot->event_box = gtk_event_box_new(); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(gui_slot->event_box), TRUE); + GTK_WIDGET_SET_FLAGS(gui_slot->event_box,GTK_CAN_FOCUS); + + g_signal_connect( G_OBJECT(gui_slot->event_box), + "button_press_event", + G_CALLBACK(on_sequencerslot_activated_by_mouse), //@@@@ + (gpointer) k + ); + gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); + + gui_slot->frame = gtk_frame_new(NULL); + gtk_container_set_border_width (GTK_CONTAINER(gui_slot->frame),0); + gtk_frame_set_shadow_type(GTK_FRAME( gui_slot->frame), GTK_SHADOW_IN ); + gtk_widget_show(GTK_WIDGET(gui_slot->frame)); + gtk_container_add (GTK_CONTAINER (gui_slot->event_box), gui_slot->frame); + + /* the slot main container */ + gui_slot->main_vbox = gtk_vbox_new(FALSE,0); + gtk_container_add (GTK_CONTAINER (gui_slot->frame), gui_slot->main_vbox); + gtk_widget_show( GTK_WIDGET(gui_slot->main_vbox) ); + + gui_slot->image = gtk_label_new(NULL); + gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), GTK_WIDGET(gui_slot->image), TRUE, TRUE, 0); + gtk_widget_show( gui_slot->image); + gtk_table_attach_defaults ( GTK_TABLE(table), gui_slot->event_box, row, row+1, col, col+1); + k++; + } +// gtk_widget_set_size_request_( table, 300,300); +// info->sequencer_view->envelope_size = envelope_size; +} + + +static void create_ref_slots(int envelope_size) +{ + gchar frame_label[50]; + GtkWidget *vbox = glade_xml_get_widget_ (info->main_window, "quickselect"); + info->quick_select = gtk_frame_new(NULL); + gtk_box_pack_start( GTK_BOX( vbox ), GTK_WIDGET(info->quick_select), TRUE, TRUE, 0); + gtk_widget_show(info->quick_select); + info->sequence_view = (sequence_envelope*) vj_calloc(sizeof(sequence_envelope) ); + info->sequence_view->gui_slot = (sequence_gui_slot_t**) vj_calloc(sizeof(sequence_gui_slot_t*) * envelope_size ); + sprintf(frame_label, "Last played" ); + GtkWidget *table = gtk_table_new( 1, envelope_size, TRUE ); + gtk_container_add( GTK_CONTAINER(info->quick_select), table ); + gtk_widget_show(table); + + gint col=0; + gint row=0; + for( row = 0; row < envelope_size; row ++ ) + { + sequence_gui_slot_t *gui_slot = (sequence_gui_slot_t*)vj_calloc(sizeof(sequence_gui_slot_t)); + info->sequence_view->gui_slot[row] = gui_slot; + gui_slot->event_box = gtk_event_box_new(); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(gui_slot->event_box), TRUE); + GTK_WIDGET_SET_FLAGS(gui_slot->event_box,GTK_CAN_FOCUS); + /* Right mouse button is popup menu, click = play */ + g_signal_connect( G_OBJECT(gui_slot->event_box), + "button_press_event", + G_CALLBACK(on_cacheslot_activated_by_mouse), + (gpointer)row + ); + gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); + /* the surrounding frame for each slot */ + gui_slot->frame = gtk_frame_new(NULL); + set_tooltip_by_widget(gui_slot->frame, tooltips[TOOLTIP_QUICKSELECT].text ); + gtk_container_set_border_width (GTK_CONTAINER(gui_slot->frame),1); + gtk_widget_show(GTK_WIDGET(gui_slot->frame)); + gtk_container_add (GTK_CONTAINER (gui_slot->event_box), gui_slot->frame); + + /* the slot main container */ + gui_slot->main_vbox = gtk_vbox_new(FALSE,0); + gtk_container_add (GTK_CONTAINER (gui_slot->frame), gui_slot->main_vbox); + gtk_widget_show( GTK_WIDGET(gui_slot->main_vbox) ); + + /* The sample's image */ + gui_slot->image = gtk_image_new(); + gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), GTK_WIDGET(gui_slot->image), TRUE, TRUE, 0); +// gtk_widget_set_size_request_( gui_slot->image, info->sequence_view->w,info->sequence_view->h ); + gtk_widget_show( GTK_WIDGET(gui_slot->image)); + + gtk_table_attach_defaults ( GTK_TABLE(table), gui_slot->event_box, row, row+1, col, col+1); + + + + } + info->sequence_view->envelope_size = envelope_size; +} + +static void create_slot(gint bank_nr, gint slot_nr, gint w, gint h) +{ + gchar hotkey[3]; + + sample_bank_t **sample_banks = info->sample_banks; + sample_gui_slot_t *gui_slot = sample_banks[bank_nr]->gui_slot[slot_nr]; + + // to reach clicks on the following GUI-Elements of one slot, they are packed into an event_box + gui_slot->event_box = gtk_event_box_new(); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(gui_slot->event_box), TRUE); + + GTK_WIDGET_SET_FLAGS(gui_slot->event_box,GTK_CAN_FOCUS); + g_signal_connect( G_OBJECT(gui_slot->event_box), + "button_press_event", + G_CALLBACK(on_slot_activated_by_mouse), + (gpointer)slot_nr + ); + gtk_widget_show(GTK_WIDGET(gui_slot->event_box)); + /* the surrounding frame for each slot */ + gui_slot->frame = gtk_frame_new(NULL); + + gtk_container_set_border_width (GTK_CONTAINER(gui_slot->frame),0); + gtk_widget_show(GTK_WIDGET(gui_slot->frame)); + gtk_container_add (GTK_CONTAINER (gui_slot->event_box), GTK_WIDGET(gui_slot->frame)); + + + /* the slot main container */ + gui_slot->main_vbox = gtk_vbox_new(FALSE,0); + gtk_container_add (GTK_CONTAINER (gui_slot->frame), gui_slot->main_vbox); + gtk_widget_show( GTK_WIDGET(gui_slot->main_vbox) ); + + + gui_slot->image = gtk_image_new(); +// gui_slot->image = gtk_drawing_area_new(); + gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), GTK_WIDGET(gui_slot->image), TRUE, TRUE, 0); +// gtk_widget_show(GTK_WIDGET(gui_slot->image)); + gtk_widget_set_size_request_( gui_slot->image, info->image_dimensions[0],info->image_dimensions[1] ); +/* g_signal_connect( gui_slot->image, "expose_event", + G_CALLBACK(image_expose_event), + (gpointer) info->sample_banks[bank_nr]->slot[slot_nr]->slot_number ); +*/ gtk_widget_show( GTK_WIDGET(gui_slot->image)); + + /* the upper container for all slot-informations */ + gui_slot->upper_hbox = gtk_hbox_new(FALSE,0); + gtk_box_pack_start (GTK_BOX (gui_slot->main_vbox), gui_slot->upper_hbox, FALSE, TRUE, 0); + gtk_widget_show(GTK_WIDGET(gui_slot->upper_hbox)); + + + if( sample_banks[bank_nr]->slot[slot_nr]->sample_type >= 0 ) + { + /* the hotkey that is assigned to this slot */ + sprintf(hotkey, "F-%d", (slot_nr+1)); + gui_slot->hotkey = gtk_label_new(hotkey); + } + else + { + gui_slot->hotkey = gtk_label_new(""); + } + gtk_misc_set_alignment(GTK_MISC(gui_slot->hotkey), 0.0, 0.0); + gtk_misc_set_padding (GTK_MISC(gui_slot->hotkey), 0, 0); + gtk_box_pack_start (GTK_BOX (gui_slot->upper_hbox), GTK_WIDGET(gui_slot->hotkey), FALSE, FALSE, 0); + gtk_widget_show(GTK_WIDGET(gui_slot->hotkey)); + gui_slot->upper_vbox = gtk_vbox_new(FALSE,0); + gtk_box_pack_start (GTK_BOX (gui_slot->upper_hbox), gui_slot->upper_vbox, TRUE, TRUE, 0); + gtk_widget_show(GTK_WIDGET(gui_slot->upper_vbox)); + gui_slot->title = gtk_label_new(""); + + gui_slot->timecode = gtk_label_new(""); + gtk_misc_set_alignment(GTK_MISC(gui_slot->timecode), 0.5, 0.0); + gtk_misc_set_alignment(GTK_MISC(gui_slot->title), 0.5, 0.0); + + gtk_misc_set_padding (GTK_MISC(gui_slot->timecode), 0,0 ); + gtk_box_pack_start (GTK_BOX (gui_slot->upper_vbox), GTK_WIDGET(gui_slot->timecode), FALSE, FALSE, 0); + gtk_widget_show(GTK_WIDGET(gui_slot->timecode)); + +} + + +/* -------------------------------------------------------------------------------------------------------------------------- + * Handler of mouse clicks on the GUI-elements of one slot + * single-click activates the slot and the loaded sample (if there is one) + * double-click or tripple-click activates it and plays it immediatelly + -------------------------------------------------------------------------------------------------------------------------- */ +static gboolean on_slot_activated_by_mouse (GtkWidget *widget, GdkEventButton *event, gpointer user_data) +{ + gint bank_nr = -1; + gint slot_nr = -1; + + bank_nr = find_bank( gtk_notebook_get_current_page(GTK_NOTEBOOK(info->sample_bank_pad))); + if(bank_nr < 0 ) + return FALSE; + + slot_nr = GPOINTER_TO_INT(user_data); + sample_bank_t **sample_banks = info->sample_banks; + + if( info->sample_banks[ bank_nr ]->slot[ slot_nr ]->sample_id <= 0 ) + return FALSE; + + if( event->type == GDK_2BUTTON_PRESS ) + { + sample_slot_t *s = sample_banks[bank_nr]->slot[slot_nr]; + multi_vims( VIMS_SET_MODE_AND_GO, "%d %d", (s->sample_type==0? 0:1), s->sample_id); + vj_midi_learning_vims_msg2( info->midi, NULL, VIMS_SET_MODE_AND_GO, s->sample_type, s->sample_id ); + vj_msg(VEEJAY_MSG_INFO, "Start playing %s %d", + (s->sample_type==0 ? "Sample" : "Stream" ), s->sample_id ); + } + else if(event->type == GDK_BUTTON_PRESS ) + { + if( (event->state & GDK_SHIFT_MASK ) == GDK_SHIFT_MASK ) { + sample_slot_t *x = sample_banks[bank_nr]->slot[slot_nr]; + multi_vims( VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, + "%d %d %d %d", + 0, + info->uc.selected_chain_entry, + x->sample_type, + x->sample_id ); + + if(x->sample_id == 1 ) { + vj_msg(VEEJAY_MSG_INFO, "Set mixing channel %d to Stream %d", info->uc.selected_chain_entry, + x->sample_id ); + } else { + vj_msg(VEEJAY_MSG_INFO, "Set mixing channel %d to Sample %d", info->uc.selected_chain_entry, + x->sample_id); + } + + char trip[100]; + snprintf(trip, sizeof(trip), "%03d:%d %d %d %d",VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, + 0, + info->uc.selected_chain_entry, + x->sample_type, + x->sample_id ); + + vj_midi_learning_vims( info->midi, NULL, trip, 0 ); + } else { + if(info->selection_slot) + set_selection_of_slot_in_samplebank(FALSE); + info->selection_slot = sample_banks[bank_nr]->slot[slot_nr]; + info->selection_gui_slot = sample_banks[bank_nr]->gui_slot[slot_nr]; + set_selection_of_slot_in_samplebank(TRUE ); + } + } + return FALSE; + +} + + +static void indicate_sequence( gboolean active, sequence_gui_slot_t *slot ) +{ + if(!active) + gtk_frame_set_shadow_type( GTK_FRAME(slot->frame), GTK_SHADOW_IN ); + else + gtk_frame_set_shadow_type( GTK_FRAME(slot->frame), GTK_SHADOW_OUT ); +} + +/* -------------------------------------------------------------------------------------------------------------------------- + * Function that handles to select/activate a special slot in the samplebank + -------------------------------------------------------------------------------------------------------------------------- */ + +void set_widget_color( GtkWidget *widget , int red, int green, int blue, int def ) +{ + GdkColor color; + if( def ) { + color.red = info->fg_->red; + color.green = info->fg_->green; + color.blue = info->fg_->blue; + } else { + color.red = red; + color.green = green; + color.blue = blue; + } + gtk_widget_modify_fg ( GTK_WIDGET(widget),GTK_STATE_NORMAL, &color ); +} + +static void set_activation_of_slot_in_samplebank( gboolean activate) +{ + if(!info->selected_gui_slot || !info->selected_slot ) + return; + GdkColor color; + color.red = info->fg_->red; + color.green = info->fg_->green; + color.blue = info->fg_->blue; + + if(info->selected_slot->sample_id <= 0 ) + { + gtk_frame_set_shadow_type( GTK_FRAME(info->selected_gui_slot->frame), GTK_SHADOW_ETCHED_IN ); + } + else + { + if (activate) + { + color.green = 0xffff; + color.red = 0; + color.blue =0; + gtk_frame_set_shadow_type(GTK_FRAME(info->selected_gui_slot->frame),GTK_SHADOW_IN); + gtk_widget_grab_focus(GTK_WIDGET(info->selected_gui_slot->frame)); + } + else + { + gtk_frame_set_shadow_type(GTK_FRAME(info->selected_gui_slot->frame),GTK_SHADOW_ETCHED_IN); + } + } + + gtk_widget_modify_fg ( GTK_WIDGET(info->selected_gui_slot->timecode), + GTK_STATE_NORMAL, &color ); +} + +static void set_selection_of_slot_in_samplebank(gboolean active) +{ + if(!info->selection_slot) + return; + if(info->selection_slot->sample_id <= 0 ) + return; + GdkColor color; + color.red = info->fg_->red; + color.green = info->fg_->green; + color.blue = info->fg_->blue; + if(active) + { + color.blue = 0xffff; + color.green = 0; + color.red =0; + } + + if(info->selected_slot == info->selection_slot) + { + color.green = 0xffff; + color.red = 0; + color.blue = 0; + } +// gtk_widget_modify_fg ( GTK_WIDGET(info->selection_gui_slot->title), +// GTK_STATE_NORMAL, &color ); + gtk_widget_modify_fg ( GTK_WIDGET(info->selection_gui_slot->timecode), + GTK_STATE_NORMAL, &color ); +// gtk_widget_modify_fg ( gtk_frame_get_label_widget( info->selection_gui_slot->frame ), +// GTK_STATE_NORMAL, &color ); + +} + +static int add_sample_to_sample_banks(int bank_page,sample_slot_t *slot) +{ + int bp = 0; int s = 0; +#ifdef STRICT_CHECKING + + int result = verify_bank_capacity( &bp, &s, slot->sample_id, slot->sample_type ); + + + veejay_msg(VEEJAY_MSG_DEBUG, "add slot on page %d: type=%d id=%d. result=%d", bank_page,slot->sample_type,slot->sample_id,result ); + + if( result ) + update_sample_slot_data( bp, s, slot->sample_id,slot->sample_type,slot->title,slot->timecode); + +#else + if(verify_bank_capacity( &bp, &s, slot->sample_id, slot->sample_type )) + update_sample_slot_data( bp, s, slot->sample_id,slot->sample_type,slot->title,slot->timecode); +#endif + + return 1; +} + + +/* -------------------------------------------------------------------------------------------------------------------------- + * Removes a selected sample from the specific sample-bank-slot and update the free_slots-GList as well as + -------------------------------------------------------------------------------------------------------------------------- */ + +static void remove_sample_from_slot() +{ + gint bank_nr = -1; + gint slot_nr = -1; + + bank_nr = find_bank( gtk_notebook_get_current_page( + GTK_NOTEBOOK( info->sample_bank_pad ) ) ); + if(bank_nr < 0 ) + return; + if(!info->selection_slot) + return; + + slot_nr = info->selection_slot->slot_number; + + if( info->selection_slot->sample_id == info->status_tokens[CURRENT_ID] && + info->selection_slot->sample_type == info->status_tokens[PLAY_MODE] ) + { + gchar error_msg[100]; + sprintf(error_msg, "Cannot delete %s %d while playing", + (info->selection_slot->sample_type == MODE_SAMPLE ? "Sample" : "Stream" ), + info->selection_slot->sample_id ); + message_dialog( "Error while deleting", error_msg ); + + return; + } + + multi_vims( (info->selection_slot->sample_type == 0 ? VIMS_SAMPLE_DEL : + VIMS_STREAM_DELETE ), + "%d", + info->selection_slot->sample_id ); + gint id_len = 0; + gint deleted_sample = 0; + gchar *deleted_id = recv_vims( 3, &id_len ); + sscanf( deleted_id, "%d", &deleted_sample ); + if( deleted_sample ) + { + // decrement history of delete type + int *his = info->history_tokens[ (info->status_tokens[PLAY_MODE]) ]; + + his[TOTAL_SLOTS] = his[TOTAL_SLOTS] - 1; + + update_sample_slot_data( bank_nr, slot_nr, 0, -1, NULL, NULL); + + set_selection_of_slot_in_samplebank( FALSE ); + info->selection_gui_slot = NULL; + info->selection_slot = NULL; + } +} + + +/* -------------------------------------------------------------------------------------------------------------------------- + * Function adds the given infos to the list of effect-sources + -------------------------------------------------------------------------------------------------------------------------- */ +static void add_sample_to_effect_sources_list(gint id, gint type, gchar *title, gchar *timecode) +{ + gchar id_string[512]; + GtkTreeIter iter; + + if (type == STREAM_NO_STREAM) + sprintf( id_string, "S[%4d] %s", id, title); + else sprintf( id_string, "T[%4d]", id); + + gtk_list_store_append( effect_sources_store, &iter ); + gtk_list_store_set( effect_sources_store, &iter, SL_ID, id_string, SL_DESCR, title, SL_TIMECODE , timecode,-1 ); + + GtkTreeIter iter2; + if(type == 1 && strncmp("bogus",title, 7)==0) { + gtk_list_store_append( cali_sourcestore,&iter2); + gtk_list_store_set( cali_sourcestore,&iter2,SL_ID, id_string,SL_DESCR,title,SL_TIMECODE,timecode,-1); + } +} + +/* + Update a slot, either set from function arguments or clear it + */ +static void update_sample_slot_data(int page_num, int slot_num, int sample_id, gint sample_type, gchar *title, gchar *timecode) +{ + sample_slot_t *slot = info->sample_banks[page_num]->slot[slot_num]; + sample_gui_slot_t *gui_slot = info->sample_banks[page_num]->gui_slot[slot_num]; + +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "update slot %d on page %d with (type=%d,id=%d)", + slot_num, page_num, sample_type, sample_id ); + veejay_msg(VEEJAY_MSG_DEBUG, "(#%d,type=%d,%s,%s) change to (#%d,type=%d,%s,%s)", + slot->sample_id,slot->sample_type,slot->timecode,slot->title, + sample_id,sample_type,timecode,title ); +#endif + + + + if(slot->timecode) free(slot->timecode); + if(slot->title) free(slot->title); + + slot->sample_id = sample_id; + slot->sample_type = sample_type; + slot->timecode = timecode == NULL ? strdup("") : strdup( timecode ); + slot->title = title == NULL ? strdup("") : strdup( title ); + + if( sample_id ) + { + char sample_key[32]; + sprintf(sample_key, "S%04d%02d", sample_id, sample_type ); + vevo_property_set( bankport_, sample_key, VEVO_ATOM_TYPE_VOIDPTR,1, &slot ); + sprintf(sample_key, "G%04d%02d", sample_id, sample_type ); + vevo_property_set( bankport_, sample_key, VEVO_ATOM_TYPE_VOIDPTR,1,&gui_slot); + add_sample_to_effect_sources_list(sample_id, sample_type, title, timecode); + } + + if(gui_slot) + { + if(gui_slot->title) + gtk_label_set_text( GTK_LABEL( gui_slot->title ), slot->title ); + if(gui_slot->timecode) + gtk_label_set_text( GTK_LABEL( gui_slot->timecode ), slot->timecode ); + + if(sample_id > 0 ) + { + gchar frame_title[20]; + sprintf(frame_title, "%s", slot->title ); + gtk_frame_set_label( GTK_FRAME(gui_slot->frame),frame_title ); + } + else + { + gtk_frame_set_label(GTK_FRAME(gui_slot->frame), NULL ); + } + } + + if( sample_id == 0 ) + { + if(slot->pixbuf) + { + gdk_pixbuf_unref( slot->pixbuf ); + slot->pixbuf = NULL; + } + } +} + +void veejay_release_track(int id, int release_this) +{ + multitrack_release_track( info->mt, id, release_this ); +} + +void veejay_bind_track( int id, int bind_this ) +{ + multitrack_bind_track(info->mt, id, bind_this ); + info->uc.reload_hint[HINT_SLIST] =1; + + +} diff --git a/branches/V-1.5.3/veejay-client/src/vj-api.h b/branches/V-1.5.3/veejay-client/src/vj-api.h new file mode 100644 index 00000000..fad44a36 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/vj-api.h @@ -0,0 +1,60 @@ +/* gveejay - Linux VeeJay - GVeejay GTK+-2/Glade User Interface + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + +#ifndef VJAPI_H +#define VJAPI_H +int veejay_tick(); +void *get_ui_info(); +void vj_gui_init(char *glade_file, int launcher, char *hostname, int port_num, int threads); +int vj_gui_reconnect( char *host, char *group, int port); +void vj_gui_free(); +void vj_fork_or_connect_veejay(); +void vj_gui_wipe(); +void vj_gui_enable(void); +void vj_gui_disable(void); +void vj_gui_disconnect(void); +void vj_gui_set_debug_level(int level, int preview_p, int pw, int ph); +void get_gd(char *buf, char *suf, const char *filename); +void vj_gui_theme_setup(int default_theme); +void vj_gui_set_timeout(int timer); +void set_skin(int skin); +void default_bank_values(int *col, int *row ); +void vj_gui_style_setup(); +gboolean gveejay_running(); +gboolean is_alive( int *sync ); +int vj_gui_sleep_time( void ); +int get_total_frames(); +int vj_img_cb(GdkPixbuf *img ); +int vj_get_preview_box_w(); +int vj_get_preview_box_h(); +int _effect_get_minmax( int effect_id, int *min, int *max, int index ); +void vj_gui_cb(int state, char *hostname, int port_num); +void gveejay_preview(int p); +int is_button_toggled(const char *name); +gchar *_utf8str( const char *c_str ); +void find_user_themes(); +int gveejay_user_preview(); +char *get_glade_path(); +char *get_gveejay_dir(); +int gveejay_restart(); +int gveejay_update(); +int update_gveejay(); +int veejay_update_multitrack( void *data ); +void gveejay_sleep( void *ui ); +#endif diff --git a/branches/V-1.5.3/veejay-client/src/vj-midi.c b/branches/V-1.5.3/veejay-client/src/vj-midi.c new file mode 100644 index 00000000..bfb8a147 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/vj-midi.c @@ -0,0 +1,536 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2007 Niels Elburg + * + * 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 + +extern GtkWidget *glade_xml_get_widget_( GladeXML *m, const char *name ); +extern void msg_vims(char *message); +extern void vj_msg(int type, const char format[], ...); +extern int prompt_dialog(const char *title, char *msg); +static int vj_midi_events(void *vv ); + +typedef struct +{ + snd_seq_t *sequencer; + void *vims; + struct pollfd *pfd; + int npfd; + int learn; + int learn_event[4]; + int active; + void *mw; +} vmidi_t; + +typedef struct +{ + int extra; + char *widget; + char *msg; +} dvims_t; + + +void vj_midi_learn( void *vv ) +{ + vmidi_t *v = (vmidi_t*) vv; + if(!v->active) return; + v->learn = 1; + vj_msg(VEEJAY_MSG_INFO, "Learning MIDI commands. Touch a midi key and then click a widget"); +} + +void vj_midi_play(void *vv ) +{ + vmidi_t *v = (vmidi_t*) vv; + if(!v->active) return; + + v->learn = 0; + int a = vj_midi_events(vv); + char msg[100]; + snprintf(msg,sizeof(msg), "MIDI listener active, %d events registered", a ); + vj_msg(VEEJAY_MSG_INFO, "%s",msg); +} +static int vj_midi_events(void *vv ) +{ + vmidi_t *v = (vmidi_t*)vv; + char **items = vevo_list_properties(v->vims); + if(!items) return 0; + + int i; + int len = 0; + for( i = 0; items[i] != NULL ; i ++ ) + { + len ++; + free(items[i]); + } + free(items); + return len; +} +void vj_midi_reset( void *vv ) +{ + vmidi_t *v = (vmidi_t*)vv; + + int a = vj_midi_events(vv); + if( a > 0 ) + { + char warn[200]; + snprintf(warn,sizeof(warn), "This will clear %d MIDI events, Continue ?",a ); + if( prompt_dialog( "MIDI", warn ) == GTK_RESPONSE_REJECT ) + return; + + } + + char **items = vevo_list_properties(v->vims); + if(!items) { + vj_msg(VEEJAY_MSG_INFO,"No MIDI events to clear"); + return; + } + int i; + for( i = 0; items[i] != NULL ; i ++ ) + { + dvims_t *d = NULL; + if( vevo_property_get( v->vims, items[i],0,&d ) == VEVO_NO_ERROR ) + { + if(d->msg) free(d->msg); + if(d->widget) free(d->widget); + free(d); + } + free(items[i]); + } + free(items); + + vevo_port_free(v->vims); + + v->vims = vpn(VEVO_ANONYMOUS_PORT); + + vj_msg(VEEJAY_MSG_INFO, "Cleared %d MIDI events.",a); +} + +void vj_midi_load(void *vv, const char *filename) +{ + vmidi_t *v = (vmidi_t*) vv; + if(!v->active) return; + + int a = vj_midi_events(vv); + if( a > 0 ) + { + char warn[200]; + snprintf(warn,sizeof(warn), "There are %d MIDI event known, loading from file will overwrite any existing events. Continue ?", a ); + if( prompt_dialog( "MIDI", warn ) == GTK_RESPONSE_REJECT ) + return; + + } + + int fd = open( filename, O_RDONLY ); + if(!fd) + { + vj_msg(VEEJAY_MSG_ERROR, "Unable to open file '%s': %s", filename, strerror(errno)); + return; + } + struct stat t; + if( fstat( fd, &t) != 0 ) + { + vj_msg(VEEJAY_MSG_ERROR,"Unable to load %s: %s", filename, strerror(errno)); + return; + } + else + { + if( !S_ISREG( t.st_mode ) && !S_ISLNK(t.st_mode) ) + { + vj_msg(VEEJAY_MSG_ERROR, "File '%s' is not a regular file or symbolic link. Refusing to load it.", + filename ); + return; + } + } + + char *buf = (char*) vj_calloc( 128000 ); + int done = 0; + uint32_t count = 0; + if (read( fd, buf, 128000 ) > 0 ) + { + int len = strlen( buf ); + int j,k=0; + + char value[1024]; + veejay_memset(value,0,sizeof(value)); + + for( j = 0; j < len; j ++ ) + { + if( buf[j] == '\0' ) break; + if( buf[j] == '\n' ) + { + char key[32]; + char widget[100]; + char message[512]; + int extra = 0; + if(sscanf( value, "%s %d %s \"%[^\"]", key, &extra, widget, message ) == 4 ) + { + veejay_memset( value,0,sizeof(value)); + k = 0; + dvims_t *d = (dvims_t*) vj_calloc(sizeof(dvims_t)); + dvims_t *cur = NULL; + d->extra = extra; + d->widget = NULL; + if( strncasecmp( widget, "none", 4 ) !=0 ) + d->widget = strdup(widget); + d->msg = strdup(message); + if( vevo_property_get( v->vims, key, 0, &cur ) == VEVO_NO_ERROR ) + { + if(cur->widget) free(cur->widget); + if(cur->msg) free(cur->msg); + free(cur); + } + int error = vevo_property_set( v->vims, key, 1, VEVO_ATOM_TYPE_VOIDPTR, &d); + veejay_memset( key,0,sizeof(key)); + veejay_memset( widget,0,sizeof(widget)); + veejay_memset( message,0,sizeof(message)); + count ++; + } + + } + if( buf[j] != '\n' && buf[j] != '\0' ) + value[k++] = buf[j]; + + } + + } + free(buf); + vj_msg(VEEJAY_MSG_INFO, "Loaded %d MIDI events from %s", count ,filename); +} + +void vj_midi_save(void *vv, const char *filename) +{ + vmidi_t *v = (vmidi_t*) vv; + if(!v->active) return; + + int fd = open( filename, O_TRUNC|O_CREAT|O_WRONLY,S_IRWXU ); + if(!fd) + { + vj_msg(VEEJAY_MSG_ERROR, "Unable to save MIDI settings to %s",filename); + return; + } + + char **items = vevo_list_properties( v->vims ); + int i; + if( items == NULL ) + { + vj_msg(VEEJAY_MSG_ERROR, "No MIDI events learned yet"); + return; + } + uint32_t count = 0; + for( i =0 ; items[i] != NULL ;i ++ ) + { + char tmp[512]; + dvims_t *d = NULL; + if( vevo_property_get( v->vims, items[i], 0, &d ) == VEVO_NO_ERROR ) + { + snprintf(tmp, 512, "%s %d %s \"%s\"\n", + items[i], + d->extra, + (d->widget == NULL ? "none" : d->widget ), + d->msg ); + if( write( fd, tmp, strlen( tmp )) >= 0 ) + count ++; + } + free(items[i]); + } + free(items); + close(fd); + + vj_msg(VEEJAY_MSG_INFO, "Wrote %d MIDI events to %s", count, filename ); +} + +void vj_midi_learning_vims( void *vv, char *widget, char *msg, int extra ) +{ + vmidi_t *v = (vmidi_t*) vv; + if(!v->active) return; + + if( !v->learn ) + return; + + if( v->learn_event[0] == -1 || v->learn_event[1] == -1 || v->learn_event[2] == -1 ) { + veejay_msg(0, "Cannot learn '%s' (%s) - unknown midi event.", + widget, msg ); + return; + } + + dvims_t *d = (dvims_t*) vj_malloc(sizeof(dvims_t)); + d->extra = extra; + d->msg = (msg == NULL ? NULL : strdup(msg)); + d->widget = (widget == NULL ? NULL : strdup(widget)); + char key[32]; + snprintf(key,sizeof(key), "%03d%03d", v->learn_event[0],v->learn_event[1] ); + + dvims_t *cur = NULL; + if( vevo_property_get( v->vims, key, 0, &cur ) == VEVO_NO_ERROR ) + { + if( cur->widget ) free(cur->widget ); + if( cur->msg ) free(cur->msg); + free(cur); + } + int error = vevo_property_set( v->vims, key, 1, VEVO_ATOM_TYPE_VOIDPTR, &d ); + if( error != VEVO_NO_ERROR ) + return; + vj_msg( VEEJAY_MSG_INFO, + "Midi %x: %x ,%x learned", v->learn_event[0],v->learn_event[1],v->learn_event[2]); +} + +void vj_midi_learning_vims_simple( void *vv, char *widget, int id ) +{ + char message[100]; + if( widget == NULL ) + snprintf(message,sizeof(message), "%03d:;", id ); + else + snprintf(message,sizeof(message), "%03d:", id ); + vj_midi_learning_vims( vv, widget, message, (widget == NULL ? 0 : 1 ) ); +} + +void vj_midi_learning_vims_spin( void *vv, char *widget, int id ) +{ + char message[100]; + if( widget == NULL ) + snprintf(message,sizeof(message), "%03d:;", id ); + else + snprintf(message,sizeof(message), "%03d:", id ); + vj_midi_learning_vims( vv, widget, message, (widget == NULL ? 0 : 2) ); +} + + +void vj_midi_learning_vims_complex( void *vv, char *widget, int id, int first , int extra) +{ + char message[100]; + snprintf( message, sizeof(message), "%03d:%d",id, first ); + + vj_midi_learning_vims( vv, widget, message, extra ); +} + +void vj_midi_learning_vims_msg( void *vv, char *widget, int id, int arg ) +{ + char message[100]; + snprintf(message, sizeof(message), "%03d:%d;",id, arg ); + + vj_midi_learning_vims( vv, widget, message, 0 ); +} + +void vj_midi_learning_vims_msg2(void *vv, char *widget, int id, int arg, int b ) +{ + char message[100]; + snprintf(message,sizeof(message), "%03d:%d %d;", id, arg,b ); + vj_midi_learning_vims( vv, widget, message, 0 ); +} + +void vj_midi_learning_vims_fx( void *vv, int widget, int id, int a, int b, int c, int extra ) +{ + char message[100]; + char wid[100]; + snprintf(message,sizeof(message), "%03d:%d %d %d", id, a,b,c ); + snprintf(wid, sizeof(wid),"slider_p%d", widget ); + vj_midi_learning_vims( vv, wid, message, extra ); +} + +static void queue_vims_event( vmidi_t *v, int *data ) +{ + char key[32]; + + if( v->learn ) + { + veejay_memcpy( v->learn_event, data, sizeof(v->learn_event )); + vj_msg(VEEJAY_MSG_INFO, "MIDI %x:%x,%x -> ?", v->learn_event[0],v->learn_event[1], + v->learn_event[2]); + return; + } + + snprintf(key,sizeof(key), "%03d%03d", data[0],data[1] ); + + dvims_t *d = NULL; + int error = vevo_property_get( v->vims, key, 0, &d); + if( error == VEVO_NO_ERROR ) + { + if( d->extra ) + { //@ argument is dynamic + double min = 0.0; + double max = 0.0; + double tmp = 0.0; + double val = 0.0; + switch(d->extra) + { + case 1: //slider + { + GtkAdjustment *a = gtk_range_get_adjustment( GTK_RANGE( + glade_xml_get_widget_( v->mw, d->widget ) ) ); + min = a->lower; + max = a->upper; + } + break; + case 2: //spinbox + gtk_spin_button_get_range( GTK_SPIN_BUTTON( + glade_xml_get_widget_( v->mw, d->widget)), &min, &max); + + break; + } + + if( data[0] == SND_SEQ_EVENT_PITCHBEND ) + { + tmp = 16384.0 / max; + val = data[2] + 8192; + if( val > 0 ) + val = val / tmp; + } + else if( data[0] == SND_SEQ_EVENT_CONTROLLER || data[0] == SND_SEQ_EVENT_KEYPRESS ) + { + tmp = 127.0 / max; + val = data[2]; + if( val > 0 ) + val = val / tmp; + } else { + vj_msg(VEEJAY_MSG_INFO, "MIDI: what's this ? %x,%x,%x",data[0],data[1],data[2]); + return; + } + + char vims_msg[255]; + snprintf(vims_msg,sizeof(vims_msg), "%s %d;", d->msg, (int) val ); + msg_vims( vims_msg ); + vj_msg(VEEJAY_MSG_INFO, "MIDI %x:%x, %x -> vims %s", data[0], data[1],data[2], vims_msg); + } + else + { + msg_vims( d->msg ); + vj_msg(VEEJAY_MSG_INFO, "MIDI %x: %x,%x -> vims %s", data[0],data[1],data[2], d->msg); + } + } + else + { + vj_msg(VEEJAY_MSG_ERROR, "No vims event for MIDI %x:%x,%x found", + data[0],data[1],data[2]); + } +} + +static void vj_midi_action( vmidi_t *v ) +{ + snd_seq_event_t *ev; + int data[4] = { 0,0,0,0}; + snd_seq_event_input( v->sequencer, &ev ); + + data[0] = -1; + data[1] = -1; + data[2] = -1; + + data[0] = ev->type; + switch( ev->type ) + { + /* controller: channel <0-N>, */ + case SND_SEQ_EVENT_CONTROLLER: + data[1] = ev->data.control.channel; + data[2] = ev->data.control.value; + break; + case SND_SEQ_EVENT_PITCHBEND: + data[1] = ev->data.control.channel; + data[2] = ev->data.control.value; + break; + case SND_SEQ_EVENT_NOTEON: + data[2] = ev->data.control.channel; + data[1] = ev->data.note.note; + break; + case SND_SEQ_EVENT_NOTEOFF: + data[2] = ev->data.control.channel; + data[1] = ev->data.note.note; + break; + case SND_SEQ_EVENT_KEYPRESS: + data[1] = ev->data.control.channel; + data[2] = ev->data.note.velocity; + break; + case SND_SEQ_EVENT_PGMCHANGE: + data[1] = ev->data.control.param; + data[2] = ev->data.control.value; + break; + default: + data[1] = -1; + data[2] = -1; + break; + } + + queue_vims_event( v, data ); + + snd_seq_free_event( ev ); +} + +int vj_midi_handle_events(void *vv) +{ + vmidi_t *v = (vmidi_t*) vv; + if(!v->active) return 0; + if( poll( v->pfd, v->npfd, 5 ) > 0 ) + { + vj_midi_action( v ); + return 1; + } + return 0; +} + + +void *vj_midi_new(void *mw) +{ + vmidi_t *v = (vmidi_t*) vj_calloc(sizeof(vmidi_t)); + int portid = 0; + + if( snd_seq_open( &(v->sequencer), "hw", SND_SEQ_OPEN_DUPLEX, 0 ) < 0 ) + { + veejay_msg(0, "Error opening ALSA sequencer"); + return v; + } + + snd_seq_set_client_name( v->sequencer, "Veejay" ); + + if( (portid = snd_seq_create_simple_port( v->sequencer, "Reloaded", + SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE , + SND_SEQ_PORT_TYPE_APPLICATION )) < 0 ) + { + veejay_msg(0, "Error creating sequencer port"); + + return v; + } + + v->npfd = snd_seq_poll_descriptors_count( v->sequencer, POLLIN ); + if( v->npfd <= 0 ) + { + veejay_msg(0,"Unable to poll in from sequencer"); + return v; + } + v->pfd = (struct pollfd *) vj_calloc( v->npfd * sizeof( struct pollfd )); + v->mw = mw; + v->learn = 0; + v->vims = vpn(VEVO_ANONYMOUS_PORT); + v->active = 1; + snd_seq_poll_descriptors( v->sequencer, v->pfd, v->npfd, POLLIN ); + + veejay_msg(VEEJAY_MSG_INFO, "MIDI listener active! Type 'aconnect -o' to see where to connect to."); + + return (void*) v; +} + + diff --git a/branches/V-1.5.3/veejay-client/src/vmidi.h b/branches/V-1.5.3/veejay-client/src/vmidi.h new file mode 100644 index 00000000..aeb2a2bc --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/vmidi.h @@ -0,0 +1,42 @@ +/* Gveejay Reloaded - graphical interface for VeeJay + * (C) 2002-2007 Niels Elburg + * + * 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. + */ +#ifndef VMIDI_H +#define VMIDI_H + +void *vj_midi_new(void *mw); + +int vj_midi_handle_events(void *vv); + +void vj_midi_play(void *vv ); + +void vj_midi_learn( void *vv ); + +void vj_midi_load(void *vv, const char *filename); + +void vj_midi_save(void *vv, const char *filename); + +void vj_midi_reset( void *vv ); + +void vj_midi_learning_vims( void *vv, char *widget, char *msg, int extra ); +void vj_midi_learning_vims_simple( void *vv, char *widget, int id ); +void vj_midi_learning_vims_complex( void *vv, char *widget, int id, int first , int extra ); +void vj_midi_learning_vims_fx( void *vv, int widget, int id, int a, int b, int c, int extra ); +void vj_midi_learning_vims_msg2(void *vv, char *widget, int id, int arg, int b ); +void vj_midi_learning_vims_msg( void *vv, char *widget, int id, int arg ); +void vj_midi_learning_vims_spin( void *vv, char *widget, int id ); +#endif diff --git a/branches/V-1.5.3/veejay-client/src/yuv4mpeg.c b/branches/V-1.5.3/veejay-client/src/yuv4mpeg.c new file mode 100644 index 00000000..a7775801 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/yuv4mpeg.c @@ -0,0 +1,1414 @@ +/* + * yuv4mpeg.c: Functions for reading and writing "new" YUV4MPEG streams + * + * Copyright (C) 2001 Matthew J. Marjanovic + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include +#include +#include +#define INTERNAL_Y4M_LIBCODE_STUFF_QPX +#include "yuv4mpeg.h" +#include "yuv4mpeg_intern.h" +#include "mjpeg_logging.h" + + +static int _y4mparam_allow_unknown_tags = 1; /* default is forgiveness */ +static int _y4mparam_feature_level = 0; /* default is ol YUV4MPEG2 */ + +static void *(*_y4m_alloc)(size_t bytes) = malloc; +static void (*_y4m_free)(void *ptr) = free; + + +int y4m_allow_unknown_tags(int yn) +{ + int old = _y4mparam_allow_unknown_tags; + if (yn >= 0) + _y4mparam_allow_unknown_tags = (yn) ? 1 : 0; + return old; +} + +int y4m_accept_extensions(int level) +{ + int old = _y4mparam_feature_level; + if (level >= 0) + _y4mparam_feature_level = level; + return old; +} + + +/************************************************************************* + * + * Convenience functions for fd read/write + * + * - guaranteed to transfer entire payload (or fail) + * - returns: + * 0 on complete success + * +(# of remaining bytes) on eof (for y4m_read) + * -(# of rem. bytes) on error (and ERRNO should be set) + * + *************************************************************************/ + +ssize_t y4m_read(int fd, void *buf, size_t len) +{ + ssize_t n; + uint8_t *ptr = (uint8_t *)buf; + + while (len > 0) { + n = read(fd, ptr, len); + if (n <= 0) { + /* return amount left to read */ + if (n == 0) + return len; /* n == 0 --> eof */ + else + return -len; /* n < 0 --> error */ + } + ptr += n; + len -= n; + } + return 0; +} + +ssize_t y4m_write(int fd, const void *buf, size_t len) +{ + ssize_t n; + const uint8_t *ptr = (const uint8_t *)buf; + + while (len > 0) { + n = write(fd, ptr, len); + if (n <= 0) return -len; /* return amount left to write */ + ptr += n; + len -= n; + } + return 0; +} + +/* read len bytes from fd into buf */ +ssize_t y4m_read_cb(y4m_cb_reader_t * fd, void *buf, size_t len) + { + return fd->read(fd->data, buf, len); + } + +/* write len bytes from fd into buf */ +ssize_t y4m_write_cb(y4m_cb_writer_t * fd, const void *buf, size_t len) + { + return fd->write(fd->data, buf, len); + } + +/* Functions to use the callback interface from plain filedescriptors */ + +/* read len bytes from fd into buf */ +ssize_t y4m_read_fd(void * data, void *buf, size_t len) + { + int * f = (int*)data; + return y4m_read(*f, buf, len); + } + +/* write len bytes from fd into buf */ +ssize_t y4m_write_fd(void * data, const void *buf, size_t len) + { + int * f = (int*)data; + return y4m_write(*f, buf, len); + } + +static void set_cb_reader_from_fd(y4m_cb_reader_t * ret, int * fd) + { + ret->read = y4m_read_fd; + ret->data = fd; + } + +static void set_cb_writer_from_fd(y4m_cb_writer_t * ret, int * fd) + { + ret->write = y4m_write_fd; + ret->data = fd; + } + + +/************************************************************************* + * + * "Extra tags" handling + * + *************************************************************************/ + +static char *y4m_new_xtag(void) +{ + return _y4m_alloc(Y4M_MAX_XTAG_SIZE * sizeof(char)); +} + +void y4m_init_xtag_list(y4m_xtag_list_t *xtags) +{ + int i; + xtags->count = 0; + for (i = 0; i < Y4M_MAX_XTAGS; i++) { + xtags->tags[i] = NULL; + } +} + +void y4m_fini_xtag_list(y4m_xtag_list_t *xtags) +{ + int i; + for (i = 0; i < Y4M_MAX_XTAGS; i++) { + if (xtags->tags[i] != NULL) { + _y4m_free(xtags->tags[i]); + xtags->tags[i] = NULL; + } + } + xtags->count = 0; +} + +void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src) +{ + int i; + for (i = 0; i < src->count; i++) { + if (dest->tags[i] == NULL) + dest->tags[i] = y4m_new_xtag(); + strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); + } + dest->count = src->count; +} + +static int y4m_snprint_xtags(char *s, int maxn, const y4m_xtag_list_t *xtags) +{ + int i, room; + + for (i = 0, room = maxn - 1; i < xtags->count; i++) { + int n = snprintf(s, room + 1, " %s", xtags->tags[i]); + if ((n < 0) || (n > room)) return Y4M_ERR_HEADER; + s += n; + room -= n; + } + s[0] = '\n'; /* finish off header with newline */ + s[1] = '\0'; /* ...and end-of-string */ + return Y4M_OK; +} + +int y4m_xtag_count(const y4m_xtag_list_t *xtags) +{ + return xtags->count; +} + +const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n) +{ + if (n >= xtags->count) + return NULL; + else + return xtags->tags[n]; +} + +int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag) +{ + if (xtags->count >= Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS; + if (xtags->tags[xtags->count] == NULL) + xtags->tags[xtags->count] = y4m_new_xtag(); + strncpy(xtags->tags[xtags->count], tag, Y4M_MAX_XTAG_SIZE); + (xtags->count)++; + return Y4M_OK; +} + +int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n) +{ + int i; + char *q; + + if ((n < 0) || (n >= xtags->count)) return Y4M_ERR_RANGE; + q = xtags->tags[n]; + for (i = n; i < (xtags->count - 1); i++) + xtags->tags[i] = xtags->tags[i+1]; + xtags->tags[i] = q; + (xtags->count)--; + return Y4M_OK; +} + +int y4m_xtag_clearlist(y4m_xtag_list_t *xtags) +{ + xtags->count = 0; + return Y4M_OK; +} + +int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src) +{ + int i, j; + + if ((dest->count + src->count) > Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS; + for (i = dest->count, j = 0; + j < src->count; + i++, j++) { + if (dest->tags[i] == NULL) + dest->tags[i] = y4m_new_xtag(); + strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); + } + dest->count += src->count; + return Y4M_OK; +} + + +/************************************************************************* + * + * Creators/destructors for y4m_*_info_t structures + * + *************************************************************************/ + +void y4m_init_stream_info(y4m_stream_info_t *info) +{ + if (info == NULL) return; + /* init substructures */ + y4m_init_xtag_list(&(info->x_tags)); + /* set defaults */ + y4m_clear_stream_info(info); +} + +void y4m_clear_stream_info(y4m_stream_info_t *info) +{ + if (info == NULL) return; + /* clear/initialize info */ + info->width = Y4M_UNKNOWN; + info->height = Y4M_UNKNOWN; + info->interlace = Y4M_UNKNOWN; + info->framerate = y4m_fps_UNKNOWN; + info->sampleaspect = y4m_sar_UNKNOWN; + if (_y4mparam_feature_level < 1) { + info->chroma = Y4M_CHROMA_420JPEG; + } else { + info->chroma = Y4M_UNKNOWN; + } + y4m_xtag_clearlist(&(info->x_tags)); +} + +void y4m_copy_stream_info(y4m_stream_info_t *dest, + const y4m_stream_info_t *src) +{ + if ((dest == NULL) || (src == NULL)) return; + /* copy info */ + dest->width = src->width; + dest->height = src->height; + dest->interlace = src->interlace; + dest->framerate = src->framerate; + dest->sampleaspect = src->sampleaspect; + dest->chroma = src->chroma; + y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags)); +} + +// returns 0 if equal, nonzero if different +static int y4m_compare_stream_info(const y4m_stream_info_t *s1,const y4m_stream_info_t *s2) +{ + int i,j; + + if( s1->width != s2->width || + s1->height != s2->height || + s1->interlace != s2->interlace || + s1->framerate.n != s2->framerate.n || + s1->framerate.d != s2->framerate.d || + s1->sampleaspect.n != s2->sampleaspect.n || + s1->sampleaspect.d != s2->sampleaspect.d || + s1->chroma != s2->chroma || + s1->x_tags.count != s2->x_tags.count ) + return 1; + + // the tags may not be in the same order + for( i=0; ix_tags.count; i++ ) { + for( j=0; jx_tags.count; j++ ) + if( !strncmp(s1->x_tags.tags[i],s2->x_tags.tags[j],Y4M_MAX_XTAG_SIZE) ) + goto next; + return 1; + next:; + } + return 0; +} + +void y4m_fini_stream_info(y4m_stream_info_t *info) +{ + if (info == NULL) return; + y4m_fini_xtag_list(&(info->x_tags)); +} + +void y4m_si_set_width(y4m_stream_info_t *si, int width) +{ + si->width = width; +} + +int y4m_si_get_width(const y4m_stream_info_t *si) +{ return si->width; } + +void y4m_si_set_height(y4m_stream_info_t *si, int height) +{ + si->height = height; +} + +int y4m_si_get_height(const y4m_stream_info_t *si) +{ return si->height; } + +void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace) +{ si->interlace = interlace; } + +int y4m_si_get_interlace(const y4m_stream_info_t *si) +{ return si->interlace; } + +void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate) +{ si->framerate = framerate; } + +y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si) +{ return si->framerate; } + +void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar) +{ si->sampleaspect = sar; } + +y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si) +{ return si->sampleaspect; } + +void y4m_si_set_chroma(y4m_stream_info_t *si, int chroma_mode) +{ si->chroma = chroma_mode; } + +int y4m_si_get_chroma(const y4m_stream_info_t *si) +{ return si->chroma; } + + +int y4m_si_get_plane_count(const y4m_stream_info_t *si) +{ + switch (si->chroma) { + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + case Y4M_CHROMA_444: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + return 3; + case Y4M_CHROMA_MONO: + return 1; + case Y4M_CHROMA_444ALPHA: + return 4; + default: + return Y4M_UNKNOWN; + } +} + +int y4m_si_get_plane_width(const y4m_stream_info_t *si, int plane) +{ + switch (plane) { + case 0: + return (si->width); + case 1: + case 2: + switch (si->chroma) { + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + return (si->width) / 2; + case Y4M_CHROMA_444: + case Y4M_CHROMA_444ALPHA: + return (si->width); + case Y4M_CHROMA_422: + return (si->width) / 2; + case Y4M_CHROMA_411: + return (si->width) / 4; + default: + return Y4M_UNKNOWN; + } + case 3: + switch (si->chroma) { + case Y4M_CHROMA_444ALPHA: + return (si->width); + default: + return Y4M_UNKNOWN; + } + default: + return Y4M_UNKNOWN; + } +} + +int y4m_si_get_plane_height(const y4m_stream_info_t *si, int plane) +{ + switch (plane) { + case 0: + return (si->height); + case 1: + case 2: + switch (si->chroma) { + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + return (si->height) / 2; + case Y4M_CHROMA_444: + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + return (si->height); + default: + return Y4M_UNKNOWN; + } + case 3: + switch (si->chroma) { + case Y4M_CHROMA_444ALPHA: + return (si->height); + default: + return Y4M_UNKNOWN; + } + default: + return Y4M_UNKNOWN; + } +} + +int y4m_si_get_plane_length(const y4m_stream_info_t *si, int plane) +{ + int w = y4m_si_get_plane_width(si, plane); + int h = y4m_si_get_plane_height(si, plane); + if ((w != Y4M_UNKNOWN) && (h != Y4M_UNKNOWN)) + return (w * h); + else + return Y4M_UNKNOWN; +} + +int y4m_si_get_framelength(const y4m_stream_info_t *si) +{ + int total = 0; + int planes = y4m_si_get_plane_count(si); + int p; + for (p = 0; p < planes; p++) { + int plen = y4m_si_get_plane_length(si, p); + if (plen == Y4M_UNKNOWN) return Y4M_UNKNOWN; + total += plen; + } + return total; +} + +y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si) +{ return &(si->x_tags); } + + +void y4m_init_frame_info(y4m_frame_info_t *info) +{ + if (info == NULL) return; + /* init substructures */ + y4m_init_xtag_list(&(info->x_tags)); + /* set defaults */ + y4m_clear_frame_info(info); +} + +void y4m_clear_frame_info(y4m_frame_info_t *info) +{ + if (info == NULL) return; + /* clear/initialize info */ + info->spatial = Y4M_UNKNOWN; + info->temporal = Y4M_UNKNOWN; + info->presentation = Y4M_UNKNOWN; + y4m_xtag_clearlist(&(info->x_tags)); +} + +void y4m_copy_frame_info(y4m_frame_info_t *dest, const y4m_frame_info_t *src) +{ + if ((dest == NULL) || (src == NULL)) return; + /* copy info */ + dest->spatial = src->spatial; + dest->temporal = src->temporal; + dest->presentation = src->presentation; + y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags)); +} + +void y4m_fini_frame_info(y4m_frame_info_t *info) +{ + if (info == NULL) return; + y4m_fini_xtag_list(&(info->x_tags)); +} + +void y4m_fi_set_presentation(y4m_frame_info_t *fi, int pres) +{ fi->presentation = pres; } + +int y4m_fi_get_presentation(const y4m_frame_info_t *fi) +{ return fi->presentation; } + +void y4m_fi_set_temporal(y4m_frame_info_t *fi, int sampling) +{ fi->temporal = sampling; } + +int y4m_fi_get_temporal(const y4m_frame_info_t *fi) +{ return fi->temporal; } + +void y4m_fi_set_spatial(y4m_frame_info_t *fi, int sampling) +{ fi->spatial = sampling; } + +int y4m_fi_get_spatial(const y4m_frame_info_t *fi) +{ return fi->spatial; } + +y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi) +{ return &(fi->x_tags); } + + +/************************************************************************* + * + * Tag parsing + * + *************************************************************************/ + +int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i) +{ + char *token, *value; + char tag; + int err; + + /* parse fields */ + for (token = strtok(s, Y4M_DELIM); + token != NULL; + token = strtok(NULL, Y4M_DELIM)) { + if (token[0] == '\0') continue; /* skip empty strings */ + tag = token[0]; + value = token + 1; + switch (tag) { + case 'W': /* width */ + i->width = atoi(value); + if (i->width <= 0) return Y4M_ERR_RANGE; + break; + case 'H': /* height */ + i->height = atoi(value); + if (i->height <= 0) return Y4M_ERR_RANGE; + break; + case 'F': /* frame rate (fps) */ + if ((err = y4m_parse_ratio(&(i->framerate), value)) != Y4M_OK) + return err; + if (i->framerate.n < 0) return Y4M_ERR_RANGE; + break; + case 'I': /* interlacing */ + switch (value[0]) { + case 'p': i->interlace = Y4M_ILACE_NONE; break; + case 't': i->interlace = Y4M_ILACE_TOP_FIRST; break; + case 'b': i->interlace = Y4M_ILACE_BOTTOM_FIRST; break; + case 'm': i->interlace = Y4M_ILACE_MIXED; break; + case '?': + default: + i->interlace = Y4M_UNKNOWN; break; + } + break; + case 'A': /* sample (pixel) aspect ratio */ + if ((err = y4m_parse_ratio(&(i->sampleaspect), value)) != Y4M_OK) + return err; + if (i->sampleaspect.n < 0) return Y4M_ERR_RANGE; + break; + case 'C': + i->chroma = y4m_chroma_parse_keyword(value); + if (i->chroma == Y4M_UNKNOWN) + return Y4M_ERR_HEADER; + break; + case 'X': /* 'X' meta-tag */ + if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; + break; + default: + /* possible error on unknown options */ + if (_y4mparam_allow_unknown_tags) { + /* unknown tags ok: store in xtag list and warn... */ + if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; + mjpeg_warn("Unknown stream tag encountered: '%s'", token); + } else { + /* unknown tags are *not* ok */ + return Y4M_ERR_BADTAG; + } + break; + } + } + + /* Without 'C' tag or any other chroma spec, default to 420jpeg */ + if (i->chroma == Y4M_UNKNOWN) + i->chroma = Y4M_CHROMA_420JPEG; + + /* Error checking... */ + /* - Width and Height are required. */ + if ((i->width == Y4M_UNKNOWN) || (i->height == Y4M_UNKNOWN)) + return Y4M_ERR_HEADER; + /* - Non-420 chroma and mixed interlace require level >= 1 */ + if (_y4mparam_feature_level < 1) { + if ((i->chroma != Y4M_CHROMA_420JPEG) && + (i->chroma != Y4M_CHROMA_420MPEG2) && + (i->chroma != Y4M_CHROMA_420PALDV)) + return Y4M_ERR_FEATURE; + if (i->interlace == Y4M_ILACE_MIXED) + return Y4M_ERR_FEATURE; + } + + /* ta da! done. */ + return Y4M_OK; +} + + + +static int y4m_parse_frame_tags(char *s, const y4m_stream_info_t *si, + y4m_frame_info_t *fi) +{ + char *token, *value; + char tag; + int err; + + /* parse fields */ + for (token = strtok(s, Y4M_DELIM); + token != NULL; + token = strtok(NULL, Y4M_DELIM)) { + if (token[0] == '\0') continue; /* skip empty strings */ + tag = token[0]; + value = token + 1; + switch (tag) { + case 'I': + /* frame 'I' tag requires feature level >= 1 */ + if (_y4mparam_feature_level < 1) return Y4M_ERR_FEATURE; + if (si->interlace != Y4M_ILACE_MIXED) return Y4M_ERR_BADTAG; + switch (value[0]) { + case 't': fi->presentation = Y4M_PRESENT_TOP_FIRST; break; + case 'T': fi->presentation = Y4M_PRESENT_TOP_FIRST_RPT; break; + case 'b': fi->presentation = Y4M_PRESENT_BOTTOM_FIRST; break; + case 'B': fi->presentation = Y4M_PRESENT_BOTTOM_FIRST_RPT; break; + case '1': fi->presentation = Y4M_PRESENT_PROG_SINGLE; break; + case '2': fi->presentation = Y4M_PRESENT_PROG_DOUBLE; break; + case '3': fi->presentation = Y4M_PRESENT_PROG_TRIPLE; break; + default: + return Y4M_ERR_BADTAG; + } + switch (value[1]) { + case 'p': fi->temporal = Y4M_SAMPLING_PROGRESSIVE; break; + case 'i': fi->temporal = Y4M_SAMPLING_INTERLACED; break; + default: + return Y4M_ERR_BADTAG; + } + switch (value[2]) { + case 'p': fi->spatial = Y4M_SAMPLING_PROGRESSIVE; break; + case 'i': fi->spatial = Y4M_SAMPLING_INTERLACED; break; + case '?': fi->spatial = Y4M_UNKNOWN; break; + default: + return Y4M_ERR_BADTAG; + } + break; + case 'X': /* 'X' meta-tag */ + if ((err = y4m_xtag_add(&(fi->x_tags), token)) != Y4M_OK) return err; + break; + default: + /* possible error on unknown options */ + if (_y4mparam_allow_unknown_tags) { + /* unknown tags ok: store in xtag list and warn... */ + if ((err = y4m_xtag_add(&(fi->x_tags), token)) != Y4M_OK) return err; + mjpeg_warn("Unknown frame tag encountered: '%s'", token); + } else { + /* unknown tags are *not* ok */ + return Y4M_ERR_BADTAG; + } + break; + } + } + /* error-checking and/or non-mixed defaults */ + switch (si->interlace) { + case Y4M_ILACE_MIXED: + /* T and P are required if stream "Im" */ + if ((fi->presentation == Y4M_UNKNOWN) || (fi->temporal == Y4M_UNKNOWN)) + return Y4M_ERR_HEADER; + /* and S is required if stream is also 4:2:0 */ + if ( ((si->chroma == Y4M_CHROMA_420JPEG) || + (si->chroma == Y4M_CHROMA_420MPEG2) || + (si->chroma == Y4M_CHROMA_420PALDV)) && + (fi->spatial == Y4M_UNKNOWN) ) + return Y4M_ERR_HEADER; + break; + case Y4M_ILACE_NONE: + /* stream "Ip" --> equivalent to frame "I1pp" */ + fi->spatial = Y4M_SAMPLING_PROGRESSIVE; + fi->temporal = Y4M_SAMPLING_PROGRESSIVE; + fi->presentation = Y4M_PRESENT_PROG_SINGLE; + break; + case Y4M_ILACE_TOP_FIRST: + /* stream "It" --> equivalent to frame "Itii" */ + fi->spatial = Y4M_SAMPLING_INTERLACED; + fi->temporal = Y4M_SAMPLING_INTERLACED; + fi->presentation = Y4M_PRESENT_TOP_FIRST; + break; + case Y4M_ILACE_BOTTOM_FIRST: + /* stream "Ib" --> equivalent to frame "Ibii" */ + fi->spatial = Y4M_SAMPLING_INTERLACED; + fi->temporal = Y4M_SAMPLING_INTERLACED; + fi->presentation = Y4M_PRESENT_BOTTOM_FIRST; + break; + default: + /* stream unknown: then, whatever */ + break; + } + /* ta da! done. */ + return Y4M_OK; +} + + + + + +/************************************************************************* + * + * Read/Write stream header + * + *************************************************************************/ + + +static int y4m_read_stream_header_line_cb(y4m_cb_reader_t * fd, y4m_stream_info_t *i,char *line,int n) +{ + int err; + + /* start with a clean slate */ + y4m_clear_stream_info(i); + /* read the header line */ + for (; n < Y4M_LINE_MAX; n++) { + if (y4m_read_cb(fd, line+n, 1)) + return Y4M_ERR_SYSTEM; + if (line[n] == '\n') { + line[n] = '\0'; /* Replace linefeed by end of string */ + break; + } + } + /* look for keyword in header */ + if (strncmp(line, Y4M_MAGIC, strlen(Y4M_MAGIC))) + return Y4M_ERR_MAGIC; + if (n >= Y4M_LINE_MAX) + return Y4M_ERR_HEADER; + if ((err = y4m_parse_stream_tags(line + strlen(Y4M_MAGIC), i)) != Y4M_OK) + return err; + + return Y4M_OK; +} + +static int y4m_reread_stream_header_line_cb(y4m_cb_reader_t *fd,const y4m_stream_info_t *si,char *line,int n) +{ + y4m_stream_info_t i; + int err=y4m_read_stream_header_line_cb(fd,&i,line,n); + if( err==Y4M_OK && y4m_compare_stream_info(si,&i) ) + err=Y4M_ERR_HEADER; + y4m_fini_stream_info(&i); + return err; +} + +int y4m_read_stream_header_cb(y4m_cb_reader_t *fd, y4m_stream_info_t *i) +{ + char line[Y4M_LINE_MAX]; + + return y4m_read_stream_header_line_cb(fd,i,line,0); +} + +int y4m_read_stream_header(int fd, y4m_stream_info_t *i) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_stream_header_cb(&r, i); +} + +int y4m_write_stream_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *i) +{ + char s[Y4M_LINE_MAX+1]; + int n; + int err; + y4m_ratio_t rate = i->framerate; + y4m_ratio_t aspect = i->sampleaspect; + const char *chroma_keyword = y4m_chroma_keyword(i->chroma); + + if ((i->chroma == Y4M_UNKNOWN) || (chroma_keyword == NULL)) + return Y4M_ERR_HEADER; + if (_y4mparam_feature_level < 1) { + if ((i->chroma != Y4M_CHROMA_420JPEG) && + (i->chroma != Y4M_CHROMA_420MPEG2) && + (i->chroma != Y4M_CHROMA_420PALDV)) + return Y4M_ERR_FEATURE; + if (i->interlace == Y4M_ILACE_MIXED) + return Y4M_ERR_FEATURE; + } + y4m_ratio_reduce(&rate); + y4m_ratio_reduce(&aspect); + n = snprintf(s, sizeof(s), "%s W%d H%d F%d:%d I%s A%d:%d C%s", + Y4M_MAGIC, + i->width, + i->height, + rate.n, rate.d, + (i->interlace == Y4M_ILACE_NONE) ? "p" : + (i->interlace == Y4M_ILACE_TOP_FIRST) ? "t" : + (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "b" : + (i->interlace == Y4M_ILACE_MIXED) ? "m" : "?", + aspect.n, aspect.d, + chroma_keyword + ); + if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; + if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(i->x_tags))) + != Y4M_OK) + return err; + /* non-zero on error */ + return (y4m_write_cb(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK); +} + +int y4m_write_stream_header(int fd, const y4m_stream_info_t *i) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_stream_header_cb(&w, i); +} + + + + +/************************************************************************* + * + * Read/Write frame header + * + *************************************************************************/ + +int y4m_read_frame_header_cb(y4m_cb_reader_t * fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi) +{ + char line[Y4M_LINE_MAX]; + char *p; + int n; + ssize_t remain; + + again: + /* start with a clean slate */ + y4m_clear_frame_info(fi); + /* This is more clever than read_stream_header... + Try to read "FRAME\n" all at once, and don't try to parse + if nothing else is there... + */ + remain = y4m_read_cb(fd, line, sizeof(Y4M_FRAME_MAGIC)-1+1); /* -'\0', +'\n' */ + if (remain < 0) return Y4M_ERR_SYSTEM; + if (remain > 0) { + /* A clean EOF should end exactly at a frame-boundary */ + if (remain == sizeof(Y4M_FRAME_MAGIC)) + return Y4M_ERR_EOF; + else + return Y4M_ERR_BADEOF; + } + if (strncmp(line, Y4M_FRAME_MAGIC, sizeof(Y4M_FRAME_MAGIC)-1)) { + int err=y4m_reread_stream_header_line_cb(fd,si,line,sizeof(Y4M_FRAME_MAGIC)-1+1); + if( err!=Y4M_OK ) + return err; + goto again; + } + if (line[sizeof(Y4M_FRAME_MAGIC)-1] == '\n') + return Y4M_OK; /* done -- no tags: that was the end-of-line. */ + + if (line[sizeof(Y4M_FRAME_MAGIC)-1] != Y4M_DELIM[0]) { + return Y4M_ERR_MAGIC; /* wasn't a space -- what was it? */ + } + + /* proceed to get the tags... (overwrite the magic) */ + for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) { + if (y4m_read_cb(fd, p, 1)) + return Y4M_ERR_SYSTEM; + if (*p == '\n') { + *p = '\0'; /* Replace linefeed by end of string */ + break; + } + } + if (n >= Y4M_LINE_MAX) return Y4M_ERR_HEADER; + /* non-zero on error */ + return y4m_parse_frame_tags(line, si, fi); +} + +int y4m_read_frame_header(int fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi) + { + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_frame_header_cb(&r, si, fi); + } + + +int y4m_write_frame_header_cb(y4m_cb_writer_t * fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi) +{ + char s[Y4M_LINE_MAX+1]; + int n, err; + + if (si->interlace == Y4M_ILACE_MIXED) { + if (_y4mparam_feature_level < 1) return Y4M_ERR_FEATURE; + n = snprintf(s, sizeof(s), "%s I%c%c%c", Y4M_FRAME_MAGIC, + (fi->presentation == Y4M_PRESENT_TOP_FIRST) ? 't' : + (fi->presentation == Y4M_PRESENT_TOP_FIRST_RPT) ? 'T' : + (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST) ? 'b' : + (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST_RPT) ? 'B' : + (fi->presentation == Y4M_PRESENT_PROG_SINGLE) ? '1' : + (fi->presentation == Y4M_PRESENT_PROG_DOUBLE) ? '2' : + (fi->presentation == Y4M_PRESENT_PROG_TRIPLE) ? '3' : + '?', + (fi->temporal == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : + (fi->temporal == Y4M_SAMPLING_INTERLACED) ? 'i' : + '?', + (fi->spatial == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : + (fi->spatial == Y4M_SAMPLING_INTERLACED) ? 'i' : + '?' + ); + } else { + n = snprintf(s, sizeof(s), "%s", Y4M_FRAME_MAGIC); + } + + if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; + if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(fi->x_tags))) + != Y4M_OK) + return err; + /* non-zero on error */ + return (y4m_write_cb(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK); +} + +int y4m_write_frame_header(int fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_frame_header_cb(&w, si, fi); +} + +/************************************************************************* + * + * Read/Write entire frame + * + *************************************************************************/ + +int y4m_read_frame_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + int planes = y4m_si_get_plane_count(si); + int p; + + /* Read each plane */ + for (p = 0; p < planes; p++) { + int w = y4m_si_get_plane_width(si, p); + int h = y4m_si_get_plane_height(si, p); + if (y4m_read_cb(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; + } + return Y4M_OK; +} + +int y4m_read_frame_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_frame_data_cb(&r, si, fi, frame); +} + +int y4m_read_frame_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + int err; + + /* Read frame header */ + if ((err = y4m_read_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Read date */ + return y4m_read_frame_data_cb(fd, si, fi, frame); +} + +int y4m_read_frame(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_frame_cb(&r, si, fi, frame); +} + + + +int y4m_write_frame_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *frame) +{ + int planes = y4m_si_get_plane_count(si); + int err, p; + + /* Write frame header */ + if ((err = y4m_write_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Write each plane */ + for (p = 0; p < planes; p++) { + int w = y4m_si_get_plane_width(si, p); + int h = y4m_si_get_plane_height(si, p); + if (y4m_write_cb(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; + } + return Y4M_OK; +} + +int y4m_write_frame(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *frame) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_frame_cb(&w, si, fi, frame); +} + +/************************************************************************* + * + * Read/Write entire frame, (de)interleaved (to)from two separate fields + * + *************************************************************************/ + + +int y4m_read_fields_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + int p; + int planes = y4m_si_get_plane_count(si); + const int maxrbuf=32*1024; + uint8_t *rbuf=_y4m_alloc(maxrbuf); + int rbufpos=0,rbuflen=0; + + /* Read each plane */ + for (p = 0; p < planes; p++) { + uint8_t *dsttop = upper_field[p]; + uint8_t *dstbot = lower_field[p]; + int height = y4m_si_get_plane_height(si, p); + int width = y4m_si_get_plane_width(si, p); + int y; + /* alternately read one line into each field */ + for (y = 0; y < height; y += 2) { + if( width*2 >= maxrbuf ) { + if (y4m_read_cb(fd, dsttop, width)) goto y4merr; + if (y4m_read_cb(fd, dstbot, width)) goto y4merr; + } else { + if( rbufpos==rbuflen ) { + rbuflen=(height-y)*width; + if( rbuflen>maxrbuf ) + rbuflen=maxrbuf-maxrbuf%(2*width); + if( y4m_read_cb(fd,rbuf,rbuflen) ) + goto y4merr; + rbufpos=0; + } + + memcpy(dsttop,rbuf+rbufpos,width); rbufpos+=width; + memcpy(dstbot,rbuf+rbufpos,width); rbufpos+=width; + } + dsttop+=width; + dstbot+=width; + } + } + _y4m_free(rbuf); + return Y4M_OK; + + y4merr: + _y4m_free(rbuf); + return Y4M_ERR_SYSTEM; +} + +int y4m_read_fields_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_fields_data_cb(&r, si, fi, upper_field, lower_field); +} + + +int y4m_read_fields_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + int err; + /* Read frame header */ + if ((err = y4m_read_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Read data */ + return y4m_read_fields_data_cb(fd, si, fi, upper_field, lower_field); +} + +int y4m_read_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_fields_cb(&r, si, fi, upper_field, lower_field); +} + +int y4m_write_fields_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + int p, err; + int planes = y4m_si_get_plane_count(si); + int numwbuf=0; + const int maxwbuf=32*1024; + uint8_t *wbuf; + + /* Write frame header */ + if ((err = y4m_write_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Write each plane */ + wbuf=_y4m_alloc(maxwbuf); + for (p = 0; p < planes; p++) { + uint8_t *srctop = upper_field[p]; + uint8_t *srcbot = lower_field[p]; + int height = y4m_si_get_plane_height(si, p); + int width = y4m_si_get_plane_width(si, p); + int y; + /* alternately write one line from each field */ + for (y = 0; y < height; y += 2) { + if( width*2 >= maxwbuf ) { + if (y4m_write_cb(fd, srctop, width)) goto y4merr; + if (y4m_write_cb(fd, srcbot, width)) goto y4merr; + } else { + if (numwbuf + 2 * width > maxwbuf) { + if(y4m_write_cb(fd, wbuf, numwbuf)) goto y4merr; + numwbuf=0; + } + + memcpy(wbuf+numwbuf,srctop,width); numwbuf += width; + memcpy(wbuf+numwbuf,srcbot,width); numwbuf += width; + } + srctop += width; + srcbot += width; + } + } + if( numwbuf ) + if( y4m_write_cb(fd, wbuf, numwbuf) ) + goto y4merr; + _y4m_free(wbuf); + return Y4M_OK; + + y4merr: + _y4m_free(wbuf); + return Y4M_ERR_SYSTEM; +} + +int y4m_write_fields(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_fields_cb(&w, si, fi, upper_field, lower_field); +} + +/************************************************************************* + * + * Handy logging of stream info + * + *************************************************************************/ + +void y4m_log_stream_info(log_level_t level, const char *prefix, + const y4m_stream_info_t *i) +{ + char s[256]; + + snprintf(s, sizeof(s), " frame size: "); + if (i->width == Y4M_UNKNOWN) + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?)x"); + else + snprintf(s+strlen(s), sizeof(s)-strlen(s), "%dx", i->width); + if (i->height == Y4M_UNKNOWN) + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?) pixels "); + else + snprintf(s+strlen(s), sizeof(s)-strlen(s), "%d pixels ", i->height); + { + int framelength = y4m_si_get_framelength(i); + if (framelength == Y4M_UNKNOWN) + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(? bytes)"); + else + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(%d bytes)", framelength); + mjpeg_log(level, "%s%s", prefix, s); + } + { + const char *desc = y4m_chroma_description(i->chroma); + if (desc == NULL) desc = "unknown!"; + mjpeg_log(level, "%s chroma: %s", prefix, desc); + } + if ((i->framerate.n == 0) && (i->framerate.d == 0)) + mjpeg_log(level, "%s frame rate: ??? fps", prefix); + else + mjpeg_log(level, "%s frame rate: %d/%d fps (~%f)", prefix, + i->framerate.n, i->framerate.d, + (double) i->framerate.n / (double) i->framerate.d); + mjpeg_log(level, "%s interlace: %s", prefix, + (i->interlace == Y4M_ILACE_NONE) ? "none/progressive" : + (i->interlace == Y4M_ILACE_TOP_FIRST) ? "top-field-first" : + (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "bottom-field-first" : + (i->interlace == Y4M_ILACE_MIXED) ? "mixed-mode" : + "anyone's guess"); + if ((i->sampleaspect.n == 0) && (i->sampleaspect.d == 0)) + mjpeg_log(level, "%ssample aspect ratio: ?:?", prefix); + else + mjpeg_log(level, "%ssample aspect ratio: %d:%d", prefix, + i->sampleaspect.n, i->sampleaspect.d); +} + + +/************************************************************************* + * + * Convert error code to string + * + *************************************************************************/ + +const char *y4m_strerr(int err) +{ + switch (err) { + case Y4M_OK: return "no error"; + case Y4M_ERR_RANGE: return "parameter out of range"; + case Y4M_ERR_SYSTEM: return "system error (failed read/write)"; + case Y4M_ERR_HEADER: return "bad stream or frame header"; + case Y4M_ERR_BADTAG: return "unknown header tag"; + case Y4M_ERR_MAGIC: return "bad header magic"; + case Y4M_ERR_XXTAGS: return "too many xtags"; + case Y4M_ERR_EOF: return "end-of-file"; + case Y4M_ERR_BADEOF: return "stream ended unexpectedly (EOF)"; + case Y4M_ERR_FEATURE: return "stream requires unsupported features"; + default: + return "unknown error code"; + } +} + + +/************************************************************************* + * + * Chroma subsampling stuff + * + *************************************************************************/ + +y4m_ratio_t y4m_chroma_ss_x_ratio(int chroma_mode) +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + r.n = 1; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + case Y4M_CHROMA_422: + r.n = 1; r.d = 2; break; + case Y4M_CHROMA_411: + r.n = 1; r.d = 4; break; + default: + r.n = 0; r.d = 0; + } + return r; +} + +y4m_ratio_t y4m_chroma_ss_y_ratio(int chroma_mode) +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + r.n = 1; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + r.n = 1; r.d = 2; break; + default: + r.n = 0; r.d = 0; + } + return r; +} + + +#if 0 /* unfinished work here */ +y4m_ratio_t y4m_chroma_ss_x_offset(int chroma_mode, int field, int plane) +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + r.n = 0; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + r.n = 1; r.d = 2; break; + default: + r.n = 0; r.d = 0; + } + return r; +} + +y4m_ratio_t y4m_chroma_ss_y_offset(int chroma_mode, int field, int plane); +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + r.n = 0; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + r.n = 1; r.d = 2; break; + default: + r.n = 0; r.d = 0; + } + return r; +} +#endif + +int y4m_chroma_parse_keyword(const char *s) +{ + if (!strcasecmp("420jpeg", s)) + return Y4M_CHROMA_420JPEG; + else if (!strcasecmp("420mpeg2", s)) + return Y4M_CHROMA_420MPEG2; + else if (!strcasecmp("420paldv", s)) + return Y4M_CHROMA_420PALDV; + else if (!strcasecmp("444", s)) + return Y4M_CHROMA_444; + else if (!strcasecmp("422", s)) + return Y4M_CHROMA_422; + else if (!strcasecmp("411", s)) + return Y4M_CHROMA_411; + else if (!strcasecmp("mono", s)) + return Y4M_CHROMA_MONO; + else if (!strcasecmp("444alpha", s)) + return Y4M_CHROMA_444ALPHA; + else + return Y4M_UNKNOWN; +} + +const char *y4m_chroma_keyword(int chroma_mode) +{ + switch (chroma_mode) { + case Y4M_CHROMA_420JPEG: return "420jpeg"; + case Y4M_CHROMA_420MPEG2: return "420mpeg2"; + case Y4M_CHROMA_420PALDV: return "420paldv"; + case Y4M_CHROMA_444: return "444"; + case Y4M_CHROMA_422: return "422"; + case Y4M_CHROMA_411: return "411"; + case Y4M_CHROMA_MONO: return "mono"; + case Y4M_CHROMA_444ALPHA: return "444alpha"; + default: + return NULL; + } +} + +const char *y4m_chroma_description(int chroma_mode) +{ + switch (chroma_mode) { + case Y4M_CHROMA_420JPEG: return "4:2:0 JPEG/MPEG-1 (interstitial)"; + case Y4M_CHROMA_420MPEG2: return "4:2:0 MPEG-2 (horiz. cositing)"; + case Y4M_CHROMA_420PALDV: return "4:2:0 PAL-DV (altern. siting)"; + case Y4M_CHROMA_444: return "4:4:4 (no subsampling)"; + case Y4M_CHROMA_422: return "4:2:2 (horiz. cositing)"; + case Y4M_CHROMA_411: return "4:1:1 (horiz. cositing)"; + case Y4M_CHROMA_MONO: return "luma plane only"; + case Y4M_CHROMA_444ALPHA: return "4:4:4 with alpha channel"; + default: + return NULL; + } +} diff --git a/branches/V-1.5.3/veejay-client/src/yuv4mpeg.h b/branches/V-1.5.3/veejay-client/src/yuv4mpeg.h new file mode 100644 index 00000000..79a41f64 --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/yuv4mpeg.h @@ -0,0 +1,757 @@ +/* + * yuv4mpeg.h: Functions for reading and writing "new" YUV4MPEG2 streams. + * + * Stream format is described at the end of this file. + * + * + * Copyright (C) 2004 Matthew J. Marjanovic + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __YUV4MPEG_H__ +#define __YUV4MPEG_H__ + +#include +#include +#ifndef _WIN32 +#include +#endif +#include + + +/************************************************************************ + * error codes returned by y4m_* functions + ************************************************************************/ +#define Y4M_OK 0 +#define Y4M_ERR_RANGE 1 /* argument or tag value out of range */ +#define Y4M_ERR_SYSTEM 2 /* failed system call, check errno */ +#define Y4M_ERR_HEADER 3 /* illegal/malformed header */ +#define Y4M_ERR_BADTAG 4 /* illegal tag character */ +#define Y4M_ERR_MAGIC 5 /* bad header magic */ +#define Y4M_ERR_EOF 6 /* end-of-file (clean) */ +#define Y4M_ERR_XXTAGS 7 /* too many xtags */ +#define Y4M_ERR_BADEOF 8 /* unexpected end-of-file */ +#define Y4M_ERR_FEATURE 9 /* stream requires features beyond allowed level */ + + +/* generic 'unknown' value for integer parameters (e.g. interlace, height) */ +#define Y4M_UNKNOWN -1 + +/************************************************************************ + * values for the "interlace" parameter [y4m_*_interlace()] + ************************************************************************/ +#define Y4M_ILACE_NONE 0 /* non-interlaced, progressive frame */ +#define Y4M_ILACE_TOP_FIRST 1 /* interlaced, top-field first */ +#define Y4M_ILACE_BOTTOM_FIRST 2 /* interlaced, bottom-field first */ +#define Y4M_ILACE_MIXED 3 /* mixed, "refer to frame header" */ + +/************************************************************************ + * values for the "chroma" parameter [y4m_*_chroma()] + ************************************************************************/ +#define Y4M_CHROMA_420JPEG 0 /* 4:2:0, H/V centered, for JPEG/MPEG-1 */ +#define Y4M_CHROMA_420MPEG2 1 /* 4:2:0, H cosited, for MPEG-2 */ +#define Y4M_CHROMA_420PALDV 2 /* 4:2:0, alternating Cb/Cr, for PAL-DV */ +#define Y4M_CHROMA_444 3 /* 4:4:4, no subsampling, phew. */ +#define Y4M_CHROMA_422 4 /* 4:2:2, H cosited */ +#define Y4M_CHROMA_411 5 /* 4:1:1, H cosited */ +#define Y4M_CHROMA_MONO 6 /* luma plane only */ +#define Y4M_CHROMA_444ALPHA 7 /* 4:4:4 with an alpha channel */ + +/************************************************************************ + * values for sampling parameters [y4m_*_spatial(), y4m_*_temporal()] + ************************************************************************/ +#define Y4M_SAMPLING_PROGRESSIVE 0 +#define Y4M_SAMPLING_INTERLACED 1 + +/************************************************************************ + * values for "presentation" parameter [y4m_*_presentation()] + ************************************************************************/ +#define Y4M_PRESENT_TOP_FIRST 0 /* top-field-first */ +#define Y4M_PRESENT_TOP_FIRST_RPT 1 /* top-first, repeat top */ +#define Y4M_PRESENT_BOTTOM_FIRST 2 /* bottom-field-first */ +#define Y4M_PRESENT_BOTTOM_FIRST_RPT 3 /* bottom-first, repeat bottom */ +#define Y4M_PRESENT_PROG_SINGLE 4 /* single progressive frame */ +#define Y4M_PRESENT_PROG_DOUBLE 5 /* progressive frame, repeat once */ +#define Y4M_PRESENT_PROG_TRIPLE 6 /* progressive frame, repeat twice */ + +#define Y4M_MAX_NUM_PLANES 4 + +/************************************************************************ + * 'ratio' datatype, for rational numbers + * (see 'ratio' functions down below) + ************************************************************************/ +typedef struct _y4m_ratio { + int n; /* numerator */ + int d; /* denominator */ +} y4m_ratio_t; + + +/************************************************************************ + * useful standard framerates (as ratios) + ************************************************************************/ +extern const y4m_ratio_t y4m_fps_UNKNOWN; +extern const y4m_ratio_t y4m_fps_NTSC_FILM; /* 24000/1001 film (in NTSC) */ +extern const y4m_ratio_t y4m_fps_FILM; /* 24fps film */ +extern const y4m_ratio_t y4m_fps_PAL; /* 25fps PAL */ +extern const y4m_ratio_t y4m_fps_NTSC; /* 30000/1001 NTSC */ +extern const y4m_ratio_t y4m_fps_30; /* 30fps */ +extern const y4m_ratio_t y4m_fps_PAL_FIELD; /* 50fps PAL field rate */ +extern const y4m_ratio_t y4m_fps_NTSC_FIELD; /* 60000/1001 NTSC field rate */ +extern const y4m_ratio_t y4m_fps_60; /* 60fps */ + +/************************************************************************ + * useful standard sample (pixel) aspect ratios (W:H) + ************************************************************************/ +extern const y4m_ratio_t y4m_sar_UNKNOWN; +extern const y4m_ratio_t y4m_sar_SQUARE; /* square pixels */ +extern const y4m_ratio_t y4m_sar_NTSC_CCIR601; /* 525-line (NTSC) Rec.601 */ +extern const y4m_ratio_t y4m_sar_NTSC_16_9; /* 16:9 NTSC/Rec.601 */ +extern const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3; /* NTSC SVCD 4:3 */ +extern const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9;/* NTSC SVCD 16:9 */ +extern const y4m_ratio_t y4m_sar_PAL_CCIR601; /* 625-line (PAL) Rec.601 */ +extern const y4m_ratio_t y4m_sar_PAL_16_9; /* 16:9 PAL/Rec.601 */ +extern const y4m_ratio_t y4m_sar_PAL_SVCD_4_3; /* PAL SVCD 4:3 */ +extern const y4m_ratio_t y4m_sar_PAL_SVCD_16_9; /* PAL SVCD 16:9 */ +extern const y4m_ratio_t y4m_sar_SQR_ANA16_9; /* anamorphic 16:9 sampled */ + /* from 4:3 with square pixels */ + +/************************************************************************ + * useful standard display aspect ratios (W:H) + ************************************************************************/ +extern const y4m_ratio_t y4m_dar_UNKNOWN; +extern const y4m_ratio_t y4m_dar_4_3; /* standard TV */ +extern const y4m_ratio_t y4m_dar_16_9; /* widescreen TV */ +extern const y4m_ratio_t y4m_dar_221_100; /* word-to-your-mother TV */ + + +#define Y4M_MAX_XTAGS 32 /* maximum number of xtags in list */ +#define Y4M_MAX_XTAG_SIZE 32 /* max length of an xtag (including 'X') */ + +typedef struct _y4m_xtag_list y4m_xtag_list_t; +typedef struct _y4m_stream_info y4m_stream_info_t; +typedef struct _y4m_frame_info y4m_frame_info_t; + + +#ifdef __cplusplus +#define BEGIN_CDECLS extern "C" { +#define END_CDECLS } +#else +#define BEGIN_CDECLS +#define END_CDECLS +#endif + +BEGIN_CDECLS + +/************************************************************************ + * 'ratio' functions + ************************************************************************/ + +/* 'normalize' a ratio (remove common factors) */ +void y4m_ratio_reduce(y4m_ratio_t *r); + +/* parse "nnn:ddd" into a ratio (returns Y4M_OK or Y4M_ERR_RANGE) */ +int y4m_parse_ratio(y4m_ratio_t *r, const char *s); + +/* quick test of two ratios for equality (i.e. identical components) */ +#define Y4M_RATIO_EQL(a,b) ( ((a).n == (b).n) && ((a).d == (b).d) ) + +/* quick conversion of a ratio to a double (no divide-by-zero check!) */ +#define Y4M_RATIO_DBL(r) ((double)(r).n / (double)(r).d) + +/************************************************************************* + * + * Guess the true SAR (sample aspect ratio) from a list of commonly + * encountered values, given the "suggested" display aspect ratio (DAR), + * and the true frame width and height. + * + * Returns y4m_sar_UNKNOWN if no match is found. + * + *************************************************************************/ +y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar); + + +/************************************************************************* + * + * Chroma Subsampling Mode information + * + * x_ratio, y_ratio - subsampling of chroma planes + * x_offset, y_offset - offset of chroma sample grid, + * relative to luma (0,0) sample + * + *************************************************************************/ + +y4m_ratio_t y4m_chroma_ss_x_ratio(int chroma_mode); +y4m_ratio_t y4m_chroma_ss_y_ratio(int chroma_mode); +#if 0 +y4m_ratio_t y4m_chroma_ss_x_offset(int chroma_mode, int field, int plane); +y4m_ratio_t y4m_chroma_ss_y_offset(int chroma_mode, int field, int plane); +#endif + +/* Given a string containing a (case-insensitive) chroma-tag keyword, + return appropriate chroma mode (or Y4M_UNKNOWN) */ +int y4m_chroma_parse_keyword(const char *s); + +/* Given a Y4M_CHROMA_* mode, return appropriate chroma-tag keyword, + or NULL if there is none. */ +const char *y4m_chroma_keyword(int chroma_mode); + +/* Given a Y4M_CHROMA_* mode, return appropriate chroma mode description, + or NULL if there is none. */ +const char *y4m_chroma_description(int chroma_mode); + + + +/************************************************************************ + * 'xtag' functions + * + * o Before using an xtag_list (but after the structure/memory has been + * allocated), you must initialize it via y4m_init_xtag_list(). + * o After using an xtag_list (but before the structure is released), + * call y4m_fini_xtag_list() to free internal memory. + * + ************************************************************************/ + +/* initialize an xtag_list structure */ +void y4m_init_xtag_list(y4m_xtag_list_t *xtags); + +/* finalize an xtag_list structure */ +void y4m_fini_xtag_list(y4m_xtag_list_t *xtags); + +/* make one xtag_list into a copy of another */ +void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); + +/* return number of tags in an xtag_list */ +int y4m_xtag_count(const y4m_xtag_list_t *xtags); + +/* access n'th tag in an xtag_list */ +const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n); + +/* append a new tag to an xtag_list + returns: Y4M_OK - success + Y4M_ERR_XXTAGS - list is already full */ +int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag); + +/* remove a tag from an xtag_list + returns: Y4M_OK - success + Y4M_ERR_RANGE - n is out of range */ +int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n); + +/* remove all tags from an xtag_list + returns: Y4M_OK - success */ +int y4m_xtag_clearlist(y4m_xtag_list_t *xtags); + +/* append copies of tags from src list to dest list + returns: Y4M_OK - success + Y4M_ERR_XXTAGS - operation would overfill dest list */ +int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); + + + +/************************************************************************ + * '*_info' functions + * + * o Before using a *_info structure (but after the structure/memory has + * been allocated), you must initialize it via y4m_init_*_info(). + * o After using a *_info structure (but before the structure is released), + * call y4m_fini_*_info() to free internal memory. + * o Use the 'set' and 'get' accessors to modify or access the fields in + * the structures; don't touch the structure directly. (Ok, so there + * is no really convenient C syntax to prevent you from doing this, + * but we are all responsible programmers here, so just don't do it!) + * + ************************************************************************/ + +/* initialize a stream_info structure */ +void y4m_init_stream_info(y4m_stream_info_t *i); + +/* finalize a stream_info structure */ +void y4m_fini_stream_info(y4m_stream_info_t *i); + +/* reset stream_info back to default/unknown values */ +void y4m_clear_stream_info(y4m_stream_info_t *info); + +/* make one stream_info into a copy of another */ +void y4m_copy_stream_info(y4m_stream_info_t *dest, + const y4m_stream_info_t *src); + +/* access or set stream_info fields */ +/* level 0 */ +int y4m_si_get_width(const y4m_stream_info_t *si); +int y4m_si_get_height(const y4m_stream_info_t *si); +int y4m_si_get_interlace(const y4m_stream_info_t *si); +y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si); +y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si); +void y4m_si_set_width(y4m_stream_info_t *si, int width); +void y4m_si_set_height(y4m_stream_info_t *si, int height); +void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace); +void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate); +void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar); +/* level 1 */ +void y4m_si_set_chroma(y4m_stream_info_t *si, int chroma_mode); +int y4m_si_get_chroma(const y4m_stream_info_t *si); + +/* derived quantities (no setter) */ +/* level 0 */ +int y4m_si_get_framelength(const y4m_stream_info_t *si); +/* level 1 */ +int y4m_si_get_plane_count(const y4m_stream_info_t *si); +int y4m_si_get_plane_width(const y4m_stream_info_t *si, int plane); +int y4m_si_get_plane_height(const y4m_stream_info_t *si, int plane); +int y4m_si_get_plane_length(const y4m_stream_info_t *si, int plane); + + +/* access stream_info xtag_list */ +y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si); + + +/* initialize a frame_info structure */ +void y4m_init_frame_info(y4m_frame_info_t *i); + +/* finalize a frame_info structure */ +void y4m_fini_frame_info(y4m_frame_info_t *i); + +/* reset frame_info back to default/unknown values */ +void y4m_clear_frame_info(y4m_frame_info_t *info); + +/* make one frame_info into a copy of another */ +void y4m_copy_frame_info(y4m_frame_info_t *dest, + const y4m_frame_info_t *src); + + +/* access or set frame_info fields (level 1) */ +int y4m_fi_get_presentation(const y4m_frame_info_t *fi); +int y4m_fi_get_temporal(const y4m_frame_info_t *fi); +int y4m_fi_get_spatial(const y4m_frame_info_t *fi); + +void y4m_fi_set_presentation(y4m_frame_info_t *fi, int pres); +void y4m_fi_set_temporal(y4m_frame_info_t *fi, int sampling); +void y4m_fi_set_spatial(y4m_frame_info_t *fi, int sampling); + + +/* access frame_info xtag_list */ +y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi); + + +/************************************************************************ + * blocking read and write functions + * + * o guaranteed to transfer entire payload (or fail) + * o return values: + * 0 (zero) complete success + * -(# of remaining bytes) error (and errno left set) + * +(# of remaining bytes) EOF (for y4m_read only) + * + ************************************************************************/ + +/* read len bytes from fd into buf */ +ssize_t y4m_read(int fd, void *buf, size_t len); + +/* write len bytes from fd into buf */ +ssize_t y4m_write(int fd, const void *buf, size_t len); + +/************************************************************************ + * callback based read and write + * + * The structures y4m_cb_reader_t and y4m_cb_writer_t must be + * set up by the caller before and of the *_read_*_cb() or + * *_write_*_cb() functions are called. Te return values of + * the read() and write() members have the same meaning as for + * y4m_read() and y4m_write() + * + ************************************************************************/ + +typedef struct y4m_cb_reader_s + { + void * data; + ssize_t (*read)(void * data, void *buf, size_t len); + } y4m_cb_reader_t; + +typedef struct y4m_cb_writer_s + { + void * data; + ssize_t (*write)(void * data, const void *buf, size_t len); + } y4m_cb_writer_t; + +/* read len bytes from fd into buf */ +ssize_t y4m_read_cb(y4m_cb_reader_t * fd, void *buf, size_t len); + +/* write len bytes from fd into buf */ +ssize_t y4m_write_cb(y4m_cb_writer_t * fd, const void *buf, size_t len); + + +/************************************************************************ + * stream header processing functions + * + * o return values: + * Y4M_OK - success + * Y4M_ERR_* - error (see y4m_strerr() for descriptions) + * + ************************************************************************/ + +/* parse a string of stream header tags */ +int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i); + +/* read a stream header from file descriptor fd + (the current contents of stream_info are erased first) */ +int y4m_read_stream_header(int fd, y4m_stream_info_t *i); + +/* read a stream header with a callback reader + (the current contents of stream_info are erased first) */ +int y4m_read_stream_header_cb(y4m_cb_reader_t * fd, y4m_stream_info_t *i); + +/* write a stream header to file descriptor fd */ +int y4m_write_stream_header(int fd, const y4m_stream_info_t *i); + +/* write a stream header with a callback writer */ +int y4m_write_stream_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *i); + + +/************************************************************************ + * frame processing functions + * + * o return values: + * Y4M_OK - success + * Y4M_ERR_* - error (see y4m_strerr() for descriptions) + * + ************************************************************************/ + +/* write a frame header to file descriptor fd */ +int y4m_write_frame_header(int fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi); + +/* write a frame header with a callback writer fd */ +int y4m_write_frame_header_cb(y4m_cb_writer_t * fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi); + +/* write a complete frame (header + data) to file descriptor fd + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_write_frame(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *planes); + +/* write a complete frame (header + data) with a callback writer fd + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_write_frame_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *planes); + +/* write a complete frame (header + data), to file descriptor fd + but interleave fields from two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_write_fields(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* write a complete frame (header + data), with a callback writer fd + but interleave fields from two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_write_fields_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read a frame header from file descriptor fd + (the current contents of frame_info are erased first) */ +int y4m_read_frame_header(int fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi); + +/* read a frame header with callback reader fd + (the current contents of frame_info are erased first) */ +int y4m_read_frame_header_cb(y4m_cb_reader_t * fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi); + +/* read frame data from file descriptor fd + [to be called after y4m_read_frame_header()] + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read frame data with callback reader fd + [to be called after y4m_read_frame_header_cb()] + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read frame data from file descriptor fd, + but de-interleave fields into two separate buffers + [to be called after y4m_read_frame_header()] + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read frame data with callback reader fd, + but de-interleave fields into two separate buffers + [to be called after y4m_read_frame_header_cb()] + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields_data_cb(y4m_cb_reader_t * fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read a complete frame (header + data) from file descriptor fd, + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read a complete frame (header + data) from callback reader fd, + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read a complete frame (header + data) from file descriptor fd, + but de-interleave fields into two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read a complete frame (header + data) from callback_reader fd, + but de-interleave fields into two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/************************************************************************ + * miscellaneous functions + ************************************************************************/ + +/* convenient dump of stream header info via mjpeg_log facility + * - each logged/printed line is prefixed by 'prefix' + */ +void y4m_log_stream_info(log_level_t level, const char *prefix, + const y4m_stream_info_t *i); + +/* convert a Y4M_ERR_* error code into mildly explanatory string */ +const char *y4m_strerr(int err); + +/* set 'allow_unknown_tag' flag for library... + o yn = 0 : unknown header tags will produce a parsing error + o yn = 1 : unknown header tags/values will produce a warning, but + are otherwise passed along via the xtags list + o yn = -1: don't change, just return current setting + + return value: previous setting of flag +*/ +int y4m_allow_unknown_tags(int yn); + + +/* set level of "accepted extensions" for the library... + o level = 0: default - conform to original YUV4MPEG2 spec; yield errors + when reading or writing a stream which exceeds it. + o level = 1: allow reading/writing streams which contain non-420jpeg + chroma and/or mixed-mode interlacing + o level = -1: don't change, just return current setting + + return value: previous setting of level + */ +int y4m_accept_extensions(int level); + + +END_CDECLS + + +/************************************************************************ + ************************************************************************ + + Description of the (new!, forever?) YUV4MPEG2 stream format: + + STREAM consists of + o one '\n' terminated STREAM-HEADER + o unlimited number of FRAMEs + + FRAME consists of + o one '\n' terminated FRAME-HEADER + o "length" octets of planar YCrCb 4:2:0 image data + (if frame is interlaced, then the two fields are interleaved) + + + STREAM-HEADER consists of + o string "YUV4MPEG2" + o unlimited number TAGGED-FIELDs, each preceded by ' ' separator + o '\n' line terminator + + FRAME-HEADER consists of + o string "FRAME" + o unlimited number of TAGGED-FIELDs, each preceded by ' ' separator + o '\n' line terminator + + + TAGGED-FIELD consists of + o single ascii character tag + o VALUE (which does not contain whitespace) + + VALUE consists of + o integer (base 10 ascii representation) + or o RATIO + or o single ascii character + or o non-whitespace ascii string + + RATIO consists of + o numerator (integer) + o ':' (a colon) + o denominator (integer) + + + The currently supported tags for the STREAM-HEADER: + W - [integer] frame width, pixels, should be > 0 + H - [integer] frame height, pixels, should be > 0 + C - [string] chroma-subsampling/data format + 420jpeg (default) + 420mpeg2 + 420paldv + 411 + 422 + 444 - non-subsampled Y'CbCr + 444alpha - Y'CbCr with alpha channel (with Y' black/white point) + mono - Y' plane only + I - [char] interlacing: p - progressive (none) + t - top-field-first + b - bottom-field-first + m - mixed -- see 'I' tag in frame header + ? - unknown + F - [ratio] frame-rate, 0:0 == unknown + A - [ratio] sample (pixel) aspect ratio, 0:0 == unknown + X - [character string] 'metadata' (unparsed, but passed around) + + The currently supported tags for the FRAME-HEADER: + Ixyz - framing/sampling (required if-and-only-if stream is "Im") + x: t - top-field-first + T - top-field-first and repeat + b - bottom-field-first + B - bottom-field-first and repeat + 1 - single progressive frame + 2 - double progressive frame (repeat) + 3 - triple progressive frame (repeat twice) + + y: p - progressive: fields sampled at same time + i - interlaced: fields sampled at different times + + z: p - progressive: subsampling over whole frame + i - interlaced: each field subsampled independently + ? - unknown (allowed only for non-4:2:0 subsampling) + + X - character string 'metadata' (unparsed, but passed around) + + ************************************************************************ + ************************************************************************/ + + +/* + + THAT'S ALL FOLKS! + + Thank you for reading the source code. We hope you have thoroughly + enjoyed the experience. + +*/ + + + + + +#ifdef INTERNAL_Y4M_LIBCODE_STUFF_QPX +#define Y4MPRIVATIZE(identifier) identifier +#else +#define Y4MPRIVATIZE(identifier) PRIVATE##identifier +#endif + +/* + * Actual structure definitions of structures which you shouldn't touch. + * + */ + +/************************************************************************ + * 'xtag_list' --- list of unparsed and/or meta/X header tags + * + * Do not touch this structure directly! + * + * Use the y4m_xtag_*() functions (see below). + * You must initialize/finalize this structure before/after use. + ************************************************************************/ +struct _y4m_xtag_list { + int Y4MPRIVATIZE(count); + char *Y4MPRIVATIZE(tags)[Y4M_MAX_XTAGS]; +}; + + +/************************************************************************ + * 'stream_info' --- stream header information + * + * Do not touch this structure directly! + * + * Use the y4m_si_*() functions (see below). + * You must initialize/finalize this structure before/after use. + ************************************************************************/ +struct _y4m_stream_info { + /* values from header/setters */ + int Y4MPRIVATIZE(width); + int Y4MPRIVATIZE(height); + int Y4MPRIVATIZE(interlace); /* see Y4M_ILACE_* definitions */ + y4m_ratio_t Y4MPRIVATIZE(framerate); /* see Y4M_FPS_* definitions */ + y4m_ratio_t Y4MPRIVATIZE(sampleaspect); /* see Y4M_SAR_* definitions */ + int Y4MPRIVATIZE(chroma); /* see Y4M_CHROMA_* definitions */ + + /* mystical X tags */ + y4m_xtag_list_t Y4MPRIVATIZE(x_tags); +}; + + +/************************************************************************ + * 'frame_info' --- frame header information + * + * Do not touch this structure directly! + * + * Use the y4m_fi_*() functions (see below). + * You must initialize/finalize this structure before/after use. + ************************************************************************/ + +struct _y4m_frame_info { + int Y4MPRIVATIZE(spatial); /* see Y4M_SAMPLING_* definitions */ + int Y4MPRIVATIZE(temporal); /* see Y4M_SAMPLING_* definitions */ + int Y4MPRIVATIZE(presentation); /* see Y4M_PRESENT_* definitions */ + /* mystical X tags */ + y4m_xtag_list_t Y4MPRIVATIZE(x_tags); +}; + + +#undef Y4MPRIVATIZE + + +#endif /* __YUV4MPEG_H__ */ + + diff --git a/branches/V-1.5.3/veejay-client/src/yuv4mpeg_intern.h b/branches/V-1.5.3/veejay-client/src/yuv4mpeg_intern.h new file mode 100644 index 00000000..3ada1cba --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/yuv4mpeg_intern.h @@ -0,0 +1,85 @@ +/* + * yuv4mpeg_intern.h: Internal constants for "new" YUV4MPEG streams + * + * Copyright (C) 2001 Andrew Stevens + * Copyright (C) 2001 Matthew J. Marjanovic + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __YUV4MPEG_INTERN_H__ +#define __YUV4MPEG_INTERN_H__ + + +#define Y4M_MAGIC "YUV4MPEG2" +#define Y4M_FRAME_MAGIC "FRAME" + +#define Y4M_DELIM " " /* single-character(space) separating tagged fields */ + +#define Y4M_LINE_MAX 256 /* max number of characters in a header line + (including the '\n', but not the '\0') */ + + +/* standard framerate ratios */ +#define Y4M_FPS_UNKNOWN { 0, 0 } +#define Y4M_FPS_NTSC_FILM { 24000, 1001 } +#define Y4M_FPS_FILM { 24, 1 } +#define Y4M_FPS_PAL { 25, 1 } +#define Y4M_FPS_NTSC { 30000, 1001 } +#define Y4M_FPS_30 { 30, 1 } +#define Y4M_FPS_PAL_FIELD { 50, 1 } +#define Y4M_FPS_NTSC_FIELD { 60000, 1001 } +#define Y4M_FPS_60 { 60, 1 } + +/* standard sample/pixel aspect ratios */ +#define Y4M_SAR_UNKNOWN { 0, 0 } +#define Y4M_SAR_SQUARE { 1, 1 } +#define Y4M_SAR_SQR_ANA_16_9 { 4, 3 } +#define Y4M_SAR_NTSC_CCIR601 { 10, 11 } +#define Y4M_SAR_NTSC_16_9 { 40, 33 } +#define Y4M_SAR_NTSC_SVCD_4_3 { 15, 11 } +#define Y4M_SAR_NTSC_SVCD_16_9 { 20, 11 } +#define Y4M_SAR_PAL_CCIR601 { 59, 54 } +#define Y4M_SAR_PAL_16_9 { 118, 81 } +#define Y4M_SAR_PAL_SVCD_4_3 { 59, 36 } +#define Y4M_SAR_PAL_SVCD_16_9 { 59, 27 } + +#define Y4M_SAR_MPEG1_1 Y4M_SAR_SQUARE +#define Y4M_SAR_MPEG1_2 { 10000, 6735 } +#define Y4M_SAR_MPEG1_3 { 10000, 7031 } /* Anamorphic 16:9 PAL */ +#define Y4M_SAR_MPEG1_4 { 10000, 7615 } +#define Y4M_SAR_MPEG1_5 { 10000, 8055 } +#define Y4M_SAR_MPEG1_6 { 10000, 8437 } /* Anamorphic 16:9 NTSC */ +#define Y4M_SAR_MPEG1_7 { 10000, 8935 } +#define Y4M_SAR_MPEG1_8 { 10000, 9375 } /* PAL/SECAM 4:3 */ +#define Y4M_SAR_MPEG1_9 { 10000, 9815 } +#define Y4M_SAR_MPEG1_10 { 10000, 10255 } +#define Y4M_SAR_MPEG1_11 { 10000, 10695 } +#define Y4M_SAR_MPEG1_12 { 10000, 11250 } /* NTSC 4:3 */ +#define Y4M_SAR_MPEG1_13 { 10000, 11575 } +#define Y4M_SAR_MPEG1_14 { 10000, 12015 } + +#define Y4M_DAR_UNKNOWN { 0, 0 } +#define Y4M_DAR_4_3 { 4, 3 } +#define Y4M_DAR_16_9 { 16, 9 } +#define Y4M_DAR_221_100 { 221, 100 } + +#define Y4M_DAR_MPEG2_1 { 1, 1 } +#define Y4M_DAR_MPEG2_2 { 4, 3 } +#define Y4M_DAR_MPEG2_3 { 16, 9 } +#define Y4M_DAR_MPEG2_4 { 221, 100 } + +#endif /* __YUV4MPEG_INTERN_H__ */ + diff --git a/branches/V-1.5.3/veejay-client/src/yuv4mpeg_ratio.c b/branches/V-1.5.3/veejay-client/src/yuv4mpeg_ratio.c new file mode 100644 index 00000000..7b50578c --- /dev/null +++ b/branches/V-1.5.3/veejay-client/src/yuv4mpeg_ratio.c @@ -0,0 +1,157 @@ +/* + * yuv4mpeg_ratio.c: Functions for dealing with y4m_ratio_t datatype. + * + * Copyright (C) 2001 Matthew J. Marjanovic + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include "yuv4mpeg.h" +#include "yuv4mpeg_intern.h" + + +/* useful list of standard framerates */ +const y4m_ratio_t y4m_fps_UNKNOWN = Y4M_FPS_UNKNOWN; +const y4m_ratio_t y4m_fps_NTSC_FILM = Y4M_FPS_NTSC_FILM; +const y4m_ratio_t y4m_fps_FILM = Y4M_FPS_FILM; +const y4m_ratio_t y4m_fps_PAL = Y4M_FPS_PAL; +const y4m_ratio_t y4m_fps_NTSC = Y4M_FPS_NTSC; +const y4m_ratio_t y4m_fps_30 = Y4M_FPS_30; +const y4m_ratio_t y4m_fps_PAL_FIELD = Y4M_FPS_PAL_FIELD; +const y4m_ratio_t y4m_fps_NTSC_FIELD = Y4M_FPS_NTSC_FIELD; +const y4m_ratio_t y4m_fps_60 = Y4M_FPS_60; + +/* useful list of standard sample aspect ratios */ +const y4m_ratio_t y4m_sar_UNKNOWN = Y4M_SAR_UNKNOWN; +const y4m_ratio_t y4m_sar_SQUARE = Y4M_SAR_SQUARE; +const y4m_ratio_t y4m_sar_SQR_ANA_16_9 = Y4M_SAR_SQR_ANA_16_9; +const y4m_ratio_t y4m_sar_NTSC_CCIR601 = Y4M_SAR_NTSC_CCIR601; +const y4m_ratio_t y4m_sar_NTSC_16_9 = Y4M_SAR_NTSC_16_9; +const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3 = Y4M_SAR_NTSC_SVCD_4_3; +const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9 = Y4M_SAR_NTSC_SVCD_16_9; +const y4m_ratio_t y4m_sar_PAL_CCIR601 = Y4M_SAR_PAL_CCIR601; +const y4m_ratio_t y4m_sar_PAL_16_9 = Y4M_SAR_PAL_16_9; +const y4m_ratio_t y4m_sar_PAL_SVCD_4_3 = Y4M_SAR_PAL_SVCD_4_3; +const y4m_ratio_t y4m_sar_PAL_SVCD_16_9 = Y4M_SAR_PAL_SVCD_16_9; + +/* useful list of standard display aspect ratios */ +const y4m_ratio_t y4m_dar_UNKNOWN = Y4M_DAR_UNKNOWN; +const y4m_ratio_t y4m_dar_4_3 = Y4M_DAR_4_3; +const y4m_ratio_t y4m_dar_16_9 = Y4M_DAR_16_9; +const y4m_ratio_t y4m_dar_221_100 = Y4M_DAR_221_100; + +/* + * Euler's algorithm for greatest common divisor + */ + +static int gcd(int a, int b) +{ + a = (a >= 0) ? a : -a; + b = (b >= 0) ? b : -b; + + while (b > 0) { + int x = b; + b = a % b; + a = x; + } + return a; +} + + +/************************************************************************* + * + * Remove common factors from a ratio + * + *************************************************************************/ + + +void y4m_ratio_reduce(y4m_ratio_t *r) +{ + int d; + if ((r->n == 0) && (r->d == 0)) return; /* "unknown" */ + d = gcd(r->n, r->d); + r->n /= d; + r->d /= d; +} + + + +/************************************************************************* + * + * Parse "nnn:ddd" into a ratio + * + * returns: Y4M_OK - success + * Y4M_ERR_RANGE - range error + * + *************************************************************************/ + +int y4m_parse_ratio(y4m_ratio_t *r, const char *s) +{ + char *t = strchr(s, ':'); + if (t == NULL) return Y4M_ERR_RANGE; + r->n = atoi(s); + r->d = atoi(t+1); + if (r->d < 0) return Y4M_ERR_RANGE; + /* 0:0 == unknown, so that is ok, otherwise zero denominator is bad */ + if ((r->d == 0) && (r->n != 0)) return Y4M_ERR_RANGE; + y4m_ratio_reduce(r); + return Y4M_OK; +} + + + +/************************************************************************* + * + * Guess the true SAR (sample aspect ratio) from a list of commonly + * encountered values, given the "suggested" display aspect ratio, and + * the true frame width and height. + * + * Returns y4m_sar_UNKNOWN if no match is found. + * + *************************************************************************/ + +/* this is big enough to accommodate the difference between 720 and 704 */ +#define GUESS_ASPECT_TOLERANCE 0.03 + +y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar) +{ + int i; + double implicit_sar = (double)(dar.n * height) / (double)(dar.d * width); + const y4m_ratio_t *sarray[] = + { + &y4m_sar_SQUARE, + &y4m_sar_NTSC_CCIR601, + &y4m_sar_NTSC_16_9, + &y4m_sar_NTSC_SVCD_4_3, + &y4m_sar_NTSC_SVCD_16_9, + &y4m_sar_PAL_CCIR601, + &y4m_sar_PAL_16_9, + &y4m_sar_PAL_SVCD_4_3, + &y4m_sar_PAL_SVCD_16_9, + &y4m_sar_UNKNOWN + }; + for (i = 0; !(Y4M_RATIO_EQL(*(sarray[i]),y4m_sar_UNKNOWN)); i++) { + double ratio = implicit_sar / Y4M_RATIO_DBL(*(sarray[i])); + if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && + (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) ) + return *(sarray[i]); + } + return y4m_sar_UNKNOWN; +} diff --git a/branches/V-1.5.3/veejay-server/AUTHORS b/branches/V-1.5.3/veejay-server/AUTHORS new file mode 100644 index 00000000..19fe4174 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/AUTHORS @@ -0,0 +1,30 @@ + +veejay contributors: +==================== + + (in no particular order) + + Jeff Carpenter + David Denny + Daniel Jircik + Pilo Chambert + Matthijs van Henten + Dursun Koca + Peter de Man + Stefan Thieme + Andrew Wood + Kyle Davenport + Daniel Rohr + Rupert Reddington + Toni (from Germany) + Thomas Reinhold + Maciek Szczesniak + + +authors: +====================== + + Niels Elburg + + + diff --git a/branches/V-1.5.3/veejay-server/COPYING b/branches/V-1.5.3/veejay-server/COPYING new file mode 100644 index 00000000..223ede7d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 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. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/branches/V-1.5.3/veejay-server/ChangeLog b/branches/V-1.5.3/veejay-server/ChangeLog new file mode 100644 index 00000000..41e9dec2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/ChangeLog @@ -0,0 +1 @@ + diff --git a/branches/V-1.5.3/veejay-server/Makefile.am b/branches/V-1.5.3/veejay-server/Makefile.am new file mode 100644 index 00000000..cf3cc105 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/Makefile.am @@ -0,0 +1,75 @@ +# Process with automake to produce Makefile.in + +SUBDIRS = mjpegtools aclib libOSC libhash libvjmsg libvjmem +SUBDIRS += bio2jack libvevo liblzo libvje libsample libvjnet libyuv libel libstream libsamplerec +SUBDIRS += veejay +SUBDIRS += man + +EXTRA_DIST = \ + autogen.sh\ + depcomp \ + cpuinfo.sh \ + autogen.sh \ + PKGBUILD \ + doc/veejay-HOWTO.html \ + doc/README.quickstart \ + doc/README.whatis \ + doc/README.performance \ + doc/HowtoPlugins.txt \ + doc/HowtoCache.txt \ + doc/VIMS.txt \ + doc/NET.txt \ + debian/changelog \ + debian/control \ + debian/copyright \ + debian/rules \ + buildinfo.sh + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = veejay.pc + +DISTCLEANFILES = \ + veejay-config.h \ + veejay.pc \ + confdefs.h \ + config.cache \ + config.status \ + config.log + +MAINTAINERCLEANFILES = \ + compile \ + depcomp \ + install-sh \ + missing \ + mkinstalldirs \ + Makefile.in \ + aclocal.m4 \ + config.guess \ + config.h.in \ + config.sub \ + configure \ + ltmain.sh \ + stamp-h.in + +## make rpms +rpm: Makefile + $(MAKE) dist + rpmbuild -ta --clean $(PACKAGE)-$(VERSION).tar.gz + +ubuntu: + chmod a+x debian/rules + debuild -i -us -uc -b + +release: + rm -rf .deps */.deps + $(MAKE) distcheck + +snapshot: + $(MAKE) dist distdir=$(PACKAGE)-`date +%Y-%m-%d` + +## make debs +deb: Makefile dist + -chmod -R +w $(PACKAGE)-$(VERSION) + rm -rf $(PACKAGE)-$(VERSION) + tar xzf $(PACKAGE)-$(VERSION).tar.gz + cd $(PACKAGE)-$(VERSION); dpkg-buildpackage -rfakeroot diff --git a/branches/V-1.5.3/veejay-server/NEWS b/branches/V-1.5.3/veejay-server/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/branches/V-1.5.3/veejay-server/PKGBUILD b/branches/V-1.5.3/veejay-server/PKGBUILD new file mode 100644 index 00000000..d1428121 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/PKGBUILD @@ -0,0 +1,30 @@ +# Contributor: Luciano A. Ferrer +pkgname=veejay-server-svn +pkgrel=1 +pkgdesc="Veejay is a visual instrument and realtime video sampler for GNU/Linux, server" +arch=(i686,x86_64) +url="http://www.veejayhq.net" +license="GPL" +conflicts=('veejay-server') +provides=('veejay-server') +depends=('libxml2' 'jack-audio-connection-kit' 'ffmpeg' ) +source=() +md5sums=() + +_svntrunk="svn://dyne.org/veejay/trunk/veejay-current/veejay-server" +_svnmod="veejay-server" + +build() { +cd $startdir/src/ + +svn co $_svntrunk --config-dir ./ $_svnmod + + cp -r $startdir/src/$_svnmod $startdir/src/$_svnmod-build + cd $startdir/src/$_svnmod-build + + ./autogen.sh + ./configure --prefix=/usr + make || return 1 + make DESTDIR=$startdir/pkg install + +} diff --git a/branches/V-1.5.3/veejay-server/README b/branches/V-1.5.3/veejay-server/README new file mode 100644 index 00000000..cc090722 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/README @@ -0,0 +1,204 @@ + + + + + 10x0 0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 x0x1 10x0 x0x1 + 0x10x0 0x0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 10x0x10x 10x0x1 10x0x1 +0x0x10 0x0x10 x10x 10x0 x0x1 10x0x10x x0x10x 10x0 +0x0x10x0 0x0x10 x10x0x10x0x1 10x0x10x0x10 x0x1 0x10 0x0 x10x0x10 + 0x10x0 x10x0x x10x0x10x0x10x 10x0x10x0x10 x0x1 0x10x0x10x0 x10x0x10 + 10x0x1 x0x10x x10x 10x0 x0x1 0x10x0x10x0 0x0x + x0x10x0x10x0x1 x10x 10x0 x10x x0x1 0x10x0x10x0x10 0x0x + x10x0x10x0 x10x0x10x0x10x 10x0x10x0x10x0 x10x 10x0 0x0x 0x10 0x0x + 0x0x10 x10x0x10x0x10x 10x0x10x0x10x0 0x010x0 0x0x 0x10 0x0x + + version 1.4 + March 2009 + + ========================================= + + :: Veejay, a visual instrument for GNU :: + http://veejayhq.net + http://veejay.dyne.org + + + + Veejay - a 'visual' instrument and realtime video sampler + +Veejay is a visual instrument and real-time video sampler. +It allows you to "play" the video like you would play a piano. +While playing, you can record the resulting video directly to disk (video sampling). + + + + FEATURE OVERVIEW + +General +------- + # Free Software (GNU GPL) (1) + # Servent architecture (2) + # Soft realtime (3) + # Frame accurate (4) + # Loop based editing (5) + # Native YUV processing + # Crash recovery + +Media +----- + # Codecs: MJPEG,MPNG, DV, YUV (raw) + # Containers: AVI , Quicktime, rawDV + # Devices: USB webcams, DV1394, TV capture cards, etc. + # Support for unlimited capture devices + # Support for Image files (PNG ,JPEG,TIFF,etc) + +Editing +------- + # 132 built-in FX , many unique and original FX filters + # FX chain (20 slots) + # All FX parameters can be animated. + # Mix up to two layers per FX slot + # Non destructive edit decision lists (cut/copy/paste/crop video) + # Simple text editor + # Sample editor + # Sequence editor + # Live disk recorder (sampling) + # Full deck save/restore + # Live clip loading + # Live sample sequencing + + + +Trickplay +--------- + # VIMS event recording/playback (6) + # Various looping modes including bounce looping + # Playback speed and direction + # Video scratching + # Change in-and out points of a sample (marker) + # Slow motion audio / video (7) + # Fast motion audio / video + # Dynamic framerate + # Random frame play + # Random sample play + # Access up to 4096 video samples instantly + +Output +------ + # Audio trough Jack (low latency audio server) (8) + # SDL and OpenGL video + # Headless + # YUV4MPEG streaming + # Network streaming (unicast and multicast) + # Preview rendering + +Interaction +----------- + # Programmable keyboard interface + # VIMS (tcp/ip) + # OSC (udp) + # PureData trough sendVIMS external + +Viewing +------- + # Full screen or windowed mode + # Perspective and foward projection (9) + + +Additional +---------- + # Support for FreeFrame plugins + # Support for Frei0r plugins + + + + + +(1) Free Software + A matter of liberty, not price. You should think of “free” as in free speech. + Free software is the matter of the users freedom to run, copy, distribute, study, change and improve the software. + +(2) A servent architecture is a peer-to-peer network mode with both functionalities of a + server and a client. The setup is designed so that each veejay-node can send and receive video, + allowing for the creation and maintenance of ad-hoc veejay-networks. + Reloaded , veejay's graphical interface, is a thin client and can be run from another computer + to track one or more veejay servers. + +(3) Soft realtime: A system is realtime if the correctness of the application not only depends on + the logical correctness but also upon the time at which it was performed. + Veejay tolerates such lateness and responds by dropping video frames. + You can instruct veejay to ignore the time aspect of the video and render all frames, effectivly + turning the server into a frame producer. + +(4) VIMS: Veejay Internal Message System. Control data is distributed via this message system, + each message consists of an 'event selector' with a list of arguments. VIMS is the lowest + level control interface available. The keyboard interface and OSC server are built on top of it. + Also all veejay clients communicate usings VIMS. + +(5) Loop based editing: Loops are (short) sections of video (up to any length) that are repeated + continuously. While playing, you can change the properties of the video sample, add filters to it + and record it on the fly to a new sample (which can be used instantly). + +(6) Frame accurate: In veejay, every frame is a key-frame (a whole image). + As a consequence, veejay has no support for video codecs that make use of difference frames. + +(7) In trickplay mode, veejay will always resample the audio analogous to varying the speed + of an analogue tape recorder . Halve the speed results in the pitch going down an octave. + Slow motion video is produced by linearly interpolating in-between frames and + faster motion is accomplished by skipping video frames or, if playing without audio, + by changing the framerate dynamically. + +(8) JACK: A low latency audio server that can connect a number of different applications to an audio device, + allowing them to share audio between themselves. + +(9) Perspective Viewing: You can define a quadrilateral to which the rendered image will be mapped. + This is usefull for setups where the image borders fall outside the projection screen area, or where + the projector/camera has a (wide) angle to the projection. + Last but not least, it can be used for on-body projection performances. + + + + + +Install +======= + +See file 'INSTALL' + +See doc/Howto_Compile.html +See doc/Howto_Compile_on_Ubuntu.html + +Documentation +============= + +See the directory 'doc' in this package, it contains usefull documentation. + + +First time setup +================ + +You need to font a TrueType Font file in $HOME/.veejay/fonts + + +Running +======= + +Start 1 or more Veejay servers: +$ veejay my-movie-A.avi +$ veejay -p 4490 my-movie-B.avi + +CONTACT / FEEDBACK & HELP +========================= + +http://veejayhq.net + + +BUG REPORTS / BLEEDING EDGE SOURCE CODE +======================================= + +Please use the ticket system ! + +http://veejay.dyne.org +http://veejayhq.net + +ENJOY! And let us know about your performances/installations with veejay! + diff --git a/branches/V-1.5.3/veejay-server/aclib/Makefile.am b/branches/V-1.5.3/veejay-server/aclib/Makefile.am new file mode 100644 index 00000000..d77b6e6b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/Makefile.am @@ -0,0 +1,22 @@ +# # Process this file with automake to produce Makefile.in. + +EXTRA_DIST= ac.h ac_internal.h imgconvert.h img_internal.h img_x86_common.h + +AM_CPPFLAGS = \ + $(PTHREAD_CFLAGS) \ + -I$(top_srcdir) + +noinst_LTLIBRARIES = libac.la + +libac_la_SOURCES = \ + accore.c \ + average.c \ + imgconvert.c \ + img_rgb_packed.c \ + img_yuv_mixed.c \ + img_yuv_packed.c \ + img_yuv_planar.c \ + img_yuv_rgb.c \ + memcpy.c \ + rescale.c + diff --git a/branches/V-1.5.3/veejay-server/aclib/ac.h b/branches/V-1.5.3/veejay-server/aclib/ac.h new file mode 100644 index 00000000..d0bb1e0d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/ac.h @@ -0,0 +1,97 @@ +/* + * ac.h -- main aclib include + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#ifndef ACLIB_AC_H +#define ACLIB_AC_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +/*************************************************************************/ + +/* CPU acceleration support flags, for use with ac_init(): */ + +#define AC_IA32ASM 0x0001 /* x86-32: standard assembly (no MMX) */ +#define AC_AMD64ASM 0x0002 /* x86-64: standard assembly (no MMX) */ +#define AC_CMOVE 0x0004 /* x86: CMOVcc instruction */ +#define AC_MMX 0x0008 /* x86: MMX instructions */ +#define AC_MMXEXT 0x0010 /* x86: MMX extended instructions (AMD) */ +#define AC_3DNOW 0x0020 /* x86: 3DNow! instructions (AMD) */ +#define AC_3DNOWEXT 0x0040 /* x86: 3DNow! instructions (AMD) */ +#define AC_SSE 0x0080 /* x86: SSE instructions */ +#define AC_SSE2 0x0100 /* x86: SSE2 instructions */ +#define AC_SSE3 0x0200 /* x86: SSE3 instructions */ + +#define AC_NONE 0 /* No acceleration (vanilla C functions) */ +#define AC_ALL (~0) /* All available acceleration */ + + +/* Endianness flag: */ +#define AC_LITTLE_ENDIAN 1 +#define AC_BIG_ENDIAN 2 + +/*************************************************************************/ + +/* Library initialization function--MUST be called before any other aclib + * functions are used! `accel' selects the accelerations to enable: + * AC_NONE, AC_ALL, or a combination of the other AC_* flags above. The + * value will always be masked to the acceleration options available on the + * actual CPU, as returned by ac_cpuinfo(). Returns 1 on success, 0 on + * failure. This function can be called multiple times to change the set + * of acceleration features to be used. */ +extern int ac_init(int accel); + +/* Returns the set of acceleration features supported by this CPU. */ +extern int ac_cpuinfo(void); + +/* Returns the endianness of this CPU (AC_BIG_ENDIAN or AC_LITTLE_ENDIAN). */ +extern int ac_endian(void); + +/* Utility routine to convert a set of flags to a descriptive string. The + * string is stored in a static buffer overwritten each call. */ +extern const char *ac_flagstotext(int accel); + +/*************************************************************************/ + +/* Acceleration-enabled functions: */ + +/* Optimized memcpy(). The copy direction is guaranteed to be ascending + * (so ac_memcpy(ptr, ptr+1, size) will work). */ +extern void *ac_memcpy(void *dest, const void *src, size_t size); + +/* Average of two sets of data */ +extern void ac_average(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes); + +/* Weighted average of two sets of data (weight1+weight2 should be 65536) */ +extern void ac_rescale(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes, + uint32_t weight1, uint32_t weight2); + +/* Image format manipulation is available in aclib/imgconvert.h */ + +/*************************************************************************/ + +#endif /* ACLIB_AC_H */ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/ac_internal.h b/branches/V-1.5.3/veejay-server/aclib/ac_internal.h new file mode 100644 index 00000000..67a9c59f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/ac_internal.h @@ -0,0 +1,42 @@ +/* + * ac_internal.h -- internal include file for aclib functions + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#ifndef ACLIB_AC_INTERNAL_H +#define ACLIB_AC_INTERNAL_H + + +/* Compiler hint that a condition is unlikely */ +#ifdef __GNUC__ +# define UNLIKELY(x) (__builtin_expect((x) != 0, 0)) +#else +# define UNLIKELY(x) (x) +#endif + +/* Are _all_ of the given acceleration flags (`test') available? */ +#define HAS_ACCEL(accel,test) (((accel) & (test)) == (test)) + +/* Initialization subfunctions */ +extern int ac_average_init(int accel); +extern int ac_imgconvert_init(int accel); +extern int ac_memcpy_init(int accel); +extern int ac_rescale_init(int accel); + + +#endif /* ACLIB_AC_INTERNAL_H */ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/accore.c b/branches/V-1.5.3/veejay-server/aclib/accore.c new file mode 100644 index 00000000..2d7d14b5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/accore.c @@ -0,0 +1,225 @@ +/* + * accore.c -- core aclib functions + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "ac_internal.h" +#include "imgconvert.h" + +#include +#include + +#if defined(ARCH_X86) || defined(ARCH_X86_64) +static int cpuinfo_x86(void); +#endif + +/*************************************************************************/ + +/* Library initialization function. Determines CPU features, then calls + * all initialization subfunctions with appropriate flags. Returns 1 on + * success, 0 on failure. This function can be called multiple times to + * change the set of acceleration features to be used. */ + +int ac_init(int accel) +{ + accel &= ac_cpuinfo(); + if (!ac_average_init(accel) + || !ac_imgconvert_init(accel) + || !ac_memcpy_init(accel) + || !ac_rescale_init(accel) + ) { + return 0; + } + return 1; +} + +/*************************************************************************/ + +/* Returns the set of acceleration features supported by this CPU. */ + +int ac_cpuinfo(void) +{ +#if defined(ARCH_X86) || defined(ARCH_X86_64) + return cpuinfo_x86(); +#else + return 0; +#endif +} + +/*************************************************************************/ + +/* Returns the endianness of this CPU (AC_BIG_ENDIAN or AC_LITTLE_ENDIAN). */ + +int ac_endian(void) +{ + volatile int test; + + test = 1; + if (*((uint8_t *)&test)) + return AC_LITTLE_ENDIAN; + else + return AC_BIG_ENDIAN; +} + +/*************************************************************************/ + +/* Utility routine to convert a set of flags to a descriptive string. The + * string is stored in a static buffer overwritten each call. `filter' + * selects whether to filter out flags not supported by the CPU. */ + +const char *ac_flagstotext(int accel) +{ + static char retbuf[1000]; + if (!accel) + return "none"; + snprintf(retbuf, sizeof(retbuf), "%s%s%s%s%s%s%s%s%s", + accel & AC_SSE3 ? " sse3" : "", + accel & AC_SSE2 ? " sse2" : "", + accel & AC_SSE ? " sse" : "", + accel & AC_3DNOWEXT ? " 3dnowext" : "", + accel & AC_3DNOW ? " 3dnow" : "", + accel & AC_MMXEXT ? " mmxext" : "", + accel & AC_MMX ? " mmx" : "", + accel & AC_CMOVE ? " cmove" : "", + accel & (AC_IA32ASM|AC_AMD64ASM) ? " asm" : ""); + return *retbuf ? retbuf+1 : retbuf; /* skip initial space */ +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Private functions to return acceleration flags corresponding to available + * CPU features for various CPUs. Currently only x86 is supported. */ + +/*************************************************************************/ + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + +#ifdef ARCH_X86_64 +# define EAX "%%rax" +# define EBX "%%rbx" +# define ESI "%%rsi" +# define PUSHF "pushfq" +# define POPF "popfq" +#else +# define EAX "%%eax" +# define EBX "%%ebx" +# define ESI "%%esi" +# define PUSHF "pushfl" +# define POPF "popfl" +#endif + +/* Macro to execute the CPUID instruction with EAX = func. Results are + * placed in ret_a (EAX), ret_b (EBX), ret_c (ECX), and ret_d (EDX), which + * must be lvalues. Note that we save and restore EBX (RBX on x86-64) + * because it is the PIC register. */ +#define CPUID(func,ret_a,ret_b,ret_c,ret_d) \ + asm("mov "EBX", "ESI"; cpuid; xchg "EBX", "ESI \ + : "=a" (ret_a), "=S" (ret_b), "=c" (ret_c), "=d" (ret_d) \ + : "a" (func)) + +/* Various CPUID flags. The second word of the macro name indicates the + * function (1: function 1, X1: function 0x80000001) and register (D: EDX) + * to which the value belongs. */ +#define CPUID_1D_CMOVE (1UL<<15) +#define CPUID_1D_MMX (1UL<<23) +#define CPUID_1D_SSE (1UL<<25) +#define CPUID_1D_SSE2 (1UL<<26) +#define CPUID_1C_SSE3 (1UL<< 0) +#define CPUID_X1D_AMD_MMXEXT (1UL<<22) /* AMD only */ +#define CPUID_X1D_AMD_3DNOW (1UL<<31) /* AMD only */ +#define CPUID_X1D_AMD_3DNOWEXT (1UL<<30) /* AMD only */ +#define CPUID_X1D_CYRIX_MMXEXT (1UL<<24) /* Cyrix only */ + +static int cpuinfo_x86(void) +{ + uint32_t eax, ebx, ecx, edx; + uint32_t cpuid_max, cpuid_ext_max; /* Maximum CPUID function numbers */ + char cpu_vendor[13]; /* 12-byte CPU vendor string + trailing null */ + uint32_t cpuid_1D, cpuid_1C, cpuid_X1D; + int accel; + + /* First see if the CPUID instruction is even available. We try to + * toggle bit 21 (ID) of the flags register; if the bit changes, then + * CPUID is available. */ + asm(PUSHF" \n\ + pop "EAX" \n\ + mov %%eax, %%edx \n\ + xor $0x200000, %%eax \n\ + push "EAX" \n\ + "POPF" \n\ + "PUSHF" \n\ + pop "EAX" \n\ + xor %%edx, %%eax" + : "=a" (eax) : : "edx"); + if (!eax) + return 0; + + /* Determine the maximum function number available, and save the vendor + * string */ + CPUID(0, cpuid_max, ebx, ecx, edx); + *((uint32_t *)(cpu_vendor )) = ebx; + *((uint32_t *)(cpu_vendor+4)) = edx; + *((uint32_t *)(cpu_vendor+8)) = ecx; + cpu_vendor[12] = 0; + cpuid_ext_max = 0; /* FIXME: how do early CPUs respond to 0x80000000? */ + CPUID(0x80000000, cpuid_ext_max, ebx, ecx, edx); + + /* Read available features */ + cpuid_1D = cpuid_1C = cpuid_X1D = 0; + if (cpuid_max >= 1) + CPUID(1, eax, ebx, cpuid_1C, cpuid_1D); + if (cpuid_ext_max >= 0x80000001) + CPUID(0x80000001, eax, ebx, ecx, cpuid_X1D); + + /* Convert to acceleration flags */ +#ifdef ARCH_X86_64 + accel = AC_AMD64ASM; /* but not IA32! (register size issues) */ +#else + accel = AC_IA32ASM; +#endif + if (cpuid_1D & CPUID_1D_CMOVE) + accel |= AC_CMOVE; + if (cpuid_1D & CPUID_1D_MMX) + accel |= AC_MMX; + if (cpuid_1D & CPUID_1D_SSE) + accel |= AC_SSE; + if (cpuid_1D & CPUID_1D_SSE2) + accel |= AC_SSE2; + if (cpuid_1C & CPUID_1C_SSE3) + accel |= AC_SSE3; + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + if (cpuid_X1D & CPUID_X1D_AMD_MMXEXT) + accel |= AC_MMXEXT; + if (cpuid_X1D & CPUID_X1D_AMD_3DNOW) + accel |= AC_3DNOW; + if (cpuid_X1D & CPUID_X1D_AMD_3DNOWEXT) + accel |= AC_3DNOWEXT; + } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { + if (cpuid_X1D & CPUID_X1D_CYRIX_MMXEXT) + accel |= AC_MMXEXT; + } + + /* And return */ + return accel; +} + +#endif /* ARCH_X86 || ARCH_X86_64 */ + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/average.c b/branches/V-1.5.3/veejay-server/aclib/average.c new file mode 100644 index 00000000..517102e6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/average.c @@ -0,0 +1,243 @@ +/* + * average.c -- average two sets of byte data + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "ac_internal.h" + +static void average(const uint8_t *, const uint8_t *, uint8_t *, int); +static void (*average_ptr)(const uint8_t *, const uint8_t *, uint8_t *, int) + = average; + +/*************************************************************************/ + +/* External interface */ + +void ac_average(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes) +{ + (*average_ptr)(src1, src2, dest, bytes); +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Vanilla C version */ + +static void average(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes) +{ + int i; + for (i = 0; i < bytes; i++) + dest[i] = (src1[i]+src2[i]+1) / 2; +} + +/*************************************************************************/ + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */ + +static void average_mmx(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes) +{ + if (bytes >= 8) { + asm("\ + pxor %%mm7, %%mm7 \n\ + movq %%mm7, %%mm6 \n\ + pcmpeqw %%mm5, %%mm5 \n\ + psubw %%mm5, %%mm6 # Put 0x0001*4 in MM6 \n\ + 0: \n\ + movq -8(%%esi,%%eax), %%mm0 \n\ + movq %%mm0, %%mm1 \n\ + punpcklbw %%mm7, %%mm0 \n\ + punpckhbw %%mm7, %%mm1 \n\ + movq -8(%%edx,%%eax), %%mm2 \n\ + movq %%mm2, %%mm3 \n\ + punpcklbw %%mm7, %%mm2 \n\ + punpckhbw %%mm7, %%mm3 \n\ + paddw %%mm2, %%mm0 \n\ + paddw %%mm6, %%mm0 \n\ + psrlw $1, %%mm0 \n\ + paddw %%mm3, %%mm1 \n\ + paddw %%mm6, %%mm1 \n\ + psrlw $1, %%mm1 \n\ + packuswb %%mm1, %%mm0 \n\ + movq %%mm0, -8(%%edi,%%eax) \n\ + subl $8, %%eax \n\ + jnz 0b \n\ + emms" + : /* no outputs */ + : "S" (src1), "d" (src2), "D" (dest), "a" (bytes & ~7)); + } + if (UNLIKELY(bytes & 7)) { + average(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7), + bytes & 7); + } +} + +#endif /* HAVE_ASM_MMX && ARCH_X86 */ + +/*************************************************************************/ + +#if defined(HAVE_ASM_SSE) && defined(ARCH_X86) + +/* SSE has PAVGB */ + +static void average_sse(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes) +{ + if (bytes >= 8) { + asm("\ + testl $~0x1F, %%eax \n\ + jz 1f \n\ + 0: \n\ + movq -32(%%esi,%%eax), %%mm0 \n\ + movq -24(%%esi,%%eax), %%mm1 \n\ + movq -16(%%esi,%%eax), %%mm2 \n\ + movq -8(%%esi,%%eax), %%mm3 \n\ + movq -32(%%edx,%%eax), %%mm4 \n\ + pavgb %%mm4, %%mm0 \n\ + movq -24(%%edx,%%eax), %%mm5 \n\ + pavgb %%mm5, %%mm1 \n\ + movq -16(%%edx,%%eax), %%mm6 \n\ + pavgb %%mm6, %%mm2 \n\ + movq -8(%%edx,%%eax), %%mm7 \n\ + pavgb %%mm7, %%mm3 \n\ + movntq %%mm0, -32(%%edi,%%eax) \n\ + movntq %%mm1, -24(%%edi,%%eax) \n\ + movntq %%mm2, -16(%%edi,%%eax) \n\ + movntq %%mm3, -8(%%edi,%%eax) \n\ + subl $32, %%eax \n\ + testl $~0x1F, %%eax \n\ + jnz 0b \n\ + testl %%eax, %%eax \n\ + jz 2f \n\ + 1: \n\ + movq -8(%%esi,%%eax), %%mm0 \n\ + movq -8(%%edx,%%eax), %%mm1 \n\ + pavgb %%mm1, %%mm0 \n\ + movntq %%mm0, -8(%%edi,%%eax) \n\ + subl $8, %%eax \n\ + jnz 1b \n\ + 2: \n\ + emms \n\ + sfence" + : /* no outputs */ + : "S" (src1), "d" (src2), "D" (dest), "a" (bytes & ~7)); + } + if (UNLIKELY(bytes & 7)) { + average(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7), + bytes & 7); + } +} + +#endif /* HAVE_ASM_SSE && ARCH_X86 */ + +/*************************************************************************/ + +#if defined(HAVE_ASM_SSE2) + +#if defined(ARCH_X86_64) +# define EAX "%%rax" +# define EDX "%%rdx" +# define ESI "%%rsi" +# define EDI "%%rdi" +#else +# define EAX "%%eax" +# define EDX "%%edx" +# define ESI "%%esi" +# define EDI "%%edi" +#endif + +static void average_sse2(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes) +{ + if (bytes >= 8) { + asm("\ + testl $~0x3F, %%eax \n\ + jz 1f \n\ + 0: \n\ + movdqu -64("ESI","EAX"), %%xmm0 \n\ + movdqu -48("ESI","EAX"), %%xmm1 \n\ + movdqu -32("ESI","EAX"), %%xmm2 \n\ + movdqu -16("ESI","EAX"), %%xmm3 \n\ + movdqu -64("EDX","EAX"), %%xmm4 \n\ + pavgb %%xmm4, %%xmm0 \n\ + movdqu -48("EDX","EAX"), %%xmm5 \n\ + pavgb %%xmm5, %%xmm1 \n\ + movdqu -32("EDX","EAX"), %%xmm6 \n\ + pavgb %%xmm6, %%xmm2 \n\ + movdqu -16("EDX","EAX"), %%xmm7 \n\ + pavgb %%xmm7, %%xmm3 \n\ + # Note that movntdq requires 16-byte alignment, which we're \n\ + # not guaranteed \n\ + movdqu %%xmm0, -64("EDI","EAX") \n\ + movdqu %%xmm1, -48("EDI","EAX") \n\ + movdqu %%xmm2, -32("EDI","EAX") \n\ + movdqu %%xmm3, -16("EDI","EAX") \n\ + subl $64, %%eax \n\ + testl $~0x3F, %%eax \n\ + jnz 0b \n\ + testl %%eax, %%eax \n\ + jz 2f \n\ + 1: \n\ + movq -8("ESI","EAX"), %%mm0 \n\ + movq -8("EDX","EAX"), %%mm1 \n\ + pavgb %%mm1, %%mm0 \n\ + movq %%mm0, -8("EDI","EAX") \n\ + subl $8, %%eax \n\ + jnz 1b \n\ + 2: \n\ + emms" + : /* no outputs */ + : "S" (src1), "d" (src2), "D" (dest), "a" (bytes & ~7)); + } + if (UNLIKELY(bytes & 7)) { + average(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7), + bytes & 7); + } +} + +#endif /* HAVE_ASM_SSE2 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Initialization routine. */ + +int ac_average_init(int accel) +{ + average_ptr = average; + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) + if (HAS_ACCEL(accel, AC_MMX)) + average_ptr = average_mmx; +#endif +#if defined(HAVE_ASM_SSE) && defined(ARCH_X86) + if (HAS_ACCEL(accel, AC_SSE)) + average_ptr = average_sse; +#endif +#if defined(HAVE_ASM_SSE2) + if (HAS_ACCEL(accel, AC_SSE2)) + average_ptr = average_sse2; +#endif + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/img_internal.h b/branches/V-1.5.3/veejay-server/aclib/img_internal.h new file mode 100644 index 00000000..153a2fb6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/img_internal.h @@ -0,0 +1,40 @@ +/* + * img_internal.h - imgconvert internal use header + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#ifndef ACLIB_IMG_INTERNAL_H +#define ACLIB_IMG_INTERNAL_H + +/* Type of a conversion function */ +typedef int (*ConversionFunc)(uint8_t **src, uint8_t **dest, + int width, int height); + +/* Function to register a conversion */ +extern int register_conversion(ImageFormat srcfmt, ImageFormat destfmt, + ConversionFunc function); + +/* Initialization routines */ +extern int ac_imgconvert_init(int accel); +extern int ac_imgconvert_init_yuv_planar(int accel); +extern int ac_imgconvert_init_yuv_packed(int accel); +extern int ac_imgconvert_init_yuv_mixed(int accel); +extern int ac_imgconvert_init_yuv_rgb(int accel); +extern int ac_imgconvert_init_rgb_packed(int accel); + +#endif /* ACLIB_IMG_INTERNAL_H */ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/img_rgb_packed.c b/branches/V-1.5.3/veejay-server/aclib/img_rgb_packed.c new file mode 100644 index 00000000..1c987130 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/img_rgb_packed.c @@ -0,0 +1,1105 @@ +/* + * img_rgb_packed.c - RGB packed image format conversion routines + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "imgconvert.h" +#include "img_internal.h" + +/*************************************************************************/ +/*************************************************************************/ + +/* Standard C implementations */ + +/*************************************************************************/ + +/* Identity transformations, all work when src==dest */ + +static int rgb_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height*3); + return 1; +} + +static int rgba_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height*4); + return 1; +} + +static int gray8_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + return 1; +} + +/*************************************************************************/ + +/* Conversions between various 32-bit formats, all usable when src==dest */ + +/* RGBA<->ABGR and ARGB<->BGRA: reverse byte order */ +static int rgba_swapall(uint8_t **src, uint8_t **dest, int width, int height) +{ + uint32_t *srcp = (uint32_t *)src[0]; + uint32_t *destp = (uint32_t *)dest[0]; + int i; + for (i = 0; i < width*height; i++) { + /* This shortcut works regardless of CPU endianness */ + destp[i] = srcp[i] >> 24 + | (srcp[i] & 0x00FF0000) >> 8 + | (srcp[i] & 0x0000FF00) << 8 + | srcp[i] << 24; + } + return 1; +} + +/* RGBA<->BGRA: swap bytes 0 and 2 */ +static int rgba_swap02(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + uint8_t tmp = src[0][i*4+2]; + dest[0][i*4+2] = src[0][i*4 ]; + dest[0][i*4 ] = tmp; + dest[0][i*4+1] = src[0][i*4+1]; + dest[0][i*4+3] = src[0][i*4+3]; + } + return 1; +} + +/* ARGB<->ABGR: swap bytes 1 and 3 */ +static int rgba_swap13(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + uint8_t tmp = src[0][i*4+3]; + dest[0][i*4+3] = src[0][i*4+1]; + dest[0][i*4+1] = tmp; + dest[0][i*4 ] = src[0][i*4 ]; + dest[0][i*4+2] = src[0][i*4+2]; + } + return 1; +} + +/* RGBA->ARGB and BGRA->ABGR: alpha moves from byte 3 to byte 0 */ +static int rgba_alpha30(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + uint8_t tmp = src[0][i*4+3]; + dest[0][i*4+3] = src[0][i*4+2]; + dest[0][i*4+2] = src[0][i*4+1]; + dest[0][i*4+1] = src[0][i*4 ]; + dest[0][i*4 ] = tmp; + } + return 1; +} + +/* ARGB->RGBA and ABGR->BGRA: alpha moves from byte 0 to byte 3 */ +static int rgba_alpha03(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + uint8_t tmp = src[0][i*4 ]; + dest[0][i*4 ] = src[0][i*4+1]; + dest[0][i*4+1] = src[0][i*4+2]; + dest[0][i*4+2] = src[0][i*4+3]; + dest[0][i*4+3] = tmp; + } + return 1; +} + +/*************************************************************************/ + +static int rgb24_bgr24(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*3 ] = src[0][i*3+2]; + dest[0][i*3+1] = src[0][i*3+1]; + dest[0][i*3+2] = src[0][i*3 ]; + } + return 1; +} + +static int rgb24_rgba32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*4 ] = src[0][i*3 ]; + dest[0][i*4+1] = src[0][i*3+1]; + dest[0][i*4+2] = src[0][i*3+2]; + dest[0][i*4+3] = 0; + } + return 1; +} + +static int rgb24_abgr32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*4 ] = 0; + dest[0][i*4+1] = src[0][i*3+2]; + dest[0][i*4+2] = src[0][i*3+1]; + dest[0][i*4+3] = src[0][i*3 ]; + } + return 1; +} + +static int rgb24_argb32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*4 ] = 0; + dest[0][i*4+1] = src[0][i*3 ]; + dest[0][i*4+2] = src[0][i*3+1]; + dest[0][i*4+3] = src[0][i*3+2]; + } + return 1; +} + +static int rgb24_bgra32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*4 ] = src[0][i*3+2]; + dest[0][i*4+1] = src[0][i*3+1]; + dest[0][i*4+2] = src[0][i*3 ]; + dest[0][i*4+3] = 0; + } + return 1; +} + +static int rgb24_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + /* Use the Y part of a YUV transformation, scaled to 0..255 */ + int r = src[0][i*3 ]; + int g = src[0][i*3+1]; + int b = src[0][i*3+2]; + dest[0][i] = (19595*r + 38470*g + 7471*b + 32768) >> 16; + } + return 1; +} + +static int bgr24_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + /* Use the Y part of a YUV transformation, scaled to 0..255 */ + int r = src[0][i*3+2]; + int g = src[0][i*3+1]; + int b = src[0][i*3 ]; + dest[0][i] = (19595*r + 38470*g + 7471*b + 32768) >> 16; + } + return 1; +} + +/*************************************************************************/ + +static int rgba32_rgb24(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*3 ] = src[0][i*4 ]; + dest[0][i*3+1] = src[0][i*4+1]; + dest[0][i*3+2] = src[0][i*4+2]; + } + return 1; +} + +static int bgra32_rgb24(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*3 ] = src[0][i*4+2]; + dest[0][i*3+1] = src[0][i*4+1]; + dest[0][i*3+2] = src[0][i*4 ]; + } + return 1; +} + +static int rgba32_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + /* Use the Y part of a YUV transformation, scaled to 0..255 */ + int r = src[0][i*4 ]; + int g = src[0][i*4+1]; + int b = src[0][i*4+2]; + dest[0][i] = (19595*r + 38470*g + 7471*b + 32768) >> 16; + } + return 1; +} + +static int bgra32_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + /* Use the Y part of a YUV transformation, scaled to 0..255 */ + int r = src[0][i*4+2]; + int g = src[0][i*4+1]; + int b = src[0][i*4 ]; + dest[0][i] = (19595*r + 38470*g + 7471*b + 32768) >> 16; + } + return 1; +} + +/*************************************************************************/ + +static int argb32_rgb24(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*3 ] = src[0][i*4+1]; + dest[0][i*3+1] = src[0][i*4+2]; + dest[0][i*3+2] = src[0][i*4+3]; + } + return 1; +} + +static int abgr32_rgb24(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*3 ] = src[0][i*4+3]; + dest[0][i*3+1] = src[0][i*4+2]; + dest[0][i*3+2] = src[0][i*4+1]; + } + return 1; +} + +static int argb32_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + /* Use the Y part of a YUV transformation, scaled to 0..255 */ + int r = src[0][i*4+1]; + int g = src[0][i*4+2]; + int b = src[0][i*4+3]; + dest[0][i] = (19595*r + 38470*g + 7471*b + 32768) >> 16; + } + return 1; +} + +static int abgr32_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + /* Use the Y part of a YUV transformation, scaled to 0..255 */ + int r = src[0][i*4+3]; + int g = src[0][i*4+2]; + int b = src[0][i*4+1]; + dest[0][i] = (19595*r + 38470*g + 7471*b + 32768) >> 16; + } + return 1; +} + +/*************************************************************************/ + +static int gray8_rgb24(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*3 ] = src[0][i]; + dest[0][i*3+1] = src[0][i]; + dest[0][i*3+2] = src[0][i]; + } + return 1; +} + +static int gray8_rgba32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*4 ] = src[0][i]; + dest[0][i*4+1] = src[0][i]; + dest[0][i*4+2] = src[0][i]; + dest[0][i*4+3] = 0; + } + return 1; +} + +static int gray8_argb32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*4 ] = 0; + dest[0][i*4+1] = src[0][i]; + dest[0][i*4+2] = src[0][i]; + dest[0][i*4+3] = src[0][i]; + } + return 1; +} + +/*************************************************************************/ +/*************************************************************************/ + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + +#define DEFINE_MASK_DATA +#include "img_x86_common.h" + +/*************************************************************************/ + +/* Basic assembly routines */ + +/* RGBA<->ABGR and ARGB<->BGRA: reverse byte order */ +static int rgba_swapall_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_REV32_X86(width*height); + return 1; +} + +/* RGBA<->BGRA: swap bytes 0 and 2 */ +static int rgba_swap02_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_02_X86(width*height); + return 1; +} + +/* ARGB<->ABGR: swap bytes 1 and 3 */ +static int rgba_swap13_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_13_X86(width*height); + return 1; +} + +/* RGBA->ARGB and BGRA->ABGR: alpha moves from byte 3 to byte 0 */ +static int rgba_alpha30_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROL32_X86(width*height); + return 1; +} + +/* ARGB->RGBA and ABGR->BGRA: alpha moves from byte 0 to byte 3 */ +static int rgba_alpha03_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROR32_X86(width*height); + return 1; +} + +/*************************************************************************/ + +/* MMX routines */ + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */ + +/* RGBA<->ABGR and ARGB<->BGRA: reverse byte order */ +static int rgba_swapall_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_REV32_MMX(width*height); + return 1; +} + +/* RGBA<->BGRA: swap bytes 0 and 2 */ +static int rgba_swap02_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_02_MMX(width*height); + return 1; +} + +/* ARGB<->ABGR: swap bytes 1 and 3 */ +static int rgba_swap13_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_13_MMX(width*height); + return 1; +} + +/* RGBA->ARGB and BGRA->ABGR: alpha moves from byte 3 to byte 0 */ +static int rgba_alpha30_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROL32_MMX(width*height); + return 1; +} + +/* ARGB->RGBA and ABGR->BGRA: alpha moves from byte 0 to byte 3 */ +static int rgba_alpha03_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROR32_MMX(width*height); + return 1; +} + +#endif /* HAVE_ASM_MMX && ARCH_X86 */ + +/*************************************************************************/ + +/* SSE2 routines */ + +#if defined(HAVE_ASM_SSE2) + +static const struct { uint32_t n[4]; } __attribute__((aligned(16))) rgb_bgr_data = {{ + 0xFF0000FF, 0x00FF0000, 0x0000FF00, 0x00000000 +}}; + +#define SHIFT_RBSWAP \ + "movdqa %%xmm6, %%xmm2 # XMM2: low bytes mask \n\ + pand %%xmm0, %%xmm2 # XMM2: R/B bytes \n\ + pshuflw $0xB1, %%xmm2, %%xmm2 # XMM2: swap R and B (low quad) \n\ + pand %%xmm7, %%xmm0 # XMM0: G bytes \n\ + pshufhw $0xB1, %%xmm2, %%xmm2 # XMM2: swap R and B (high quad)\n\ + por %%xmm2, %%xmm0 # XMM0: data now in BGRA32 \n" + +#define SHIFT_AFIRST \ + "pslldq $1, %%xmm0 # XMM0: move A first \n" + +#define SHIFT_ALAST \ + "psrldq $1, %%xmm0 # XMM0: move A last \n" + +#define RGB24TO32(ROFS,GOFS,BOFS,AOFS,SHIFT) \ + asm("pcmpeqd %%xmm5, %%xmm5 \n\ + movdqa %%xmm5, %%xmm6 \n\ + psrldq $13, %%xmm5 # XMM5: 24-bit mask \n\ + movdqa %%xmm6, %%xmm7 \n\ + psrlw $8, %%xmm6 # XMM6: low bytes mask \n\ + psllw $8, %%xmm7 # XMM7: high bytes mask \n"\ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "lea ("ECX","ECX",2),"EDX" \n\ + movb -3("ESI","EDX"), %%al \n\ + movb %%al, ("#ROFS"-4)("EDI","ECX",4) \n\ + movb -2("ESI","EDX"), %%al \n\ + movb %%al, ("#GOFS"-4)("EDI","ECX",4) \n\ + movb -1("ESI","EDX"), %%al \n\ + movb %%al, ("#BOFS"-4)("EDI","ECX",4) \n\ + movb $0, ("#AOFS"-4)("EDI","ECX",4)", \ + /* main_loop */ \ + "lea ("ECX","ECX",2),"EDX" \n\ + # We can't just movdqu, because we might run over the edge \n\ + movd -12("ESI","EDX"), %%xmm1 \n\ + movq -8("ESI","EDX"), %%xmm0 \n\ + pshufd $0xD3, %%xmm0, %%xmm0 # shift left by 4 bytes \n\ + por %%xmm1, %%xmm0 # XMM0: original RGB24 data \n\ + pshufd $0xF3, %%xmm5, %%xmm2 # XMM2: pixel 1 mask \n\ + movdqa %%xmm5, %%xmm1 # XMM1: pixel 0 mask \n\ + pshufd $0xCF, %%xmm5, %%xmm3 # XMM3: pixel 2 mask \n\ + pand %%xmm0, %%xmm1 # XMM1: pixel 0 \n\ + pslldq $1, %%xmm0 \n\ + pand %%xmm0, %%xmm2 # XMM2: pixel 1 \n\ + pshufd $0x3F, %%xmm5, %%xmm4 # XMM4: pixel 3 mask \n\ + por %%xmm2, %%xmm1 # XMM1: pixels 0 and 1 \n\ + pslldq $1, %%xmm0 \n\ + pand %%xmm0, %%xmm3 # XMM3: pixel 2 \n\ + por %%xmm3, %%xmm1 # XMM1: pixels 0, 1, and 2 \n\ + pslldq $1, %%xmm0 \n\ + pand %%xmm4, %%xmm0 # XMM0: pixel 3 \n\ + por %%xmm1, %%xmm0 # XMM0: RGBA32 data \n\ + "SHIFT" # shift bytes to target position\n\ + movdqu %%xmm0, -16("EDI","ECX",4)", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), \ + "d" (&rgb_bgr_data), "m" (rgb_bgr_data) \ + : "eax"); + +#define RGB32TO24(ROFS,GOFS,BOFS,AOFS,SHIFT) \ + asm("pcmpeqd %%xmm5, %%xmm5 \n\ + movdqa %%xmm5, %%xmm6 \n\ + psrldq $13, %%xmm5 # 24-bit mask \n\ + movdqa %%xmm6, %%xmm7 \n\ + psrlw $8, %%xmm6 # low bytes mask \n\ + psllw $8, %%xmm7 # high bytes mask \n"\ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "lea ("ECX","ECX",2),"EDX" \n\ + movb ("#ROFS"-4)("ESI","ECX",4), %%al \n\ + movb %%al, -3("EDI","EDX") \n\ + movb ("#GOFS"-4)("ESI","ECX",4), %%al \n\ + movb %%al, -2("EDI","EDX") \n\ + movb ("#BOFS"-4)("ESI","ECX",4), %%al \n\ + movb %%al, -1("EDI","EDX")", \ + /* main_loop */ \ + "lea ("ECX","ECX",2),"EDX" \n\ + movdqu -16("ESI","ECX",4), %%xmm0 \n\ + "SHIFT" # shift source data to RGBA \n\ + pshufd $0xF3, %%xmm5, %%xmm1 # XMM1: pixel 1 mask \n\ + pshufd $0xCF, %%xmm5, %%xmm2 # XMM2: pixel 2 mask \n\ + pshufd $0x3F, %%xmm5, %%xmm3 # XMM3: pixel 3 mask \n\ + pand %%xmm0, %%xmm3 # XMM3: pixel 3 \n\ + psrldq $1, %%xmm3 \n\ + pand %%xmm0, %%xmm2 # XMM2: pixel 2 \n\ + por %%xmm3, %%xmm2 # XMM2: pixels 2 and 3 \n\ + psrldq $1, %%xmm2 \n\ + pand %%xmm0, %%xmm1 # XMM1: pixel 1 \n\ + pand %%xmm5, %%xmm0 # XMM0: pixel 0 \n\ + por %%xmm2, %%xmm1 # XMM1: pixels 1, 2, and 3 \n\ + psrldq $1, %%xmm1 \n\ + por %%xmm1, %%xmm0 # XMM0: RGB24 data \n\ + # We can't just movdqu, because we might run over the edge \n\ + movd %%xmm0, -12("EDI","EDX") # store low 4 bytes \n\ + pshufd $0xF9, %%xmm0, %%xmm0 # shift right 4 bytes \n\ + movq %%xmm0, -8("EDI","EDX") # store high 8 bytes \n",\ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), \ + "d" (&rgb_bgr_data), "m" (rgb_bgr_data) \ + : "eax"); + + +/* RGBA<->ABGR and ARGB<->BGRA: reverse byte order */ +static int rgba_swapall_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_REV32_SSE2(width*height); + return 1; +} + +/* RGBA<->BGRA: swap bytes 0 and 2 */ +static int rgba_swap02_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_02_SSE2(width*height); + return 1; +} + +/* ARGB<->ABGR: swap bytes 1 and 3 */ +static int rgba_swap13_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_13_SSE2(width*height); + return 1; +} + +/* RGBA->ARGB and BGRA->ABGR: alpha moves from byte 3 to byte 0 */ +static int rgba_alpha30_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROL32_SSE2(width*height); + return 1; +} + +/* ARGB->RGBA and ABGR->BGRA: alpha moves from byte 0 to byte 3 */ +static int rgba_alpha03_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROR32_SSE2(width*height); + return 1; +} + +/* RGB<->BGR */ +static int rgb24_bgr24_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa ("EDX"), %%xmm5 # byte 0 mask \n\ + pshufd $0xD2, %%xmm5, %%xmm6 # byte 1 mask \n\ + pshufd $0xC9, %%xmm5, %%xmm7 # byte 2 mask \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 4, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ + "lea ("ECX","ECX",2),"EDX" \n\ + movb -3("ESI","EDX"), %%al \n\ + movb -2("ESI","EDX"), %%ah \n\ + movb %%ah, -2("EDI","EDX") \n\ + movb -1("ESI","EDX"), %%ah \n\ + movb %%ah, -3("EDI","EDX") \n\ + movb %%al, -1("EDI","EDX")", + /* main_loop */ + "lea ("ECX","ECX",2),"EDX" \n\ + # We can't just movdqu, because we might run over the edge \n\ + movd -12("ESI","EDX"), %%xmm1 \n\ + movq -8("ESI","EDX"), %%xmm0 \n\ + pshufd $0xD3, %%xmm0, %%xmm0 # shift left by 4 bytes \n\ + por %%xmm1, %%xmm0 # XMM0: original data \n\ + movdqa %%xmm5, %%xmm2 \n\ + movdqa %%xmm6, %%xmm3 \n\ + movdqa %%xmm7, %%xmm4 \n\ + pand %%xmm0, %%xmm2 # XMM2: byte 0 \n\ + pslldq $2, %%xmm2 # shift to byte 2 position \n\ + pand %%xmm0, %%xmm3 # XMM3: byte 1 \n\ + pand %%xmm0, %%xmm4 # XMM4: byte 2 \n\ + psrldq $2, %%xmm4 # shift to byte 0 position \n\ + por %%xmm2, %%xmm3 \n\ + por %%xmm4, %%xmm3 # XMM3: reversed data \n\ + movd %%xmm3, -12("EDI","EDX") # avoid running over the edge \n\ + pshufd $0xF9, %%xmm3, %%xmm3 # shift right by 4 bytes \n\ + movq %%xmm3, -8("EDI","EDX")", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "d" (&rgb_bgr_data), "m" (rgb_bgr_data) + : "eax"); + return 1; +} + +/* RGB->RGBA */ +static int rgb24_rgba32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB24TO32(0,1,2,3, ""); + return 1; +} + +/* RGB->ABGR */ +static int rgb24_abgr32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB24TO32(3,2,1,0, SHIFT_RBSWAP SHIFT_AFIRST); + return 1; +} + +/* RGB->ARGB */ +static int rgb24_argb32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB24TO32(1,2,3,0, SHIFT_AFIRST); + return 1; +} + +/* RGB->BGRA */ +static int rgb24_bgra32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB24TO32(2,1,0,3, SHIFT_RBSWAP); + return 1; +} + +/* RGBA->RGB */ +static int rgba32_rgb24_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB32TO24(0,1,2,3, ""); + return 1; +} + +/* ABGR->RGB */ +static int abgr32_rgb24_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB32TO24(3,2,1,0, SHIFT_ALAST SHIFT_RBSWAP); + return 1; +} + +/* ARGB->RGB */ +static int argb32_rgb24_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB32TO24(1,2,3,0, SHIFT_ALAST); + return 1; +} + +/* BGRA->RGB */ +static int bgra32_rgb24_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + RGB32TO24(2,1,0,3, SHIFT_RBSWAP); + return 1; +} + +/*************************************************************************/ + +#define R_GRAY 19595 +#define G_GRAY 38470 +#define B_GRAY 7471 +#define INIT_GRAY8 \ + "pxor %%xmm4, %%xmm4 # XMM4: all 0's \n\ + movl %3, %%eax \n\ + movd %%eax, %%xmm5 \n\ + pshuflw $0x00, %%xmm5, %%xmm5 \n\ + pshufd $0x00, %%xmm5, %%xmm5 # XMM5: R->gray constant \n\ + movl %4, %%eax \n\ + movd %%eax, %%xmm6 \n\ + pshuflw $0x00, %%xmm6, %%xmm6 \n\ + pshufd $0x00, %%xmm6, %%xmm6 # XMM6: G->gray constant \n\ + movl %5, %%eax \n\ + movd %%eax, %%xmm7 \n\ + pshuflw $0x00, %%xmm7, %%xmm7 \n\ + pshufd $0x00, %%xmm7, %%xmm7 # XMM7: B->gray constant \n\ + pcmpeqd %%xmm3, %%xmm3 \n\ + psllw $15, %%xmm3 \n\ + psrlw $8, %%xmm3 # XMM3: 0x0080*8 (for rounding) \n" +#define SINGLE_GRAY8(idx,ofsR,ofsG,ofsB) \ + "movzbl "#ofsR"("ESI","idx"), %%eax # retrieve red byte \n\ + imull %3, %%eax # multiply by red->gray factor \n\ + movzbl "#ofsG"("ESI","idx"), %%edx # retrieve green byte \n\ + imull %4, %%edx # multiply by green->gray factor\n\ + addl %%edx, %%eax # add to total \n\ + movzbl "#ofsB"("ESI","idx"), %%edx # retrieve blue byte \n\ + imull %5, %%edx # multiply by blue->gray factor \n\ + addl %%edx, %%eax # add to total \n\ + addl $0x8000, %%eax # round \n\ + shrl $16, %%eax # shift back down \n\ + movb %%al, -1("EDI","ECX") # and store \n" +#define STORE_GRAY8 \ + "psllw $8, %%xmm0 # XMM0: add 8 bits of precision \n\ + pmulhuw %%xmm5, %%xmm0 # XMM0: r7 r6 r5 r4 r3 r2 r1 r0 \n\ + psllw $8, %%xmm1 # XMM1: add 8 bits of precision \n\ + pmulhuw %%xmm6, %%xmm1 # XMM1: g7 g6 g5 g4 g3 g2 g1 g0 \n\ + paddw %%xmm3, %%xmm0 # XMM0: add rounding constant \n\ + psllw $8, %%xmm2 # XMM2: add 8 bits of precision \n\ + pmulhuw %%xmm7, %%xmm2 # XMM2: b7 b6 b5 b4 b3 b2 b1 b0 \n\ + paddw %%xmm1, %%xmm0 # XMM0: add green part \n\ + paddw %%xmm2, %%xmm0 # XMM0: add blue part \n\ + psrlw $8, %%xmm0 # XMM0: shift back to bytes \n\ + packuswb %%xmm4, %%xmm0 # XMM0: gray7..gray0 packed \n\ + movq %%xmm0, -8("EDI","ECX") \n" + +#define ASM_RGB24_GRAY(ofsR,ofsG,ofsB,load) \ + asm(INIT_GRAY8 \ + "push "EBX" \n\ + lea ("ECX","ECX",2),"EBX" \n"\ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ SINGLE_GRAY8(EBX, ofsR,ofsG,ofsB) "subl $3, %%ebx;",\ + /* main_loop */ load(4) STORE_GRAY8 "subl $24, %%ebx;", \ + /* emms */ "emms") \ + "pop "EBX \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), \ + "i" (R_GRAY), "i" (G_GRAY), "i" (B_GRAY) \ + : "eax", "edx") + +#define ASM_RGB32_GRAY(ofsR,ofsG,ofsB,load) \ + asm(INIT_GRAY8 \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ SINGLE_GRAY8(ECX",4", ofsR,ofsG,ofsB), \ + /* main_loop */ load(4) STORE_GRAY8, \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), \ + "i" (R_GRAY), "i" (G_GRAY), "i" (B_GRAY) \ + : "eax", "edx") + + +static int rgb24_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_RGB24_GRAY(-3,-2,-1, SSE2_LOAD_RGB24); + return 1; +} + +static int bgr24_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_RGB24_GRAY(-1,-2,-3, SSE2_LOAD_BGR24); + return 1; +} + +static int rgba32_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_RGB32_GRAY(-4,-3,-2, SSE2_LOAD_RGBA32); + return 1; +} + +static int bgra32_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_RGB32_GRAY(-2,-3,-4, SSE2_LOAD_BGRA32); + return 1; +} + +static int argb32_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_RGB32_GRAY(-3,-2,-1, SSE2_LOAD_ARGB32); + return 1; +} + +static int abgr32_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_RGB32_GRAY(-1,-2,-3, SSE2_LOAD_ABGR32); + return 1; +} + +/*************************************************************************/ + +static int gray8_rgb24_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("# Store all 0's in XMM4 \n\ + pxor %%xmm4, %%xmm4 \n\ + # Generate mask in XMM7 to select bytes 0,3,6,9 of an XMM register\n\ + pcmpeqd %%xmm7, %%xmm7 # XMM7: all 1's \n\ + psrlw $8, %%xmm7 # XMM7: 0x00FF * 8 \n\ + pcmpeqd %%xmm6, %%xmm6 # XMM6: all 1's \n\ + psllw $8, %%xmm6 # XMM6: 0xFF00 * 8 \n\ + pslldq $8, %%xmm6 \n\ + psrldq $8, %%xmm7 \n\ + por %%xmm6, %%xmm7 # XMM7: 0xFF00*4, 0x00FF*4 \n\ + pshufd $0xCC, %%xmm7, %%xmm7 # XMM7: {0xFF00*2, 0x00FF*2} * 2\n\ + pshuflw $0xC0, %%xmm7, %%xmm7 # XMM7.l: FF0000FF00FF00FF \n\ + psrldq $4, %%xmm7 # XMM7: 0x00000000FF00FF00 \n\ + # 00FF00FFFF0000FF \n\ + pshufd $0xEC, %%xmm7, %%xmm7 # XMM7: 0x00000000FF00FF00 \n\ + # 00000000FF0000FF \n\ + pshuflw $0x24, %%xmm7, %%xmm7 # XMM7.l: 00FF0000FF0000FF \n\ + pshufhw $0xFC, %%xmm7, %%xmm7 # XMM7.h: 000000000000FF00 \n\ + # Load ECX*3 into EDX ahead of time \n\ + lea ("ECX","ECX",2), "EDX" \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 4, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movb -1("ESI","ECX"), %%al # retrieve gray byte \n\ + movb %%al, -3("EDI","EDX") # and store 3 times \n\ + movb %%al, -2("EDI","EDX") \n\ + movb %%al, -1("EDI","EDX") \n\ + subl $3, %%edx \n", + /* main_loop */ "\ + movd -4("ESI","ECX"), %%xmm0 # XMM0: G3..G0 \n\ + pshufd $0xCC, %%xmm0, %%xmm0 # XMM0: {0,0,0,0,G3..G0} * 2 \n\ + pshuflw $0x50, %%xmm0, %%xmm0 # X0.l: G3 G2 G3 G2 G1 G0 G1 G0 \n\ + pshufhw $0x55, %%xmm0, %%xmm0 # X0.h: G3 G2 G3 G2 G3 G2 G3 G2 \n\ + pand %%xmm7, %%xmm0 # XMM0: ------3--2--1--0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: ------3--2--1--0 \n\ + pslldq $1, %%xmm1 # XMM1: -----3--2--1--0- \n\ + movdqa %%xmm0, %%xmm2 # XMM2: ------3--2--1--0 \n\ + pslldq $2, %%xmm2 # XMM2: ----3--2--1--0-- \n\ + por %%xmm1, %%xmm0 # XMM0: -----33-22-11-00 \n\ + por %%xmm2, %%xmm0 # XMM0: ----333222111000 \n\ + movd %%xmm0, -12("EDI","EDX") \n\ + pshufd $0xC9, %%xmm0, %%xmm0 \n\ + movq %%xmm0, -8("EDI","EDX") \n\ + subl $12, %%edx \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height) + : "eax", "edx"); + return 1; +} + +static int gray8_rgba32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("pxor %%xmm4, %%xmm4 # XMM4: all 0's \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 4, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movb -1("ESI","ECX"), %%al # retrieve gray byte \n\ + movb %%al, -4("EDI","ECX",4) # and store 3 times \n\ + movb %%al, -3("EDI","ECX",4) \n\ + movb %%al, -2("EDI","ECX",4) \n\ + movb $0, -1("EDI","ECX",4) # clear A byte \n", + /* main_loop */ "\ + movd -4("ESI","ECX"), %%xmm0 # XMM0: 00 00 00 00 G3 G2 G1 G0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: 00 00 00 00 G3 G2 G1 G0 \n\ + punpcklbw %%xmm0, %%xmm0 # XMM0: G3 G3 G2 G2 G1 G1 G0 G0 \n\ + punpcklbw %%xmm4, %%xmm1 # XMM1: 00 G3 00 G2 00 G1 00 G0 \n\ + punpcklbw %%xmm1, %%xmm0 # XMM0: 0GGG3 0GGG2 0GGG1 0GGG0 \n\ + movdqu %%xmm0, -16("EDI","ECX",4) \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height) + : "eax"); + return 1; +} + +static int gray8_argb32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("pxor %%xmm4, %%xmm4 # XMM4: all 0's \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 4, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movb -1("ESI","ECX"), %%al # retrieve gray byte \n\ + movb %%al, -3("EDI","ECX",4) # and store 3 times \n\ + movb %%al, -2("EDI","ECX",4) \n\ + movb %%al, -1("EDI","ECX",4) \n\ + movb $0, -4("EDI","ECX",4) # clear A byte \n", + /* main_loop */ "\ + movd -4("ESI","ECX"), %%xmm0 # XMM0: 00 00 00 00 G3 G2 G1 G0 \n\ + movdqa %%xmm4, %%xmm1 # XMM1: 00 00 00 00 00 00 00 00 \n\ + punpcklbw %%xmm0, %%xmm1 # XMM1: G3 00 G2 00 G1 00 G0 00 \n\ + punpcklbw %%xmm0, %%xmm0 # XMM0: G3 G3 G2 G2 G1 G1 G0 G0 \n\ + punpcklbw %%xmm0, %%xmm1 # XMM0: GGG03 GGG02 GGG01 GGG00 \n\ + movdqu %%xmm1, -16("EDI","ECX",4) \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height) + : "eax"); + return 1; +} + +#endif /* HAVE_ASM_SSE2 */ + +/*************************************************************************/ + +#endif /* ARCH_X86 || ARCH_X86_64 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Initialization */ + +int ac_imgconvert_init_rgb_packed(int accel) +{ + if (!register_conversion(IMG_RGB24, IMG_RGB24, rgb_copy) + || !register_conversion(IMG_RGB24, IMG_BGR24, rgb24_bgr24) + || !register_conversion(IMG_RGB24, IMG_RGBA32, rgb24_rgba32) + || !register_conversion(IMG_RGB24, IMG_ABGR32, rgb24_abgr32) + || !register_conversion(IMG_RGB24, IMG_ARGB32, rgb24_argb32) + || !register_conversion(IMG_RGB24, IMG_BGRA32, rgb24_bgra32) + || !register_conversion(IMG_RGB24, IMG_GRAY8, rgb24_gray8) + + || !register_conversion(IMG_BGR24, IMG_BGR24, rgb_copy) + || !register_conversion(IMG_BGR24, IMG_RGB24, rgb24_bgr24) + || !register_conversion(IMG_BGR24, IMG_RGBA32, rgb24_bgra32) + || !register_conversion(IMG_BGR24, IMG_ABGR32, rgb24_argb32) + || !register_conversion(IMG_BGR24, IMG_ARGB32, rgb24_abgr32) + || !register_conversion(IMG_BGR24, IMG_BGRA32, rgb24_rgba32) + || !register_conversion(IMG_BGR24, IMG_GRAY8, bgr24_gray8) + + || !register_conversion(IMG_RGBA32, IMG_RGB24, rgba32_rgb24) + || !register_conversion(IMG_RGBA32, IMG_BGR24, bgra32_rgb24) + || !register_conversion(IMG_RGBA32, IMG_RGBA32, rgba_copy) + || !register_conversion(IMG_RGBA32, IMG_ABGR32, rgba_swapall) + || !register_conversion(IMG_RGBA32, IMG_ARGB32, rgba_alpha30) + || !register_conversion(IMG_RGBA32, IMG_BGRA32, rgba_swap02) + || !register_conversion(IMG_RGBA32, IMG_GRAY8, rgba32_gray8) + + || !register_conversion(IMG_ABGR32, IMG_RGB24, abgr32_rgb24) + || !register_conversion(IMG_ABGR32, IMG_BGR24, argb32_rgb24) + || !register_conversion(IMG_ABGR32, IMG_RGBA32, rgba_swapall) + || !register_conversion(IMG_ABGR32, IMG_ABGR32, rgba_copy) + || !register_conversion(IMG_ABGR32, IMG_ARGB32, rgba_swap13) + || !register_conversion(IMG_ABGR32, IMG_BGRA32, rgba_alpha03) + || !register_conversion(IMG_ABGR32, IMG_GRAY8, abgr32_gray8) + + || !register_conversion(IMG_ARGB32, IMG_RGB24, argb32_rgb24) + || !register_conversion(IMG_ARGB32, IMG_BGR24, abgr32_rgb24) + || !register_conversion(IMG_ARGB32, IMG_RGBA32, rgba_alpha03) + || !register_conversion(IMG_ARGB32, IMG_ABGR32, rgba_swap13) + || !register_conversion(IMG_ARGB32, IMG_ARGB32, rgba_copy) + || !register_conversion(IMG_ARGB32, IMG_BGRA32, rgba_swapall) + || !register_conversion(IMG_ARGB32, IMG_GRAY8, argb32_gray8) + + || !register_conversion(IMG_BGRA32, IMG_RGB24, bgra32_rgb24) + || !register_conversion(IMG_BGRA32, IMG_BGR24, rgba32_rgb24) + || !register_conversion(IMG_BGRA32, IMG_RGBA32, rgba_swap02) + || !register_conversion(IMG_BGRA32, IMG_ABGR32, rgba_alpha30) + || !register_conversion(IMG_BGRA32, IMG_ARGB32, rgba_swapall) + || !register_conversion(IMG_BGRA32, IMG_BGRA32, rgba_copy) + || !register_conversion(IMG_BGRA32, IMG_GRAY8, bgra32_gray8) + + || !register_conversion(IMG_GRAY8, IMG_RGB24, gray8_rgb24) + || !register_conversion(IMG_GRAY8, IMG_BGR24, gray8_rgb24) + || !register_conversion(IMG_GRAY8, IMG_RGBA32, gray8_rgba32) + || !register_conversion(IMG_GRAY8, IMG_ABGR32, gray8_argb32) + || !register_conversion(IMG_GRAY8, IMG_ARGB32, gray8_argb32) + || !register_conversion(IMG_GRAY8, IMG_BGRA32, gray8_rgba32) + || !register_conversion(IMG_GRAY8, IMG_GRAY8, gray8_copy) + ) { + return 0; + } + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + + if (accel & (AC_IA32ASM | AC_AMD64ASM)) { + if (!register_conversion(IMG_RGBA32, IMG_ABGR32, rgba_swapall_x86) + || !register_conversion(IMG_RGBA32, IMG_ARGB32, rgba_alpha30_x86) + || !register_conversion(IMG_RGBA32, IMG_BGRA32, rgba_swap02_x86) + + || !register_conversion(IMG_ABGR32, IMG_RGBA32, rgba_swapall_x86) + || !register_conversion(IMG_ABGR32, IMG_ARGB32, rgba_swap13_x86) + || !register_conversion(IMG_ABGR32, IMG_BGRA32, rgba_alpha03_x86) + + || !register_conversion(IMG_ARGB32, IMG_RGBA32, rgba_alpha03_x86) + || !register_conversion(IMG_ARGB32, IMG_ABGR32, rgba_swap13_x86) + || !register_conversion(IMG_ARGB32, IMG_BGRA32, rgba_swapall_x86) + + || !register_conversion(IMG_BGRA32, IMG_RGBA32, rgba_swap02_x86) + || !register_conversion(IMG_BGRA32, IMG_ABGR32, rgba_alpha30_x86) + || !register_conversion(IMG_BGRA32, IMG_ARGB32, rgba_swapall_x86) + ) { + return 0; + } + } + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) + if (accel & AC_MMX) { + if (!register_conversion(IMG_RGBA32, IMG_ABGR32, rgba_swapall_mmx) + || !register_conversion(IMG_RGBA32, IMG_ARGB32, rgba_alpha30_mmx) + || !register_conversion(IMG_RGBA32, IMG_BGRA32, rgba_swap02_mmx) + + || !register_conversion(IMG_ABGR32, IMG_RGBA32, rgba_swapall_mmx) + || !register_conversion(IMG_ABGR32, IMG_ARGB32, rgba_swap13_mmx) + || !register_conversion(IMG_ABGR32, IMG_BGRA32, rgba_alpha03_mmx) + + || !register_conversion(IMG_ARGB32, IMG_RGBA32, rgba_alpha03_mmx) + || !register_conversion(IMG_ARGB32, IMG_ABGR32, rgba_swap13_mmx) + || !register_conversion(IMG_ARGB32, IMG_BGRA32, rgba_swapall_mmx) + + || !register_conversion(IMG_BGRA32, IMG_RGBA32, rgba_swap02_mmx) + || !register_conversion(IMG_BGRA32, IMG_ABGR32, rgba_alpha30_mmx) + || !register_conversion(IMG_BGRA32, IMG_ARGB32, rgba_swapall_mmx) + ) { + return 0; + } + } +#endif + +#if defined(HAVE_ASM_SSE2) + if (accel & AC_SSE2) { + if (!register_conversion(IMG_RGB24, IMG_BGR24, rgb24_bgr24_sse2) + || !register_conversion(IMG_RGB24, IMG_RGBA32, rgb24_rgba32_sse2) + || !register_conversion(IMG_RGB24, IMG_ABGR32, rgb24_abgr32_sse2) + || !register_conversion(IMG_RGB24, IMG_ARGB32, rgb24_argb32_sse2) + || !register_conversion(IMG_RGB24, IMG_BGRA32, rgb24_bgra32_sse2) + || !register_conversion(IMG_RGB24, IMG_GRAY8, rgb24_gray8_sse2) + + || !register_conversion(IMG_BGR24, IMG_RGB24, rgb24_bgr24_sse2) + || !register_conversion(IMG_BGR24, IMG_RGBA32, rgb24_bgra32_sse2) + || !register_conversion(IMG_BGR24, IMG_ABGR32, rgb24_argb32_sse2) + || !register_conversion(IMG_BGR24, IMG_ARGB32, rgb24_abgr32_sse2) + || !register_conversion(IMG_BGR24, IMG_BGRA32, rgb24_rgba32_sse2) + || !register_conversion(IMG_BGR24, IMG_GRAY8, bgr24_gray8_sse2) + + || !register_conversion(IMG_RGBA32, IMG_RGB24, rgba32_rgb24_sse2) + || !register_conversion(IMG_RGBA32, IMG_BGR24, bgra32_rgb24_sse2) + || !register_conversion(IMG_RGBA32, IMG_ABGR32, rgba_swapall_sse2) + || !register_conversion(IMG_RGBA32, IMG_ARGB32, rgba_alpha30_sse2) + || !register_conversion(IMG_RGBA32, IMG_BGRA32, rgba_swap02_sse2) + || !register_conversion(IMG_RGBA32, IMG_GRAY8, rgba32_gray8_sse2) + + || !register_conversion(IMG_ABGR32, IMG_RGB24, abgr32_rgb24_sse2) + || !register_conversion(IMG_ABGR32, IMG_BGR24, argb32_rgb24_sse2) + || !register_conversion(IMG_ABGR32, IMG_RGBA32, rgba_swapall_sse2) + || !register_conversion(IMG_ABGR32, IMG_ARGB32, rgba_swap13_sse2) + || !register_conversion(IMG_ABGR32, IMG_BGRA32, rgba_alpha03_sse2) + || !register_conversion(IMG_ABGR32, IMG_GRAY8, abgr32_gray8_sse2) + + || !register_conversion(IMG_ARGB32, IMG_RGB24, argb32_rgb24_sse2) + || !register_conversion(IMG_ARGB32, IMG_BGR24, abgr32_rgb24_sse2) + || !register_conversion(IMG_ARGB32, IMG_RGBA32, rgba_alpha03_sse2) + || !register_conversion(IMG_ARGB32, IMG_ABGR32, rgba_swap13_sse2) + || !register_conversion(IMG_ARGB32, IMG_BGRA32, rgba_swapall_sse2) + || !register_conversion(IMG_ARGB32, IMG_GRAY8, argb32_gray8_sse2) + + || !register_conversion(IMG_BGRA32, IMG_RGB24, bgra32_rgb24_sse2) + || !register_conversion(IMG_BGRA32, IMG_BGR24, rgba32_rgb24_sse2) + || !register_conversion(IMG_BGRA32, IMG_RGBA32, rgba_swap02_sse2) + || !register_conversion(IMG_BGRA32, IMG_ABGR32, rgba_alpha30_sse2) + || !register_conversion(IMG_BGRA32, IMG_ARGB32, rgba_swapall_sse2) + || !register_conversion(IMG_BGRA32, IMG_GRAY8, bgra32_gray8_sse2) + + || !register_conversion(IMG_GRAY8, IMG_RGB24, gray8_rgb24_sse2) + || !register_conversion(IMG_GRAY8, IMG_BGR24, gray8_rgb24_sse2) + || !register_conversion(IMG_GRAY8, IMG_RGBA32, gray8_rgba32_sse2) + || !register_conversion(IMG_GRAY8, IMG_ABGR32, gray8_argb32_sse2) + || !register_conversion(IMG_GRAY8, IMG_ARGB32, gray8_argb32_sse2) + || !register_conversion(IMG_GRAY8, IMG_BGRA32, gray8_rgba32_sse2) + ) { + return 0; + } + } +#endif + +#endif /* ARCH_X86 || ARCH_X86_64 */ + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/img_x86_common.h b/branches/V-1.5.3/veejay-server/aclib/img_x86_common.h new file mode 100644 index 00000000..a04084a1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/img_x86_common.h @@ -0,0 +1,596 @@ +/* + * img_x86_common.h - common x86/x86-64 assembly macros + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#ifndef ACLIB_IMG_X86_COMMON_H +#define ACLIB_IMG_X86_COMMON_H + +/*************************************************************************/ + +/* Register names for pointers */ +#ifdef ARCH_X86_64 +# define EAX "%%rax" +# define EBX "%%rbx" +# define ECX "%%rcx" +# define EDX "%%rdx" +# define ESP "%%rsp" +# define EBP "%%rbp" +# define ESI "%%rsi" +# define EDI "%%rdi" +#else +# define EAX "%%eax" +# define EBX "%%ebx" +# define ECX "%%ecx" +# define EDX "%%edx" +# define ESP "%%esp" +# define EBP "%%ebp" +# define ESI "%%esi" +# define EDI "%%edi" +#endif + +/* Data for isolating particular bytes. Used by the SWAP32 macros; if you + * use them, make sure to define DEFINE_MASK_DATA before including this + * file! */ +#ifdef DEFINE_MASK_DATA +static const struct { uint32_t n[64]; } __attribute__((aligned(16))) mask_data = {{ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF, + 0x0000FF00, 0x0000FF00, 0x0000FF00, 0x0000FF00, + 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, 0x0000FFFF, + 0x00FF0000, 0x00FF0000, 0x00FF0000, 0x00FF0000, + 0x00FF00FF, 0x00FF00FF, 0x00FF00FF, 0x00FF00FF, + 0x00FFFF00, 0x00FFFF00, 0x00FFFF00, 0x00FFFF00, + 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, + 0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000, + 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, 0xFF0000FF, + 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00, + 0xFF00FFFF, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FFFF, + 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, + 0xFFFF00FF, 0xFFFF00FF, 0xFFFF00FF, 0xFFFF00FF, + 0xFFFFFF00, 0xFFFFFF00, 0xFFFFFF00, 0xFFFFFF00, + 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, +}}; +#endif + +/*************************************************************************/ + +/* Basic assembly macros, used for odd-count loops */ + +/* Swap bytes in pairs of 16-bit values */ +#define X86_SWAP16_2 \ + "movl -4("ESI","ECX",4), %%eax \n\ + movl %%eax, %%edx \n\ + shll $8, %%eax \n\ + andl $0xFF00FF00, %%eax \n\ + shrl $8, %%edx \n\ + andl $0x00FF00FF, %%edx \n\ + orl %%edx, %%eax \n\ + movl %%eax, -4("EDI","ECX",4)" + +/* Swap words in a 32-bit value */ +#define X86_SWAP32 \ + "movl -4("ESI","ECX",4), %%eax \n\ + roll $16, %%eax \n\ + movl %%eax, -4("EDI","ECX",4)" + +/* Swap bytes 0 and 2 of a 32-bit value */ +#define X86_SWAP32_02 \ + "movw -4("ESI","ECX",4), %%ax \n\ + movw -2("ESI","ECX",4), %%dx \n\ + xchg %%dl, %%al \n\ + movw %%ax, -4("EDI","ECX",4) \n\ + movw %%dx, -2("EDI","ECX",4)" + +/* Swap bytes 1 and 3 of a 32-bit value */ +#define X86_SWAP32_13 \ + "movw -4("ESI","ECX",4), %%ax \n\ + movw -2("ESI","ECX",4), %%dx \n\ + xchg %%dh, %%ah \n\ + movw %%ax, -4("EDI","ECX",4) \n\ + movw %%dx, -2("EDI","ECX",4)" + +/* Reverse the order of bytes in a 32-bit value */ +#define X86_REV32 \ + "movl -4("ESI","ECX",4), %%eax \n\ + xchg %%ah, %%al \n\ + roll $16, %%eax \n\ + xchg %%ah, %%al \n\ + movl %%eax, -4("EDI","ECX",4)" + +/* The same, using the BSWAP instruction */ +#define X86_REV32_BSWAP \ + "movl -4("ESI","ECX",4), %%eax \n\ + bswap %%eax \n\ + movl %%eax, -4("EDI","ECX",4)" + +/* Rotate a 32-bit value left 8 bits */ +#define X86_ROL32 \ + "movl -4("ESI","ECX",4), %%eax \n\ + roll $8, %%eax \n\ + movl %%eax, -4("EDI","ECX",4)" + +/* Rotate a 32-bit value right 8 bits */ +#define X86_ROR32 \ + "movl -4("ESI","ECX",4), %%eax \n\ + rorl $8, %%eax \n\ + movl %%eax, -4("EDI","ECX",4)" + +/*************************************************************************/ + +/* Basic assembly routines. Sizes are all given in 32-bit units. */ + +#define ASM_SWAP16_2_X86(size) \ + asm("0: "X86_SWAP16_2" \n\ + subl $1, %%ecx \n\ + jnz 0b" \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax", "edx") + +#define ASM_SWAP32_X86(size) \ + asm("0: "X86_SWAP32" \n\ + subl $1, %%ecx \n\ + jnz 0b" \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax", "edx") + +#define ASM_SWAP32_02_X86(size) \ + asm("0: "X86_SWAP32_02" \n\ + subl $1, %%ecx \n\ + jnz 0b" \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax", "edx") + +#define ASM_SWAP32_13_X86(size) \ + asm("0: "X86_SWAP32_13" \n\ + subl $1, %%ecx \n\ + jnz 0b" \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax", "edx") + +#define ASM_REV32_X86(size) \ + asm("0: "X86_REV32" \n\ + subl $1, %%ecx \n\ + jnz 0b" \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax") + +#define ASM_ROL32_X86(size) \ + asm("0: "X86_ROL32" \n\ + subl $1, %%ecx \n\ + jnz 0b" \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax") + +#define ASM_ROR32_X86(size) \ + asm("0: "X86_ROR32" \n\ + subl $1, %%ecx \n\ + jnz 0b" \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax") + +/*************************************************************************/ +/*************************************************************************/ + +/* Wrapper for SIMD loops. This generates the body of an asm() construct + * (the string only, not the input/output/clobber lists) given the data + * block size (number of data units processed per SIMD loop iteration), + * instructions to save and restore unclobberable registers (such as EBX), + * and the bodies of the odd-count and main loops. The data count is + * assumed to be preloaded in ECX. Parameters are: + * blocksize: number of units of data processed per SIMD loop (must be + * a power of 2); can be a constant or a numerical + * expression containing only constants + * push_regs: string constant containing instructions to push registers + * that must be saved over the small loop + * pop_regs: string constant containing instructions to pop registers + * saved by `push_regs' (restored before the main loop) + * small_loop: loop for handling data elements one at a time (when the + * count is not a multiple of `blocksize' + * main_loop: main SIMD loop for processing data + * emms: EMMS/SFENCE instructions to end main loop with, as needed + */ + +#define SIMD_LOOP_WRAPPER(blocksize,push_regs,pop_regs,small_loop,main_loop,emms) \ + /* Always save ECX--GCC may rely on it being unmodified */ \ + "push "ECX"; " \ + /* Check whether the count is a multiple of the blocksize (this \ + * can cause branch mispredicts but seems to be faster overall) */ \ + "testl $(("#blocksize")-1), %%ecx; " \ + "jz 1f; " \ + /* It's not--run the small loop to align the count */ \ + push_regs"; " \ + "0: " \ + small_loop"; " \ + "subl $1, %%ecx; " \ + "testl $(("#blocksize")-1), %%ecx; " \ + "jnz 0b; " \ + pop_regs"; " \ + /* Make sure there's some data left */ \ + "testl %%ecx, %%ecx; " \ + "jz 2f; " \ + /* Now run the main SIMD loop */ \ + "1: " \ + main_loop"; " \ + "subl $("#blocksize"), %%ecx; " \ + "jnz 1b; " \ + /* Clear MMX state and/or SFENCE, as needed */ \ + emms"; " \ + /* Restore ECX and finish */ \ + "2: " \ + "pop "ECX";" + +/*************************************************************************/ + +/* MMX- and SSE2-optimized swap/rotate routines. These routines are + * identical save for data size, so we use common macros to implement them, + * with register names and data offsets replaced by parameters to the + * macros. */ + +#define ASM_SIMD_MMX(name,size) \ + name((size), 64, \ + "movq", "movq", "movq", "", \ + "%%mm0", "%%mm1", "%%mm2", "%%mm3", \ + "%%mm4", "%%mm5", "%%mm6", "%%mm7") +#define ASM_SIMD_SSE2(name,size) \ + name((size), 128, \ + "movdqu", "movdqa", "movdqu", "", \ + "%%xmm0", "%%xmm1", "%%xmm2", "%%xmm3",\ + "%%xmm4", "%%xmm5", "%%xmm6", "%%xmm7") +#define ASM_SIMD_SSE2_ALIGNED(name,size) \ + name((size), 128, \ + "movdqa", "movdqa", "movntdq", "sfence",\ + "%%xmm0", "%%xmm1", "%%xmm2", "%%xmm3",\ + "%%xmm4", "%%xmm5", "%%xmm6", "%%xmm7") + +#define ASM_SWAP16_2_MMX(size) ASM_SIMD_MMX(ASM_SWAP16_2_SIMD,(size)) +#define ASM_SWAP16_2_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP16_2_SIMD,(size)) +#define ASM_SWAP16_2_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP16_2_SIMD,(size)) +#define ASM_SWAP32_MMX(size) ASM_SIMD_MMX(ASM_SWAP32_SIMD,(size)) +#define ASM_SWAP32_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP32_SIMD,(size)) +#define ASM_SWAP32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP32_SIMD,(size)) +#define ASM_SWAP32_02_MMX(size) ASM_SIMD_MMX(ASM_SWAP32_02_SIMD,(size)) +#define ASM_SWAP32_02_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP32_02_SIMD,(size)) +#define ASM_SWAP32_02_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP32_02_SIMD,(size)) +#define ASM_SWAP32_13_MMX(size) ASM_SIMD_MMX(ASM_SWAP32_13_SIMD,(size)) +#define ASM_SWAP32_13_SSE2(size) ASM_SIMD_SSE2(ASM_SWAP32_13_SIMD,(size)) +#define ASM_SWAP32_13_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_SWAP32_13_SIMD,(size)) +#define ASM_REV32_MMX(size) ASM_SIMD_MMX(ASM_REV32_SIMD,(size)) +#define ASM_REV32_SSE2(size) ASM_SIMD_SSE2(ASM_REV32_SIMD,(size)) +#define ASM_REV32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_REV32_SIMD,(size)) +#define ASM_ROL32_MMX(size) ASM_SIMD_MMX(ASM_ROL32_SIMD,(size)) +#define ASM_ROL32_SSE2(size) ASM_SIMD_SSE2(ASM_ROL32_SIMD,(size)) +#define ASM_ROL32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_ROL32_SIMD,(size)) +#define ASM_ROR32_MMX(size) ASM_SIMD_MMX(ASM_ROR32_SIMD,(size)) +#define ASM_ROR32_SSE2(size) ASM_SIMD_SSE2(ASM_ROR32_SIMD,(size)) +#define ASM_ROR32_SSE2A(size) ASM_SIMD_SSE2_ALIGNED(ASM_ROR32_SIMD,(size)) + +/*************************************************************************/ + +/* Actual implementations. Note that unrolling the SIMD loops doesn't seem + * to be a win (only 2-3% improvement at most), and in fact can lose by a + * bit in short loops. */ + +#define ASM_SWAP16_2_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ (regsize)/32, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ X86_SWAP16_2, \ + /* main_loop */ \ + ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\ + # MM0: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\ + psrlw $8, "MM0" # MM0: - 7 - 5 - 3 - 1 \n\ + psllw $8, "MM1" # MM1: 6 - 4 - 2 - 0 - \n\ + por "MM1", "MM0" # MM0: 6 7 4 5 2 3 0 1 \n\ + "stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \ + /* emms */ "emms; "sfence) \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax", "edx") + +#define ASM_SWAP32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ (regsize)/32, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ X86_SWAP32, \ + /* main_loop */ \ + ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\ + # MM0: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\ + psrld $16, "MM0" # MM0: - - 7 6 - - 3 2 \n\ + pslld $16, "MM1" # MM1: 5 4 - - 1 0 - - \n\ + por "MM1", "MM0" # MM0: 5 4 7 6 1 0 3 2 \n\ + "stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \ + /* emms */ "emms; "sfence) \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax") + +#define ASM_SWAP32_02_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ (regsize)/32, \ + /* push_regs */ "push "EDX, \ + /* pop_regs */ "pop "EDX, \ + /* small_loop */ X86_SWAP32_02, \ + /* main_loop */ \ + ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\ + # MM0: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM2" # MM2: 7 6 5 4 3 2 1 0 \n\ + pand 16("EDX"), "MM1" # MM1: - - - 4 - - - 0 \n\ + pslld $16, "MM1" # MM1: - 4 - - - 0 - - \n\ + pand 64("EDX"), "MM2" # MM2: - 6 - - - 2 - - \n\ + psrld $16, "MM2" # MM2: - - - 6 - - - 2 \n\ + pand 160("EDX"), "MM0" # MM0: 7 - 5 - 3 - 1 - \n\ + por "MM1", "MM0" # MM0: 7 4 5 - 3 0 1 - \n\ + por "MM2", "MM0" # MM0: 7 4 5 6 3 0 1 2 \n\ + "stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \ + /* emms */ "emms; "sfence) \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size), "d" (&mask_data), \ + "m" (mask_data) \ + : "eax") + +#define ASM_SWAP32_13_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ (regsize)/32, \ + /* push_regs */ "push "EDX, \ + /* pop_regs */ "pop "EDX, \ + /* small_loop */ X86_SWAP32_13, \ + /* main_loop */ \ + ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\ + # MM0: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM2" # MM2: 7 6 5 4 3 2 1 0 \n\ + pand 32("EDX"), "MM1" # MM1: - - 5 - - - 1 - \n\ + pslld $16, "MM1" # MM1: 5 - - - 1 - - - \n\ + pand 128("EDX"), "MM2" # MM2: 7 - - - 3 - - - \n\ + psrld $16, "MM2" # MM2: - - 7 - - - 3 - \n\ + pand 80("EDX"), "MM0" # MM0: - 6 - 4 - 2 - 0 \n\ + por "MM1", "MM0" # MM0: 5 6 - 4 1 2 - 0 \n\ + por "MM2", "MM0" # MM0: 5 6 7 4 1 2 3 0 \n\ + "stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \ + /* emms */ "emms; "sfence) \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size), "d" (&mask_data), \ + "m" (mask_data) \ + : "eax"); + +#define ASM_REV32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ (regsize)/32, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ X86_REV32_BSWAP, \ + /* main_loop */ \ + ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\ + # MM0: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM2" # MM2: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM3" # MM3: 7 6 5 4 3 2 1 0 \n\ + psrld $24, "MM0" # MM0: - - - 7 - - - 3 \n\ + pand 32("EDX"), "MM2" # MM2: - - 5 - - - 1 - \n\ + psrld $8, "MM1" # MM1: - 7 6 5 - 3 2 1 \n\ + pand 32("EDX"), "MM1" # MM1: - - 6 - - - 2 - \n\ + pslld $8, "MM2" # MM2: - 5 - - - 1 - - \n\ + pslld $24, "MM3" # MM3: 4 - - - 0 - - - \n\ + por "MM1", "MM0" # MM0: - - 6 7 - - 2 3 \n\ + por "MM2", "MM0" # MM0: - 5 6 7 - 1 2 3 \n\ + por "MM3", "MM0" # MM0: 4 5 6 7 0 1 2 3 \n\ + "stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \ + /* emms */ "emms; "sfence) \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size), "d" (&mask_data), \ + "m" (mask_data) \ + : "eax") + +#define ASM_ROL32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ (regsize)/32, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ X86_ROL32, \ + /* main_loop */ \ + ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\ + # MM0: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\ + pslld $8, "MM0" # MM0: 6 5 4 - 2 1 0 - \n\ + psrld $24, "MM1" # MM1: - - - 7 - - - 3 \n\ + por "MM1", "MM0" # MM0: 6 5 4 7 2 1 0 3 \n\ + "stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \ + /* emms */ "emms; "sfence) \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax") + +#define ASM_ROR32_SIMD(size,regsize,ldq,movq,stq,sfence,MM0,MM1,MM2,MM3,MM4,MM5,MM6,MM7) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ (regsize)/32, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ X86_ROR32, \ + /* main_loop */ \ + ldq" -("#regsize"/8)("ESI","ECX",4), "MM0" \n\ + # MM0: 7 6 5 4 3 2 1 0 \n\ + "movq" "MM0", "MM1" # MM1: 7 6 5 4 3 2 1 0 \n\ + psrld $8, "MM0" # MM0: - 7 6 5 - 3 2 1 \n\ + pslld $24, "MM1" # MM1: 4 - - - 0 - - - \n\ + por "MM1", "MM0" # MM0: 4 7 6 5 0 3 2 1 \n\ + "stq" "MM0", -("#regsize"/8)("EDI","ECX",4)", \ + /* emms */ "emms; "sfence) \ + : /* no outputs */ \ + : "S" (src[0]), "D" (dest[0]), "c" (size) \ + : "eax") + +/*************************************************************************/ + +/* SSE2 macros to load 8 24- or 32-bit RGB pixels into XMM0/1/2 (R/G/B) as + * 16-bit values, used for RGB->YUV and RGB->grayscale conversions. + * ZERO is the number of the XMM register containing all zeroes. */ + +#define SSE2_LOAD_RGB24(ZERO) \ + "movl -21("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm0 # XMM0: ----- ----- ----- xBGR1 \n\ + pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xBGR1 ----- ----- ----- \n\ + movl -18("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm0 # XMM0: xBGR1 ----- ----- xBGR2 \n\ + pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xBGR2 xBGR1 ----- ----- \n\ + movl -15("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm0 # XMM0: xBGR2 xBGR1 ----- xBGR3 \n\ + pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xBGR3 xBGR2 xBGR1 ----- \n\ + movl -24("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm0 # XMM0: xBGR3 xBGR2 xBGR1 xBGR0 \n\ + movl -9("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm1 # XMM1: ----- ----- ----- xBGR5 \n\ + pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xBGR5 ----- ----- ----- \n\ + movl -6("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm1 # XMM1: xBGR5 ----- ----- xBGR6 \n\ + pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xBGR6 xBGR5 ----- ----- \n\ + movl -3("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm1 # XMM1: xBGR6 xBGR5 ----- xBGR7 \n\ + pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xBGR7 xBGR6 xBGR5 ----- \n\ + movl -12("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm1 # XMM1: xBGR7 xBGR6 xBGR5 xBGR4 \n"\ + SSE2_MASSAGE_RGBA32(ZERO) + +#define SSE2_LOAD_BGR24(ZERO) \ + "movl -21("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm0 # XMM0: ----- ----- ----- xRGB1 \n\ + pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xRGB1 ----- ----- ----- \n\ + movl -18("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm0 # XMM0: xRGB1 ----- ----- xRGB2 \n\ + pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xRGB2 xRGB1 ----- ----- \n\ + movl -15("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm0 # XMM0: xRGB2 xRGB1 ----- xRGB3 \n\ + pshufd $0x39, %%xmm0, %%xmm0 # XMM0: xRGB3 xRGB2 xRGB1 ----- \n\ + movl -24("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm0 # XMM0: xRGB3 xRGB2 xRGB1 xRGB0 \n\ + movl -9("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm1 # XMM1: ----- ----- ----- xRGB5 \n\ + pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xRGB5 ----- ----- ----- \n\ + movl -6("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm1 # XMM1: xRGB5 ----- ----- xRGB6 \n\ + pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xRGB6 xRGB5 ----- ----- \n\ + movl -3("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm1 # XMM1: xRGB6 xRGB5 ----- xRGB7 \n\ + pshufd $0x39, %%xmm1, %%xmm1 # XMM1: xRGB7 xRGB6 xRGB5 ----- \n\ + movl -12("ESI","EBX"), %%eax \n\ + movd %%eax, %%xmm2 \n\ + por %%xmm2, %%xmm1 # XMM1: xRGB7 xRGB6 xRGB5 xRGB4 \n"\ + SSE2_MASSAGE_BGRA32(ZERO) + +#define SSE2_LOAD_RGBA32(ZERO) "\ + movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: ABGR3 ABGR2 ABGR1 ABGR0 \n\ + movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: ABGR7 ABGR6 ABGR5 ABGR4 \n"\ + SSE2_MASSAGE_RGBA32(ZERO) +#define SSE2_MASSAGE_RGBA32(ZERO) "\ + movdqa %%xmm0, %%xmm2 # XMM2: ABGR3 ABGR2 ABGR1 ABGR0 \n\ + punpcklbw %%xmm1, %%xmm0 # X0.l: A4 A0 B4 B0 G4 G0 R4 R0 \n\ + punpckhbw %%xmm1, %%xmm2 # X2.l: A6 A2 B6 B2 G6 G2 R6 R2 \n\ + movdqa %%xmm0, %%xmm1 # X1.l: A4 A0 B4 B0 G4 G0 R4 R0 \n\ + punpcklbw %%xmm2, %%xmm0 # X0.l: G6 G4 G2 G0 R6 R4 R2 R0 \n\ + punpckhbw %%xmm2, %%xmm1 # X1.l: G7 G5 G3 G1 R7 R5 R3 R1 \n\ + movdqa %%xmm0, %%xmm2 # X2.l: G6 G4 G2 G0 R6 R4 R2 R0 \n\ + punpcklbw %%xmm1, %%xmm0 # XMM0: G7.......G0 R7.......R0 \n\ + punpckhbw %%xmm1, %%xmm2 # XMM2: A7.......A0 B7.......B0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: G7.......G0 R7.......R0 \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + punpckhbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + punpcklbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n" + +#define SSE2_LOAD_BGRA32(ZERO) "\ + movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: ARGB3 ARGB2 ARGB1 ARGB0 \n\ + movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: ARGB7 ARGB6 ARGB5 ARGB4 \n"\ + SSE2_MASSAGE_BGRA32(ZERO) +#define SSE2_MASSAGE_BGRA32(ZERO) "\ + movdqa %%xmm0, %%xmm2 # XMM2: ARGB3 ARGB2 ARGB1 ARGB0 \n\ + punpcklbw %%xmm1, %%xmm2 # X2.l: A4 A0 R4 R0 G4 G0 B4 B0 \n\ + punpckhbw %%xmm1, %%xmm0 # X0.l: A6 A2 R6 R2 G6 G2 B6 B2 \n\ + movdqa %%xmm2, %%xmm1 # X1.l: A4 A0 R4 R0 G4 G0 B4 B0 \n\ + punpcklbw %%xmm0, %%xmm2 # X2.l: G6 G4 G2 G0 B6 B4 B2 B0 \n\ + punpckhbw %%xmm0, %%xmm1 # X1.l: G7 G5 G3 G1 B7 B5 B3 B1 \n\ + movdqa %%xmm2, %%xmm0 # X0.l: G6 G4 G2 G0 B6 B4 B2 B0 \n\ + punpcklbw %%xmm1, %%xmm2 # XMM2: G7.......G0 B7.......B0 \n\ + punpckhbw %%xmm1, %%xmm0 # XMM0: A7.......A0 R7.......R0 \n\ + movdqa %%xmm2, %%xmm1 # XMM1: G7.......G0 B7.......B0 \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + punpckhbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + punpcklbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n" + +#define SSE2_LOAD_ARGB32(ZERO) "\ + movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: BGRA3 BGRA2 BGRA1 BGRA0 \n\ + movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: BGRA7 BGRA6 BGRA5 BGRA4 \n"\ + SSE2_MASSAGE_ARGB32(ZERO) +#define SSE2_MASSAGE_ARGB32(ZERO) "\ + movdqa %%xmm0, %%xmm2 # XMM2: BGRA3 BGRA2 BGRA1 BGRA0 \n\ + punpcklbw %%xmm1, %%xmm0 # X0.l: B4 B0 G4 G0 R4 R0 A4 A0 \n\ + punpckhbw %%xmm1, %%xmm2 # X2.l: B6 B2 G6 G2 R6 R2 A6 A2 \n\ + movdqa %%xmm0, %%xmm1 # X1.l: B4 B0 G4 G0 R4 R0 A4 A0 \n\ + punpcklbw %%xmm2, %%xmm0 # X0.l: R6 R4 R2 R0 A6 A4 A2 A0 \n\ + punpckhbw %%xmm2, %%xmm1 # X1.l: R7 R5 R3 R1 A7 A5 A3 A1 \n\ + movdqa %%xmm0, %%xmm2 # X2.l: R6 R4 R2 R0 A6 A4 A2 A0 \n\ + punpcklbw %%xmm1, %%xmm0 # XMM0: R7.......G0 A7.......A0 \n\ + punpckhbw %%xmm1, %%xmm2 # XMM2: B7.......G0 G7.......G0 \n\ + movdqa %%xmm2, %%xmm1 # XMM1: B7.......B0 G7.......G0 \n\ + punpckhbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + punpcklbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + punpckhbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n" + +#define SSE2_LOAD_ABGR32(ZERO) "\ + movdqu -32("ESI","ECX",4),%%xmm0 #XMM0: RGBA3 RGBA2 RGBA1 RGBA0 \n\ + movdqu -16("ESI","ECX",4),%%xmm1 #XMM1: RGBA7 RGBA6 RGBA5 RGBA4 \n"\ + SSE2_MASSAGE_ABGR32(ZERO) +#define SSE2_MASSAGE_ABGR32(ZERO) "\ + movdqa %%xmm0, %%xmm2 # XMM2: RGBA3 RGBA2 RGBA1 RGBA0 \n\ + punpcklbw %%xmm1, %%xmm2 # X2.l: R4 R0 G4 G0 B4 B0 A4 A0 \n\ + punpckhbw %%xmm1, %%xmm0 # X0.l: R6 R2 G6 G2 B6 B2 A6 A2 \n\ + movdqa %%xmm2, %%xmm1 # X1.l: R4 R0 G4 G0 B4 B0 A4 A0 \n\ + punpcklbw %%xmm0, %%xmm2 # X2.l: B6 B4 B2 B0 A6 A4 A2 A0 \n\ + punpckhbw %%xmm0, %%xmm1 # X1.l: B7 B5 B3 B1 A7 A5 A3 A1 \n\ + movdqa %%xmm2, %%xmm0 # X0.l: B6 B4 B2 B0 A6 A4 A2 A0 \n\ + punpcklbw %%xmm1, %%xmm2 # XMM2: B7.......B0 A7.......A0 \n\ + punpckhbw %%xmm1, %%xmm0 # XMM0: R7.......R0 G7.......G0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: R7.......R0 G7.......G0 \n\ + punpckhbw %%xmm4, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + punpcklbw %%xmm4, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + punpckhbw %%xmm4, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n" + +/*************************************************************************/ + +#endif /* ACLIB_IMG_X86_COMMON_H */ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/img_yuv_mixed.c b/branches/V-1.5.3/veejay-server/aclib/img_yuv_mixed.c new file mode 100644 index 00000000..004d5378 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/img_yuv_mixed.c @@ -0,0 +1,912 @@ +/* + * img_yuv_packed.c - YUV planar<->packed image format conversion routines + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "imgconvert.h" +#include "img_internal.h" + +/*************************************************************************/ +/*************************************************************************/ + +/* Standard C implementations */ + +/*************************************************************************/ + +/* Wrappers for UYVY and YVYU */ +/* Note: we rely on YUY2<->{UYVY,YVYU} working for src==dest */ +/* FIXME: when converting from UYVY/YVYU, src is destroyed! */ + +static int uyvy_yvyu_wrapper(uint8_t **src, ImageFormat srcfmt, + uint8_t **dest, ImageFormat destfmt, + int width, int height) +{ + if (srcfmt == IMG_UYVY || srcfmt == IMG_YVYU) + return ac_imgconvert(src, srcfmt, src, IMG_YUY2, width, height) + && ac_imgconvert(src, IMG_YUY2, dest, destfmt, width, height); + else + return ac_imgconvert(src, srcfmt, dest, IMG_YUY2, width, height) + && ac_imgconvert(dest, IMG_YUY2, dest, destfmt, width, height); +} + +static int yuv420p_uyvy(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV420P, dest, IMG_UYVY, width, height); } + +static int yuv420p_yvyu(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV420P, dest, IMG_YVYU, width, height); } + +static int yuv411p_uyvy(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV411P, dest, IMG_UYVY, width, height); } + +static int yuv411p_yvyu(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV411P, dest, IMG_YVYU, width, height); } + +static int yuv422p_uyvy(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV422P, dest, IMG_UYVY, width, height); } + +static int yuv422p_yvyu(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV422P, dest, IMG_YVYU, width, height); } + +static int yuv444p_uyvy(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV444P, dest, IMG_UYVY, width, height); } + +static int yuv444p_yvyu(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YUV444P, dest, IMG_YVYU, width, height); } + +static int uyvy_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV420P, width, height); } + +static int yvyu_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV420P, width, height); } + +static int uyvy_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV411P, width, height); } + +static int yvyu_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV411P, width, height); } + +static int uyvy_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV422P, width, height); } + +static int yvyu_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV422P, width, height); } + +static int uyvy_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_UYVY, dest, IMG_YUV444P, width, height); } + +static int yvyu_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ return uyvy_yvyu_wrapper(src, IMG_YVYU, dest, IMG_YUV444P, width, height); } + +/*************************************************************************/ + +static int yuv420p_yuy2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + + for (y = 0; y < (height & ~1); y++) { + for (x = 0; x < (width & ~1); x += 2) { + dest[0][(y*width+x)*2 ] = src[0][y*width+x]; + dest[0][(y*width+x)*2+1] = src[1][(y/2)*(width/2)+x/2]; + dest[0][(y*width+x)*2+2] = src[0][y*width+x+1]; + dest[0][(y*width+x)*2+3] = src[2][(y/2)*(width/2)+x/2]; + } + } + return 1; +} + +static int yuv411p_yuy2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + + for (y = 0; y < height; y++) { + for (x = 0; x < (width & ~1); x += 2) { + dest[0][(y*width+x)*2 ] = src[0][y*width+x]; + dest[0][(y*width+x)*2+1] = src[1][y*(width/4)+x/4]; + dest[0][(y*width+x)*2+2] = src[0][y*width+x+1]; + dest[0][(y*width+x)*2+3] = src[2][y*(width/4)+x/4]; + } + } + return 1; +} + +static int yuv422p_yuy2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < (width/2)*height; i++) { + dest[0][i*4 ] = src[0][i*2]; + dest[0][i*4+1] = src[1][i]; + dest[0][i*4+2] = src[0][i*2+1]; + dest[0][i*4+3] = src[2][i]; + } + return 1; +} + +static int yuv444p_yuy2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < (width/2)*height; i++) { + dest[0][i*4 ] = src[0][i*2]; + dest[0][i*4+1] = (src[1][i*2] + src[1][i*2+1]) / 2; + dest[0][i*4+2] = src[0][i*2+1]; + dest[0][i*4+3] = (src[2][i*2] + src[2][i*2+1]) / 2; + } + return 1; +} + +/*************************************************************************/ + +static int yuy2_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + + for (y = 0; y < (height & ~1); y++) { + for (x = 0; x < (width & ~1); x += 2) { + dest[0][y*width+x ] = src[0][(y*width+x)*2 ]; + dest[0][y*width+x+1] = src[0][(y*width+x)*2+2]; + if (y%2 == 0) { + dest[1][(y/2)*(width/2)+x/2] = src[0][(y*width+x)*2+1]; + dest[2][(y/2)*(width/2)+x/2] = src[0][(y*width+x)*2+3]; + } else { + dest[1][(y/2)*(width/2)+x/2] = + (dest[1][(y/2)*(width/2)+x/2] + src[0][(y*width+x)*2+1] + 1) / 2; + dest[2][(y/2)*(width/2)+x/2] = + (dest[2][(y/2)*(width/2)+x/2] + src[0][(y*width+x)*2+3] + 1) / 2; + } + } + } + return 1; +} + +static int yuy2_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + for (y = 0; y < height; y++) { + for (x = 0; x < (width & ~3); x += 4) { + dest[0][y*width+x] = src[0][(y*width+x)*2 ]; + dest[0][y*width+x+1] = src[0][(y*width+x)*2+2]; + dest[0][y*width+x+2] = src[0][(y*width+x)*2+4]; + dest[0][y*width+x+3] = src[0][(y*width+x)*2+6]; + dest[1][y*(width/4)+x/4] = (src[0][(y*width+x)*2+1] + + src[0][(y*width+x)*2+5] + 1) / 2; + dest[2][y*(width/4)+x/4] = (src[0][(y*width+x)*2+3] + + src[0][(y*width+x)*2+7] + 1) / 2; + } + } + return 1; +} + +static int yuy2_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < (width/2)*height; i++) { + dest[0][i*2] = src[0][i*4 ]; + dest[1][i] = src[0][i*4+1]; + dest[0][i*2+1] = src[0][i*4+2]; + dest[2][i] = src[0][i*4+3]; + } + return 1; +} + +static int yuy2_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < (width & ~1)*height; i += 2) { + dest[0][i] = src[0][i*2 ]; + dest[1][i] = src[0][i*2+1]; + dest[1][i+1] = src[0][i*2+1]; + dest[0][i+1] = src[0][i*2+2]; + dest[2][i] = src[0][i*2+3]; + dest[2][i+1] = src[0][i*2+3]; + } + return 1; +} + +/*************************************************************************/ + +static int y8_yuy2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*2 ] = src[0][i]; + dest[0][i*2+1] = 128; + } + return 1; +} + +static int y8_uyvy(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) { + dest[0][i*2 ] = 128; + dest[0][i*2+1] = src[0][i]; + } + return 1; +} + +static int yuy2_y8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) + dest[0][i] = src[0][i*2]; + return 1; +} + +static int uyvy_y8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height; i++) + dest[0][i] = src[0][i*2+1]; + return 1; +} + +/*************************************************************************/ +/*************************************************************************/ + +#if defined(HAVE_ASM_SSE2) + +/* SSE2 routines. See comments in img_x86_common.h for why we don't bother + * unrolling the loops. */ + +/* Common macros/data for x86 code */ +#include "img_x86_common.h" + +/* YUV420P (1 row) or YUV422P -> YUY2 (unit: 2 pixels) */ +#define YUV42XP_YUY2 \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "push "EBX, \ + /* pop_regs */ "pop "EBX, \ + /* small_loop */ \ + "movb -1("EDX","ECX"), %%bh \n\ + movb -1("ESI","ECX",2), %%bl \n\ + shll $16, %%ebx \n\ + movb -1("EAX","ECX"), %%bh \n\ + movb -2("ESI","ECX",2), %%bl \n\ + movl %%ebx, -4("EDI","ECX",4)", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",2),%%xmm0 #XM0: YF YE YD ..... Y2 Y1 Y0 \n\ + movq -8("EAX","ECX"), %%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\ + movq -8("EDX","ECX"), %%xmm3 # XMM3: V7 V6 V5 V4 V3 V2 V1 V0 \n\ + punpcklbw %%xmm3, %%xmm2 # XMM2: V7 U7 V6 ..... U1 V0 U0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\ + punpcklbw %%xmm2, %%xmm0 # XMM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + punpckhbw %%xmm2, %%xmm1 # XMM1: V7 YF U7 ..... Y9 U4 Y8 \n\ + movdqu %%xmm0, -32("EDI","ECX",4) \n\ + movdqu %%xmm1, -16("EDI","ECX",4)", \ + /* emms */ "emms") + +/* YUV411P -> YUY2 (unit: 4 pixels) */ +#define YUV411P_YUY2 \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "push "EBX, \ + /* pop_regs */ "pop "EBX, \ + /* small_loop */ \ + "movb -1("EDX","ECX"), %%bh \n\ + movb -1("ESI","ECX",4), %%bl \n\ + shll $16, %%ebx \n\ + movb -1("EAX","ECX"), %%bh \n\ + movb -2("ESI","ECX",4), %%bl \n\ + movl %%ebx, -4("EDI","ECX",8) \n\ + movb -1("EDX","ECX"), %%bh \n\ + movb -3("ESI","ECX",4), %%bl \n\ + shll $16, %%ebx \n\ + movb -1("EAX","ECX"), %%bh \n\ + movb -4("ESI","ECX",4), %%bl \n\ + movl %%ebx, -8("EDI","ECX",8)", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",4),%%xmm0 #XM0: YF YE YD ..... Y2 Y1 Y0 \n\ + movd -4("EAX","ECX"), %%xmm2 # XMM2: U3 U2 U1 U0 \n\ + punpcklbw %%xmm2, %%xmm2 # XMM2: U3 U3 U2 U2 U1 U1 U0 U0 \n\ + movd -4("EDX","ECX"), %%xmm3 # XMM3: V3 V2 V1 V0 \n\ + punpcklbw %%xmm3, %%xmm3 # XMM3: V3 V3 V2 V2 V1 V1 V0 V0 \n\ + punpcklbw %%xmm3, %%xmm2 # XMM2: V3 U3 V3 ..... U0 V0 U0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\ + punpcklbw %%xmm2, %%xmm0 # XMM0: V1 Y7 U1 ..... Y1 U0 Y0 \n\ + punpckhbw %%xmm2, %%xmm1 # XMM1: V3 YF U3 ..... Y9 U2 Y8 \n\ + movdqu %%xmm0, -32("EDI","ECX",8) \n\ + movdqu %%xmm1, -16("EDI","ECX",8)", \ + /* emms */ "emms") + +/* YUV444P -> YUY2 (unit: 2 pixels) */ +#define YUV444P_YUY2 \ + /* Load 0x00FF*8 into XMM7 for masking */ \ + "pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "push "EBX"; push "EBP, \ + /* pop_regs */ "pop "EBP"; pop "EBX, \ + /* small_loop */ \ + "movzbl -1("EDX","ECX",2), %%ebx \n\ + movzbl -2("EDX","ECX",2), %%ebp \n\ + addl %%ebp, %%ebx \n\ + shrl $1, %%ebx \n\ + movb %%bl, -1("EDI","ECX",4) \n\ + movb -1("ESI","ECX",2), %%bl \n\ + movb %%bl, -2("EDI","ECX",4) \n\ + movzbl -1("EAX","ECX",2), %%ebx \n\ + movzbl -2("EAX","ECX",2), %%ebp \n\ + addl %%ebp, %%ebx \n\ + shrl $1, %%ebx \n\ + movb %%bl, -3("EDI","ECX",4) \n\ + movb -2("ESI","ECX",2), %%bl \n\ + movb %%bl, -4("EDI","ECX",4)", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",2),%%xmm0 #XM0: YF YE YD ..... Y2 Y1 Y0 \n\ + movdqu -16("EAX","ECX",2), %%xmm2 #XM2: UF UE UD ..... U2 U1 U0 \n\ + movdqu -16("EDX","ECX",2), %%xmm3 #XM3: VF VE VD ..... V2 V1 V0 \n\ + movdqa %%xmm2, %%xmm4 # XMM4: UF UE UD ..... U2 U1 U0 \n\ + pand %%xmm7, %%xmm2 # XMM2: -- UE -- ..... U2 -- U0 \n\ + psrlw $8, %%xmm4 # XMM4: -- UF -- ..... U3 -- U1 \n\ + pavgw %%xmm4, %%xmm2 # XMM2: -- u7 -- ..... u1 -- u0 \n\ + movdqa %%xmm3, %%xmm5 # XMM4: UF UE UD ..... U2 U1 U0 \n\ + pand %%xmm7, %%xmm3 # XMM3: -- VE -- ..... V2 -- V0 \n\ + psrlw $8, %%xmm5 # XMM5: -- VF -- ..... V3 -- V1 \n\ + pavgw %%xmm5, %%xmm3 # XMM3: -- v7 -- ..... v1 -- v0 \n\ + psllw $8, %%xmm3 # XMM3: v7 -- v6 ..... -- v0 -- \n\ + por %%xmm3, %%xmm2 # XMM2: v7 u7 v6 ..... u1 v0 u0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\ + punpcklbw %%xmm2, %%xmm0 # XMM0: v3 Y7 u3 ..... Y1 u0 Y0 \n\ + punpckhbw %%xmm2, %%xmm1 # XMM1: v7 YF u7 ..... Y9 u4 Y8 \n\ + movdqu %%xmm0, -32("EDI","ECX",4) \n\ + movdqu %%xmm1, -16("EDI","ECX",4)", \ + /* emms */ "emms") + +/* YUY2 -> YUV420P (U row) (unit: 2 pixels) */ +#define YUY2_YUV420P_U \ + /* Load 0x00FF*8 into XMM7 for masking */ \ + "pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "push "EBX"; push "EBP, \ + /* pop_regs */ "pop "EBP"; pop "EBX, \ + /* small_loop */ \ + "movb -4("ESI","ECX",4), %%bl \n\ + movb %%bl, -2("EDI","ECX",2) \n\ + movb -2("ESI","ECX",4), %%bl \n\ + movb %%bl, -1("EDI","ECX",2) \n\ + movzbl -3("ESI","ECX",4), %%ebx \n\ + movzbl -3("EAX","ECX",4), %%ebp \n\ + addl %%ebp, %%ebx \n\ + shrl $1, %%ebx \n\ + movb %%bl, -1("EDX","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + movdqu -16("EAX","ECX",4),%%xmm2 #XMM2: Vd Yh Ud ..... Yb Ua Ya \n\ + pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\ + psrlw $8, %%xmm2 # XMM2: -- Vd -- ..... Va -- Ua \n\ + pavgw %%xmm2, %%xmm1 # XMM1: -- v3 -- ..... v0 -- u0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: v3 u3 v2 u2 v1 u1 v0 u0 \n\ + pand %%xmm7, %%xmm1 # XMM1: -- u3 -- u2 -- u1 -- u0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: u3 u2 u1 u0 \n\ + movq %%xmm0, -8("EDI","ECX",2) \n\ + movd %%xmm1, -4("EDX","ECX")", \ + /* emms */ "emms") + +/* YUY2 -> YUV420P (V row) (unit: 2 pixels) */ +#define YUY2_YUV420P_V \ + /* Load 0x00FF*8 into XMM7 for masking */ \ + "pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "push "EBX"; push "EBP, \ + /* pop_regs */ "pop "EBP"; pop "EBX, \ + /* small_loop */ \ + "movb -4("ESI","ECX",4), %%bl \n\ + movb %%bl, -2("EDI","ECX",2) \n\ + movb -2("ESI","ECX",4), %%bl \n\ + movb %%bl, -1("EDI","ECX",2) \n\ + movzbl -1("ESI","ECX",4), %%ebx \n\ + movzbl -1("EAX","ECX",4), %%ebp \n\ + addl %%ebp, %%ebx \n\ + shrl $1, %%ebx \n\ + movb %%bl, -1("EDX","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + movdqu -16("EAX","ECX",4),%%xmm2 #XMM2: Vd Yh Ud ..... Yb Ua Ya \n\ + pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\ + psrlw $8, %%xmm2 # XMM2: -- Vd -- ..... Va -- Ua \n\ + pavgw %%xmm1, %%xmm2 # XMM2: -- v3 -- ..... v0 -- u0 \n\ + packuswb %%xmm2, %%xmm2 # XMM2: v3 u3 v2 u2 v1 u1 v0 u0 \n\ + psrlw $8, %%xmm2 # XMM2: -- v3 -- v2 -- v1 -- v0 \n\ + packuswb %%xmm2, %%xmm2 # XMM2: v3 v2 v1 v0 \n\ + movq %%xmm0, -8("EDI","ECX",2) \n\ + movd %%xmm2, -4("EDX","ECX")", \ + /* emms */ "emms") + +/* YUY2 -> YUV411P (unit: 4 pixels) */ +#define YUY2_YUV411P \ + /* Load 0x000..000FFFFFFFF into XMM6, 0x00FF*8 into XMM7 for masking */ \ + "pcmpeqd %%xmm6, %%xmm6; psrldq $12, %%xmm6;" \ + "pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 2, \ + /* push_regs */ "push "EBX"; push "EBP, \ + /* pop_regs */ "pop "EBP"; pop "EBX, \ + /* small_loop */ \ + "movb -8("ESI","ECX",8), %%bl \n\ + movb %%bl, -4("EDI","ECX",4) \n\ + movb -6("ESI","ECX",8), %%bl \n\ + movb %%bl, -3("EDI","ECX",4) \n\ + movb -4("ESI","ECX",8), %%bl \n\ + movb %%bl, -2("EDI","ECX",4) \n\ + movb -2("ESI","ECX",8), %%bl \n\ + movb %%bl, -1("EDI","ECX",4) \n\ + movzbl -7("ESI","ECX",8), %%ebx \n\ + movzbl -3("ESI","ECX",8), %%ebp \n\ + addl %%ebp, %%ebx \n\ + shrl $1, %%ebx \n\ + movb %%bl, -1("EAX","ECX") \n\ + movzbl -5("ESI","ECX",8), %%ebx \n\ + movzbl -1("ESI","ECX",8), %%ebp \n\ + addl %%ebp, %%ebx \n\ + shrl $1, %%ebx \n\ + movb %%bl, -1("EDX","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",8),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + movdqa %%xmm1, %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + pand %%xmm7, %%xmm1 # XMM1: -- U3 -- U2 -- U1 -- U0 \n\ + psrlw $8, %%xmm2 # XMM2: -- V3 -- V2 -- V1 -- V0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: U3 U2 U1 U0 \n\ + packuswb %%xmm2, %%xmm2 # XMM2: V3 V2 V1 V0 \n\ + pand %%xmm6, %%xmm1 # XMM1: -- -- -- -- U3 U2 U1 U0 \n\ + psllq $32, %%xmm2 # XMM2: V3 V2 V1 V0 -- -- -- -- \n\ + por %%xmm1, %%xmm2 # XMM2: V3 V2 V1 V0 U3 U2 U1 U0 \n\ + movdqa %%xmm2, %%xmm1 # XMM1: V3 V2 V1 V0 U3 U2 U1 U0 \n\ + pand %%xmm7, %%xmm1 # XMM1: -- V2 -- V0 -- U2 -- U0 \n\ + psrlw $8, %%xmm2 # XMM2: -- V3 -- V1 -- U3 -- U1 \n\ + pavgw %%xmm2, %%xmm1 # XMM1: -- v1 -- v0 -- u1 -- u0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: v1 v0 u1 u0 \n\ + movq %%xmm0, -8("EDI","ECX",4) \n\ + movd %%xmm1, %%ebx \n\ + movw %%bx, -2("EAX","ECX") \n\ + shrl $16, %%ebx; \n\ + movw %%bx, -2("EDX","ECX")", \ + /* emms */ "emms") + +/* YUY2 -> YUV422P (unit: 2 pixels) */ +#define YUY2_YUV422P \ + /* Load 0x00FF*8 into XMM7 for masking */ \ + "pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "push "EBX, \ + /* pop_regs */ "pop "EBX, \ + /* small_loop */ \ + "movb -4("ESI","ECX",4), %%bl \n\ + movb %%bl, -2("EDI","ECX",2) \n\ + movb -2("ESI","ECX",4), %%bl \n\ + movb %%bl, -1("EDI","ECX",2) \n\ + movb -3("ESI","ECX",4), %%bl \n\ + movb %%bl, -1("EAX","ECX") \n\ + movb -1("ESI","ECX",4), %%bl \n\ + movb %%bl, -1("EDX","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + movdqa %%xmm1, %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + pand %%xmm7, %%xmm1 # XMM1: -- U3 -- U2 -- U1 -- U0 \n\ + psrlw $8, %%xmm2 # XMM2: -- V3 -- V2 -- V1 -- V0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: U3 U2 U1 U0 \n\ + packuswb %%xmm2, %%xmm2 # XMM2: V3 V2 V1 V0 \n\ + movq %%xmm0, -8("EDI","ECX",2) \n\ + movd %%xmm1, -4("EAX","ECX") \n\ + movd %%xmm2, -4("EDX","ECX")", \ + /* emms */ "emms") + +/* YUY2 -> YUV444P (unit: 2 pixels) */ +#define YUY2_YUV444P \ + /* Load 0x00FF*8 into XMM7 for masking */ \ + "pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "push "EBX, \ + /* pop_regs */ "pop "EBX, \ + /* small_loop */ \ + "movb -4("ESI","ECX",4), %%bl \n\ + movb %%bl, -2("EDI","ECX",2) \n\ + movb -2("ESI","ECX",4), %%bl \n\ + movb %%bl, -1("EDI","ECX",2) \n\ + movb -3("ESI","ECX",4), %%bl \n\ + movb %%bl, -2("EAX","ECX",2) \n\ + movb %%bl, -1("EAX","ECX",2) \n\ + movb -1("ESI","ECX",4), %%bl \n\ + movb %%bl, -2("EDX","ECX",2) \n\ + movb %%bl, -1("EDX","ECX",2)", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",4),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + psrlw $8, %%xmm1 # XMM1: -- V3 -- ..... V0 -- U0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + movdqa %%xmm1, %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + pand %%xmm7, %%xmm1 # XMM1: -- U3 -- U2 -- U1 -- U0 \n\ + psrlw $8, %%xmm2 # XMM2: -- V3 -- V2 -- V1 -- V0 \n\ + movdqa %%xmm1, %%xmm3 # XMM3: -- U3 -- U2 -- U1 -- U0 \n\ + psllw $8, %%xmm3 # XMM3: U3 -- U2 -- U1 -- U0 -- \n\ + por %%xmm3, %%xmm1 # XMM1: U3 U3 U2 U2 U1 U1 U0 U0 \n\ + movdqa %%xmm2, %%xmm3 # XMM3: -- V3 -- V2 -- V1 -- V0 \n\ + psllw $8, %%xmm3 # XMM3: V3 -- V2 -- V1 -- V0 -- \n\ + por %%xmm3, %%xmm2 # XMM1: V3 V3 V2 V2 V1 V1 V0 V0 \n\ + movq %%xmm0, -8("EDI","ECX",2) \n\ + movq %%xmm1, -8("EAX","ECX",2) \n\ + movq %%xmm2, -8("EDX","ECX",2)", \ + /* emms */ "emms") + + +/* Y8 -> YUY2/YVYU (unit: 1 pixel) */ +#define Y8_YUY2 \ + /* Load 0x80*16 into XMM7 for interlacing U/V */ \ + "pcmpeqd %%xmm7, %%xmm7; psllw $7, %%xmm7; packsswb %%xmm7, %%xmm7;"\ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 16, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movb -1("ESI","ECX"), %%al \n\ + movb %%al, -2("EDI","ECX",2) \n\ + movb $0x80, -1("EDI","ECX",2)", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX"),%%xmm0 # XMM0: YF YE YD ..... Y2 Y1 Y0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: YF YE YD ..... Y2 Y1 Y0 \n\ + punpcklbw %%xmm7, %%xmm0 # XMM0: 80 Y7 80 ..... Y1 80 Y0 \n\ + movdqu %%xmm0, -32("EDI","ECX",2) \n\ + punpckhbw %%xmm7, %%xmm1 # XMM1: 80 YF 80 ..... Y9 80 Y8 \n\ + movdqu %%xmm1, -16("EDI","ECX",2)", \ + /* emms */ "emms") + +/* Y8 -> UYVY (unit: 1 pixel) */ +#define Y8_UYVY \ + /* Load 0x80*16 into XMM7 for interlacing U/V */ \ + "pcmpeqd %%xmm7, %%xmm7; psllw $7, %%xmm7; packsswb %%xmm7, %%xmm7;"\ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 16, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movb -1("ESI","ECX"), %%al \n\ + movb %%al, -1("EDI","ECX",2) \n\ + movb $0x80, -2("EDI","ECX",2)", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX"),%%xmm0 # XMM0: YF YE YD ..... Y2 Y1 Y0 \n\ + movdqa %%xmm7, %%xmm1 # XMM1: 80 80 80 ..... 80 80 80 \n\ + punpcklbw %%xmm0, %%xmm1 # XMM1: Y7 80 Y6 ..... 80 Y0 80 \n\ + movdqu %%xmm1, -32("EDI","ECX",2) \n\ + movdqa %%xmm7, %%xmm2 # XMM2: 80 80 80 ..... 80 80 80 \n\ + punpckhbw %%xmm0, %%xmm2 # XMM0: YF 80 YE ..... 80 Y8 80 \n\ + movdqu %%xmm2, -16("EDI","ECX",2)", \ + /* emms */ "emms") + +/* YUY2/YVYU -> Y8 (unit: 1 pixel) */ +#define YUY2_Y8 \ + /* Load 0x00FF*8 into XMM7 for masking */ \ + "pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movb -2("ESI","ECX",2), %%al \n\ + movb %%al, -1("EDI","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",2),%%xmm0 #XM0: V3 Y7 U3 ..... Y1 U0 Y0 \n\ + pand %%xmm7, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + movq %%xmm0, -8("EDI","ECX")", \ + /* emms */ "emms") + +/* UYVY -> Y8 (unit: 1 pixel) */ +#define UYVY_Y8 \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movb -1("ESI","ECX",2), %%al \n\ + movb %%al, -1("EDI","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",2),%%xmm0 #XM0: Y7 V3 Y6 ..... V0 Y0 U0 \n\ + psrlw $8, %%xmm0 # XMM0: -- Y7 -- ..... Y1 -- Y0 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + movq %%xmm0, -8("EDI","ECX")", \ + /* emms */ "emms") + +/*************************************************************************/ + +static int yuv420p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + for (y = 0; y < (height & ~1); y++) { + asm(YUV42XP_YUY2 + : /* no outputs */ + : "S" (src[0]+y*width), "a" (src[1]+(y/2)*(width/2)), + "d" (src[2]+(y/2)*(width/2)), "D" (dest[0]+y*width*2), + "c" (width/2)); + } + return 1; +} + +static int yuv411p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!(width & 3)) { + asm(YUV411P_YUY2 + : /* no outputs */ + : "S" (src[0]), "a" (src[1]), "d" (src[2]), "D" (dest[0]), + "c" ((width/4)*height)); + } else { + int y; + for (y = 0; y < height; y++) { + asm(YUV411P_YUY2 + : /* no outputs */ + : "S" (src[0]+y*width), "a" (src[1]+y*(width/4)), + "d" (src[2]+y*(width/4)), "D" (dest[0]+y*width*2), + "c" (width/4)); + } + } + return 1; +} + +static int yuv422p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!(width & 1)) { + asm(YUV42XP_YUY2 + : /* no outputs */ + : "S" (src[0]), "a" (src[1]), "d" (src[2]), "D" (dest[0]), + "c" ((width/2)*height)); + } else { + int y; + for (y = 0; y < height; y++) { + asm(YUV42XP_YUY2 + : /* no outputs */ + : "S" (src[0]+y*width), "a" (src[1]+y*(width/2)), + "d" (src[2]+y*(width/2)), "D" (dest[0]+y*width*2), + "c" (width/2)); + } + } + return 1; +} + +static int yuv444p_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!(width & 1)) { + asm(YUV444P_YUY2 + : /* no outputs */ + : "S" (src[0]), "a" (src[1]), "d" (src[2]), "D" (dest[0]), + "c" ((width/2)*height)); + } else { + int y; + for (y = 0; y < height; y++) { + asm(YUV444P_YUY2 + : /* no outputs */ + : "S" (src[0]+y*width), "a" (src[1]+y*(width/2)), + "d" (src[2]+y*(width/2)), "D" (dest[0]+y*width*2), + "c" (width/2)); + } + } + return 1; +} + +/*************************************************************************/ + +static int yuy2_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + + for (y = 0; y < (height & ~1); y += 2) { + asm(YUY2_YUV420P_U + : /* no outputs */ + : "S" (src[0]+y*width*2), "a" (src[0]+(y+1)*width*2), + "D" (dest[0]+y*width), "d" (dest[1]+(y/2)*(width/2)), + "c" (width/2)); + asm(YUY2_YUV420P_V + : /* no outputs */ + : "S" (src[0]+(y+1)*width*2), "a" (src[0]+y*width*2), + "D" (dest[0]+(y+1)*width), "d" (dest[2]+(y/2)*(width/2)), + "c" (width/2)); + } + return 1; +} + +static int yuy2_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!(width & 3)) { + asm(YUY2_YUV411P + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "a" (dest[1]), "d" (dest[2]), + "c" ((width/4)*height)); + } else { + int y; + for (y = 0; y < height; y++) { + asm(YUY2_YUV411P + : /* no outputs */ + : "S" (src[0]+y*width*2), "D" (dest[0]+y*width), + "a" (dest[1]+y*(width/4)), "d" (dest[2]+y*(width/4)), + "c" (width/4)); + } + } + return 1; +} + +static int yuy2_yuv422p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!(width & 1)) { + asm(YUY2_YUV422P + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "a" (dest[1]), "d" (dest[2]), + "c" ((width/2)*height)); + } else { + int y; + for (y = 0; y < height; y++) { + asm(YUY2_YUV422P + : /* no outputs */ + : "S" (src[0]+y*width*2), "D" (dest[0]+y*width), + "a" (dest[1]+y*(width/2)), "d" (dest[2]+y*(width/2)), + "c" (width/2)); + } + } + return 1; +} + +static int yuy2_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!(width & 1)) { + asm(YUY2_YUV444P + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "a" (dest[1]), "d" (dest[2]), + "c" ((width/2)*height)); + } else { + int y; + for (y = 0; y < height; y++) { + asm(YUY2_YUV444P + : /* no outputs */ + : "S" (src[0]+y*width*2), "D" (dest[0]+y*width), + "a" (dest[1]+y*width), "d" (dest[2]+y*width), + "c" (width/2)); + } + } + return 1; +} + +/*************************************************************************/ + +static int y8_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm(Y8_YUY2 + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height) + : "eax"); + return 1; +} + +static int y8_uyvy_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm(Y8_UYVY + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height) + : "eax"); + return 1; +} + +static int yuy2_y8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm(YUY2_Y8 + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height) + : "eax"); + return 1; +} + +static int uyvy_y8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm(UYVY_Y8 + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height) + : "eax"); + return 1; +} + +/*************************************************************************/ + +#endif /* HAVE_ASM_SSE2 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Initialization */ + +int ac_imgconvert_init_yuv_mixed(int accel) +{ + if (!register_conversion(IMG_YUV420P, IMG_YUY2, yuv420p_yuy2) + || !register_conversion(IMG_YUV411P, IMG_YUY2, yuv411p_yuy2) + || !register_conversion(IMG_YUV422P, IMG_YUY2, yuv422p_yuy2) + || !register_conversion(IMG_YUV444P, IMG_YUY2, yuv444p_yuy2) + || !register_conversion(IMG_Y8, IMG_YUY2, y8_yuy2) + || !register_conversion(IMG_YUV420P, IMG_UYVY, yuv420p_uyvy) + || !register_conversion(IMG_YUV411P, IMG_UYVY, yuv411p_uyvy) + || !register_conversion(IMG_YUV422P, IMG_UYVY, yuv422p_uyvy) + || !register_conversion(IMG_YUV444P, IMG_UYVY, yuv444p_uyvy) + || !register_conversion(IMG_Y8, IMG_UYVY, y8_uyvy) + || !register_conversion(IMG_YUV420P, IMG_YVYU, yuv420p_yvyu) + || !register_conversion(IMG_YUV411P, IMG_YVYU, yuv411p_yvyu) + || !register_conversion(IMG_YUV422P, IMG_YVYU, yuv422p_yvyu) + || !register_conversion(IMG_YUV444P, IMG_YVYU, yuv444p_yvyu) + || !register_conversion(IMG_Y8, IMG_YVYU, y8_yuy2) + + || !register_conversion(IMG_YUY2, IMG_YUV420P, yuy2_yuv420p) + || !register_conversion(IMG_YUY2, IMG_YUV411P, yuy2_yuv411p) + || !register_conversion(IMG_YUY2, IMG_YUV422P, yuy2_yuv422p) + || !register_conversion(IMG_YUY2, IMG_YUV444P, yuy2_yuv444p) + || !register_conversion(IMG_YUY2, IMG_Y8, yuy2_y8) + || !register_conversion(IMG_UYVY, IMG_YUV420P, uyvy_yuv420p) + || !register_conversion(IMG_UYVY, IMG_YUV411P, uyvy_yuv411p) + || !register_conversion(IMG_UYVY, IMG_YUV422P, uyvy_yuv422p) + || !register_conversion(IMG_UYVY, IMG_YUV444P, uyvy_yuv444p) + || !register_conversion(IMG_UYVY, IMG_Y8, uyvy_y8) + || !register_conversion(IMG_YVYU, IMG_YUV420P, yvyu_yuv420p) + || !register_conversion(IMG_YVYU, IMG_YUV411P, yvyu_yuv411p) + || !register_conversion(IMG_YVYU, IMG_YUV422P, yvyu_yuv422p) + || !register_conversion(IMG_YVYU, IMG_YUV444P, yvyu_yuv444p) + || !register_conversion(IMG_YVYU, IMG_Y8, yuy2_y8) + ) { + return 0; + } + +#if defined(HAVE_ASM_SSE2) + if (accel & AC_SSE2) { + if (!register_conversion(IMG_YUV420P, IMG_YUY2, yuv420p_yuy2_sse2) + || !register_conversion(IMG_YUV411P, IMG_YUY2, yuv411p_yuy2_sse2) + || !register_conversion(IMG_YUV422P, IMG_YUY2, yuv422p_yuy2_sse2) + || !register_conversion(IMG_YUV444P, IMG_YUY2, yuv444p_yuy2_sse2) + || !register_conversion(IMG_Y8, IMG_YUY2, y8_yuy2_sse2) + || !register_conversion(IMG_Y8, IMG_UYVY, y8_uyvy_sse2) + || !register_conversion(IMG_Y8, IMG_YVYU, y8_yuy2_sse2) + + || !register_conversion(IMG_YUY2, IMG_YUV420P, yuy2_yuv420p_sse2) + || !register_conversion(IMG_YUY2, IMG_YUV411P, yuy2_yuv411p_sse2) + || !register_conversion(IMG_YUY2, IMG_YUV422P, yuy2_yuv422p_sse2) + || !register_conversion(IMG_YUY2, IMG_YUV444P, yuy2_yuv444p_sse2) + || !register_conversion(IMG_YUY2, IMG_Y8, yuy2_y8_sse2) + || !register_conversion(IMG_UYVY, IMG_Y8, uyvy_y8_sse2) + || !register_conversion(IMG_YVYU, IMG_Y8, yuy2_y8_sse2) + ) { + return 0; + } + } +#endif /* ARCH_X86 || ARCH_X86_64 */ + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/img_yuv_packed.c b/branches/V-1.5.3/veejay-server/aclib/img_yuv_packed.c new file mode 100644 index 00000000..05357405 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/img_yuv_packed.c @@ -0,0 +1,290 @@ +/* + * img_yuv_packed.c - YUV packed image format conversion routines + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "imgconvert.h" +#include "img_internal.h" + +/*************************************************************************/ +/*************************************************************************/ + +/* Standard C implementations */ + +/*************************************************************************/ + +/* Identity transformation, works when src==dest */ +static int yuv16_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height*2); + return 1; +} + +/* Used for YUY2->UYVY and UYVY->YUY2, works when src==dest */ +static int yuv16_swap16(uint8_t **src, uint8_t **dest, int width, int height) +{ + uint16_t *srcp = (uint16_t *)src[0]; + uint16_t *destp = (uint16_t *)dest[0]; + int i; + for (i = 0; i < width*height; i++) + destp[i] = srcp[i]>>8 | srcp[i]<<8; + return 1; +} + +/* Used for YUY2->YVYU and YVYU->YUY2, works when src==dest */ +static int yuv16_swapuv(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height/2; i++) { + uint8_t tmp = src[0][i*4+1]; + dest[0][i*4 ] = src[0][i*4 ]; + dest[0][i*4+1] = src[0][i*4+3]; + dest[0][i*4+2] = src[0][i*4+2]; + dest[0][i*4+3] = tmp; + } + return 1; +} + +/*************************************************************************/ + +static int uyvy_yvyu(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height/2; i++) { + dest[0][i*4 ] = src[0][i*4+1]; + dest[0][i*4+1] = src[0][i*4+2]; + dest[0][i*4+2] = src[0][i*4+3]; + dest[0][i*4+3] = src[0][i*4 ]; + } + return 1; +} + +static int yvyu_uyvy(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + for (i = 0; i < width*height/2; i++) { + dest[0][i*4 ] = src[0][i*4+3]; + dest[0][i*4+1] = src[0][i*4 ]; + dest[0][i*4+2] = src[0][i*4+1]; + dest[0][i*4+3] = src[0][i*4+2]; + } + return 1; +} + +/*************************************************************************/ +/*************************************************************************/ + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + +/* Common macros/data for x86 code */ +#define DEFINE_MASK_DATA +#include "img_x86_common.h" + +/*************************************************************************/ + +/* Basic assembly routines */ + +static int yuv16_swap16_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP16_2_X86(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +static int yuv16_swapuv_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_13_X86(width*height/2); + return 1; +} + +static int uyvy_yvyu_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROR32_X86(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +static int yvyu_uyvy_x86(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROL32_X86(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +/*************************************************************************/ + +/* MMX routines */ + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */ + +static int yuv16_swap16_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP16_2_MMX(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +static int yuv16_swapuv_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_13_MMX(width*height/2); + return 1; +} + +static int uyvy_yvyu_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROR32_MMX(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +static int yvyu_uyvy_mmx(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROL32_MMX(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +#endif /* HAVE_ASM_MMX && ARCH_X86 */ + +/*************************************************************************/ + +/* SSE2 routines */ + +#if defined(HAVE_ASM_SSE2) + +static int yuv16_swap16_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP16_2_SSE2(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +static int yuv16_swapuv_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_SWAP32_13_SSE2(width*height/2); + return 1; +} + +static int uyvy_yvyu_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROR32_SSE2(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +static int yvyu_uyvy_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ASM_ROL32_SSE2(width*height/2); + if (width*height % 1) + ((uint16_t *)(dest[0]))[width*height-1] = + src[0][width*height*2-2]<<8 | src[0][width*height*2-1]; + return 1; +} + +#endif /* HAVE_ASM_SSE2 */ + +/*************************************************************************/ + +#endif /* ARCH_X86 || ARCH_X86_64 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Initialization */ + +int ac_imgconvert_init_yuv_packed(int accel) +{ + if (!register_conversion(IMG_YUY2, IMG_YUY2, yuv16_copy) + || !register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16) + || !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv) + + || !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16) + || !register_conversion(IMG_UYVY, IMG_UYVY, yuv16_copy) + || !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu) + + || !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv) + || !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy) + || !register_conversion(IMG_YVYU, IMG_YVYU, yuv16_copy) + ) { + return 0; + } + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + if (accel & (AC_IA32ASM | AC_AMD64ASM)) { + if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_x86) + || !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_x86) + || !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_x86) + || !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_x86) + || !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_x86) + || !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_x86) + ) { + return 0; + } + } + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) + if (accel & AC_MMX) { + if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_mmx) + || !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_mmx) + || !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_mmx) + || !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_mmx) + || !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_mmx) + || !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_mmx) + ) { + return 0; + } + } +#endif + +#if defined(HAVE_ASM_SSE2) + if (accel & AC_SSE2) { + if (!register_conversion(IMG_YUY2, IMG_UYVY, yuv16_swap16_sse2) + || !register_conversion(IMG_YUY2, IMG_YVYU, yuv16_swapuv_sse2) + || !register_conversion(IMG_UYVY, IMG_YUY2, yuv16_swap16_sse2) + || !register_conversion(IMG_UYVY, IMG_YVYU, uyvy_yvyu_sse2) + || !register_conversion(IMG_YVYU, IMG_YUY2, yuv16_swapuv_sse2) + || !register_conversion(IMG_YVYU, IMG_UYVY, yvyu_uyvy_sse2) + ) { + return 0; + } + } +#endif + +#endif /* ARCH_X86 || ARCH_X86_64 */ + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/img_yuv_planar.c b/branches/V-1.5.3/veejay-server/aclib/img_yuv_planar.c new file mode 100644 index 00000000..3ebef89a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/img_yuv_planar.c @@ -0,0 +1,771 @@ +/* + * img_yuv_planar.c - YUV planar image format conversion routines + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "imgconvert.h" +#include "img_internal.h" + +#include + +/*************************************************************************/ +/*************************************************************************/ + +/* Standard C implementations */ + +/*************************************************************************/ + +/* Identity transformations */ + +static int yuv420p_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + ac_memcpy(dest[1], src[1], (width/2)*(height/2)); + ac_memcpy(dest[2], src[2], (width/2)*(height/2)); + return 1; +} + +static int yuv411p_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + ac_memcpy(dest[1], src[1], (width/4)*height); + ac_memcpy(dest[2], src[2], (width/4)*height); + return 1; +} + +static int yuv422p_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + ac_memcpy(dest[1], src[1], (width/2)*height); + ac_memcpy(dest[2], src[2], (width/2)*height); + return 1; +} + +static int yuv444p_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + ac_memcpy(dest[1], src[1], width*height); + ac_memcpy(dest[2], src[2], width*height); + return 1; +} + +static int y8_copy(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + return 1; +} + +/*************************************************************************/ + +static int yuv420p_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + for (x = 0; x < (width/2 & ~1); x += 2) { + dest[1][y*(width/4)+x/2] = (src[1][(y/2)*(width/2)+x] + + src[1][(y/2)*(width/2)+x+1] + 1) / 2; + dest[2][y*(width/4)+x/2] = (src[2][(y/2)*(width/2)+x] + + src[2][(y/2)*(width/2)+x+1] + 1) / 2; + } + ac_memcpy(dest[1]+(y+1)*(width/4), dest[1]+y*(width/4), width/4); + ac_memcpy(dest[2]+(y+1)*(width/4), dest[2]+y*(width/4), width/4); + } + return 1; +} + +static int yuv420p_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + ac_memcpy(dest[1]+(y )*(width/2), src[1]+(y/2)*(width/2), width/2); + ac_memcpy(dest[1]+(y+1)*(width/2), src[1]+(y/2)*(width/2), width/2); + ac_memcpy(dest[2]+(y )*(width/2), src[2]+(y/2)*(width/2), width/2); + ac_memcpy(dest[2]+(y+1)*(width/2), src[2]+(y/2)*(width/2), width/2); + } + return 1; +} + +static int yuv420p_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y += 2) { + for (x = 0; x < width; x += 2) { + dest[1][y*width+x ] = + dest[1][y*width+x+1] = src[1][(y/2)*(width/2)+(x/2)]; + dest[2][y*width+x ] = + dest[2][y*width+x+1] = src[2][(y/2)*(width/2)+(x/2)]; + } + ac_memcpy(dest[1]+(y+1)*width, dest[1]+y*width, width); + ac_memcpy(dest[2]+(y+1)*width, dest[2]+y*width, width); + } + return 1; +} + +/*************************************************************************/ + +static int yuv411p_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + for (x = 0; x < ((width/2) & ~1); x += 2) { + dest[1][(y/2)*(width/2)+x] = (src[1][y*(width/4)+x/2] + + src[1][(y+1)*(width/4)+x/2] + 1) / 2; + dest[2][(y/2)*(width/2)+x] = (src[2][y*(width/4)+x/2] + + src[2][(y+1)*(width/4)+x/2] + 1) / 2; + dest[1][(y/2)*(width/2)+x+1] = dest[1][(y/2)*(width/2)+x]; + dest[2][(y/2)*(width/2)+x+1] = dest[2][(y/2)*(width/2)+x]; + } + } + return 1; +} + +static int yuv411p_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y++) { + for (x = 0; x < ((width/2) & ~1); x += 2) { + dest[1][y*(width/2)+x ] = src[1][y*(width/4)+x/2]; + dest[1][y*(width/2)+x+1] = src[1][y*(width/4)+x/2]; + dest[2][y*(width/2)+x ] = src[2][y*(width/4)+x/2]; + dest[2][y*(width/2)+x+1] = src[2][y*(width/4)+x/2]; + } + } + return 1; +} + +static int yuv411p_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y++) { + for (x = 0; x < (width & ~3); x += 4) { + dest[1][y*width+x ] = src[1][y*(width/4)+x/4]; + dest[1][y*width+x+1] = src[1][y*(width/4)+x/4]; + dest[1][y*width+x+2] = src[1][y*(width/4)+x/4]; + dest[1][y*width+x+3] = src[1][y*(width/4)+x/4]; + dest[2][y*width+x ] = src[2][y*(width/4)+x/4]; + dest[2][y*width+x+1] = src[2][y*(width/4)+x/4]; + dest[2][y*width+x+2] = src[2][y*(width/4)+x/4]; + dest[2][y*width+x+3] = src[2][y*(width/4)+x/4]; + } + } + return 1; +} + +/*************************************************************************/ + +static int yuv422p_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + for (x = 0; x < width/2; x++) { + dest[1][(y/2)*(width/2)+x] = (src[1][y*(width/2)+x] + + src[1][(y+1)*(width/2)+x] + 1) / 2; + dest[2][(y/2)*(width/2)+x] = (src[2][y*(width/2)+x] + + src[2][(y+1)*(width/2)+x] + 1) / 2; + } + } + return 1; +} + +static int yuv422p_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y++) { + for (x = 0; x < ((width/2) & ~1); x += 2) { + dest[1][y*(width/4)+x/2] = (src[1][y*(width/2)+x] + + src[1][y*(width/2)+x+1] + 1) / 2; + dest[2][y*(width/4)+x/2] = (src[2][y*(width/2)+x] + + src[2][y*(width/2)+x+1] + 1) / 2; + } + } + return 1; +} + +static int yuv422p_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y++) { + for (x = 0; x < (width & ~1); x += 2) { + dest[1][y*width+x ] = src[1][y*(width/2)+x/2]; + dest[1][y*width+x+1] = src[1][y*(width/2)+x/2]; + dest[2][y*width+x ] = src[2][y*(width/2)+x/2]; + dest[2][y*width+x+1] = src[2][y*(width/2)+x/2]; + } + } + return 1; +} + +/*************************************************************************/ + +static int yuv444p_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + for (x = 0; x < (width & ~1); x += 2) { + dest[1][(y/2)*(width/2)+x/2] = (src[1][y*width+x] + + src[1][y*width+x+1] + + src[1][(y+1)*width+x] + + src[1][(y+1)*width+x+1] + 2) / 4; + dest[2][(y/2)*(width/2)+x/2] = (src[2][y*width+x] + + src[2][y*width+x+1] + + src[2][(y+1)*width+x] + + src[2][(y+1)*width+x+1] + 2) / 4; + } + } + return 1; +} + +static int yuv444p_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y++) { + for (x = 0; x < (width & ~3); x += 4) { + dest[1][y*(width/4)+x/4] = (src[1][y*width+x] + + src[1][y*width+x+1] + + src[1][y*width+x+2] + + src[1][y*width+x+3] + 2) / 4; + dest[2][y*(width/4)+x/4] = (src[2][y*width+x] + + src[2][y*width+x+1] + + src[2][y*width+x+2] + + src[2][y*width+x+3] + 2) / 4; + } + } + return 1; +} + +static int yuv444p_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ + int x, y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y++) { + for (x = 0; x < (width & ~1); x += 2) { + dest[1][y*(width/2)+x/2] = (src[1][y*width+x] + + src[1][y*width+x+1] + 1) / 2; + dest[2][y*(width/2)+x/2] = (src[2][y*width+x] + + src[2][y*width+x+1] + 1) / 2; + } + } + return 1; +} + +/*************************************************************************/ + +/* We treat Y8 as a planar format */ + +static int yuvp_y8(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + return 1; +} + +static int y8_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + memset(dest[1], 128, (width/2)*(height/2)); + memset(dest[2], 128, (width/2)*(height/2)); + return 1; +} + +static int y8_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + memset(dest[1], 128, (width/4)*height); + memset(dest[2], 128, (width/4)*height); + return 1; +} + +static int y8_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + memset(dest[1], 128, (width/2)*height); + memset(dest[2], 128, (width/2)*height); + return 1; +} + +static int y8_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + memset(dest[1], 128, width*height); + memset(dest[2], 128, width*height); + return 1; +} + +/*************************************************************************/ +/*************************************************************************/ + +#if defined(HAVE_ASM_SSE2) + +/* SSE2 routines. See comments in img_x86_common.h for why we don't bother + * unrolling the loops. */ + +/* Common macros/data for x86 code */ +#include "img_x86_common.h" + +/* Average 2 bytes horizontally (e.g. 422P->411P) (unit: 2 source bytes) */ +#define AVG_2H(src,dest,count) \ + asm("pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" /* XMM7: 0x00FF*8 */ \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movzbl -2("ESI","ECX",2), %%eax \n\ + movzbl -1("ESI","ECX",2), %%edx \n\ + addl %%edx, %%eax \n\ + shrl $1, %%eax \n\ + movb %%al, -1("EDI","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",2),%%xmm0 #XMM0:FEDCBA9876543210 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: FEDCBA9876543210 \n\ + pand %%xmm7, %%xmm0 # XMM0: E C A 8 6 4 2 0 \n\ + psrlw $8, %%xmm1 # XMM1: F D B 9 7 5 3 1 \n\ + pavgw %%xmm1, %%xmm0 # XMM0: w v u t s r q p (avgs) \n\ + packuswb %%xmm0, %%xmm0 # XMM0: wvutsrqpwvutsrqp \n\ + movq %%xmm0, -8("EDI","ECX")", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src), "D" (dest), "c" (count) \ + : "eax", "edx") + +/* Average 4 bytes horizontally (e.g. 444P->411P) (unit: 4 source bytes) */ +#define AVG_4H(src,dest,count) \ + asm("pcmpeqd %%xmm7, %%xmm7; psrld $24, %%xmm7;" /* XMM7: 0x000000FF*4 */ \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movzbl -4("ESI","ECX",4), %%eax \n\ + movzbl -3("ESI","ECX",4), %%edx \n\ + addl %%edx, %%eax \n\ + movzbl -2("ESI","ECX",4), %%edx \n\ + addl %%edx, %%eax \n\ + movzbl -1("ESI","ECX",4), %%edx \n\ + addl %%edx, %%eax \n\ + shrl $2, %%eax \n\ + movb %%al, -1("EDI","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",4),%%xmm0 #XMM0:FEDCBA9876543210 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: FEDCBA9876543210 \n\ + movdqa %%xmm0, %%xmm2 # XMM2: FEDCBA9876543210 \n\ + movdqa %%xmm0, %%xmm3 # XMM3: FEDCBA9876543210 \n\ + pand %%xmm7, %%xmm0 # XMM0: C 8 4 0 \n\ + psrld $8, %%xmm1 # XMM1: FED BA9 765 321 \n\ + pand %%xmm7, %%xmm1 # XMM1: D 9 5 1 \n\ + psrld $16, %%xmm2 # XMM2: FE BA 76 32 \n\ + pand %%xmm7, %%xmm2 # XMM2: E A 6 2 \n\ + psrld $24, %%xmm3 # XMM3: F B 7 3 \n\ + pavgw %%xmm1, %%xmm0 # XMM0: C+D 8+9 4+5 0+1 (avgs) \n\ + pavgw %%xmm3, %%xmm2 # XMM2: E+F A+B 6+7 2+3 (avgs) \n\ + pavgw %%xmm2, %%xmm0 # XMM0: s r q p (avgs) \n\ + packuswb %%xmm0, %%xmm0 # XMM0: s r q p s r q p \n\ + packuswb %%xmm0, %%xmm0 # XMM0: srqpsrqpsrqpsrqp \n\ + movd %%xmm0, -4("EDI","ECX")", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src), "D" (dest), "c" (count) \ + : "eax", "edx") + +/* Repeat 2 bytes horizontally (e.g. 422P->444P) (unit: 1 source byte) */ +#define REP_2H(src,dest,count) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movb -1("ESI","ECX"), %%al \n\ + movb %%al, %%ah \n\ + movw %%ax, -2("EDI","ECX",2)", \ + /* main_loop */ \ + "movq -8("ESI","ECX"), %%xmm0 # XMM0: 76543210 \n\ + punpcklbw %%xmm0, %%xmm0 # XMM0: 7766554433221100 \n\ + movdqu %%xmm0, -16("EDI","ECX",2)", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src), "D" (dest), "c" (count) \ + : "eax") + +/* Repeat 4 bytes horizontally (e.g. 411P->444P) (unit: 1 source byte) */ +#define REP_4H(src,dest,count) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ 4, \ + /* push_regs */ "", \ + /* pop_regs */ "", \ + /* small_loop */ \ + "movzbl -1("ESI","ECX"), %%eax \n\ + movb %%al, %%ah \n\ + movl %%eax, %%edx \n\ + shll $16, %%eax \n\ + orl %%edx, %%eax \n\ + movl %%eax, -4("EDI","ECX",4)", \ + /* main_loop */ \ + "movd -4("ESI","ECX"), %%xmm0 # XMM0: 3210 \n\ + punpcklbw %%xmm0, %%xmm0 # XMM0: 33221100 \n\ + punpcklwd %%xmm0, %%xmm0 # XMM0: 3333222211110000 \n\ + movdqu %%xmm0, -16("EDI","ECX",4)", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src), "D" (dest), "c" (count) \ + : "eax", "edx") + +/* Average 2 bytes vertically and double horizontally (411P->420P) + * (unit: 1 source byte) */ +#define AVG_411_420(src1,src2,dest,count) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "push "EBX, \ + /* pop_regs */ "pop "EBX, \ + /* small_loop */ \ + "movzbl -1("ESI","ECX"), %%eax \n\ + movzbl -1("EDX","ECX"), %%ebx \n\ + addl %%ebx, %%eax \n\ + shrl $1, %%eax \n\ + movb %%al, %%ah \n\ + movw %%ax, -2("EDI","ECX",2)", \ + /* main_loop */ \ + "movq -8("ESI","ECX"), %%xmm0 \n\ + movq -8("EDX","ECX"), %%xmm1 \n\ + pavgb %%xmm1, %%xmm0 \n\ + punpcklbw %%xmm0, %%xmm0 \n\ + movdqu %%xmm0, -16("EDI","ECX",2)", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src1), "d" (src2), "D" (dest), "c" (count) \ + : "eax") + +/* Average 2 bytes vertically (422P->420P) (unit: 1 source byte) */ +#define AVG_422_420(src1,src2,dest,count) \ + asm(SIMD_LOOP_WRAPPER( \ + /* blocksize */ 16, \ + /* push_regs */ "push "EBX, \ + /* pop_regs */ "pop "EBX, \ + /* small_loop */ \ + "movzbl -1("ESI","ECX"), %%eax \n\ + movzbl -1("EDX","ECX"), %%ebx \n\ + addl %%ebx, %%eax \n\ + shrl $1, %%eax \n\ + movb %%al, -1("EDI","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX"), %%xmm0 \n\ + movdqu -16("EDX","ECX"), %%xmm1 \n\ + pavgb %%xmm1, %%xmm0 \n\ + movdqu %%xmm0, -16("EDI","ECX")", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src1), "d" (src2), "D" (dest), "c" (count) \ + : "eax") + +/* Average 4 bytes, 2 horizontally and 2 vertically (444P->420P) + * (unit: 2 source bytes) */ +#define AVG_444_420(src1,src2,dest,count) \ + asm("pcmpeqd %%xmm7, %%xmm7; psrlw $8, %%xmm7;" /* XMM7: 0x00FF*8 */ \ + SIMD_LOOP_WRAPPER( \ + /* blocksize */ 8, \ + /* push_regs */ "push "EBX, \ + /* pop_regs */ "pop "EBX, \ + /* small_loop */ \ + "movzbl -2("ESI","ECX",2), %%eax \n\ + movzbl -1("ESI","ECX",2), %%ebx \n\ + addl %%ebx, %%eax \n\ + movzbl -2("EDX","ECX",2), %%ebx \n\ + addl %%ebx, %%eax \n\ + movzbl -1("EDX","ECX",2), %%ebx \n\ + addl %%ebx, %%eax \n\ + shrl $2, %%eax \n\ + movb %%al, -1("EDI","ECX")", \ + /* main_loop */ \ + "movdqu -16("ESI","ECX",2), %%xmm0 \n\ + movdqu -16("EDX","ECX",2), %%xmm2 \n\ + movdqa %%xmm0, %%xmm1 \n\ + pand %%xmm7, %%xmm0 \n\ + psrlw $8, %%xmm1 \n\ + pavgw %%xmm1, %%xmm0 \n\ + movdqa %%xmm2, %%xmm3 \n\ + pand %%xmm7, %%xmm2 \n\ + psrlw $8, %%xmm3 \n\ + pavgw %%xmm3, %%xmm2 \n\ + pavgw %%xmm2, %%xmm0 \n\ + packuswb %%xmm0, %%xmm0 \n\ + movq %%xmm0, -8("EDI","ECX")", \ + /* emms */ "emms") \ + : /* no outputs */ \ + : "S" (src1), "d" (src2), "D" (dest), "c" (count)) + +/*************************************************************************/ + +static int yuv420p_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + AVG_2H(src[1]+(y/2)*(width/2), dest[1]+y*(width/4), width/4); + ac_memcpy(dest[1]+(y+1)*(width/4), dest[1]+y*(width/4), width/4); + AVG_2H(src[2]+(y/2)*(width/2), dest[2]+y*(width/4), width/4); + ac_memcpy(dest[2]+(y+1)*(width/4), dest[2]+y*(width/4), width/4); + } + return 1; +} + +static int yuv420p_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < height; y += 2) { + REP_2H(src[1]+(y/2)*(width/2), dest[1]+y*width, width/2); + ac_memcpy(dest[1]+(y+1)*width, dest[1]+y*width, width); + REP_2H(src[2]+(y/2)*(width/2), dest[2]+y*width, width/2); + ac_memcpy(dest[2]+(y+1)*width, dest[2]+y*width, width); + } + return 1; +} + +/*************************************************************************/ + +static int yuv411p_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + AVG_411_420(src[1]+y*(width/4), src[1]+(y+1)*(width/4), + dest[1]+(y/2)*(width/2), width/4); + AVG_411_420(src[2]+y*(width/4), src[2]+(y+1)*(width/4), + dest[2]+(y/2)*(width/2), width/4); + } + return 1; +} + +static int yuv411p_yuv422p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + if (!(width & 3)) { + /* Fast version, no bytes at end of row to skip */ + REP_2H(src[1], dest[1], (width/4)*height); + REP_2H(src[2], dest[2], (width/4)*height); + } else { + /* Slow version, loop through each row */ + int y; + for (y = 0; y < height; y++) { + REP_2H(src[1]+y*(width/4), dest[1]+y*(width/2), width/4); + REP_2H(src[2]+y*(width/4), dest[2]+y*(width/2), width/4); + } + } + return 1; +} + +static int yuv411p_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + if (!(width & 3)) { + /* Fast version, no bytes at end of row to skip */ + REP_4H(src[1], dest[1], (width/4)*height); + REP_4H(src[2], dest[2], (width/4)*height); + } else { + /* Slow version, loop through each row */ + int y; + for (y = 0; y < height; y++) { + REP_4H(src[1]+y*(width/4), dest[1]+y*width, width/4); + REP_4H(src[2]+y*(width/4), dest[2]+y*width, width/4); + } + } + return 1; +} + +/*************************************************************************/ + +static int yuv422p_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + AVG_422_420(src[1]+y*(width/2), src[1]+(y+1)*(width/2), + dest[1]+(y/2)*(width/2), width/2); + AVG_422_420(src[2]+y*(width/2), src[2]+(y+1)*(width/2), + dest[2]+(y/2)*(width/2), width/2); + } + return 1; +} + +static int yuv422p_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + if (!(width & 3)) { + /* Fast version, no bytes at end of row to skip */ + AVG_2H(src[1], dest[1], (width/4)*height); + AVG_2H(src[2], dest[2], (width/4)*height); + } else { + /* Slow version, loop through each row */ + int y; + for (y = 0; y < height; y++) { + AVG_2H(src[1]+y*(width/2), dest[1]+y*(width/4), width/4); + AVG_2H(src[2]+y*(width/2), dest[2]+y*(width/4), width/4); + } + } + return 1; +} + +static int yuv422p_yuv444p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + if (!(width & 1)) { + /* Fast version, no bytes at end of row to skip */ + REP_2H(src[1], dest[1], (width/2)*height); + REP_2H(src[2], dest[2], (width/2)*height); + } else { + /* Slow version, loop through each row */ + int y; + for (y = 0; y < height; y++) { + REP_2H(src[1]+y*(width/2), dest[1]+y*width, width/2); + REP_2H(src[2]+y*(width/2), dest[2]+y*width, width/2); + } + } + return 1; +} + +/*************************************************************************/ + +static int yuv444p_yuv420p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int y; + ac_memcpy(dest[0], src[0], width*height); + for (y = 0; y < (height & ~1); y += 2) { + AVG_444_420(src[1]+y*width, src[1]+(y+1)*width, + dest[1]+(y/2)*(width/2), width/2); + AVG_444_420(src[2]+y*width, src[2]+(y+1)*width, + dest[2]+(y/2)*(width/2), width/2); + } + return 1; +} + +static int yuv444p_yuv411p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + if (!(width & 3)) { + /* Fast version, no bytes at end of row to skip */ + AVG_4H(src[1], dest[1], (width/4)*height); + AVG_4H(src[2], dest[2], (width/4)*height); + } else { + /* Slow version, loop through each row */ + int y; + for (y = 0; y < height; y++) { + AVG_4H(src[1]+y*width, dest[1]+y*(width/4), width/4); + AVG_4H(src[2]+y*width, dest[2]+y*(width/4), width/4); + } + } + return 1; +} + +static int yuv444p_yuv422p_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + ac_memcpy(dest[0], src[0], width*height); + if (!(width & 1)) { + /* Fast version, no bytes at end of row to skip */ + AVG_2H(src[1], dest[1], (width/2)*height); + AVG_2H(src[2], dest[2], (width/2)*height); + } else { + /* Slow version, loop through each row */ + int y; + for (y = 0; y < height; y++) { + AVG_2H(src[1]+y*width, dest[1]+y*(width/2), width/2); + AVG_2H(src[2]+y*width, dest[2]+y*(width/2), width/2); + } + } + return 1; +} + +/*************************************************************************/ + +#endif /* HAVE_ASM_SSE2 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Initialization */ + +int ac_imgconvert_init_yuv_planar(int accel) +{ + if (!register_conversion(IMG_YUV420P, IMG_YUV420P, yuv420p_copy) + || !register_conversion(IMG_YUV420P, IMG_YUV411P, yuv420p_yuv411p) + || !register_conversion(IMG_YUV420P, IMG_YUV422P, yuv420p_yuv422p) + || !register_conversion(IMG_YUV420P, IMG_YUV444P, yuv420p_yuv444p) + || !register_conversion(IMG_YUV420P, IMG_Y8, yuvp_y8) + + || !register_conversion(IMG_YUV411P, IMG_YUV420P, yuv411p_yuv420p) + || !register_conversion(IMG_YUV411P, IMG_YUV411P, yuv411p_copy) + || !register_conversion(IMG_YUV411P, IMG_YUV422P, yuv411p_yuv422p) + || !register_conversion(IMG_YUV411P, IMG_YUV444P, yuv411p_yuv444p) + || !register_conversion(IMG_YUV411P, IMG_Y8, yuvp_y8) + + || !register_conversion(IMG_YUV422P, IMG_YUV420P, yuv422p_yuv420p) + || !register_conversion(IMG_YUV422P, IMG_YUV411P, yuv422p_yuv411p) + || !register_conversion(IMG_YUV422P, IMG_YUV422P, yuv422p_copy) + || !register_conversion(IMG_YUV422P, IMG_YUV444P, yuv422p_yuv444p) + || !register_conversion(IMG_YUV422P, IMG_Y8, yuvp_y8) + + || !register_conversion(IMG_YUV444P, IMG_YUV420P, yuv444p_yuv420p) + || !register_conversion(IMG_YUV444P, IMG_YUV411P, yuv444p_yuv411p) + || !register_conversion(IMG_YUV444P, IMG_YUV422P, yuv444p_yuv422p) + || !register_conversion(IMG_YUV444P, IMG_YUV444P, yuv444p_copy) + || !register_conversion(IMG_YUV444P, IMG_Y8, yuvp_y8) + + || !register_conversion(IMG_Y8, IMG_YUV420P, y8_yuv420p) + || !register_conversion(IMG_Y8, IMG_YUV411P, y8_yuv411p) + || !register_conversion(IMG_Y8, IMG_YUV422P, y8_yuv422p) + || !register_conversion(IMG_Y8, IMG_YUV444P, y8_yuv444p) + || !register_conversion(IMG_Y8, IMG_Y8, y8_copy) + ) { + return 0; + } + +#if defined(HAVE_ASM_SSE2) + if (accel & AC_SSE2) { + if (!register_conversion(IMG_YUV420P, IMG_YUV411P, yuv420p_yuv411p_sse2) + || !register_conversion(IMG_YUV420P, IMG_YUV444P, yuv420p_yuv444p_sse2) + + || !register_conversion(IMG_YUV411P, IMG_YUV420P, yuv411p_yuv420p_sse2) + || !register_conversion(IMG_YUV411P, IMG_YUV422P, yuv411p_yuv422p_sse2) + || !register_conversion(IMG_YUV411P, IMG_YUV444P, yuv411p_yuv444p_sse2) + + || !register_conversion(IMG_YUV422P, IMG_YUV420P, yuv422p_yuv420p_sse2) + || !register_conversion(IMG_YUV422P, IMG_YUV411P, yuv422p_yuv411p_sse2) + || !register_conversion(IMG_YUV422P, IMG_YUV444P, yuv422p_yuv444p_sse2) + + || !register_conversion(IMG_YUV444P, IMG_YUV420P, yuv444p_yuv420p_sse2) + || !register_conversion(IMG_YUV444P, IMG_YUV411P, yuv444p_yuv411p_sse2) + || !register_conversion(IMG_YUV444P, IMG_YUV422P, yuv444p_yuv422p_sse2) + ) { + return 0; + } + } +#endif /* ARCH_X86 || ARCH_X86_64 */ + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/img_yuv_rgb.c b/branches/V-1.5.3/veejay-server/aclib/img_yuv_rgb.c new file mode 100644 index 00000000..95deb4fd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/img_yuv_rgb.c @@ -0,0 +1,2398 @@ +/* + * img_yuv_rgb.c - YUV<->RGB image format conversion routines + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "ac_internal.h" +#include "imgconvert.h" +#include "img_internal.h" + +#include + +#define USE_LOOKUP_TABLES /* for YUV420P->RGB24 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Standard C implementations */ + +const int cY = 76309; +const int crV = 104597; +const int cgU = -25675; +const int cgV = -53279; +const int cbU = 132201; + +/*************************************************************************/ + +#ifdef USE_LOOKUP_TABLES +# define TABLE_SCALE 16 /* scale factor for Y */ +static int Ylutbase[768*TABLE_SCALE]; +static int *Ylut = Ylutbase+256*TABLE_SCALE; +static int rVlut[256]; +static int gUlut[256]; +static int gVlut[256]; +static int bUlut[256]; +static void yuv_create_tables(void) { + static int yuv_tables_created = 0; + if (!yuv_tables_created) { + int i; + for (i = -256*TABLE_SCALE; i < 512*TABLE_SCALE; i++) { + int v = ((cY*(i-16*TABLE_SCALE)/TABLE_SCALE) + 32768) >> 16; + Ylut[i] = v<0 ? 0 : v>255 ? 255 : v; + } + for (i = 0; i < 256; i++) { + rVlut[i] = ((crV * (i-128)) * TABLE_SCALE + cY/2) / cY; + gUlut[i] = ((cgU * (i-128)) * TABLE_SCALE + cY/2) / cY; + gVlut[i] = ((cgV * (i-128)) * TABLE_SCALE + cY/2) / cY; + bUlut[i] = ((cbU * (i-128)) * TABLE_SCALE + cY/2) / cY; + } + yuv_tables_created = 1; + } +} +# define YUV2RGB(uvofs,rgbsz,rofs,gofs,bofs) do { \ + int Y = src[0][y*width+x] * TABLE_SCALE; \ + int U = src[1][(uvofs)]; \ + int V = src[2][(uvofs)]; \ + dest[0][(y*width+x)*rgbsz+rofs] = Ylut[Y+rVlut[V]]; \ + dest[0][(y*width+x)*rgbsz+gofs] = Ylut[Y+gUlut[U]+gVlut[V]];\ + dest[0][(y*width+x)*rgbsz+bofs] = Ylut[Y+bUlut[U]]; \ +} while (0) +# define YUV2RGB_PACKED(yofs,uofs,vofs,rgbsz,rofs,gofs,bofs) do { \ + int Y = src[0][(y*width+x)*2+yofs] * TABLE_SCALE; \ + int U = src[0][(y*width+(x&~1))*2+uofs]; \ + int V = src[0][(y*width+(x&~1))*2+vofs]; \ + dest[0][(y*width+x)*rgbsz+rofs] = Ylut[Y+rVlut[V]]; \ + dest[0][(y*width+x)*rgbsz+gofs] = Ylut[Y+gUlut[U]+gVlut[V]];\ + dest[0][(y*width+x)*rgbsz+bofs] = Ylut[Y+bUlut[U]]; \ +} while (0) +#else /* !USE_LOOKUP_TABLES */ +# define yuv_create_tables() /*nothing*/ +# define YUV2RGB(uvofs,rgbsz,rofs,gofs,bofs) do { \ + int Y = cY * (src[0][y*width+x] - 16); \ + int U = src[1][(uvofs)] - 128; \ + int V = src[2][(uvofs)] - 128; \ + int r = (Y + crV*V + 32768) >> 16; \ + int g = (Y + cgU*U + cgV*V + 32768) >> 16; \ + int b = (Y + cbU*U + 32768) >> 16; \ + dest[0][(y*width+x)*rgbsz+rofs] = r<0 ? 0 : r>255 ? 255 : r;\ + dest[0][(y*width+x)*rgbsz+gofs] = g<0 ? 0 : g>255 ? 255 : g;\ + dest[0][(y*width+x)*rgbsz+bofs] = b<0 ? 0 : b>255 ? 255 : b;\ +} while (0) +# define YUV2RGB_PACKED(yofs,uofs,vofs,rgbsz,rofs,gofs,bofs) do { \ + int Y = cY * (src[0][(y*width+x)*2+yofs] - 16); \ + int U = src[0][(y*width+(x&~1))*2+uofs] - 128; \ + int V = src[0][(y*width+(x&~1))*2+vofs] - 128; \ + int r = (Y + crV*V + 32768) >> 16; \ + int g = (Y + cgU*U + cgV*V + 32768) >> 16; \ + int b = (Y + cbU*U + 32768) >> 16; \ + dest[0][(y*width+x)*rgbsz+rofs] = r<0 ? 0 : r>255 ? 255 : r;\ + dest[0][(y*width+x)*rgbsz+gofs] = g<0 ? 0 : g>255 ? 255 : g;\ + dest[0][(y*width+x)*rgbsz+bofs] = b<0 ? 0 : b>255 ? 255 : b;\ +} while (0) +#endif + +#define YUV2RGB_420P(s,r,g,b) YUV2RGB((y/2)*(width/2)+(x/2),s,r,g,b) +#define YUV2RGB_411P(s,r,g,b) YUV2RGB((y )*(width/4)+(x/4),s,r,g,b) +#define YUV2RGB_422P(s,r,g,b) YUV2RGB((y )*(width/2)+(x/2),s,r,g,b) +#define YUV2RGB_444P(s,r,g,b) YUV2RGB((y )*(width )+(x ),s,r,g,b) +#define YUV2RGB_YUY2(s,r,g,b) YUV2RGB_PACKED(0,1,3, s,r,g,b) +#define YUV2RGB_UYVY(s,r,g,b) YUV2RGB_PACKED(1,0,2, s,r,g,b) +#define YUV2RGB_YVYU(s,r,g,b) YUV2RGB_PACKED(0,3,1, s,r,g,b) + +#define DEFINE_YUV2RGB(name,op) \ +static int name(uint8_t **src, uint8_t **dest, int width, int height) \ +{ \ + int x, y; \ + \ + yuv_create_tables(); \ + for (y = 0; y < height; y++) { \ + for (x = 0; x < width; x++) { \ + op; \ + } \ + } \ + return 1; \ +} + +#define DEFINE_YUV2RGB_SET(rgb,rgbsz,rofs,gofs,bofs) \ + DEFINE_YUV2RGB(yuv420p_##rgb, YUV2RGB_420P(rgbsz,rofs,gofs,bofs)) \ + DEFINE_YUV2RGB(yuv411p_##rgb, YUV2RGB_411P(rgbsz,rofs,gofs,bofs)) \ + DEFINE_YUV2RGB(yuv422p_##rgb, YUV2RGB_422P(rgbsz,rofs,gofs,bofs)) \ + DEFINE_YUV2RGB(yuv444p_##rgb, YUV2RGB_444P(rgbsz,rofs,gofs,bofs)) \ + DEFINE_YUV2RGB(yuy2_##rgb, YUV2RGB_YUY2(rgbsz,rofs,gofs,bofs)) \ + DEFINE_YUV2RGB(uyvy_##rgb, YUV2RGB_UYVY(rgbsz,rofs,gofs,bofs)) \ + DEFINE_YUV2RGB(yvyu_##rgb, YUV2RGB_YVYU(rgbsz,rofs,gofs,bofs)) + +DEFINE_YUV2RGB_SET(rgb24, 3,0,1,2) +DEFINE_YUV2RGB_SET(bgr24, 3,2,1,0) +DEFINE_YUV2RGB_SET(rgba32, 4,0,1,2) +DEFINE_YUV2RGB_SET(abgr32, 4,3,2,1) +DEFINE_YUV2RGB_SET(argb32, 4,1,2,3) +DEFINE_YUV2RGB_SET(bgra32, 4,2,1,0) + +/* Y8->RGB is defined as part of grayscale stuff below */ + +/*************************************************************************/ + +#define RGB2Y() \ + (dest[0][y*width+x] = ((16829*r + 33039*g + 6416*b + 32768) >> 16) + 16) +#define RGB2U(uvofs) \ + (dest[1][(uvofs)] = ((-9714*r - 19070*g + 28784*b + 32768) >> 16) + 128) +#define RGB2V(uvofs) \ + (dest[2][(uvofs)] = ((28784*r - 24103*g - 4681*b + 32768) >> 16) + 128) +#define RGB2Y_PACKED(ofs) \ + (dest[0][(y*width+x)*2+(ofs)] = ((16829*r + 33039*g + 6416*b + 32768) >> 16) + 16) +#define RGB2U_PACKED(ofs) \ + (dest[0][(y*width+x)*2+(ofs)] = ((-9714*r - 19070*g + 28784*b + 32768) >> 16) + 128) +#define RGB2V_PACKED(ofs) \ + (dest[0][(y*width+x)*2+(ofs)] = ((28784*r - 24103*g - 4681*b + 32768) >> 16) + 128) + +#define RGB2YUV(utest,vtest,uvofs) \ + RGB2Y(); if (utest) RGB2U(uvofs); if (vtest) RGB2V(uvofs) +#define RGB2YUV_PACKED(utest,vtest,yofs,uvofs) \ + RGB2Y_PACKED(yofs); \ + if (utest) RGB2U_PACKED(uvofs); \ + if (vtest) RGB2V_PACKED(uvofs) +/* YUV420P: take Cb/Cr from opposite corners */ +#define RGB2YUV_420P RGB2YUV(!((x|y) & 1), (x&y) & 1, (y/2)*(width/2)+(x/2)) +/* YUV411P: take Cb/Cr from points 2 pixels apart */ +#define RGB2YUV_411P RGB2YUV(!(x & 3), !((x^2) & 3), y*(width/4)+(x/4)) +/* YUV422P: take Cb/Cr from adjacent pixels */ +#define RGB2YUV_422P RGB2YUV(!(x & 1), x & 1, y*(width/2)+(x/2)) +/* YUV444P: every pixel is sampled */ +#define RGB2YUV_444P RGB2YUV(1, 1, y*width+x) +/* YUY2/UYVY/YVYU: take Cb/Cr from the corresponding pixel */ +#define RGB2YUV_YUY2 RGB2YUV_PACKED(!(x & 1), x & 1, 0,1) +#define RGB2YUV_UYVY RGB2YUV_PACKED(!(x & 1), x & 1, 1,0) +#define RGB2YUV_YVYU RGB2YUV_PACKED(x & 1, !(x & 1), 0,1) + +#define DEFINE_RGB2YUV(name,rgbsz,rofs,gofs,bofs,op) \ +static int name(uint8_t **src, uint8_t **dest, int width, int height) \ +{ \ + int x, y; \ + \ + for (y = 0; y < height; y++) { \ + for (x = 0; x < width; x++) { \ + int r = src[0][(y*width+x)*rgbsz+rofs]; \ + int g = src[0][(y*width+x)*rgbsz+gofs]; \ + int b = src[0][(y*width+x)*rgbsz+bofs]; \ + op; \ + } \ + } \ + return 1; \ +} + +#define DEFINE_RGB2Y8(name,rgbsz,rofs,gofs,bofs) \ +static int name(uint8_t **src, uint8_t **dest, int width, int height) \ +{ \ + int x, y; \ + \ + for (y = 0; y < height; y++) { \ + for (x = 0; x < width; x++) { \ + int r = src[0][(y*width+x)*rgbsz+rofs]; \ + int g = src[0][(y*width+x)*rgbsz+gofs]; \ + int b = src[0][(y*width+x)*rgbsz+bofs]; \ + RGB2Y(); \ + } \ + } \ + return 1; \ +} + +#define DEFINE_RGB2YUV_SET(rgb,rgbsz,rofs,gofs,bofs) \ + DEFINE_RGB2YUV(rgb##_yuv420p, rgbsz,rofs,gofs,bofs, RGB2YUV_420P) \ + DEFINE_RGB2YUV(rgb##_yuv411p, rgbsz,rofs,gofs,bofs, RGB2YUV_411P) \ + DEFINE_RGB2YUV(rgb##_yuv422p, rgbsz,rofs,gofs,bofs, RGB2YUV_422P) \ + DEFINE_RGB2YUV(rgb##_yuv444p, rgbsz,rofs,gofs,bofs, RGB2YUV_444P) \ + DEFINE_RGB2YUV(rgb##_yuy2, rgbsz,rofs,gofs,bofs, RGB2YUV_YUY2) \ + DEFINE_RGB2YUV(rgb##_uyvy, rgbsz,rofs,gofs,bofs, RGB2YUV_UYVY) \ + DEFINE_RGB2YUV(rgb##_yvyu, rgbsz,rofs,gofs,bofs, RGB2YUV_YVYU) \ + DEFINE_RGB2Y8 (rgb##_y8, rgbsz,rofs,gofs,bofs) + +DEFINE_RGB2YUV_SET(rgb24, 3,0,1,2) +DEFINE_RGB2YUV_SET(bgr24, 3,2,1,0) +DEFINE_RGB2YUV_SET(rgba32, 4,0,1,2) +DEFINE_RGB2YUV_SET(abgr32, 4,3,2,1) +DEFINE_RGB2YUV_SET(argb32, 4,1,2,3) +DEFINE_RGB2YUV_SET(bgra32, 4,2,1,0) + +/*************************************************************************/ + +/* All YUV planar formats convert to grayscale the same way */ + +#ifdef USE_LOOKUP_TABLES +static uint8_t graylut[2][256]; +static int graylut_created = 0; +static void gray8_create_tables(void) +{ + if (!graylut_created) { + int i; + for (i = 0; i < 256; i++) { + if (i <= 16) + graylut[0][i] = 0; + else if (i >= 235) + graylut[0][i] = 255; + else + graylut[0][i] = (i-16) * 255 / 219; + graylut[1][i] = 16 + i*219/255; + } + graylut_created = 1; + } +} +# define Y2GRAY(val) (graylut[0][(val)]) +# define GRAY2Y(val) (graylut[1][(val)]) +#else +# define gray8_create_tables() /*nothing*/ +# define Y2GRAY(val) ((val)<16 ? 0 : (val)>=235 ? 255 : ((val)-16)*256/219) +# define GRAY2Y(val) (16 + (val)*219/255) +#endif + +static int yuvp_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) + dest[0][i] = Y2GRAY(src[0][i]); + return 1; +} + +static int yuy2_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) + dest[0][i] = Y2GRAY(src[0][i*2]); + return 1; +} + +static int uyvy_gray8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) + dest[0][i] = Y2GRAY(src[0][i*2+1]); + return 1; +} + +/*************************************************************************/ + +static int gray8_y8(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) + dest[0][i] = GRAY2Y(src[0][i]); + return 1; +} + +static int gray8_yuv420p(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!ac_imgconvert(src, IMG_GRAY8, dest, IMG_Y8, width, height)) + return 0; + memset(dest[1], 128, (width/2)*(height/2)); + memset(dest[2], 128, (width/2)*(height/2)); + return 1; +} + +static int gray8_yuv411p(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!ac_imgconvert(src, IMG_GRAY8, dest, IMG_Y8, width, height)) + return 0; + memset(dest[1], 128, (width/4)*height); + memset(dest[2], 128, (width/4)*height); + return 1; +} + +static int gray8_yuv422p(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!ac_imgconvert(src, IMG_GRAY8, dest, IMG_Y8, width, height)) + return 0; + memset(dest[1], 128, (width/2)*height); + memset(dest[2], 128, (width/2)*height); + return 1; +} + +static int gray8_yuv444p(uint8_t **src, uint8_t **dest, int width, int height) +{ + if (!ac_imgconvert(src, IMG_GRAY8, dest, IMG_Y8, width, height)) + return 0; + memset(dest[1], 128, width*height); + memset(dest[2], 128, width*height); + return 1; +} + +static int gray8_yuy2(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) { + dest[0][i*2 ] = GRAY2Y(src[0][i]); + dest[0][i*2+1] = 128; + } + return 1; +} + +static int gray8_uyvy(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) { + dest[0][i*2 ] = 128; + dest[0][i*2+1] = GRAY2Y(src[0][i]); + } + return 1; +} + +/*************************************************************************/ + +/* We only need 3 functions for Y8->RGB (no difference between RGB and BGR) */ + +static int y8_rgb24(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) + dest[0][i*3] = dest[0][i*3+1] = dest[0][i*3+2] = Y2GRAY(src[0][i]); + return 1; +} + +static int y8_rgba32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) + dest[0][i*4] = dest[0][i*4+1] = dest[0][i*4+2] = Y2GRAY(src[0][i]); + return 1; +} + +static int y8_argb32(uint8_t **src, uint8_t **dest, int width, int height) +{ + int i; + gray8_create_tables(); + for (i = 0; i < width*height; i++) + dest[0][i*4+1] = dest[0][i*4+2] = dest[0][i*4+3] = Y2GRAY(src[0][i]); + return 1; +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Accelerated versions of colorspace routines. */ + +/* Common constant values used in routines: */ + +#if defined(HAVE_ASM_MMX) + +#include "img_x86_common.h" + +static const struct { uint16_t n[72]; } __attribute__((aligned(16))) yuv_data = {{ + 0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF, /* for odd/even */ + 0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010, /* for Y -16 */ + 0x0080,0x0080,0x0080,0x0080,0x0080,0x0080,0x0080,0x0080, /* for U/V -128 */ + 0x2543,0x2543,0x2543,0x2543,0x2543,0x2543,0x2543,0x2543, /* Y constant */ + 0x3313,0x3313,0x3313,0x3313,0x3313,0x3313,0x3313,0x3313, /* rV constant */ + 0xF377,0xF377,0xF377,0xF377,0xF377,0xF377,0xF377,0xF377, /* gU constant */ + 0xE5FC,0xE5FC,0xE5FC,0xE5FC,0xE5FC,0xE5FC,0xE5FC,0xE5FC, /* gV constant */ + 0x408D,0x408D,0x408D,0x408D,0x408D,0x408D,0x408D,0x408D, /* bU constant */ + 0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008, /* for rounding */ +}}; +/* Note that G->Y exceeds 0x7FFF, so be careful to treat it as unsigned + * (the rest of the values are signed) */ +static const struct { uint16_t n[96]; } __attribute__((aligned(16))) rgb_data = {{ + 0x41BD,0x41BD,0x41BD,0x41BD,0x41BD,0x41BD,0x41BD,0x41BD, /* R->Y */ + 0x810F,0x810F,0x810F,0x810F,0x810F,0x810F,0x810F,0x810F, /* G->Y */ + 0x1910,0x1910,0x1910,0x1910,0x1910,0x1910,0x1910,0x1910, /* B->Y */ + 0xDA0E,0xDA0E,0xDA0E,0xDA0E,0xDA0E,0xDA0E,0xDA0E,0xDA0E, /* R->U */ + 0xB582,0xB582,0xB582,0xB582,0xB582,0xB582,0xB582,0xB582, /* G->U */ + 0x7070,0x7070,0x7070,0x7070,0x7070,0x7070,0x7070,0x7070, /* B->U */ + 0x7070,0x7070,0x7070,0x7070,0x7070,0x7070,0x7070,0x7070, /* R->V */ + 0xA1D9,0xA1D9,0xA1D9,0xA1D9,0xA1D9,0xA1D9,0xA1D9,0xA1D9, /* G->V */ + 0xEDB7,0xEDB7,0xEDB7,0xEDB7,0xEDB7,0xEDB7,0xEDB7,0xEDB7, /* B->V */ + 0x0420,0x0420,0x0420,0x0420,0x0420,0x0420,0x0420,0x0420, /* Y +16.5 */ + 0x2020,0x2020,0x2020,0x2020,0x2020,0x2020,0x2020,0x2020, /* U/V +128.5 */ + 0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FF, /* for odd/even */ +}}; +#define Y_GRAY 0x4A85 +#define GRAY_Y 0x36F7 +static const struct { uint16_t n[32]; } __attribute__((aligned(16))) gray_data = {{ + Y_GRAY,Y_GRAY,Y_GRAY,Y_GRAY,Y_GRAY,Y_GRAY,Y_GRAY,Y_GRAY, /* 255/219 */ + GRAY_Y,GRAY_Y,GRAY_Y,GRAY_Y,GRAY_Y,GRAY_Y,GRAY_Y,GRAY_Y, /* 219/255 */ + 0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010,0x0010, /* Y +/-16 */ + 0x00FF,0xFF00,0x0000,0x00FF,0xFF00,0x0000,0x0000,0x0000, /* for Y->RGB */ +}}; + +/* Convert 4 RGB32 pixels in EAX/EBX/ECX/EDX to RGB24 in EAX/EBX/ECX */ +#define IA32_RGB32_TO_RGB24 \ + "movl %%ebx, %%esi # ESI: 00 B1 G1 R1 \n\ + shll $24, %%esi # ESI: R1 00 00 00 \n\ + shrl $8, %%ebx # EBX: 00 00 B1 G1 \n\ + orl %%esi, %%eax # EAX: R1 B0 G0 R0 \n\ + movl %%ecx, %%esi # ESI: 00 B2 G2 R2 \n\ + shll $16, %%esi # ESI: G2 R2 00 00 \n\ + shrl $16, %%ecx # ECX: 00 00 00 B2 \n\ + shll $8, %%edx # EDX: B3 G3 R3 00 \n\ + orl %%esi, %%ebx # EBX: G2 R2 B1 G1 \n\ + orl %%edx, %%ecx # ECX: B3 G3 R3 B2 \n" + +/* Convert 4 RGB24 pixels in EAX/EBX/ECX to RGB32 in EAX/EBX/ECX/EDX */ +#define IA32_RGB24_TO_RGB32 \ + "movl %%ecx, %%edx # EDX: B3 G3 R3 B2 \n\ + shrl $8, %%edx # EDX: 00 B3 G3 R3 \n\ + andl $0xFF, %%ecx # ECX: 00 00 00 B2 \n\ + movl %%ebx, %%edi # EDI: G2 R2 B1 G1 \n\ + andl $0xFFFF0000, %%edi # EDI: G2 R2 00 00 \n\ + orl %%edi, %%ecx # ECX: G2 R2 00 B2 \n\ + rorl $16, %%ecx # ECX: 00 B2 G2 R2 \n\ + movl %%eax, %%edi # EDI: R1 B0 G0 R0 \n\ + andl $0xFF000000, %%edi # EDI: R1 00 00 00 \n\ + andl $0x0000FFFF, %%ebx # EBX: 00 00 B1 G1 \n\ + orl %%edi, %%ebx # EBX: R1 00 B1 G1 \n\ + roll $8, %%ebx # EBX: 00 B1 G1 R1 \n\ + andl $0x00FFFFFF, %%eax # EAX: 00 B0 G0 R0 \n" + +#endif /* HAVE_ASM_MMX */ + +/*************************************************************************/ +/*************************************************************************/ + +/* MMX routines */ + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */ + +static inline void mmx_yuv42Xp_to_rgb(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV); +#define mmx_yuv420p_to_rgb mmx_yuv42Xp_to_rgb +#define mmx_yuv422p_to_rgb mmx_yuv42Xp_to_rgb +static inline void mmx_store_rgb24(uint8_t *dest); +static inline void mmx_store_bgr24(uint8_t *dest); +static inline void mmx_store_rgba32(uint8_t *dest); +static inline void mmx_store_abgr32(uint8_t *dest); +static inline void mmx_store_argb32(uint8_t *dest); +static inline void mmx_store_bgra32(uint8_t *dest); + +#define DEFINE_YUV2RGB_MMX(yuv,rgb,uvofs,rgbsz,rofs,gofs,bofs) \ +static int yuv##_##rgb##_mmx(uint8_t **src, uint8_t **dest, \ + int width, int height) \ +{ \ + int x, y; \ + \ + yuv_create_tables(); \ + for (y = 0; y < height; y++) { \ + for (x = 0; x < (width & ~7); x += 8) { \ + mmx_##yuv##_to_rgb(src[0]+y*width+x, \ + src[1]+(uvofs), src[2]+(uvofs)); \ + mmx_store_##rgb(dest[0]+(y*width+x)*rgbsz); \ + } \ + while (x < width) { \ + YUV2RGB(uvofs,rgbsz,rofs,gofs,bofs); \ + x++; \ + } \ + } \ + asm("emms"); \ + return 1; \ +} + +#define DEFINE_YUV2RGB_MMX_SET(rgb,rgbsz,rofs,gofs,bofs) \ + DEFINE_YUV2RGB_MMX(yuv420p,rgb,(y/2)*(width/2)+(x/2),rgbsz,rofs,gofs,bofs)\ + DEFINE_YUV2RGB_MMX(yuv422p,rgb,(y )*(width/2)+(x/2),rgbsz,rofs,gofs,bofs) + +DEFINE_YUV2RGB_MMX_SET(rgb24, 3,0,1,2) +DEFINE_YUV2RGB_MMX_SET(bgr24, 3,2,1,0) +DEFINE_YUV2RGB_MMX_SET(rgba32, 4,0,1,2) +DEFINE_YUV2RGB_MMX_SET(abgr32, 4,3,2,1) +DEFINE_YUV2RGB_MMX_SET(argb32, 4,1,2,3) +DEFINE_YUV2RGB_MMX_SET(bgra32, 4,2,1,0) + +/************************************/ + +static inline void mmx_yuv42Xp_to_rgb(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV) +{ + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%mm4, %%mm4 # MM4: 00 00 00 00 00 00 00 00 \n\ + movq ("EAX"), %%mm6 # MM6: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + movd ("ECX"), %%mm2 # MM2: U3 U2 U1 U0 \n\ + movd ("EDX"), %%mm3 # MM3: V3 V2 V1 V0 \n\ + movq %%mm6, %%mm7 # MM7: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + pand ("ESI"), %%mm6 # MM6: -Y6- -Y4- -Y2- -Y0- \n\ + psrlw $8, %%mm7 # MM7: -Y7- -Y5- -Y3- -Y1- \n\ + punpcklbw %%mm4, %%mm2 # MM2: -U3- -U2- -U1- -U0- \n\ + punpcklbw %%mm4, %%mm3 # MM3: -V3- -V2- -V1- -V0- \n\ + psubw 16("ESI"), %%mm6 # MM6: subtract 16 \n\ + psubw 16("ESI"), %%mm7 # MM7: subtract 16 \n\ + psubw 32("ESI"), %%mm2 # MM2: subtract 128 \n\ + psubw 32("ESI"), %%mm3 # MM3: subtract 128 \n\ + psllw $7, %%mm6 # MM6: convert to fixed point 8.7 \n\ + psllw $7, %%mm7 # MM7: convert to fixed point 8.7 \n\ + psllw $7, %%mm2 # MM2: convert to fixed point 8.7 \n\ + psllw $7, %%mm3 # MM3: convert to fixed point 8.7 \n\ + # Multiply by constants \n\ + pmulhw 48("ESI"), %%mm6 # MM6: -cY6- -cY4- -cY2- -cY0- \n\ + pmulhw 48("ESI"), %%mm7 # MM6: -cY7- -cY5- -cY3- -cY1- \n\ + movq 80("ESI"), %%mm4 # MM4: gU constant \n\ + movq 96("ESI"), %%mm5 # MM5: gV constant \n\ + pmulhw %%mm2, %%mm4 # MM4: -gU3- -gU2- -gU1- -gU0- \n\ + pmulhw %%mm3, %%mm5 # MM5: -gV3- -gV2- -gV1- -gV0- \n\ + paddw %%mm5, %%mm4 # MM4: -g3- -g2- -g1- -g0- \n\ + pmulhw 64("ESI"), %%mm3 # MM3: -r3- -r2- -r1- -r0- \n\ + pmulhw 112("ESI"),%%mm2 # MM2: -b3- -b2- -b1- -b0- \n\ + movq %%mm3, %%mm0 # MM0: -r3- -r2- -r1- -r0- \n\ + movq %%mm4, %%mm1 # MM1: -g3- -g2- -g1- -g0- \n\ + movq %%mm2, %%mm5 # MM5: -b3- -b2- -b1- -b0- \n\ + # Add intermediate results and round/shift to get R/G/B values \n\ + paddw 128("ESI"), %%mm6 # Add rounding value (0.5 @ 8.4 fixed) \n\ + paddw 128("ESI"), %%mm7 \n\ + paddw %%mm6, %%mm0 # MM0: -R6- -R4- -R2- -R0- \n\ + psraw $4, %%mm0 # Shift back to 8.0 fixed \n\ + paddw %%mm6, %%mm1 # MM1: -G6- -G4- -G2- -G0- \n\ + psraw $4, %%mm1 \n\ + paddw %%mm6, %%mm2 # MM2: -B6- -B4- -B2- -B0- \n\ + psraw $4, %%mm2 \n\ + paddw %%mm7, %%mm3 # MM3: -R7- -R5- -R3- -R1- \n\ + psraw $4, %%mm3 \n\ + paddw %%mm7, %%mm4 # MM4: -G7- -G5- -G3- -G1- \n\ + psraw $4, %%mm4 \n\ + paddw %%mm7, %%mm5 # MM5: -B7- -B5- -B3- -B1- \n\ + psraw $4, %%mm5 \n\ + # Saturate to 0-255 and pack into bytes \n\ + packuswb %%mm0, %%mm0 # MM0: R6 R4 R2 R0 R6 R4 R2 R0 \n\ + packuswb %%mm1, %%mm1 # MM1: G6 G4 G2 G0 G6 G4 G2 G0 \n\ + packuswb %%mm2, %%mm2 # MM2: B6 B4 B2 B0 B6 B4 B2 B0 \n\ + packuswb %%mm3, %%mm3 # MM3: R7 R5 R3 R1 R7 R5 R3 R1 \n\ + packuswb %%mm4, %%mm4 # MM4: G7 G5 G3 G1 G7 G5 G3 G1 \n\ + packuswb %%mm5, %%mm5 # MM5: B7 B5 B3 B1 B7 B5 B3 B1 \n\ + punpcklbw %%mm3, %%mm0 # MM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + punpcklbw %%mm4, %%mm1 # MM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + punpcklbw %%mm5, %%mm2 # MM2: B7 B6 B5 B4 B3 B2 B1 B0 \n" + : /* no outputs */ + : "a" (srcY), "c" (srcU), "d" (srcV), "S" (&yuv_data), "m" (yuv_data) + ); +} + +/************************************/ + +/* Convert YUV->RGB output to RGBA pixels in MM0..MM3 */ +#define MMX_RGB_TO_RGBA "\ + pxor %%mm7, %%mm7 # MM7: 00 00 00 00 00 00 00 00 \n\ + movq %%mm0, %%mm3 # MM3: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + movq %%mm1, %%mm4 # MM4: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + movq %%mm2, %%mm5 # MM5: B7 B6 B5 B4 B3 B2 B1 B0 \n\ + punpcklbw %%mm1, %%mm0 # MM0: G3 R3 G2 R2 G1 R1 G0 R0 \n\ + punpcklbw %%mm7, %%mm2 # MM2: 00 B3 00 B2 00 B1 00 B0 \n\ + movq %%mm0, %%mm1 # MM1: G3 R3 G2 R2 G1 R1 G0 R0 \n\ + punpcklwd %%mm2, %%mm0 # MM0: 00 B1 G1 R1 00 B0 G0 R0 \n\ + punpckhwd %%mm2, %%mm1 # MM1: 00 B3 G3 R3 00 B2 G2 R2 \n\ + punpckhbw %%mm4, %%mm3 # MM3: G7 R7 G6 R6 G5 R5 G4 R4 \n\ + punpckhbw %%mm7, %%mm5 # MM5: 00 B7 00 B6 00 B5 00 B4 \n\ + movq %%mm3, %%mm2 # MM2: G7 R7 G6 R6 G5 R5 G4 R4 \n\ + punpckhwd %%mm5, %%mm3 # MM3: 00 B7 G7 R7 00 B6 G6 R6 \n\ + punpcklwd %%mm5, %%mm2 # MM2: 00 B5 G5 R5 00 B4 G4 R4 \n" + +/* Convert YUV->RGB output to BGRA pixels in MM0..MM3 */ +#define MMX_RGB_TO_BGRA "\ + pxor %%mm7, %%mm7 # MM7: 00 00 00 00 00 00 00 00 \n\ + movq %%mm0, %%mm5 # MM5: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + movq %%mm1, %%mm4 # MM4: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + movq %%mm2, %%mm3 # MM3: B7 B6 B5 B4 B3 B2 B1 B0 \n\ + punpcklbw %%mm1, %%mm2 # MM2: G3 B3 G2 B2 G1 B1 G0 B0 \n\ + punpcklbw %%mm7, %%mm0 # MM0: 00 R3 00 R2 00 R1 00 R0 \n\ + movq %%mm2, %%mm1 # MM1: G3 B3 G2 B2 G1 B1 G0 B0 \n\ + punpcklwd %%mm0, %%mm2 # MM2: 00 R1 G1 B1 00 R0 G0 B0 \n\ + punpckhwd %%mm0, %%mm1 # MM1: 00 R3 G3 B3 00 R2 G2 B2 \n\ + movq %%mm2, %%mm0 # MM0: 00 R1 G1 B1 00 R0 G0 B0 \n\ + punpckhbw %%mm4, %%mm3 # MM3: G7 B7 G6 B6 G5 B5 G4 B4 \n\ + punpckhbw %%mm7, %%mm5 # MM5: 00 R7 00 R6 00 R5 00 R4 \n\ + movq %%mm3, %%mm2 # MM2: G7 B7 G6 B6 G5 B5 G4 B4 \n\ + punpckhwd %%mm5, %%mm3 # MM3: 00 R7 G7 B7 00 R6 G6 B6 \n\ + punpcklwd %%mm5, %%mm2 # MM2: 00 R5 G5 B5 00 R4 G4 B4 \n" + + +static inline void mmx_store_rgb24(uint8_t *dest) +{ + /* It looks like it's fastest to go to RGB32 first, then shift the + * result to merge the 24-bit pixels together. */ + asm(MMX_RGB_TO_RGBA "\ + movq %%mm0, %%mm4 # MM4: 00 B1 G1 R1 00 B0 G0 R0 \n\ + movq %%mm1, %%mm5 # MM5: 00 B3 G3 R3 00 B2 G2 R2 \n\ + movq %%mm2, %%mm6 # MM6: 00 B5 G5 R5 00 B4 G4 R4 \n\ + movq %%mm3, %%mm7 # MM7: 00 B7 G7 R7 00 B6 G6 R6 \n\ + psrlq $32, %%mm4 # MM4: 00 00 00 00 00 B1 G1 R1 \n\ + psrlq $32, %%mm5 # MM5: 00 00 00 00 00 B3 G3 R3 \n\ + psrlq $32, %%mm6 # MM6: 00 00 00 00 00 B5 G5 R5 \n\ + psrlq $32, %%mm7 # MM7: 00 00 00 00 00 B7 G7 R7 \n\ + push "EBX" \n\ + movd %%mm0, %%eax # EAX: 00 B0 G0 R0 \n\ + movd %%mm4, %%ebx # EBX: 00 B1 G1 R1 \n\ + movd %%mm1, %%ecx # ECX: 00 B2 G2 R2 \n\ + movd %%mm5, %%edx # EDX: 00 B3 G3 R3 \n\ + "IA32_RGB32_TO_RGB24" \n\ + movl %%eax, ("EDI") \n\ + movl %%ebx, 4("EDI") \n\ + movl %%ecx, 8("EDI") \n\ + movd %%mm2, %%eax # EAX: 00 B4 G4 R4 \n\ + movd %%mm6, %%ebx # EBX: 00 B5 G5 R5 \n\ + movd %%mm3, %%ecx # ECX: 00 B6 G6 R6 \n\ + movd %%mm7, %%edx # EDX: 00 B7 G7 R7 \n\ + "IA32_RGB32_TO_RGB24" \n\ + movl %%eax, 12("EDI") \n\ + movl %%ebx, 16("EDI") \n\ + movl %%ecx, 20("EDI") \n\ + pop "EBX" \n" + : /* no outputs */ + : "D" (dest) + : "eax", "ecx", "edx", "esi" + ); +} + +static inline void mmx_store_bgr24(uint8_t *dest) +{ + asm(MMX_RGB_TO_BGRA "\ + movq %%mm0, %%mm4 # MM4: 00 B1 G1 R1 00 B0 G0 R0 \n\ + movq %%mm1, %%mm5 # MM5: 00 B3 G3 R3 00 B2 G2 R2 \n\ + movq %%mm2, %%mm6 # MM6: 00 B5 G5 R5 00 B4 G4 R4 \n\ + movq %%mm3, %%mm7 # MM7: 00 B7 G7 R7 00 B6 G6 R6 \n\ + psrlq $32, %%mm4 # MM4: 00 00 00 00 00 B1 G1 R1 \n\ + psrlq $32, %%mm5 # MM5: 00 00 00 00 00 B3 G3 R3 \n\ + psrlq $32, %%mm6 # MM6: 00 00 00 00 00 B5 G5 R5 \n\ + psrlq $32, %%mm7 # MM7: 00 00 00 00 00 B7 G7 R7 \n\ + push "EBX" \n\ + movd %%mm0, %%eax # EAX: 00 B0 G0 R0 \n\ + movd %%mm4, %%ebx # EBX: 00 B1 G1 R1 \n\ + movd %%mm1, %%ecx # ECX: 00 B2 G2 R2 \n\ + movd %%mm5, %%edx # EDX: 00 B3 G3 R3 \n\ + "IA32_RGB32_TO_RGB24" \n\ + movl %%eax, ("EDI") \n\ + movl %%ebx, 4("EDI") \n\ + movl %%ecx, 8("EDI") \n\ + movd %%mm2, %%eax # EAX: 00 B4 G4 R4 \n\ + movd %%mm6, %%ebx # EBX: 00 B5 G5 R5 \n\ + movd %%mm3, %%ecx # ECX: 00 B6 G6 R6 \n\ + movd %%mm7, %%edx # EDX: 00 B7 G7 R7 \n\ + "IA32_RGB32_TO_RGB24" \n\ + movl %%eax, 12("EDI") \n\ + movl %%ebx, 16("EDI") \n\ + movl %%ecx, 20("EDI") \n\ + pop "EBX" \n" + : /* no outputs */ + : "D" (dest) + : "eax", "ecx", "edx", "esi" + ); +} + +static inline void mmx_store_rgba32(uint8_t *dest) +{ + asm(MMX_RGB_TO_RGBA "\ + movq %%mm0, ("EDI") \n\ + movq %%mm1, 8("EDI") \n\ + movq %%mm2, 16("EDI") \n\ + movq %%mm3, 24("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +static inline void mmx_store_abgr32(uint8_t *dest) +{ + asm(MMX_RGB_TO_BGRA "\ + psllq $8, %%mm0 \n\ + psllq $8, %%mm1 \n\ + psllq $8, %%mm2 \n\ + psllq $8, %%mm3 \n\ + movq %%mm0, ("EDI") \n\ + movq %%mm1, 8("EDI") \n\ + movq %%mm2, 16("EDI") \n\ + movq %%mm3, 24("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +static inline void mmx_store_argb32(uint8_t *dest) +{ + asm(MMX_RGB_TO_RGBA "\ + psllq $8, %%mm0 \n\ + psllq $8, %%mm1 \n\ + psllq $8, %%mm2 \n\ + psllq $8, %%mm3 \n\ + movq %%mm0, ("EDI") \n\ + movq %%mm1, 8("EDI") \n\ + movq %%mm2, 16("EDI") \n\ + movq %%mm3, 24("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +static inline void mmx_store_bgra32(uint8_t *dest) +{ + asm(MMX_RGB_TO_BGRA "\ + movq %%mm0, ("EDI") \n\ + movq %%mm1, 8("EDI") \n\ + movq %%mm2, 16("EDI") \n\ + movq %%mm3, 24("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +#endif /* HAVE_ASM_MMX && ARCH_X86 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* SSE2 routines */ + +#if defined(HAVE_ASM_SSE2) + +/*************************************************************************/ + +static inline void sse2_load_yuv420p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width); +static inline void sse2_load_yuv411p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width); +static inline void sse2_load_yuv422p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width); +static inline void sse2_load_yuv444p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width); +static inline void sse2_load_yuy2(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width); +static inline void sse2_load_uyvy(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width); +static inline void sse2_load_yvyu(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width); +static inline void sse2_yuv_to_rgb(void); +static inline void sse2_yuv444_to_rgb(void); +static inline void sse2_store_rgb24(uint8_t *dest); +static inline void sse2_store_bgr24(uint8_t *dest); +static inline void sse2_store_rgba32(uint8_t *dest); +static inline void sse2_store_abgr32(uint8_t *dest); +static inline void sse2_store_argb32(uint8_t *dest); +static inline void sse2_store_bgra32(uint8_t *dest); + +#define DEFINE_YUV2RGB_SSE2(yuv,y2r,rgb,rgbsz,slowop) \ +static int yuv##_##rgb##_sse2(uint8_t **src, uint8_t **dest, \ + int width, int height) \ +{ \ + int x, y; \ + \ + yuv_create_tables(); \ + for (y = 0; y < height; y++) { \ + for (x = 0; x < (width & ~15); x += 16) { \ + sse2_load_##yuv(src[0], src[1], src[2], x, y, width); \ + sse2_##y2r(); \ + sse2_store_##rgb(dest[0] + (y*width+x)*rgbsz); \ + } \ + while (x < width) { \ + slowop; \ + x++; \ + } \ + } \ + asm("emms"); \ + return 1; \ +} + +#define DEFINE_YUV2RGB_SSE2_SET(rgb,sz,r,g,b) \ + DEFINE_YUV2RGB_SSE2(yuv420p, yuv_to_rgb, rgb,sz, YUV2RGB_420P(sz,r,g,b))\ + DEFINE_YUV2RGB_SSE2(yuv411p, yuv_to_rgb, rgb,sz, YUV2RGB_411P(sz,r,g,b))\ + DEFINE_YUV2RGB_SSE2(yuv422p, yuv_to_rgb, rgb,sz, YUV2RGB_422P(sz,r,g,b))\ + DEFINE_YUV2RGB_SSE2(yuv444p, yuv444_to_rgb,rgb,sz, YUV2RGB_444P(sz,r,g,b))\ + DEFINE_YUV2RGB_SSE2(yuy2, yuv_to_rgb, rgb,sz, YUV2RGB_YUY2(sz,r,g,b))\ + DEFINE_YUV2RGB_SSE2(uyvy, yuv_to_rgb, rgb,sz, YUV2RGB_UYVY(sz,r,g,b))\ + DEFINE_YUV2RGB_SSE2(yvyu, yuv_to_rgb, rgb,sz, YUV2RGB_YVYU(sz,r,g,b)) + +DEFINE_YUV2RGB_SSE2_SET(rgb24, 3,0,1,2) +DEFINE_YUV2RGB_SSE2_SET(bgr24, 3,2,1,0) +DEFINE_YUV2RGB_SSE2_SET(rgba32, 4,0,1,2) +DEFINE_YUV2RGB_SSE2_SET(abgr32, 4,3,2,1) +DEFINE_YUV2RGB_SSE2_SET(argb32, 4,1,2,3) +DEFINE_YUV2RGB_SSE2_SET(bgra32, 4,2,1,0) + +/************************************/ + +static inline void sse2_load_yuv420p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width) +{ + srcY += y*width+x; + srcU += (y/2)*(width/2)+(x/2); + srcV += (y/2)*(width/2)+(x/2); + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%xmm4, %%xmm4 # XMM4: 00 00 00 00 00 00 00 00 \n\ + movdqu ("EAX"), %%xmm6 # XMM6: YF...................Y0 \n\ + movq ("ECX"), %%xmm2 # XMM2: U7.......U0 \n\ + movq ("EDX"), %%xmm3 # XMM3: V7.......V0 \n\ + movdqa %%xmm6, %%xmm7 # XMM7: YF...................Y0 \n\ + pand ("ESI"), %%xmm6 # XMM6: YE YC YA Y8 Y6 Y4 Y2 Y0 \n\ + psrlw $8, %%xmm7 # XMM7: YF YD YB Y9 Y7 Y5 Y3 Y1 \n\ + punpcklbw %%xmm4,%%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\ + punpcklbw %%xmm4,%%xmm3 # XMM3: V7 V6 V5 V4 V3 V2 V1 V0 \n" + : /* no outputs */ + : "a" (srcY), "c" (srcU), "d" (srcV), "S" (&yuv_data), "m" (yuv_data) + ); +} + +static inline void sse2_load_yuv411p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width) +{ + srcY += y*width+x; + srcU += y*(width/4)+(x/4); + srcV += y*(width/4)+(x/4); + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%xmm4, %%xmm4 # XMM4: 00 00 00 00 00 00 00 00 \n\ + movdqu ("EAX"), %%xmm6 # XMM6: YF...................Y0 \n\ + movd ("ECX"), %%xmm2 # XMM2: U3.U0 \n\ + punpcklbw %%xmm2,%%xmm2 # XMM2: U3 U3.U0 U0 \n\ + movd ("EDX"), %%xmm3 # XMM3: V3.V0 \n\ + punpcklbw %%xmm3,%%xmm3 # XMM2: V3 V3.V0 V0 \n\ + movdqa %%xmm6, %%xmm7 # XMM7: YF...................Y0 \n\ + pand ("ESI"), %%xmm6 # XMM6: YE YC YA Y8 Y6 Y4 Y2 Y0 \n\ + psrlw $8, %%xmm7 # XMM7: YF YD YB Y9 Y7 Y5 Y3 Y1 \n\ + punpcklbw %%xmm4,%%xmm2 # XMM2: U3 U3 U2 U2 U1 U1 U0 U0 \n\ + punpcklbw %%xmm4,%%xmm3 # XMM3: V3 V3 V2 V2 V1 V1 V0 V0 \n" + : /* no outputs */ + : "a" (srcY), "c" (srcU), "d" (srcV), "S" (&yuv_data), "m" (yuv_data) + ); +} + +static inline void sse2_load_yuv422p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width) +{ + srcY += y*width+x; + srcU += y*(width/2)+(x/2); + srcV += y*(width/2)+(x/2); + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%xmm4, %%xmm4 # XMM4: 00 00 00 00 00 00 00 00 \n\ + movdqu ("EAX"), %%xmm6 # XMM6: YF...................Y0 \n\ + movq ("ECX"), %%xmm2 # XMM2: U7.......U0 \n\ + movq ("EDX"), %%xmm3 # XMM3: V7.......V0 \n\ + movdqa %%xmm6, %%xmm7 # XMM7: YF...................Y0 \n\ + pand ("ESI"), %%xmm6 # XMM6: YE YC YA Y8 Y6 Y4 Y2 Y0 \n\ + psrlw $8, %%xmm7 # XMM7: YF YD YB Y9 Y7 Y5 Y3 Y1 \n\ + punpcklbw %%xmm4,%%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\ + punpcklbw %%xmm4,%%xmm3 # XMM3: V7 V6 V5 V4 V3 V2 V1 V0 \n" + : /* no outputs */ + : "a" (srcY), "c" (srcU), "d" (srcV), "S" (&yuv_data), "m" (yuv_data) + ); +} + +static inline void sse2_load_yuv444p(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width) +{ + srcY += y*width+x; + srcU += y*width+x; + srcV += y*width+x; + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%xmm4, %%xmm4 # XMM4: 00 00 00 00 00 00 00 00 \n\ + movdqu ("EAX"), %%xmm6 # XMM6: YF...................Y0 \n\ + movdqu ("ECX"), %%xmm2 # XMM2: UF...................U0 \n\ + movdqu ("EDX"), %%xmm0 # XMM0: VF...................V0 \n\ + movdqa %%xmm6, %%xmm7 # XMM7: YF...................Y0 \n\ + punpcklbw %%xmm4,%%xmm6 # XMM6: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + punpckhbw %%xmm4,%%xmm7 # XMM7: YF YE YD YC YB YA Y9 Y8 \n\ + movdqa %%xmm2, %%xmm5 # XMM5: UF...................U0 \n\ + punpcklbw %%xmm4,%%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\ + punpckhbw %%xmm4,%%xmm5 # XMM5: UF UE UD UC UB UA U9 U8 \n\ + movdqa %%xmm0, %%xmm3 # XMM3: VF...................V0 \n\ + punpcklbw %%xmm4,%%xmm0 # XMM0: V7 V6 V5 V4 V3 V2 V1 V0 \n\ + punpckhbw %%xmm4,%%xmm3 # XMM3: VF VE VD VC VB VA V9 V8 \n" + : /* no outputs */ + : "a" (srcY), "c" (srcU), "d" (srcV), "S" (&yuv_data), "m" (yuv_data) + ); +} + +static inline void sse2_load_yuy2(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width) +{ + srcY += (y*width+x)*2; + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%xmm4, %%xmm4 # XMM4: 00 00 00 00 00 00 00 00 \n\ + movdqu ("EAX"), %%xmm6 # XMM6: V3 Y7.............U0 Y0 \n\ + movdqu 16("EAX"),%%xmm7 # XMM7: V7 YF.............U4 Y8 \n\ + movdqa %%xmm6, %%xmm2 # XMM2: V3 Y7.............U0 Y0 \n\ + psrlw $8, %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + pand ("ESI"), %%xmm6 # XMM6: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + movdqa %%xmm7, %%xmm3 # XMM3: V7 YF.............U4 Y8 \n\ + psrlw $8, %%xmm3 # XMM3: V7 U7 V6 U6 V5 U5 V4 U4 \n\ + pand ("ESI"), %%xmm7 # XMM6: YF YE YD YC YB YA Y9 Y8 \n\ + packuswb %%xmm3, %%xmm2 # XMM2: V7 U7.............V0 U0 \n\ + movdqa %%xmm2, %%xmm3 # XMM3: V7 U7.............V0 U0 \n\ + pand ("ESI"), %%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\ + psrlw $8, %%xmm3 # XMM3: V7 V6 V5 V4 V3 V2 V1 V0 \n\ + packuswb %%xmm7, %%xmm6 # XMM6: YF...................Y0 \n\ + movdqa %%xmm6, %%xmm7 # XMM7: YF...................Y0 \n\ + pand ("ESI"), %%xmm6 # XMM6: YE YC YA Y8 Y6 Y4 Y2 Y0 \n\ + psrlw $8, %%xmm7 # XMM7: YF YD YB Y9 Y7 Y5 Y3 Y1 \n" + : /* no outputs */ + : "a" (srcY), "S" (&yuv_data), "m" (yuv_data) + ); +} + +static inline void sse2_load_uyvy(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width) +{ + srcY += (y*width+x)*2; + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%xmm4, %%xmm4 # XMM4: 00 00 00 00 00 00 00 00 \n\ + movdqu ("EAX"), %%xmm6 # XMM6: Y7 V3.............Y0 00 \n\ + movdqu 16("EAX"),%%xmm7 # XMM7: YF V7.............Y8 U4 \n\ + movdqa %%xmm6, %%xmm2 # XMM2: Y7 V3.............Y0 U0 \n\ + pand ("ESI"), %%xmm2 # XMM2: V3 U3 V2 U2 V1 U1 V0 U0 \n\ + psrlw $8, %%xmm6 # XMM6: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + movdqa %%xmm7, %%xmm3 # XMM3: YF V7.............Y8 U4 \n\ + pand ("ESI"), %%xmm3 # XMM3: V7 U7 V6 U6 V5 U5 V4 U4 \n\ + psrlw $8, %%xmm7 # XMM6: YF YE YD YC YB YA Y9 Y8 \n\ + packuswb %%xmm3, %%xmm2 # XMM2: V7 U7.............V0 U0 \n\ + movdqa %%xmm2, %%xmm3 # XMM3: V7 U7.............V0 U0 \n\ + pand ("ESI"), %%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\ + psrlw $8, %%xmm3 # XMM3: V7 V6 V5 V4 V3 V2 V1 V0 \n\ + packuswb %%xmm7, %%xmm6 # XMM6: YF...................Y0 \n\ + movdqa %%xmm6, %%xmm7 # XMM7: YF...................Y0 \n\ + pand ("ESI"), %%xmm6 # XMM6: YE YC YA Y8 Y6 Y4 Y2 Y0 \n\ + psrlw $8, %%xmm7 # XMM7: YF YD YB Y9 Y7 Y5 Y3 Y1 \n" + : /* no outputs */ + : "a" (srcY), "S" (&yuv_data), "m" (yuv_data) + ); +} + +static inline void sse2_load_yvyu(uint8_t *srcY, uint8_t *srcU, + uint8_t *srcV, int x, int y, int width) +{ + srcY += (y*width+x)*2; + asm("\ + # Load data, bias and expand to 16 bits \n\ + pxor %%xmm4, %%xmm4 # XMM4: 00 00 00 00 00 00 00 00 \n\ + movdqu ("EAX"), %%xmm6 # XMM6: U3 Y7.............V0 Y0 \n\ + movdqu 16("EAX"),%%xmm7 # XMM7: U7 YF.............V4 Y8 \n\ + movdqa %%xmm6, %%xmm2 # XMM2: U3 Y7.............V0 Y0 \n\ + psrlw $8, %%xmm2 # XMM2: U3 V3 U2 V2 U1 V1 U0 V0 \n\ + pand ("ESI"), %%xmm6 # XMM6: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\ + movdqa %%xmm7, %%xmm3 # XMM3: U7 YF.............V4 Y8 \n\ + psrlw $8, %%xmm3 # XMM3: U7 V7 U6 V6 U5 V5 U4 V4 \n\ + pand ("ESI"), %%xmm7 # XMM6: YF YE YD YC YB YA Y9 Y8 \n\ + packuswb %%xmm3, %%xmm2 # XMM2: U7 V7.............U0 V0 \n\ + movdqa %%xmm2, %%xmm3 # XMM3: U7 V7.............U0 V0 \n\ + psrlw $8, %%xmm2 # XMM2: U7 U6 U5 U4 U3 U2 U1 U0 \n\ + pand ("ESI"), %%xmm3 # XMM3: V7 V6 V5 V4 V3 V2 V1 V0 \n\ + packuswb %%xmm7, %%xmm6 # XMM6: YF...................Y0 \n\ + movdqa %%xmm6, %%xmm7 # XMM7: YF...................Y0 \n\ + pand ("ESI"), %%xmm6 # XMM6: YE YC YA Y8 Y6 Y4 Y2 Y0 \n\ + psrlw $8, %%xmm7 # XMM7: YF YD YB Y9 Y7 Y5 Y3 Y1 \n" + : /* no outputs */ + : "a" (srcY), "S" (&yuv_data), "m" (yuv_data) + ); +} + +/************************************/ + +/* Standard YUV->RGB (Yodd=XMM7 Yeven=XMM6 U=XMM2 V=XMM3) */ +static inline void sse2_yuv_to_rgb(void) +{ + asm("\ + psubw 16("ESI"), %%xmm6 # XMM6: subtract 16 \n\ + psllw $7, %%xmm6 # XMM6: convert to fixed point 8.7 \n\ + psubw 16("ESI"), %%xmm7 # XMM7: subtract 16 \n\ + psllw $7, %%xmm7 # XMM7: convert to fixed point 8.7 \n\ + psubw 32("ESI"), %%xmm2 # XMM2: subtract 128 \n\ + psllw $7, %%xmm2 # XMM2: convert to fixed point 8.7 \n\ + psubw 32("ESI"), %%xmm3 # XMM3: subtract 128 \n\ + psllw $7, %%xmm3 # XMM3: convert to fixed point 8.7 \n\ + # Multiply by constants \n\ + pmulhw 48("ESI"),%%xmm6 # XMM6: cYE.................cY0 \n\ + pmulhw 48("ESI"),%%xmm7 # XMM7: cYF.................cY1 \n\ + movdqa 80("ESI"),%%xmm4 # XMM4: gU constant \n\ + pmulhw %%xmm2, %%xmm4 # XMM4: gU7.................gU0 \n\ + movdqa 96("ESI"),%%xmm5 # XMM5: gV constant \n\ + pmulhw %%xmm3, %%xmm5 # XMM5: gV7.................gV0 \n\ + paddw %%xmm5, %%xmm4 # XMM4: g7 g6 g5 g4 g3 g2 g1 g0 \n\ + pmulhw 64("ESI"),%%xmm3 # XMM3: r7 r6 r5 r4 r3 r2 r1 r0 \n\ + pmulhw 112("ESI"),%%xmm2 #XMM2: b7 b6 b5 b4 b3 b2 b1 b0 \n\ + movdqa %%xmm3, %%xmm0 # XMM0: r7 r6 r5 r4 r3 r2 r1 r0 \n\ + movdqa %%xmm4, %%xmm1 # XMM1: g7 g6 g5 g4 g3 g2 g1 g0 \n\ + movdqa %%xmm2, %%xmm5 # XMM5: b7 b6 b5 b4 b3 b2 b1 b0 \n\ + # Add intermediate results and round/shift to get R/G/B values \n\ + paddw 128("ESI"),%%xmm6 # Add rounding value (0.5 @ 8.4 fixed) \n\ + paddw 128("ESI"),%%xmm7 \n\ + paddw %%xmm6, %%xmm0 # XMM0: RE RC RA R8 R6 R4 R2 R0 \n\ + psraw $4, %%xmm0 # Shift back to 8.0 fixed \n\ + paddw %%xmm6, %%xmm1 # XMM1: GE GC GA G8 G6 G4 G2 G0 \n\ + psraw $4, %%xmm1 \n\ + paddw %%xmm6, %%xmm2 # XMM2: BE BC BA B8 B6 B4 B2 B0 \n\ + psraw $4, %%xmm2 \n\ + paddw %%xmm7, %%xmm3 # XMM3: RF RD RB R9 R7 R5 R3 R1 \n\ + psraw $4, %%xmm3 \n\ + paddw %%xmm7, %%xmm4 # XMM4: GF GD GB G9 G7 G5 G3 G1 \n\ + psraw $4, %%xmm4 \n\ + paddw %%xmm7, %%xmm5 # XMM5: BF BD BB B9 B7 B5 B3 B1 \n\ + psraw $4, %%xmm5 \n\ + # Saturate to 0-255 and pack into bytes \n\ + packuswb %%xmm0, %%xmm0 # XMM0: RE.......R0 RE.......R0 \n\ + packuswb %%xmm1, %%xmm1 # XMM1: GE.......G0 GE.......G0 \n\ + packuswb %%xmm2, %%xmm2 # XMM2: BE.......B0 BE.......B0 \n\ + packuswb %%xmm3, %%xmm3 # XMM3: RF.......R1 RF.......R1 \n\ + packuswb %%xmm4, %%xmm4 # XMM4: GF.......G1 GF.......G1 \n\ + packuswb %%xmm5, %%xmm5 # XMM5: BF.......B1 BF.......B1 \n\ + punpcklbw %%xmm3,%%xmm0 # XMM0: RF...................R0 \n\ + punpcklbw %%xmm4,%%xmm1 # XMM1: GF...................G0 \n\ + punpcklbw %%xmm5,%%xmm2 # XMM2: BF...................B0 \n" + : /* no outputs */ + : "S" (&yuv_data), "m" (yuv_data) + ); +} + +/* YUV444 YUV->RGB (Y=XMM7:XMM6 U=XMM5:XMM2 V=XMM3:XMM0) */ +static inline void sse2_yuv444_to_rgb(void) +{ + asm("\ + psubw 16("ESI"), %%xmm6 # XMM6: subtract 16 \n\ + psllw $7, %%xmm6 # XMM6: convert to fixed point 8.7 \n\ + psubw 16("ESI"), %%xmm7 # XMM7: subtract 16 \n\ + psllw $7, %%xmm7 # XMM7: convert to fixed point 8.7 \n\ + psubw 32("ESI"), %%xmm2 # XMM2: subtract 128 \n\ + psllw $7, %%xmm2 # XMM2: convert to fixed point 8.7 \n\ + psubw 32("ESI"), %%xmm5 # XMM5: subtract 128 \n\ + psllw $7, %%xmm5 # XMM5: convert to fixed point 8.7 \n\ + psubw 32("ESI"), %%xmm0 # XMM0: subtract 128 \n\ + psllw $7, %%xmm0 # XMM0: convert to fixed point 8.7 \n\ + psubw 32("ESI"), %%xmm3 # XMM3: subtract 128 \n\ + psllw $7, %%xmm3 # XMM3: convert to fixed point 8.7 \n\ + # Multiply by constants \n\ + pmulhw 48("ESI"),%%xmm6 # XMM6: cY7.................cY0 \n\ + movdqa 80("ESI"),%%xmm1 # XMM1: gU constant \n\ + pmulhw %%xmm2, %%xmm1 # XMM1: gU7.................gU0 \n\ + movdqa 96("ESI"),%%xmm4 # XMM4: gV constant \n\ + pmulhw %%xmm0, %%xmm4 # XMM4: gV7.................gV0 \n\ + paddw %%xmm4, %%xmm1 # XMM1: g7 g6 g5 g4 g3 g2 g1 g0 \n\ + pmulhw 64("ESI"),%%xmm0 # XMM0: r7 r6 r5 r4 r3 r2 r1 r0 \n\ + pmulhw 112("ESI"),%%xmm2 #XMM2: b7 b6 b5 b4 b3 b2 b1 b0 \n\ + # Add intermediate results and round/shift to get R/G/B values \n\ + paddw 128("ESI"),%%xmm6 # Add rounding value (0.5 @ 8.4 fixed) \n\ + paddw %%xmm6, %%xmm0 # XMM0: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + psraw $4, %%xmm0 # Shift back to 8.0 fixed \n\ + paddw %%xmm6, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n\ + psraw $4, %%xmm1 \n\ + paddw %%xmm6, %%xmm2 # XMM2: B7 B6 B5 B4 B3 B2 B1 B0 \n\ + psraw $4, %%xmm2 \n\ + # Do it all over again for pixels 8-15 \n\ + pmulhw 48("ESI"),%%xmm7 # XMM7: cYF.................cY8 \n\ + movdqa 80("ESI"),%%xmm6 # XMM6: gU constant \n\ + pmulhw %%xmm5, %%xmm6 # XMM6: gUF.................gU8 \n\ + movdqa 96("ESI"),%%xmm4 # XMM4: gV constant \n\ + pmulhw %%xmm3, %%xmm4 # XMM4: gVF.................gV8 \n\ + paddw %%xmm6, %%xmm4 # XMM4: gF gE gD gC gB gA g9 g8 \n\ + pmulhw 64("ESI"),%%xmm3 # XMM3: rF rE rD rC rB rA r9 r8 \n\ + pmulhw 112("ESI"),%%xmm5 #XMM5: bF bE bD bC bB bA b9 b8 \n\ + paddw 128("ESI"),%%xmm7 # Add rounding value (0.5 @ 8.4 fixed) \n\ + paddw %%xmm7, %%xmm3 # XMM3: RF RE RD RC RB RA R9 R8 \n\ + psraw $4, %%xmm3 \n\ + paddw %%xmm7, %%xmm4 # XMM4: GF GE GD GC GB GA G9 G8 \n\ + psraw $4, %%xmm4 \n\ + paddw %%xmm7, %%xmm5 # XMM5: BF BE BD BC BB BA B9 B8 \n\ + psraw $4, %%xmm5 \n\ + # Saturate to 0-255 and pack into bytes \n\ + packuswb %%xmm3, %%xmm0 # XMM0: RF...................R0 \n\ + packuswb %%xmm4, %%xmm1 # XMM1: GF...................G0 \n\ + packuswb %%xmm5, %%xmm2 # XMM2: BF...................B0 \n" + : /* no outputs */ + : "S" (&yuv_data), "m" (yuv_data) + ); +} + +/************************************/ + +/* Convert YUV->RGB output to RGBA pixels in XMM0..XMM3 */ +#define SSE2_RGB_TO_RGBA "\ + pxor %%xmm7, %%xmm7 # XMM7: 00 00 00 00 00 00 00 00 \n\ + movdqa %%xmm0, %%xmm3 # XMM3: RF...................R0 \n\ + movdqa %%xmm1, %%xmm4 # XMM4: GF...................G0 \n\ + movdqa %%xmm2, %%xmm5 # XMM5: BF...................B0 \n\ + punpcklbw %%xmm1,%%xmm0 # XMM0: G7 R7.............G0 R0 \n\ + punpcklbw %%xmm7,%%xmm2 # XMM2: 00 B7.............00 B0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: G7 R7.............G0 R0 \n\ + punpcklwd %%xmm2,%%xmm0 # XMM0: 0BGR3 0BGR2 0BGR1 0BGR0 \n\ + punpckhwd %%xmm2,%%xmm1 # XMM1: 0BGR7 0BGR6 0BGR5 0BGR4 \n\ + punpckhbw %%xmm4,%%xmm3 # XMM3: GF RF.............G8 R8 \n\ + punpckhbw %%xmm7,%%xmm5 # XMM5: 00 BF.............00 B8 \n\ + movdqa %%xmm3, %%xmm2 # XMM2: GF RF.............G8 R8 \n\ + punpckhwd %%xmm5,%%xmm3 # XMM3: 0BGRF 0BGRE 0BGRD 0BGRC \n\ + punpcklwd %%xmm5,%%xmm2 # XMM2: 0BGRB 0BGRA 0BGR9 0BGR8 \n" + +/* Convert YUV->RGB output to BGRA pixels in XMM0..XMM3 */ +#define SSE2_RGB_TO_BGRA "\ + pxor %%xmm7, %%xmm7 # XMM7: 00 00 00 00 00 00 00 00 \n\ + movdqa %%xmm0, %%xmm5 # XMM5: RF...................R0 \n\ + movdqa %%xmm1, %%xmm4 # XMM4: GF...................G0 \n\ + movdqa %%xmm2, %%xmm3 # XMM3: BF...................B0 \n\ + punpcklbw %%xmm1,%%xmm2 # XMM0: G7 B7.............G0 B0 \n\ + punpcklbw %%xmm7,%%xmm0 # XMM2: 00 R7.............00 R0 \n\ + movdqa %%xmm2, %%xmm1 # XMM1: G7 B7.............G0 B0 \n\ + punpcklwd %%xmm0,%%xmm2 # XMM2: 0RGB3 0RGB2 0RGB1 0RGB0 \n\ + punpckhwd %%xmm0,%%xmm1 # XMM1: 0RGB7 0RGB6 0RGB5 0RGB4 \n\ + movdqa %%xmm2, %%xmm0 # XMM0: 0RGB3 0RGB2 0RGB1 0RGB0 \n\ + punpckhbw %%xmm4,%%xmm3 # XMM3: GF BF.............G8 B8 \n\ + punpckhbw %%xmm7,%%xmm5 # XMM5: 00 RF.............00 R8 \n\ + movdqa %%xmm3, %%xmm2 # XMM2: GF BF.............G8 B8 \n\ + punpckhwd %%xmm5,%%xmm3 # XMM3: 0RGBF 0RGBE 0RGBD 0RGBC \n\ + punpcklwd %%xmm5,%%xmm2 # XMM2: 0RGBB 0RGBA 0RGB9 0RGB8 \n" + +/* Convert and 4 RGBA32 (BGRA32) pixels in XMMn to RGB24 (BGR24) and store + * at EDI+(12*n) */ +#define SSE2_RGB32_TO_RGB24(n) "\ + movd %%xmm"#n", %%eax # EAX: 00 B0 G0 R0 \n\ + psrldq $4, %%xmm"#n" # XMMn: 00000 0BGR3 0BGR2 0BGR1 \n\ + movd %%xmm"#n", %%ebx # EBX: 00 B1 G1 R1 \n\ + psrldq $4, %%xmm"#n" # XMMn: 00000 00000 0BGR3 0BGR2 \n\ + movd %%xmm"#n", %%ecx # ECX: 00 B2 G2 R2 \n\ + psrldq $4, %%xmm"#n" # XMMn: 00000 00000 00000 0BGR3 \n\ + movd %%xmm"#n", %%edx # EDX: 00 B3 G3 R3 \n\ + "IA32_RGB32_TO_RGB24" \n\ + movl %%eax, 12*"#n"+0("EDI") \n\ + movl %%ebx, 12*"#n"+4("EDI") \n\ + movl %%ecx, 12*"#n"+8("EDI") \n" + + +static inline void sse2_store_rgb24(uint8_t *dest) +{ + /* It looks like it's fastest to go to RGB32 first, then shift the + * result to merge the 24-bit pixels together. */ + asm(SSE2_RGB_TO_RGBA "\ + push "EBX" \n\ + "SSE2_RGB32_TO_RGB24(0)" \n\ + "SSE2_RGB32_TO_RGB24(1)" \n\ + "SSE2_RGB32_TO_RGB24(2)" \n\ + "SSE2_RGB32_TO_RGB24(3)" \n\ + pop "EBX" \n" + : /* no outputs */ + : "D" (dest) + : "eax", "ecx", "edx", "esi" + ); +} + +static inline void sse2_store_bgr24(uint8_t *dest) +{ + asm(SSE2_RGB_TO_BGRA "\ + push "EBX" \n\ + "SSE2_RGB32_TO_RGB24(0)" \n\ + "SSE2_RGB32_TO_RGB24(1)" \n\ + "SSE2_RGB32_TO_RGB24(2)" \n\ + "SSE2_RGB32_TO_RGB24(3)" \n\ + pop "EBX" \n" + : /* no outputs */ + : "D" (dest) + : "eax", "ecx", "edx", "esi" + ); +} + +/* It would be nice to be able to use movntdq here for a 50% speedup, + * but we're not guaranteed alignment... (think 766x512 for example) */ +static inline void sse2_store_rgba32(uint8_t *dest) +{ + asm(SSE2_RGB_TO_RGBA "\ + movdqu %%xmm0, ("EDI") \n\ + movdqu %%xmm1, 16("EDI") \n\ + movdqu %%xmm2, 32("EDI") \n\ + movdqu %%xmm3, 48("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +static inline void sse2_store_abgr32(uint8_t *dest) +{ + asm(SSE2_RGB_TO_BGRA "\ + pslldq $1, %%xmm0 \n\ + pslldq $1, %%xmm1 \n\ + pslldq $1, %%xmm2 \n\ + pslldq $1, %%xmm3 \n\ + movdqu %%xmm0, ("EDI") \n\ + movdqu %%xmm1, 16("EDI") \n\ + movdqu %%xmm2, 32("EDI") \n\ + movdqu %%xmm3, 48("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +static inline void sse2_store_argb32(uint8_t *dest) +{ + asm(SSE2_RGB_TO_RGBA "\ + pslldq $1, %%xmm0 \n\ + pslldq $1, %%xmm1 \n\ + pslldq $1, %%xmm2 \n\ + pslldq $1, %%xmm3 \n\ + movdqu %%xmm0, ("EDI") \n\ + movdqu %%xmm1, 16("EDI") \n\ + movdqu %%xmm2, 32("EDI") \n\ + movdqu %%xmm3, 48("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +static inline void sse2_store_bgra32(uint8_t *dest) +{ + asm(SSE2_RGB_TO_BGRA "\ + movdqu %%xmm0, ("EDI") \n\ + movdqu %%xmm1, 16("EDI") \n\ + movdqu %%xmm2, 32("EDI") \n\ + movdqu %%xmm3, 48("EDI") \n" + : /* no outputs */ + : "D" (dest) + ); +} + +/*************************************************************************/ + +static inline void sse2_load_rgb24(uint8_t *src); +static inline void sse2_load_bgr24(uint8_t *src); +static inline void sse2_load_rgba32(uint8_t *src); +static inline void sse2_load_abgr32(uint8_t *src); +static inline void sse2_load_argb32(uint8_t *src); +static inline void sse2_load_bgra32(uint8_t *src); +static inline void sse2_rgb_to_yuv420p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); +static inline void sse2_rgb_to_yuv411p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); +static inline void sse2_rgb_to_yuv422p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); +static inline void sse2_rgb_to_yuv444p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); +static inline void sse2_rgb_to_yuy2( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); +static inline void sse2_rgb_to_uyvy( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); +static inline void sse2_rgb_to_yvyu( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); +static inline void sse2_rgb_to_y8( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width); + +#define DEFINE_RGB2YUV_SSE2(rgb,yuv,rgbsz,rofs,gofs,bofs,slowop) \ +static int rgb##_##yuv##_sse2(uint8_t **src, uint8_t **dest, \ + int width, int height) \ +{ \ + int x, y; \ + \ + for (y = 0; y < height; y++) { \ + for (x = 0; x < (width & ~7); x += 8) { \ + sse2_load_##rgb(src[0]+(y*width+x)*rgbsz); \ + sse2_rgb_to_##yuv(dest[0], dest[1], dest[2], x, y, width); \ + } \ + while (x < width) { \ + int r = src[0][(y*width+x)*rgbsz+rofs]; \ + int g = src[0][(y*width+x)*rgbsz+gofs]; \ + int b = src[0][(y*width+x)*rgbsz+bofs]; \ + slowop; \ + x++; \ + } \ + } \ + asm("emms"); \ + return 1; \ +} + +#define DEFINE_RGB2YUV_SSE2_SET(rgb,sz,r,g,b) \ + DEFINE_RGB2YUV_SSE2(rgb,yuv420p, sz,r,g,b, RGB2YUV_420P) \ + DEFINE_RGB2YUV_SSE2(rgb,yuv411p, sz,r,g,b, RGB2YUV_411P) \ + DEFINE_RGB2YUV_SSE2(rgb,yuv422p, sz,r,g,b, RGB2YUV_422P) \ + DEFINE_RGB2YUV_SSE2(rgb,yuv444p, sz,r,g,b, RGB2YUV_444P) \ + DEFINE_RGB2YUV_SSE2(rgb,yuy2, sz,r,g,b, RGB2YUV_YUY2) \ + DEFINE_RGB2YUV_SSE2(rgb,uyvy, sz,r,g,b, RGB2YUV_UYVY) \ + DEFINE_RGB2YUV_SSE2(rgb,yvyu, sz,r,g,b, RGB2YUV_YVYU) \ + DEFINE_RGB2YUV_SSE2(rgb,y8, sz,r,g,b, RGB2Y()) + +DEFINE_RGB2YUV_SSE2_SET(rgb24, 3,0,1,2) +DEFINE_RGB2YUV_SSE2_SET(bgr24, 3,2,1,0) +DEFINE_RGB2YUV_SSE2_SET(rgba32, 4,0,1,2) +DEFINE_RGB2YUV_SSE2_SET(abgr32, 4,3,2,1) +DEFINE_RGB2YUV_SSE2_SET(argb32, 4,1,2,3) +DEFINE_RGB2YUV_SSE2_SET(bgra32, 4,2,1,0) + +/************************************/ + +/* Split 8 RGBA pixels in XMMr/XMMb into R/G/B in XMM0/XMM1/XMM2. + * r and b are 0 and 2 for RGB, 2 and 0 for BGR */ +#define SSE2_SPLIT_RGB32(r,b) "\ + movdqa 176(%%edi), %%xmm7 # XMM7: 00FF*8 \n\ + movdqa %%xmm"#r", %%xmm1 # XMM1: XBGR3 XBGR2 XBGR1 XBGR0 \n\ + movdqa %%xmm"#b", %%xmm3 # XMM3: XBGR7 XBGR6 XBGR5 XBGR4 \n\ + pand %%xmm7, %%xmm"#r" # XMMr: B3 R3 B2 R2 B1 R1 B0 R0 \n\ + psrld $8, %%xmm1 # XMM1: -XBG3 -XBG2 -XBG1 -XBG0 \n\ + pand %%xmm7, %%xmm"#b" # XMMb: B7 R7 B6 R6 B5 R5 B4 R4 \n\ + psrld $8, %%xmm3 # XMM3: -XBG7 -XBG6 -XBG5 -XBG4 \n\ + pand %%xmm7, %%xmm1 # XMM1: XX G3 XX G2 XX G1 XX G0 \n\ + packuswb %%xmm"#b", %%xmm"#r" # XMMr: B7 R7 ........... B0 R0 \n\ + pand %%xmm7, %%xmm3 # XMM3: XX G7 XX G6 XX G5 XX G4 \n\ + movdqa %%xmm"#r", %%xmm"#b" # XMMb: B7 R7 ........... B0 R0 \n\ + packuswb %%xmm3, %%xmm1 # XMM1: XX G7 ........... XX G0 \n\ + pand %%xmm7, %%xmm"#r" # XMMr: R7 R6 R5 R4 R3 R2 R1 R0 \n\ + psrlw $8, %%xmm"#b" # XMMb: B7 B6 B5 B4 B3 B2 B1 B0 \n\ + pand %%xmm7, %%xmm1 # XMM1: G7 G6 G5 G4 G3 G2 G1 G0 \n" + +static inline void sse2_load_rgb24(uint8_t *src) +{ + asm("\ + push "EBX" \n\ + # Make stack space for loading XMM registers \n\ + sub $24, "ESP" \n\ + # Copy source pixels to appropriate positions in stack (this \n\ + # seems to be the fastest way to get them where we want them) \n\ + movl $8, %%ebx \n\ + movl $24, %%edx \n\ + 0: \n\ + movb -3("ESI","EDX"), %%al \n\ + movb %%al, 0-1("ESP","EBX") \n\ + movb -2("ESI","EDX"), %%al \n\ + movb %%al, 8-1("ESP","EBX") \n\ + movb -1("ESI","EDX"), %%al \n\ + movb %%al, 16-1("ESP","EBX") \n\ + subl $3, %%edx \n\ + subl $1, %%ebx \n\ + jnz 0b \n\ + # Load XMM0-XMM2 with R/G/B values and expand to 16-bit \n\ + pxor %%xmm7, %%xmm7 \n\ + movq ("ESP"), %%xmm0 \n\ + punpcklbw %%xmm7, %%xmm0 \n\ + movq 8("ESP"), %%xmm1 \n\ + punpcklbw %%xmm7, %%xmm1 \n\ + movq 16("ESP"), %%xmm2 \n\ + punpcklbw %%xmm7, %%xmm2 \n\ + add $24, "ESP" \n\ + pop "EBX" \n" + : /* no outputs */ + : "S" (src) + : "eax", "ecx", "edx", "edi" + ); +} + +static inline void sse2_load_bgr24(uint8_t *src) +{ + /* Load as RGB and swap registers */ + sse2_load_rgb24(src); + asm("\ + movdqa %%xmm0, %%xmm3 \n\ + movdqa %%xmm2, %%xmm0 \n\ + movdqa %%xmm3, %%xmm2 \n" + : /* no outputs */ + : /* no inputs */ + ); +} + +static inline void sse2_load_rgba32(uint8_t *src) +{ + asm("\ + movdqu (%%esi), %%xmm0 # XMM0: XBGR3 XBGR2 XBGR1 XBGR0 \n\ + movdqu 16(%%esi), %%xmm2 # XMM2: XBGR7 XBGR6 XBGR5 XBGR4 \n\ + "SSE2_SPLIT_RGB32(0,2)" \n" + : /* no outputs */ + : "S" (src), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_load_abgr32(uint8_t *src) +{ + asm("\ + movdqu (%%esi), %%xmm2 # XMM2: RGBX3 RGBX2 RGBX1 RGBX0 \n\ + movdqu 16(%%esi), %%xmm0 # XMM0: RGBX7 RGBX6 RGBX5 RGBX4 \n\ + psrld $8, %%xmm2 # XMM2: -RGB3 -RGB2 -RGB1 -RGB0 \n\ + psrld $8, %%xmm0 # XMM0: -RGB7 -RGB6 -RGB5 -RGB4 \n\ + "SSE2_SPLIT_RGB32(2,0)" \n" + : /* no outputs */ + : "S" (src), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_load_argb32(uint8_t *src) +{ + asm("\ + movdqu (%%esi), %%xmm0 # XMM0: BGRX3 BGRX2 BGRX1 BGRX0 \n\ + movdqu 16(%%esi), %%xmm2 # XMM2: BGRX7 BGRX6 BGRX5 BGRX4 \n\ + psrld $8, %%xmm0 # XMM0: -BGR3 -BGR2 -BGR1 -BGR0 \n\ + psrld $8, %%xmm2 # XMM2: -BGR7 -BGR6 -BGR5 -BGR4 \n\ + "SSE2_SPLIT_RGB32(0,2)" \n" + : /* no outputs */ + : "S" (src), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_load_bgra32(uint8_t *src) +{ + asm("\ + movdqu (%%esi), %%xmm2 # XMM2: XRGB3 XRGB2 XRGB1 XRGB0 \n\ + movdqu 16(%%esi), %%xmm0 # XMM0: XRGB7 XRGB6 XRGB5 XRGB4 \n\ + "SSE2_SPLIT_RGB32(2,0)" \n" + : /* no outputs */ + : "S" (src), "D" (&rgb_data), "m" (rgb_data) + ); +} + +/************************************/ + +#define SSE2_RGB2Y "\ + # Make RGB data into 8.6 fixed-point, then create 8.6 \n\ + # fixed-point Y data in XMM3 \n\ + psllw $6, %%xmm0 \n\ + movdqa %%xmm0, %%xmm3 \n\ + pmulhuw ("EDI"), %%xmm3 \n\ + psllw $6, %%xmm1 \n\ + movdqa %%xmm1, %%xmm6 \n\ + pmulhuw 16("EDI"), %%xmm6 \n\ + psllw $6, %%xmm2 \n\ + movdqa %%xmm2, %%xmm7 \n\ + pmulhuw 32("EDI"), %%xmm7 \n\ + paddw %%xmm6, %%xmm3 # No possibility of overflow \n\ + paddw %%xmm7, %%xmm3 \n\ + paddw 144("EDI"), %%xmm3 \n" +#define SSE2_RGB2U "\ + # Create 8.6 fixed-point U data in XMM4 \n\ + movdqa %%xmm0, %%xmm4 \n\ + pmulhw 48("EDI"), %%xmm4 \n\ + movdqa %%xmm1, %%xmm6 \n\ + pmulhw 64("EDI"), %%xmm6 \n\ + movdqa %%xmm2, %%xmm7 \n\ + pmulhw 80("EDI"), %%xmm7 \n\ + paddw %%xmm6, %%xmm4 \n\ + paddw %%xmm7, %%xmm4 \n\ + paddw 160("EDI"), %%xmm4 \n" +#define SSE2_RGB2U0 "\ + # Create 8.6 fixed-point U data in XMM0 \n\ + pmulhw 48("EDI"), %%xmm0 \n\ + pmulhw 64("EDI"), %%xmm1 \n\ + pmulhw 80("EDI"), %%xmm2 \n\ + paddw %%xmm1, %%xmm0 \n\ + paddw %%xmm2, %%xmm0 \n\ + paddw 160("EDI"), %%xmm0 \n" +#define SSE2_RGB2V "\ + # Create 8.6 fixed-point V data in XMM0 \n\ + pmulhw 96("EDI"), %%xmm0 \n\ + pmulhw 112("EDI"), %%xmm1 \n\ + pmulhw 128("EDI"), %%xmm2 \n\ + paddw %%xmm1, %%xmm0 \n\ + paddw %%xmm2, %%xmm0 \n\ + paddw 160("EDI"), %%xmm0 \n" +#define SSE2_PACKYU "\ + # Shift back down to 8-bit values \n\ + psraw $6, %%xmm3 \n\ + psraw $6, %%xmm0 \n\ + # Pack into bytes \n\ + pxor %%xmm7, %%xmm7 \n\ + packuswb %%xmm7, %%xmm3 \n\ + packuswb %%xmm7, %%xmm0 \n" +#define SSE2_PACKYUV "\ + # Shift back down to 8-bit values \n\ + psraw $6, %%xmm3 \n\ + psraw $6, %%xmm4 \n\ + psraw $6, %%xmm0 \n\ + # Pack into bytes \n\ + pxor %%xmm7, %%xmm7 \n\ + packuswb %%xmm7, %%xmm3 \n\ + packuswb %%xmm7, %%xmm4 \n\ + packuswb %%xmm7, %%xmm0 \n" +#define SSE2_STRIPU(N) "\ + # Remove every odd U value \n\ + pand 176("EDI"), %%xmm"#N" \n\ + packuswb %%xmm7, %%xmm"#N" \n" +#define SSE2_STRIPV "\ + # Remove every even V value \n\ + psrlw $8, %%xmm0 \n\ + packuswb %%xmm7, %%xmm0 \n" + +static inline void sse2_rgb_to_yuv420p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + if (y%2 == 0) { + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2U0" \n\ + "SSE2_PACKYU" \n\ + "SSE2_STRIPU(0)" \n\ + # Store into destination pointers \n\ + movq %%xmm3, ("EAX") \n\ + movd %%xmm0, ("ECX") \n" + : /* no outputs */ + : "a" (destY+y*width+x), "c" (destU+(y/2)*(width/2)+(x/2)), + "D" (&rgb_data), "m" (rgb_data) + ); + } else { + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2V" \n\ + "SSE2_PACKYU" \n\ + "SSE2_STRIPV" \n\ + # Store into destination pointers \n\ + movq %%xmm3, ("EAX") \n\ + movd %%xmm0, ("EDX") \n" + : /* no outputs */ + : "a" (destY+y*width+x), "d" (destV+(y/2)*(width/2)+(x/2)), + "D" (&rgb_data), "m" (rgb_data) + ); + } +} + +static inline void sse2_rgb_to_yuv411p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2U" \n\ + "SSE2_RGB2V" \n\ + "SSE2_PACKYUV" \n\ + "SSE2_STRIPU(4)" \n\ + "SSE2_STRIPU(4)" \n\ + "SSE2_STRIPU(0)" \n\ + "SSE2_STRIPV" \n\ + # Store into destination pointers \n\ + movq %%xmm3, ("EAX") \n\ + push "EAX" # needed because GCC might rely on it later \n\ + movd %%xmm4, %%eax \n\ + movw %%ax, ("ECX") \n\ + movd %%xmm0, %%eax \n\ + movw %%ax, ("EDX") \n\ + pop "EAX" \n" + : /* no outputs */ + : "a" (destY+y*width+x), "c" (destU+y*(width/4)+(x/4)), + "d" (destV+y*(width/4)+(x/4)), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_rgb_to_yuv422p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2U" \n\ + "SSE2_RGB2V" \n\ + "SSE2_PACKYUV" \n\ + "SSE2_STRIPU(4)" \n\ + "SSE2_STRIPV" \n\ + # Store into destination pointers \n\ + movq %%xmm3, ("EAX") \n\ + movd %%xmm4, ("ECX") \n\ + movd %%xmm0, ("EDX") \n" + : /* no outputs */ + : "a" (destY+y*width+x), "c" (destU+y*(width/2)+(x/2)), + "d" (destV+y*(width/2)+(x/2)), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_rgb_to_yuv444p( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2U" \n\ + "SSE2_RGB2V" \n\ + "SSE2_PACKYUV" \n\ + # Store into destination pointers \n\ + movq %%xmm3, ("EAX") \n\ + movq %%xmm4, ("ECX") \n\ + movq %%xmm0, ("EDX") \n" + : /* no outputs */ + : "a" (destY+y*width+x), "c" (destU+y*width+x), "d" (destV+y*width+x), + "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_rgb_to_yuy2( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2U" \n\ + "SSE2_RGB2V" \n\ + "SSE2_PACKYUV" \n\ + "SSE2_STRIPU(4)" \n\ + "SSE2_STRIPV" \n\ + # Interleave Y/U/V \n\ + punpcklbw %%xmm0, %%xmm4 \n\ + punpcklbw %%xmm4, %%xmm3 \n\ + # Store into destination pointer \n\ + movdqu %%xmm3, ("EAX") \n" + : /* no outputs */ + : "a" (destY+(y*width+x)*2), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_rgb_to_uyvy( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2U" \n\ + "SSE2_RGB2V" \n\ + "SSE2_PACKYUV" \n\ + "SSE2_STRIPU(4)" \n\ + "SSE2_STRIPV" \n\ + # Interleave Y/U/V \n\ + punpcklbw %%xmm0, %%xmm4 \n\ + punpcklbw %%xmm3, %%xmm4 \n\ + # Store into destination pointer \n\ + movdqu %%xmm4, ("EAX") \n" + : /* no outputs */ + : "a" (destY+(y*width+x)*2), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_rgb_to_yvyu( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + asm("\ + "SSE2_RGB2Y" \n\ + "SSE2_RGB2U" \n\ + "SSE2_RGB2V" \n\ + "SSE2_PACKYUV" \n\ + # Remove every odd V value \n\ + pand 176("EDI"), %%xmm0 \n\ + packuswb %%xmm7, %%xmm0 \n\ + # Remove every even U value \n\ + psrlw $8, %%xmm4 \n\ + packuswb %%xmm7, %%xmm4 \n\ + # Interleave Y/U/V \n\ + punpcklbw %%xmm4, %%xmm0 \n\ + punpcklbw %%xmm0, %%xmm3 \n\ + # Store into destination pointer \n\ + movdqu %%xmm3, ("EAX") \n" + : /* no outputs */ + : "a" (destY+(y*width+x)*2), "D" (&rgb_data), "m" (rgb_data) + ); +} + +static inline void sse2_rgb_to_y8( + uint8_t *destY, uint8_t *destU, uint8_t *destV, int x, int y, int width) +{ + asm("\ + psllw $6, %%xmm0 \n\ + pmulhuw ("EDI"), %%xmm0 \n\ + psllw $6, %%xmm1 \n\ + pmulhuw 16("EDI"), %%xmm1 \n\ + psllw $6, %%xmm2 \n\ + pmulhuw 32("EDI"), %%xmm2 \n\ + paddw %%xmm1, %%xmm0 # No possibility of overflow \n\ + paddw %%xmm2, %%xmm0 \n\ + paddw 144("EDI"), %%xmm0 \n\ + psraw $6, %%xmm0 \n\ + packuswb %%xmm0, %%xmm0 \n\ + movq %%xmm0, ("EAX") \n" + : /* no outputs */ + : "a" (destY+y*width+x), "D" (&rgb_data), "m" (rgb_data) + ); +} + +/*************************************************************************/ + +static int yuvp_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa ("EDX"), %%xmm7 # constant: 255/219 \n\ + movdqa 32("EDX"), %%xmm6 # constant: 16 \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 16, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -1("ESI","ECX"), %%eax # retrieve Y byte \n\ + subl $16, %%eax # subtract 16 \n\ + imull %3, %%eax # multiply by 255/219 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + testb %%ah, %%ah # saturate to 0..255 \n\ + movl $-1, %%edx # (trash EDX, we don't need it \n\ + cmovnz %%edx, %%eax # anymore) \n\ + movl $0, %%edx \n\ + cmovs %%edx, %%eax \n\ + movb %%al, -1("EDI","ECX") # and store \n", + /* main_loop */ "\ + movdqu -16("ESI","ECX"), %%xmm0 # XMM0: Y15..Y0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: Y15..Y0 \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: Y7..Y0 \n\ + psubw %%xmm6, %%xmm0 # XMM0: unbias by 16 \n\ + psllw $2, %%xmm0 # XMM0: fixed point 8.2 \n\ + pmulhw %%xmm7, %%xmm0 # XMM0: multiply by 255/219>>2 \n\ + punpckhbw %%xmm4, %%xmm1 # XMM1: Y15..Y8 << 8 \n\ + psubw %%xmm6, %%xmm1 # XMM1: unbias by 16 \n\ + psllw $2, %%xmm1 # XMM1: fixed point 8.2 \n\ + pmulhw %%xmm7, %%xmm1 # XMM1: multiply by 255/219>>2 \n\ + packuswb %%xmm1, %%xmm0 # XMM0: G15..G0, saturated \n\ + movdqu %%xmm0, -16("EDI","ECX") \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (Y_GRAY), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +static int yuy2_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa ("EDX"), %%xmm7 # constant: 255/219 \n\ + movdqa 32("EDX"), %%xmm6 # constant: 16 \n\ + pcmpeqd %%xmm5, %%xmm5 \n\ + psrlw $8, %%xmm5 # constant: 0x00FF \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 8, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -2("ESI","ECX",2), %%eax # retrieve Y byte \n\ + subl $16, %%eax # subtract 16 \n\ + imull %3, %%eax # multiply by 255/219 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + testb %%ah, %%ah # saturate to 0..255 \n\ + movl $-1, %%edx # (trash EDX, we don't need it \n\ + cmovnz %%edx, %%eax # anymore) \n\ + movl $0, %%edx \n\ + cmovs %%edx, %%eax \n\ + movb %%al, -1("EDI","ECX") # and store \n", + /* main_loop */ "\ + movdqu -16("ESI","ECX",2),%%xmm0 #XMM0: V3 Y7..U0 Y0 \n\ + pand %%xmm5, %%xmm0 # XMM0: Y7..Y0 \n\ + psubw %%xmm6, %%xmm0 # XMM0: unbias by 16 \n\ + psllw $2, %%xmm0 # XMM0: fixed point 8.2 \n\ + pmulhw %%xmm7, %%xmm0 # XMM0: multiply by 255/219>>2 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: G7..G0, saturated \n\ + movq %%xmm0, -8("EDI","ECX") \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (Y_GRAY), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +static int uyvy_gray8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa ("EDX"), %%xmm7 # constant: 255/219 \n\ + movdqa 32("EDX"), %%xmm6 \n\ + psllw $2, %%xmm6 # constant: 16<<2 \n\ + pcmpeqd %%xmm5, %%xmm5 \n\ + psllw $8, %%xmm5 # constant: 0xFF00 \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 8, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -1("ESI","ECX",2), %%eax # retrieve Y byte \n\ + subl $16, %%eax # subtract 16 \n\ + imull %3, %%eax # multiply by 255/219 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + testb %%ah, %%ah # saturate to 0..255 \n\ + movl $-1, %%edx # (trash EDX, we don't need it \n\ + cmovnz %%edx, %%eax # anymore) \n\ + movl $0, %%edx \n\ + cmovs %%edx, %%eax \n\ + movb %%al, -1("EDI","ECX") # and store \n", + /* main_loop */ "\ + movdqu -16("ESI","ECX",2),%%xmm0 #XMM0: Y7 V3..Y0 U0 \n\ + pand %%xmm5, %%xmm0 # XMM0: Y7..Y0 << 8 \n\ + psrlw $6, %%xmm0 # XMM0: fixed point 8.2 \n\ + psubw %%xmm6, %%xmm0 # XMM0: unbias by 16 \n\ + pmulhw %%xmm7, %%xmm0 # XMM0: multiply by 255/219>>2 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: G7..G0, saturated \n\ + movq %%xmm0, -8("EDI","ECX") \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (Y_GRAY), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +/*************************************************************************/ + +static int gray8_y8_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa 16("EDX"), %%xmm7 # constant: 219/255 \n\ + movdqa 32("EDX"), %%xmm6 # constant: 16 \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 16, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -1("ESI","ECX"), %%eax # retrieve gray byte \n\ + imull %3, %%eax # multiply by 219/255 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + addl $16, %%eax # add 16 \n\ + movb %%al, -1("EDI","ECX") # and store \n", + /* main_loop */ "\ + movdqu -16("ESI","ECX"), %%xmm2 # XMM2: G15..G0 \n\ + movdqa %%xmm4, %%xmm0 \n\ + punpcklbw %%xmm2, %%xmm0 # XMM0: G7..G0 << 8 \n\ + pmulhuw %%xmm7, %%xmm0 # XMM0: multiply by 219/255>>2 \n\ + movdqa %%xmm4, %%xmm1 \n\ + punpckhbw %%xmm2, %%xmm1 # XMM1: G15..G8 << 8 \n\ + pmulhuw %%xmm7, %%xmm1 # XMM1: multiply by 219/255>>2 \n\ + psrlw $6, %%xmm0 # XMM0: shift down to 8 bits \n\ + paddw %%xmm6, %%xmm0 # XMM0: bias by 16 \n\ + psrlw $6, %%xmm1 # XMM1: shift down to 8 bits \n\ + paddw %%xmm6, %%xmm1 # XMM1: bias by 16 \n\ + packuswb %%xmm1, %%xmm0 # XMM0: Y15..Y0 \n\ + movdqu %%xmm0, -16("EDI","ECX") \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (GRAY_Y), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +static int gray8_yuy2_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa 16("EDX"), %%xmm7 # constant: 219/255 \n\ + movdqa 32("EDX"), %%xmm6 # constant: 16 \n\ + pcmpeqd %%xmm5, %%xmm5 \n\ + psllw $15, %%xmm5 # constant: 0x8000 \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 8, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -1("ESI","ECX"), %%eax # retrieve gray byte \n\ + imull %3, %%eax # multiply by 219/255 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + addl $16, %%eax # add 16 \n\ + movb %%al, -2("EDI","ECX",2) # and store \n\ + movb $128, -1("EDI","ECX",2) # store 128 in U/V byte \n", + /* main_loop */ "\ + movq -8("ESI","ECX"), %%xmm2 # XMM2: G5..G0 \n\ + movdqa %%xmm4, %%xmm0 \n\ + punpcklbw %%xmm2, %%xmm0 # XMM0: G7..G0 << 8 \n\ + pmulhuw %%xmm7, %%xmm0 # XMM0: multiply by 219/255>>2 \n\ + psrlw $6, %%xmm0 # XMM0: shift down to 8 bits \n\ + paddw %%xmm6, %%xmm0 # XMM0: bias by 16 \n\ + por %%xmm5, %%xmm0 # XMM0: OR in U/V bytes \n\ + movdqu %%xmm0, -16("EDI","ECX",2) \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (GRAY_Y), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +static int gray8_uyvy_sse2(uint8_t **src, uint8_t **dest, int width, int height) { + asm("movdqa 16("EDX"), %%xmm7 # constant: 219/255 \n\ + movdqa 32("EDX"), %%xmm6 \n\ + psllw $8, %%xmm6 # constant: 16 << 8 \n\ + pcmpeqd %%xmm5, %%xmm5 \n\ + psllw $15, %%xmm5 \n\ + psrlw $8, %%xmm5 # constant: 0x0080 \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n\ + pcmpeqd %%xmm3, %%xmm3 \n\ + psllw $8, %%xmm3 # constant: 0xFF00 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 8, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -1("ESI","ECX"), %%eax # retrieve gray byte \n\ + imull %3, %%eax # multiply by 219/255 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + addl $16, %%eax # add 16 \n\ + movb %%al, -1("EDI","ECX",2) # and store \n\ + movb $128, -2("EDI","ECX",2) # store 128 in U/V byte \n", + /* main_loop */ "\ + movq -8("ESI","ECX"), %%xmm2 # XMM2: G5..G0 \n\ + movdqa %%xmm4, %%xmm0 \n\ + punpcklbw %%xmm2, %%xmm0 # XMM0: G7..G0 << 8 \n\ + pmulhuw %%xmm7, %%xmm0 # XMM0: multiply by 219/255>>2 \n\ + psllw $2, %%xmm0 # XMM0: shift results to hi byte\n\ + pand %%xmm3, %%xmm0 # XMM0: clear low byte \n\ + paddw %%xmm6, %%xmm0 # XMM0: bias by 16 \n\ + por %%xmm5, %%xmm0 # XMM0: OR in U/V bytes \n\ + movdqu %%xmm0, -16("EDI","ECX",2) \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (GRAY_Y), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +/*************************************************************************/ + +static int y8_rgb24_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa ("EDX"), %%xmm7 # constant: 255/219 \n\ + movdqa 32("EDX"), %%xmm6 # constant: 16 \n\ + movdqa 48("EDX"), %%xmm5 # constant: bytes 0/3/6/9 mask \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 4, + /* push_regs */ "push "EBX, + /* pop_regs */ "pop "EBX, + /* small_loop */ "\ + lea ("ECX","ECX",2), "EDX" # 3*count for RGB offset \n\ + movzbl -1("ESI","ECX"), %%eax # retrieve Y byte \n\ + subl $16, %%eax # subtract 16 \n\ + imull %3, %%eax # multiply by 255/219 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + testb %%ah, %%ah # saturate to 0..255 \n\ + movl $-1, %%ebx \n\ + cmovnz %%ebx, %%eax \n\ + movl $0, %%ebx \n\ + cmovs %%ebx, %%eax \n\ + movb %%al, -3("EDI","EDX") # and store \n\ + movb %%al, -2("EDI","EDX") \n\ + movb %%al, -1("EDI","EDX") \n", + /* main_loop */ "\ + lea ("ECX","ECX",2), "EDX" \n\ + movd -4("ESI","ECX"), %%xmm0 # XMM0: Y3..Y0 \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: Y3..Y0 in 16 bits \n\ + psubw %%xmm6, %%xmm0 # XMM0: unbias by 16 \n\ + psllw $2, %%xmm0 # XMM0: fixed point 8.2 \n\ + pmulhw %%xmm7, %%xmm0 # XMM0: multiply by 255/219>>2 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: G3..G0, saturated \n\ + pshuflw $0x50, %%xmm0, %%xmm0 # X0.l: G3 G2 G3 G2 G1 G0 G1 G0 \n\ + pshufhw $0x55, %%xmm0, %%xmm0 # X0.h: G3 G2 G3 G2 G3 G2 G3 G2 \n\ + pand %%xmm5, %%xmm0 # XMM0: ------3--2--1--0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: ------3--2--1--0 \n\ + pslldq $1, %%xmm1 # XMM1: -----3--2--1--0- \n\ + movdqa %%xmm0, %%xmm2 # XMM2: ------3--2--1--0 \n\ + pslldq $2, %%xmm2 # XMM2: ----3--2--1--0-- \n\ + por %%xmm1, %%xmm0 # XMM0: -----33-22-11-00 \n\ + por %%xmm2, %%xmm0 # XMM0: ----333222111000 \n\ + movd %%xmm0, -12("EDI","EDX") \n\ + pshufd $0xC9, %%xmm0, %%xmm0 \n\ + movq %%xmm0, -8("EDI","EDX") \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (Y_GRAY), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +/* 4BPP is slightly easier... */ +static int y8_rgba32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa ("EDX"), %%xmm7 # constant: 255/219 \n\ + movdqa 32("EDX"), %%xmm6 # constant: 16 \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 4, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -1("ESI","ECX"), %%eax # retrieve Y byte \n\ + subl $16, %%eax # subtract 16 \n\ + imull %3, %%eax # multiply by 255/219 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + testb %%ah, %%ah # saturate to 0..255 \n\ + movl $-1, %%edx \n\ + cmovnz %%edx, %%eax \n\ + movl $0, %%edx \n\ + cmovs %%edx, %%eax \n\ + movb %%al, -4("EDI","ECX",4) # and store \n\ + movb %%al, -3("EDI","ECX",4) \n\ + movb %%al, -2("EDI","ECX",4) \n", + /* main_loop */ "\ + movd -4("ESI","ECX"), %%xmm0 # XMM0: Y3..Y0 \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: Y3..Y0 in 16 bits \n\ + psubw %%xmm6, %%xmm0 # XMM0: unbias by 16 \n\ + psllw $2, %%xmm0 # XMM0: fixed point 8.2 \n\ + pmulhw %%xmm7, %%xmm0 # XMM0: multiply by 255/219>>2 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: G3..G0, saturated \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: G3..G0 in 16 bits \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: ---3---2---1---0 \n\ + movdqa %%xmm0, %%xmm1 # XMM1: ---3---2---1---0 \n\ + pslldq $1, %%xmm1 # XMM1: --3---2---1---0- \n\ + movdqa %%xmm0, %%xmm2 # XMM2: ---3---2---1---0 \n\ + pslldq $2, %%xmm2 # XMM2: -3---2---1---0-- \n\ + por %%xmm1, %%xmm0 # XMM0: --33--22--11--00 \n\ + por %%xmm2, %%xmm0 # XMM0: -333-222-111-000 \n\ + movntdq %%xmm0, -16("EDI","ECX",4) \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (Y_GRAY), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +static int y8_argb32_sse2(uint8_t **src, uint8_t **dest, int width, int height) +{ + asm("movdqa ("EDX"), %%xmm7 # constant: 255/219 \n\ + movdqa 32("EDX"), %%xmm6 # constant: 16 \n\ + pxor %%xmm4, %%xmm4 # constant: 0 \n" + SIMD_LOOP_WRAPPER( + /* blocksize */ 4, + /* push_regs */ "", + /* pop_regs */ "", + /* small_loop */ "\ + movzbl -1("ESI","ECX"), %%eax # retrieve Y byte \n\ + subl $16, %%eax # subtract 16 \n\ + imull %3, %%eax # multiply by 255/219 \n\ + shrl $14, %%eax # shift down to 8 bits \n\ + testb %%ah, %%ah # saturate to 0..255 \n\ + movl $-1, %%edx \n\ + cmovnz %%edx, %%eax \n\ + movl $0, %%edx \n\ + cmovs %%edx, %%eax \n\ + movb %%al, -3("EDI","ECX",4) # and store \n\ + movb %%al, -2("EDI","ECX",4) \n\ + movb %%al, -1("EDI","ECX",4) \n", + /* main_loop */ "\ + movd -4("ESI","ECX"), %%xmm0 # XMM0: Y3..Y0 \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: Y3..Y0 in 16 bits \n\ + psubw %%xmm6, %%xmm0 # XMM0: unbias by 16 \n\ + psllw $2, %%xmm0 # XMM0: fixed point 8.2 \n\ + pmulhw %%xmm7, %%xmm0 # XMM0: multiply by 255/219>>2 \n\ + packuswb %%xmm0, %%xmm0 # XMM0: G3..G0, saturated \n\ + punpcklbw %%xmm4, %%xmm0 # XMM0: G3..G0 in 16 bits \n\ + movdqa %%xmm4, %%xmm3 # XMM3: 0 \n\ + punpcklbw %%xmm0, %%xmm3 # XMM3: --3---2---1---0- \n\ + movdqa %%xmm3, %%xmm1 # XMM1: --3---2---1---0- \n\ + pslldq $1, %%xmm1 # XMM1: -3---2---1---0-- \n\ + movdqa %%xmm3, %%xmm2 # XMM2: --3---2---1---0- \n\ + pslldq $2, %%xmm2 # XMM2: 3---2---1---0--- \n\ + por %%xmm1, %%xmm3 # XMM3: -33--22--11--00- \n\ + por %%xmm2, %%xmm3 # XMM3: 333-222-111-000- \n\ + movntdq %%xmm3, -16("EDI","ECX",4) \n", + /* emms */ "emms") + : /* no outputs */ + : "S" (src[0]), "D" (dest[0]), "c" (width*height), + "i" (Y_GRAY), "d" (&gray_data), "m" (gray_data) + : "eax"); + return 1; +} + +/*************************************************************************/ + +#endif /* HAVE_ASM_SSE2 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Initialization */ + +int ac_imgconvert_init_yuv_rgb(int accel) +{ + /******** Standard C implementations ********/ + + //---- YUV->RGB ----// + + if (!register_conversion(IMG_YUV420P, IMG_RGB24, yuv420p_rgb24) + || !register_conversion(IMG_YUV411P, IMG_RGB24, yuv411p_rgb24) + || !register_conversion(IMG_YUV422P, IMG_RGB24, yuv422p_rgb24) + || !register_conversion(IMG_YUV444P, IMG_RGB24, yuv444p_rgb24) + || !register_conversion(IMG_YUY2, IMG_RGB24, yuy2_rgb24) + || !register_conversion(IMG_UYVY, IMG_RGB24, uyvy_rgb24) + || !register_conversion(IMG_YVYU, IMG_RGB24, yvyu_rgb24) + || !register_conversion(IMG_Y8, IMG_RGB24, y8_rgb24) + + || !register_conversion(IMG_YUV420P, IMG_BGR24, yuv420p_bgr24) + || !register_conversion(IMG_YUV411P, IMG_BGR24, yuv411p_bgr24) + || !register_conversion(IMG_YUV422P, IMG_BGR24, yuv422p_bgr24) + || !register_conversion(IMG_YUV444P, IMG_BGR24, yuv444p_bgr24) + || !register_conversion(IMG_YUY2, IMG_BGR24, yuy2_bgr24) + || !register_conversion(IMG_UYVY, IMG_BGR24, uyvy_bgr24) + || !register_conversion(IMG_YVYU, IMG_BGR24, yvyu_bgr24) + || !register_conversion(IMG_Y8, IMG_BGR24, y8_rgb24) + + || !register_conversion(IMG_YUV420P, IMG_RGBA32, yuv420p_rgba32) + || !register_conversion(IMG_YUV411P, IMG_RGBA32, yuv411p_rgba32) + || !register_conversion(IMG_YUV422P, IMG_RGBA32, yuv422p_rgba32) + || !register_conversion(IMG_YUV444P, IMG_RGBA32, yuv444p_rgba32) + || !register_conversion(IMG_YUY2, IMG_RGBA32, yuy2_rgba32) + || !register_conversion(IMG_UYVY, IMG_RGBA32, uyvy_rgba32) + || !register_conversion(IMG_YVYU, IMG_RGBA32, yvyu_rgba32) + || !register_conversion(IMG_Y8, IMG_RGBA32, y8_rgba32) + + || !register_conversion(IMG_YUV420P, IMG_ABGR32, yuv420p_abgr32) + || !register_conversion(IMG_YUV411P, IMG_ABGR32, yuv411p_abgr32) + || !register_conversion(IMG_YUV422P, IMG_ABGR32, yuv422p_abgr32) + || !register_conversion(IMG_YUV444P, IMG_ABGR32, yuv444p_abgr32) + || !register_conversion(IMG_YUY2, IMG_ABGR32, yuy2_abgr32) + || !register_conversion(IMG_UYVY, IMG_ABGR32, uyvy_abgr32) + || !register_conversion(IMG_YVYU, IMG_ABGR32, yvyu_abgr32) + || !register_conversion(IMG_Y8, IMG_ABGR32, y8_argb32) + + || !register_conversion(IMG_YUV420P, IMG_ARGB32, yuv420p_argb32) + || !register_conversion(IMG_YUV411P, IMG_ARGB32, yuv411p_argb32) + || !register_conversion(IMG_YUV422P, IMG_ARGB32, yuv422p_argb32) + || !register_conversion(IMG_YUV444P, IMG_ARGB32, yuv444p_argb32) + || !register_conversion(IMG_YUY2, IMG_ARGB32, yuy2_argb32) + || !register_conversion(IMG_UYVY, IMG_ARGB32, uyvy_argb32) + || !register_conversion(IMG_YVYU, IMG_ARGB32, yvyu_argb32) + || !register_conversion(IMG_Y8, IMG_ARGB32, y8_argb32) + + || !register_conversion(IMG_YUV420P, IMG_BGRA32, yuv420p_bgra32) + || !register_conversion(IMG_YUV411P, IMG_BGRA32, yuv411p_bgra32) + || !register_conversion(IMG_YUV422P, IMG_BGRA32, yuv422p_bgra32) + || !register_conversion(IMG_YUV444P, IMG_BGRA32, yuv444p_bgra32) + || !register_conversion(IMG_YUY2, IMG_BGRA32, yuy2_bgra32) + || !register_conversion(IMG_UYVY, IMG_BGRA32, uyvy_bgra32) + || !register_conversion(IMG_YVYU, IMG_BGRA32, yvyu_bgra32) + || !register_conversion(IMG_Y8, IMG_BGRA32, y8_rgba32) + + //---- RGB->YUV ----// + + || !register_conversion(IMG_RGB24, IMG_YUV420P, rgb24_yuv420p) + || !register_conversion(IMG_RGB24, IMG_YUV411P, rgb24_yuv411p) + || !register_conversion(IMG_RGB24, IMG_YUV422P, rgb24_yuv422p) + || !register_conversion(IMG_RGB24, IMG_YUV444P, rgb24_yuv444p) + || !register_conversion(IMG_RGB24, IMG_YUY2, rgb24_yuy2) + || !register_conversion(IMG_RGB24, IMG_UYVY, rgb24_uyvy) + || !register_conversion(IMG_RGB24, IMG_YVYU, rgb24_yvyu) + || !register_conversion(IMG_RGB24, IMG_Y8, rgb24_y8) + + || !register_conversion(IMG_BGR24, IMG_YUV420P, bgr24_yuv420p) + || !register_conversion(IMG_BGR24, IMG_YUV411P, bgr24_yuv411p) + || !register_conversion(IMG_BGR24, IMG_YUV422P, bgr24_yuv422p) + || !register_conversion(IMG_BGR24, IMG_YUV444P, bgr24_yuv444p) + || !register_conversion(IMG_BGR24, IMG_YUY2, bgr24_yuy2) + || !register_conversion(IMG_BGR24, IMG_UYVY, bgr24_uyvy) + || !register_conversion(IMG_BGR24, IMG_YVYU, bgr24_yvyu) + || !register_conversion(IMG_BGR24, IMG_Y8, bgr24_y8) + + || !register_conversion(IMG_RGBA32, IMG_YUV420P, rgba32_yuv420p) + || !register_conversion(IMG_RGBA32, IMG_YUV411P, rgba32_yuv411p) + || !register_conversion(IMG_RGBA32, IMG_YUV422P, rgba32_yuv422p) + || !register_conversion(IMG_RGBA32, IMG_YUV444P, rgba32_yuv444p) + || !register_conversion(IMG_RGBA32, IMG_YUY2, rgba32_yuy2) + || !register_conversion(IMG_RGBA32, IMG_UYVY, rgba32_uyvy) + || !register_conversion(IMG_RGBA32, IMG_YVYU, rgba32_yvyu) + || !register_conversion(IMG_RGBA32, IMG_Y8, rgba32_y8) + + || !register_conversion(IMG_ABGR32, IMG_YUV420P, abgr32_yuv420p) + || !register_conversion(IMG_ABGR32, IMG_YUV411P, abgr32_yuv411p) + || !register_conversion(IMG_ABGR32, IMG_YUV422P, abgr32_yuv422p) + || !register_conversion(IMG_ABGR32, IMG_YUV444P, abgr32_yuv444p) + || !register_conversion(IMG_ABGR32, IMG_YUY2, abgr32_yuy2) + || !register_conversion(IMG_ABGR32, IMG_UYVY, abgr32_uyvy) + || !register_conversion(IMG_ABGR32, IMG_YVYU, abgr32_yvyu) + || !register_conversion(IMG_ABGR32, IMG_Y8, abgr32_y8) + + || !register_conversion(IMG_ARGB32, IMG_YUV420P, argb32_yuv420p) + || !register_conversion(IMG_ARGB32, IMG_YUV411P, argb32_yuv411p) + || !register_conversion(IMG_ARGB32, IMG_YUV422P, argb32_yuv422p) + || !register_conversion(IMG_ARGB32, IMG_YUV444P, argb32_yuv444p) + || !register_conversion(IMG_ARGB32, IMG_YUY2, argb32_yuy2) + || !register_conversion(IMG_ARGB32, IMG_UYVY, argb32_uyvy) + || !register_conversion(IMG_ARGB32, IMG_YVYU, argb32_yvyu) + || !register_conversion(IMG_ARGB32, IMG_Y8, argb32_y8) + + || !register_conversion(IMG_BGRA32, IMG_YUV420P, bgra32_yuv420p) + || !register_conversion(IMG_BGRA32, IMG_YUV411P, bgra32_yuv411p) + || !register_conversion(IMG_BGRA32, IMG_YUV422P, bgra32_yuv422p) + || !register_conversion(IMG_BGRA32, IMG_YUV444P, bgra32_yuv444p) + || !register_conversion(IMG_BGRA32, IMG_YUY2, bgra32_yuy2) + || !register_conversion(IMG_BGRA32, IMG_UYVY, bgra32_uyvy) + || !register_conversion(IMG_BGRA32, IMG_YVYU, bgra32_yvyu) + || !register_conversion(IMG_BGRA32, IMG_Y8, bgra32_y8) + + //---- Grayscale ----// + + || !register_conversion(IMG_YUV420P, IMG_GRAY8, yuvp_gray8) + || !register_conversion(IMG_YUV411P, IMG_GRAY8, yuvp_gray8) + || !register_conversion(IMG_YUV422P, IMG_GRAY8, yuvp_gray8) + || !register_conversion(IMG_YUV444P, IMG_GRAY8, yuvp_gray8) + || !register_conversion(IMG_YUY2, IMG_GRAY8, yuy2_gray8) + || !register_conversion(IMG_UYVY, IMG_GRAY8, uyvy_gray8) + || !register_conversion(IMG_YVYU, IMG_GRAY8, yuy2_gray8) + || !register_conversion(IMG_Y8, IMG_GRAY8, yuvp_gray8) + + || !register_conversion(IMG_GRAY8, IMG_YUV420P, gray8_yuv420p) + || !register_conversion(IMG_GRAY8, IMG_YUV411P, gray8_yuv411p) + || !register_conversion(IMG_GRAY8, IMG_YUV422P, gray8_yuv422p) + || !register_conversion(IMG_GRAY8, IMG_YUV444P, gray8_yuv444p) + || !register_conversion(IMG_GRAY8, IMG_YUY2, gray8_yuy2) + || !register_conversion(IMG_GRAY8, IMG_UYVY, gray8_uyvy) + || !register_conversion(IMG_GRAY8, IMG_YVYU, gray8_yuy2) + || !register_conversion(IMG_GRAY8, IMG_Y8, gray8_y8) + ) { + return 0; + } + + /******** MMX implementations ********/ + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) + if (accel & AC_MMX) { + + //---- YUV->RGB ----// + + if (!register_conversion(IMG_YUV420P, IMG_RGB24, yuv420p_rgb24_mmx) + || !register_conversion(IMG_YUV422P, IMG_RGB24, yuv422p_rgb24_mmx) + || !register_conversion(IMG_YUV420P, IMG_BGR24, yuv420p_bgr24_mmx) + || !register_conversion(IMG_YUV422P, IMG_BGR24, yuv422p_bgr24_mmx) + || !register_conversion(IMG_YUV420P, IMG_RGBA32, yuv420p_rgba32_mmx) + || !register_conversion(IMG_YUV422P, IMG_RGBA32, yuv422p_rgba32_mmx) + || !register_conversion(IMG_YUV420P, IMG_ABGR32, yuv420p_abgr32_mmx) + || !register_conversion(IMG_YUV422P, IMG_ABGR32, yuv422p_abgr32_mmx) + || !register_conversion(IMG_YUV420P, IMG_ARGB32, yuv420p_argb32_mmx) + || !register_conversion(IMG_YUV422P, IMG_ARGB32, yuv422p_argb32_mmx) + || !register_conversion(IMG_YUV420P, IMG_BGRA32, yuv420p_bgra32_mmx) + || !register_conversion(IMG_YUV422P, IMG_BGRA32, yuv422p_bgra32_mmx) + ) { + return 0; + } + } +#endif + + /******** SSE2 implementations ********/ + +#if defined(HAVE_ASM_SSE2) + if (HAS_ACCEL(accel, AC_SSE2)) { + + //---- YUV->RGB ----// + if (!register_conversion(IMG_YUV420P, IMG_RGB24, yuv420p_rgb24_sse2) + || !register_conversion(IMG_YUV411P, IMG_RGB24, yuv411p_rgb24_sse2) + || !register_conversion(IMG_YUV422P, IMG_RGB24, yuv422p_rgb24_sse2) + || !register_conversion(IMG_YUV444P, IMG_RGB24, yuv444p_rgb24_sse2) + || !register_conversion(IMG_YUY2, IMG_RGB24, yuy2_rgb24_sse2) + || !register_conversion(IMG_UYVY, IMG_RGB24, uyvy_rgb24_sse2) + || !register_conversion(IMG_YVYU, IMG_RGB24, yvyu_rgb24_sse2) + || !register_conversion(IMG_Y8, IMG_RGB24, y8_rgb24_sse2) + + || !register_conversion(IMG_YUV420P, IMG_BGR24, yuv420p_bgr24_sse2) + || !register_conversion(IMG_YUV411P, IMG_BGR24, yuv411p_bgr24_sse2) + || !register_conversion(IMG_YUV422P, IMG_BGR24, yuv422p_bgr24_sse2) + || !register_conversion(IMG_YUV444P, IMG_BGR24, yuv444p_bgr24_sse2) + || !register_conversion(IMG_YUY2, IMG_BGR24, yuy2_bgr24_sse2) + || !register_conversion(IMG_UYVY, IMG_BGR24, uyvy_bgr24_sse2) + || !register_conversion(IMG_YVYU, IMG_BGR24, yvyu_bgr24_sse2) + || !register_conversion(IMG_Y8, IMG_BGR24, y8_rgb24_sse2) + + || !register_conversion(IMG_YUV420P, IMG_RGBA32, yuv420p_rgba32_sse2) + || !register_conversion(IMG_YUV411P, IMG_RGBA32, yuv411p_rgba32_sse2) + || !register_conversion(IMG_YUV422P, IMG_RGBA32, yuv422p_rgba32_sse2) + || !register_conversion(IMG_YUV444P, IMG_RGBA32, yuv444p_rgba32_sse2) + || !register_conversion(IMG_YUY2, IMG_RGBA32, yuy2_rgba32_sse2) + || !register_conversion(IMG_UYVY, IMG_RGBA32, uyvy_rgba32_sse2) + || !register_conversion(IMG_YVYU, IMG_RGBA32, yvyu_rgba32_sse2) + || !register_conversion(IMG_Y8, IMG_RGBA32, y8_rgba32_sse2) + + || !register_conversion(IMG_YUV420P, IMG_ABGR32, yuv420p_abgr32_sse2) + || !register_conversion(IMG_YUV411P, IMG_ABGR32, yuv411p_abgr32_sse2) + || !register_conversion(IMG_YUV422P, IMG_ABGR32, yuv422p_abgr32_sse2) + || !register_conversion(IMG_YUV444P, IMG_ABGR32, yuv444p_abgr32_sse2) + || !register_conversion(IMG_YUY2, IMG_ABGR32, yuy2_abgr32_sse2) + || !register_conversion(IMG_UYVY, IMG_ABGR32, uyvy_abgr32_sse2) + || !register_conversion(IMG_YVYU, IMG_ABGR32, yvyu_abgr32_sse2) + || !register_conversion(IMG_Y8, IMG_ABGR32, y8_argb32_sse2) + + || !register_conversion(IMG_YUV420P, IMG_ARGB32, yuv420p_argb32_sse2) + || !register_conversion(IMG_YUV411P, IMG_ARGB32, yuv411p_argb32_sse2) + || !register_conversion(IMG_YUV422P, IMG_ARGB32, yuv422p_argb32_sse2) + || !register_conversion(IMG_YUV444P, IMG_ARGB32, yuv444p_argb32_sse2) + || !register_conversion(IMG_YUY2, IMG_ARGB32, yuy2_argb32_sse2) + || !register_conversion(IMG_UYVY, IMG_ARGB32, uyvy_argb32_sse2) + || !register_conversion(IMG_YVYU, IMG_ARGB32, yvyu_argb32_sse2) + || !register_conversion(IMG_Y8, IMG_ARGB32, y8_argb32_sse2) + + || !register_conversion(IMG_YUV420P, IMG_BGRA32, yuv420p_bgra32_sse2) + || !register_conversion(IMG_YUV411P, IMG_BGRA32, yuv411p_bgra32_sse2) + || !register_conversion(IMG_YUV422P, IMG_BGRA32, yuv422p_bgra32_sse2) + || !register_conversion(IMG_YUV444P, IMG_BGRA32, yuv444p_bgra32_sse2) + || !register_conversion(IMG_YUY2, IMG_BGRA32, yuy2_bgra32_sse2) + || !register_conversion(IMG_UYVY, IMG_BGRA32, uyvy_bgra32_sse2) + || !register_conversion(IMG_YVYU, IMG_BGRA32, yvyu_bgra32_sse2) + || !register_conversion(IMG_Y8, IMG_BGRA32, y8_rgba32_sse2) + + //---- RGB->YUV ----// + + || !register_conversion(IMG_RGB24, IMG_YUV420P, rgb24_yuv420p_sse2) + || !register_conversion(IMG_RGB24, IMG_YUV411P, rgb24_yuv411p_sse2) + || !register_conversion(IMG_RGB24, IMG_YUV422P, rgb24_yuv422p_sse2) + || !register_conversion(IMG_RGB24, IMG_YUV444P, rgb24_yuv444p_sse2) + || !register_conversion(IMG_RGB24, IMG_YUY2, rgb24_yuy2_sse2) + || !register_conversion(IMG_RGB24, IMG_UYVY, rgb24_uyvy_sse2) + || !register_conversion(IMG_RGB24, IMG_YVYU, rgb24_yvyu_sse2) + || !register_conversion(IMG_RGB24, IMG_Y8, rgb24_y8_sse2) + + || !register_conversion(IMG_BGR24, IMG_YUV420P, bgr24_yuv420p_sse2) + || !register_conversion(IMG_BGR24, IMG_YUV411P, bgr24_yuv411p_sse2) + || !register_conversion(IMG_BGR24, IMG_YUV422P, bgr24_yuv422p_sse2) + || !register_conversion(IMG_BGR24, IMG_YUV444P, bgr24_yuv444p_sse2) + || !register_conversion(IMG_BGR24, IMG_YUY2, bgr24_yuy2_sse2) + || !register_conversion(IMG_BGR24, IMG_UYVY, bgr24_uyvy_sse2) + || !register_conversion(IMG_BGR24, IMG_YVYU, bgr24_yvyu_sse2) + || !register_conversion(IMG_BGR24, IMG_Y8, bgr24_y8_sse2) + + || !register_conversion(IMG_RGBA32, IMG_YUV420P, rgba32_yuv420p_sse2) + || !register_conversion(IMG_RGBA32, IMG_YUV411P, rgba32_yuv411p_sse2) + || !register_conversion(IMG_RGBA32, IMG_YUV422P, rgba32_yuv422p_sse2) + || !register_conversion(IMG_RGBA32, IMG_YUV444P, rgba32_yuv444p_sse2) + || !register_conversion(IMG_RGBA32, IMG_YUY2, rgba32_yuy2_sse2) + || !register_conversion(IMG_RGBA32, IMG_UYVY, rgba32_uyvy_sse2) + || !register_conversion(IMG_RGBA32, IMG_YVYU, rgba32_yvyu_sse2) + || !register_conversion(IMG_RGBA32, IMG_Y8, rgba32_y8_sse2) + + || !register_conversion(IMG_ABGR32, IMG_YUV420P, abgr32_yuv420p_sse2) + || !register_conversion(IMG_ABGR32, IMG_YUV411P, abgr32_yuv411p_sse2) + || !register_conversion(IMG_ABGR32, IMG_YUV422P, abgr32_yuv422p_sse2) + || !register_conversion(IMG_ABGR32, IMG_YUV444P, abgr32_yuv444p_sse2) + || !register_conversion(IMG_ABGR32, IMG_YUY2, abgr32_yuy2_sse2) + || !register_conversion(IMG_ABGR32, IMG_UYVY, abgr32_uyvy_sse2) + || !register_conversion(IMG_ABGR32, IMG_YVYU, abgr32_yvyu_sse2) + || !register_conversion(IMG_ABGR32, IMG_Y8, abgr32_y8_sse2) + + || !register_conversion(IMG_ARGB32, IMG_YUV420P, argb32_yuv420p_sse2) + || !register_conversion(IMG_ARGB32, IMG_YUV411P, argb32_yuv411p_sse2) + || !register_conversion(IMG_ARGB32, IMG_YUV422P, argb32_yuv422p_sse2) + || !register_conversion(IMG_ARGB32, IMG_YUV444P, argb32_yuv444p_sse2) + || !register_conversion(IMG_ARGB32, IMG_YUY2, argb32_yuy2_sse2) + || !register_conversion(IMG_ARGB32, IMG_UYVY, argb32_uyvy_sse2) + || !register_conversion(IMG_ARGB32, IMG_YVYU, argb32_yvyu_sse2) + || !register_conversion(IMG_ARGB32, IMG_Y8, argb32_y8_sse2) + + || !register_conversion(IMG_BGRA32, IMG_YUV420P, bgra32_yuv420p_sse2) + || !register_conversion(IMG_BGRA32, IMG_YUV411P, bgra32_yuv411p_sse2) + || !register_conversion(IMG_BGRA32, IMG_YUV422P, bgra32_yuv422p_sse2) + || !register_conversion(IMG_BGRA32, IMG_YUV444P, bgra32_yuv444p_sse2) + || !register_conversion(IMG_BGRA32, IMG_YUY2, bgra32_yuy2_sse2) + || !register_conversion(IMG_BGRA32, IMG_UYVY, bgra32_uyvy_sse2) + || !register_conversion(IMG_BGRA32, IMG_YVYU, bgra32_yvyu_sse2) + || !register_conversion(IMG_BGRA32, IMG_Y8, bgra32_y8_sse2) + + //---- Grayscale ----// + + || !register_conversion(IMG_GRAY8, IMG_YUY2, gray8_yuy2_sse2) + || !register_conversion(IMG_GRAY8, IMG_UYVY, gray8_uyvy_sse2) + || !register_conversion(IMG_GRAY8, IMG_YVYU, gray8_yuy2_sse2) + || !register_conversion(IMG_GRAY8, IMG_Y8, gray8_y8_sse2) + ) { + return 0; + } + } + + /* YUV->GRAY8 routines use CMOVcc */ + if (HAS_ACCEL(accel, AC_CMOVE|AC_SSE2)) { + if (!register_conversion(IMG_YUV420P, IMG_GRAY8, yuvp_gray8_sse2) + || !register_conversion(IMG_YUV411P, IMG_GRAY8, yuvp_gray8_sse2) + || !register_conversion(IMG_YUV422P, IMG_GRAY8, yuvp_gray8_sse2) + || !register_conversion(IMG_YUV444P, IMG_GRAY8, yuvp_gray8_sse2) + || !register_conversion(IMG_YUY2, IMG_GRAY8, yuy2_gray8_sse2) + || !register_conversion(IMG_UYVY, IMG_GRAY8, uyvy_gray8_sse2) + || !register_conversion(IMG_YVYU, IMG_GRAY8, yuy2_gray8_sse2) + || !register_conversion(IMG_Y8, IMG_GRAY8, yuvp_gray8_sse2) + ) { + return 0; + } + } +#endif + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/imgconvert.c b/branches/V-1.5.3/veejay-server/aclib/imgconvert.c new file mode 100644 index 00000000..cc502977 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/imgconvert.c @@ -0,0 +1,119 @@ +/* + * imgconvert.c - image format conversion routines + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "imgconvert.h" +#include "img_internal.h" + +#include +#include + +/*************************************************************************/ + +static struct { + ImageFormat srcfmt, destfmt; + ConversionFunc func; +} *conversions; +static int n_conversions = 0; + +/*************************************************************************/ +/*************************************************************************/ + +/* Image conversion routine. src and dest are arrays of pointers to planes + * (for packed formats with only one plane, just use `&data'); srcfmt and + * destfmt specify the source and destination image formats (IMG_*). + * width and height are in pixels. Returns 1 on success, 0 on failure. */ + +int ac_imgconvert(uint8_t **src, ImageFormat srcfmt, + uint8_t **dest, ImageFormat destfmt, + int width, int height) +{ + int i; + + /* Hack to handle YV12 easily, because conversion routines don't get + * format tags */ + uint8_t *newsrc[3], *newdest[3]; + if (srcfmt == IMG_YV12) { + srcfmt = IMG_YUV420P; + newsrc[0] = src[0]; + newsrc[1] = src[2]; + newsrc[2] = src[1]; + src = newsrc; + } + if (destfmt == IMG_YV12) { + destfmt = IMG_YUV420P; + newdest[0] = dest[0]; + newdest[1] = dest[2]; + newdest[2] = dest[1]; + dest = newdest; + } + + for (i = 0; i < n_conversions; i++) { + if (conversions[i].srcfmt==srcfmt && conversions[i].destfmt==destfmt) + return (*conversions[i].func)(src, dest, width, height); + } + + return 0; +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Internal use only! */ + +int ac_imgconvert_init(int accel) +{ + if (!ac_imgconvert_init_yuv_planar(accel) + || !ac_imgconvert_init_yuv_packed(accel) + || !ac_imgconvert_init_yuv_mixed(accel) + || !ac_imgconvert_init_yuv_rgb(accel) + || !ac_imgconvert_init_rgb_packed(accel) + ) { + fprintf(stderr, "ac_imgconvert_init() failed"); + return 0; + } + return 1; +} + +int register_conversion(ImageFormat srcfmt, ImageFormat destfmt, + ConversionFunc function) +{ + int i; + + for (i = 0; i < n_conversions; i++) { + if (conversions[i].srcfmt==srcfmt && conversions[i].destfmt==destfmt) { + conversions[i].func = function; + return 1; + } + } + + if (!(conversions = realloc(conversions, + (n_conversions+1) * sizeof(*conversions)))) { + fprintf(stderr, "register_conversion(): out of memory\n"); + return 0; + } + conversions[n_conversions].srcfmt = srcfmt; + conversions[n_conversions].destfmt = destfmt; + conversions[n_conversions].func = function; + n_conversions++; + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/imgconvert.h b/branches/V-1.5.3/veejay-server/aclib/imgconvert.h new file mode 100644 index 00000000..c02d5a01 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/imgconvert.h @@ -0,0 +1,105 @@ +/* + * imgconvert.h - defines for image format conversion routines + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#ifndef ACLIB_IMGCONVERT_H +#define ACLIB_IMGCONVERT_H + +/*************************************************************************/ + +/* Image format defines */ +typedef enum { + IMG_UNKNOWN = 0, /* Unknown/unset (dummy value, guaranteed to be 0) */ + /* YUV formats */ + IMG_YUV_BASE = 0x1000, + IMG_YUV420P, /* YUV planar, 1 U/V per 2x2 Y pixels */ + IMG_YV12, /* YUV420P with U and V reversed */ + IMG_YUV411P, /* YUV planar, 1 U/V per 4x1 Y pixels */ + IMG_YUV422P, /* YUV planar, 1 U/V per 2x1 Y pixels */ + IMG_YUV444P, /* YUV planar, 1 U/V per 1x1 Y pixels */ + IMG_YUY2, /* YUV packed, 1 U/V per 2x1 Y pixels, Y:U:Y:V */ + IMG_UYVY, /* YUV packed, 1 U/V per 2x1 Y pixels, U:Y:V:Y */ + IMG_YVYU, /* YUV packed, 1 U/V per 2x1 Y pixels, Y:V:Y:U */ + IMG_Y8, /* Y-only 8-bit data */ + IMG_YUV_LAST, + /* RGB formats */ + IMG_RGB_BASE = 0x2000, + IMG_RGB24, /* RGB packed, 8 bits per component, R:G:B */ + IMG_BGR24, /* RGB packed, 8 bits per component, B:G:R */ + IMG_RGBA32, /* RGB+alpha packed, 8 bits per component, R:G:B:A */ + IMG_ABGR32, /* RGB+alpha packed, 8 bits per component, A:B:G:R */ + IMG_ARGB32, /* RGB+alpha packed, 8 bits per component, A:R:G:B */ + IMG_BGRA32, /* RGB+alpha packed, 8 bits per component, B:G:R:A */ + IMG_GRAY8, /* Grayscale 8-bit data */ + IMG_RGB_LAST, +} ImageFormat; + +/* Alias */ +#define IMG_NONE IMG_UNKNOWN + +/* Default YUV and RGB formats */ +#define IMG_YUV_DEFAULT IMG_YUV420P +#define IMG_RGB_DEFAULT IMG_RGB24 + +/* Is the given image format a YUV/RGB one? */ +#define IS_YUV_FORMAT(fmt) ((fmt) > IMG_YUV_BASE && (fmt) < IMG_YUV_LAST) +#define IS_RGB_FORMAT(fmt) ((fmt) > IMG_RGB_BASE && (fmt) < IMG_RGB_LAST) + +/* U/V plane size for YUV planar formats (Y plane size is always w*h) */ +#define UV_PLANE_SIZE(fmt,w,h) \ + ((fmt)==IMG_YUV420P ? ((w)/2)*((h)/2) : \ + (fmt)==IMG_YV12 ? ((w)/2)*((h)/2) : \ + (fmt)==IMG_YUV411P ? ((w)/4)* (h) : \ + (fmt)==IMG_YUV422P ? ((w)/2)* (h) : \ + (fmt)==IMG_YUV444P ? (w) * (h) : 0) + +/* Macro to initialize an array of planes from a buffer */ +#define YUV_INIT_PLANES(planes,buffer,fmt,w,h) \ + ((planes)[0] = (buffer), \ + (planes)[1] = (planes)[0] + (w)*(h), \ + (planes)[2] = (planes)[1] + UV_PLANE_SIZE((fmt),(w),(h))) + +#if 0 +/* Structure describing an image. FIXME: not currently used--this should + * eventually replace the (planes,format) pairs passed to ac_imgconvert. */ +typedef struct { + ImageFormat format; /* Format of image data */ + int width, height; /* Size of image */ + uint8_t *planes[4]; /* Data planes (use planes[0] for packed data) */ + int stride[4]; /* Length of one row in each plane, incl. padding */ +} Image; +#endif + +/*************************************************************************/ + +/* Initialization routine. Returns 1 on success, 0 on failure. */ +extern int ac_imgconvert_init(int accel); + +/* Conversion routine. Returns 1 on success, 0 on failure. */ +extern int ac_imgconvert(uint8_t **src, /* Array of source planes */ + ImageFormat srcfmt, /* Source image format */ + uint8_t **dest, /* Array of dest planes */ + ImageFormat destfmt, /* Destination image format */ + int width, /* Image width in pixels */ + int height /* Image height in pixels */ + ); + +/*************************************************************************/ + +#endif /* ACLIB_IMGCONVERT_H */ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/memcpy.c b/branches/V-1.5.3/veejay-server/aclib/memcpy.c new file mode 100644 index 00000000..00ca19af --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/memcpy.c @@ -0,0 +1,507 @@ +/* + * memcpy.c - optimized memcpy() routines for aclib + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "ac_internal.h" +#include + +/* Use memmove because memcpy isn't guaranteed to be ascending */ +static void *(*memcpy_ptr)(void *, const void *, size_t) = memmove; + +/*************************************************************************/ + +/* External interface */ + +void *ac_memcpy(void *dest, const void *src, size_t size) +{ + return (*memcpy_ptr)(dest, src, size); +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Note the check for ARCH_X86 here: this is to prevent compilation of this + * code on x86_64, since all x86_64 processors support SSE2, and because + * this code is not set up to use the 64-bit registers for addressing on + * x86_64. */ + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) + +/* MMX-optimized routine, intended for PMMX/PII processors. + * Nonstandard instructions used: + * (CPUID.MMX) MOVQ + */ + +static void *memcpy_mmx(void *dest, const void *src, size_t bytes) +{ + asm("\ +PENTIUM_LINE_SIZE = 32 # PMMX/PII cache line size \n\ +PENTIUM_CACHE_SIZE = 8192 # PMMX/PII total cache size \n\ +# Use only half because writes may touch the cache too (PII) \n\ +PENTIUM_CACHE_BLOCK = (PENTIUM_CACHE_SIZE/2 - PENTIUM_LINE_SIZE) \n\ + \n\ + push %%ebx # Save PIC register \n\ + push %%edi # Save destination for return value \n\ + cld # MOVS* should ascend \n\ + \n\ + mov $64, %%ebx # Constant \n\ + \n\ + cmp %%ebx, %%ecx \n\ + jb mmx.memcpy_last # Just use movs if <64 bytes \n\ + \n\ + # First align destination address to a multiple of 8 bytes \n\ + mov $8, %%eax # EAX <- (8-dest) & 7 \n\ + sub %%edi, %%eax \n\ + and $0b111, %%eax # ... which is the number of bytes to copy\n\ + lea 0f, %%edx # Use a computed jump--faster than a loop\n\ + sub %%eax, %%edx \n\ + jmp *%%edx # Execute 0-7 MOVSB's \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ +0: sub %%eax, %%ecx # Update count \n\ + \n\ + # Now copy data in blocks \n\ +0: mov %%ecx, %%edx # EDX <- ECX >> 6 (cache lines to copy) \n\ + shr $6, %%edx \n\ + jz mmx.memcpy_last # <64 bytes left? Skip to end \n\ + cmp $PENTIUM_CACHE_BLOCK/64, %%edx \n\ + jb 1f # Limit size of block \n\ + mov $PENTIUM_CACHE_BLOCK/64, %%edx \n\ +1: mov %%edx, %%eax # EAX <- EDX << 6 (bytes to copy) \n\ + shl $6, %%eax \n\ + sub %%eax, %%ecx # Update remaining count \n\ + add %%eax, %%esi # Point to end of region to be block-copied\n\ +2: test %%eax, -32(%%esi) # Touch each cache line in reverse order\n\ + test %%eax, -64(%%esi) \n\ + sub %%ebx, %%esi # Update pointer \n\ + sub %%ebx, %%eax # And loop \n\ + jnz 2b \n\ + # Note that ESI now points to the beginning of the block \n\ +3: movq (%%esi), %%mm0 # Do the actual copy, 64 bytes at a time\n\ + movq 8(%%esi), %%mm1 \n\ + movq 16(%%esi), %%mm2 \n\ + movq 24(%%esi), %%mm3 \n\ + movq 32(%%esi), %%mm4 \n\ + movq 40(%%esi), %%mm5 \n\ + movq 48(%%esi), %%mm6 \n\ + movq 56(%%esi), %%mm7 \n\ + movq %%mm0, (%%edi) \n\ + movq %%mm1, 8(%%edi) \n\ + movq %%mm2, 16(%%edi) \n\ + movq %%mm3, 24(%%edi) \n\ + movq %%mm4, 32(%%edi) \n\ + movq %%mm5, 40(%%edi) \n\ + movq %%mm6, 48(%%edi) \n\ + movq %%mm7, 56(%%edi) \n\ + add %%ebx, %%esi # Update pointers \n\ + add %%ebx, %%edi \n\ + dec %%edx # And loop \n\ + jnz 3b \n\ + jmp 0b \n\ + \n\ +mmx.memcpy_last: \n\ + # Copy last <64 bytes, using the computed jump trick \n\ + mov %%ecx, %%eax # EAX <- ECX>>2 \n\ + shr $2, %%eax \n\ + lea 0f, %%edx \n\ + sub %%eax, %%edx \n\ + jmp *%%edx # Execute 0-15 MOVSD's \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ +0: and $0b11, %%ecx # ECX <- ECX & 3 \n\ + lea 0f, %%edx \n\ + sub %%ecx, %%edx \n\ + jmp *%%edx # Execute 0-3 MOVSB's \n\ + movsb \n\ + movsb \n\ + movsb \n\ +0: \n\ + # All done! \n\ + emms # Clean up MMX state \n\ + pop %%edi # Restore destination (return value) \n\ + pop %%ebx # Restore PIC register \n\ + " : /* no outputs */ + : "D" (dest), "S" (src), "c" (bytes) + : "%eax", "%edx" + ); + return dest; +} + +#endif /* HAVE_ASM_MMX && ARCH_X86 */ + +/*************************************************************************/ + +#if defined(HAVE_ASM_SSE) && defined(ARCH_X86) + +/* SSE-optimized routine. Backported from AMD64 routine below. + * Nonstandard instructions used: + * (CPUID.CMOVE) CMOVA + * (CPUID.MMX) MOVQ + * (CPUID.SSE) MOVNTQ + */ + +static void *memcpy_sse(void *dest, const void *src, size_t bytes) +{ + asm("\ + push %%ebx # Save PIC register \n\ + push %%edi # Save destination for return value \n\ + cld # MOVS* should ascend \n\ + \n\ + cmp $64, %%ecx # Skip block copy for small blocks \n\ + jb sse.memcpy_last \n\ + \n\ + mov $128, %%ebx # Constant used later \n\ + \n\ + # First align destination address to a multiple of 8 bytes \n\ + mov $8, %%eax # EAX <- (8-dest) & 7 \n\ + sub %%edi, %%eax \n\ + and $0b111, %%eax # ... which is the number of bytes to copy\n\ + lea 0f, %%edx # Use a computed jump--faster than a loop\n\ + sub %%eax, %%edx \n\ + jmp *%%edx # Execute 0-7 MOVSB's \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ +0: sub %%eax, %%ecx # Update count \n\ + \n\ + cmp $0x10040, %%ecx # Is this a large block? (0x10040 is an \n\ + # arbitrary value where prefetching and \n\ + # write combining seem to start becoming\n\ + # faster) \n\ + jae sse.memcpy_bp # Yup, use prefetch copy \n\ + \n\ +sse.memcpy_small: # Small block copy routine--no prefetch \n" +#if 0 +" mov %%ecx, %%edx # EDX <- bytes to copy / 8 \n\ + shr $3, %%edx \n\ + mov %%edx, %%eax # Leave remainder in ECX for later \n\ + shl $3, %%eax \n\ + sub %%eax, %%ecx \n\ + .align 16 \n\ +0: movq (%%esi), %%mm0 # Copy 8 bytes of data \n\ + movq %%mm0, (%%edi) \n\ + add $8, %%esi # Update pointers \n\ + add $8, %%edi \n\ + dec %%edx # And loop \n\ + jg 0b \n\ + jmp sse.memcpy_last # Copy any remaining bytes \n\ + \n\ + nop # Align loops below \n" +#else +" # It appears that a simple rep movs is faster than cleverness \n\ + # with movq... \n\ + mov %%ecx, %%edx # EDX <- ECX & 3 \n\ + and $0b11, %%edx \n\ + shr $2, %%ecx # ECX <- ECX >> 2 \n\ + rep movsl # Copy away! \n\ + mov %%edx, %%ecx # Take care of last 0-3 bytes \n\ + rep movsb \n\ + jmp sse.memcpy_end # And exit \n\ + \n\ + .align 16 \n\ + nop \n\ + nop \n" +#endif +"sse.memcpy_bp: # Block prefetch copy routine \n\ +0: mov %%ecx, %%edx # EDX: temp counter \n\ + shr $6, %%edx # Divide by cache line size (64 bytes) \n\ + cmp %%ebx, %%edx # ... and cap at 128 (8192 bytes) \n\ + cmova %%ebx, %%edx \n\ + shl $3, %%edx # EDX <- cache lines to copy * 8 \n\ + mov %%edx, %%eax # EAX <- cache lines to preload * 8 \n\ + # (also used as memory offset) \n\ +1: test %%eax, -64(%%esi,%%eax,8) # Preload cache lines in pairs \n\ + test %%eax, -128(%%esi,%%eax,8) # (going backwards) \n\ + # (note that test %%eax,... seems to be faster than prefetchnta \n\ + # on x86) \n\ + sub $16, %%eax # And loop \n\ + jg 1b \n\ + \n\ + # Then copy--forward, which seems to be faster than reverse for \n\ + # certain alignments \n\ + xor %%eax, %%eax \n\ +2: movq (%%esi,%%eax,8), %%mm0 # Copy 8 bytes and loop \n\ + movntq %%mm0, (%%edi,%%eax,8) \n\ + inc %%eax \n\ + cmp %%edx, %%eax \n\ + jb 2b \n\ + \n\ + # Finally, update pointers and count, and loop \n\ + shl $3, %%edx # EDX <- bytes copied \n\ + add %%edx, %%esi \n\ + add %%edx, %%edi \n\ + sub %%edx, %%ecx \n\ + cmp $64, %%ecx # At least one cache line left? \n\ + jae 0b # Yup, loop \n\ + \n\ +sse.memcpy_last: \n\ + # Copy last <64 bytes, using the computed jump trick \n\ + mov %%ecx, %%eax # EAX <- ECX>>2 \n\ + shr $2, %%eax \n\ + lea 0f, %%edx \n\ + sub %%eax, %%edx \n\ + jmp *%%edx # Execute 0-15 MOVSD's \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ + movsd \n\ +0: and $0b11, %%ecx # ECX <- ECX & 3 \n\ + lea sse.memcpy_end, %%edx \n\ + sub %%ecx, %%edx \n\ + jmp *%%edx # Execute 0-3 MOVSB's \n\ + movsb \n\ + movsb \n\ + movsb \n\ + \n\ +sse.memcpy_end: \n\ + # All done! \n\ + emms # Clean up after MMX instructions \n\ + sfence # Flush the write buffer \n\ + pop %%edi # Restore destination (return value) \n\ + pop %%ebx # Restore PIC register \n\ + " : /* no outputs */ + : "D" (dest), "S" (src), "c" (bytes) + : "%eax", "%edx" + ); + return dest; +} + +#endif /* HAVE_ASM_SSE && ARCH_X86 */ + +/*************************************************************************/ + +#if defined(HAVE_ASM_SSE2) && defined(ARCH_X86_64) + +/* AMD64-optimized routine, using SSE2. Derived from AMD64 optimization + * guide section 5.13: Appropriate Memory Copying Routines. + * Nonstandard instructions used: + * (CPUID.CMOVE) CMOVA + * (CPUID.SSE2) MOVDQA, MOVDQU, MOVNTDQ + * + * Note that this routine will also run more or less as-is (modulo register + * names and label(%%rip) references) on x86 CPUs, but tests have shown the + * SSE1 version above to be faster. + */ + +/* The block copying code--macroized because we use two versions of it + * depending on whether the source is 16-byte-aligned or not. Pass either + * movdqa or movdqu (unquoted) for the parameter. */ +#define AMD64_BLOCK_MEMCPY(movdq) \ +" # First prefetch (note that if we end on an odd number of cache \n\ + # lines, we skip prefetching the last one--faster that way than \n\ + # prefetching line by line or treating it as a special case) \n\ +0: mov %%ecx, %%edx # EDX: temp counter (always <32 bits) \n\ + shr $6, %%edx # Divide by cache line size (64 bytes) \n\ + cmp %%ebx, %%edx # ... and cap at 128 (8192 bytes) \n\ + cmova %%ebx, %%edx \n\ + shl $3, %%edx # EDX <- cache lines to copy * 8 \n\ + mov %%edx, %%eax # EAX <- cache lines to preload * 8 \n\ + # (also used as memory offset) \n\ +1: prefetchnta -64(%%rsi,%%rax,8) # Preload cache lines in pairs \n\ + prefetchnta -128(%%rsi,%%rax,8) # (going backwards) \n\ + sub $16, %%eax # And loop \n\ + jg 1b \n\ + \n\ + # Then copy--forward, which seems to be faster than reverse for \n\ + # certain alignments \n\ + xor %%eax, %%eax \n\ +2: " #movdq " (%%rsi,%%rax,8), %%xmm0 # Copy 16 bytes and loop \n\ + movntdq %%xmm0, (%%rdi,%%rax,8) \n\ + add $2, %%eax \n\ + cmp %%edx, %%eax \n\ + jb 2b \n\ + \n\ + # Finally, update pointers and count, and loop \n\ + shl $3, %%edx # EDX <- bytes copied \n\ + add %%rdx, %%rsi \n\ + add %%rdx, %%rdi \n\ + sub %%rdx, %%rcx \n\ + cmp $64, %%rcx # At least one cache line left? \n\ + jae 0b # Yup, loop \n" + +static void *memcpy_amd64(void *dest, const void *src, size_t bytes) +{ + asm("\ + push %%rdi # Save destination for return value \n\ + cld # MOVS* should ascend \n\ + \n\ + cmp $64, %%rcx # Skip block copy for small blocks \n\ + jb amd64.memcpy_last \n\ + \n\ + mov $128, %%ebx # Constant used later \n\ + \n\ + # First align destination address to a multiple of 16 bytes \n\ + mov $8, %%eax # EAX <- (8-dest) & 7 \n\ + sub %%edi, %%eax # (we don't care about the top 32 bits) \n\ + and $0b111, %%eax # ... which is the number of bytes to copy\n\ + lea 0f(%%rip), %%rdx # Use a computed jump--faster than a loop\n\ + sub %%rax, %%rdx \n\ + jmp *%%rdx # Execute 0-7 MOVSB's \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ +0: sub %%rax, %%rcx # Update count \n\ + test $0b1000, %%edi # Is destination not 16-byte aligned? \n\ + je 1f \n\ + movsq # Then move 8 bytes to align it \n\ + sub $8, %%rcx \n\ + \n\ +1: cmp $0x38000, %%rcx # Is this a large block? (0x38000 is an \n\ + # arbitrary value where prefetching and \n\ + # write combining seem to start becoming\n\ + # faster) \n\ + jb amd64.memcpy_small # Nope, use small copy (no prefetch/WC) \n\ + test $0b1111, %%esi # Is source also 16-byte aligned? \n\ + # (use ESI to save a REX prefix byte) \n\ + jnz amd64.memcpy_normal_bp # Nope, use slow copy \n\ + jmp amd64.memcpy_fast_bp # Yup, use fast copy \n\ + \n\ +amd64.memcpy_small: # Small block copy routine--no prefetch \n\ + mov %%ecx, %%edx # EDX <- bytes to copy / 16 \n\ + shr $4, %%edx # (count known to fit in 32 bits) \n\ + mov %%edx, %%eax # Leave remainder in ECX for later \n\ + shl $4, %%eax \n\ + sub %%eax, %%ecx \n\ + .align 16 \n\ +0: movdqu (%%rsi), %%xmm0 # Copy 16 bytes of data \n\ + movdqa %%xmm0, (%%rdi) \n\ + add $16, %%rsi # Update pointers \n\ + add $16, %%rdi \n\ + dec %%edx # And loop \n\ + jnz 0b \n\ + jmp amd64.memcpy_last # Copy any remaining bytes \n\ + \n\ + .align 16 \n\ + nop \n\ + nop \n\ +amd64.memcpy_fast_bp: # Fast block prefetch loop \n" +AMD64_BLOCK_MEMCPY(movdqa) +" jmp amd64.memcpy_last # Copy any remaining bytes \n\ + \n\ + .align 16 \n\ + nop \n\ + nop \n\ +amd64.memcpy_normal_bp: # Normal (unaligned) block prefetch loop\n" +AMD64_BLOCK_MEMCPY(movdqu) +" \n\ +amd64.memcpy_last: \n\ + # Copy last <64 bytes, using the computed jump trick \n\ + mov %%ecx, %%eax # EAX <- ECX>>3 \n\ + shr $3, %%eax \n\ + lea 0f(%%rip), %%rdx \n\ + add %%eax, %%eax # Watch out, MOVSQ is 2 bytes! \n\ + sub %%rax, %%rdx \n\ + jmp *%%rdx # Execute 0-7 MOVSQ's \n\ + movsq \n\ + movsq \n\ + movsq \n\ + movsq \n\ + movsq \n\ + movsq \n\ + movsq \n\ +0: and $0b111, %%ecx # ECX <- ECX & 7 \n\ + lea 0f(%%rip), %%rdx \n\ + sub %%rcx, %%rdx \n\ + jmp *%%rdx # Execute 0-7 MOVSB's \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ + movsb \n\ +0: \n\ + # All done! \n\ + emms # Clean up after MMX instructions \n\ + sfence # Flush the write buffer \n\ + pop %%rdi # Restore destination (return value) \n\ + " : /* no outputs */ + : "D" (dest), "S" (src), "c" (bytes) + : "%rax", "%rbx", "%rdx" + ); + return dest; +} + +#endif /* HAVE_ASM_SSE2 && ARCH_X86_64 */ + +/*************************************************************************/ + +/* Initialization routine. */ + +int ac_memcpy_init(int accel) +{ + memcpy_ptr = memmove; + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) + if (HAS_ACCEL(accel, AC_MMX)) + memcpy_ptr = memcpy_mmx; +#endif + +#if defined(HAVE_ASM_SSE) && defined(ARCH_X86) + if (HAS_ACCEL(accel, AC_CMOVE|AC_SSE)) + memcpy_ptr = memcpy_sse; +#endif + +#if defined(HAVE_ASM_SSE2) && defined(ARCH_X86_64) + if (HAS_ACCEL(accel, AC_CMOVE|AC_SSE2)) + memcpy_ptr = memcpy_amd64; +#endif + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/rescale.c b/branches/V-1.5.3/veejay-server/aclib/rescale.c new file mode 100644 index 00000000..5a619735 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/rescale.c @@ -0,0 +1,280 @@ +/* + * rescale.c -- take the weighted average of two sets of byte data + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "ac.h" +#include "ac_internal.h" + +static void rescale(const uint8_t *, const uint8_t *, uint8_t *, int, + uint32_t, uint32_t); +static void (*rescale_ptr)(const uint8_t *, const uint8_t *, uint8_t *, int, + uint32_t, uint32_t) = rescale; + +/*************************************************************************/ + +/* External interface */ + +void ac_rescale(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes, uint32_t weight1, uint32_t weight2) +{ + if (weight1 >= 0x10000) + ac_memcpy(dest, src1, bytes); + else if (weight2 >= 0x10000) + ac_memcpy(dest, src2, bytes); + else + (*rescale_ptr)(src1, src2, dest, bytes, weight1, weight2); +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Vanilla C version */ + +static void rescale(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes, + uint32_t weight1, uint32_t weight2) +{ + int i; + for (i = 0; i < bytes; i++) + dest[i] = (src1[i]*weight1 + src2[i]*weight2 + 32768) >> 16; +} + +/*************************************************************************/ + +/* MMX version */ + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) /* i.e. not x86_64 */ + +static void rescale_mmx(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes, + uint32_t weight1, uint32_t weight2) +{ + if (bytes >= 8) { + /* First store weights in MM4/MM5 to relieve register pressure; + * save time by making 2 copies ahead of time in the general + * registers. Note that we divide by 2 for MMX due to the lack + * of an unsigned SIMD multiply instruction (PMULHUW). */ + int half1 = weight1 / 2; + int half2 = weight2 / 2; + half2 += weight1 & weight2 & 1; // pick up the lost bit here + asm("movd %%eax, %%mm4; movd %%edx, %%mm5" + : : "a" (half1<<16|half1), "d" (half2<<16|half2)); + asm("\ + movq %%mm4, %%mm6 # MM6: 00 00 W1 W1 \n\ + psllq $32, %%mm4 # MM4: W1 W1 00 00 \n\ + por %%mm6, %%mm4 # MM4: W1 W1 W1 W1 \n\ + movq %%mm5, %%mm7 # MM7: 00 00 W2 W2 \n\ + psllq $32, %%mm5 # MM5: W2 W2 00 00 \n\ + por %%mm7, %%mm5 # MM5: W2 W2 W2 W2 \n\ + pxor %%mm7, %%mm7 # MM7: 00 00 00 00 \n\ + pxor %%mm6, %%mm6 # Put 0x0020*4 in MM6 (rounding)\n\ + pcmpeqw %%mm3, %%mm3 \n\ + psubw %%mm3, %%mm6 \n\ + psllw $5, %%mm6 \n\ + 0: \n\ + movq -8(%%esi,%%ecx), %%mm0 \n\ + movq %%mm0, %%mm1 \n\ + punpcklbw %%mm7, %%mm0 \n\ + psllw $7, %%mm0 # 9.7 fixed point \n\ + pmulhw %%mm4, %%mm0 # Multiply to get 10.6 fixed \n\ + punpckhbw %%mm7, %%mm1 \n\ + psllw $7, %%mm1 \n\ + pmulhw %%mm4, %%mm1 \n\ + movq -8(%%edx,%%ecx), %%mm2 \n\ + movq %%mm2, %%mm3 \n\ + punpcklbw %%mm7, %%mm2 \n\ + psllw $7, %%mm2 \n\ + pmulhw %%mm5, %%mm2 \n\ + punpckhbw %%mm7, %%mm3 \n\ + psllw $7, %%mm3 \n\ + pmulhw %%mm5, %%mm3 \n\ + paddw %%mm2, %%mm0 \n\ + paddw %%mm6, %%mm0 \n\ + psrlw $6, %%mm0 \n\ + paddw %%mm3, %%mm1 \n\ + paddw %%mm6, %%mm1 \n\ + psrlw $6, %%mm1 \n\ + packuswb %%mm1, %%mm0 \n\ + movq %%mm0, -8(%%edi,%%ecx) \n\ + subl $8, %%ecx \n\ + jnz 0b \n\ + emms" + : /* no outputs */ + : "S" (src1), "d" (src2), "D" (dest), "c" (bytes & ~7)); + } + if (UNLIKELY(bytes & 7)) { + rescale(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7), + bytes & 7, weight1, weight2); + } +} + +#endif /* HAVE_ASM_MMX && ARCH_X86 */ + +/*************************************************************************/ + +/* MMXEXT version (also for SSE) */ + +#if (defined(HAVE_ASM_MMXEXT) || defined(HAVE_ASM_SSE)) && defined(ARCH_X86) + +static void rescale_mmxext(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes, + uint32_t weight1, uint32_t weight2) +{ + if (bytes >= 8) { + asm("movd %%eax, %%mm4; movd %%edx, %%mm5" + : : "a" (weight1), "d" (weight2)); + asm("\ + pshufw $0, %%mm4, %%mm4 # MM4: W1 W1 W1 W1 \n\ + pshufw $0, %%mm5, %%mm5 # MM5: W2 W2 W2 W2 \n\ + pxor %%mm6, %%mm6 # Put 0x0080*4 in MM6 (rounding)\n\ + pcmpeqw %%mm7, %%mm7 \n\ + psubw %%mm7, %%mm6 \n\ + psllw $7, %%mm6 \n\ + 0: \n\ + movq -8(%%esi,%%ecx), %%mm7 \n\ + pxor %%mm0, %%mm0 # Load data into high bytes \n\ + punpcklbw %%mm7, %%mm0 # (gives 8.8 fixed point) \n\ + pmulhuw %%mm4, %%mm0 # Result: 0000..FF00 \n\ + pxor %%mm1, %%mm1 \n\ + punpckhbw %%mm7, %%mm1 \n\ + pmulhuw %%mm4, %%mm1 \n\ + movq -8(%%edx,%%ecx), %%mm7 \n\ + pxor %%mm2, %%mm2 \n\ + punpcklbw %%mm7, %%mm2 \n\ + pmulhuw %%mm5, %%mm2 \n\ + pxor %%mm3, %%mm3 \n\ + punpckhbw %%mm7, %%mm3 \n\ + pmulhuw %%mm5, %%mm3 \n\ + paddw %%mm2, %%mm0 \n\ + paddw %%mm6, %%mm0 \n\ + psrlw $8, %%mm0 # Shift back down to 00..FF \n\ + paddw %%mm3, %%mm1 \n\ + paddw %%mm6, %%mm1 \n\ + psrlw $8, %%mm1 \n\ + packuswb %%mm1, %%mm0 \n\ + movq %%mm0, -8(%%edi,%%ecx) \n\ + subl $8, %%ecx \n\ + jnz 0b \n\ + emms" + : /* no outputs */ + : "S" (src1), "d" (src2), "D" (dest), "c" (bytes & ~7)); + } + if (UNLIKELY(bytes & 7)) { + rescale(src1+(bytes & ~7), src2+(bytes & ~7), dest+(bytes & ~7), + bytes & 7, weight1, weight2); + } +} + +#endif /* (HAVE_ASM_MMXEXT || HAVE_ASM_SSE) && ARCH_X86 */ + +/*************************************************************************/ + +/* SSE2 version */ + +#if defined(HAVE_ASM_SSE2) + +#ifdef ARCH_X86_64 +# define ECX "%%rcx" +# define EDX "%%rdx" +# define ESI "%%rsi" +# define EDI "%%rdi" +#else +# define ECX "%%ecx" +# define EDX "%%edx" +# define ESI "%%esi" +# define EDI "%%edi" +#endif + +static void rescale_sse2(const uint8_t *src1, const uint8_t *src2, + uint8_t *dest, int bytes, + uint32_t weight1, uint32_t weight2) +{ + if (bytes >= 16) { + asm("movd %%eax, %%xmm4; movd %%edx, %%xmm5" + : : "a" (weight1<<16|weight1), "d" (weight2<<16|weight2)); + asm("\ + pshufd $0, %%xmm4, %%xmm4 # XMM4: W1 W1 W1 W1 W1 W1 W1 W1 \n\ + pshufd $0, %%xmm5, %%xmm5 # XMM5: W2 W2 W2 W2 W2 W2 W2 W2 \n\ + pxor %%xmm6, %%xmm6 # Put 0x0080*4 in XMM6 (rounding)\n\ + pcmpeqw %%xmm7, %%xmm7 \n\ + psubw %%xmm7, %%xmm6 \n\ + psllw $7, %%xmm6 \n\ + 0: \n\ + movdqu -16("ESI","ECX"), %%xmm7 \n\ + pxor %%xmm0, %%xmm0 \n\ + punpcklbw %%xmm7, %%xmm0 \n\ + pmulhuw %%xmm4, %%xmm0 \n\ + pxor %%xmm1, %%xmm1 \n\ + punpckhbw %%xmm7, %%xmm1 \n\ + pmulhuw %%xmm4, %%xmm1 \n\ + movdqu -16("EDX","ECX"), %%xmm7 \n\ + pxor %%xmm2, %%xmm2 \n\ + punpcklbw %%xmm7, %%xmm2 \n\ + pmulhuw %%xmm5, %%xmm2 \n\ + pxor %%xmm3, %%xmm3 \n\ + punpckhbw %%xmm7, %%xmm3 \n\ + pmulhuw %%xmm5, %%xmm3 \n\ + paddw %%xmm2, %%xmm0 \n\ + paddw %%xmm6, %%xmm0 \n\ + psrlw $8, %%xmm0 \n\ + paddw %%xmm3, %%xmm1 \n\ + paddw %%xmm6, %%xmm1 \n\ + psrlw $8, %%xmm1 \n\ + packuswb %%xmm1, %%xmm0 \n\ + movdqu %%xmm0, -16("EDI","ECX") \n\ + subl $16, %%ecx \n\ + jnz 0b \n\ + emms" + : /* no outputs */ + : "S" (src1), "d" (src2), "D" (dest), "c" (bytes & ~15)); + } + if (UNLIKELY(bytes & 15)) { + rescale(src1+(bytes & ~15), src2+(bytes & ~15), dest+(bytes & ~15), + bytes & 15, weight1, weight2); + } +} + +#endif /* HAVE_ASM_SSE2 */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Initialization routine. */ + +int ac_rescale_init(int accel) +{ + rescale_ptr = rescale; + +#if defined(HAVE_ASM_MMX) && defined(ARCH_X86) + if (HAS_ACCEL(accel, AC_MMX)) + rescale_ptr = rescale_mmx; +#endif +#if (defined(HAVE_ASM_MMXEXT) || defined(HAVE_ASM_SSE)) && defined(ARCH_X86) + if (HAS_ACCEL(accel, AC_MMXEXT) || HAS_ACCEL(accel, AC_SSE)) + rescale_ptr = rescale_mmxext; +#endif +#if defined(HAVE_ASM_SSE2) + if (HAS_ACCEL(accel, AC_SSE2)) + rescale_ptr = rescale_sse2; +#endif + + return 1; +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ diff --git a/branches/V-1.5.3/veejay-server/aclib/rgb-yuv-conv.pl b/branches/V-1.5.3/veejay-server/aclib/rgb-yuv-conv.pl new file mode 100755 index 00000000..a2b6257c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/aclib/rgb-yuv-conv.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w +# Calculate conversion matrices for RGB<->YUV given Kb and Kr + +die "Usage: $0 Kb Kr [scale]\n" if @ARGV < 2; +$scale = $ARGV[2] || 1; +$Kb = $ARGV[0]; +$Kr = $ARGV[1]; +$Kg = 1 - $Kr - $Kb; +$a11 = $Kr; +$a12 = $Kg; +$a13 = $Kb; +$a21 = -$Kr/(1-$Kb)/2; +$a22 = -$Kg/(1-$Kb)/2; +$a23 = 1/2; +$a31 = 1/2; +$a32 = -$Kg/(1-$Kr)/2; +$a33 = -$Kb/(1-$Kr)/2; +print "Y [R] = ".($a11*$scale)."\n"; +print "Y [G] = ".($a12*$scale)."\n"; +print "Y [B] = ".($a13*$scale)."\n"; +print "Cb[R] = ".($a21*$scale)."\n"; +print "Cb[G] = ".($a22*$scale)."\n"; +print "Cb[B] = ".($a23*$scale)."\n"; +print "Cr[R] = ".($a31*$scale)."\n"; +print "Cr[G] = ".($a32*$scale)."\n"; +print "Cr[B] = ".($a33*$scale)."\n"; +$det = $a11*$a22*$a33 - $a11*$a23*$a32 + + $a12*$a23*$a31 - $a12*$a21*$a33 + + $a13*$a21*$a32 - $a13*$a22*$a31; +$b11 = (1/$det)*($a22*$a33-$a23*$a32); +$b12 = (1/$det)*($a13*$a32-$a12*$a33); +$b13 = (1/$det)*($a12*$a23-$a13*$a22); +$b21 = (1/$det)*($a23*$a31-$a21*$a33); +$b22 = (1/$det)*($a11*$a33-$a13*$a31); +$b23 = (1/$det)*($a13*$a21-$a11*$a23); +$b31 = (1/$det)*($a21*$a32-$a22*$a31); +$b32 = (1/$det)*($a12*$a31-$a11*$a32); +$b33 = (1/$det)*($a11*$a22-$a12*$a21); +map {$_ = 0 if abs($_) < 1e-10} ($b11,$b12,$b13,$b21,$b22,$b23,$b31,$b32,$b33); +print "R[Y ] = ".($b11*$scale)."\n"; +print "R[Cb] = ".($b12*$scale)."\n"; +print "R[Cr] = ".($b13*$scale)."\n"; +print "G[Y ] = ".($b21*$scale)."\n"; +print "G[Cb] = ".($b22*$scale)."\n"; +print "G[Cr] = ".($b23*$scale)."\n"; +print "B[Y ] = ".($b31*$scale)."\n"; +print "B[Cb] = ".($b32*$scale)."\n"; +print "B[Cr] = ".($b33*$scale)."\n"; diff --git a/branches/V-1.5.3/veejay-server/autogen.sh b/branches/V-1.5.3/veejay-server/autogen.sh new file mode 100755 index 00000000..ba7e3840 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/autogen.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + + +autoreconf -v -f -i diff --git a/branches/V-1.5.3/veejay-server/bio2jack/AUTHORS b/branches/V-1.5.3/veejay-server/bio2jack/AUTHORS new file mode 100644 index 00000000..87c570cd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/AUTHORS @@ -0,0 +1,4 @@ +bio2jack - a library for porting blocked io(OSS/ALSA) apps to jack +--------------------------------------------------------- + +Chris Morgan diff --git a/branches/V-1.5.3/veejay-server/bio2jack/COPYING b/branches/V-1.5.3/veejay-server/bio2jack/COPYING new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/COPYING @@ -0,0 +1,339 @@ + 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 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 + + 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/branches/V-1.5.3/veejay-server/bio2jack/INSTALL b/branches/V-1.5.3/veejay-server/bio2jack/INSTALL new file mode 100644 index 00000000..6906d0cb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/INSTALL @@ -0,0 +1,6 @@ +Installing bio2jack +---------------------- + +This library is intended only for static linking as it is small and there +is no need to require yet another library for a user to install. So +please, statically link to this library. diff --git a/branches/V-1.5.3/veejay-server/bio2jack/Makefile.am b/branches/V-1.5.3/veejay-server/bio2jack/Makefile.am new file mode 100644 index 00000000..8c4a1b50 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/Makefile.am @@ -0,0 +1,4 @@ +noinst_LTLIBRARIES = libbio2jack4vj.la +INCLUDES=-I$(top_srcdir)/libvjmem +LIBS = @LIBS@ @PTHREAD_LIBS@ @JACK_LIBS@ +libbio2jack4vj_la_SOURCES = bio2jack.c bio2jack.h diff --git a/branches/V-1.5.3/veejay-server/bio2jack/NEWS b/branches/V-1.5.3/veejay-server/bio2jack/NEWS new file mode 100644 index 00000000..8c269fef --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/NEWS @@ -0,0 +1,10 @@ +bio2jack - NEWS +-------- +9/12/2004 - Check out ChangeLog for news ;-) +10/26/2003 - Updated to the new jack api, fixed a bunch of bugs + Removed all blocking functions, blocking is BAD as it could potentially + hold off the callback function. +1/13/2003 - Continuing to refine the api by working on the xine plugin. + Fixed a few bugs in the code. Uploaded newer packages to + sourceforge. +12/31/2002 - Sourceforge project is setup. diff --git a/branches/V-1.5.3/veejay-server/bio2jack/README b/branches/V-1.5.3/veejay-server/bio2jack/README new file mode 100644 index 00000000..ac5cf24e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/README @@ -0,0 +1,30 @@ +bio2jack +----------- + +To Build: +---------- +run ./autogen.sh +run ./configure +run make +enjoy ;-) + + +Bio(blocked i/o) 2 jack. + +A library for enabling easy porting of blocked io(OSS/ALSA) applications to +the jack sound server(http://jackit.sourceforge.net). This library allows the +person porting the code to simply replace the calls into OSS/ALSA with +calls into interface functions of this library. The library buffers a +small amount of audio data and takes care of the rest of the jack +implementation including the linked list of audio data buffers and the jack +callback. + +Interface functions: +TODO: once these become stable copy and paste from the header file + + +Currently these drivers use the bio2jack library: +--------------------------------------------------- +xmms-jack: Written in conjunction with this library +xine: + diff --git a/branches/V-1.5.3/veejay-server/bio2jack/bio2jack.c b/branches/V-1.5.3/veejay-server/bio2jack/bio2jack.c new file mode 100644 index 00000000..409b63dd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/bio2jack.c @@ -0,0 +1,2692 @@ +/* + * Copyright 2003-2006 Chris Morgan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* NOTE: All functions that take a jack_driver_t* do NOT lock the device, in order to get a */ +/* jack_driver_t* you must call getDriver() which will pthread_mutex_lock() */ + +#include +#ifdef HAVE_JACK +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SAMPLERATE +#include +#endif +#include "bio2jack.h" + +/* enable/disable TRACING through the JACK_Callback() function */ +/* this can sometimes be too much information */ +#define TRACE_CALLBACK 0 + +/* set to 1 for verbose output */ +#define VERBOSE_OUTPUT 0 + +/* set to 1 to enable debug messages */ +#define DEBUG_OUTPUT 0 + +/* set to 1 to enable tracing */ +#define TRACE_ENABLE 0 + +/* set to 1 to enable the function timers */ +#define TIMER_ENABLE 0 + +/* set to 1 to enable tracing of getDriver() and releaseDriver() */ +#define TRACE_getReleaseDevice 0 + +#define ENABLE_WARNINGS 0 + +#define DEFAULT_RB_SIZE 4096 + +#define OUTFILE stderr + +#if TIMER_ENABLE +/* This seemingly construct makes timing arbitrary functions really easy + all you have to do is place a 'TIMER("start\n")' at the beginning and + a 'TIMER("stop\n")' at the end of any function and this does the rest + (naturally you can place any printf-compliant text you like in the argument + along with the associated values). */ +static struct timeval timer_now; +#define TIMER(format,args...) gettimeofday(&timer_now,0); \ + veejay_msg(4, "%ld.%06ld: %s::%s(%d) "format, timer_now.tv_sec, timer_now.tv_usec, __FILE__, __FUNCTION__, __LINE__, ##args) +#else +#define TIMER(...) +#endif + +#if TRACE_ENABLE +#define TRACE(format,args...) veejay_msg(4, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args); \ + fflush(OUTFILE); +#else +#define TRACE(...) +#endif + +#if DEBUG_OUTPUT +#define DEBUG(format,args...) veejay_msg(4, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args); \ + fflush(OUTFILE); +#else +#define DEBUG(...) +#endif + +#if TRACE_CALLBACK +#define CALLBACK_TRACE(format,args...) veejay_msg(4, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args); \ + fflush(OUTFILE); +#else +#define CALLBACK_TRACE(...) +#endif + +#if ENABLE_WARNINGS +#define WARN(format,args...) veejay_msg(1, "WARN: %s::%s(%d) "format, __FILE__,__FUNCTION__,__LINE__,##args); \ + fflush(OUTFILE); +#else +#define WARN(...) +#endif + +#define ERR(format,args...) veejay_msg(0, "ERR: %s::%s(%d) "format, __FILE__,__FUNCTION__,__LINE__,##args); \ + fflush(OUTFILE); + +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) < (b)) ? (b) : (a)) + +#define MAX_OUTPUT_PORTS 10 +#define MAX_INPUT_PORTS 10 + +typedef struct jack_driver_s +{ + bool allocated; /* whether or not this device has been allocated */ + + int deviceID; /* id of this device */ + int clientCtr; /* to prevent overlapping client ids */ + long jack_sample_rate; /* jack samples(frames) per second */ + + long client_sample_rate; /* client samples(frames) per second */ + double output_sample_rate_ratio; /* ratio between jack's output rate & ours */ + double input_sample_rate_ratio; /* ratio between our input rate & jack's */ + + unsigned long num_input_channels; /* number of input channels(1 is mono, 2 stereo etc..) */ + unsigned long num_output_channels; /* number of output channels(1 is mono, 2 stereo etc..) */ + + unsigned long bits_per_channel; /* number of bits per channel (only 8 & 16 are currently supported) */ + + unsigned long bytes_per_output_frame; /* (num_output_channels * bits_per_channel) / 8 */ + unsigned long bytes_per_input_frame; /* (num_input_channels * bits_per_channel) / 8 */ + + unsigned long bytes_per_jack_output_frame; /* (num_output_channels * bits_per_channel) / 8 */ + unsigned long bytes_per_jack_input_frame; /* (num_input_channels * bits_per_channel) / 8 */ + + unsigned long latencyMS; /* latency in ms between writing and actual audio output of the written data */ + + long clientBytesInJack; /* number of INPUT bytes(from the client of bio2jack) we wrote to jack(not necessary the number of bytes we wrote to jack) */ + long jack_buffer_size; /* size of the buffer jack will pass in to the process callback */ + + unsigned long callback_buffer1_size; /* number of bytes in the buffer allocated for processing data in JACK_Callback */ + char *callback_buffer1; + unsigned long callback_buffer2_size; /* number of bytes in the buffer allocated for processing data in JACK_Callback */ + char *callback_buffer2; + + unsigned long rw_buffer1_size; /* number of bytes in the buffer allocated for processing data in JACK_(Read|Write) */ + char *rw_buffer1; + + struct timeval previousTime; /* time of last JACK_Callback() write to jack, allows for MS accurate bytes played */ + + unsigned long num_ticks; + unsigned long chunk_size; + unsigned long written_client_bytes; /* input bytes we wrote to jack, not necessarily actual bytes we wrote to jack due to channel and other conversion */ + unsigned long played_client_bytes; /* input bytes that jack has played */ + + unsigned long client_bytes; /* total bytes written by the client of bio2jack via JACK_Write() */ + + jack_port_t *output_port[MAX_OUTPUT_PORTS]; /* output ports */ + jack_port_t *input_port[MAX_OUTPUT_PORTS]; /* input ports */ + + jack_client_t *client; /* pointer to jack client */ + + char **jack_port_name; /* user given strings for the port names, can be NULL */ + unsigned int jack_port_name_count; /* the number of port names given */ + + unsigned long jack_output_port_flags; /* flags to be passed to jack when opening the output ports */ + unsigned long jack_input_port_flags; /* flags to be passed to jack when opening the output ports */ + + jack_ringbuffer_t *pPlayPtr; /* the playback ringbuffer */ + jack_ringbuffer_t *pRecPtr; /* the recording ringbuffer */ +/* + SRC_STATE *output_src; + SRC_STATE *input_src; +*/ + + enum status_enum state; /* one of PLAYING, PAUSED, STOPPED, CLOSED, RESET etc */ + + unsigned int volume[MAX_OUTPUT_PORTS]; /* percentage of sample value to preserve, 100 would be no attenuation */ + enum JACK_VOLUME_TYPE volumeEffectType; /* linear or dbAttenuation, if dbAttenuation volume is the number of dBs of + attenuation to apply, 0 volume being no attenuation, full volume */ + + long position_byte_offset; /* an offset that we will apply to returned position queries to achieve */ + /* the position that the user of the driver desires set */ + + bool in_use; /* true if this device is currently in use */ + + pthread_mutex_t mutex; /* mutex to lock this specific device */ + + /* variables used for trying to restart the connection to jack */ + bool jackd_died; /* true if jackd has died and we should try to restart it */ + struct timeval last_reconnect_attempt; +} jack_driver_t; + + +static char *client_name; /* the name bio2jack will use when creating a new + jack client. client_name_%deviceID% will be used */ + + +static bool do_sample_rate_conversion; /* whether the client has requested sample rate conversion, + default to on for improved compatibility */ + +/* + Which SRC converter function we should use when doing sample rate conversion. + Default to the fastest of the 'good quality' set. + */ +#ifdef HAVE_SAMPLE_RATE +static int preferred_src_converter = SRC_SINC_FASTEST; +#endif +static bool init_done = 0; /* just to prevent clients from calling JACK_Init twice, that would be very bad */ + +static enum JACK_PORT_CONNECTION_MODE port_connection_mode = CONNECT_ALL; + +/* enable/disable code that allows us to close a device without actually closing the jack device */ +/* this works around the issue where jack doesn't always close devices by the time the close function call returns */ +#define JACK_CLOSE_HACK 1 + +typedef jack_default_audio_sample_t sample_t; +typedef jack_nframes_t nframes_t; + +/* allocate devices for output */ +/* if you increase this past 10, you might want to update 'out_client_name = ... ' in JACK_OpenDevice */ +#define MAX_OUTDEVICES 10 +static jack_driver_t outDev[MAX_OUTDEVICES]; + +static pthread_mutex_t device_mutex = PTHREAD_MUTEX_INITIALIZER; /* this is to lock the entire outDev array + to make managing it in a threaded + environment sane */ + +#if JACK_CLOSE_HACK +static void JACK_CloseDevice(jack_driver_t * drv, bool close_client); +#else +static void JACK_CloseDevice(jack_driver_t * drv); +#endif + + +/* Prototypes */ +static int JACK_OpenDevice(jack_driver_t * drv); +static unsigned long JACK_GetBytesFreeSpaceFromDriver(jack_driver_t * drv); +static void JACK_ResetFromDriver(jack_driver_t * drv); +static long JACK_GetPositionFromDriver(jack_driver_t * drv, + enum pos_enum position, int type); +static void JACK_CleanupDriver(jack_driver_t * drv); + + +/* Return the difference between two timeval structures in terms of milliseconds */ +long +TimeValDifference(struct timeval *start, struct timeval *end) +{ + double long ms; /* milliseconds value */ + + ms = end->tv_sec - start->tv_sec; /* compute seconds difference */ + ms *= (double) 1000; /* convert to milliseconds */ + + ms += (double) (end->tv_usec - start->tv_usec) / (double) 1000; /* add on microseconds difference */ + + return (long) ms; +} + +/* get a device and lock the devices mutex */ +/* */ +/* also attempt to reconnect to jack since this function is called from */ +/* most other bio2jack functions it provides a good point to attempt reconnection */ +/* */ +/* Ok, I know this looks complicated and it kind of is. The point is that when you're + trying to trace mutexes it's more important to know *who* called us than just that + we were called. This uses from pre-processor trickery so that the fprintf is actually + placed in the function making the getDriver call. Thus, the __FUNCTION__ and __LINE__ + macros will actually reference our caller, rather than getDriver. The reason the + fprintf call is passes as a parameter is because this macro has to still return a + jack_driver_t* and we want to log both before *and* after the getDriver call for + easier detection of blocked calls. + */ +#if TRACE_getReleaseDevice +#define getDriver(x) _getDriver(x,veejay_msg(4, "%s::%s(%d) getting driver %d\n", __FILE__, __FUNCTION__, __LINE__,x)); TRACE("got driver %d\n",x); +jack_driver_t * +_getDriver(int deviceID, int ignored) +{ + fflush(OUTFILE); +#else +jack_driver_t * +getDriver(int deviceID) +{ +#endif + jack_driver_t *drv = &outDev[deviceID]; + + if(pthread_mutex_lock(&drv->mutex) != 0) + ERR("lock returned an error\n"); + + /* should we try to restart the jack server? */ + if(drv->jackd_died && drv->client == 0) + { + struct timeval now; + gettimeofday(&now, 0); + + /* wait 250ms before trying again */ + if(TimeValDifference(&drv->last_reconnect_attempt, &now) >= 250) + { + JACK_OpenDevice(drv); + drv->last_reconnect_attempt = now; + } + } + + return drv; +} + +#if TRACE_getReleaseDevice +#define tryGetDriver(x) _tryGetDriver(x,veejay_msg(4, "%s::%s(%d) trying to get driver %d\n", __FILE__, __FUNCTION__, __LINE__,x)); TRACE("got driver %d\n",x); +jack_driver_t * +_tryGetDriver(int deviceID, int ignored) +{ + fflush(OUTFILE); +#else +jack_driver_t * +tryGetDriver(int deviceID) +{ +#endif + jack_driver_t *drv = &outDev[deviceID]; + + int err; + if((err = pthread_mutex_trylock(&drv->mutex)) == 0) + return drv; + + if(err == EBUSY) + { + TRACE("driver %d is busy\n",deviceID); + return 0; + } + + ERR("lock returned an error\n"); + return 0; +} + + +/* release a device's mutex */ +/* */ +/* This macro is similar to the one for getDriver above, only simpler since we only + really need to know when the lock was release for the sake of debugging. +*/ +#if TRACE_getReleaseDevice +#define releaseDriver(x) TRACE("releasing driver %d\n",x->deviceID); _releaseDriver(x); +void +_releaseDriver(jack_driver_t * drv) +#else +void +releaseDriver(jack_driver_t * drv) +#endif +{ + /* + #if TRACE_getReleaseDevice + TRACE("deviceID == %d\n", drv->deviceID); + #endif + */ + if(pthread_mutex_unlock(&drv->mutex) != 0) + ERR("lock returned an error\n"); +} + + +/* Return a string corresponding to the input state */ +char * +DEBUGSTATE(enum status_enum state) +{ + if(state == PLAYING) + return "PLAYING"; + else if(state == PAUSED) + return "PAUSED"; + else if(state == STOPPED) + return "STOPPED"; + else if(state == CLOSED) + return "CLOSED"; + else if(state == RESET) + return "RESET"; + else + return "unknown state"; +} + + +#define SAMPLE_MAX_16BIT 32767.0f +#define SAMPLE_MAX_8BIT 255.0f + +/* floating point volume routine */ +/* volume should be a value between 0.0 and 1.0 */ +static void +float_volume_effect(sample_t * buf, unsigned long nsamples, float volume, + int skip) +{ + if(volume < 0) + volume = 0; + if(volume > 1.0) + volume = 1.0; + + while(nsamples--) + { + *buf = (*buf) * volume; + buf += skip; + } +} + +/* place one channel into a multi-channel stream */ +static inline void +mux(sample_t * dst, sample_t * src, unsigned long nsamples, + unsigned long dst_skip) +{ + /* ALERT: signed sign-extension portability !!! */ + while(nsamples--) + { + *dst = *src; + dst += dst_skip; + src++; + } +} + +/* pull one channel out of a multi-channel stream */ +static void +demux(sample_t * dst, sample_t * src, unsigned long nsamples, + unsigned long src_skip) +{ + /* ALERT: signed sign-extension portability !!! */ + while(nsamples--) + { + *dst = *src; + dst++; + src += src_skip; + } +} + +/* convert from 16 bit to floating point */ +static inline void +sample_move_short_float(sample_t * dst, short *src, unsigned long nsamples) +{ + /* ALERT: signed sign-extension portability !!! */ + unsigned long i; + for(i = 0; i < nsamples; i++) + dst[i] = (sample_t) (src[i]) / SAMPLE_MAX_16BIT; +} + +/* convert from floating point to 16 bit */ +static inline void +sample_move_float_short(short *dst, sample_t * src, unsigned long nsamples) +{ + /* ALERT: signed sign-extension portability !!! */ + unsigned long i; + for(i = 0; i < nsamples; i++) + dst[i] = (short) ((src[i]) * SAMPLE_MAX_16BIT); +} + +/* convert from 8 bit to floating point */ +static inline void +sample_move_char_float(sample_t * dst, unsigned char *src, unsigned long nsamples) +{ + /* ALERT: signed sign-extension portability !!! */ + unsigned long i; + for(i = 0; i < nsamples; i++) + dst[i] = (sample_t) (src[i]) / SAMPLE_MAX_8BIT; +} + +/* convert from floating point to 8 bit */ +static inline void +sample_move_float_char(unsigned char *dst, sample_t * src, unsigned long nsamples) +{ + /* ALERT: signed sign-extension portability !!! */ + unsigned long i; + for(i = 0; i < nsamples; i++) + dst[i] = (char) ((src[i]) * SAMPLE_MAX_8BIT); +} + +/* fill dst buffer with nsamples worth of silence */ +static inline void +sample_silence_float(sample_t * dst, unsigned long nsamples) +{ + /* ALERT: signed sign-extension portability !!! */ + while(nsamples--) + { + *dst = 0; + dst++; + } +} + +static inline bool +ensure_buffer_size(char **buffer, unsigned long *cur_size, + unsigned long needed_size) +{ + DEBUG("current size = %lu, needed size = %lu\n", *cur_size, needed_size); + if(*cur_size >= needed_size) + return TRUE; + DEBUG("reallocing\n"); + char *tmp = realloc(*buffer, needed_size); + if(tmp) + { + *cur_size = needed_size; + *buffer = tmp; + return TRUE; + } + DEBUG("reallocing failed\n"); + return FALSE; +} + +/****************************************************************** + * JACK_callback + * + * every time the jack server wants something from us it calls this + * function, so we either deliver it some sound to play or deliver it nothing + * to play + */ +static int +JACK_callback(nframes_t nframes, void *arg) +{ + jack_driver_t *drv = (jack_driver_t *) arg; + + unsigned int i; + + + drv->chunk_size = nframes; + + TIMER("start\n"); + gettimeofday(&drv->previousTime, 0); /* record the current time */ + + CALLBACK_TRACE("nframes %ld, sizeof(sample_t) == %d\n", (long) nframes, + sizeof(sample_t)); + + if(!drv->client) + ERR("client is closed, this is weird...\n"); + + sample_t *out_buffer[MAX_OUTPUT_PORTS]; + /* retrieve the buffers for the output ports */ + for(i = 0; i < drv->num_output_channels; i++) + out_buffer[i] = (sample_t *) jack_port_get_buffer(drv->output_port[i], nframes); + + sample_t *in_buffer[MAX_INPUT_PORTS]; + /* retrieve the buffers for the input ports */ + for(i = 0; i < drv->num_input_channels; i++) + in_buffer[i] = (sample_t *) jack_port_get_buffer(drv->input_port[i], nframes); + + /* handle playing state */ + if(drv->state == PLAYING) + { + /* handle playback data, if any */ + if(drv->num_output_channels > 0) + { + unsigned long jackFramesAvailable = nframes; /* frames we have left to write to jack */ + unsigned long numFramesToWrite; /* num frames we are writing */ + size_t inputBytesAvailable = jack_ringbuffer_read_space(drv->pPlayPtr); + unsigned long inputFramesAvailable; /* frames we have available */ + + inputFramesAvailable = inputBytesAvailable / drv->bytes_per_jack_output_frame; + size_t jackBytesAvailable = jackFramesAvailable * drv->bytes_per_jack_output_frame; + + long read = 0; + + CALLBACK_TRACE("playing... jackFramesAvailable = %ld inputFramesAvailable = %ld\n", + jackFramesAvailable, inputFramesAvailable); + +#if JACK_CLOSE_HACK + if(drv->in_use == FALSE) + { + /* output silence if nothing is being outputted */ + for(i = 0; i < drv->num_output_channels; i++) + sample_silence_float(out_buffer[i], nframes); + + return -1; + } +#endif + + /* make sure our buffer is large enough for the data we are writing */ + /* ie. callback_buffer2_size < (bytes we already wrote + bytes we are going to write in this loop) */ + if(!ensure_buffer_size + (&drv->callback_buffer2, &drv->callback_buffer2_size, + jackBytesAvailable)) + { + + + return -1; + } + + /* do sample rate conversion if needed & requested */ +#ifdef HAVE_SAMPLERATE + if(drv->output_src && drv->output_sample_rate_ratio != 1.0) + { + long bytes_needed_write = nframes * drv->bytes_per_jack_output_frame; + + /* make a very good guess at how many raw bytes we'll need to satisfy jack's request after conversion */ + long bytes_needed_read = min(inputBytesAvailable, + (double) (bytes_needed_write + + drv-> + output_sample_rate_ratio + * + drv-> + bytes_per_jack_output_frame) + / drv->output_sample_rate_ratio); + DEBUG("guessing that we need %ld bytes in and %ld out for rate conversion ratio = %f\n", + bytes_needed_read, bytes_needed_write, + drv->output_sample_rate_ratio); + + if(!ensure_buffer_size(&drv->callback_buffer1, + &drv->callback_buffer1_size, + bytes_needed_read)) + { + ERR("could not realloc callback_buffer2!\n"); + return 1; + } + if(!ensure_buffer_size(&drv->callback_buffer2, + &drv->callback_buffer2_size, + bytes_needed_write)) + { + ERR("could not realloc callback_buffer2!\n"); + return 1; + } + + if(jackFramesAvailable && inputBytesAvailable > 0) + { + /* read in the data, but don't move the read pointer until we know how much SRC used */ + jack_ringbuffer_peek(drv->pPlayPtr, drv->callback_buffer1, + bytes_needed_read); + + SRC_DATA srcdata; + srcdata.data_in = (sample_t *) drv->callback_buffer1; + srcdata.input_frames = bytes_needed_read / drv->bytes_per_jack_output_frame; + srcdata.src_ratio = drv->output_sample_rate_ratio; + srcdata.data_out = (sample_t *) drv->callback_buffer2; + srcdata.output_frames = nframes; + srcdata.end_of_input = 0; // it's a stream, it never ends + DEBUG("input_frames = %ld, output_frames = %ld\n", + srcdata.input_frames, srcdata.output_frames); + /* convert the sample rate */ + src_error = src_process(drv->output_src, &srcdata); + DEBUG("used = %ld, generated = %ld, error = %d: %s.\n", + srcdata.input_frames_used, srcdata.output_frames_gen, + src_error, src_strerror(src_error)); + + if(src_error == 0) + { + /* now we can move the read pointer */ + jack_ringbuffer_read_advance(drv->pPlayPtr, + srcdata. + input_frames_used * + drv->bytes_per_jack_output_frame); + /* add on what we wrote */ + read = srcdata.input_frames_used * drv->bytes_per_output_frame; + jackFramesAvailable -= srcdata.output_frames_gen; /* take away what was used */ + } + } + } + else /* no resampling needed or requested */ + { + /* read as much data from the buffer as is available */ + if(jackFramesAvailable && inputBytesAvailable > 0) + { + /* write as many bytes as we have space remaining, or as much as we have data to write */ + numFramesToWrite = min(jackFramesAvailable, inputFramesAvailable); + jack_ringbuffer_read(drv->pPlayPtr, drv->callback_buffer2, + jackBytesAvailable); + /* add on what we wrote */ + read = numFramesToWrite * drv->bytes_per_output_frame; + jackFramesAvailable -= numFramesToWrite; /* take away what was written */ + } + } +#else + /* read as much data from the buffer as is available */ + if(jackFramesAvailable && inputBytesAvailable > 0) + { + /* write as many bytes as we have space remaining, or as much as we have data to write */ + numFramesToWrite = min(jackFramesAvailable, inputFramesAvailable); + jack_ringbuffer_read(drv->pPlayPtr, drv->callback_buffer2, + jackBytesAvailable); + /* add on what we wrote */ + read = numFramesToWrite * drv->bytes_per_output_frame; + jackFramesAvailable -= numFramesToWrite; /* take away what was written */ + } + +#endif + drv->written_client_bytes += read; + drv->played_client_bytes += drv->clientBytesInJack; /* move forward by the previous bytes we wrote since those must have finished by now */ + drv->clientBytesInJack = read; /* record the input bytes we wrote to jack */ + drv->num_ticks ++; + /* see if we still have jackBytesLeft here, if we do that means that we + ran out of wave data to play and had a buffer underrun, fill in + the rest of the space with zero bytes so at least there is silence */ + if(jackFramesAvailable) + { + WARN("buffer underrun of %ld frames\n", jackFramesAvailable); + for(i = 0; i < drv->num_output_channels; i++) + sample_silence_float(out_buffer[i] + + (nframes - jackFramesAvailable), + jackFramesAvailable); + } + + /* if we aren't converting or we are converting and src_error == 0 then we should */ + /* apply volume and demux */ +#ifdef HAVE_SAMPLERATE + if(!(drv->output_src && drv->output_sample_rate_ratio != 1.0) || (src_error == 0)) + { + /* apply volume */ + for(i = 0; i < drv->num_output_channels; i++) + { + if(drv->volumeEffectType == dbAttenuation) + { + /* assume the volume setting is dB of attenuation, a volume of 0 */ + /* is 0dB attenuation */ + float volume = powf(10.0, -((float) drv->volume[i]) / 20.0); + float_volume_effect((sample_t *) drv->callback_buffer2 + i, + (nframes - jackFramesAvailable), volume, drv->num_output_channels); + } else + { + float_volume_effect((sample_t *) drv->callback_buffer2 + i, (nframes - jackFramesAvailable), + ((float) drv->volume[i] / 100.0), + drv->num_output_channels); + } + } + } +#endif + if( !(drv->output_sample_rate_ratio != 1.0)) + { + /* demux the stream: we skip over the number of samples we have output channels as the channel data */ + /* is encoded like chan1,chan2,chan3,chan1,chan2,chan3... */ + for(i = 0; i < drv->num_output_channels; i++) + { + demux(out_buffer[i], + (sample_t *) drv->callback_buffer2 + i, + (nframes - jackFramesAvailable), drv->num_output_channels); + } + + } + } + + /* handle record data, if any */ + if(drv->num_input_channels > 0) + { + long jack_bytes = nframes * drv->bytes_per_jack_input_frame; /* how many bytes jack is feeding us */ + + if(!ensure_buffer_size(&drv->callback_buffer1, &drv->callback_buffer1_size, jack_bytes)) + { + ERR("allocated %lu bytes, need %lu bytes\n", + drv->callback_buffer1_size, jack_bytes); + return -1; + } + + /* mux the invividual channels into one stream */ + for(i = 0; i < drv->num_input_channels; i++) + { + mux((sample_t *) drv->callback_buffer1 + i, in_buffer[i], + nframes, drv->num_input_channels); + } + + /* do sample rate conversion if needed & requested */ +#ifdef HAVE_SAMPLERATE + if(drv->input_src && drv->input_sample_rate_ratio != 1.0) + { + /* make a very good guess at how many raw bytes we'll need to read all the data jack gave us */ + long bytes_needed_write = (double) (jack_bytes + + drv->input_sample_rate_ratio * + drv->bytes_per_jack_input_frame) * + drv->input_sample_rate_ratio; + DEBUG("guessing that we need %ld bytes in and %ld out for rate conversion ratio = %f\n", + nframes * drv->bytes_per_jack_input_frame, + bytes_needed_write, drv->input_sample_rate_ratio); + + if(!ensure_buffer_size(&drv->callback_buffer2, + &drv->callback_buffer2_size, + bytes_needed_write)) + { + ERR("could not realloc callback_buffer2!\n"); + return 1; + } + + SRC_DATA srcdata; + srcdata.data_in = (sample_t *) drv->callback_buffer1; + srcdata.input_frames = nframes; + srcdata.src_ratio = drv->input_sample_rate_ratio; + srcdata.data_out = (sample_t *) drv->callback_buffer2; + srcdata.output_frames = drv->callback_buffer2_size / drv->bytes_per_jack_input_frame; + srcdata.end_of_input = 0; // it's a stream, it never ends + DEBUG("input_frames = %ld, output_frames = %ld\n", + srcdata.input_frames, srcdata.output_frames); + /* convert the sample rate */ + src_error = src_process(drv->input_src, &srcdata); + DEBUG("used = %ld, generated = %ld, error = %d: %s.\n", + srcdata.input_frames_used, srcdata.output_frames_gen, + src_error, src_strerror(src_error)); + + if(src_error == 0) + { + long write_space = jack_ringbuffer_write_space(drv->pRecPtr); + long bytes_used = srcdata.output_frames_gen * drv->bytes_per_jack_input_frame; + /* if there isn't enough room, make some. sure this discards data, but when dealing with input sources + it seems like it's better to throw away old data than new */ + if(write_space < bytes_used) + { + /* the ringbuffer is designed such that only one thread should ever access each pointer. + since calling read_advance here will be touching the read pointer which is also accessed + by JACK_Read, we need to lock the mutex first for safety */ + jack_driver_t *d = tryGetDriver(drv->deviceID); + if( d ) + { + /* double check the write space after we've gained the lock, just + in case JACK_Read was being called before we gained it */ + write_space = jack_ringbuffer_write_space(drv->pRecPtr); + if(write_space < bytes_used) + { + /* hey, we warn about underruns, we might as well warn about overruns as well */ + WARN("buffer overrun of %ld bytes\n", jack_bytes - write_space); + jack_ringbuffer_read_advance(drv->pRecPtr, bytes_used - write_space); + } + + releaseDriver(drv); + } + } + + jack_ringbuffer_write(drv->pRecPtr, drv->callback_buffer2, + bytes_used); + } + } + else /* no resampling needed */ + { +#endif + long write_space = jack_ringbuffer_write_space(drv->pRecPtr); + /* if there isn't enough room, make some. sure this discards data, but when dealing with input sources + it seems like it's better to throw away old data than new */ + if(write_space < jack_bytes) + { + /* the ringbuffer is designed such that only one thread should ever access each pointer. + since calling read_advance here will be touching the read pointer which is also accessed + by JACK_Read, we need to lock the mutex first for safety */ + jack_driver_t *d = tryGetDriver(drv->deviceID); + if( d ) + { + /* double check the write space after we've gained the lock, just + in case JACK_Read was being called before we gained it */ + write_space = jack_ringbuffer_write_space(drv->pRecPtr); + if(write_space < jack_bytes) + { + ERR("buffer overrun of %ld bytes\n", jack_bytes - write_space); + jack_ringbuffer_read_advance(drv->pRecPtr, jack_bytes - write_space); + } + releaseDriver(drv); + } + } + + jack_ringbuffer_write(drv->pRecPtr, drv->callback_buffer1, + jack_bytes); +#ifdef HAVE_SAMPLERATE + } +#endif + } + } + else if(drv->state == PAUSED || + drv->state == STOPPED || + drv->state == CLOSED || drv->state == RESET) + { + CALLBACK_TRACE("%s, outputting silence\n", DEBUGSTATE(drv->state)); + + /* output silence if nothing is being outputted */ + for(i = 0; i < drv->num_output_channels; i++) + sample_silence_float(out_buffer[i], nframes); + + /* if we were told to reset then zero out some variables */ + /* and transition to STOPPED */ + if(drv->state == RESET) + { + drv->written_client_bytes = 0; + drv->played_client_bytes = 0; /* number of the clients bytes that jack has played */ + + drv->client_bytes = 0; /* bytes that the client wrote to use */ + + drv->clientBytesInJack = 0; /* number of input bytes in jack(not necessary the number of bytes written to jack) */ + + drv->position_byte_offset = 0; + + if(drv->pPlayPtr) + jack_ringbuffer_reset(drv->pPlayPtr); + + if(drv->pRecPtr) + jack_ringbuffer_reset(drv->pRecPtr); + + drv->state = STOPPED; /* transition to STOPPED */ + } + } + + CALLBACK_TRACE("done\n"); + TIMER("finish\n"); + + return 0; +} + + +/****************************************************************** + * JACK_bufsize + * + * Called whenever the jack server changes the the max number + * of frames passed to JACK_callback + */ +static int +JACK_bufsize(nframes_t nframes, void *arg) +{ + jack_driver_t *drv = (jack_driver_t *) arg; + TRACE("the maximum buffer size is now %lu frames\n", (long) nframes); + + drv->jack_buffer_size = nframes; + + return 0; +} + +/****************************************************************** + * JACK_srate + */ +int +JACK_srate(nframes_t nframes, void *arg) +{ + jack_driver_t *drv = (jack_driver_t *) arg; + + drv->jack_sample_rate = (long) nframes; + drv->output_sample_rate_ratio = 1.0; + drv->input_sample_rate_ratio = 1.0; +#ifdef HAVE_SAMPLERATE + /* make sure to recalculate the ratios needed for proper sample rate conversion */ + drv->output_sample_rate_ratio = (double) drv->jack_sample_rate / (double) drv->client_sample_rate; + if(drv->output_src) src_set_ratio(drv->output_src, drv->output_sample_rate_ratio); + + drv->input_sample_rate_ratio = (double) drv->client_sample_rate / (double) drv->jack_sample_rate; + if(drv->input_src) src_set_ratio(drv->input_src, drv->input_sample_rate_ratio); +#endif + TRACE("the sample rate is now %lu/sec\n", (long) nframes); + return 0; +} + + +/****************************************************************** + * JACK_shutdown + * + * if this is called then jack shut down... handle this appropriately */ +void +JACK_shutdown(void *arg) +{ + jack_driver_t *drv = (jack_driver_t *) arg; + + TRACE("\n"); + + getDriver(drv->deviceID); + + drv->client = 0; /* reset client */ + drv->jackd_died = TRUE; + + TRACE("jack shutdown, setting client to 0 and jackd_died to true, closing device\n"); + +#if JACK_CLOSE_HACK + JACK_CloseDevice(drv, TRUE); +#else + JACK_CloseDevice(drv); +#endif + + TRACE("trying to reconnect right now\n"); + /* lets see if we can't reestablish the connection */ + if(JACK_OpenDevice(drv) != ERR_SUCCESS) + { + ERR("unable to reconnect with jack\n"); + } + + releaseDriver(drv); +} + + +/****************************************************************** + * JACK_Error + * + * Callback for jack errors + */ +static void +JACK_Error(const char *desc) +{ + ERR("%s\n", desc); +} + + +/****************************************************************** + * JACK_OpenDevice + * + * RETURNS: ERR_SUCCESS upon success + */ +static int +JACK_OpenDevice(jack_driver_t * drv) +{ + const char **ports; + char *our_client_name = 0; + unsigned int i; + int failed = 0; + + TRACE("creating jack client and setting up callbacks\n"); + +#if JACK_CLOSE_HACK + /* see if this device is already open */ + if(drv->client) + { + /* if this device is already in use then it is bad for us to be in here */ + if(drv->in_use) + return ERR_OPENING_JACK; + + TRACE("using existing client\n"); + drv->in_use = TRUE; + return ERR_SUCCESS; + } +#endif + + /* set up an error handler */ + jack_set_error_function(JACK_Error); + + + /* build the client name */ + our_client_name = (char *) malloc(snprintf + (our_client_name, 0, "%s_%d_%d%02d", client_name, getpid(), + drv->deviceID, drv->clientCtr + 1) + 1); + sprintf(our_client_name, "%s_%d_%d%02d", client_name, getpid(), + drv->deviceID, drv->clientCtr++); + + /* try to become a client of the JACK server */ + TRACE("client name '%s'\n", our_client_name); + if((drv->client = jack_client_new(our_client_name)) == 0) + { + /* try once more */ + TRACE("trying once more to jack_client_new"); + if((drv->client = jack_client_new(our_client_name)) == 0) + { + ERR("jack server not running?\n"); + free(our_client_name); + return ERR_OPENING_JACK; + } + } + + free(our_client_name); + + drv->client_sample_rate = jack_get_sample_rate(drv->client); + + TRACE("setting up jack callbacks\n"); + + /* JACK server to call `JACK_callback()' whenever + there is work to be done. */ + jack_set_process_callback(drv->client, JACK_callback, drv); + + /* setup a buffer size callback */ + jack_set_buffer_size_callback(drv->client, JACK_bufsize, drv); + + /* tell the JACK server to call `srate()' whenever + the sample rate of the system changes. */ + jack_set_sample_rate_callback(drv->client, JACK_srate, drv); + + /* tell the JACK server to call `jack_shutdown()' if + it ever shuts down, either entirely, or if it + just decides to stop calling us. */ + jack_on_shutdown(drv->client, JACK_shutdown, drv); + + /* display the current sample rate. once the client is activated + (see below), you should rely on your own sample rate + callback (see above) for this value. */ + drv->jack_sample_rate = jack_get_sample_rate(drv->client); + drv->output_sample_rate_ratio = (double) drv->jack_sample_rate / (double) drv->client_sample_rate; + drv->input_sample_rate_ratio = (double) drv->client_sample_rate / (double) drv->jack_sample_rate; + TRACE("client sample rate: %lu, jack sample rate: %lu, output ratio = %f, input ratio = %f\n", + drv->client_sample_rate, drv->jack_sample_rate, + drv->output_sample_rate_ratio, drv->input_sample_rate_ratio); + + drv->jack_buffer_size = jack_get_buffer_size(drv->client); + + /* create the output ports */ + TRACE("creating output ports\n"); + for(i = 0; i < drv->num_output_channels; i++) + { + char portname[32]; + sprintf(portname, "out_%d", i); + TRACE("port %d is named '%s'\n", i, portname); + /* NOTE: Yes, this is supposed to be JackPortIsOutput since this is an output */ + /* port FROM bio2jack */ + drv->output_port[i] = jack_port_register(drv->client, portname, + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0); + } + + /* create the input ports */ + TRACE("creating input ports\n"); + for(i = 0; i < drv->num_input_channels; i++) + { + char portname[32]; + sprintf(portname, "in_%d", i); + TRACE("port %d is named '%s'\n", i, portname); + /* NOTE: Yes, this is supposed to be JackPortIsInput since this is an input */ + /* port TO bio2jack */ + drv->input_port[i] = jack_port_register(drv->client, portname, + JACK_DEFAULT_AUDIO_TYPE, + JackPortIsInput, 0); + } + +#if JACK_CLOSE_HACK + drv->in_use = TRUE; +#endif + + /* tell the JACK server that we are ready to roll */ + TRACE("calling jack_activate()\n"); + if(jack_activate(drv->client)) + { + ERR("cannot activate client\n"); + return ERR_OPENING_JACK; + } + + /* if we have output channels and the port connection mode isn't CONNECT_NONE */ + /* then we should connect up some ports */ + if((drv->num_output_channels > 0) && (port_connection_mode != CONNECT_NONE)) + { + /* determine how we are to acquire output port names */ + if((drv->jack_port_name_count == 0) || (drv->jack_port_name_count == 1)) + { + if(drv->jack_port_name_count == 0) + { + TRACE("jack_get_ports() passing in NULL/NULL\n"); + ports = jack_get_ports(drv->client, NULL, NULL, + drv->jack_output_port_flags); + } + else + { + TRACE("jack_get_ports() passing in port of '%s'\n", + drv->jack_port_name[0]); + ports = jack_get_ports(drv->client, drv->jack_port_name[0], NULL, + drv->jack_output_port_flags); + } + + /* display a trace of the output ports we found */ + unsigned int num_ports = 0; + if(ports) + { + for(i = 0; ports[i]; i++) + { + TRACE("ports[%d] = '%s'\n", i, ports[i]); + num_ports++; + } + } + + /* ensure that we found enough ports */ + if(!ports || (i < drv->num_output_channels)) + { + TRACE("ERR: jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n", + drv->jack_output_port_flags); +#if JACK_CLOSE_HACK + JACK_CloseDevice(drv, TRUE); +#else + JACK_CloseDevice(drv); +#endif + return ERR_PORT_NOT_FOUND; + } + + /* connect a port for each output channel. Note: you can't do this before + the client is activated (this may change in the future). */ + for(i = 0; i < drv->num_output_channels; i++) + { + TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[i]); + if(jack_connect(drv->client, jack_port_name(drv->output_port[i]), ports[i])) + { + ERR("cannot connect to output port %d('%s')\n", i, ports[i]); + failed = 1; + } + } + + /* only if we are in CONNECT_ALL mode should we keep connecting ports up beyond */ + /* the minimum number of ports required for each output channel coming into bio2jack */ + if(port_connection_mode == CONNECT_ALL) + { + /* It's much cheaper and easier to let JACK do the processing required to + connect 2 channels to 4 or 4 channels to 2 or any other combinations. + This effectively eliminates the need for sample_move_d16_d16() */ + if(drv->num_output_channels < num_ports) + { + for(i = drv->num_output_channels; ports[i]; i++) + { + int n = i % drv->num_output_channels; + TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[n]); + if(jack_connect(drv->client, jack_port_name(drv->output_port[n]), ports[i])) + { + // non fatal + ERR("cannot connect to output port %d('%s')\n", n, ports[i]); + } + } + } + else if(drv->num_output_channels > num_ports) + { + for(i = num_ports; i < drv->num_output_channels; i++) + { + int n = i % num_ports; + TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[n]); + if(jack_connect(drv->client, jack_port_name(drv->output_port[i]), ports[n])) + { + // non fatal + ERR("cannot connect to output port %d('%s')\n", i, ports[n]); + } + } + } + } + + free(ports); /* free the returned array of ports */ + } + else + { + for(i = 0; i < drv->jack_port_name_count; i++) + { + TRACE("jack_get_ports() portname %d of '%s\n", i, + drv->jack_port_name[i]); + ports = jack_get_ports(drv->client, drv->jack_port_name[i], NULL, + drv->jack_output_port_flags); + + if(!ports) + { + ERR("jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n", + drv->jack_output_port_flags); + return ERR_PORT_NOT_FOUND; + } + + TRACE("ports[%d] = '%s'\n", 0, ports[0]); /* display a trace of the output port we found */ + + /* connect the port */ + TRACE("jack_connect() to port %d('%p')\n", i, drv->output_port[i]); + if(jack_connect(drv->client, jack_port_name(drv->output_port[i]), ports[0])) + { + ERR("cannot connect to output port %d('%s')\n", 0, ports[0]); + failed = 1; + } + free(ports); /* free the returned array of ports */ + } + } + } /* if( drv->num_output_channels > 0 ) */ + + + if(drv->num_input_channels > 0) + { + /* determine how we are to acquire input port names */ + if((drv->jack_port_name_count == 0) || (drv->jack_port_name_count == 1)) + { + if(drv->jack_port_name_count == 0) + { + TRACE("jack_get_ports() passing in NULL/NULL\n"); + ports = jack_get_ports(drv->client, NULL, NULL, drv->jack_input_port_flags); + } + else + { + TRACE("jack_get_ports() passing in port of '%s'\n", + drv->jack_port_name[0]); + ports = jack_get_ports(drv->client, drv->jack_port_name[0], NULL, + drv->jack_input_port_flags); + } + + /* display a trace of the input ports we found */ + unsigned int num_ports = 0; + if(ports) + { + for(i = 0; ports[i]; i++) + { + TRACE("ports[%d] = '%s'\n", i, ports[i]); + num_ports++; + } + } + + /* ensure that we found enough ports */ + if(!ports || (i < drv->num_input_channels)) + { + TRACE("ERR: jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n", + drv->jack_input_port_flags); +#if JACK_CLOSE_HACK + JACK_CloseDevice(drv, TRUE); +#else + JACK_CloseDevice(drv); +#endif + return ERR_PORT_NOT_FOUND; + } + + /* connect the ports. Note: you can't do this before + the client is activated (this may change in the future). */ + for(i = 0; i < drv->num_input_channels; i++) + { + TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[i]); + if(jack_connect(drv->client, ports[i], jack_port_name(drv->input_port[i]))) + { + ERR("cannot connect to input port %d('%s')\n", i, ports[i]); + failed = 1; + } + } + + /* It's much cheaper and easier to let JACK do the processing required to + connect 2 channels to 4 or 4 channels to 2 or any other combinations. + This effectively eliminates the need for sample_move_d16_d16() */ + if(drv->num_input_channels < num_ports) + { + for(i = drv->num_input_channels; ports[i]; i++) + { + int n = i % drv->num_input_channels; + TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[n]); + if(jack_connect(drv->client, ports[i], jack_port_name(drv->input_port[n]))) + { + // non fatal + ERR("cannot connect to input port %d('%s')\n", n, ports[i]); + } + } + } + else if(drv->num_input_channels > num_ports) + { + for(i = num_ports; i < drv->num_input_channels; i++) + { + int n = i % num_ports; + TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[n]); + if(jack_connect(drv->client, ports[n], jack_port_name(drv->input_port[i]))) + { + // non fatal + ERR("cannot connect to input port %d('%s')\n", i, ports[n]); + } + } + } + + free(ports); /* free the returned array of ports */ + } + else + { + for(i = 0; i < drv->jack_port_name_count; i++) + { + TRACE("jack_get_ports() portname %d of '%s\n", i, + drv->jack_port_name[i]); + ports = jack_get_ports(drv->client, drv->jack_port_name[i], NULL, + drv->jack_input_port_flags); + + if(!ports) + { + ERR("jack_get_ports() failed to find ports with jack port flags of 0x%lX'\n", + drv->jack_input_port_flags); + return ERR_PORT_NOT_FOUND; + } + + TRACE("ports[%d] = '%s'\n", 0, ports[0]); /* display a trace of the input port we found */ + + /* connect the port */ + TRACE("jack_connect() to port %d('%p')\n", i, drv->input_port[i]); + if(jack_connect(drv->client, jack_port_name(drv->input_port[i]), ports[0])) + { + ERR("cannot connect to input port %d('%s')\n", 0, ports[0]); + failed = 1; + } + free(ports); /* free the returned array of ports */ + } + } + } /* if( drv->num_input_channels > 0 ) */ + + /* if something failed we need to shut the client down and return 0 */ + if(failed) + { + TRACE("failed, closing and returning error\n"); +#if JACK_CLOSE_HACK + JACK_CloseDevice(drv, TRUE); +#else + JACK_CloseDevice(drv); +#endif + return ERR_OPENING_JACK; + } + + TRACE("success\n"); + + drv->jackd_died = FALSE; /* clear out this flag so we don't keep attempting to restart things */ + drv->state = PLAYING; /* clients seem to behave much better with this on from the start, especially when recording */ + + return ERR_SUCCESS; /* return success */ +} + + +/****************************************************************** + * JACK_CloseDevice + * + * Close the connection to the server cleanly. + * If close_client is TRUE we close the client for this device instead of + * just marking the device as in_use(JACK_CLOSE_HACK only) + */ +#if JACK_CLOSE_HACK +static void +JACK_CloseDevice(jack_driver_t * drv, bool close_client) +#else +static void +JACK_CloseDevice(jack_driver_t * drv) +#endif +{ + unsigned int i; + +#if JACK_CLOSE_HACK + if(close_client) + { +#endif + + TRACE("closing the jack client thread\n"); + if(drv->client) + { + TRACE("after jack_deactivate()\n"); + int errorCode = jack_client_close(drv->client); + if(errorCode) + ERR("jack_client_close() failed returning an error code of %d\n", + errorCode); + } + + /* reset client */ + drv->client = 0; + + /* free up the port strings */ + TRACE("freeing up %d port strings\n", drv->jack_port_name_count); + if(drv->jack_port_name_count > 1) + { + for(i = 0; i < drv->jack_port_name_count; i++) + free(drv->jack_port_name[i]); + free(drv->jack_port_name); + } + JACK_CleanupDriver(drv); + + JACK_ResetFromDriver(drv); + +#if JACK_CLOSE_HACK + } else + { + TRACE("setting in_use to FALSE\n"); + drv->in_use = FALSE; + + if(!drv->client) + { + TRACE("critical error, closing a device that has no client\n"); + } + } +#endif +} + + + + +/**************************************/ +/* External interface functions below */ +/**************************************/ + +/* Clear out any buffered data, stop playing, zero out some variables */ +static void +JACK_ResetFromDriver(jack_driver_t * drv) +{ + TRACE("resetting drv->deviceID(%d)\n", drv->deviceID); + + /* NOTE: we use the RESET state so we don't need to worry about clearing out */ + /* variables that the callback modifies while the callback is running */ + /* we set the state to RESET and the callback clears the variables out for us */ + drv->state = RESET; /* tell the callback that we are to reset, the callback will transition this to STOPPED */ +} + +/* Clear out any buffered data, stop playing, zero out some variables */ +void +JACK_Reset(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + TRACE("resetting deviceID(%d)\n", deviceID); + JACK_ResetFromDriver(drv); + releaseDriver(drv); +} + + +/* + * open the audio device for writing to + * + * deviceID is set to the opened device + * if client is non-zero and in_use is FALSE then just set in_use to TRUE + * + * return value is zero upon success, non-zero upon failure + * + * if ERR_RATE_MISMATCH (*rate) will be updated with the jack servers rate + */ +int +JACK_Open(int *deviceID, unsigned int bits_per_channel, unsigned long *rate, + int channels) +{ + /* we call through to JACK_OpenEx(), but default the input channels to 0 for better backwards + compatibility with clients written before recording was available */ + return JACK_OpenEx(deviceID, bits_per_channel, + rate, + 0, channels, + NULL, 0, JackPortIsPhysical); +} + +/* + * see JACK_Open() for comments + * NOTE: jack_port_name has three ways of being used: + * - NULL - finds all ports with the given flags + * - A single regex string used to retrieve all port names + * - A series of port names, one for each output channel + * + * we set *deviceID + */ +int +JACK_OpenEx(int *deviceID, unsigned int bits_per_channel, + unsigned long *rate, + unsigned int input_channels, unsigned int output_channels, + const char **jack_port_name, + unsigned int jack_port_name_count, unsigned long jack_port_flags) +{ + jack_driver_t *drv = 0; + unsigned int i; + int retval; + + if(input_channels < 1 && output_channels < 1) + { + ERR("no input OR output channels, nothing to do\n"); + return ERR_OPENING_JACK; + } + + switch (bits_per_channel) + { + case 8: + case 16: + break; + default: + ERR("invalid bits_per_channel\n"); + return ERR_OPENING_JACK; + } + + /* Lock the device_mutex and find one that's not allocated already. + We'll keep this lock until we've either made use of it, or given up. */ + pthread_mutex_lock(&device_mutex); + + for(i = 0; i < MAX_OUTDEVICES; i++) + { + if(!outDev[i].allocated) + { + drv = &outDev[i]; + break; + } + } + + if(!drv) + { + ERR("no more devices available\n"); + return ERR_OPENING_JACK; + } + + /* We found an unallocated device, now lock it for extra saftey */ + getDriver(drv->deviceID); + + TRACE("bits_per_channel=%d rate=%ld, input_channels=%d, output_channels=%d\n", + bits_per_channel, *rate, input_channels, output_channels); + + if(output_channels > MAX_OUTPUT_PORTS) + { + ERR("output_channels == %d, MAX_OUTPUT_PORTS == %d\n", output_channels, + MAX_OUTPUT_PORTS); + releaseDriver(drv); + pthread_mutex_unlock(&device_mutex); + return ERR_TOO_MANY_OUTPUT_CHANNELS; + } + + if(input_channels > MAX_INPUT_PORTS) + { + ERR("input_channels == %d, MAX_INPUT_PORTS == %d\n", input_channels, + MAX_INPUT_PORTS); + releaseDriver(drv); + pthread_mutex_unlock(&device_mutex); + return ERR_TOO_MANY_INPUT_CHANNELS; + } + + drv->jack_output_port_flags = jack_port_flags | JackPortIsInput; /* port must be input(ie we can put data into it), so mask this in */ + drv->jack_input_port_flags = jack_port_flags | JackPortIsOutput; /* port must be output(ie we can get data from it), so mask this in */ + + /* check that we have the correct number of port names + FIXME?: not sure how we should handle output ports vs input ports.... + */ + if((jack_port_name_count > 1) + && ((jack_port_name_count < output_channels) + || (jack_port_name_count < input_channels))) + { + ERR("specified individual port names but not enough, gave %d names, need %d\n", + jack_port_name_count, output_channels); + releaseDriver(drv); + pthread_mutex_unlock(&device_mutex); + return ERR_PORT_NAME_OUTPUT_CHANNEL_MISMATCH; + } else + { + /* copy this data into the device information */ + drv->jack_port_name_count = jack_port_name_count; + + if(drv->jack_port_name_count != 0) + { + drv->jack_port_name = + (char **) malloc(sizeof(char *) * drv->jack_port_name_count); + for(i = 0; i < drv->jack_port_name_count; i++) + { + drv->jack_port_name[i] = strdup(jack_port_name[i]); + TRACE("jack_port_name[%d] == '%s'\n", i, jack_port_name[i]); + } + } else + { + drv->jack_port_name = NULL; + TRACE("jack_port_name = NULL\n"); + } + } + + /* initialize some variables */ + drv->in_use = FALSE; + + JACK_ResetFromDriver(drv); /* flushes all queued buffers, sets status to STOPPED and resets some variables */ + + /* drv->jack_sample_rate is set by JACK_OpenDevice() */ +//@ veejay resamples + drv->client_sample_rate = *rate; + drv->bits_per_channel = bits_per_channel; + drv->num_input_channels = input_channels; + drv->num_output_channels = output_channels; + drv->bytes_per_input_frame = (drv->bits_per_channel * drv->num_input_channels) / 8; + drv->bytes_per_output_frame = (drv->bits_per_channel * drv->num_output_channels) / 8; + drv->bytes_per_jack_output_frame = sizeof(sample_t) * drv->num_output_channels; + drv->bytes_per_jack_input_frame = sizeof(sample_t) * drv->num_input_channels; + + if(drv->num_output_channels > 0) + { + drv->pPlayPtr = jack_ringbuffer_create(drv->num_output_channels * + drv->bytes_per_jack_output_frame * + DEFAULT_RB_SIZE); + } + + if(drv->num_input_channels > 0) + { + drv->pRecPtr = jack_ringbuffer_create(drv->num_input_channels * + drv->bytes_per_jack_input_frame * + DEFAULT_RB_SIZE); + } + + DEBUG("bytes_per_output_frame == %ld\n", drv->bytes_per_output_frame); + DEBUG("bytes_per_input_frame == %ld\n", drv->bytes_per_input_frame); + DEBUG("bytes_per_jack_output_frame == %ld\n", + drv->bytes_per_jack_output_frame); + DEBUG("bytes_per_jack_input_frame == %ld\n", + drv->bytes_per_jack_input_frame); + + /* go and open up the device */ + retval = JACK_OpenDevice(drv); + if(retval != ERR_SUCCESS) + { + TRACE("error opening jack device\n"); + releaseDriver(drv); + pthread_mutex_unlock(&device_mutex); + return retval; + } + else + { + TRACE("succeeded opening jack device\n"); + } + + /* setup SRC objects just in case they'll be needed but only if requested */ +#ifdef HAVE_SAMPLERATE + if(do_sample_rate_conversion) + { + int error; + if(drv->num_output_channels > 0) + { + drv->output_src = src_new(preferred_src_converter, drv->num_output_channels, &error); + if(error != 0) + { + src_delete(drv->output_src); + drv->output_src = 0; + ERR("Could not created SRC object for output stream %d: %s\n", + error, src_strerror(error)); + } + } + if(drv->num_input_channels > 0) + { + drv->input_src = src_new(preferred_src_converter, drv->num_input_channels, &error); + if(error != 0) + { + src_delete(drv->input_src); + drv->input_src = 0; + ERR("Could not created SRC object for input stream %d: %s\n", + error, src_strerror(error)); + } + } + } +#endif +/* if((long) (*rate) != drv->jack_sample_rate) + { + TRACE("rate of %ld doesn't match jack sample rate of %ld, returning error\n", + *rate, drv->jack_sample_rate); + *rate = drv->jack_sample_rate; +#if JACK_CLOSE_HACK + JACK_CloseDevice(drv, TRUE); +#else + JACK_CloseDevice(drv); +#endif + releaseDriver(drv); + pthread_mutex_unlock(&device_mutex); + return ERR_RATE_MISMATCH; + } */ + + drv->allocated = TRUE; /* record that we opened this device */ + + DEBUG("sizeof(sample_t) == %d\n", sizeof(sample_t)); + + int periodSize = jack_get_buffer_size(drv->client); + int periods = 0; + /* FIXME: maybe we should keep different latency values for input vs output? */ + if(drv->num_output_channels > 0) + { + periods = jack_port_get_total_latency(drv->client, + drv->output_port[0]) / periodSize; + drv->latencyMS = periodSize * periods * 1000 / (drv->jack_sample_rate * + (drv->bits_per_channel / 8 * + drv->num_output_channels)); + } + else if(drv->num_input_channels > 0) + { + periods = jack_port_get_total_latency(drv->client, + drv->input_port[0]) / periodSize; + drv->latencyMS = + periodSize * periods * 1000 / (drv->jack_sample_rate * + (drv->bits_per_channel / 8 * + drv->num_input_channels)); + } + + TRACE("drv->latencyMS == %ldms\n", drv->latencyMS); + + *deviceID = drv->deviceID; /* set the deviceID for the caller */ + releaseDriver(drv); + pthread_mutex_unlock(&device_mutex); + return ERR_SUCCESS; /* success */ +} + +/* Close the jack device */ +//FIXME: add error handling in here at some point... +/* NOTE: return 0 for success, non-zero for failure */ +int +JACK_Close(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + + TRACE("deviceID(%d)\n", deviceID); + +#if JACK_CLOSE_HACK + JACK_CloseDevice(drv, TRUE); +#else + JACK_CloseDevice(drv); +#endif + + JACK_ResetFromDriver(drv); /* reset this device to a normal starting state */ + + pthread_mutex_lock(&device_mutex); + + /* free buffer memory */ + drv->callback_buffer1_size = 0; + if(drv->callback_buffer1) free(drv->callback_buffer1); + drv->callback_buffer1 = 0; + + drv->callback_buffer2_size = 0; + if(drv->callback_buffer2) free(drv->callback_buffer2); + drv->callback_buffer2 = 0; + + drv->rw_buffer1_size = 0; + if(drv->rw_buffer1) free(drv->rw_buffer1); + drv->rw_buffer1 = 0; + + if(drv->pPlayPtr) jack_ringbuffer_free(drv->pPlayPtr); + drv->pPlayPtr = 0; + + if(drv->pRecPtr) jack_ringbuffer_free(drv->pRecPtr); + drv->pRecPtr = 0; + + /* free the SRC objects */ +#ifdef HAVE_SAMPLERATE + if(drv->output_src) src_delete(drv->output_src); + drv->output_src = 0; + + if(drv->input_src) src_delete(drv->input_src); + drv->input_src = 0; +#endif + drv->allocated = FALSE; /* release this device */ + + pthread_mutex_unlock(&device_mutex); + + releaseDriver(drv); + + return 0; +} + +/* If we haven't already taken in the max allowed data then create a wave header */ +/* to package the audio data and attach the wave header to the end of the */ +/* linked list of wave headers */ +/* These wave headers will be peeled off as they are played by the callback routine */ +/* Return value is the number of bytes written */ +/* NOTE: this function takes the length of data to be written bytes */ +long +JACK_Write(int deviceID, unsigned char *data, unsigned long bytes) +{ + jack_driver_t *drv = getDriver(deviceID); + + long frames_free, frames; + + TIMER("start\n"); + + TRACE("deviceID(%d), bytes == %ld\n", deviceID, bytes); + + /* check and see that we have enough space for this audio */ + frames_free = + jack_ringbuffer_write_space(drv->pPlayPtr) / + drv->bytes_per_jack_output_frame; + frames = bytes / drv->bytes_per_output_frame; + TRACE("frames free == %ld, bytes = %lu\n", frames_free, bytes); + + TRACE("state = '%s'\n", DEBUGSTATE(drv->state)); + /* if we are currently STOPPED we should start playing now... + do this before the check for bytes == 0 since some clients like + to write 0 bytes the first time out */ + if(drv->state == STOPPED) + { + TRACE("currently STOPPED, transitioning to PLAYING\n"); + drv->state = PLAYING; + } + + /* handle the case where the user calls this routine with 0 bytes */ + if(bytes == 0 || frames_free < 1) + { + TRACE("no room left\n"); + TIMER("finish (nothing to do, buffer is full)\n"); + releaseDriver(drv); + return 0; /* indicate that we couldn't write any bytes */ + } + + frames = min(frames, frames_free); + long jack_bytes = frames * drv->bytes_per_jack_output_frame; + if(!ensure_buffer_size(&drv->rw_buffer1, &drv->rw_buffer1_size, jack_bytes)) + { + ERR("couldn't allocate enough space for the buffer\n"); + releaseDriver(drv); + return 0; + } + /* adjust bytes to be how many client bytes we're actually writing */ + bytes = frames * drv->bytes_per_output_frame; + + /* convert from client samples to jack samples + we have to tell it how many samples there are, which is frames * channels */ + switch (drv->bits_per_channel) + { + case 8: + sample_move_char_float((sample_t *) drv->rw_buffer1, (unsigned char *) data, + frames * drv->num_output_channels); + break; + case 16: + sample_move_short_float((sample_t *) drv->rw_buffer1, (short *) data, + frames * drv->num_output_channels); + break; + } + + DEBUG("ringbuffer read space = %d, write space = %d\n", + jack_ringbuffer_read_space(drv->pPlayPtr), + jack_ringbuffer_write_space(drv->pPlayPtr)); + + jack_ringbuffer_write(drv->pPlayPtr, drv->rw_buffer1, jack_bytes); + DEBUG("wrote %lu bytes, %lu jack_bytes\n", bytes, jack_bytes); + + DEBUG("ringbuffer read space = %d, write space = %d\n", + jack_ringbuffer_read_space(drv->pPlayPtr), + jack_ringbuffer_write_space(drv->pPlayPtr)); + + drv->client_bytes += bytes; /* update client_bytes */ + + TIMER("finish\n"); + + DEBUG("returning bytes written of %ld\n", bytes); + + releaseDriver(drv); + return bytes; /* return the number of bytes we wrote out */ +} + +long +JACK_Read(int deviceID, unsigned char *data, unsigned long bytes) +{ + jack_driver_t *drv = getDriver(deviceID); + + long frames_available, frames; + + TIMER("start\n"); + + TRACE("deviceID(%d), bytes == %ld\n", deviceID, bytes); + + /* find out if there's any room to write this data */ + frames_available = + jack_ringbuffer_read_space(drv->pRecPtr) / + drv->bytes_per_jack_input_frame; + frames = bytes / drv->bytes_per_input_frame; + DEBUG("frames available = %ld, bytes = %lu\n", frames_available, bytes); + + TRACE("state = '%s'\n", DEBUGSTATE(drv->state)); + /* if we are currently STOPPED we should start recording now... */ + if(drv->state == STOPPED) + { + TRACE("currently STOPPED, transitioning to PLAYING\n"); + drv->state = PLAYING; + } + + /* handle the case where the user calls this routine with 0 bytes */ + if(bytes == 0 || frames_available < 1) + { + TRACE("no bytes in buffer\n"); + + TIMER("finish (nothing to do)\n"); + releaseDriver(drv); + return 0; + } + + frames = min(frames, frames_available); + long jack_bytes = frames * drv->bytes_per_jack_input_frame; + if(!ensure_buffer_size(&drv->rw_buffer1, &drv->rw_buffer1_size, jack_bytes)) + { + ERR("couldn't allocate enough space for the buffer\n"); + releaseDriver(drv); + return 0; + } + + DEBUG("ringbuffer read space = %d, write space = %d\n", + jack_ringbuffer_read_space(drv->pRecPtr), + jack_ringbuffer_write_space(drv->pRecPtr)); + + jack_ringbuffer_read(drv->pRecPtr, drv->rw_buffer1, + frames * drv->bytes_per_jack_input_frame); + + DEBUG("ringbuffer read space = %d, write space = %d\n", + jack_ringbuffer_read_space(drv->pRecPtr), + jack_ringbuffer_write_space(drv->pRecPtr)); + + unsigned int i; + for(i = 0; i < drv->num_output_channels; i++) + { + /* apply volume to the floating value */ + if(drv->volumeEffectType == dbAttenuation) + { + /* assume the volume setting is dB of attenuation, a volume of 0 */ + /* is 0dB attenuation */ + float volume = powf(10.0, -((float) drv->volume[i]) / 20.0); + float_volume_effect((sample_t *) drv->rw_buffer1 + i, + frames, volume, drv->num_output_channels); + } else + { + float_volume_effect((sample_t *) drv->rw_buffer1 + i, frames, + ((float) drv->volume[i] / 100.0), + drv->num_output_channels); + } + } + + /* convert from jack samples to client samples + we have to tell it how many samples there are, which is frames * channels */ + switch (drv->bits_per_channel) + { + case 8: + sample_move_float_char((unsigned char *) data, (sample_t *) drv->rw_buffer1, + frames * drv->num_input_channels); + break; + case 16: + sample_move_float_short((short *) data, (sample_t *) drv->rw_buffer1, + frames * drv->num_input_channels); + break; + } + + TIMER("finish\n"); + + long read_bytes = frames * drv->bytes_per_input_frame; + + DEBUG("returning bytes read of %ld\n", bytes); + + releaseDriver(drv); + return read_bytes; +} + +/* return ERR_SUCCESS for success */ +static int +JACK_SetVolumeForChannelFromDriver(jack_driver_t * drv, + unsigned int channel, unsigned int volume) +{ + /* TODO?: maybe we should have different volume levels for input & output */ + /* ensure that we have the channel we are setting volume for */ + if(channel > (drv->num_output_channels - 1)) + return 1; + + if(volume > 100) + volume = 100; /* check for values in excess of max */ + + drv->volume[channel] = volume; + return ERR_SUCCESS; +} + +/* return ERR_SUCCESS for success */ +int +JACK_SetVolumeForChannel(int deviceID, unsigned int channel, + unsigned int volume) +{ + jack_driver_t *drv = getDriver(deviceID); + int retval = JACK_SetVolumeForChannelFromDriver(drv, channel, volume); + releaseDriver(drv); + return retval; +} + +/* Set the volume */ +/* return 0 for success */ +/* NOTE: we check for invalid volume values */ +int +JACK_SetAllVolume(int deviceID, unsigned int volume) +{ + jack_driver_t *drv = getDriver(deviceID); + unsigned int i; + + TRACE("deviceID(%d), setting volume of %d\n", deviceID, volume); + + for(i = 0; i < drv->num_output_channels; i++) + { + if(JACK_SetVolumeForChannelFromDriver(drv, i, volume) != ERR_SUCCESS) + { + releaseDriver(drv); + return 1; + } + } + + releaseDriver(drv); + return ERR_SUCCESS; +} + +/* Return the current volume in the inputted pointers */ +/* NOTE: we check for null pointers being passed in just in case */ +void +JACK_GetVolumeForChannel(int deviceID, unsigned int channel, + unsigned int *volume) +{ + jack_driver_t *drv = getDriver(deviceID); + + /* ensure that we have the channel we are getting volume for */ + if(channel > (drv->num_output_channels - 1)) + { + ERR("asking for channel index %d but we only have %ld channels\n", channel, drv->num_output_channels); + releaseDriver(drv); + return; + } + + if(volume) + *volume = drv->volume[channel]; + +#if VERBOSE_OUTPUT + if(volume) + { + TRACE("deviceID(%d), returning volume of %d for channel %d\n", + deviceID, *volume, channel); + } + else + { + TRACE("volume is null, can't dereference it\n"); + } +#endif + + releaseDriver(drv); +} + + +/* linear means 0 volume is silence, 100 is full volume */ +/* dbAttenuation means 0 volume is 0dB attenuation */ +/* Bio2jack defaults to linear */ +enum JACK_VOLUME_TYPE +JACK_SetVolumeEffectType(int deviceID, enum JACK_VOLUME_TYPE type) +{ + enum JACK_VOLUME_TYPE retval; + jack_driver_t *drv = getDriver(deviceID); + + TRACE("setting type of '%s'\n", + (type == dbAttenuation ? "dbAttenuation" : "linear")); + + retval = drv->volumeEffectType; + drv->volumeEffectType = type; + + releaseDriver(drv); + return retval; +} + + +/* Controls the state of the playback(playing, paused, ...) */ +int +JACK_SetState(int deviceID, enum status_enum state) +{ + jack_driver_t *drv = getDriver(deviceID); + + switch (state) + { + case PAUSED: + drv->state = PAUSED; + break; + case PLAYING: + drv->state = PLAYING; + break; + case STOPPED: + drv->state = STOPPED; + break; + default: + TRACE("unknown state of %d\n", state); + } + + TRACE("%s\n", DEBUGSTATE(drv->state)); + + releaseDriver(drv); + return 0; +} + +/* Retrieve the current state of the device */ +enum status_enum +JACK_GetState(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + enum status_enum return_val; + + return_val = drv->state; + releaseDriver(drv); + + TRACE("deviceID(%d), returning current state of %s\n", deviceID, + DEBUGSTATE(return_val)); + return return_val; +} + +/* Retrieve the number of bytes per second we are outputting */ +unsigned long +JACK_GetOutputBytesPerSecondFromDriver(jack_driver_t * drv) +{ + unsigned long return_val; + + return_val = drv->bytes_per_output_frame * drv->client_sample_rate; + +#if VERBOSE_OUTPUT + TRACE("deviceID(%d), return_val = %ld\n", drv->deviceID, return_val); +#endif + + return return_val; +} + +/* Retrieve the number of bytes per second we are outputting */ +unsigned long +JACK_GetOutputBytesPerSecond(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + unsigned long return_val; + + return_val = JACK_GetOutputBytesPerSecondFromDriver(drv); + releaseDriver(drv); + + return return_val; +} + +/* Retrieve the number of input bytes(from jack) per second we are outputting + to the user of bio2jack */ +static long +JACK_GetInputBytesPerSecondFromDriver(jack_driver_t * drv) +{ + long return_val; + + return_val = drv->bytes_per_input_frame * drv->client_sample_rate; +#if VERBOSE_OUTPUT + TRACE("drv->deviceID(%d), return_val = %ld\n", drv->deviceID, return_val); +#endif + + return return_val; +} + +/* Retrieve the number of input bytes(from jack) per second we are outputting + to the user of bio2jack */ +unsigned long +JACK_GetInputBytesPerSecond(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val = JACK_GetInputBytesPerSecondFromDriver(drv); + releaseDriver(drv); + +#if VERBOSE_OUTPUT + TRACE("deviceID(%d), return_val = %ld\n", deviceID, return_val); +#endif + + return return_val; +} + +/* Return the number of bytes we have buffered thus far for output */ +/* NOTE: convert from output bytes to input bytes in here */ +static long +JACK_GetBytesStoredFromDriver(jack_driver_t * drv) +{ + if(drv->pPlayPtr == 0 || drv->bytes_per_jack_output_frame == 0) + return 0; + + /* leave at least one frame in the buffer at all times to prevent underruns */ + long return_val = + jack_ringbuffer_read_space(drv->pPlayPtr) - drv->jack_buffer_size; + if(return_val <= 0) + { + return_val = 0; + } else + { + /* adjust from jack bytes to client bytes */ + return_val = + return_val / drv->bytes_per_jack_output_frame * + drv->bytes_per_output_frame; + } + + return return_val; +} + +/* An approximation of how many bytes we have to send out to jack */ +/* that is computed as if we were sending jack a continuous stream of */ +/* bytes rather than chunks during discrete callbacks. */ +/* Return the number of bytes we have buffered thus far for output */ +/* NOTE: convert from output bytes to input bytes in here */ +unsigned long +JACK_GetBytesStored(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long retval = JACK_GetBytesStoredFromDriver(drv); + releaseDriver(drv); + TRACE("deviceID(%d), retval = %ld\n", deviceID, retval); + return retval; +} + +static unsigned long +JACK_GetBytesFreeSpaceFromDriver(jack_driver_t * drv) +{ + if(drv->pPlayPtr == 0 || drv->bytes_per_jack_output_frame == 0) + return 0; + + /* leave at least one frame in the buffer at all times to prevent underruns */ + long return_val = jack_ringbuffer_write_space(drv->pPlayPtr) - drv->jack_buffer_size; + if(return_val <= 0) + { + return_val = 0; + } else + { + /* adjust from jack bytes to client bytes */ + return_val = + return_val / drv->bytes_per_jack_output_frame * + drv->bytes_per_output_frame; + } + + return return_val; +} + +/* Return the number of bytes we can write to the device */ +unsigned long +JACK_GetBytesFreeSpace(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + unsigned long return_val; + + return_val = JACK_GetBytesFreeSpaceFromDriver(drv); + releaseDriver(drv); + + TRACE("deviceID(%d), retval == %ld\n", deviceID, return_val); + + return return_val; +} + +/* bytes of space used in the input buffer */ +unsigned long +JACK_GetBytesUsedSpace(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val; + + if(drv->pRecPtr == 0 || drv->bytes_per_jack_input_frame == 0) + { + return_val = 0; + } else + { + /* adjust from jack bytes to client bytes */ + return_val = + jack_ringbuffer_read_space(drv->pRecPtr) / + drv->bytes_per_jack_input_frame * drv->bytes_per_input_frame; + } + + releaseDriver(drv); + + if(return_val < 0) + return_val = 0; + TRACE("deviceID(%d), retval == %ld\n", deviceID, return_val); + + return return_val; +} + +/* Get the current position of the driver, either in bytes or */ +/* in milliseconds */ +/* NOTE: this is position relative to input bytes, output bytes may differ greatly due to + input vs. output channel count */ +static long +JACK_GetPositionFromDriver(jack_driver_t * drv, enum pos_enum position, + int type) +{ + long return_val = 0; + struct timeval now; + long elapsedMS; + double sec2msFactor = 1000; + + char *type_str = "UNKNOWN type"; + + /* if we are reset we should return a position of 0 */ + if(drv->state == RESET) + { + TRACE("we are currently RESET, returning 0\n"); + return 0; + } + + if(type == WRITTEN) + { + type_str = "WRITTEN"; + return_val = drv->client_bytes; + } else if(type == WRITTEN_TO_JACK) + { + type_str = "WRITTEN_TO_JACK"; + return_val = drv->written_client_bytes; + } else if(type == PLAYED) /* account for the elapsed time for the played_bytes */ + { + type_str = "PLAYED"; + return_val = drv->played_client_bytes; + gettimeofday(&now, 0); + + elapsedMS = TimeValDifference(&drv->previousTime, &now); /* find the elapsed milliseconds since last JACK_Callback() */ + + TRACE("elapsedMS since last callback is '%ld'\n", elapsedMS); + + /* account for the bytes played since the last JACK_Callback() */ + /* NOTE: [Xms * (Bytes/Sec)] * (1 sec/1,000ms) */ + /* NOTE: don't do any compensation if no data has been sent to jack since the last callback */ + /* as this would result a bogus computed result */ + if(drv->clientBytesInJack != 0) + { + return_val += (long) ((double) elapsedMS * + ((double) JACK_GetOutputBytesPerSecondFromDriver(drv) / + sec2msFactor)); + } else + { + TRACE("clientBytesInJack == 0\n"); + } + } + + /* add on the offset */ + return_val += drv->position_byte_offset; + + /* convert byte position to milliseconds value if necessary */ + if(position == MILLISECONDS) + { + if(JACK_GetOutputBytesPerSecondFromDriver(drv) != 0) + { + return_val = (long) (((double) return_val / + (double) JACK_GetOutputBytesPerSecondFromDriver(drv)) * + (double) sec2msFactor); + } else + { + return_val = 0; + } + } + + TRACE("drv->deviceID(%d), type(%s), return_val = %ld\n", drv->deviceID, + type_str, return_val); + + return return_val; +} + +/* Get the current position of the driver, either in bytes or */ +/* in milliseconds */ +/* NOTE: this is position relative to input bytes, output bytes may differ greatly due to input vs. output channel count */ +long +JACK_GetPosition(int deviceID, enum pos_enum position, int type) +{ + jack_driver_t *drv = getDriver(deviceID); + long retval = JACK_GetPositionFromDriver(drv, position, type); + releaseDriver(drv); + TRACE("retval == %ld\n", retval); + return retval; +} + +// Set position always applies to written bytes +// NOTE: we must apply this instantly because if we pass this as a message +// to the callback we risk the user sending us audio data in the mean time +// and there is no need to send this as a message, we don't modify any +// internal variables +void +JACK_SetPositionFromDriver(jack_driver_t * drv, enum pos_enum position, + long value) +{ + double sec2msFactor = 1000; +#if TRACE_ENABLE + long input_value = value; +#endif + + /* convert the incoming value from milliseconds into bytes */ + if(position == MILLISECONDS) + { + value = (long) (((double) value * + (double) JACK_GetOutputBytesPerSecondFromDriver(drv)) / + sec2msFactor); + } + + /* ensure that if the user asks for the position */ + /* they will at this instant get the correct position */ + drv->position_byte_offset = value - drv->client_bytes; + + TRACE("deviceID(%d) input_value of %ld %s, new value of %ld, setting position_byte_offset to %ld\n", + drv->deviceID, input_value, (position == MILLISECONDS) ? "ms" : "bytes", + value, drv->position_byte_offset); +} + +// Set position always applies to written bytes +// NOTE: we must apply this instantly because if we pass this as a message +// to the callback we risk the user sending us audio data in the mean time +// and there is no need to send this as a message, we don't modify any +// internal variables +void +JACK_SetPosition(int deviceID, enum pos_enum position, long value) +{ + jack_driver_t *drv = getDriver(deviceID); + JACK_SetPositionFromDriver(drv, position, value); + releaseDriver(drv); + + TRACE("deviceID(%d) value of %ld\n", drv->deviceID, value); +} + +/* Return the number of bytes per frame, or (output_channels * bits_per_channel) / 8 */ +unsigned long +JACK_GetBytesPerOutputFrame(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val = drv->bytes_per_output_frame; + releaseDriver(drv); + TRACE("deviceID(%d), return_val = %ld\n", deviceID, return_val); + return return_val; +} + +/* Return the number of bytes per frame, or (input_channels * bits_per_channel) / 8 */ +unsigned long +JACK_GetBytesPerInputFrame(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val = drv->bytes_per_input_frame; + releaseDriver(drv); + TRACE("deviceID(%d), return_val = %ld\n", deviceID, return_val); + return return_val; +} + +/* Return the number of output bytes we buffer max */ +long +JACK_GetMaxOutputBufferedBytes(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val; + + if(drv->pPlayPtr == 0 || drv->bytes_per_jack_output_frame == 0) return_val = 0; + + /* adjust from jack bytes to client bytes */ + return_val = + (jack_ringbuffer_read_space(drv->pPlayPtr) + + jack_ringbuffer_write_space(drv->pPlayPtr)) / + drv->bytes_per_jack_output_frame * drv->bytes_per_output_frame; + + releaseDriver(drv); + + TRACE("return_val = %ld\n", return_val); + + return return_val; +} + +/* Return the number of input bytes we buffer max */ +long +JACK_GetMaxInputBufferedBytes(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val; + + if(drv->pRecPtr == 0 || drv->bytes_per_jack_input_frame == 0) return_val = 0; + + /* adjust from jack bytes to client bytes */ + return_val = + (jack_ringbuffer_read_space(drv->pRecPtr) + + jack_ringbuffer_write_space(drv->pRecPtr)) / + drv->bytes_per_jack_input_frame * drv->bytes_per_input_frame; + + releaseDriver(drv); + + TRACE("return_val = %ld\n", return_val); + + return return_val; +} + +/* Get the number of output channels */ +int +JACK_GetNumOutputChannels(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + int return_val = drv->num_output_channels; + releaseDriver(drv); + TRACE("getting num_output_channels of %d\n", return_val); + return return_val; +} + +/* Get the number of input channels */ +int +JACK_GetNumInputChannels(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + int return_val = drv->num_input_channels; + releaseDriver(drv); + TRACE("getting num_input_channels of %d\n", return_val); + return return_val; +} + +/* Get the number of samples per second, the sample rate */ +long +JACK_GetSampleRate(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + int return_val = drv->client_sample_rate; + releaseDriver(drv); + TRACE("getting sample_rate of %d\n", return_val); + return return_val; +} + +void +JACK_CleanupDriver(jack_driver_t * drv) +{ + TRACE("\n"); + /* things that need to be reset both in JACK_Init & JACK_CloseDevice */ + drv->client = 0; + drv->in_use = FALSE; + drv->state = CLOSED; + drv->jack_sample_rate = 0; + drv->output_sample_rate_ratio = 1.0; + drv->input_sample_rate_ratio = 1.0; + drv->jackd_died = FALSE; + gettimeofday(&drv->previousTime, 0); /* record the current time */ + gettimeofday(&drv->last_reconnect_attempt, 0); +} + +/* Initialize the jack porting library to a clean state */ +void +JACK_Init(void) +{ + jack_driver_t *drv; + int x, y; + + if(init_done) + { + TRACE("not initing twice\n"); + return; + } + + init_done = 1; + + TRACE("\n"); + + pthread_mutex_lock(&device_mutex); + + /* initialize the device structures */ + for(x = 0; x < MAX_OUTDEVICES; x++) + { + drv = &outDev[x]; + + pthread_mutex_init(&drv->mutex, NULL); + + getDriver(x); + + memset(drv, 0, sizeof(jack_driver_t)); + drv->volumeEffectType = linear; + drv->deviceID = x; + + for(y = 0; y < MAX_OUTPUT_PORTS; y++) /* make all volume 25% as a default */ + drv->volume[y] = 25; + + JACK_CleanupDriver(drv); + JACK_ResetFromDriver(drv); + releaseDriver(drv); + } + + client_name = 0; /* initialize the name to null */ + do_sample_rate_conversion = FALSE; /* default to on */ + //@ veejay: default to false! + JACK_SetClientName("bio2jack"); + + pthread_mutex_unlock(&device_mutex); + + TRACE("finished\n"); +} + +/* Get the latency, in frames, of jack */ +long +JACK_GetJackOutputLatency(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val = 0; + + if(drv->client && drv->num_output_channels) + return_val = jack_port_get_total_latency(drv->client, drv->output_port[0]); + + TRACE("got latency of %ld frames\n", return_val); + + releaseDriver(drv); + return return_val; +} + +/* Get the latency, in frames, of jack */ +long +JACK_GetJackInputLatency(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val = 0; + + if(drv->client && drv->num_input_channels) + return_val = jack_port_get_total_latency(drv->client, drv->input_port[0]); + + TRACE("got latency of %ld frames\n", return_val); + + releaseDriver(drv); + return return_val; +} + +/* bytes that jack requests during each callback */ +unsigned long +JACK_GetJackBufferedBytes(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val; + + if(drv->bytes_per_jack_output_frame == 0) + { + return_val = 0; + } else + { + /* adjust from jack bytes to client bytes */ + return_val = + drv->jack_buffer_size / drv->bytes_per_jack_output_frame * + drv->bytes_per_output_frame * drv->num_output_channels; + } + + releaseDriver(drv); + return return_val; +} + +/* value = TRUE, perform sample rate conversion */ +void +JACK_DoSampleRateConversion(bool value) +{ +#ifdef HAVE_SAMPLERATE + do_sample_rate_conversion = value; +#endif +} + +/* FIXME: put the filename of the resample library header file with the decoders in here */ +/* consider mapping them in the bio2jack.h header file since its useless to the user unless */ +/* they can figure out wtf the settings on */ +void +JACK_SetSampleRateConversionFunction(int converter) +{ +#ifdef HAVE_SAMPLERATE + preferred_src_converter = converter; +#endif +} + +/* set the client name that will be reported to jack when we open a */ +/* connection via JACK_OpenDevice() */ +void +JACK_SetClientName(char *name) +{ + if(name) + { + if(client_name) free(client_name); + + /* jack_client_name_size() is the max length of a client name, including + the terminating null. */ + int size = strlen(name) + 1; /* take into account the terminating null */ + if(size > jack_client_name_size()) + size = jack_client_name_size(); + + client_name = malloc(size); + if(client_name) + snprintf(client_name, size, "%s", name); + else + ERR("unable to allocate %d bytes for client_name\n", size); + } +} + +long JACK_OutputStatus(int deviceID,long int *sec, long int *usec) +{ + jack_driver_t *this = &outDev[deviceID]; + *sec = (long int) this->previousTime.tv_sec; + *usec = (long int) this->previousTime.tv_usec; + return (this->num_ticks * this->chunk_size); +} + + + +void +JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode) +{ + port_connection_mode = mode; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/bio2jack/bio2jack.h b/branches/V-1.5.3/veejay-server/bio2jack/bio2jack.h new file mode 100644 index 00000000..7a295681 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/bio2jack/bio2jack.h @@ -0,0 +1,147 @@ +/* + * Copyright 2003-2004 Chris Morgan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _H_JACK_OUT_H +#define _H_JACK_OUT_H + +#include + +#ifdef __cplusplus +extern "C" { +#else +#define bool long +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define ERR_SUCCESS 0 +#define ERR_OPENING_JACK 1 +#define ERR_RATE_MISMATCH 2 +#define ERR_BYTES_PER_OUTPUT_FRAME_INVALID 3 +#define ERR_BYTES_PER_INPUT_FRAME_INVALID 4 +#define ERR_TOO_MANY_OUTPUT_CHANNELS 5 +#define ERR_PORT_NAME_OUTPUT_CHANNEL_MISMATCH 6 +#define ERR_PORT_NOT_FOUND 7 +#define ERR_TOO_MANY_INPUT_CHANNELS 8 +#define ERR_PORT_NAME_INPUT_CHANNEL_MISMATCH 9 + +enum status_enum { PLAYING, PAUSED, STOPPED, CLOSED, RESET }; +enum pos_enum { BYTES, MILLISECONDS }; + +#define PLAYED 1 /* played out of the speakers(estimated value but should be close */ +#define WRITTEN_TO_JACK 2 /* amount written out to jack */ +#define WRITTEN 3 /* amount written to the bio2jack device */ + +/**********************/ +/* External functions */ +void JACK_Init(void); /* call this before any other bio2jack calls */ +void JACK_DoSampleRateConversion(bool value); /* whether the next device that's Open()d should do + sample rate conversion if necessary */ +void JACK_SetSampleRateConversionFunction(int converter); /* which SRC converter function should be used + for the next Open()d device */ +int JACK_Open(int *deviceID, unsigned int bits_per_sample, unsigned long *rate, int channels); /* Note: defaults to 0 input channels + if you need input (record) use OpenEx + instead */ +int JACK_OpenEx(int *deviceID, unsigned int bits_per_channel, + unsigned long *rate, + unsigned int input_channels, unsigned int output_channels, + const char **jack_port_name, unsigned int jack_port_name_count, + unsigned long jack_port_flags); +int JACK_Close(int deviceID); /* return 0 for success */ +void JACK_Reset(int deviceID); /* free all buffered data and reset several values in the device */ +long JACK_Write(int deviceID, unsigned char *data, unsigned long bytes); /* returns the number of bytes written */ +long JACK_Read(int deviceID, unsigned char *data, unsigned long bytes); /* returns the number of bytes read */ + +/* state setting values */ +/* set/get the written/played/buffered value based on a byte or millisecond input value */ +long JACK_GetPosition(int deviceID, enum pos_enum position, int type); +void JACK_SetPosition(int deviceID, enum pos_enum position, long value); + +long JACK_GetJackLatency(int deviceID); /* deprectated, you probably want JACK_GetJackOutputLatency */ +long JACK_GetJackOutputLatency(int deviceID); /* return the output latency in frames */ +long JACK_GetJackInputLatency(int deviceID); /* return the input latency in frames */ + +int JACK_SetState(int deviceID, enum status_enum state); /* playing, paused, stopped */ +enum status_enum JACK_GetState(int deviceID); + +long JACK_GetMaxOutputBufferedBytes(int deviceID); +long JACK_GetMaxInputBufferedBytes(int deviceID); + +/* bytes that jack requests during each callback */ +unsigned long JACK_GetJackBufferedBytes(int deviceID); + +/* Properties of the jack driver */ + +/* linear means 0 volume is silence, 100 is full volume */ +/* dbAttenuation means 0 volume is 0dB attenuation */ +/* Bio2jack defaults to linear */ +/* Note: volume controls only effect output channels for now */ +enum JACK_VOLUME_TYPE { linear, dbAttenuation }; +enum JACK_VOLUME_TYPE JACK_SetVolumeEffectType(int deviceID, + enum JACK_VOLUME_TYPE type); + +int JACK_SetAllVolume(int deviceID, unsigned int volume); /* returns 0 on success */ +int JACK_SetVolumeForChannel(int deviceID, unsigned int channel, unsigned int volume); +void JACK_GetVolumeForChannel(int deviceID, unsigned int channel, unsigned int *volume); + + +unsigned long JACK_GetOutputBytesPerSecond(int deviceID); /* bytes_per_output_frame * sample_rate */ +unsigned long JACK_GetInputBytesPerSecond(int deviceID); /* bytes_per_input_frame * sample_rate */ +unsigned long JACK_GetBytesStored(int deviceID); /* bytes currently buffered in the output buffer */ +unsigned long JACK_GetBytesFreeSpace(int deviceID); /* bytes of free space in the output buffer */ +unsigned long JACK_GetBytesUsedSpace(int deviceID); /* bytes of space used in the input buffer */ +unsigned long JACK_GetBytesPerOutputFrame(int deviceID); +unsigned long JACK_GetBytesPerInputFrame(int deviceID); + +/* Note: these will probably be removed in a future release */ +int JACK_GetNumInputChannels(int deviceID); +int JACK_GetNumOutputChannels(int deviceID); + +long JACK_GetSampleRate(int deviceID); /* samples per second */ + +void JACK_SetClientName(char *name); /* sets the name that bio2jack will use when + creating a new jack client. name_%pid%_%deviceID%%counter% + will be used + NOTE: this defaults to name = bio2jack + NOTE: we limit the size of the client name to + jack_client_name_size() */ + +enum JACK_PORT_CONNECTION_MODE +{ + CONNECT_ALL, /* connect to all avaliable ports */ + CONNECT_OUTPUT, /* connect only to the ports we need for output */ + CONNECT_NONE /* don't connect to any ports */ +}; + +/* set the mode for port connections */ +/* defaults to CONNECT_ALL */ +void JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode); + +long JACK_OutputStatus(int deviceID,long int *sec, long int *usec); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef JACK_OUT_H */ diff --git a/branches/V-1.5.3/veejay-server/build.sh b/branches/V-1.5.3/veejay-server/build.sh new file mode 100644 index 00000000..0b5ee7de --- /dev/null +++ b/branches/V-1.5.3/veejay-server/build.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# veejay build script + +SCRIPT=`whereis script|cut -d ':' -f1` +RUNSCRIPT="-a -c" +FILE="veejay.build.log" +if [ -n "$SCRIPT" ]; then + echo "Enabling typescript for logging"; +fi + +if [ -f autogen.sh ]; then + echo "Bootstrapping ..." + $SCRIPT $RUNSCRIPT./autogen.sh $FILE > /dev/null +fi + +PKGCONFIG=`echo $PKG_CONFIG_PATH` +if [ ! -n "$PKGCONFIG" ]; then + echo "Guess that your .pc files are in /usr/lib/pkgconfig and /usr/local/pkgconfig" + export PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/local/lib/pkgconfig +fi + +if [ -f configure ]; then + echo "Configuring ..." + $SCRIPT $RUNSCRIPT"./configure --enable-debug" $FILE > /dev/null + RET=$? + if [ $RET = 0 ]; then + tail -n38 $FILE + echo "Building veejay, please wait." + $SCRIPT $RUNSCRIPT make $FILE > /dev/null + RET=$? + if [ $RET = 0 ]; then + echo "Veejay build completed. You can continue with 'make install'" + echo "" + echo "Open another Terminal and type 'veejay myvideo.avi" + echo "Open another Terminal and type 'reloaded'" + exit + else + echo "Build error in Make, please send $FILE to the Veejay Group" + echo "http://groups.google.com/group/veejay-discussion/topics" + exit + fi + else + echo "Please run ./configure manually to see which dependencies are missing." + echo "On ubuntu/debian systems you will most likely need to install the *-dev packages" + echo "According to http://www.veejayhq.net/2009/01/veejay-howto-compile/ you could use:" + echo "$ sudo apt-get install build-essential autogen autotools-dev autoconf automake1.8 libtool libsdl1.2-dev \ +libjack0.100.0-dev libquicktime-dev libxml2-dev libglade2-dev libgtk2.0-dev libmjpegtools-dev \ +libavcodec-dev libjpeg62-dev libavformat-dev libswscale-dev libdv-dev xorg-dev libasound-dev \ +libsamplerate-dev +" + exit + fi +fi diff --git a/branches/V-1.5.3/veejay-server/buildinfo.sh b/branches/V-1.5.3/veejay-server/buildinfo.sh new file mode 100755 index 00000000..7163fd4f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/buildinfo.sh @@ -0,0 +1,17 @@ +#!/bin/sh +HOST=`uname -n` +KERNEL=`uname -r` +MACHINE=`uname -m` +OS=`uname -s` +DATE=`date -u "+%Y-%m-%d %H:%M:%S"` +cat <build.h +/* +* buildinfo.h +* Do not edit this file, it is auto-generated. +*/ +#define BUILD_HOSTNAME "${HOST}" +#define BUILD_KERNEL "${KERNEL}" +#define BUILD_MACHINE "${MACHINE}" +#define BUILD_OS "${OS}" +#define BUILD_DATE "${DATE} UTC" +EOF diff --git a/branches/V-1.5.3/veejay-server/configure.ac b/branches/V-1.5.3/veejay-server/configure.ac new file mode 100644 index 00000000..ac5884ef --- /dev/null +++ b/branches/V-1.5.3/veejay-server/configure.ac @@ -0,0 +1,1073 @@ +dnl Process this file with autoconf to produce a configure script. +dnl AC_INIT +AC_INIT([veejay],[1.5.3],[veejay-users@lists.sourceforge.net]) +AC_PREREQ(2.57) +AC_CONFIG_SRCDIR([veejay/veejay.c]) + +VEEJAY_MAJOR_VERSION=1 +VEEJAY_MINOR_VERSION=5 +VEEJAY_MICRO_VERSION=3 +VEEJAY_VERSION=$VEEJAY_MAJOR_VERSION.$VEEJAY_MINOR_VERSION.$VEEJAY_MICRO_VERSION +VEEJAY_CODENAME="Veejay Classic - build $VEEJAY_MINOR_VERSION $VEEJAY_MICRO_VERSION" +AC_CONFIG_HEADERS([config.h]) +dnl AX_CONFIG_PREFIXED_HEADER([veejay-config.h], [VEEJAY], [config.h]) + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE([1.7]) +AM_MAINTAINER_MODE +AM_INIT_AUTOMAKE([dist-bzip2]) + +AC_DEFINE(VEEJAY,1,[Building Veejay]) +AC_DEFINE(HAVE_CONFIG_H,1,[Include config.h]) +# libtool versioning +LT_RELEASE=$VEEJAY_MAJOR_VERSION.$VEEJAY_MINOR_VERSION +LT_CURRENT=$VEEJAY_MAJOR_VERSION +LT_REVISION=$VEEJAY_MINOR_VERSION +LT_AGE=$VEEJAY_MAJOR_VERSION +AC_SUBST(LT_RELEASE) +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +AC_SUBST(LT_AGE) +dnl ********************************************************************** +dnl Options + +AC_CONFIG_MACRO_DIR([m4]) + +dnl kill CFLAGS +CFLAGS="" +AC_ARG_ENABLE(strict, + AC_HELP_STRING([--enable-strict], + [Compile in paranoia assertion checking])) +AC_ARG_ENABLE(debug, + AC_HELP_STRING([--enable-debug], + [Compile in debugging information])) +AC_ARG_ENABLE(profile, + AC_HELP_STRING([--enable-profiling], + [Compile in profiling information])) +AC_ARG_ENABLE(compile-warnings, + AC_HELP_STRING([--enable-compile-warnings], + [Turn on compiler warnings.])) +AC_ARG_ENABLE(warnings_as_errors, + AC_HELP_STRING([--enable-warnings_as_errors], + [Compiler warnings are errors.])) +AC_ARG_ENABLE(simd-accel, + AC_HELP_STRING([--enable-simd-accel], + [use SIMD multimedia instructions such as MMX, AltiVec, etc.if possible])) + +AC_ARG_WITH(extra-cflags, + AC_HELP_STRING([--with-extra-cflags=flags], + [Options to be added to CFLAGS (optional)])) +AC_ARG_WITH(libdv, + AC_HELP_STRING([--without-libdv], [Do not use libdv.]), + [], [with_libdv=yes]) + +AC_ARG_WITH(pixbuf, + AC_HELP_STRING([--without-pixbuf], [Do not use GDK pixbuf]), + [], [with_pixbuf=yes]) + +AC_ARG_WITH(playthread, + AC_HELP_STRING([--without-playthread], [Do not use playback thread]), + [], [with_playthread=yes]) + +AC_ARG_WITH(directfb, + AC_HELP_STRING([--without-directfb], [Do not use DirectFB.]), + [], [with_directfb=yes]) +AC_ARG_WITH(sdl, + AC_HELP_STRING([--without-sdl], [Do not use SDL.]), + [], [with_sdl=yes]) +AC_ARG_WITH(jack, + AC_HELP_STRING([--without-jack], [Do not use jack.]), + [], [with_jack=yes]) +AC_ARG_WITH(samplerate, + AC_HELP_STRING([--without-samplerate], [Do not use libsamplerate.]), + [], [with_samplerate=yes]) + +AC_ARG_WITH(v4l, + AC_HELP_STRING([--without-v4l], [Do not use video4linux]), + [], [with_v4l=yes]) +AC_ARG_WITH(xml2, + AC_HELP_STRING([--without-xml2], [Do not use the XML library for Gnome]), + [], [with_xml2=yes]) + +AC_ARG_WITH(jpeg, + AC_HELP_STRING([--without-jpeg], [Do not JPEG support]), + [], [with_libjpeg=yes]) + +AC_ARG_WITH(jpeg-mmx, + AC_HELP_STRING([--with-jpegmmx=PFX], + [Prefix where jpeg-mmx is installed (optional).])) + +AC_ARG_WITH(unicap, AC_HELP_STRING([--without-unicap], [Do not use unicap]), + [], [with_unicap=yes]) + + +AC_GNU_SOURCE + +dnl Initialize libtool +AC_PROG_LIBTOOL + +dnl Checks for programs. +AC_PROG_AWK +AC_PROG_CC +AM_PROG_CC_STDC +AC_PROG_YACC +AM_PROG_LEX +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_LN_S +AC_C_BIGENDIAN +AC_C_CONST +AC_C_INLINE +AC_SYS_LARGEFILE + +dnl configure AS and ASFLAGS... +AM_PROG_AS + +AC_CHECK_HEADERS([fenv.h stdint.h inttypes.h sys/types.h alloca.h]) + +dnl AX_PREFIXED_DEFINE([VEEJAY], [HAVE_STDINT_H]) +dnl AX_PREFIXED_DEFINE([VEEJAY], [HAVE_INTTYPES_H]) + +AC_CHECK_FUNCS([posix_memalign memalign fmax lround pow bzero gettimeofday memset mmap strndup strstr strncasecmp]) +AC_CHECK_FUNCS([sched_get_priority_max]) +AC_CHECK_FUNCS([select socket getpagesize memcpy]) + +AC_CHECK_FUNC(getopt_long, + [AC_DEFINE(HAVE_GETOPT_LONG, 1, [long getopt support])], + [ # FreeBSD and BSD/OS have a gnugetopt library for this: + AC_CHECK_LIB([gnugetopt], [getopt_long], + [AC_DEFINE(HAVE_GETOPT_LONG, 1, + [long getopt support]) + LIBGETOPT_LIB="-lgnugetopt"]) + ]) + +AC_CHECK_SIZEOF([int]) +AC_CHECK_SIZEOF([long int]) +AC_CHECK_SIZEOF([size_t]) +AC_CHECK_SIZEOF([float]) + + + +AC_SUBST(LIBGETOPT_LIB) + +AC_TYPE_SIGNAL + +AC_MSG_NOTICE([The host is $host $host_cpu $host_vendor $host_os .]) + + + +dnl e_xdpms=no +dnl ACCHECK_HEADER(X11/extensions/dpms.h, +dnl AC_DEFINE( HAVE_XDPMS, 1, [If we have xpdms] ) have_xdpms=yes,, +dnl []) + +dnl ********************************************************************* +dnl Test whether we're linux or not. If so, define HAVE_V4L and build the +dnl video4linux/hardware dependent tools. Else, undefine HAVE_V4L +have_v4l=false +have_linux=false +have_darwin=false +case $host in + *-*-linux*) + AC_CHECK_HEADER(linux/version.h, + [have_linux=true + AC_DEFINE(HAVE_LINUX,,[Linux platform]) + ], + [AC_MSG_ERROR([version.h not found - please install the linux kernel headers]) + ]) + LIBM_LIBS="-lm" + ;; + *-apple-darwin*) + AC_DEFINE(HAVE_DARWIN,,[MAC OS X Darin]) + dnl OS-X/Darwin needs no-cpp-precomp + CFLAGS="$CFLAGS -no-cpp-precomp" + have_darwin=true + LIBM_LIBS="" + ;; + *) + AC_MSG_WARN([Alien platform - Good Luck!]) + LIBM_LIBS="" + ;; +esac + + +dnl ====== check for PKG_CONFIG_PATH +if test x"$PKG_CONFIG_PATH" = x ; then + AC_MSG_NOTICE([The PKG_CONFIG_PATH variable was not set]) + AC_MSG_NOTICE([You should set it to the directories that contain the .pc files]) + AC_MSG_ERROR([Abort]) +fi + +AC_MSG_CHECKING(whether to compile in debugging information) +debugCFLAGS="" +if test "x$enable_debug" = "xyes" ; then + debugCFLAGS="-g" + CFLAGS="$CFLAGS $debugCFLAGS" + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +AC_MSG_CHECKING(whether to compile in profiling information) +if test "x$enable_profiling" = "xyes" ; then + debugCFLAGS="$debugCFLAGS -fprofile-arcs -ftest-coverage" + DEBUGLIBS="-lgcov" + AC_SUBST(DEBUGLIBS) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +AC_MSG_CHECKING(whether to compile in assertion checking) +if test "x$enable_strict" = "xyes" ; then + debugCFLAGS="$debugCFLAGS -DSTRICT_CHECKING" + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + + +dnl ******************************************************************** +dnl Test for MMX support if an IA32 platform. If on a PPC then look for +dnl Altivec support. For the IA32 platform see if gcc understands inline +dnl MMX instructions. +dnl +dnl TODO: host = non intel, target = intel do the checks also? +dnl Remember we are checking that the toolchain can generate the +dnl code, not whether the host can execute the code, thats done +dnl at run time with the exception of the SSE code. + + +have_asm_nasm=false +have_asm_mmx=false +have_asm_sse=false +have_asm_sse2=false +have_asm_mmx2=false +have_asm_3dnow=false +have_cmov=false +have_x86cpu=false +have_x86_64cpu=false +have_altivec=false +have_mips=false +have_ppccpu=false +have_ps2=false + +OP_CFLAGS="" +YUVCFLAGS="-fif-conversion" + +AC_MSG_CHECKING([Architecture]) +case $host_cpu in + i[[3-7]]86) + AC_DEFINE(HAVE_X86CPU,, [Compiling for x86 architecture CPU]) + AC_DEFINE(ARCH_X86,1,[Compiling for x86 architecture]) + have_x86cpu=true + + PROGRAM_NOPIC="-fno-PIC" + + if test "x$enable_debug" != "xyes" ; then + OP_CFLAGS="-O3" + fi + + AC_SUBST(OP_CFLAGS) + AC_SUBST(YUVCFLAGS) + + dnl If the host is pentium, align on double word boundary + case $host_cpu in + i686) + CFLAGS="$CFLAGS" + ;; + *) + ;; + esac + + ;; + x86_64*|k8-*) + AC_DEFINE(HAVE_X86_CPU,, [Compiling for x86-64 architecture CPU]) + AC_DEFINE(ARCH_X86_64,1, [Compiling for x86-64 architecture CPU]) + have_x86cpu=true + have_x86_64cpu=true + CFLAGS="$CFLAGS -fPIC -DPIC" + ;; + powerpc | powerpc64) + AC_DEFINE(HAVE_PPCCPU,, [Compiling for PowerPC CPU]) + AC_DEFINE(ARCH_PPC,,[Compiling for PowerPC]) + have_ppccpu=true + + case $host in + *-apple-darwin*) + PROGRAM_NOPIC="-mdynamic-no-pic" # dynamic-no-pic is an Apple gcc option +dnl CFLAGS="$CFLAGS -no-cpp-precomp" + + ;; + *) + PROGRAM_NOPIC="" + ;; + esac + ;; + mips | mipsel) + AC_DEFINE(ARCH_MIPS,,[Compiling for MIPS CPU]) + AC_DEFINE(HAVE_MIPS,,[Compiling for MIPS CPU]) + have_mips=true + AC_MSG_CHECKING([if we are compiling on playstation2 hardware]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], + [[#include + #include + ]])], + [have_ps2=true], + [have_ps2=false]) + + if test x$have_ps2 = xtrue ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PS2,,[Compile for playstation2]) + else + AC_MSG_RESULT(no) + fi + + ;; + *) + AC_MSG_RESULT([unknown]) + ;; +esac + +dnl This flag is used for PROGRAMS not SHARED LIBRARIES. PIC code is required +dnl for shared libraries but is slower than non-pic code. Compute bound +dnl programs such as yuvdenoise and y4mspatialfilter can use this flag by +dnl simply adding programname_CFLAGS=@PROGRAM_NOPIC@ to the Makefile.am + +AC_SUBST(PROGRAM_NOPIC) + +if test x$have_x86cpu = xtrue +then + AC_CACHE_CHECK(for MMX on processor(s), ac_cv_flag_mmx, [ + if grep "^flags.* mmx" /proc/cpuinfo > /dev/null; then + ac_cv_flag_mmx=yes + else + ac_cv_flag_mmx=no + fi + ]) + + if test $ac_cv_flag_mmx = yes; then + AC_DEFINE(HAVE_ASM_MMX,,[Compiling in MMX support]) + AC_DEFINE(HAVE_MMX,,[Compiling in MMX support]) + have_asm_mmx=true + fi + + AC_CACHE_CHECK(for SSE on processor(s), ac_cv_flag_sse, [ + if grep "^flags.* sse" /proc/cpuinfo > /dev/null; then + ac_cv_flag_sse=yes + else + ac_cv_flag_sse=no + fi + ]) + + if test $ac_cv_flag_sse = yes; then + AC_DEFINE(HAVE_ASM_SSE,,[Compiling in SSE support]) + AC_DEFINE(HAVE_SSE,,[Compiling in SSE support]) + have_asm_sse=true + fi + + + dnl check for sse2 + AC_CACHE_CHECK(for SSE2 on processor(s), ac_cv_flag_sse2, [ + if grep "^flags.* sse2" /proc/cpuinfo > /dev/null; then + ac_cv_flag_sse2=yes + else + ac_cv_flag_sse2=no + fi + ]) + + if test $ac_cv_flag_sse2 = yes; then + AC_DEFINE(HAVE_ASM_SSE2,,[Compiling in SSE2 support]) + AC_DEFINE(HAVE_SSE2,,[Compiling in SSE2 support]) + have_asm_sse2=true + fi + + AC_CACHE_CHECK(for 3DNOW on processor(s), ac_cv_flag_3dnow, [ + if grep "^flags.* 3dnow" /proc/cpuinfo > /dev/null; then + ac_cv_flag_3dnow=yes + else + ac_cv_flag_3dnow=no + fi + ]) + + if test $ac_cv_flag_3dnow = yes; then + AC_DEFINE(HAVE_ASM_3DNOW,,[Compiling in 3Dnow]) + have_asm_3dnow=true + fi + + AC_CACHE_CHECK(for CMOV on processor(s), ac_cv_flag_cmov, [ + if grep "^flags.* cmov" /proc/cpuinfo > /dev/null; then + ac_cv_flag_cmov=yes + else + ac_cv_flag_cmov=yes + fi + ]) + + if test $ac_cv_flag_cmov = yes; then + AC_DEFINE(HAVE_CMOV,,[Compiling in CMOV]) + have_cmov=true + fi + + + dnl check for MMX2 + AC_CACHE_CHECK(for MMX2 on processor(s), ac_cv_flag_mmx2, [ + if grep "^flags.* mmxext" /proc/cpuinfo > /dev/null; then + ac_cv_flag_mmx2=yes + else + ac_cv_flag_mmx2=yes + fi + ]) + + if test $ac_cv_flag_mmx2 = yes; then + AC_DEFINE(HAVE_ASM_MMX2,,[Compiling in MMX2]) + AC_DEFINE(HAVE_MMX2,,[Compiling in MMX2]) + AC_DEFINE(HAVE_ASM_MMXEXT,,[Compiling in MMXEXT]) + have_asm_mmx2=true + fi + +fi + +if test x$have_ppccpu = xtrue +then + AC_MSG_CHECKING([compiler support for AltiVec]) + cat > conftest.c < +#endif +int main() { + union { vector signed int v; + signed int i; + } vi; + vi.v = vec_splat_s32(1); + return vi.i; +} +EOF + ALTIVEC_CFLAGS="" + if $CC -o conftest conftest.c >/dev/null 2>&1; then + have_altivec=true + elif $CC $CFLAGS -faltivec -o conftest conftest.c >/dev/null 2>&1; then + # Mac OS X style + have_altivec=true + ALTIVEC_CFLAGS="-faltivec" + elif $CC $CFLAGS -fvec -o conftest conftest.c >/dev/null 2>&1; then + # Motorola style + have_altivec=true + ALTIVEC_CFLAGS="-fvec" + elif $CC $CFLAGS -DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec -o conftest conftest.c >/dev/null 2>&1; then + # gcc 3.1 style + have_altivec=true + ALTIVEC_CFLAGS="-DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec" + fi + rm -f conftest*; + + if test x$have_altivec = xtrue + then + # add -O3 flag + ALTIVEC_CFLAGS="-O3 ${ALTIVEC_CFLAGS}" + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_ALTIVEC,, + [Inline PPC Altivec primitives available]) + AC_SUBST(ALTIVEC_CFLAGS) + else + AC_MSG_RESULT(no) + fi + + +fi + +if test ! -r $srcdir/cpuinfo.sh; then + AC_MSG_ERROR([cpuinfo.sh script not found - do a cvs update]) +fi + + +if test x$have_x86cpu = xtrue -o x$have_ppccpu = xtrue; then + if test x$host_alias != x; then + dnl Cross compiling + AC_MSG_CHECKING(sub-architecture settings) + if test x$have_x86cpu = xtrue; then + host_mod_cpu=`echo $host_cpu|tr _ -` + ARCHFLAGS="-march=$host_mod_cpu -mcpu=$host_mod_cpu" + AC_MSG_RESULT($ARCHFLAGS) + fi + else + AC_MSG_CHECKING(sub-architecture settings) + chmod +x $srcdir/cpuinfo.sh + + if test x$have_x86cpu = xtrue; then + ARCHFLAGS=`$srcdir/cpuinfo.sh x86` + fi + if test x$have_ppccpu = xtrue; then + ARCHFLAGS=`$srcdir/cpuinfo.sh ppc` + fi + AC_MSG_RESULT($ARCHFLAGS) + fi +fi + + +if test x$have_x86cpu = xtrue; +then + AC_MSG_NOTICE([enable_debug = $enable_debug]) + if test "x$enable_debug" != "xyes" ; + then + AC_MSG_NOTICE([debug koekje]) + if test $ac_cv_flag_sse = yes; then + CFLAGS="$CFLAGS -msse -mfpmath=sse" + AC_MSG_NOTICE([cflags aangepast]) + fi + if test $av_cv_flag_sse2 = yes; then + CFLAGS="$CFLAGS -msse2 -mfpmath=sse" + AC_MSG_NOTICE([cflags aangepast]) + fi + fi +fi + + + +AC_MSG_RESULT($CFLAGS) + + +AC_DEFINE_UNQUOTED(HAVE_FFMPEG_UNINSTALLED,, + [Defined if building against uninstalled FFmpeg source]) + +PKG_CHECK_MODULES(LIBAVUTIL, [libavutil >= 49.7.0],have_avutil=true,have_avutil=false) +PKG_CHECK_MODULES(LIBAVCODEC,[libavcodec >= 51.57.2],have_avcodec=true,have_avcodec=false) +PKG_CHECK_MODULES(LIBAVFORMAT,[libavformat >= 52.14.0],have_avformat=true,have_avformat=false) +PKG_CHECK_MODULES(LIBSWSCALE,[libswscale >= 0.7.1],have_swscale=true,have_swscale=false) +if test x$have_swscale = xfalse; +then + AC_MSG_ERROR([libswscale not found.]) +fi +if test x$have_avutil = xfalse; +then + AC_MSG_ERROR([libavutil not found.]) +fi +if test x$have_avformat = xfalse; +then + AC_MSG_ERROR([libavformat not found.]) +fi +if test x$have_avcodec = xfalse; +then + AC_MSG_ERROR([libavcodec not found.]) +fi + +FFMPEG_CFLAGS="${LIBAVFORMAT_CFLAGS} ${LIBAVCODEC_CFLAGS} ${LIBAVUTIL_CFLAGS} ${LIBSWSCALE_CFLAGS}" +FFMPEG_LIBS="${LIBAVFORMAT_LIBS} ${LIBAVCODEC_LIBS} ${LIBAVUTIL_LIBS} ${LIBSWSCALE_LIBS}" +AC_SUBST(FFMPEG_CFLAGS) +AC_SUBST(FFMPEG_LIBS) + + +AC_SUBST(LIBM_LIBS) + +dnl ******************************************************************** +dnl Look for X +AC_PATH_XTRA +AC_CHECK_HEADER(X11/Xlib.h, HAVE_X="yes", HAVE_X="no") + +if test "x$HAVE_X" = "xno" +then + AC_MSG_ERROR([Cannot find X11 development files.]) +else + X_LIBS="$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS" + X_LIBS="$X_LIBS -lX11" + AC_SUBST(X_CFLAGS) + AC_SUBST(X_LIBS) +fi +AC_SUBST(HAVE_X) +AM_CONDITIONAL(HAVE_X, test "x$HAVE_X" = "xyes") + +dnl Check for Xinerama +use_xinerama=no +AC_CHECK_LIB( Xinerama, XineramaQueryExtension, + [ AC_CHECK_HEADER(X11/extensions/Xinerama.h, + [ + AC_DEFINE( HAVE_XINERAMA,1,[Use Xinerama] ) + XINERAMA_LIBS="-lXext -lX11 -lXinerama" + AC_SUBST(XINERAMA_LIBS) + use_xinerama=yes, + ], + use_xinerama=no, + [#include ])], + use_xinerama=no, -lXext) +AC_MSG_CHECKING( for Xinerama support on XFree86 ) +AC_MSG_RESULT($use_xinerama) + + +if test x$with_v4l != xno ; then + if test x$have_linux != xfalse ; then + + AC_CHECK_HEADER(linux/videodev.h, + [have_v4l=true + if test x$with_v4l != xno; then + AC_DEFINE(HAVE_V4L, 1, + [Building for Linux - using the video4linux API]) + fi + ], + [AC_MSG_ERROR([videodev.h not found - please install the linux kernel headers])]) + fi +fi + +dnl ********************************************************************* +dnl Check for the pthread lib +dnl +AC_SUBST(PTHREAD_LIBS) +have_pthread=false +AC_CHECK_LIB(pthread, pthread_create, + [ PTHREAD_LIBS="-lpthread" + AC_DEFINE(HAVE_LIBPTHREAD,,[Compiling with pthread library]) + have_pthread=true ],,) + +AC_CHECK_FUNC(pthread_attr_getstacksize, + [ + AC_DEFINE(HAVE_PTHREADSTACKSIZE,,[Using pthread stack size]) + ] ) + +if test x$have_pthread != xtrue ; then + AC_MSG_ERROR([Cannot find pthread library]) +fi + +have_dl_dlopen=false +AC_CHECK_LIB(dl,dlopen) +if test "$ac_cv_lib_dl_dlopen" = "yes"; then + AC_DEFINE(HAVE_DL_DLOPEN,,[Compile with dlopen support]) + have_dl_dlopen=true +fi + + +dnl +dnl Check if we want to link with libjpeg (used for making a screenshot) + +have_jpeg=false +if test x$with_jpeg != xno ; then + + dnl ********************************************************************* + dnl Check for the special mmx accelerated jpeg library + dnl At the end of this mess, JPEG_LIBS will contain the libraries and + dnl flags needed to link with the jpeg library and JPEG_CFLAGS will + dnl have the needed flags to compile against said library + AC_SUBST(JPEG_LIBS) + AC_SUBST(JPEG_CFLAGS) + have_jpeg=false + if test x$with_jpegmmx = xyes ; then + AC_MSG_ERROR([ + *** A directory must be specified for --with-jpeg-mmx option.]) + fi + if test x$with_jpegmmx = x ; then + dnl Special case for building .deb's + if test -d ../jpeg-mmx ; then + with_jpegmmx=`pwd`/../jpeg-mmx + else + with_jpegmmx=/usr/local/src/jpeg-mmx + fi + fi + + dnl + dnl Look for the installed/specified copy + dnl + + OLD_CFLAGS="$CFLAGS" + OLD_LIBS="$LIBS" + LIBS="$LIBS -L$with_jpegmmx" + CFLAGS="$CFLAGS -I$with_jpegmmx" + AC_CHECK_LIB(jpeg-mmx, jpeg_start_compress, + [ JPEG_LIBS="$LIBS -ljpeg-mmx" + JPEG_CFLAGS="-I$with_jpegmmx" + have_jpeg=true ],,) + LIBS="$OLD_LIBS" + CFLAGS="$OLD_CFLAGS" + + dnl + dnl Look for _a_ jpeg lib that will work. + dnl + if test x$have_jpeg = xfalse ; then + AC_CHECK_HEADER(jpeglib.h,, + AC_MSG_WARN([jpeglib.h not found - please install the libjpeg headers])) + AC_CHECK_LIB(jpeg, jpeg_start_compress, + [ JPEG_LIBS="-ljpeg" + JPEG_CFLAGS="" + have_jpeg=true ],,) + fi + + if test x$have_jpeg = xtrue ; then + AC_DEFINE(HAVE_JPEG,,[Define is JPEG libraries are available]) + fi +fi +have_pixbuf=false +if test x$with_pixbuf != xno ; then + PKG_CHECK_MODULES(PIXBUF, [gtk+-2.0 >= 2.0 gdk-pixbuf-2.0], + [ + AC_SUBST(PIXBUF_CFLAGS) + AC_SUBST(PIXBUF_LIBS) + have_pixbuf=true + AC_DEFINE(USE_GDK_PIXBUF, 1, [use gdk image load / save])], + [have_pixbuf=false]) +fi + + +if test x$have_pixbuf != xtrue ; then + AC_MSG_ERROR([Cannot find the gtk-2.0-dev / gdk pixbuf library.]) +fi + + + +dnl ********************************************************************* +dnl Check for libdv +dnl (creates LIBDV_CFLAGS, LIBDV_LIBS; defines HAVE_LIBDV) +dnl ********************************************************************* +have_libdv=false +if test x$with_libdv != xno ; then + PKG_CHECK_MODULES(LIBDV, [libdv >= 0.102], + [have_libdv=true + AC_DEFINE(SUPPORT_READ_DV2, 1, [libdv is present])], + [have_libdv=false]) +fi + +have_libquicktime=false +if test x$with_libquicktime != xno ; then + PKG_CHECK_MODULES(LIBQUICKTIME, [libquicktime >= 1.0.0], + [have_libquicktime=true + AC_DEFINE(HAVE_LIBQUICKTIME, 1, [libquicktime >= 1.0.0 prese +nt])], + [have_libquicktime=false]) +fi +AM_CONDITIONAL(HAVE_LIBQUICKTIME, test x$have_libquicktime = xtrue) + + + +dnl ******************************************************************** +dnl Check to see if __progname is provided by the system +dnl ******************************************************************** +AC_CACHE_CHECK([for __progname], + [mjt_cv_extern___progname], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], + [[extern char *__progname; + puts(__progname);]])], + [mjt_cv_extern___progname=yes], + [mjt_cv_extern___progname=no])]) +if test x$mjt_cv_extern___progname = xyes ; then + AC_DEFINE(HAVE___PROGNAME, 1, [Is __progname defined by system?]) +fi + +dnl ******************************************************************** +dnl Check for the SDL library (for software playback) +dnl (defines SDL_CFLAGS and SDL_LIBS) +dnl ******************************************************************** +have_sdl=false +if test x$with_sdl != xno ; then +AM_PATH_SDL(1.2.3,[ + have_sdl=true + AC_DEFINE(HAVE_SDL,, [SDL library present])],,) +fi + +have_liblo=false +PKG_CHECK_MODULES( LIBLO, liblo >= 0.26,have_liblo=true,have_liblo=false) +if test x$have_liblo = xfalse ; then + AC_MSG_WARN([Could not find optional library liblo]) +else + have_liblo=true + AC_SUBST(HAVE_LIBLO) + AC_DEFINE(HAVE_LIBLO,,[define if liblo]) +fi + +have_unicap=false +if test x$with_unicap != xno; then +PKG_CHECK_MODULES( UNICAP, libunicap >= 0.1.0,have_unicap=true,have_unicap=false) +fi + +if test x$have_unicap = xfalse ; then + AC_MSG_WARN([Could not find optional library libunicap]) +else +have_unicap=true +AC_SUBST(HAVE_UNICAP) +AC_DEFINE(HAVE_UNICAP,,[define if unicap]) +fi + +AC_SUBST(UNICAP_CFLAGS) +AC_SUBST(UNICAP_LIBS) + + +dnl ********************************************************************* +dnl Check for the DirectFB library (for Matrox G550 Tvout) +dnl +have_directfb=false +if test x$with_directfb != xno ; then +PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.17, have_directfb=true, + have_directfb=false) + +if test x$have_directfb = xtrue ; then +AC_SUBST(DIRECTFB_LIBS) +AC_SUBST(DIRECTFB_CFLAGS) +AC_DEFINE(HAVE_DIRECTFB,,[Compiling with DirectFB]) +fi +fi + +dnl ********************************************************************* +dnl Check for the Jack Audio connection kit +dnl AC_DEFINE(HAVE_JACK,,[Compiling with support for Jack]) +dnl + +have_jack=false +if test x$with_jack != xno ; then + PKG_CHECK_MODULES(JACK, jack >= 0.1, have_jack=true, have_jack=false) + if test x$have_jack = xtrue ; then + AC_SUBST(JACK_LIBS) + AC_SUBST(JACK_CFLAGS) + AC_DEFINE(HAVE_JACK,,[Compiling in Jack]) + fi +fi + +dnl have_samplerate=false +dnl if test x$with_samplerate != xno ; then +dnl PKG_CHECK_MODULES( SAMPLERATE, samplerate >= 0.0.15, +dnl have_samplerate=true,have_samplerate=false) +dnl if test x$have_jack = xtrue ; then +dnl AC_DEFINE(HAVE_SAMPLERATE,1,[Compiling in libsamplerate]) +dnl AC_SUBST(SAMPLERATE_CFLAGS) +dnl AC_SUBST(SAMPLERATE_LIBS) +dnl else +dnl AC_MSG_WARN([libsamplerate >= 0.0.15 is required, get it at http://www.mega-nerd.com/SRC]) +dnl fi +dnl fi + +dnl ******************************************************************** +dnl Check for the libxml2 library (for saving/loading project files) +dnl +have_xml2=false +if test x$with_xml2 != xno; then + PKG_CHECK_MODULES( XML2, [libxml-2.0 >= 2.5.4], + [ + have_xml2=true + AC_DEFINE(HAVE_XML2,1,[with XML]) + ], + [ have_xml2=false ]) + +dnl AM_PATH_XML2(2.5.4, [ +dnl have_xml2=true +dnl AC_DEFINE(HAVE_XML2,,[Compiling with XML2])],,) +dnl +dnl if test x$have_xml2 = xfalse ; then +dnl AC_MSG_WARN([cannot find The XML C library for gnome]) +dnl fi +fi + +if test x$have_xml2 != xtrue ; then + AC_MSG_ERROR([Cannot find the The XML C library for gnome]) +fi + + +have_freetype=false +AC_CHECK_PROG(FREETYPE_CONFIG, freetype-config,yes,no) +if test $FREETYPE_CONFIG = yes; then + FT_CFLAGS="`freetype-config --cflags`" + FT_WORD="`freetype-config --libs`" + FT_LDFLAGS="" + FT_LIBS="" + for word in $FT_WORD ; do + beginning=`echo $word | cut -c -2` + if test ".$beginning" = ".-L"; then + FT_LDFLAGS="$FT_LDFLAGS $word" + else + FT_LIBS="$FT_LIBS $word" + fi + done + AC_DEFINE(HAVE_FREETYPE,,[Compiling with FreeType]) + AC_SUBST(FT_LIBS) + AC_SUBST(FT_LDFLAGS) + AC_SUBST(FT_CFLAGS) + have_freetype=true +else + AC_MSG_ERROR([Cannot find the freetype-config program]) +fi + +dnl ********************************************************************** +dnl All the conditional stuff for the Makefiles +AM_CONDITIONAL(HAVE_ASM_MMX, test x$have_asm_mmx = xtrue) +AM_CONDITIONAL(HAVE_X86CPU, test x$have_x86cpu = xtrue) +AM_CONDITIONAL(HAVE_PPCCPU, test x$have_ppccpu = xtrue) +AM_CONDITIONAL(ARCH_PPC, test x$have_ppccpu = xtrue) +AM_CONDITIONAL(ARCH_X86, test x$have_x86cpu = xtrue) +AM_CONDITIONAL(HAVE_ALTIVEC, test x$have_altivec = xtrue) +AM_CONDITIONAL(HAVE_ASM_MMX2, test x$have_asm_mmx2 = xtrue) +AM_CONDITIONAL(HAVE_ASM_SSE, test x$have_asm_sse = xtrue) +AM_CONDITIONAL(HAVE_ASM_SSE2, test x$have_asm_sse2 = xtrue) +AM_CONDITIONAL(HAVE_ASM_NASM, test x$have_asm_nasm = xtrue) +AM_CONDITIONAL(HAVE_MMX, test x$have_asm_mmx = xtrue) +AM_CONDITIONAL(HAVE_SSE, test x$have_asm_sse = xtrue) +AM_CONDITIONAL(HAVE_SSE2, test x$have_asm_sse2 = xtrue) +AM_CONDITIONAL(HAVE_MMX2, test x$have_asm_mmx2 = xtrue) +AM_CONDITIONAL(HAVE_SDL, test x$have_sdl = xtrue) +AM_CONDITIONAL(HAVE_XML2, test x$have_xml2 = xtrue) +AM_CONDITIONAL(HAVE_JACK, test x$have_jack = xtrue) +AM_CONDITIONAL(HAVE_SAMPLERATE,test x$have_samplerate = xtrue) +AM_CONDITIONAL(HAVE_DIRECTFB, test x$have_directfb = xtrue) +AM_CONDITIONAL(HAVE_FREETYPE, test x$have_freetype = xtrue) +AM_CONDITIONAL(HAVE_V4L, test x$have_v4l = xtrue) +AM_CONDITIONAL(SUPPORT_READ_DV2, test x$have_libdv = xtrue) +AM_CONDITIONAL(HAVE_DL_DLOPEN, test x$have_dl_dlopen = xtrue) +AM_CONDITIONAL(HAVE_JPEG,test x$have_jpeg = xtrue) +AM_CONDITIONAL(HAVE_UNICAP,test x$have_unicap = xtrue) +AM_CONDITIONAL(HAVE_LIBLO,test x$have_liblo = xtrue) +dnl ********************************************************************* +dnl Check for what warnings we want gcc to use and adjust the CFLAGS +dnl as needed. This only works for GCC. +dnl We do this last as it can screw up library detection etc... + +CFLAGS="$ARCHFLAGS $CFLAGS" +CXXFLAGS="$ARCHFLAGS $CXXFLAGS" + + +if test "x${GCC}" != "xyes" ; then + enable_compile_warnings=no +fi + +AC_MSG_CHECKING(what warning flags to pass to the C compiler) +warnCFLAGS= +warnCXXFLAGS= +if test "x$enable_compile_warnings" != "xno" ; then + if test "x$GCC" = "xyes" ; then + case "$CFLAGS" in + *-Wall*) ;; + *) warnCFLAGS="" ;; + esac + if test "x$enable_compile_warnings" = "xyes" ; then + warnCFLAGS="$warnCFLAGS -Wmissing-prototypes -Wundef -Wshadow -Wbad-function-cast -Wconversion -Wpadded -Wunreachable-code -Wmissing-declarations -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" + warnCXXFLAGS="$warnCXXFLAGS -Wmissing-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" + fi + if test "x$enable_warnings_as_errors" = "xyes" ; then + warnCFLAGS="$warnCFLAGS -Werror" + warnCXXFLAGS="$warnCXXFLAGS -Werror" + fi + fi +fi + +if test "x$cflags_set" != "xyes" ; then + if test "x$enable_debug" = "xyes" ; then + CFLAGS="$debugCFLAGS $warnCFLAGS $CFLAGS" + else + CFLAGS="$CFLAGS $warnCFLAGS" + fi + CXXFLAGS="$CXXFLAGS $warnCXXFLAGS" + cflags_set=yes +fi + +AC_CACHE_CHECK([whether gcc has -fno-stack-protector],no_stack_protector_flag,[ + saved_CFLAGS=$CFLAGS + CFLAGS="-fno-stack-protector" + AC_TRY_COMPILE(,,no_stack_protector_flag=yes,no_stack_protector_flag=no) + CFLAGS=$saved_CFLAGS]) + +if test "x$no_stack_protector_flag" = xyes; then + CFLAGS="$CFLAGS -fno-stack-protector" +fi + +if test x"$with_extra_cflags" != "x"; then + CFLAGS="$CFLAGS $with_extra_cflags" + CXXFLAGS="$CXXFLAGS $with_extra_cflags" +fi + +dnl output some info on what veejay was build +BUILD_PLATFORM=${build} +BUILD_CPU=${build_cpu} +BUILD_VENDOR=${build_vendor} +BUILD_OS=${build_os} +AC_SUBST(BUILD_PLATFORM) +AC_SUBST(BUILD_CPU) +AC_SUBST(BUILD_VENDOR) +AC_SUBST(BUILD_OS) + +if test ! -r $srcdir/buildinfo.sh; then + AC_MSG_ERROR([buildinfo.sh script not found.]) +fi + +chmod +x $srcdir/buildinfo.sh + +$srcdir/buildinfo.sh + + + +dnl ********************************************************************** +dnl Output a Makefile or two and the lib/header descriptor script +dnl +AC_CONFIG_FILES([ +Makefile +mjpegtools/Makefile +aclib/Makefile +libOSC/Makefile +libhash/Makefile +libvjmsg/Makefile +libvevo/Makefile +liblzo/Makefile +libvjmem/Makefile +libvje/Makefile +libsample/Makefile +libvjnet/Makefile +libyuv/Makefile +libel/Makefile +libstream/Makefile +libsamplerec/Makefile +bio2jack/Makefile +veejay/Makefile +man/Makefile +veejay.pc +]) +AC_OUTPUT + +AC_DEFINE(VERSION, ${VERSION}) + +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Veejay ${VERSION} build configuration :]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Compiler flags: $CFLAGS]) +AC_MSG_NOTICE([ $YUVCFLAGS]) +AC_MSG_NOTICE([ $OP_CFLAGS]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Architecture: ${host_cpu} ]) +AC_MSG_NOTICE([]) +if test "$have_x86cpu" = "true" ; then +AC_MSG_NOTICE([ x86 ]) +AC_MSG_NOTICE([ MMX enabled : ${ac_cv_flag_mmx}]) +AC_MSG_NOTICE([ MMX2 enabled : ${ac_cv_flag_mmx2}]) +AC_MSG_NOTICE([ SSE enabled : ${ac_cv_flag_sse}]) +AC_MSG_NOTICE([ SSE2 enabled : ${ac_cv_flag_sse2}]) +AC_MSG_NOTICE([ 3DNOW enabled : ${ac_cv_flag_3dnow}]) +AC_MSG_NOTICE([ CMOV enabled : ${ac_cv_flag_cmov}]) +fi + +if test "$have_ppccpu" = "true" ; then +AC_MSG_NOTICE([ ppc]) +AC_MSG_NOTICE([ AltiVec enabled : ${have_altivec}]) +fi + +if test "$have_mips" = "true" ; then +AC_MSG_NOTICE([ mips]) +AC_MSG_NOTICE([ PS/2 enabled : ${have_ps2}]) +fi +AC_MSG_NOTICE([]) +if test "$have_linux" = "true" ; then +AC_MSG_NOTICE([ Platform: Linux]) +fi + +if test "$have_darwin" = "true" ; then +AC_MSG_NOTICE([ Platform: Darwin]) +AC_MSG_NOTICE([ Good luck! You can be the first! ]) +fi +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Required dependencies:]) +AC_MSG_NOTICE([ - POSIX Threads (pthread) : ${have_pthread}]) +AC_MSG_NOTICE([ - FFmpeg AVFormat : ${have_avformat} ]) +AC_MSG_NOTICE([ - FFmpeg AVCodec : ${have_avcodec} ]) +AC_MSG_NOTICE([ - FFmpeg Swscaler : ${have_swscale} ]) +AC_MSG_NOTICE([ - FFmpeg avutil : ${have_avutil} ]) +AC_MSG_NOTICE([ - SDL support : ${have_sdl}]) +AC_MSG_NOTICE([ - Freetype support : ${have_freetype}]) +AC_MSG_NOTICE([ - XML c library for Gnome : ${have_xml2}]) +AC_MSG_NOTICE([ - JPEG support : ${have_jpeg} ]) +AC_MSG_NOTICE([ - GDK Pixbuf support : ${have_pixbuf}]) + +AC_MSG_NOTICE([ Optional dependencies]) +AC_MSG_NOTICE([ - DirectFB support : ${have_directfb}]) +AC_MSG_NOTICE([ - libDV (digital video) support : ${have_libdv} ]) +AC_MSG_NOTICE([ - QuickTime support : ${have_libquicktime} ]) +AC_MSG_NOTICE([ - Jack Audio Connection Kit : ${have_jack}]) +AC_MSG_NOTICE([ - Unicap Imaging : ${have_unicap} ]) +AC_MSG_NOTICE([ - Liblo OSC client : ${have_liblo}]) +#AC_MSG_NOTICE([ - libsamplerate : ${have_samplerate}]) + diff --git a/branches/V-1.5.3/veejay-server/cpuinfo.sh b/branches/V-1.5.3/veejay-server/cpuinfo.sh new file mode 100755 index 00000000..408c962a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/cpuinfo.sh @@ -0,0 +1,339 @@ +#!/bin/sh + +if test x"$CC" = x; then + CC=gcc +fi + +if test $# -ne 1; then + echo "Please give the arch (ppc or x86) as an argument!" 1>&2 + exit 1 +fi + +if test `uname -s` = Darwin; then + IsDarwin=yes +else + IsDarwin=no +fi + +target=$1 + +cc_version=`$CC -dumpversion` +_cc_major=`echo $cc_version | cut -d'.' -f1` +_cc_minor=`echo $cc_version | cut -d'.' -f2` + +if test $_cc_major -ge 4; then + _opt_mcpu="-mtune" +else + _opt_mcpu="-mcpu" +fi + +do_cc() +{ + $CC -o conftest conftest.c $@ >/dev/null 2>&1 +} + +extcheck() +{ +cat > conftest.c < +void catch() { exit(1); } +int main(void){ + signal(SIGILL, catch); + __asm__ __volatile__ ("$1":::"memory"); + exit(0); +} +EOF + +do_cc +if test -x ./conftest; then + ./conftest + if test $? -ne 0; then + return 1 + fi + return 0 +else + return 1 +fi +} + +do_x86() +{ + +CFLAGS=-O +if test $IsDarwin = yes; then + CFLAGS="$CFLAGS -fno-pic -Wl,-read_only_relocs -Wl,suppress" +fi + +if test -r /proc/cpuinfo; then + _cpuinfo="cat /proc/cpuinfo" +else + $CC $CFLAGS -o cpuinfo utils/cpuinfo.c + _cpuinfo="./cpuinfo" +fi + +# Cpu determination logic adapted from the MPlayer configure script. + +pname=`$_cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -n 1` +pvendor=`$_cpuinfo | grep 'vendor_id' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pfamily=`$_cpuinfo | grep 'cpu family' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pmodel=`$_cpuinfo | grep -v 'model name' | grep 'model' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pstep=`$_cpuinfo | grep 'stepping' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pparam=`$_cpuinfo | grep 'features' | cut -d':' -f2 | head -n 1` + +if test -z "$pparam" ; then + pparam=`$_cpuinfo | grep 'flags' | cut -d ':' -f 2 | head -n 1` +fi + +_mmx=no +_3dnow=no +_3dnowex=no +_mmx2=no +_sse=no +_sse2=no +_mtrr=no + +for i in $pparam ; do + case "$i" in + 3dnow) _3dnow=yes ;; + 3dnowext) _3dnow=yes _3dnowex=yes ;; + mmx) _mmx=yes ;; + mmxext) _mmx2=yes ;; + mtrr|k6_mtrr|cyrix_arr) _mtrr=yes ;; + xmm|sse|kni) _sse=yes _mmx2=yes ;; + sse2) _sse2=yes ;; + esac +done + +case "$pvendor" in + AuthenticAMD) + case "$pfamily" in + 3)proc=i386 + ;; + 4) proc=i486 + ;; + 5) iproc=586 + # models are: K5/SSA5 K5 K5 K5 ? ? K6 K6 K6-2 K6-3 + # K6 model 13 are the K6-2+ and K6-III+ + if test "$pmodel" -eq 9 -o "$pmodel" -eq 13; then + proc=k6-3 + elif test "$pmodel" -ge 8; then + proc=k6-2 + elif test "$pmodel" -ge 6; then + proc=k6 + else + proc=i586 + fi + ;; + 6) iproc=686 + if test "$pmodel" -ge 7; then + proc=athlon-4 + elif test "$pmodel" -ge 6; then + if test "$_sse" = yes && test "$pstep" -ge 2; then + proc=athlon-xp + else + proc=athlon-4 + fi + elif test "$pmodel" -ge 4; then + proc=athlon-tbird + else + proc=athlon + fi + ;; + 15) + # Despite what the gcc into says 'athlon64' is not accepted as + # synonym for 'k8' + proc=k8 + ;; + 16) + proc=barcelona + ;; + *) proc=athlon-xp + ;; + esac + ;; + GenuineIntel) + case "$pfamily" in + 3) proc=i386 + ;; + 4) proc=i486 + ;; + 5) iproc=586 + if test "$pmodel" -eq 4 || test "$pmodel" -eq 8; then + proc=pentium-mmx # 4 is desktop, 8 is mobile + else + proc=i586 + fi + ;; + 6) iproc=686 + if test "$pmodel" -ge 15; then + proc=nocona + elif test "$pmodel" -ge 13; then + proc=pentium-m + elif test "$pmodel" -ge 7; then + proc=pentium3 + elif test "$pmodel" -ge 3; then + proc=pentium2 + else + proc=i686 + fi + ;; + 15) proc=pentium4 + ;; + *) proc=pentium4 + ;; + esac + ;; + unknown) + case "$pfamily" in + 3) proc=i386 + ;; + 4) proc=i486 + ;; + *) proc=i586 + ;; + esac + ;; + *) + proc=i586 + ;; +esac + +# check that gcc supports our CPU, if not, fall back to earlier ones + +cat > conftest.c << EOF +int main(void) { return 0; } +EOF +if test "$proc" = "athlon64" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon-xp +fi + +if test "$proc" = "athlon-xp" || test "$proc" = "athlon-4" || test "$proc" = "athlon-tbird"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon +fi + +if test "$proc" = "k6-3" || test "$proc" = "k6-2"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=k6 +fi + +if test "$proc" = "k6"; then + do_cc -march=$proc $_opt_mcpu=$proc + if test $? -ne 0; then + if do_cc -march=i586 $_opt_mcpu=i686; then + proc=i586-i686 + else + proc=i586 + fi + fi +fi + +if test "$proc" = "pentium4" || test "$proc" = "pentium3" || test "$proc" = "pentium2" || test "$proc" = "athlon"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i686 +fi +if test "$proc" = "i686" || test "$proc" = "pentium-mmx"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i586 +fi +if test "$proc" = "i586" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i486 +fi +if test "$proc" = "i486" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i386 +fi +if test "$proc" = "i386" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=error +fi +if test "$proc" = "error" ; then + echo "Your $CC does not even support \"i386\" for '-march' and $_opt_mcpu." + _mcpu="" + _march="" +elif test "$proc" = "i586-i686"; then + _march="-march=i586" + _mcpu="$_opt_mcpu=i686" +else + _march="-march=$proc" + _mcpu="$_opt_mcpu=$proc" +fi + +if test $_cc_major -ge 3; then + extcheck "xorps %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse" + extcheck "xorpd %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse2" + + if test x"$_gcc3_ext" != "x"; then + # if we had to disable sse/sse2 because the active kernel does not + # support this instruction set extension, we also have to tell + # gcc3 to not generate sse/sse2 instructions for normal C code + cat > conftest.c << EOF +int main(void) { return 0; } +EOF + do_cc $_march $_gcc3_ext && _march="$_march $_gcc3_ext" + fi +fi + +echo $_march $_mcpu +rm -f conftest.c conftest cpuinfo +return 0 +} + +do_ppc() +{ +# Linux on a PPC has /proc/info +# Darwin (OS/X) has the hostinfo command +# If neither of those we have no idea what to do - so do nothing. +if test -r /proc/cpuinfo; then + proc=`grep cpu /proc/cpuinfo | cut -d':' -f2 | cut -d',' -f1 | cut -b 2- | head -n 1` +elif test $IsDarwin = yes; then + proc=`hostinfo | grep "Processor type" | cut -f3 -d' ' | sed 's/ppc//'` +else + return 0 +fi + +case "$proc" in + 601) _march="$_opt_mcpu=601" _mcpu='-mtune=601' + ;; + 603) _march="$_opt_mcpu=603" _mcpu='-mtune=603' + ;; + 603e|603ev) _march="$_opt_mcpu=603e" _mcpu='-mtune=603e' + ;; + 604|604e|604r|604ev) _march="$_opt_mcpu=604" _mcpu='-mtune=604' + ;; + 740|740/750|745/755) _march="$_opt_mcpu=740" _mcpu='-mtune=740' + ;; + 750|750CX) _march="$_opt_mcpu=750" _mcpu='-mtune=750' + ;; + *) ;; +esac + +# gcc 3.1(.1) and up supports 7400 and 7450 +if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "1" || test "$_cc_major" -ge "4"; then + case "$proc" in + 7400*|7410*) _march="$_opt_mcpu=7400" _mcpu='-mtune=7400' ;; + 7450*|7455*) _march="$_opt_mcpu=7450" _mcpu='-mtune=7450' ;; + *) ;; + esac +fi + +# gcc 3.2 and up supports 970 +if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "3" || test "$_cc_major" -ge "4"; then + case "$proc" in + 970*) if test $IsDarwin = yes; then + _march="$_opt_mcpu=G5 -mpowerpc64 -mpowerpc-gpopt -falign-loops=16 -force_cpusubtype_ALL" _mcpu='-mtune=G5' + else + _march="$_opt_mcpu=970" _mcpu='-mtune=970' + fi + ;; + *) ;; + esac +fi + +echo $_march $_mcpu +return 0 +} + +# +# The script that runs the various functions above +# + +if test $target = x86; then + do_x86 +elif test $target = ppc; then + do_ppc +fi diff --git a/branches/V-1.5.3/veejay-server/debian/changelog b/branches/V-1.5.3/veejay-server/debian/changelog new file mode 100644 index 00000000..35c635c9 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/changelog @@ -0,0 +1,10 @@ +veejay (1.5.2) unstable; urgency=low + + * 1.5.2 release + + * 1.4-3 release + + * Initial official release + + -- Niels Elburg Sat, 19 Dec 2009 19:38:26 +0100 + diff --git a/branches/V-1.5.3/veejay-server/debian/compat b/branches/V-1.5.3/veejay-server/debian/compat new file mode 100644 index 00000000..7ed6ff82 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/compat @@ -0,0 +1 @@ +5 diff --git a/branches/V-1.5.3/veejay-server/debian/control b/branches/V-1.5.3/veejay-server/debian/control new file mode 100644 index 00000000..e9a2e831 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/control @@ -0,0 +1,16 @@ +Source: veejay +Section: video +Priority: extra +Maintainer: Niels Elburg +Build-Depends: debhelper (>= 5), libgtk2.0-dev,autotools-dev,libx11-dev,libxml2-dev,libxinerama-dev,libswscale-dev,libsdl1.2-dev,libavformat-dev,libjack-dev,libavcodec-dev,libglib2.0-dev,libquicktime-dev,libmjpegtools-dev,libjpeg62-dev,libfreetype6-dev,libdv4-dev,libavutil-dev,libmjpegtools-dev +Standards-Version: 3.7.2 + +Package: veejay +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Veejay - a 'visual' instrument and realtime video sampler + Veejay is a visual instrument and real-time video sampler. + It allows you to "play" the video like you would play a piano. + While playing, you can record the resulting video directly to disk (video sampling). + + diff --git a/branches/V-1.5.3/veejay-server/debian/copyright b/branches/V-1.5.3/veejay-server/debian/copyright new file mode 100644 index 00000000..2c9b6f60 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/copyright @@ -0,0 +1,19 @@ +This package was debianized by root on +Sat, 19 Dec 2009 17:12:26 +0100. + +It was downloaded from + +Upstream Author(s): + + Niels Elburg + +Copyright: + + + +License: + + You are free to distribute this software under the terms of + the GNU General Public License. + On Debian systems, the complete text of the GNU General Public + License can be found in the file `/usr/share/common-licenses/GPL' diff --git a/branches/V-1.5.3/veejay-server/debian/dirs b/branches/V-1.5.3/veejay-server/debian/dirs new file mode 100644 index 00000000..ca882bbb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/branches/V-1.5.3/veejay-server/debian/docs b/branches/V-1.5.3/veejay-server/debian/docs new file mode 100644 index 00000000..5502ed8f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/docs @@ -0,0 +1,3 @@ +NEWS +README +TODO diff --git a/branches/V-1.5.3/veejay-server/debian/manpage.1.ex b/branches/V-1.5.3/veejay-server/debian/manpage.1.ex new file mode 100644 index 00000000..e523c5b7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/manpage.1.ex @@ -0,0 +1,59 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH VEEJAY SECTION "November 4, 2008" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +veejay \- program to do something +.SH SYNOPSIS +.B veejay +.RI [ options ] " files" ... +.br +.B bar +.RI [ options ] " files" ... +.SH DESCRIPTION +This manual page documents briefly the +.B veejay +and +.B bar +commands. +.PP +.\" TeX users may be more comfortable with the \fB\fP and +.\" \fI\fP escape sequences to invode bold face and italics, +.\" respectively. +\fBveejay\fP is a program that... +.SH OPTIONS +These programs follow the usual GNU command line syntax, with long +options starting with two dashes (`-'). +A summary of options is included below. +For a complete description, see the Info files. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-v, \-\-version +Show version of program. +.SH SEE ALSO +.BR bar (1), +.BR baz (1). +.br +The programs are documented fully by +.IR "The Rise and Fall of a Fooish Bar" , +available via the Info system. +.SH AUTHOR +veejay was written by . +.PP +This manual page was written by root , +for the Debian project (but may be used by others). diff --git a/branches/V-1.5.3/veejay-server/debian/manpage.sgml.ex b/branches/V-1.5.3/veejay-server/debian/manpage.sgml.ex new file mode 100644 index 00000000..f563c857 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/manpage.sgml.ex @@ -0,0 +1,156 @@ + manpage.1'. You may view + the manual page with: `docbook-to-man manpage.sgml | nroff -man | + less'. A typical entry in a Makefile or Makefile.am is: + +manpage.1: manpage.sgml + docbook-to-man $< > $@ + + + The docbook-to-man binary is found in the docbook-to-man package. + Please remember that if you create the nroff version in one of the + debian/rules file targets (such as build), you will need to include + docbook-to-man in your Build-Depends control field. + + --> + + + FIRSTNAME"> + SURNAME"> + + November 4, 2008"> + + SECTION"> + nwelburg@gmail.com"> + + VEEJAY"> + + + Debian"> + GNU"> + GPL"> +]> + + + +
+ &dhemail; +
+ + &dhfirstname; + &dhsurname; + + + 2003 + &dhusername; + + &dhdate; +
+ + &dhucpackage; + + &dhsection; + + + &dhpackage; + + program to do something + + + + &dhpackage; + + + + + + + + DESCRIPTION + + This manual page documents briefly the + &dhpackage; and bar + commands. + + This manual page was written for the &debian; distribution + because the original program does not have a manual page. + Instead, it has documentation in the &gnu; + Info format; see below. + + &dhpackage; is a program that... + + + + OPTIONS + + These programs follow the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + Info files. + + + + + + + + Show summary of options. + + + + + + + + Show version of program. + + + + + + SEE ALSO + + bar (1), baz (1). + + The programs are documented fully by The Rise and + Fall of a Fooish Bar available via the + Info system. + + + AUTHOR + + This manual page was written by &dhusername; &dhemail; for + the &debian; system (but may be used by others). Permission is + granted to copy, distribute and/or modify this document under + the terms of the &gnu; General Public License, Version 2 any + later version published by the Free Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + + + +
+ + + + diff --git a/branches/V-1.5.3/veejay-server/debian/manpage.xml.ex b/branches/V-1.5.3/veejay-server/debian/manpage.xml.ex new file mode 100644 index 00000000..360876fc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/manpage.xml.ex @@ -0,0 +1,144 @@ + +.
will be generated. You may view the +manual page with: nroff -man .
| less'. A +typical entry in a Makefile or Makefile.am is: + +DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/\ +manpages/docbook.xsl +XP=xsltproc -''-nonet + +manpage.1: manpage.dbk + $(XP) $(DB2MAN) $< + +The xsltproc binary is found in the xsltproc package. The +XSL files are in docbook-xsl. Please remember that if you +create the nroff version in one of the debian/rules file +targets (such as build), you will need to include xsltproc +and docbook-xsl in your Build-Depends control field. + +--> + + + FIRSTNAME"> + SURNAME"> + + November 4, 2008"> + + SECTION"> + nwelburg@gmail.com"> + + VEEJAY"> + + + Debian"> + GNU"> + GPL"> +]> + + + +
+ &dhemail; +
+ + 2007 + &dhusername; + + &dhdate; +
+ + &dhucpackage; + + &dhsection; + + + &dhpackage; + + program to do something + + + + &dhpackage; + + + + + + + + DESCRIPTION + + This manual page documents briefly the + &dhpackage; and bar + commands. + + This manual page was written for the &debian; distribution + because the original program does not have a manual page. + Instead, it has documentation in the &gnu; + Info format; see below. + + &dhpackage; is a program that... + + + + OPTIONS + + These programs follow the usual &gnu; command line syntax, + with long options starting with two dashes (`-'). A summary of + options is included below. For a complete description, see the + Info files. + + + + + + + + Show summary of options. + + + + + + + + Show version of program. + + + + + + SEE ALSO + + bar (1), baz (1). + + The programs are documented fully by The Rise and + Fall of a Fooish Bar available via the + Info system. + + + AUTHOR + + This manual page was written by &dhusername; &dhemail; for + the &debian; system (but may be used by others). Permission is + granted to copy, distribute and/or modify this document under + the terms of the &gnu; General Public License, Version 2 any + later version published by the Free Software Foundation. + + + On Debian systems, the complete text of the GNU General Public + License can be found in /usr/share/common-licenses/GPL. + + + +
+ diff --git a/branches/V-1.5.3/veejay-server/debian/menu.ex b/branches/V-1.5.3/veejay-server/debian/menu.ex new file mode 100644 index 00000000..2f16bcfa --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/menu.ex @@ -0,0 +1,2 @@ +?package(veejay):needs="X11|text|vc|wm" section="Apps/see-menu-manual"\ + title="veejay" command="/usr/bin/veejay" diff --git a/branches/V-1.5.3/veejay-server/debian/postinst.ex b/branches/V-1.5.3/veejay-server/debian/postinst.ex new file mode 100644 index 00000000..72300385 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/postinst.ex @@ -0,0 +1,41 @@ +#!/bin/sh +# postinst script for veejay +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `configure' +# * `abort-upgrade' +# * `abort-remove' `in-favour' +# +# * `abort-remove' +# * `abort-deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + configure) + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-server/debian/postrm.ex b/branches/V-1.5.3/veejay-server/debian/postrm.ex new file mode 100644 index 00000000..ba9bbb69 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/postrm.ex @@ -0,0 +1,39 @@ +#!/bin/sh +# postrm script for veejay +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `purge' +# * `upgrade' +# * `failed-upgrade' +# * `abort-install' +# * `abort-install' +# * `abort-upgrade' +# * `disappear' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-server/debian/preinst.ex b/branches/V-1.5.3/veejay-server/debian/preinst.ex new file mode 100644 index 00000000..268e7319 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/preinst.ex @@ -0,0 +1,37 @@ +#!/bin/sh +# preinst script for veejay +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `install' +# * `install' +# * `upgrade' +# * `abort-upgrade' +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + install|upgrade) + ;; + + abort-upgrade) + ;; + + *) + echo "preinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-server/debian/prerm.ex b/branches/V-1.5.3/veejay-server/debian/prerm.ex new file mode 100644 index 00000000..9899b086 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/prerm.ex @@ -0,0 +1,40 @@ +#!/bin/sh +# prerm script for veejay +# +# see: dh_installdeb(1) + +set -e + +# summary of how this script can be called: +# * `remove' +# * `upgrade' +# * `failed-upgrade' +# * `remove' `in-favour' +# * `deconfigure' `in-favour' +# `removing' +# +# for details, see http://www.debian.org/doc/debian-policy/ or +# the debian-policy package + + +case "$1" in + remove|upgrade|deconfigure) + ;; + + failed-upgrade) + ;; + + *) + echo "prerm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +# dh_installdeb will replace this with shell code automatically +# generated by other debhelper scripts. + +#DEBHELPER# + +exit 0 + + diff --git a/branches/V-1.5.3/veejay-server/debian/rules b/branches/V-1.5.3/veejay-server/debian/rules new file mode 100755 index 00000000..930aa905 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/rules @@ -0,0 +1,137 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. +# +# Modified to make a template file for a multi-binary package with separated +# build-arch and build-indep targets by Bill Allombert 2001 + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This has to be exported to make some magic below work. +export DH_OPTIONS + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) + + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +config.status: configure + dh_testdir + # Add here commands to configure the package. +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --enable-debug --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs" + + +#Architecture +build: build-arch build-indep + +build-arch: build-arch-stamp +build-arch-stamp: config.status + + # Add here commands to compile the arch part of the package. + $(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)" + touch $@ + +build-indep: build-indep-stamp +build-indep-stamp: config.status + + # Add here commands to compile the indep part of the package. + #$(MAKE) doc + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-arch-stamp build-indep-stamp #CONFIGURE-STAMP# + + # Add here commands to clean up after the build process. + -$(MAKE) distclean + rm -f config.sub config.guess + + dh_clean + +install: install-indep install-arch +install-indep: + dh_testdir + dh_testroot + dh_clean -k -i + dh_installdirs -i + + # Add here commands to install the indep part of the package into + # debian/-doc. + #INSTALLDOC# + + dh_install -i + +install-arch: + dh_testdir + dh_testroot + dh_clean -k -s + dh_installdirs -s + + # Add here commands to install the arch part of the package into + # debian/tmp. + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + dh_install -s +# Must not depend on anything. This is to be called by +# binary-arch/binary-indep +# in another 'make' thread. +binary-common: + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb +# Build architecture independant packages using the common target. +binary-indep: build-indep install-indep + $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common + +# Build architecture dependant packages using the common target. +binary-arch: build-arch install-arch + $(MAKE) -f debian/rules DH_OPTIONS=-s binary-common + +binary: binary-arch binary-indep +.PHONY: build clean binary-indep binary-arch binary install install-indep install-arch diff --git a/branches/V-1.5.3/veejay-server/debian/veejay-default.ex b/branches/V-1.5.3/veejay-server/debian/veejay-default.ex new file mode 100644 index 00000000..4f040a0f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/veejay-default.ex @@ -0,0 +1,10 @@ +# Defaults for veejay initscript +# sourced by /etc/init.d/veejay +# installed at /etc/default/veejay by the maintainer scripts + +# +# This is a POSIX shell fragment +# + +# Additional options that are passed to the Daemon. +DAEMON_OPTS="" diff --git a/branches/V-1.5.3/veejay-server/debian/veejay-doc.docs b/branches/V-1.5.3/veejay-server/debian/veejay-doc.docs new file mode 100644 index 00000000..299950c5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/veejay-doc.docs @@ -0,0 +1,2 @@ +#DOCS# + diff --git a/branches/V-1.5.3/veejay-server/debian/veejay-doc.install b/branches/V-1.5.3/veejay-server/debian/veejay-doc.install new file mode 100644 index 00000000..299950c5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/veejay-doc.install @@ -0,0 +1,2 @@ +#DOCS# + diff --git a/branches/V-1.5.3/veejay-server/debian/veejay.1.ex b/branches/V-1.5.3/veejay-server/debian/veejay.1.ex new file mode 100644 index 00000000..c4acb483 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/veejay.1.ex @@ -0,0 +1,480 @@ +.TH "veejay" 1 +.SH NAME +veejay - a visual (video) instrument and video sampler for GNU/Linux +.SH SYNOPSIS +.B veejay [options] Videofile1 [Videofile2 ... VideofileN] +.SH DESCRIPTION +.B veejay +Veejay is a visual instrument and realtime video sampler. It allos you +to "play" the video like you would play a Piano and it allows you to +record the resulting video directly to disk for immediate playback (video sampling). + +Veejay can be operated live by using the keyboard (which is 100% user definable) +and remotely over network (both unicast and multicast) using an inhouse message +system that allows mapping of various protocols on top of it, including OSC. + +Veejay is beeing developed in the hope it will be usefull for VJ's , media artists +theathers and other interested users that want to use Free Software for their +performances and/or video installations. + +.TP +.SH Supported video codecs +.TP +MJPEG (either jpeg 4:2:0 or jpeg 4:2:2), YUV 4:2:0 i420/yv12 AVI, Quasar DV codec (only I-frames), MPEG4 (only I-frames) +.TP +.SH Supported video containers +AVI , QuickTime +.TP +.SH Audio +.TP +Veejay uses Jack , a low latency audio server, to transport (playback) audio in sync with video. This allows you to process veejay's audio output in another sound processing application. +.TP +.SH General Usage (How to work with veejay) +.TP +Veejay has a console- and a video window ; the console is used for displaying messages only. If the mouse is moved over to the video window, you can use the keyboard like a piano to play/manipulate the video. +.TP +You can start veejay with multiple files , video files and/or Mjpegtools' EditList files. Upon startup, veejay creates a new EditList in memory containing all the files you have loaded. As a result, all files will appear as a single large video file.Next you can start making selections (samples) of your EditList. These samples will be placed in so called 'sample banks' and they can be triggered for playback by pressing the F-keys (1 to 12). You can select a bank by pressing a number 1 to 9. +.TP +Note that if you change the EditList (for example , when deleting portions of your editlist) you should save your editlist as well as your samplelist. +.TP +You can select effects to put on your samples by pressing the cursor keys up and down, once you have found an effect you would like to use, press ENTER and it will be added to the current chain entry. The current chain entry can be changed with the PLUG and MINUS key on your numeric keyboard. Look at the KEYBINDS in this manual page to see what other possibilities you could have. +.TP +.SH Interactive camera/projection system +.TP +You can use veejay to calibrate a camera (or another input source) against a projector screen to map a physical position to veejay's projection. To use this feature, you can press CTRL\-s to activate the projection/camera calibration setup. This will render a graphical OSD on top of the video.Next, you need to play the live input source in order to find veejay's projection in the camera image. Set the points to the edges of the screen and right-click. Now press CTRL\-s or the middle mouse button to leave setup. Press CTRL-i to enable transforming the camera input and press CTRL-p to bring the projection screen in front. +.TP +.SH Interoperability +.TP +Veejay can be used with PD (PureData) by using sendVIMS, a small commandline utility that translates PD's symbols to veejay and vice versa.Look at the REFERENCES to find out where to download this utility. Also, by using the OpenSoundControl veejay can be used with a great number of sound and video processing applications.Also veejay can stream video data to STDOUT (-o stdout -O3) in yuv4mpeg format, or stream uncompressed video over the network (uni - and multicast) +.SH OPTIONS +.TP +.B \-w/--projection-width +Specify video output width for projection / on screen purposes +.TP +.B \-h/--projection-height +Specify video output height for projection / on screen purposes +.TP +.B \-p/--portoffset +TCP port offset for communication with clients like 'reloaded' , 'sayVIMS' or sendVIMS for PD (default 3490) +.TP +.B \-h/--host +Start as client of another veejay session (default is server) +.TP +.B \-o/--outstream +write video in YCbCr (YUV 4:2:0) format to specified file. Use this with -O3. +If you use 'stdout' here, veejay will be silent and write yuv4mpeg streams to STDOUT +.TP +.B \-O/--output [012345] +specify video output 0 = SDL (default) 1 = DirectFB 2 = SDL and DirectFB 3 = YUV4MPEG stream , 4 = Open GL (required ARB fragment shader), 5 = Silent (no visual output) +.TP +.B \-s/--size NxN +Scaled video dimensions for SDL video output +.TP +.B \-a/--audio [01] +Play audio 0 = off , 1 = on (default) +.TP +.B \-c/--synchronization [01] +Sync correction off/on (default on) +.TP +.B \-P/--preverse-pathnames +Do not 'canonicalise' pathnames in editlists +.TP +.B \-v/--verbose +verbosity on/off +.TP +.B \-t/--timer [012] +timer to use ( none, normal, rtc ) +.TP +.B \-f/--fps +Override framerate of video +.TP +.B \-x/--geometryx +Geometry x offset for SDL video window +.TP +.B \-y/--geometryy +Geometry y offset for SDL video window +.TP +.B \-l/--action-file +Configuration File to load at initialization. +The configuration file stores custom keybindings, custom bundles, available VIMS events, editlist,samplelist,streamlist +and commandline options. +.TP +.B \-b/--bezerk +Bezerk mode, if enabled it allows you to change input channels on the fly (without restarting the samples) +.TP +.B \-g/--clip-as-sample +Load every file on the commandline as a new sample +.TP +.B \-q/--quit +Quit at end of video +.TP +.B \-n/--no-color +Dont use colored text. +.TP +.B \-m/--memory [0-100] +Frame cache size in percentage of total system RAM +.TP +.B \-j/--max_cache [0-100] +Maximum number of samples to cache +.TP +.B \-F/--features +Show compiled in options +.TP +.B \-Y/--yuv [0123] +Force pixel format if you get a corrupted image. Its recommanded to load +only one videofile and re-record it. +.TP +.B \-d/--dummy +Start veejay with no video files (dummy mode). By default it will play black video (Stream 1 [F1]) +.TP +.B \-W/--width +Specify width of dummy video. +.TP +.B \-H/--height +Specify height of dummy video +.TP +.B \-R/--framerate +Specify framerate of dummy video +.TP +.B \-N [01] +Specify norm of dummy video (0=PAL, 1=NTSC). defaults to PAL +.TP +.B \-M/--multicast-osc
+Starts OSC receiver in multicast mode +.TP +.B \-T/--multicast-vims
+Setup additional multicast frame sender / command receiver. +The frame sender transmits on port offset + 3, send commands to port offset + 4, +.TP +.B \ /--map-from-file +To reduce transfers between memory and disk, you can set a number +of frames to be cached in memory from file (only valid for rawDV and AVI) +Use smaller values for better performance (mapping several hundreds of +megabytes can become a problem) +.TP +.B \-V/--viewport +Start with source viewport enabled. Use this if you have previously setup +a viewport. Use CTRL+v to enable the viewport setup. +.TP +.B \-A/--all +Start with all capture devices active as streams +.TP +.B \-D/--composite +Do not start with projection enabled. +.TP +.SH Environment variables +.TP +.B VEEJAY_SET_CPU +Tell veejay which CPU to use (and lock) for rendering. By default +veejay will lock CPU #1 if running on a SMP machine. +Use "0" to disable this behaviour. Use 1 for CPU#1, etc. +.TP +.SH Home directory +.TP +Veejay creates a new directory in your HOME , ".veejay". +.TP +.B .veejay/recovery +If veejay stops unexpectedly, it will try to save your samplelist and editlist before aborting. +.TP +.B .veejay/theme +Theme directory for GVeejayReloaded. +.TP +.B .veejay/plugins.cfg +If you want to load frei0r or freeframe plugins , set the paths +to the .so files in the plugins.cfg file. Only support for single +channel plugins. +.TP +.SH EXAMPLES +.TP +.B veejay -u |less +Startup veejay and list all events (VIMS/OSC) and effect descriptions +.TP +.B veejay -p 4000 ~/my_video1.avi +Startup veejay listening on port 4000 (use this to use multiple veejays) +.TP +.B veejay -d -W 352 -H 288 -R 25 -N 0 +Startup veejay using dummy video at 25 frames per second, dimensions 352x288 +and using PAL. +.TP +.B veejay movie1.avi -V 224.0.0.50 -p 5000 -n -v -L +Startup veejay, using multicast protocol on port 5000 , with autolooping +and no colored verbose output +.TP +.B veejay -O4 ~/my_video1.avi +Startup veejay with openGL video window +.TP +.SH INTERFACE COMMANDS (STDIN) +When you are running veejay with a SDL window you can use keybindings for +realtime interaction. See +.B KEYBINDINGS +for details. +.TP + +.SH KEYBINDINGS +.TP +.B [Keypad *] +Set sample looptype +.TP +.B [Keypad -] +Decrease chain index pointer +.TP +.B [Keypad +] +Increase chain index pointer +.TP +.B [Keypad 1] +Goto start of sample +.TP +.B [Keypad 2] +Go back 25 frames +.TP +.B [Keypad 3] +Goto end of sample +.TP +.B [Keypad 4] +Play backward +.TP +.B [Keypad 5] +Pause +.TP +.B [Keypad 6] +Play forward +.TP +.B [Keypad 7] +Goto previous frame +.TP +.B [Keypad 8] +Go forward 25 frames +.TP +.B [Keypad 9] +Goto next frame +.TP +.B [Keypad /] +Switch to Plain video playback mode (from Sample or Tag mode) +.TP +.B [LEFT BRACKET] +Set sample start +.TP +.B [RIGHT BRACKET] +Set sample end and create new sample +.TP +.B [ALT] + [LEFT BRACKET] +Set marker start +.TP +.B [ALT] + [LEFT BRACKET] +Set marker end and activate marker +.TP +.B [Backspace] +Delete current marker +.TP +.B [a,s,d,f,g,h,j,k,l] +Set playback speed to 1,2,3,4,5,6,7,8, or 9 +.TP +.B [ALT] + [a|s|d|f|g|h|j|k|l] +Set frame duplicator to 1,2,3,4,5,6,7,8 or 9. Interpolates missing frames. +.TP +.B [1..9] +Set sample range 0-12, 12-24, 24-36 etc. +.TP +.B ALT + [1..9] +Set channel ID 1-9, depending on sample range +.TP +.B [F1..F12] +Select and play sample 1 .. 12 +.TP +.B [DELETE] +Delete selected effect +.TP +.B [Home] +Print sample/tag information +.TP +.B [ESC] +Switch between Plain -> Tag or Sample playback mode +.TP +.B [CURSOR RIGHT] +Go up 5 positions in the effect list +.TP +.B [CURSOR LEFT] +Go back 5 positions in the effect list +.TP +.B [UP] +Go up 1 position in the effect list +.TP +.B [DOWN] +Go down 1 position in the effect list +.TP +.B [RETURN | ENTER] +Add selected effect from list to sample +.TP +.B [v] +Toggle sample's playlist +.TP +.B [-] +Decrease mixing channel ID +.TP +.B [=] +Increase mixing channel ID +.TP +.B SLASH +Toggle mixing source between Clips and Streams +.TP +.B [z] +Audio Fade in decrease (*) +.TP +.B [x] +Audio Fade in increase (*) +.TP +.B [b] +Toggle a selected effect on/off +.TP +.B [END] +Enable/Disable Effect Chain +.TP +.B [Left ALT] + [END] +Enable/Disable Video on selected Entry +.TP +.B [Right ALT] + [END] +Enable/Disable Audio on selected Entry +.TP +.B [LCTRL] + [END] +Enable/Disable Video on selected Entry +.TP +.B [RCTRL] + [END] +Enable/Disable Audio on selected Entry +.TP +.B [NUMLOCK] +Auto increment/decrement of a parameter-key +.TP +.B [n] +Decrease trimmer value of selected effect +.TP +.B [m] +Increase trimmer value of selected effect +.TP +.B [x] +Decrease audio volume (not functional) +.TP +.B [c] +Increase audio volume (not functional) +.TP +.B [0] +Capture frame to jpeg file +.TP +.B [PgUp] +Increase parameter 0 of selected effect +.TP +.B [PgDn] +Decrease parameter 0 of selected effect +.TP +.B [Keypad 0] +Decrease parameter 1 of selected effect +.TP +.B [Keypad .] +Increase parameter 1 of selected effect +.TP +.B [.] +Increase parameter 2 of selected effect +.TP +.B [,] +Decrease parameter 2 of selected effect +.TP +.B [QUOTE] +Increase parameter 3 of selected effect +.TP +.B [SEMICOLON] +Decrease parameter 3 of selected effect +.TP +.B [q] +Decrease parameter 4 of selected effect +.TP +.B [w] +Increase parameter 4 of selected effect +.TP +.B [e] +Decrease parameter 5 of selected effect +.TP +.B [r] +Increase parameter 5 of selected effect +.TP +.B [t] +Decrease parameter 6 of selected effect +.TP +.B [y] +Increase parameter 6 of selected effect +.TP +.B [u] +Decrease parameter 7 of selected effect +.TP +.B [i] +Increase parameter 7 of selected effect +.TP + +.B SHIFT + spacebar +Start keystroke recorder. The keystroke recorder +records most of the received VIMS messages and plays them +back in order and on the position you have pressed them. +Instead of using the keyboard, you can also use 'Reloaded', +and record the buttons pressed. However, some VIMS messages +are excluded from the keystroke recorder for safety reasons. +.TP +.B spacebar +(re)play recorded VIMS messages. The keystroke recorder +will jump to the starting position and replay all +recorded VIMS messages. +.TP +.B CTRL + spacebar +Clear recorded keystrokes. This clears all VIMS messages +in the current selected macro slot. +.TP +.B CTRL + [ F1 - F12 ] +Select a slot to record keystrokes to (default=0) +Use this if you want to record multiple keystrokes. You +can switch slots while in keystroke playback. +.TP +.B ALT + B +Take a snapshot of a video frame and put it in a seperate +buffer (used by some effects like Difference Overlay) +.TP +.B CTRL + s +Show/hide interactive camera/projector calibration setup +.TP +.B CTRL + p +Focus on front (primary output) or back (secundary input) projection +.TP +.B CTRL + i +Toggle current playing sample/stream as input source to be transformed +.TP +.B CTRL + v +Toggle grayscale/color mode for unicap streams +.TP +.B CTRL + h +Toggle OSD help for camera/projector setup +.TP +.B CTRL + o +Toggle OSD help for general status messages and mouse coordinates +.TP +.B CTRL + d +Toggle rendering of single source FX on underlying samples +.TP +.B CTRL + r +Start recording +.TP +.B CTRL + t +Stop recording +.TP +.SH REFERENCES +.TP +http://veejay.sourceforge.net +http://veejayhq.net +.SH BUGS +see BUGS in the source package +.SH AUTHOR +This man page was written by Niels Elburg. +If you have questions, remarks or you just want to +contact the developers, the main mailing list for this +project is: +.I http://groups.google.com/group/veejay-discussion/post?hl=en +For more info see the website at +.I http://veejayhq.net +.I http://veejay.dyne.org +.SH "SEE ALSO" +.B veejay sayVIMS diff --git a/branches/V-1.5.3/veejay-server/debian/veejay.doc-base.EX b/branches/V-1.5.3/veejay-server/debian/veejay.doc-base.EX new file mode 100644 index 00000000..574aea4f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/debian/veejay.doc-base.EX @@ -0,0 +1,22 @@ +Document: veejay +Title: Debian veejay Manual +Author: +Abstract: This manual describes what veejay is + and how it can be used to + manage online manuals on Debian systems. +Section: unknown + +Format: debiandoc-sgml +Files: /usr/share/doc/veejay/veejay.sgml.gz + +Format: postscript +Files: /usr/share/doc/veejay/veejay.ps.gz + +Format: text +Files: /usr/share/doc/veejay/veejay.text.gz + +Format: HTML +Index: /usr/share/doc/veejay/html/index.html +Files: /usr/share/doc/veejay/html/*.html + + diff --git a/branches/V-1.5.3/veejay-server/doc/COPYING b/branches/V-1.5.3/veejay-server/doc/COPYING new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/COPYING @@ -0,0 +1,339 @@ + 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 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 + + 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/branches/V-1.5.3/veejay-server/doc/HowtoCache.txt b/branches/V-1.5.3/veejay-server/doc/HowtoCache.txt new file mode 100644 index 00000000..524d328d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/HowtoCache.txt @@ -0,0 +1,8 @@ +Since version 0.9.3 veejay features a caching mechanism to load frames from disk into the system's memory. The cache size is limited to the amount of RAM available in your machine. If the cache is full, Veejay must decide which frames to discard. Veejay will discard the frame furthest away from the current position. + +You can configure the cache with two commandline options: + + -m / --memory [percentage of available RAM to use] + -j / --max_chain [maximum number of samples to cache] + +The second option, '-j' is used to divide up the cache memory into a number of equal sized chunks. Veejay will cache by default up to 8 samples into your system's main memory, if you specified the -m option. diff --git a/branches/V-1.5.3/veejay-server/doc/HowtoCompile.txt b/branches/V-1.5.3/veejay-server/doc/HowtoCompile.txt new file mode 100644 index 00000000..76a2a8c5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/HowtoCompile.txt @@ -0,0 +1,118 @@ + +Compiling Veejay Âĥ +Prerequisities Âĥ + +Required: + + * MJPEG Tools + * FFmpeg + * libxml2 for saving project data + * SDL for the video window + * libdv for playback of DV Video + * DirectFB for secundary head (TVOut) + * Jack for audio playback + * freetype2 for font rendering + * libjpegMMX for SIMD optimized JPEG decoding + * [http://www.gtk.org GTK-2.4 (GTK 2.6 recommended) + * [http://www.gnome.org GdkPixbuf (comes with Gnome) + * Cairo (needed for GVeejay Reloaded) + * GtkCairo (needed for GVeejay Reloaded) + * Libquicktime for Quicktime] + * openGL library (gl.h and libGL.so) for the video window + * Unicap API for more video input devices] + +You should check with the package manager of your distribution to see if all development packages have been installed, among others this includes: + + * libdv-dev + * cairo + * jack-dev + * glib >= 2.4 dev + * gtk >= 2.4 dev + * libglade >= 2.2 dev + * automake, autoconf, libtool, etc. + * linux kernel header files + +If you are one of those lucky users with a distribution without any compiler pre-installed you will need to setup a build system by installing a gcc, automake, autoconf, etc etc. + + * Compiling On Ubuntu: doc/HowtoUbuntu.txt + +Preperation Âĥ +Configuration Âĥ + +Before running configure, check if the PKG_CONFIG_PATH variable is setup correctly: + + $ echo $PKG_CONFIG_PATH + +If echo is silent, you must set the PKG_CONFIG_PATH to point to the directory containing all your .pc files (like for example libdv.pc or jack.pc ) + + $ find /usr -name libdv.pc + /usr/local/lib/pkgconfig/libdv.pc + + $ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig + +1. Get the sources from Veejay's repository: + + $ svn co svn://dyne.org/veejay/trunk/veejay/current + +2. Enter the source directory and run autogen.sh + + $ cd veejay-current + $ sh autogen.sh + +3. Run ./configure + + $ ./configure + +If you want to disable the graphical interfaces for some reason, use: + + $ ./configure --without-gveejayreloaded --without-gveejay + +Building Âĥ + +Type 'make' to build veejay + + $ make + +Installing Âĥ + + $ sudo make install + +or + + $ su + # make install + +Running veejay Âĥ + +Test if veejay works: + + $ veejay -d -n + +To run veejay without accelerated display: + + $ veejay -O5 -d -n + +To run veejay in verbose mode: + + $ veejay -O5 -d -n -v + +To run veejay with openGL display: + + $ veejay -O4 -d -n + +Start another terminal and type: + + $ gveejayreloaded + +or + + $ gveejayreloaded -n + +Stopping veejay Âĥ + +Open another terminal + + $ sayVIMS "600:;" + +(or press CTRL-C in the terminal running veejay) + diff --git a/branches/V-1.5.3/veejay-server/doc/HowtoPlugins.txt b/branches/V-1.5.3/veejay-server/doc/HowtoPlugins.txt new file mode 100644 index 00000000..99a764fb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/HowtoPlugins.txt @@ -0,0 +1,13 @@ + Âĥ + +First, you need to create a file to tell veejay where to find plugins. + + $ mkdir ~/.veejay + $ vi ~/.veejay/plugins + +The contents of the file can look like: + +/usr/local/lib/freeframe +/usr/local/lib/frei0r-1 + +Veejay will pick up the plugins the next time you start it. diff --git a/branches/V-1.5.3/veejay-server/doc/HowtoUbuntu.txt b/branches/V-1.5.3/veejay-server/doc/HowtoUbuntu.txt new file mode 100644 index 00000000..2785c5d8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/HowtoUbuntu.txt @@ -0,0 +1,23 @@ + + +To build the package from source yourself: + + +# 1 # get the required software + sudo devscripts apt-get install libgtk2.0-dev autotools-dev libx11-dev libxml2-dev libxinerama-dev libswscale-dev libsdl1.2-dev libavformat-dev libjack-dev libavcodec-dev libglib2.0-dev libquicktime-dev libmjpegtools-dev libjpeg62-dev libfreetype6-dev libdv4-dev libavutil-dev + + +# 2 # build a .deb package + dpkg-buildpackage -rfakeroot -us -uc -b + +# 3 # install + dpkg -i veejay-1.5.x.deb + + +To install the binary version: + +# 1 dpkg -i veejay-1.5.x.deb + +(meet package dependency requirements) +# apt-cache search +# apt-get install diff --git a/branches/V-1.5.3/veejay-server/doc/HowtoVeejay-PureData.html b/branches/V-1.5.3/veejay-server/doc/HowtoVeejay-PureData.html new file mode 100644 index 00000000..9e23c672 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/HowtoVeejay-PureData.html @@ -0,0 +1,503 @@ + + + + + Using sendVIMS to write simple control paches for veejay in +PureData + + +

Using sendVIMS to write simple control paches for veejay in PureData

+

M. van Henten cola at looze.net

+V0.01 104-10-09 +
+SendVIMS is a Puredata external written by Niels +Elburg and Tom Schouten. It is a control interface to veejay, a +realtime video processing package. +I will explain some of my work using both tools together. +
+

1. Introduction

+

+ SendVIMS is a Puredata external written +by Niels Elburg and Tom Schouten. It is a control interface to veejay, +a realtime video processing package. VIMS stands for 'Veejay's Internal +Messaging System.
+I have been working with veejay +for a long time now so I took my knowledge of what it could do and +built a few paches that will demonstrate the power of building +interactive controls for veejay. This might be interesting for the +newcomers to linux video, but also for the experienced who want to know +more about veejay, and puredata although it is not intended as step by +step guide on how to use PureData or veejay( Especially since I'm +rather new to PureData), but I will try to explain some basics on how +to get this working. +

+

1.1 Copyright

+

This document is Copyright © 104-10-09 M. van Henten. +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.1 or +any later version published by the Free Software Foundation with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +

+

1.2 Disclaimer

+

Use the information in this document at your own risk. I disavow any +potential liability for the contents of this document. Use of the +concepts, examples, and/or other content of this document is entirely +at your own risk. +

+

All copyrights are owned by their owners, unless specifically noted +otherwise. Use of a term in this document should not be regarded as +affecting the validity of any trademark or service mark. +

+

Naming of particular products or brands should not be seen as +endorsements. +

+

You are strongly recommended to take a backup of your system before +major installation and backups at regular intervals. +

+

1.3 News

+

9-10-2004 +Started Writing first draft to this howto, after finishing up on some +basic patches. +

+

1.4 Credits

+

Many thanks to of course to Tom Schouten en Niels Elburg for +creating this tool, thanks to Niels for creating veejay after numerous +sessions of feature dreaming, and continue working on it to create more +then we ever fantasized about.

+

Also, much obliged to the people in te PureData community, who +helped me getting started in the first place.Thanks to Derek Holzer, +who introduced me to PD and showed me how easy and fun PD was. +

+

A thankyou should be in place for the people at BEK ( +http://www.bek.no) Who brought a lot of video guys in the OS world +together, and made this collaboration possible in the first place. +

+

2. Technologies

+

2.1 Expected Skills
+

+

I assume that you know how to work with the linux commandline. +Veejay is ( up to this date) mainly a console application ( besides the +video bit of course) and you need to type stuff to get it working. If this is all +too strange for you, I would advice you to get know a bit more of linux +first, by reading some magazines, and some howto's ( the linux documentation project has a +lot of howto's) like the windows/dos +to linux howto.
+

+

2.2 Veejay
+

+

First of all, you need to download and install a later version of +veejay.  In this document, I used veejay-0.6.2. Any version before +0.5.9 will not work as expected, or not at all together with SendVims.
+

+

Veejay sources are located http://veejay.sourceforge.net, +or go directly to the sourceforge +download area.
+Installation is standard: open a shell, or terminal, unpack the package +somehwere, go into the newly created directory, and type:
+

+

./configure
+

+

when configure has finished, something like:
+

+

 veejay 0.6.2 build +configuration :
+
+ Build +configuration:
+                    +MMX +enabled                     +: true
+                    +MMX2 +enabled                    +: false
+                    +SSE +enabled                     +: true
+                    +3DNow +enabled                   +: false
+                    +CMOV +enabled                    +: true
+                    +glibc support for >2GB files    : true
+
+ Required +dependencies:
+                    +POSIX Threads (pthread)         +: true
+                    +video4linux recording/playback  : true
+                    +Simple Direct Media Layer       : true
+                    +XML C library for Gnome libxml2 : true
+                    +libJPEG                         +: true
+
+ Optional +dependencies:
+                    +libDV (digital +video)                 +: true
+                    +Jack Audio Connection Kit       : true
+                    +DirectFB +support                +: false

+
+

+Should appear.
+
+Note that veejay depends on the XML +C library ( it comes as part of the GNOME libraries and desktop) +and SDL, if you don't have these +packages you should install them. Libdv is optional, for being +able to play dv type 2 format avi's, jack is optional but needed +if you want to hear sound with your movies.
+
+Describing how to get jack working optimal is not within the scope of +this document, I can only say that if you have jack setup properly +veejay should be able to output sound.
+
+When this is done, do a "make" followed by a "make install".
+Veejay should now be installed. Get some movie to edit( you can borrow +one from me here)
+

2.2 PureData

+

PureData is a whole story upon itself. Please read the installation +notes and documentation on http://www.puredata.org. +You can verify if everything works by just running pd, goto help en +check out some of the example paches. Using the documentation  +from within pd you should at least get some basic understanding.
+

+

2.3 SendVims
+

+

In this document I used sendVIMS-0.1.
+This is compied from the README in sendVIMS-0.1.tar.gz :
+
+

+

sendVIMS +- very simple VeeJay client for pure data
+             +(C) 2002-2004 Niels Elburg <elburg@hio.hen.nl>
+             +(C) 2004 Tom Schouten <doelie@zzz.kotnet.org>
+
+This is free +software covered under the terms of the
+GNU GPL. See +the file COPYING for details.
+
+
+building:
+
+./configure +&& make && make install
+
+
+'make +install' copies these files to your pd directory:
+
+<prefix>/lib/pd/extra/sendVIMS.pd_linux
+<prefix>/lib/pd/doc/5.reference/help-sendVIMS.pd
+
+the default +<prefix> is /usr/local
+
+
+
+running:
+
+if the module +is in your pd path it will be loaded automaticly.

+

+

3. Implementation

+

3.1 Get veejay running
+

+

To start veejay, you need to start it with a video file. Veejay only +plays avi files, so no quicktime, or mpeg movies.
+Veejay only knows of two types of video codecs: mjpeg and DV type 2.0.
+So to get veejay running, you need at least one mjpeg or DV type 2.0 +.avi file. These formats were chosen with some reasons, explained in +the veejay-howto. Converting into codecs and other formats is a whole +science upon itself, and I do intend to write a crash course into video +and linux in the future. For creating mjpeg avi's I use the lavtools and mplayer, and veejay itself.
+

+

You can grab a one +second mjpeg avi from here.
+

+

This is copyright free material I transcoded out of a movie from archive.org
+Start veejay by opening up a terminal window such as xterm and type:
+

+

veejay +mymovie.avi

+

If you used the example one second avi, it will briefly play the +whole movie and stop at the last frame. Move your mouse into the video +window. As long as the mouse pointer is inside the video window, you +can use the built in keyboard controls. press keypad-5, this pauzes +playback. now press keypad-1, to skip to the start of your movie. press +the [ key, this marks 'clip start', press keypad-3, to skip to the end +of the movie, and press the ] key, this marks the 'clip end'. You can +now sellect your clip by pressing the F1 key. the movie will +automatically keep looping. you can alterate loopmode by pressing +keypad-*. try some other keypad keys to see what they do. See 'man +veejay' for the other controls.
+

+

3.2 Running PD/SendVIMS
+

+

Open up a terminal window such as xterm and type:
+

+

pd
+

+

You'll need the terminal to get some feedback from pd. From the file +menu of pd, choose 'new'. In the new window, choose 'put > object'.
+A rectangular object appears under your mousepointer. Click somewhere +in the white area of the window, and type "sendVIMS" inside the object. +If you installed the sendVIMS external properly, you should read  +in the terminal:
+

+

sendVIMS: +version 0.1
+sendVIMS: (c) +2004 Niels Elburg & Tom Schouten
+sendVIMS: +connected to localhost:3490

+

+

That's it! you should now be able to right-click on the sendVIMS +object, and choose 'help' from the popup window.
+You are now properly set up to use sendVIMS and veejay. Please refer to +some of the examples I provide under 'examples' for more information. +You should note that my examples will work right away, even without +understanding PD in the first place, but they are not intended as a +tutorial on how to use PD. you should see the 'help' menu and various +resources around the web for that!.
+

+


+

+

4. Troubleshooting

+

+4.1 Veejay doesn't start!
+

+

You need to start veejay from a terminal, using a proper encoded avi +file. you can use the demo +file if you don't have one.
+Please refer to veejay documentation and maillinglist.
+

+

4.2 SendVIMS doesn't work, PD tells +me it can't create sendvims.
+

+

The sendVIMS-0.1 external is not installed. please install the +external and restart PD.
+

+

4.3 I have a different problem, +please help me.
+

+

If the problem is relevant to this document please mail me and I'll add it here. Try the +PD and veejay maillinglist otherwise.
+

+

5. Further Information

+

5.1 HOWTO's and documentation
+

+

The veejay howto can be found here: http://veejay.sourceforge.net/veejay-HOWTO.html
+PureData documentation is here:   http://www.puredata.org
+

+

I have have been working on some more patches besides the ones in +the examples, they're on my personal homepage:
+http://cola.looze.net/sendvims/

+


+5.2 Email, Mailinglists

+

Please post your questions to the veejay mailinglist, you can +subscribe here.
+
+

+

6. Examples

+

6.1 Basic Example: play, play +backwards.
+

+

In PD, you send a message by creating a message object, type the +message into that object, and connect the output of the message to the +sendVIMS object.
+

+

Screenhost of example patch
+

+

In this example, I used PD aliasses: video.play.forward, and +video.play.backward. Normally, most VIMS messages are represented as +numbers, preceded by a 'p', for example, p100 stands for 'select and +play sample' followed by an argument. In the following example, you can +select different clips to play in veejay by changing the number inside +the number box. ( you can make diferent clips in veejay when in 'plain +video' mode, by pressing keypad '/'. Use keypad play controls to select +different frame positions, use the [ and ] keys to mark in and +outpoints of clips, use the function keys to select samples with the +keyboard controls).
+

+

6.2 Set the playing clip with an argument.
+

+

Set the playing clip with an argument
+

+

The $1 takes the number from the number box, and together with the +p100 message it gives the command "select and play sample $1" to +veejay. Note, that since PD doesn't know how many clips we have here, +we can select non-existing clips. We can give negative numbers. veejay +will give an error message.
+

+

6.3 Getting status output from +veejay.
+

+

This example shows how to get information you need from veejay: for +example the current frame.
+

+

Example of getting status information
+

+

Now, there are two number boxes. When playing clips, the first +number box will display the current frame, but when playing in plain +video, the second box outputs the current frame. Veejay sends it's +status in one big string of numbers, seperated by spaces. all +information comes in at the same time. You can use the 'unpack' object +to split the information in smaller chunks. notice how many outputs it +has - there are lots of status messages to be read. I have made a patch +that helps me remember what goes where, and I include it as a subpatch +when working with sendVIMS. You can find it on my personal weppage: http://cola.looze.net/sendvims.
+

+

6.4 Controlling video effects.
+

+

Veejay has many video effects. you can find out what kind of effects +on veejay's homepage, in the gallery section. For this next example, +you need two different clips. Assuming that you are working with the +example movie, press Keypad-5 for pauze, and Keypad-1 to go to the +start of the movie. Mark the beginning of your first clip here. Now, we +gently scrub to frame 12 in the movie using Keypad-9 - it skips one +frame ahead at a time - and mark the end of the first clip, and, on the +same frame, the beginning of the second clip, and at the last frame of +the movie, the end of the second clip( HINT: you could use the +"video.set.frame <frame>" message here instead).
+You should have two samples now, which you can select with the F1 and +F2 keys. Lets start with selecting the first clip and have a look at +the example:
+

+

example of effect controls
+

+

The first message sets up the effect chain. Veejay can chain +multiple effects on top of eachother, like layers in an image editing +program. In this example, it sets effect 4 on current playing sample ( +the number zero in the VIMS messages that control effects always stands +for the current playing clip, as a convenience. you could also replace +the number with a variable, and read it from veejay's output to know +the current clip).
+Effect 4 is the "Normal Overlay" effect, it simply mixes two video like +a videomixer.
+

+

The second message controls the clip the overlay effect mixes with. +Put it to 2 to mix with our second clip.
+The third message is a PD message, that controls the boundaries of the +slider. Normally, sliders have value 0 to 127 by default. the overlay +effect has only one controll, opacity, and it is mesured in value 0 to +255, so I want the slider to have boundaries ranging 0 to 255.
+The slider is connected to the third message: control parameter 0 of +the effect on chain-entry 3 of the current playing clip.
+The order of these values is typical: first, tell which sample to +select. second, what effect chain entry, third, which control +parameter, and last, the value of that parameter.
+You can make a dump of the effects numbers and the VIMS messages by +running:
+

+

veejay +--dump-events -d > veejay-events.txt
+

+

The last message, "connect localhost 3490" actually (re)connects the +sendVIMS object to veejay if not already connected. You can use the +message "disconnect" and "quit", too, have a look at the sendVIMS +helpfile.
+

+

6.5 More advanced playback control: +scrubbing.
+

+

This example shows two things: One slider can be used to set a new +play position in a clip, the other shows the play position in the +current clip.
+Both sliders get their boundaries updated with the starting position of +the clip and the ending position. This only works in the 'clip' mode, +not when playing in plain video.
+

+

Example of controlling play position with a slider
+

+

From the status, the starting frame and the end frame of the current +playing clip are read, which sets the boundaries of both sliders. The +slider in the top of the patch controls message p089: set frame $1, the +slider in the bottom gets updated with the 'current frame of clip' +information.
+However, when switching from clip to plain video mode, this will no +longer work as the outputs get different status updates. Switching +between clips wil work perfectly however.
+

+

More advanced combinations are possible. PD offers a lot of +functionality, such as MIDI, joystick controls and controlling things +through sound. Some more examples of my work are on my personal +website.
+

+


+

+


+

+


+

+ + diff --git a/branches/V-1.5.3/veejay-server/doc/HowtoVideoCodecs.txt b/branches/V-1.5.3/veejay-server/doc/HowtoVideoCodecs.txt new file mode 100644 index 00000000..1d836945 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/HowtoVideoCodecs.txt @@ -0,0 +1,83 @@ + +Video files Âĥ + +A video file consists out of TWO seperate elements: + + * container + * codec + +The container holds the digitally encoded data and the codec is capable of decoding/encoding this digitally encoded data. + +Veejay supports the AVI and the Quicktime container , with the following codecs: + +Quicktime: + + * mpjeg,mjpa,jpeg,dmb1 + * dvsd, dv, dvcp, dvhd + +AVI + + * mjpeg, mjpa,jpeg,jfif,dmb1 + * dvsd, dv, dvcp, dvhd + * i420, i422, yv16, hfyu + +Raw DV + + * PAL / NTSC dvsd + +Veejay can only deal with video files that consists entirely out of whole images (only I-frames). The codecs below will only work if all frames are I-frames. Otherwise, veejay will abort with an error message. + +AVI / Quicktime: + + * xvid, mp4v,divx,dxsd,mp4s,m4s2 + * div3,mp43,mp42,mpg4 + * avc1,h264,x264,davc,svq1,svq3,avc1 + +Wich codec to use Âĥ + +MotionJPEG ( mjpeg) is the veejay codec of choice for most applications, it gives you a good tradeof between compression, quality and compatibility. If you want speed, use AVI yv16 or i420 while recording to new samples. + +Tools that support MJPEG: + + * http://cvs.cinelerra.org/Cinelerra + * http://www.kinodv.org/Kino + * http://ronald.bitfreak.net/lvs/Linux video studio + * http://mjpeg.sourceforge.net/mjpegtools + * http://www.mplayerhq.huMplayer, and mencoder + * http://lives.sf.net Lives + +Wich resolutions to use Âĥ + +Veejay can do: + + * high definition (use MLZO/YUV avi) + * pal: 720x576 (recommended to use MLZO/YUV avi) + * ntsc: 720x480 + * 1/4 pal: 360x288 (any) + * 1/4 ntsc: 360x240 (any) + +If you load multiple video files on the commandline, make sure that all files have the same resolution and audio properties. +How to convert Âĥ + +Veejay can convert dv video to mjpeg for you, however, I prefer to use mplayer for this, wich has more flexibility. + +From "anything" mplayer can play to mjpeg, use: + + $ mencoder -ovc lavc -oac pcm -lavcopts vcodec=mjpeg -o + +To scale on the fly, use: + + $ mencoder -ovc lavc -oac pcm -lavcopts vcodec=mjpeg -vf scale=352:288 -o + +consult mplayer documentation about other options, such as cropping and filtering out blocks in video. + +a quick hint for bulk encoding a bunch of capture.dv files: + + $ for i in `ls *dv`;do mencoder -ovc lavc -oac pcm -lavcopts vcodec=mjpeg -o `echo $i | sed s/.dv/.avi/` $i; done; + +What is this dummy mode Âĥ + +Dummy mode opens up a 'color stream' to start veejay without a video file. + +If you use a video file, veejay will take that file's properties as default settings for the whole session. + diff --git a/branches/V-1.5.3/veejay-server/doc/INSTALL b/branches/V-1.5.3/veejay-server/doc/INSTALL new file mode 100644 index 00000000..b42a17ac --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/branches/V-1.5.3/veejay-server/doc/NET.txt b/branches/V-1.5.3/veejay-server/doc/NET.txt new file mode 100644 index 00000000..960ca11e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/NET.txt @@ -0,0 +1,112 @@ +Veejay stats +============ + +As of veejay 1.4.4, veejay server will make a hit on veejay.dyne.org +for collecting geographical data on veejay usage. +This is the HTTP request send: "GET /veejay- HTTP/1.1\nHost: veejay.dyne.org\n\n" +It is defined in vj-server.c and cannot be disabled. + +Veejay can stream over the Network +================================================= + +With -p you can give Veejay's port offset + +TCP socket for sending commands: + 0 (sayVIMS -h) +TCP socket for receiving status: + 1 (gveejay) +TCP socket for querying commands:+ 2 (gveejay - editlist/sampellist etc) +UDP multicast frame sender : + 3 (input stream multicast/other applications) +UDP multicast for sending commands: + 4 (sayVIMS -g) + + +How to activate: + +1. veejay movie1.avi +2. veejay movie2.avi -p 5000 + +(Both movie clips must have identical properties!!) + +veejay 2 makes a connection with veejay 1 + +3. sayVIMS "245:localhost 3490;" -p 5000 -h localhost + +4. move mouse to veejay2 video window and press 'ESC' + +if everything is OK, the video will be playing. + +5. stop veejay1 (CTRL-C) + +6. veejay2 will show last frame (press ESC) + +7. restart veejay1 + +8. press 'ESC' in veejay2 to resume streaming (auto-reconnect) + +Veejay can stream over the Network (UDP / Multicast ) +===================================================== + +How to activate: + +1. veejay -V 224.0.0.50 -p 5000 -v movie1.avi +2. veejay -d -W -H + +3. sayVIMS -h localhost -p 3490 "246:5000 224.0.0.50;" +4. press F7 to activate newest created stream + + +Veejay can receive OSC (Open Sound Control) messages over Multicast protocol +============================================================================ +How to activate: + +1. veejay --multicast 224.0.0.30 movie1.avi + +Note that you must have 'multicast' enabled in your kernel configuration. +Use the tool 'mcastOSC' in test/OSC to send OSC messages to all +veejay's you have started with --multicast (on multiple hosts!!) + +2. export MCAST_ADDR=224.0.0.30 +4. mcastOSC -r 3495 + + +Veejay can send/receive VIMS (Veejay Internal Message System) packets +over Multicast protocol +============================================================================= + +How to activate: + +1. veejay --multicast-vims 224.0.0.32 movie1.avi +2. veejay --multicast-vims 224.0.0.32 movie2.avi + +3. sayVIMS -g 224.0.0.32 -f test/vims/magicmirror-vims.txt + + +How to setup multicast? +======================= +1. enable 'multicast' in kernel configuration + +2. type 'route add -net 224.0.0.0 netmask 255.255.255.0 dev eth0' + (or something similar, read the man page of route to figure out + what addresses are reserved for multicast) + +What is multicast? +================== + +Multicasts enables you to (ab)use the network topology to transmit +packets to multiple hosts. + + +Limitations +=========== + +1. Veejay can only stream to another veejay +2. All veejays must have identical video properties (fps,width,height, ... ) +3. Veejay will drop frames when it cannot keep up (or when packets are dropped) +4. Audio is not supported + +What header format? +=================== + +see libvjnet/packet.h for multicast packet definition + +for peer-to-peer streaming, the first 11 bytes of the buffer indicate +width, height and format in plain ASCII: "%04d %04d %1d" + diff --git a/branches/V-1.5.3/veejay-server/doc/README.performance b/branches/V-1.5.3/veejay-server/doc/README.performance new file mode 100644 index 00000000..234cb133 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/README.performance @@ -0,0 +1,22 @@ + + Veejay's performace depends much on the memory bandwith, CPU and disk access. + + For HDTV (1280x720) mjpeg, you need at least a 2.5 ghz. The faster the better. + + For full PAL/NTSC resolutions (720x576 resp. 720x480) DV/Mjpeg you need at least a 1.5 ghz, + for lower resolution (352x288) you can do fine with a 500-800 mhz PC. + + If you need to record without framedrop, you can do so by disabling audio and + disabling synchronization with the commandline options -a0 -c0 + + On newer PC's (pentium4) your best bet is working in RAW or MLZO (compressed) + YUV 4:2:0 / 4:2:2 On my pentium 4 , 3.0 ghz playing a AVI file that contains RAW YUV frames + uses about 3-4% for a full PAL movie and 10-12% for mixing 2 movies. + The tradeoff here is your diskspeed. You could use compression, this reduces the + size of the videofile anywhere between 0-30% . + + Typical for laptops is slow diskspeed access, on my 1.8 ghz dell latitude laptop + the best I get is an average of about 20.0 mb/sec which is barely sufficient + for playing full PAL avi's containing RAW YUV. + (you can test yours with hdparm -T -t /dev/hdX) + diff --git a/branches/V-1.5.3/veejay-server/doc/README.quickstart b/branches/V-1.5.3/veejay-server/doc/README.quickstart new file mode 100644 index 00000000..a55cdb13 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/README.quickstart @@ -0,0 +1,110 @@ + +It is advised to read the howto and the MAN page as well. + +You can launch veejay with + +$ veejay -d + +This should show some moving black/white footage. Most of the effects will be boring on this footage, +so you can try to open your video4linux device with + +sayVIMS "240:0 1;" (device 0, channel 1) + +Or, to use mplayer, create a FIFO first: + +$ mkfifo stream.yuv + +Use something like 'mplayer -vo yuv4mpeg -x 352 -y 288 -vf scale -zoom' + +and open the stream in veejay's console: + +sayVIMS "243:stream.yuv;" + +Move your mouse pointer to the SDL window (so it dissapears) and press 'ESC' to +switch from the dummy footage to the last created or played video stream. + +Try loading an AVI file with something like: + +$ veejay -v mjpeg-video-file.avi + +The '-v' commandline option generates extra debugging output. + +By default, veejay uses a SDL window for displaying video. You can specify veejay to +write to STDOUT : + +$ veejay -O3 -o stdout mjpeg-video-file.avi | yuvplay + +In this mode, the console input and SDL keyboard functions are disabled. You must use +the sendVIMS commandline utility to interact with veejay or with an alternative utility like sendOSC. +Refer to the howto for more information. + + +Once you have loaded veejay (preferably with a videofile) + + (see man veejay for an overview of both console input and SDL keyboard events) + + press 'KP 1' , 'left bracket', 'KP 3', 'right bracket' , 'F1' + + This will create a virtual clip (in memory) from your entire video file. + + If you press 'KP divide' , veejay will return to plain video mode so you can create more clips. + If you press 'ESC' , veejay will switch from playing streams to playing clips or vice versa + + Press F1 to F12 to select a clip, + press 1 to 9 to select a bank (1 = clips 1 to 12, 2 = clips 12 to 24, etc ) + + Once you are playing a clip/stream, simply press + 'Cursor UP' , 'ENTER' + + If you add a video effect, try pressing '-' and '=' to select another channel and '/' to + toggle between clip/stream sources + + + Veejay supports chaining of effects since day 0, a number of keys have some importance + + '-' ,'=' and '/' + + 'END' for enabling/disabling the chain + 'KP -' for selecting the previous entry + 'KP +' for selecting the next entry + 'ALT+END' for enabling/disabling the current selected entry + 'ENTER' for adding an effect from the list to the chain + 'DEL' for removing an effect from the chain + + + Also, you can press 'HOME' to see clip or stream information. + + Try the keys 'A' to 'L' to increase/decrease playback speed. + + +Also, you can load some predefined custom effect chain templates that +will put a template on your effect chain when you press SHIFT + some alphabetic character + +First, load an action file + +$ veejay -l test/livecinema/action-file.xml + +Or in veejay's console + +> al test/livecinema/action-file.xml + +(activate a stream or clip and) press SHIFT+S or SHIFT+B or SHIFT+ ... + + +Except all that, try this: + + +sayVIMS -h localhost -p 3490 "241:63;" +(press F7) + +to open your dv1394 firewire device + +or +sayVIMS -h localhost -p 3490 "240:0 1;" +(press F7) + +to open your video4linux device /dev/video0, channel 1 + + + + Enjoy! diff --git a/branches/V-1.5.3/veejay-server/doc/README.whatis b/branches/V-1.5.3/veejay-server/doc/README.whatis new file mode 100644 index 00000000..9bc806ca --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/README.whatis @@ -0,0 +1,16 @@ +Veejay is a live performance tool featuring simple non-linear editing and mixing from multiple sources. You can load multiple video clips, cut and paste portions of video/audio and save it as an EditList. Also, you can record new clips from existing clips or (live) streams. With these clips you can change playback speed (slow motion/acceleration), change the looptype and set markers. + +With both clips and streams you can edit the effect chain and mix from multiple sources to one. Veejay has a 84+ effects, divided into two categories: Image and Video Effects, only with Video Effects you can select a channel to mix in. + +Veejay has many frame blending methods, some of these are: Additive,Substractive,Difference Negate, Relative Addition and Selective Replacement. Next to blending, you can key on Luma and Chroma seperatly or combined or simply use Transitions or other effects. + +Most edit and navigation commands are mapped to single key press commands, this allows you to control, depending on the playback mode, video navigation, the effect chain, effect parameters and clip properties at playback time. + +Also, you can record a new clip on the fly from a live feed or from the video clip you are playing. If requested, the recorded videofile will be added to the edit descision list and activated as a new video clip. This is particular usefull for time-looping,rebouncing and rough clip scratching/editing + +Veejay can be remotely controled through using OSC (Open Sound Control) or via its own internal message interface 'VIMS'. 'VIMS' allows you to create/load/save effect chain templates and to add customized events which can be triggered by a keypress or a remote message. + +Veejay supports streaming from multiple video sources to one, this can be a Video4Linux device , a vloopback device or a yuv4mpeg stream. You can chain several veejays with effectv and vice versa to create some amazing footage. + + +veejay is licensed as Free Software (GNU). diff --git a/branches/V-1.5.3/veejay-server/doc/VIMS.txt b/branches/V-1.5.3/veejay-server/doc/VIMS.txt new file mode 100644 index 00000000..e4abecc0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/VIMS.txt @@ -0,0 +1,318 @@ +1. VIMS is Veejay's IMS (Internal Message System) +================================================= + +All control data is distributed via VIMS. Each (atomical) message consists of an Action Identifier +and a list of zero or more Arguments which can be used to control Video Clips, Video Streams, +the Effect Chain and many other things. + +VIMS allows events to be triggered through: + +SDL Keyboard Event (libsdl) +OSC (OpenSoundControl) +IMP (Internal Message Protocol) + + +After intalling veejay, you will have a commandline utility 'sayVIMS' + +This document describes what messages you can send to veejay through using VIMS + +Inside of veejay's source package you will find a test/ directory containing various examples demonstrating +how to load an ActionFile, how to use Perl for batch like video processing and how to attach message bundles to +keyboard events. + + +Use the command + +$ veejay -u -n |less + +to see documentation generated by veejay on using Effects, VIMS and OSC. +If there is an error in the documentation, you have found a bug in veejay +and should report it :) + +1.1 Message Format +================== + +A message is described as: + + : ; + +Example: + + 080:; + 099:0 0; + + + +The action identifier is a 3 digit number describing a Network Event +The colon is used to indicate the start of the Argument List and must be given. + + + +The Argument List is described by a printf() style formatted template +which describes the number and type of arguments to be used. + +The semicolon must be given to indicate the end of this message + + + +1.2 Bundled Messages +==================== + +A message bundle is a special message that contains an ordered list of at least 1 or more messages. Each message is executed from left to right (first in, first out) while parsing the bundle. + + +Example: + + 5032|BUN:002{361:0 3 56 230 93 0;361:0 4 1 7;}| + 5033|BUN:003{361:0 3 56 230 93 0;361:0 4 1 7;361:0 5 1 7;}| + 5034|BUN:003{361:0 3 56 230 93 0;361:0 4 1 7;361:0 5 1 8;}| + + +A message bundle is described as: + + BUN: { + : ; + : ; + ... + } + ; + + +The token 'BUN:' indicates the start of a messaage bundle, the first 3 digit numeric value represents the total number of messages in the bundle. The '{' symbol indicates the start of a message block and is ended with '};' or just '}'. + + +1.3 Format of an Action File/Attaching Keys to Bundles +====================================================== + + <501 - 599> | | + +The contents of some action file can be : + + 516|BUN:001{355:;}| + + + +The message bundle BUN sends '355' for clear effect chain. +This message bundle is attached to action identifier 516. + +A key is attached to this function trough using the GUI (GVeejay) +or by using: + + +DYNAMIC KEYMAPPING: +================== + + "083:516 ;" + + +The message bundle can be attached to a key , for example 'SHIFT + A' by sending + + 083:516 97 3; + +Which attaches bundle '516' to SDL key '97' using a modifier '3', which is SHIFT. + +Modifiers: 0 = none, 1 = alt , 2 = ctrl, 3 = shift +Keys : see SDLkeysym.h somewhere in include/SDL/ + +If the number 0 is used for an event number, a given key combination can be +unset (wiped) : + + 083:0 97 3; + +Alternativly, you can bind keys to any action identifier. The complete +list can be viewd by typing veejay -u |less or with Gveejay. + + 083:20 97 0 4; + +The example above sets key 'a' to 'change video speed to 4' + + + +General description of VIMS messages +===================================== + + +Some reserved numbers: + + clip id 0 : select currently playing clip + clip id -1 : select highest clip number + chain entry -1 : select current chain entry + stream id 0 : select currently playing stream + stream id -1 : select highest stream number + key modifier : 0 = normal, 1= alt , 2 = ctrl, 3 = shift + frame -1 : use highest possible frame number (usually num video frames) + playback mode : 0 = clip, 1 = stream, 2 = plain + data format : yv16 (yuv 4:2:2 raw) , mpeg4, divx, msmpeg4v3, + div3, dvvideo, dvsd, mjpeg, i420 and yv12 (yuv 4:2:0 raw) + loop type : 0 = no looping, 1 = normal loop, 2 = pingpong (bounce) loop + + +What follows now is a general description of argument formatting and its ordering. +In the future, veejay -u will describe all VIMS arguments as well. +I wont put it into this document, since auto documentation will work much better +(eliminating the need to update this documentation when things change). + + all EditList commands, the arguments represent frame numbers (from 0 - max frames) + +For example; + 021:10 100; will copy frames 10-100 into a temporary buffer + 020:100; will insert the frames 10-100 from the temporary buffer on frame 100 + + +For all Clip commands, the first argument always represent the clip number except for 099 +(create new clip) which takes 2 arguments ; starting and ending positions. +The arguments that may follow usually represent a number to describe either a property setting +(like speed, slow motion or looptype) and in other cases relative or real frame numbers. + +Idem for Streams. + +In general, for Chain commands the first argument is also the clip or stream number. +The second (or following arguments) usually represent the property setting or some value. + +For example; 178 (fade in) takes 2 arguments. The first is to identify the clip number, +the second describes the duration (in frames) for the fade in. + +181 (set effect with defaults) takes 3 arguments. Again, the first is to identify a clip or +stream, the second for the chain entry and the last for the effect number. +Idem for 182, but here starting from the 4th argument it takes preset values + + + + +2. OSC - Open Sound Control +============================ + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl + +(quote from the website) + +OpenSound Control ("OSC") is a protocol for communication among computers, sound synthesizers +and other multimedia devices that is optimized for modern networking technology. + +Veejay starts up an OSC server that listens on port number VJ_PORT + 2 (usually 3492). +In the veejay/libOMC/send+dump you can compile a test application that sends OSC strings to veejay. +Bundled messages are handled automatically by libOMC + + +Type veejay -u |less to see an overview of all actions, it includes OSC. The OSC messages +are mapped onto its respective VIMS Action Identifiers. + + +EXAMPLES: + + To create a new clip and play it: + + /clip/new 100 200 + /clip/select 0 + + To record from a clip and auto play the recording after 10 seconds of PAL video: + + /clip/record/start 250 1 + + To add Effect 45 to the clip's Effect Chain + + /clip/chain/entry/add 45 + + To fade in the Effect Chain in 4 seconds + + /clip/chain/fade_in 100 + + To add Effect 45 on Entry 4 of clip 2's Effect Chain + + /clip/chain/add 2 4 45 + + To play newest clip + + /clip/select + + To record from a clip and auto play the new clip after recording + + /clip/record 100 1 + + + +currently, OSC support in veejay is meant for triggering only. +Some users have showed genuine interest in building user interfaces for Veejay using +this protocol. However, for such thing bi-directional communication is required +(i.e. current frame number, current playing clip, total number of clips, etc etc) + +In veejay, VIMS provides a status port that can be read which will provide all kind +of status information but it is not mapped to OSC yet. + +Also, in the veejay source package you will find a utility 'mcastOSC' +(which is not installed by default) + +Build instructions (from veejay top source directory) + +$ cd test/OSC +$ cd libOSC +$ make +$ cd .. +$ cd send+dump +$ make + +Start veejay with -M or --multicast-osc , and use mcastOSC to control +all instances of veejay listening on the given multicast address. +(One tool to rule all). + + +SAVING/RESTORING Veejay states +=============================== +Example configuration file (with most options) + + + + 3490 + + 352 + 288 + + + + 1 + + 2 + + 3 + + 0 + 0 + + 1 + + 0 + + 1 + + 352 + 288 + + 0.000000 + 0 + 0 + 0 + + 0 + + 0 + + + + + + +Initially, you can setup veejay on the commandline and tell it to save +its settings in a configuration file. + + veejay -z 1 -W 720 -H 576 /tmp/videofile.avi -p 5000 + +(in another terminal) + + sayVIMS -h localhost -p 5000 "084:/tmp/config.tmp 1;" + +In this file, not only the configuration is stored : +Bundled VIMS events, valid VIMS identifiers and Keymappings are +stored here. + + diff --git a/branches/V-1.5.3/veejay-server/doc/YCbCr.txt b/branches/V-1.5.3/veejay-server/doc/YCbCr.txt new file mode 100644 index 00000000..23c79a51 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/YCbCr.txt @@ -0,0 +1,23 @@ +Veejay processing +================= + + Veejay processes nativly in YUV, this is to keep colorspace conversions + to a minimum. + + YUV 4:2:0 Planar ( 1 Cr and 1 Cb sample per 2x2 Y samples) + YUV 4:2:2 Planar ( 1 Cr and 1 Cr sample per 1x2 Y samples) + (both full range JPEG and clipped to 16-235 / 16-240) + + Places where veejay uses software conversion: + Conversion from RGB to YUV is for webcam devices. + Conversion from YUV to RGB is for preview image + Some FX convert the frame to RGB + +Why YUV ? +========= + + - Many video codecs decode into some YUV flavour + - Many capture devices deliver YUV + - Software conversion of RGB <-> YUV is expensive + - Consumes less bandwith then RGB + diff --git a/branches/V-1.5.3/veejay-server/doc/veejay-HOWTO.html b/branches/V-1.5.3/veejay-server/doc/veejay-HOWTO.html new file mode 100644 index 00000000..9f6420a1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/doc/veejay-HOWTO.html @@ -0,0 +1,1439 @@ + + + + +veejay HOWTO (work in progress) + + +
+

Veejay HOWTO

+Matthijs van Henten ( cola@cb3rob.net )
+Niels Elburg ( nielselburg@yahoo.de )
+v1.0, 30 March 2003
+v1.1, 22 June 2003
+v1.2, 26 August 2003
+v1.3, 9 November 2003
+v1.4, 24 May 2004
+v2.0, 25 July 2004
+v2.1 27 January 2005
+v2.2 22 April 2005
+v3.0 8 March 2008
+
+This document describes how to use veejay, a visual 'music' instrument for Linux/GNU +

+ +
1.Introduction
+
1.1 Disclaimer
+
1.2 Acknowledgements
+
1.3 Audience and Intent
+
1.4 Revision History
+
1.5 New versions of this document
+
1.6 Feedback
+
1.7 Distribution Policy
+ +
2. About veejay
+
2.1 Features
+
2.2Hardware configuration
+
+ +
3. Installation
+
3.1 Dependencies
+
3.2 Installing veejay
+
3.3 Setting up multicast
+ +
4. Using Veejay
+
4.1 Terminology and limitations
+
4.2 VIMS
+
4.3 The keyboard interface
+
4.4 Recording video
+
4.5 Streaming video
+
4.6 Other utilities
+ +
5Popular packages
+
5.1EffecTV
+
5.2mplayer
+
5.3The MJPEG Tools
+
5.4Transcode
+
+
+ + + +
6.Other Resources
+
6.1Web Sites
+
6.2 Mailing Lists
+ +
7.Credits

+
8.GNU Free Documentation License
+


+ + +

1. Introduction

+

+ +

1.1 Disclaimer

+No liability for the contents of this documents can be accepted. Use the concepts, examples and other +content at your own risk. As this is a new edition of this document, there may be errors and inaccuracies, that may of course be damaging to your system. Proceed with caution, and although this is highly unlikely, the authors do not take any responsibility for that. +
+All copyrights are held by their respective owners, unless specifically noted otherwise. Use of a term in +this document should not be regarded as affecting the validity of any trademark or service mark. +
+Naming of particular products or brands should not be seen as endorsements. +
+You are strongly recommended to take a backup of your system before major installation and backups at regular intervals. +

+ +

1.2 Acknowledgements

+The following peope have been helpful in getting this HOWTO done: +

+ +

+ +

1.3 Audience and Intent

+This document is targeted at the Linux user interested in learning a bit about veejay and trying it out. +

+ +

1.4 Revision History

+Version 1.0 +

First version for public release
+Version 1.1 +
Updated Howto to match version 0.4.0. Revised chapters 2.2,4.4, 5.3 and 6
+Version 1.2 +
Updated Howto to match version 0.4.6. Revised chapter 2.1,2.2,3.3
+Version 1.3 +
Updated Howto to match version 0.5.3.
+Version 1.4 +
Updated Howto to match version 0.5.9
+Version 2.0 +
Partial re-write to match version 0.6
+Version 2.1 +
Updated Howto to match version 0.7.2
+Version 2.2 +
Updated Howto to match version 0.8
+Version 3.0 +
Large rewrite to match version 1.1
+

+ +

1.5 New versions of this document

+

+You will find the most recent version of this document at veejay.sourceforge.net/veejay-HOWTO.html.
+If you make a translation of this document into another langauge, let us know and we'll include a reference to it here. +

+ +

1.6 Feedback

+We rely on you, the reader, to make this HOWTO usefull. If you have any suggestions, corrections , or comments , please +send them to us ( veejay-users@lists.sourceforge.net ), and we will try to incorporate +them in the next revision. Please add 'HOWTO veejay' to the Subject-line of the mail. +
+Before sending bug reports or questions, please read all of the information in this HOWTO, and send detailed information about the problem. +
+If you publish this document on a CD-ROM or in hardcopy form, a complimentary copy would be appreciated. Mail us for our postal address. +Also consider making a donation to the Veejay Project to help support free video editing software in the future. + +

+ +

1.7 Distribution Policy

+Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, +Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, +with no Front-Cover Texts , and with no Back-Cover Texts. A copy of this license is included in the section entitled "GNU Free Documentation License". + +

+ + + +

2. About Veejay

+Veejay is a visual instrument and realtime video sampler. +It allows you to 'play' the video like you would play a Piano +and it allows you to record the resulting video directly to disk for +immediate playback (video sampling).
+
+Veejay consists out of several packages:
+

    +
  • veejay-server +
  • veejay-client +
  • veejay-tools +
  • veejay-themes +
+ + + + + + + + + + + + + + + + + +
+ veejay-server + + This is veejay +
+ veejay-client + + This is reloaded, the graphical user interface to veejay +
+ veejay-tools + + Commandline utilities to interface with veejay +
+ veejay-themes + + Themepack for reloaded +
+

+ +

2.1 Features

+ +

General

+
    +
  • Free Software (GNU GPL) +
  • Servent architecture +
  • Soft realtime +
  • Frame accurate +
  • Loop based editing +
  • Native YUV processing +
  • Crash recovery +
+ +

Media

+
    +
  • Codecs: MJPEG,MPNG, DV, YUV (raw) +
  • Containers: AVI , Quicktime, rawDV +
  • Devices: USB webcams, DV1394, TV capture cards, etc. +
  • Support for unlimited capture devices +
  • Support for Image files (PNG ,JPEG,TIFF,etc) +
+ +

FX processing

+
    +
  • 132 built-in FX , many unique and original FX filters +
  • FX chain (20 slots) +
  • All FX parameters can be animated. +
  • Mix up to two layers per FX slot +
+ +

Editing

+
    +
  • Non destructive edit decision lists (cut/copy/paste/crop video) +
  • Simple text editor +
  • Sample editor +
  • Sequence editor +
  • Live disk recorder (sampling) +
  • Full deck save/restore +
  • Live clip loading +
  • Live sample sequencing +
  • VIMS event recording/playback (6) +
  • Various looping modes including bounce looping +
  • Playback speed and direction +
  • Video scratching +
  • Change in-and out points of a sample (marker) +
  • Slow motion audio / video (7) +
  • Fast motion audio / video +
  • Dynamic framerate +
  • Random frame play +
  • Random sample play +
  • Access up to 4096 video samples instantly +
  • Full screen or windowed mode +
  • Perspective and foward projection +
+ +

Output

+
    +
  • Audio trough Jack (low latency audio server) (8) +
  • SDL and OpenGL video +
  • Headless +
  • YUV4MPEG streaming +
  • Network streaming (unicast and multicast) +
  • Preview rendering +
+ +

Input

+
    +
  • Programmable keyboard interface +
  • VIMS (tcp/ip) +
  • OSC (udp) +
  • PureData trough sendVIMS external +
  • Full screen or windowed mode +
+ +

Plugin systems

+
    +
  • Support for FreeFrame plugins +
  • Support for Frei0r plugins +
+ +

+ +

2.2 Hardware configuration

+ +Veejay requires at least a linux kernel 2.4.x, 2.6.x or later, a lot of diskspace and a fast CPU. +Depending on the speed of your machine, your milage may vary. See the list below for +a few systems veejay was reported to work on:
+

    +
  • An Intel Pentium 4 3.0 Ghz HT/512 MB DDR RAM with a ATI Radeon 9600 XT +
  • A dual celeron 400 Mhz/512 MB RAM with a voodoo3 and second pci card. +
  • An Athlon 750 Mhz with voodoo3 and second pci card. +
  • An Athlon 750 Mhz with Matrox G400 Dualhead(TVout using X11/SDL or DirectFB) +
  • An Athlon 850 Mhz and Matrox G550 Dualhead( TVout support through DirectFB) +
  • An Athlon XP 1600 Mhz and Matrox G550 Dualhead( TVout support through DirectFB) +
  • A Pentium 4 2.2 Ghz and Matrox G550 Dualhead( TVout support through DirectFB) +
  • A Pentium 4 3.0 Ghz and ATI Radeon 9600 XT/ (no TVout yet) +
  • Sony Playstation 2 (MIPS, little endian) (but runs very slow +/- 20 fps) +

+Video Editing requires a lot of diskspace, make sure you you have enough diskspace available for +your project. If you are going to use the recording functions, make sure you have sufficient free disk space available.Otherwise you are quite safe, veejay does not change your original video or fill your harddisk with needless temporary files. Neither does it waste your resources (unless you fill the effect chain with a lot of effects)
+

+ +

3. Installation

+

+ +

3.1 Dependencies

+Before you install Veejay, you should install the following software packages. +Although none of them is required, Veejay will be much less usable without them.
+

    +
  • (required) mjpegtools >= 1.9.0 +
  • (required) The XML C library 2 for gnome >= 2.5.4 +
  • (required) libunicap >= 0.2.0 +
  • (required) ffmpeg (libavcodec, etc) >= 0.50.0 +
  • (optional) libdv >= 1.02 +
  • (optional) The SDL library >= 1.2.3 +
  • (optional) JACK low latency audio server >= 0.98.1 +
  • (optional) DirectFB >= 0.9.17 +
  • (optional) FreeType >= 2.1.9 +
  • (optional) GTK >= 2.6.0 +
+
+On newer distributions, some of the listed software is already installed but you may be missing the -devel- packages! (especially on redhat, suse and debdian systems!!)

+You can find the websites of these projects in Other Resources.

+

+

3.1.0 From source

+You can compile the following packages from source if your distribution does not include them:
+

    +
  • libavcodec, libavutil, libswscale and libavformat from the FFmpeg project +
  • mjpegtools +
  • unicap +
  • gtkcairo +
+
+

FFmpeg

+

+You can download the ffmpeg sources from the SVN repository via http://ffmpeg.sourecforge.net" +After downloading and unpacking the source tarball, run the configure script with the following options:
+

+$ ./configure --enable-swscaler --enable-shared --enable-gpl
+...
+$ make
+# make install
+
+

+

+

MjpegTools, Unicap

+You can download the MjpegTools from http://mjpeg.sourceforge.net
+and the Unicap Imaging library from http://unicap.sourceforge.net
+
+Compilation of both packages is straightforward , in general the following will do it:
+
+$ ./configure && make
+# make install
+
+

+

GtkCairo

+

+ GtkCairo is available from the veejay repository. +

+
+

+

3.2 Installing veejay

+Verify that the PKG_CONFIG_PATH variable is set to the directory containing files like jack.pc and directfb.pc to include them in the build process. If it is not set , the configure script will abort with an error message. +

+$ echo $PKG_CONFIG_PATH   
+
+If nothing is set, do something like +
+$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
+
+Decompress and untar the file by typing: +
+$ tar -jxvf veejay-1.1.x.tar.bz2
+
+Change to the directory containing veejay's source's: +
+$ cd veejay-1.1.x
+
+$ ./configure
+
+On completion it will summarize the results of the ./configure script, which could look like this: +
+configure:  Veejay 1.1 build configuration :
+configure: 
+configure:  Compiler flags: -march=pentium4 -mtune=pentium4  -msse -mfpmath=sse 
+configure:                  -fif-conversion
+configure:                      -O3
+configure: 
+configure:  Architecture: i686 
+configure: 
+configure:    x86  
+configure:     MMX     enabled     : yes
+configure:     MMX2    enabled     : yes
+configure:     SSE     enabled     : yes
+configure:     SSE2    enabled     : yes
+configure:     3DNOW   enabled     : no
+configure:     CMOV    enabled     : yes
+configure: 
+configure:    Platform: Linux
+configure: 
+configure:  Required dependencies:
+configure:   - POSIX Threads (pthread)       : true
+configure:   - MJPEGTools                        : true
+configure:   - AVI MJPEG playback/recording  : true (always)
+configure:   - FFmpeg AVFormat               : true 
+configure:   - FFmpeg AVCodec                : true 
+configure:   - FFmpeg Swscaler           : true 
+configure:  Optional dependencies
+configure:   - SDL support                   : true
+configure:   - DirectFB support              : false
+configure:   - OpenGL support                : false
+configure:   - libDV (digital video) support : false 
+configure:   - QuickTime support             : false 
+configure:   - Unicap Imaging                : true 
+configure:   - video4linux                   : true
+configure:   - JPEG support                  : true 
+configure:   - GDK Pixbuf support            : true
+configure:   - Jack Audio Connection Kit     : false
+configure:   - XML c library for Gnome       : true
+configure:   - Freetype support              : true
+
+Now, you can start building veejay +
+$ make
+
+Followed by +
+# make install
+
+

+ +

3.3 Setting up multicast

+ +Multicast is a technology that reduces network traffic by +simultaneously delivering a single stream of information +to any interested recipient. +

+To enable multicast in Veejay, you must have enabled IP multicast +in your kernel configuration. +

+Finally you need to add a multicast route : +

+for 1 ethernet device:
+# route add -net 224.0.0.0 netmask 255.255.255.0 dev eth0
+
+for > 1 
+# route add -net 224.0.0.0 netmask 255.255.255.0 gw 192.168.100.1 dev eth1
+
+
+Next, Veejay can be started with the commandline flags +-M/--multicast-osc and/or -V/--multicast-vims +
+ +

+ +

4. Using Veejay

+Veejay uses by default a SDL window to play the video. +All the keybinding in veejay depend on SDL; if you move your mouse over to the +SDL windows to focus it , you can press the keys explained in 4.3 The keyboard interface.
+To use veejay in commandline style interface mode, see +4.2 sayVIMS.
+You must no longer provide a video file to use with veejay; it will run in dummy mode by +using the '-d' commandline parameter:
+

+$ veejay -d
+
+
+To use the graphical client with veejay: +
+$ reloaded -h localhost
+
+
+

+

4.1 Terminology and limitations

+Veejay has a number of playback modes, each playback mode is unique and defines more or less +a different functionality:

+Also, note that veejay runs in only 1 resolution at a time (depending on the video dimensions of +the first loaded movie). All movies loaded must have identical properties, otherwise veejay will not start. +This limitation is also valid when streaming video from veejay to another veejay.
+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Playback modes in veejay

ModeDescriptionNavigationLoopingSpeedEffect Chain
PlainDefault mode, playback of videoYesNoYesNo
SampleSample mode, playback of video samples.YesYesYesYes
TagTag mode, playback of video streamsNoNoNoYes
+ +

+ +

4.2 VIMS

+

+
+Use the command 
+$ veejay -u -n |less
+
+to dump all VIMS messages.
+
+1.1 Message Format
+==================
+
+A message is described as:
+
+	  :  ; 
+
+Example:
+
+	080:;
+	099:0 0;
+
+
+
+The action identifier is a 3 digit number describing a Network Event  
+The colon is used to indicate the start of the Argument List and must be given. 
+
+
+
+The Argument List is described by a printf() style formatted template 
+which describes the number and type of arguments to be used. 
+
+The semicolon must be given to indicate the end of this message
+
+1.2 Bundled Messages
+====================
+
+A message bundle is a special message that contains an ordered list of at least 1 or more messages. Each message is executed from left to right (first in, first out) while parsing the bundle.   
+
+
+Example:
+
+	5032|BUN:002{361:0 3 56 230 93 0;361:0 4 1 7;}|
+	5033|BUN:003{361:0 3 56 230 93 0;361:0 4 1 7;361:0 5 1 7;}|
+	5034|BUN:003{361:0 3 56 230 93 0;361:0 4 1 7;361:0 5 1 8;}|
+
+
+A message bundle is described as:
+
+	 BUN:  { 
+		 :  ;
+		 :  ;
+		... 
+		}
+		;
+
+
+The token 'BUN:' indicates the start of a messaage bundle, the first 3 digit numeric value represents the total number of messages in the bundle. The '{' symbol indicates the start of a message block and is ended with '};' or just '}'. 
+
+
+1.3 Format of an Action File/Attaching Keys to Bundles
+======================================================
+
+	<501 - 599> |  |
+
+The contents of some action file can be :
+
+	516|BUN:001{355:;}|
+
+
+
+The message bundle BUN sends '355' for clear effect chain.
+This message bundle is attached to action identifier 516.
+
+A key is attached to this function trough using the GUI (GVeejay)
+or by using: 
+
+
+DYNAMIC KEYMAPPING:
+==================
+
+	"083:516   ;"
+
+
+The message bundle can be attached to a key , for example 'SHIFT + A' by sending 
+	
+	083:516 97 3;
+
+Which attaches bundle '516' to SDL key '97' using a modifier '3', which is SHIFT. 
+
+Modifiers: 0 = none, 1 = alt , 2 = ctrl,  3 = shift
+Keys     : see SDLkeysym.h somewhere in include/SDL/
+
+If the number 0 is used for an event number, a given key combination can be
+unset (wiped) :
+
+	083:0 97 3;
+
+Alternativly, you can bind keys to any action identifier. The complete
+list can be viewd by typing veejay -u |less or with Gveejay. 
+
+	083:20 97 0 4;
+
+The example above sets key 'a' to 'change video speed to 4'
+
+
+
+General  description of VIMS messages
+=====================================  
+
+
+Some reserved numbers:
+
+	clip id		0	:	select currently playing clip	
+	clip id		-1	:	select highest clip number 
+        chain entry	-1      :   	select current chain entry 
+	stream id 	0	:	select currently playing stream 
+	stream id 	-1	:	select highest stream number
+	key modifier	        :	0 = normal, 1= alt , 2 = ctrl, 3 = shift
+	frame		-1	:	use highest possible frame number (usually num video frames)
+	playback mode   	:	0 = clip, 1 = stream, 2 = plain
+	data format     	: 	yv16 (yuv 4:2:2 raw) , mpeg4, divx, msmpeg4v3,
+					div3, dvvideo, dvsd, mjpeg, i420 and yv12 (yuv 4:2:0 raw)
+	loop type		:  	0 = no looping, 1 = normal loop, 2 = pingpong (bounce) loop
+
+

+

sayVIMS

+

+sayVIMS is a commandline utility distributed with the veejay package, +it allows you to give short commands in interactive mode

+$ sayVIMS -i -h localhost -p 3490

+Typing '?' followed by pressing ENTER gives the list of command below: +
+  vi [file]           Open video4linux device 
+  fi [file]           Open Y4M stream for input 
+  fo [file]           Open Y4M stream for output 
+  av [file]           Open (almost any) video file using FFmpeg 
+  mc [address] [port] Open a multicast UDP video stream 
+  pr [hostname][port] Open a unicast TCP video stream
+  cl [file]           Load cliplist from file 
+  cn [n1] [n2]        New clip from frames n1 to n2 
+  cd [n]              Delete clip n1 
+  sd [n]              Delete Stream n1 
+  cs [file]           Save cliplist to file 
+  es [file]           Save editlist to file 
+  ec [n1] [n2]        Cut frames n1 - n2 to buffer 
+  ed [n1] [n2]        Del franes n1 - n2  
+  ep [n]              Paste from buffer at frame n1 
+  ex [n1] [n2]        Copy frames n1 - n2 to buffer 
+  er [n1] [n2]        Crop frames n1 - n2 
+  al [file]           Action file Load 
+  as [file]           Action file save 
+  de                  Toggle debug level (default off) 
+  be                  Toggle bezerk mode (default on) 
+
+Also, you can send messages in VIMS format (or files, containing VIMS messages )

+For example, add the Pixelate effect on the Effect Chain of the current playing stream or clip: +
+sayVIMS -h localhost -p 3490 "361:0 0 150 3;"
+
+
+Last but not least, sayVIMS can parse files containing VIMS messages.
+See the test/examples directory of the package for a list of perl +scripts that output a VIMS script.
+
+sayVIMS -f advocate.vims -h localhost -p 3490
+
+
+Alternativly, you can start a secundary veejay and stream from peer to peer in uncompressed video: +
+
+$ veejay -d -p 5000
+
+$ sayVIMS -h localhost -p 5000 "245:localhost 3490;"
+
+(press 'F7' in veejay to display the stream, prob. stream 7)
+
+Or for multicast: +
+$ veejay -V 224.0.0.50 -p 5000 -n -L movie1.avi
+
+$ veejay -d 
+
+$ sayVIMS -h localhost -p 3490 "246:224.0.0.50 5000;"
+
+$ veejay -d -p 4000
+
+$ sayVIMS -h localhost -p 4000 "246:224.0.0.50 5000;"
+
+
+ +Or, if you want to play a XVID movie (or any other compressed format that is not I frame only): +
+$ sayVIMS -h localhost -p 3490 "244:/tmp/my-XVID-movie.avi;"
+
+ +

4.3 The keyboard interface

+Here is a quick overview for the most used default keys, if applied in order you will end up +with a newly created video sample looping in some way (depending on how many times you press the asterix key)
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Some keyboard bindings

DescriptionSDL key In plain english
Set the starting position of a new sampleSDLK_LEFTBRACKETLeft bracket
Set ending position and create a new sampleSDLK_RIGHTBRACKETRight bracket
Select and play sample 1SDLK_F1F1
Set playback speed to 3SDLK_dd
Change looptypeSDLK_KP_MULTIPLYasterix on numeric keypad
Play backwardSDLK_KP_4Cursor left on numeric keypad
Play forwardSDLK_KP_6Cursor right on numeric keypad
Skip 1 secondSDLK_KP_8Cursor up on numeric keypad
Switch playmode to PlainSDLK_KP_DIVIDEDivide on numeric keypad
Print information about sampleSDLK_HOMEHome
+

+The function keys F1...F12 can be used to select sample 1 ... 12, +use the keys 1...9 to select a sample range 1-12 ... 108-120 and press +one of the F-keys to play that sample.
+
+Use ESC to switch between samples and streams. +Press ESC again to switch back to the sample playmode
+You can create new input streams by using the console interface or by using GVeejay.
+All new input streams (and samples) are auto numbered.
+

+

+ +

4.4 Recording video

+You can record video to a new clip , by using the stream- or clip recorder functions.
+For example, to record a new clip from a playing clip in MJPG format:
+

+302:mjpg;
+
+Record 100 frames and start playing new clip when ready: +
+130:100 1;
+
+Record the whole clip and dont start playing new clip when ready: +
+130:0 0;
+
+If your Effect Chain is very CPU demanding , consider disabling audio and using the commandline parameter -c 0 to +disable sync correction.
+
+It is possible to start veejay headless and have it write all video data to +a (special) file for further processing.

+Refer to chapter 5.3 for some examples.

+ +

4.5 Streaming video

+You can create an input stream to read video coming from a video4linux device, from a pipe +or from a network socket (both unicast and multicast).
+

4.5.1 video4linux

+To open a video4linux device use gveejay or type the command:
+
+
+$ sayVIMS 240:0 1;
+
+The selector '240' tells veejay to open a video4linux device, the first argument '0' indicates +the device number (i.e. /dev/video0) and the last argument '1' indicates the video in port +of your capture card (in this case composite).
+Veejay will create a new stream see chapter 4.4 for activating the stream.
+

+

4.5.2 pipe

+Veejay supports reading video data from a pipe (FIFO) by means of an input stream.
+The only supported transport format is yuv4mpeg (yuv 4:2:0). When playing YUV 4:2:2 +the video stream will be sampled to YUV 4:2:0 and vice versa
+You can create the input stream by typing the command +
+$ sayVIMS 243:/tmp/stream.yuv;
+
+

4.5.3 network

+To get frames from another running veejay, use the command: +
+
+$ sayVIMS 245: ;
+
+For example, sayVIMS 245:localhost 5000;
+
+If you want to send the same video to multiple running veejays accross the network, +you can save bandwith by starting the veejay you wish to use as server with the -V option. +
+You can use the -V option to start an optional multicast frame sender.
+First, you need a multicast route in your routing table. See chapter 3.3 for +a short introduction +or consult a howto that disuccess setting up multicast for your operating system. +
+
+ +
+$ veejay -V 224.0.0.50 -p 5000
+
+ +Start another veejay, and use this command: +
+
+$ sayVIMS "246:5000 224.0.0.50;" 
+
+To create a new input stream. Start more veejays and use sayVIMS with the -p option to give +it a port offset number.
+

+

4.6 Other utilities

+ +Currently there are 4 extra utilities yuv2rawdv , rawdv2yuv , sayVIMS and any2yuv included in the veejay package for encoding +a Y'CBCR 4:2:0 stream to raw DV and vice versa. +

+ +yuv2rawdv takes input from STDIN and outputs to STDOUT, we illustrate this with +a few examples.
+
+When loading yuv2raw dv without parameters you will see:
+

+This program reads a YUV4MPEG stream and puts RAW DV to stdout
+Usage:  yuv2rawdv [params]
+where possible params are:
+    -v num    Verbosity [0..2] (default 1)
+    -l num    Clamp Luma (default 0)
+    -c num    Clamp Chroma (default 0)
+
+ +If you use the clamp parameters, it will clip (not scale!) a pixel into a valid range, +the resulting video could be for example a bit darker if the input stream has values for +Luminance exceeding the maximum of 235.
+See the table below for all valid ranges. + + + + + + + + + + + + + + + + + + + + + + + + + + +

Y'CBCR

ChannelRange (Clamp)Byte range (no clamping)
Y (Luminance)16 - 2350 - 255
Cb (Chroma Blue)16 - 2400 - 255
Cr (Chroma Red) 16 - 2400 - 255
+
+ +To convert a yuv4mpeg file to rawdv (the yuv4mpeg file needs to be compatible with the +digital video format properties)
+
$ cat yuv4mpeg-file.yuv | yuv2rawdv | playdv
+

+To convert a yuv4mpeg file to rawdv with luminance and chroma information clipped +to a valid range:
+
$ cat yuv4mpeg-file.yuv | yuv2rawdv -l 1 -c 1 | playdv
+
+ +

+rawdv2yuv takes input from STDIN and outputs to STDOUT, we illustrate this with +a few examples.
+ +
+This program reads a raw DV stream from stdin and puts YV12/I420 to stdout
+Usage:  rawdv2yuv [params]
+where possible params are:
+   -v num     Verbosity [0..2] (default 1)
+   -x         Swap Cb/Cr channels to produce IV12 (default is I420)
+   -n num     Norm to use: 0 = NTSC, 1 = PAL (default 1)
+   -q         DV quality to fastest (Monochrome)
+   -h         Output Half frame size
+   -c num     clip off  rows of frame (for use with -h)
+              must be a multiple of 8
+
+
+If you want to convert a full PAL/NTSC dv frame to half PAL YCbCr (I420 or YV12) you can +give the command: +
+
+$ cat raw.dv | rawdv2yuv -h | yuvplay
+
+You can use the -c parameter to clip the width of the video frame.
+
+$ cat raw.dv | rawdv2yuv -h -c 8 | yuvplay
+
+The resizer in rawdv2yuv uses a best neighbour interpolation algorithm for downsizing.
+ +

+any2yuv takes input from STDIN and puts YV12/I420 to stdout: +
+This program reads anything from stdin and puts YV12/I420 to stdout
+Usage:  any2yuv [params]
+where possible params are:
+   -v num     Verbosity [0..2] (default 1)
+   -x         Swap Cb/Cr channels to produce IV12 (default is I420)
+   -n num     Norm to use: 0 = NTSC, 1 = PAL (default 1)
+
+
+

+sayVIMS can be used to send commands or files to batch-process to veejay +
+Usage: sayVIMS [options] [messages]
+where options are:
+ -p             Veejay port (3490)
+ -h             Veejay host (localhost)
+ -g			    Veejay multicast address (224.0.0.50)
+ -f   Send contents of this file to veejay
+ -c             Colored output (geek feature)
+
+Messages to send to veejay must be wrapped in quotes
+You can send multiple messages by seperating them with a whitespace
+
+

+ +

+ +

5 Popular Packages

+Usefull software (in no apparant order): +

    +
  • The MJPEG Tools +
  • Transcode +
  • PureData (PD) +
  • PDP for PD +
+Please refer to Other Resources to find the project's website
+

+

5.1 The MJPEG Tools

+

The Mjpeg tools are a set of tools that can do recording of videos and playback, simple cut-and-paste +editing and the MPEG compression of audio and video under Linux. +You can use the EditLists from this package in veejay and vice versa
+ +Here are a few examples for processing video data:

+ +1. Start veejay headless: +

+$ mkfifo /tmp/special_file
+$ veejay /video/video.avi -O3 -o /tmp/special_file
+
+
+Encoding it to DV avi type 2 (if video dimensions match either full PAL or NTSC) +
+$ cat /tmp/special_file | yuv2rawdv -v 2 > rawdv
+
+
+Encoding it to MJPEG file 'video-mjpeg.avi' +
+$ cat /tmp/special_file | yuv2lav -v2 -f 0 -I 0 -q 90 -o video-mjpeg.avi
+
+Encoding veejay output to MJPEG file: +
+$ veejay movie1.avi -o stdout -O3 | yuv2lav -f 0 -I 0 -q 90 -o movie1-mjpeg.avi
+
+ +

+ +

5.2 Transcode

+

Transcode is a Linux video Stream Processing Tool, it can convert between different types of video formats
+
+Encode a file to mjpeg with no audio and rescale the output video to 352x288:

+

$ transcode -i input_file.avi -o new_mjpeg_file.avi -y mjpeg,null -Z352x288
+
+

+ + + + +

6. Other Resources

+Here you will find the websites of the packages veejay requires as well as packages +you can use in combination with veejay. +

6.1 Web Sites

+

Packages you need

+ +

+

+

Usefull software

+ +

+

6.2 Mailing Lists

+There is a mailing list for veejay which is hosted by Sourceforge. +The address is veejay-users@lists.sourceforge.net +

+

+

6.3 Veejay developer's lounge

+Veejay's developer lounge provides a ticket system for you , the user, to report +any problem or feature requests. The ticket system allows us to keep track of +problems.
+Also, the developer lounge hosts a subversion code repository where you can +find the 'on the bleeding edge' source codes of veejay.
+Many thanks to jaromil (author of FreeJ/Muse) and the Dyne Foundation for providing these tools
. +

+ +

7. Credits

+End of the Veejay HOWTO. (You can stop reading here.) +

+ +

8. GNU Free Documentation License

+ +

GNU Free Documentation License + +

Version 1.1, March 2000 + +

Copyright (C) 2000 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. + +

0. PREAMBLE + +

The purpose of this License is to make a manual, textbook, or other +written document "free" in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +

This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +

We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + +

1. APPLICABILITY AND DEFINITIONS + +

This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The "Document", below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as "you". + +

A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +

A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +

The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +

The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +

A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not "Transparent" is called "Opaque". + +

Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +

The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + +

2. VERBATIM COPYING + +

You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +

You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + +

3. COPYING IN QUANTITY + +

If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +

If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +

If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +

It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + +

4. MODIFICATIONS + +

You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +

A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five). +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section entitled "History", and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. In any section entitled "Acknowledgements" or "Dedications", + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section as "Endorsements" + or to conflict in title with any Invariant Section. + +

If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +

You may add a section entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties-for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +

You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +

The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + +

5. COMBINING DOCUMENTS + +

You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +

The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +

In the combination, you must combine any sections entitled "History" +in the various original documents, forming one section entitled +"History"; likewise combine any sections entitled "Acknowledgements", +and any sections entitled "Dedications". You must delete all sections +entitled "Endorsements." + +

6. COLLECTIONS OF DOCUMENTS + +

You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +

You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + +

7. AGGREGATION WITH INDEPENDENT WORKS + +

A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an "aggregate", and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +

If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + +

8. TRANSLATION + +

Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. + +

9. TERMINATION + +

You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document 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. + +

10. FUTURE REVISIONS OF THIS LICENSE + +

The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation 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. See +http://www.gnu.org/copyleft/. + +

Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + +

ADDENDUM: How to use this License for your documents + +

To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + +

    Copyright (c)  YEAR  YOUR NAME.
+    Permission is granted to copy, distribute and/or modify this document
+    under the terms of the GNU Free Documentation License, Version 1.1
+    or any later version published by the Free Software Foundation;
+    with the Invariant Sections being LIST THEIR TITLES, with the
+    Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.
+    A copy of the license is included in the section entitled "GNU
+    Free Documentation License".
+
+ +

If you have no Invariant Sections, write "with no Invariant Sections" +instead of saying which ones are invariant. If you have no +Front-Cover Texts, write "no Front-Cover Texts" instead of +"Front-Cover Texts being LIST"; likewise for Back-Cover Texts. + +

If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. + + + +

+ + + diff --git a/branches/V-1.5.3/veejay-server/libOSC/AUTHORS b/branches/V-1.5.3/veejay-server/libOSC/AUTHORS new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/AUTHORS @@ -0,0 +1 @@ + diff --git a/branches/V-1.5.3/veejay-server/libOSC/Makefile.am b/branches/V-1.5.3/veejay-server/libOSC/Makefile.am new file mode 100644 index 00000000..657a8fc3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/Makefile.am @@ -0,0 +1,23 @@ +INCLUDES = -I$(top_srcdir)/libOSC -I$(includedir) +AM_CFLAGS=$(OP_CFLAGS) +OSC_LIB_FILE = libOSC.la +noinst_LTLIBRARIES = $(OSC_LIB_FILE) +libOSC_la_CFLAGS = $(AM_CFLAGS) +libOSC_la_SOURCES = OSC-address-space.c \ + OSC-callbacklist.c \ + OSC-drop.c \ + OSC-pattern-match.c \ + OSC-priority-queue.c \ + OSC-receive.c \ + OSC-string-help.c \ + OSC-common.c \ + OSC-timetag.c \ + NetworkReturnAddress.c + +EXTRA_DIST= libosc.h OSC-address-space.h OSC-dispatch.h \ + OSC-pattern-match.h OSC-string-help.h NetworkReturnAddress.h \ + OSC-callbacklist.h OSC-drop.h OSC-priority-queue.h \ + OSC-struct.h NetworkUDP.h OSC-common.h \ + OSC-internal-messages.h OSC-receive.h \ + OSC-timetag.h + diff --git a/branches/V-1.5.3/veejay-server/libOSC/NEWS b/branches/V-1.5.3/veejay-server/libOSC/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/branches/V-1.5.3/veejay-server/libOSC/NetworkReturnAddress.c b/branches/V-1.5.3/veejay-server/libOSC/NetworkReturnAddress.c new file mode 100644 index 00000000..07418215 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/NetworkReturnAddress.c @@ -0,0 +1,58 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + +/* + NetworkReturnAddress.c + + This version implements UDP return addresses on SGI + + Matt Wright, + 9/11/98 +*/ + +#include +#include +#include +#include +#include +#include +#include + + + +int SizeOfNetworkReturnAddress(void) { + return sizeof(struct NetworkReturnAddressStruct); +} + +Boolean NetworkSendReturnMessage(NetworkReturnAddressPtr addr, + int n, + void *buf) { + if (addr == 0) return FALSE; + + return n == sendto(addr->sockfd, buf, n, 0,(const struct sockaddr*) &(addr->cl_addr), addr->clilen); +} diff --git a/branches/V-1.5.3/veejay-server/libOSC/NetworkReturnAddress.h b/branches/V-1.5.3/veejay-server/libOSC/NetworkReturnAddress.h new file mode 100644 index 00000000..086cc00f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/NetworkReturnAddress.h @@ -0,0 +1,52 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + NetworkReturnAddress.h + + API that the OSC Kit uses to deal with network return addresses. You will + fill in parts of this file and write NetworkReturnAddress.c to implement + this API via whatever network services you use. + + NB: This API is the only interface the Kit uses for dealing with network + addresses, but of course the part of the application that accepts incoming + packets needs to know about network return addresses so it can fill in the + correct return address when it receives a packet. + + Matt Wright, + 6/3/98 +*/ + +/* Return sizeof(struct NetworkReturnAddressStruct). */ +int SizeOfNetworkReturnAddress(void); + +/* Send a packet back to the client, or do nothing if addr==0 */ +Boolean NetworkSendReturnMessage(NetworkReturnAddressPtr addr, + int n, + void *buf); diff --git a/branches/V-1.5.3/veejay-server/libOSC/NetworkUDP.h b/branches/V-1.5.3/veejay-server/libOSC/NetworkUDP.h new file mode 100644 index 00000000..7f693250 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/NetworkUDP.h @@ -0,0 +1,7 @@ +#include + +struct NetworkReturnAddressStruct { + struct sockaddr_in cl_addr; + int clilen; + int sockfd; +}; diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-address-space.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-address-space.c new file mode 100644 index 00000000..63437602 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-address-space.c @@ -0,0 +1,599 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + OSC-address-space.c + Matt Wright, 3/16/98 +*/ +#include +#include +#include +#include +#include + +#include + +#define MAX_ALIASES_PER_CONTAINER 3 +#define MAX_CHILDREN_PER_CONTAINER 32 +#define MAX_METHODS_PER_CONTAINER 32 +#define BASE_NUM_TO_REALLOCATE 10 + + +struct OSCContainerStruct { + struct OSCContainerStruct *parent; + int numChildren; + Name childrenNames[MAX_CHILDREN_PER_CONTAINER]; + struct OSCContainerStruct *children[MAX_CHILDREN_PER_CONTAINER]; + int numMethods; + Name methodNames[MAX_METHODS_PER_CONTAINER]; + OSCMethod methods[MAX_METHODS_PER_CONTAINER]; + struct OSCContainerQueryResponseInfoStruct QueryResponseInfo; + struct OSCContainerStruct *next; +}; + +struct OSCMethodStruct { + methodCallback callback; + void *context; + struct OSCMethodQueryResponseInfoStruct QueryResponseInfo; + struct OSCMethodStruct *next; +}; + +/* Globals */ +static Boolean Initialized = FALSE; +static OSCcontainer OSCTopLevelContainer; +static OSCcontainer freeContainers; /* Linked list via next field. */ +static OSCMethod freeMethods; /* Linked list via next field. */ +static void *(*RealTimeMemoryAllocator)(int numBytes); + + +/* Note: The free list of containers should actually be a "free forest", so + that all the subcontainers recursively under a freed container are + automatically freed. + + FREE: just stick the freed subtree on the front of the list. + + ALLOC: Take all the children of the first container on the list and + insert them in the free list, then return that first container. + +*/ + + + +/************************ Initialization and Memory ************************/ + +static void MakeFreeContainersList(int n) { + int i; + + for (i = 0; i+1 < n; ++i) { + freeContainers[i].next = &(freeContainers[i+1]); + } + freeContainers[n-1].next = 0; +} + +static void MakeFreeMethodsList(int n) { + int i; + + for (i = 0; i+1 < n; ++i) { + freeMethods[i].next = &(freeMethods[i+1]); + } + freeMethods[n-1].next = 0; +} + +OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t) { + int bytesNeeded; + + if (Initialized) + fatal_error("OSCInitAddressSpace: already initialized!"); + Initialized = TRUE; + + RealTimeMemoryAllocator = t->RealTimeMemoryAllocator; + + bytesNeeded = (1 + t->initNumContainers) * sizeof(*freeContainers); + freeContainers = (OSCcontainer) (*(t->InitTimeMemoryAllocator))(bytesNeeded); + if (freeContainers == 0) { + fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d containers", + bytesNeeded, t->initNumContainers); + } + + OSCTopLevelContainer = &freeContainers[t->initNumContainers]; + MakeFreeContainersList(t->initNumContainers); + + bytesNeeded = t->initNumMethods * sizeof(*freeMethods); + freeMethods = (OSCMethod) (*(t->InitTimeMemoryAllocator))(bytesNeeded); + if (freeMethods == 0) { + fatal_error("OSCInitAddressSpace: couldn't allocate %d bytes for %d methods", + bytesNeeded, t->initNumMethods); + } + MakeFreeMethodsList(t->initNumMethods); + + /* Initialize the top-level container */ + OSCTopLevelContainer->parent = 0; + OSCTopLevelContainer->numChildren = 0; + OSCTopLevelContainer->numMethods = 0; + OSCTopLevelContainer->QueryResponseInfo.comment = "OSC top-level container"; + OSCTopLevelContainer->next = 0; + + return OSCTopLevelContainer; +} + + +/* Container and method memory management: linked lists of free objects */ + +static OSCcontainer AllocContainer(void) { + static int numExtraAllocs = 0; + + OSCcontainer result; + if (freeContainers != 0) { + result = freeContainers; + freeContainers = freeContainers->next; + return result; + } + + OSCWarning("Out of memory for containers; trying to allocate more in real time"); + { + int num = BASE_NUM_TO_REALLOCATE * ++numExtraAllocs; + freeContainers = (*RealTimeMemoryAllocator)(num * sizeof(*freeContainers)); + if (freeContainers == 0) { + OSCWarning("Real-time allocation failed"); + return 0; + } + MakeFreeContainersList(num); + return AllocContainer(); + } +} + +//static void FreeContainer(OSCcontainer c) { +// c->next = freeContainers; +// freeContainers = c; +//} + +static OSCMethod AllocMethod(void) { + static int numExtraAllocs = 0; + OSCMethod result; + + if (freeMethods != 0) { + result = freeMethods; + freeMethods = freeMethods->next; + return result; + } + + OSCWarning("Out of memory for methods; trying to allocate more in real time"); + { + int num = BASE_NUM_TO_REALLOCATE * ++numExtraAllocs; + freeMethods = (*RealTimeMemoryAllocator)(num * sizeof(*freeMethods)); + if (freeMethods == 0) { + OSCWarning("Real-time allocation failed"); + return 0; + } + MakeFreeMethodsList(num); + return AllocMethod(); + } +} + +//static void FreeMethod(OSCMethod c) { +// c->next = freeMethods; +// freeMethods = c; +//} + + +/**************************** Containers ****************************/ + +/* Managing the tree of containers and subcontainers, with aliases */ + +void AddSubContainer(OSCcontainer parent, OSCcontainer child, Name name) { + if (parent->numChildren >= MAX_CHILDREN_PER_CONTAINER) { + fatal_error("AddSubContainer: exceeded MAX_CHILDREN_PER_CONTAINER (%d)\n" + "Increase the value in OSC-address-space.c and recompile.", + MAX_CHILDREN_PER_CONTAINER); + } + + parent->childrenNames[parent->numChildren] = name; + parent->children[parent->numChildren] = child; + ++(parent->numChildren); +} + + +Boolean OSCAddContainerAlias(OSCcontainer container, Name otherName) { + if (container->parent->numChildren >= MAX_CHILDREN_PER_CONTAINER) { + return FALSE; + } + AddSubContainer(container->parent, container, otherName); + return TRUE; +} + +void RemoveSubContainer(OSCcontainer parent, OSCcontainer child) { + int i, numRemoved; + + /* Remove every pointer to the container, even if it has multiple aliases */ + + numRemoved = 0; + for (i = 0; i < parent->numChildren; ++i) { + if (parent->children[i] != child) { + parent->children[i-numRemoved] = parent->children[i]; + parent->childrenNames[i-numRemoved] = parent->childrenNames[i]; + } else { + ++numRemoved; + } + } + + parent->numChildren -= numRemoved; + + if (numRemoved == 0) { + fatal_error("RemoveSubContainer: subcontainer not found!\n"); + } +} + + + + + +Boolean OSCRemoveContainerAlias(OSCcontainer container, Name otherName) { + int i, j; + OSCcontainer parent = container->parent; + Boolean found = FALSE; + + for (i = 0; i < parent->numChildren; ++i) { + if (parent->childrenNames[i] == otherName) { + if (parent->children[i] != container) { + fatal_error("OSCRemoveContainerAlias: %s is actually a sibling's name!", + otherName); + } + found = TRUE; + for (j = i+1; j < parent->numChildren; ++j) { + parent->children[j-1] = parent->children[j]; + parent->childrenNames[j-1] = parent->childrenNames[j]; + --(parent->numChildren); + } + } + } + if (!found) { + fatal_error("OSCRemoveContainerAlias: %s not found!", otherName); + } + + /* Now make sure the child still exists under another name */ + for (i = 0; i < parent->numChildren; ++i) { + if (parent->children[i] == container) return TRUE; + } + + OSCWarning("OSCRemoveContainerAlias: %s was the last name for that subcontainer"); + + /* xxx should recursively free the container and its children... */ + return TRUE; +} + + +OSCcontainer OSCNewContainer(Name name, OSCcontainer parent, + struct OSCContainerQueryResponseInfoStruct *QueryResponseInfo) { + OSCcontainer me; + + me = AllocContainer(); + if (me == 0) return 0; + + if (strchr(name, '/') != NULL) { + OSCProblem("Container name \"%s\" contains a slash --- not good.", + name); + return 0; + } + + me->parent = parent; + AddSubContainer(me->parent, me, name); + me->numChildren = 0; + me->numMethods = 0; + me->QueryResponseInfo = (*QueryResponseInfo); + return me; +} + + +static const char *ContainerName(OSCcontainer c) { + /* Return the first name associated with me in my parent's child list. + (Assume all later ones are aliases.) */ + int i; + + for (i = 0; i < c->parent->numChildren; ++i) { + if (c->parent->children[i] == c) { + return c->parent->childrenNames[i]; + } + } + fatal_error("ContainerName: Container %p isn't in its parent's child list.", c); + return 0; +} + +static int gasHelp(char *target, int maxlength, OSCcontainer c ); + +Boolean OSCGetAddressString(char *target, int maxLength, OSCcontainer c) { + int lenNeeded; + + if (maxLength <= 1) return FALSE; + + lenNeeded = gasHelp(target, maxLength-1, c) + 1; /* -1, +1 are for null char. */ + if (lenNeeded > maxLength) { + OSCProblem("Address string too long (room for %d chars; need %d)", + maxLength, lenNeeded); + target[0] = '\0'; + return FALSE; + } + return TRUE; +} + +static int gasHelp(char *target, int maxLength, OSCcontainer c) { + int sublength, length; + const char *myName; + +/* printf("*** gasHelp %s %d %p %s\n", target, maxLength, c, c->name); */ + + if (c == OSCTopLevelContainer) { + target[0] = '/'; + target[1] = '\0'; + return 1; + } + + myName = ContainerName(c); + sublength = gasHelp(target, maxLength, c->parent); + length = sublength + strlen(myName) + 1; /* +1 is for trailing slash */ + if (length > maxLength) { + return length; + } + + strcpy(target+sublength, myName); + target[length-1] = '/'; + target[length] = '\0'; + + return length; +} + + +/**************************** Methods ****************************/ + +#define LONG_ADDR_SIZE 1000 /* Just for error messages */ + +OSCMethod OSCNewMethod(Name name, OSCcontainer me, methodCallback callback, + void *context, struct OSCMethodQueryResponseInfoStruct *QueryResponseInfo) { + + char addr[LONG_ADDR_SIZE]; + OSCMethod m; + + if (strchr(name, '/') != NULL) { + OSCProblem("Method name \"%s\" contains a slash --- not good.", + name); + return 0; + } + + + if (me->numMethods >= MAX_METHODS_PER_CONTAINER) { + addr[0] = '\0'; + OSCGetAddressString(addr, LONG_ADDR_SIZE, me); + OSCProblem("OSCNewMethod: container %s already has %d methods; can't add another\n" + "Change MAX_METHODS_PER_CONTAINER in OSC-address-space.c and recompile.", + addr, me->numMethods); + return 0; + } + + m = AllocMethod(); + if (!m) return 0; + + m->callback = callback; + m->context = context; + m->QueryResponseInfo = *QueryResponseInfo; + + me->methodNames[me->numMethods] = name; + me->methods[me->numMethods] = m; + ++(me->numMethods); + return m; +} + +/**************************** Queries ****************************/ + +void OSCInitContainerQueryResponseInfo(struct OSCContainerQueryResponseInfoStruct *i) { + i->comment = 0; +} + +void OSCInitMethodQueryResponseInfo(struct OSCMethodQueryResponseInfoStruct *i) { + i->description = 0; + i->pvq = 0; +} + +/******************************* Debug ********************************/ + + +static int ContainerAliases(OSCcontainer c, char *target) { + /* Write a space-delimited list of alias names in the given string, + and return the number */ + int i, n; + + if (c == OSCTopLevelContainer) return 0; + target[0] = '\0'; + n = 0; + + for (i = 0; i < c->parent->numChildren; ++i) { + if (c->parent->children[i] == c) { + if (n > 0) { + strcat(target, " "); + strcat(target, c->parent->childrenNames[i]); + } + ++n; + } + } + if (n == 0) fatal_error("ContainerAliases: internal inconsistency"); + + return n-1; +} + +#define BIG_ADDRESS 50 + +static void PrintHelp(OSCcontainer c) { + char addr[BIG_ADDRESS]; + char aliasNames[1000]; + + int i, j, numAliases; + + if (OSCGetAddressString(addr, BIG_ADDRESS, c) == FALSE) { + printf(" /.../%s", ContainerName(c)); + } else { + printf(" %s", addr); + } + + numAliases = ContainerAliases(c, aliasNames); + if (numAliases > 0) { + printf(" (%d aliases:%s)", numAliases, aliasNames); + } + printf("\n"); + + for (i = 0; i < c->numMethods; ++i) { + printf(" %s%s: %s\n", addr, c->methodNames[i], + c->methods[i]->QueryResponseInfo.description); + } + + /* Forgive this quadratic kludge: */ + for (i = 0; i < c->numChildren; ++i) { + int matches = 0; + for (j = 0; j < i; ++j) { + if (c->children[j] == c->children[i]) { + /* c->children[i] is just an alias to c->children[j], + which we already printed, so ignore it. */ + matches ++; + } + } + + if(matches == 0 ) PrintHelp(c->children[i]); + } +} + +void OSCPrintWholeAddressSpace(void) { + printf("\n----- The OSC address space -----\n"); + PrintHelp(OSCTopLevelContainer); + printf("...end of OSC address space.\n\n\n"); +} + + + + +/***************************** Dispatching *****************************/ + +#include +#include +#include + +/* To do quick concatenation of singly-linked lists, we pass around + this data structure that points to the first and last elements: */ + +typedef struct callbackListEnds_struct { + callbackList begin; + callbackList end; +} callbackListEnds; + +/* Helper proc. declarations */ +static callbackListEnds DispatchSubMessage(char *pattern, OSCcontainer c); +static char *NextSlashOrNull(char *p); + + +callbackList OSCDispatchMessage(char *pattern) { + callbackListEnds result; + + if (pattern[0] != '/') { + OSCProblem("Invalid address \"%s\" does not begin with /", pattern); + return 0; + } + + result = DispatchSubMessage(pattern+1, OSCTopLevelContainer); + + return result.begin; +} + +#define LONG_ADDR_LEN 100 + + +static callbackListEnds DispatchSubMessage(char *pattern, OSCcontainer c) { + callbackListEnds result; + char *nextSlash, *restOfPattern; + char offendingAddr[LONG_ADDR_LEN]; + int i; + + result.begin = result.end = 0; + nextSlash = NextSlashOrNull(pattern); + + if (*nextSlash == '\0') { + /* Base case: the pattern names methods of this container. */ + for (i = 0; i < c->numMethods; i++) { + if (PatternMatch(pattern, c->methodNames[i])) { + callbackList node = AllocCallbackListNode(c->methods[i]->callback, + c->methods[i]->context, + result.begin); + if (node == 0) { + /* Excuse the hairyness of the code to generate the error message. */ + if (OSCGetAddressString(offendingAddr, + LONG_ADDR_LEN-strlen(c->methodNames[i]), + c)) { + strcat(offendingAddr, c->methodNames[i]); + } else { + strcpy(offendingAddr, c->methodNames[i]); + } + + OSCWarning("No memory for callback node; not invoking %s", + offendingAddr); + } else { + if (result.end == 0) { + result.end = node; + } + result.begin = node; + } + } + } + } else { + /* Recursive case: in the middle of an address, so the job at this + step is to look for containers that match. We temporarily turn + the next slash into a null so pattern will be a null-terminated + string of the stuff between the slashes. */ + *nextSlash = '\0'; + restOfPattern = nextSlash + 1; + + for (i = 0; i < c->numChildren; ++i) { + if (PatternMatch(pattern, c->childrenNames[i])) { + callbackListEnds subResult = + DispatchSubMessage(restOfPattern, c->children[i]); + if (result.end == 0) { + result = subResult; + } else { + subResult.end->next = result.begin; + result.begin = subResult.begin; + } + } + } + *nextSlash = '/'; + } + return result; +} + + +static char *NextSlashOrNull(char *p) { + while (*p != '/' && *p != '\0') { + p++; + } + return p; +} + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-address-space.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-address-space.h new file mode 100644 index 00000000..f25d623a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-address-space.h @@ -0,0 +1,364 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + OSC-address-space.h + Matt Wright, 11/20/97 + Version 2.0 5/28/98 + + C interface for registering the nodes in the OSC address space for an + application. + + include OSC-timetag.h before this file + +****************************** Introduction ****************************** + + + The model is based on our original C++ design and consists of two kinds of + objects: + + methods are the leaf nodes of the address space hierarchy. A complete OSC + address corresponds to a particular method, which has a corresponding + callback procedure that will be invoked to implement commands sent by an + OSC client. + + containers are branch nodes of the address space hierarchy, and contain + methods and other containers. Each container has a single namespace; + it cannot contain a method and a subcontainer with the same name. + + For example, let's examine the OSC message "/resonators/foo/decay 2.5". The + address of this message is "/resonators/foo/decay" and the message has a + single argument, 2.5. We'd say that the object corresponding to the prefix + "/resonators" is a container, and that it contains another container whose + address is "/resonators/foo". The "/resonators/foo" container has a method + "decay". + + The memory model used by this module is pre-allocation of fixed-size objects + for containers, methods, and other internal objects. This preallocated + memory is dynamically managed internally by a custom high-performance memory + allocator. When the preallocated memory runs out, this module calls an + optional realtime memory allocator that you provide. If your memory allocator + gives this module more memory, it will add it to the pool of objects and + never free the memory. If your system does not have a realtime memory + allocator, provide a procedure that always returns 0. +*/ + +/*************************** Type Definitions ******************************/ + +/* Users of this module don't get to see what's inside these objects */ +typedef struct OSCContainerStruct *OSCcontainer; +typedef struct OSCMethodStruct *OSCMethod; + +/* This makes it easy to change the way we represent symbolic names: */ +typedef const char *Name; + + +/************************ Initialization and Memory ************************/ + +/* You will fill an OSCAddressSpaceMemoryTuner struct with the parameters that + determine how memory will be allocated. + + initNumContainers is the number of containers that will be allocated at + initialization time. This should be the maximum number of containers you + ever expect to have in your address space. + + initNumMethods is the number of methods that will be allocated at + initialization time. If you register the same method callback procedure + multiple times at different places in the address space, each of these + locations counts as a separate method as far as memory allocation is + concerned. + + The MemoryAllocator fields are procedures you will provide that allocate + memory. Like malloc(), they take the number of bytes as arguments and return + either a pointer to the new memory or 0 for failure. This memory will never + be freed. + + The InitTimeMemoryAllocator will be called only at initialization time, + i.e., before OSCInitAddressSpace() returns. If it ever returns 0, that's + a fatal error. + + The RealTimeMemoryAllocator will be called if, while the application is + running, the address space grows larger than can fit in what was allocated + at initialization time. If the RealTimeMemoryAllocator() returns 0, the + operation attempting to grow the address space will fail. If your system + does not have real-time memory allocation, RealTimeMemoryAllocator should + be a procedure that always returns 0. +*/ + +struct OSCAddressSpaceMemoryTuner { + int initNumContainers; + int initNumMethods; + void *(*InitTimeMemoryAllocator)(int numBytes); + void *(*RealTimeMemoryAllocator)(int numBytes); +}; + +/* Given an OSCAddressSpaceMemoryTuner, return the number of bytes of + memory that would be allocated if OSCInitAddressSpace() were called + on it. */ +int OSCAddressSpaceMemoryThatWouldBeAllocated(struct OSCAddressSpaceMemoryTuner *t); + + +/* Call this before you call anything else. It returns the container that + corresponds to the address "/" and is the root of the address space tree. +*/ +OSCcontainer OSCInitAddressSpace(struct OSCAddressSpaceMemoryTuner *t); + + +/**************************** Containers ****************************/ + +/* Here's how this system deals with the standard OSC queries addressed to + containers. This module handles the details of listening for these queries + and returning a correctly-formatted answer; all it needs from you is the + actual data that constitute the answers to these queries. + + You pass this data in an OSCContainerQueryResponseInfo structure. Future versions + of this module may have new kinds of queries that they can deal with, so + the list of fields in this structure may grow. That's why your code should + call OSCInitContainerQueryResponseInfo() on your struct before putting new values + into it; this procedure will initialize all of the fields to 0, meaning + "don't have that information", which will cause the associated queries to + fail. + + The "null" message, i.e., a message with a trailing slash, requesting the + list of addresses under a given container, is handled automatically. +*/ + +struct OSCContainerQueryResponseInfoStruct { + char *comment; + /* Other fields may go here */ +}; + +void OSCInitContainerQueryResponseInfo(struct OSCContainerQueryResponseInfoStruct *i); + + +/* Allocate a new container and initialize it. Returns 0 if it cannot + allocate a new container, e.g., if you've exceeded the initNumContainers + limit of the OSCAddressSpaceMemoryTuner() and the RealTimeMemoryAllocator() + didn't return any new memory. + + This procedure doesn't make a copy of the name string or any of the + contents of the OSCContainerQueryResponseInfoStruct. It does copy the fields + of the OSCContainerQueryResponseInfoStruct. +*/ +OSCcontainer OSCNewContainer(Name name, OSCcontainer parent, + struct OSCContainerQueryResponseInfoStruct *queryInfo); + + +/* Remove a container from the address space. This also removes all the + container's methods and recursively removes all sub-containers. Memory + freed by removing a container is kept in this module's internal pool. +*/ +void OSCRemoveContainer(OSCcontainer container); + + +/* Given a pointer to a container, and another name for that container, add or + remove that name as an alias for the container. Return FALSE for failure. */ +Boolean OSCAddContainerAlias(OSCcontainer container, Name otherName); +Boolean OSCRemoveContainerAlias(OSCcontainer container, Name otherName); + + +/* Write the OSC address of the given container into the given string. + Return FALSE if the address won't fit in the string. */ +Boolean OSCGetAddressString(char *target, int maxLength, OSCcontainer c); + + +/* Given an address (not a pattern!), return the single OSCcontainer it names, + or 0 if there is no container at that address */ +OSCcontainer OSCLookUpContainer(Name address); + + +/**************************** Methods ****************************/ + +/* A methodCallback is a procedure that you write that will be called at the + time that an OSC message is to take effect. It will be called with 5 + arguments: + - A context pointer that was registered with the methodNode + this is a method of. (Something like the C++ "this" pointer.) + - The number of bytes of argument data + - A pointer to the argument portion of the OSC message + - The time tag at which this message is supposed to take effect. + - A "return address" object you can use to send a message back to the + client that sent this message. This return channel is guaranteed + to be usable only during the invocation of your method, so your method + must use the return address immediately or ignore it, not store it away + for later use. +*/ +typedef struct NetworkReturnAddressStruct *NetworkReturnAddressPtr; +/* removed const */ + +typedef void (*methodCallback)(void *context, int arglen, const void *args, + OSCTimeTag when, NetworkReturnAddressPtr returnAddr); + + +/* A ParamValQuerier is a procedure that the OSC system will call when the + user wants to know the current value of a parameter. It will be passed the + same context pointer as the associated method. It should write its return + value in the given buffer in the same format as the associated + methodCallback would expect its "args" argument, and should return the + length of data just like the method would expect in its "arglen" argument. + It doesn't have to worry about the address portion of the OSC message. +*/ +typedef char OSCData; /* For pointers to OSC-formatted data */ +typedef int (*ParamValQuerier)(OSCData *result, void *context); + + +/* This system deals with other standard per-method queries, such as + documentation, valid parameter types and ranges, units, default values, + etc., pretty much just like per-container queries. +*/ + +struct OSCMethodQueryResponseInfoStruct { + char *description; + ParamValQuerier pvq; + /* For each argument of the method: + min, max, default, units */ +}; + +void OSCInitMethodQueryResponseInfo(struct OSCMethodQueryResponseInfoStruct *i); + + +/* Allocate a new method, initialize it, and add it to a container. Returns 0 + for failure, e.g., if you've exceeded the initNumMethods limit of the + OSCAddressSpaceMemoryTuner() and the RealTimeMemoryAllocator() didn't return any + new memory. + + This procedure doesn't make a copy of the name string or any of the + contents of the OSCMethodQueryResponseInfoStruct. +*/ + +OSCMethod OSCNewMethod(Name name, OSCcontainer container, methodCallback meth, + void *context, struct OSCMethodQueryResponseInfoStruct *queryInfo); + + + +/******************************* Debug ********************************/ + + +void OSCPrintWholeAddressSpace(void); + + +/**************************** Sample Code *****************************/ + +/* Here's a gross approximation of how your application will invoke the + procedures in this module. It registers an address space with + containers with addresses "/foo", "/foo/foochild", and "/bar", + and gives each of them "play" and "shuddup" messages. + + +#include "OSC-common.h" +#include "OSC-timetag.h" +#include "OSC-address-space.h" + + +typedef struct { + int playing; + int param; + float otherParam; +} Player; + +void PlayCallback(void *context, int arglen, const void *vargs, + OSCTimeTag when, NetworkReturnAddressPtr ra) { + Player *p = context; + const int *args = vargs; + + + p->playing = 1; + if (arglen >= 4) { + p->param = args[0]; + } +} + +void ShuddupCallback(void *context, int arglen, const void *vargs, + OSCTimeTag when, NetworkReturnAddressPtr ra) { + Player *p = context; + const float *args = vargs; + + + p->playing = 0; + if (arglen >= 4) { + p->otherParam = args[0]; + } +} + +void *InitTimeMalloc(int numBytes) { + return malloc(numBytes); +} + +void *NoRealTimeMalloc(int numBytes) { + return 0; +} + +main() { + struct OSCAddressSpaceMemoryTuner oasmt; + OSCcontainer topLevelContainer, foo, foochild, bar; + struct OSCContainerQueryResponseInfoStruct ocqris; + struct OSCMethodQueryResponseInfoStruct omqris; + + Player *players; + + players = (Player *) malloc(3 * sizeof(*players)); + if (!players) exit(1); + + oasmt.initNumContainers = 10; + oasmt.initNumMethods = 10; + oasmt.InitTimeMemoryAllocator = InitTimeMalloc; + oasmt.RealTimeMemoryAllocator = NoRealTimeMalloc; + + topLevelContainer = OSCInitAddressSpace(&oasmt); + + OSCInitContainerQueryResponseInfo(&ocqris); + ocqris.comment = "Foo for you"; + foo = OSCNewContainer("foo", topLevelContainer, &ocqris); + + OSCInitContainerQueryResponseInfo(&ocqris); + ocqris.comment = "Beware the son of foo!"; + foochild = OSCNewContainer("foochild", foo, &ocqris); + + OSCInitContainerQueryResponseInfo(&ocqris); + ocqris.comment = "Belly up to the bar"; + bar = OSCNewContainer("bar", topLevelContainer, &ocqris); + + if (foo == 0 || foochild == 0 || bar == 0) { + fprintf(stderr, "Problem!\n"); + exit(1); + } + + OSCInitMethodQueryResponseInfo(&omqris); + OSCNewMethod("play", foo, PlayCallback, &(players[0]), &omqris); + OSCNewMethod("shuddup", foo, ShuddupCallback, &(players[0]), &omqris); + + OSCNewMethod("play", foochild, PlayCallback, &(players[1]), &omqris); + OSCNewMethod("shuddup", foochild, ShuddupCallback, &(players[1]), &omqris); + + OSCNewMethod("play", bar, PlayCallback, &(players[2]), &omqris); + OSCNewMethod("shuddup", bar, ShuddupCallback, &(players[2]), &omqris); +} + +*/ + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-callbacklist.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-callbacklist.c new file mode 100644 index 00000000..3193ae8f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-callbacklist.c @@ -0,0 +1,95 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + OSC-callbacklist.c + Linked lists of methods + + Matt Wright, 11/20/97 + + Allocator is a simple linked list of free nodes. + +*/ + + + +#include +#include +#include +#include +#include + +static callbackList allNodes; +static callbackList freeNodes; + +/* Call this before you call anything else */ +Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes)) { + int i; + + allNodes = (*InitTimeMalloc)(numNodes * sizeof(*allNodes)); + if (allNodes == 0) return FALSE; + + /* Initialize list of freeNodes */ + freeNodes = &(allNodes[0]); + for (i = 0; i < numNodes-1; ++i) { + allNodes[i].next = &(allNodes[i+1]); + } + allNodes[numNodes-1].next = 0; + return TRUE; +} + +callbackList AllocCallbackListNode(methodCallback callback, void *context, + struct callbackListNode *next) { + callbackList result; + if (freeNodes == 0) { + /* OSCProblem("Out of memory for callback lists!"); */ + return 0; + } + + result = freeNodes; + freeNodes = freeNodes->next; + + result->callback = callback; + result->context = context; + result->next = next; +#ifdef DEBUG_CBL + printf("AllocCallbackListNode: returning %p (cb %p, context %p, next %p)\n", + result, result->callback, result->context, result->next); +#endif + return result; +} + + +void FreeCallbackListNode(callbackList cb) { +#ifdef DEBUG_CBL + printf("FreeCallbackListNode(%p)\n", cb); +#endif + cb->next = freeNodes; + freeNodes = cb; +} diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-callbacklist.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-callbacklist.h new file mode 100644 index 00000000..2e49fd24 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-callbacklist.h @@ -0,0 +1,49 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + OSC-callbacklist.h + Linked lists of methods + + Matt Wright, 3/13/98 + + include "OSC-dispatch.h" before this file. + +*/ + + +/* Call this before you call anything else. */ +Boolean InitCallbackListNodes(int numNodes, void *(*InitTimeMalloc)(int numBytes)); + +callbackList AllocCallbackListNode(methodCallback callback, void *context, + struct callbackListNode *next); + +void FreeCallbackListNode(callbackList); + + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-common.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-common.c new file mode 100644 index 00000000..c5808a39 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-common.c @@ -0,0 +1,87 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + + +/* OSC-system-dependent.c + + Matt Wright, 3/13/98 + + File of procedures OSC has to call that are not part of the OSC package + and that you, the developer adding OSC addressability to an application, + must write in a way that makes sense in the context of your system. + + You should also look at OSC-timetag.c and see if there's a better way + to handle time tags on your system. + +*/ + +#include + +/* Printing stuff: for now, use stderr. Some cleverer stuff we could do: + + - Make a silent mode where these don't do anything. + - Return error messages via OSC to some client +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +void fatal_error(char *s, ...) { + va_list ap; + fprintf(stderr, "Fatal error: "); + va_start(ap, s); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(-1); +} + +void OSCProblem(char *s, ...) { + va_list ap; + fprintf(stderr, "OSC Problem: "); + va_start(ap, s); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void OSCWarning(char *s, ...) { + /* va_list ap; + fprintf(stderr, "OSC Warning: "); + va_start(ap, s); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap);*/ +} diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-common.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-common.h new file mode 100644 index 00000000..80ee70b3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-common.h @@ -0,0 +1,60 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + + +/* OSC-common.h + Simple stuff to #include everywhere in the OSC package + + by Matt Wright, 3/13/98 +*/ + +/* Boolean type */ + +#ifndef TRUE +typedef int Boolean; +#define TRUE 1 +#define FALSE 0 +#endif + + +/* Fixed byte width types */ +typedef int int4; /* 4 byte int */ + +/* Printing type procedures. All take printf-style format string */ + +/* Catastrophic failure: print message and halt system */ +void fatal_error(char *s, ...); + +/* Error message for user */ +void OSCProblem(char *s, ...); + +/* Warning for user */ +void OSCWarning(char *s, ...); + + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-dispatch.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-dispatch.h new file mode 100644 index 00000000..2411029c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-dispatch.h @@ -0,0 +1,52 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-dispatch.h + + Given an OSC message pattern from an incoming message, match the + pattern against the OSC address space and produce a list of the + callbacks corresponding to all the addresses that were matched. + + Matt Wright, 6/5/98 +*/ + +/***************************** Dispatching *****************************/ + +typedef struct callbackListNode { + methodCallback callback; + void *context; + struct callbackListNode *next; +} *callbackList; + + +/* Given an OSC message pattern from an incoming message, match the + pattern against the OSC address space and produce a list of the + callbacks corresponding to all the addresses that were matched. */ +callbackList OSCDispatchMessage(char *pattern); + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-drop.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-drop.c new file mode 100644 index 00000000..88585ac7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-drop.c @@ -0,0 +1,58 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-drop.c + + This implementation just prints a warning. + + Matt Wright, 3/16/98 +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void DropPacket(OSCPacketBuffer p) { + OSCWarning("Packet dropped."); +} + +void DropBundle(char *buf, int n, OSCPacketBuffer p) { + OSCWarning("Bundle dropped."); +} + +void DropMessage(char *buf, int n, OSCPacketBuffer p) { + OSCWarning("Message dropped."); +} + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-drop.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-drop.h new file mode 100644 index 00000000..59c810ea --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-drop.h @@ -0,0 +1,43 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-drop.h + + These procedures will be called on a packet, bundle, or message that's + being dropped for whatever reason. They can do nothing, print (or + otherwise inform the user of) a warning, save the offending data somewhere, + etc. + + Matt Wright, 3/16/98 +*/ + +void DropPacket(OSCPacketBuffer p); +void DropBundle(char *buf, int n, OSCPacketBuffer p); +void DropMessage(char *buf, int n, OSCPacketBuffer p); + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-internal-messages.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-internal-messages.h new file mode 100644 index 00000000..54de8e5a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-internal-messages.h @@ -0,0 +1,70 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-internal-messages.h + + Interface for having an application send OSC messages to itself + internally. + + All these procedures return FALSE if unable to deliver the message. + + Matt Wright, 3/17/98 + +*/ + +/* Send a message immediately, with no return address. This procedure + returns after the message has been sent (or has failed to be sent), + so the memory for address and args can be on the stack. Returns FALSE + if there's a problem; TRUE otherwise. */ +Boolean OSCSendInternalMessage(char *address, int arglen, void *args); + + +/* Same thing, but with a return address supplied. */ +Boolean OSCSendInternalMessageWithRSVP(char *address, int arglen, void *args, + NetworkReturnAddressPtr returnAddr); + + +/* Schedule some messages to occur at a given time. This allocates one of the + OSCPacketBuffer structures (see OSC-receive.h) to hold the addresses and argument + data until the messages take effect, so if you're going to call this, you + should take this use of packets into account in setting the + numReceiveBuffers argument to OSCInitReceive(). + + This provides an less general interface than OSC's bundle mechanism, because + the bundle of messages you provide cannot include subbundles. + + The addresses, arglens, and args arguments are arrays of size numMessages. + + There's no return address argument because you're not allowed to save a network + return address for later use. +*/ + +Boolean OSCScheduleInternalMessages(OSCTimeTag when, int numMessages, + char **addresses, int *arglens, + void **args); diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-pattern-match.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-pattern-match.c new file mode 100644 index 00000000..b1614ae5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-pattern-match.c @@ -0,0 +1,193 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + + +/* + OSC-pattern-match.c + Matt Wright, 3/16/98 + Adapted from oscpattern.c, by Matt Wright and Amar Chaudhury + */ + +#include +#include +#include +#include +static const char *theWholePattern; /* Just for warning messages */ + +static Boolean MatchBrackets (const char *pattern, const char *test); +static Boolean MatchList (const char *pattern, const char *test); + +Boolean PatternMatch (const char * pattern, const char * test) { + theWholePattern = pattern; + + if (pattern == 0 || pattern[0] == 0) { + return test[0] == 0; + } + + if (test[0] == 0) { + if (pattern[0] == '*') + return PatternMatch (pattern+1,test); + else + return FALSE; + } + + switch (pattern[0]) { + case 0 : return test[0] == 0; + case '?' : return PatternMatch (pattern + 1, test + 1); + case '*' : + if (PatternMatch (pattern+1, test)) { + return TRUE; + } else { + return PatternMatch (pattern, test+1); + } + case ']' : + case '}' : + OSCWarning("Spurious %c in pattern \".../%s/...\"",pattern[0], theWholePattern); + return FALSE; + case '[' : + return MatchBrackets (pattern,test); + case '{' : + return MatchList (pattern,test); + case '\\' : + if (pattern[1] == 0) { + return test[0] == 0; + } else if (pattern[1] == test[0]) { + return PatternMatch (pattern+2,test+1); + } else { + return FALSE; + } + default : + if (pattern[0] == test[0]) { + return PatternMatch (pattern+1,test+1); + } else { + return FALSE; + } + } +} + + +/* we know that pattern[0] == '[' and test[0] != 0 */ + +static Boolean MatchBrackets (const char *pattern, const char *test) { + Boolean result; + Boolean negated = FALSE; + const char *p = pattern; + + if (pattern[1] == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + + if (pattern[1] == '!') { + negated = TRUE; + p++; + } + + while (*p != ']') { + if (*p == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + if (p[1] == '-' && p[2] != 0) { + if (test[0] >= p[0] && test[0] <= p[2]) { + result = !negated; + goto advance; + } + } + if (p[0] == test[0]) { + result = !negated; + goto advance; + } + p++; + } + + result = negated; + +advance: + + if (!result) + return FALSE; + + while (*p != ']') { + if (*p == 0) { + OSCWarning("Unterminated [ in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + p++; + } + + return PatternMatch (p+1,test+1); +} + +static Boolean MatchList (const char *pattern, const char *test) { + + const char *restOfPattern, *tp = test; + + + for(restOfPattern = pattern; *restOfPattern != '}'; restOfPattern++) { + if (*restOfPattern == 0) { + OSCWarning("Unterminated { in pattern \".../%s/...\"", theWholePattern); + return FALSE; + } + } + + restOfPattern++; /* skip close curly brace */ + + + pattern++; /* skip open curly brace */ + + while (1) { + + if (*pattern == ',') { + if (PatternMatch (restOfPattern, tp)) { + return TRUE; + } else { + tp = test; + ++pattern; + } + } else if (*pattern == '}') { + return PatternMatch (restOfPattern, tp); + } else if (*pattern == *tp) { + ++pattern; + ++tp; + } else { + tp = test; + while (*pattern != ',' && *pattern != '}') { + pattern++; + } + if (*pattern == ',') { + pattern++; + } + } + } + +} + + + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-pattern-match.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-pattern-match.h new file mode 100644 index 00000000..653b54d2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-pattern-match.h @@ -0,0 +1,35 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + OSC-pattern-match.h +*/ + +Boolean PatternMatch (const char *pattern, const char *test); + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-priority-queue.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-priority-queue.c new file mode 100644 index 00000000..5c29b694 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-priority-queue.c @@ -0,0 +1,190 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-priority-queue.c + Priority queue used by OSC time tag scheduler + + This is the most trivial implementation, an unsorted array of queued + objects, mostly for debug purposes. + + Matt Wright, 9/17/98 +*/ + +#include +#include +#include +#include +#include +#define PRINT_PRIORITY_QUEUE + +#ifdef DEBUG_OSC_PRIORITY_QUEUE +#define PRINT_PRIORITY_QUEUE +#endif + +#if defined(PRINT_PRIORITY_QUEUE) || defined(DEBUG_OSC_PRIORITY_QUEUE) + +#include +void OSCQueuePrint(OSCQueue q); +#endif + +#define CAPACITY 1000 + + +struct OSCQueueStruct { + OSCSchedulableObject list[CAPACITY]; + int n; + int scanIndex; +}; + + +OSCQueue OSCNewQueue(int maxItems, void *(*InitTimeMalloc)(int numBytes)) { + OSCQueue result; + + if (maxItems > CAPACITY) fatal_error("Increase CAPACITY in OSC-priority-queue.c"); + + result = (*InitTimeMalloc)(sizeof(*result)); + if (result == 0) return 0; + + result->n = 0; + +#ifdef DEBUG_OSC_PRIORITY_QUEUE + OSCQueuePrint(result); +#endif + return result; +} + +int OSCQueueInsert(OSCQueue q, OSCSchedulableObject new) { + if (q->n == CAPACITY) return FALSE; + + q->list[q->n] = new; + ++(q->n); +#ifdef DEBUG_OSC_PRIORITY_QUEUE + printf("OSCQueueInsert: just inserted %p\n", new); + OSCQueuePrint(q); +#endif + return TRUE; +} + + +OSCTimeTag OSCQueueEarliestTimeTag(OSCQueue q) { + int i; + OSCTimeTag smallest = OSCTT_BiggestPossibleTimeTag(); + + for (i = 0; i < q->n; ++i) { + if (OSCTT_Compare(smallest, q->list[i]->timetag) > 0) { + smallest = q->list[i]->timetag; + } + } + +#ifdef DEBUG_OSC_PRIORITY_QUEUE + printf("OSCQueueEarliestTimeTag: about to return %llx\n", smallest); + OSCQueuePrint(q); +#endif + return smallest; +} + + +static void RemoveElement(int goner, OSCQueue q) { + int i; + --(q->n); + + for (i = goner; i < q->n; ++i) { + q->list[i] = q->list[i+1]; + } +} + +OSCSchedulableObject OSCQueueRemoveEarliest(OSCQueue q) { + OSCSchedulableObject result; + int i, smallestIndex; + + if (q->n == 0) { + OSCWarning("OSCQueueRemoveEarliest: empty queue"); + return NULL; + } + +#ifdef DEBUG_OSC_PRIORITY_QUEUE + printf("OSCQueueRemoveEarliest: begin\n"); + OSCQueuePrint(q); +#endif + + smallestIndex = 0; + for (i = 1; i < q->n; ++i) { + if (OSCTT_Compare(q->list[smallestIndex]->timetag, q->list[i]->timetag) > 0) { + smallestIndex = i; + } + } + + result = q->list[smallestIndex]; + + RemoveElement(smallestIndex, q); + +#ifdef DEBUG_OSC_PRIORITY_QUEUE + printf("OSCQueueRemoveEarliest: done\n"); + OSCQueuePrint(q); +#endif + return result; +} + +#ifdef PRINT_PRIORITY_QUEUE + +void OSCQueuePrint(OSCQueue q) { + int i; + printf("OSC Priority queue at %p has %d elements:\n", q, q->n); + + for (i = 0; i < q->n; ++i) { + printf(" list[%2d] is %p, timetag = %llx\n", i, q->list[i], q->list[i]->timetag); + } + printf("\n\n"); +} + +#endif + + +void OSCQueueScanStart(OSCQueue q) { + q->scanIndex = 0; +} + +OSCSchedulableObject OSCQueueScanNext(OSCQueue q) { + if (q->scanIndex >= q->n) return 0; + + return (q->list[(q->scanIndex)++]); +} + +void OSCQueueRemoveCurrentScanItem(OSCQueue q) { + /* Remember that q->scanIndex is the index of the *next* + item that will be returned, so the "current" item, i.e., + the one most recently returned by OSCQueueScanNext(), + is q->scanIndex-1. */ + + RemoveElement(q->scanIndex-1, q); + --(q->scanIndex); +} + +void CheckWholeQueue(void) { +} diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-priority-queue.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-priority-queue.h new file mode 100644 index 00000000..dc15c8a2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-priority-queue.h @@ -0,0 +1,90 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-priority-queue.h + Interface to priority queue used by OSC time tag scheduler + + Matt Wright, 3/13/98 + +*/ + +/* include OSC-timetag.h before this file. */ + +/* This queue manages pointers to data objects. It doesn't care what's in the + objects except that the first element has to be an OSCTimeTag. So whatever + data you want to store, cast your pointer to it to a pointer to this type. */ + +typedef struct { + OSCTimeTag timetag; + /* There will be other stuff... */ +} *OSCSchedulableObject; + +typedef struct OSCQueueStruct *OSCQueue; + +/* Make a new queue, or return 0 for failure. */ +OSCQueue OSCNewQueue(int maxItems, void *(*InitTimeMalloc)(int numBytes)); + +/* Put something into the queue. Return FALSE if quque is full. */ +Boolean OSCQueueInsert(OSCQueue q, OSCSchedulableObject o); + +/* What's the time tag of the earliest item in the queue? + Return OSCTT_BiggestPossibleTimeTag() if queue is empty. */ +OSCTimeTag OSCQueueEarliestTimeTag(OSCQueue q); + +/* Remove the item from the front of the queue. Fatal error + if the queue is empty. */ +OSCSchedulableObject OSCQueueRemoveEarliest(OSCQueue q); + + +/* Interface for examining items currently stored on the queue: + + - To start, call OSCQueueScanStart(). + + - Then each subsequent call to OSCQueueScanNext() returns a pointer to an + OSCSchedulableObject that is stored on the queue, until + OSCQueueScanNext() returns 0 to indicate that all objects on the queue + have been scanned. + + The objects returned by OSCQueueScanNext() come in chronological order (or + approximately chronological order, depending on the underlying queue data + structure). + + If you call OSCQueueRemoveCurrentScanItem(), the object most recently + returned by OSCQueueScanNext() will be removed from the queue. + + If there are any insertions or deletions to the queue, the sequence of + scanned objects must still include every object in the queue. This may + cause a particular object to be returned more than once by + OSCQueueScanNext(). +*/ + + +void OSCQueueScanStart(OSCQueue q); +OSCSchedulableObject OSCQueueScanNext(OSCQueue q); +void OSCQueueRemoveCurrentScanItem(OSCQueue q); diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-receive.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-receive.c new file mode 100644 index 00000000..216188f1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-receive.c @@ -0,0 +1,893 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +#define PARANOID 0 +/* + OSC-receive.c + Matt Wright, 3/13/98, 6/3/98 + + Adapted from OSC-addressability.c (and seriously cleaned up!) + +*/ + #include + #include + #include + #include + #include + #include + #include + #include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(DEBUG_INTERNAL) || defined(DEBUG) || defined(DEBUG_PACKET_MEM) || defined(DEBUG_QD_MEM) || defined(DEBUG_8BYTE_ALIGN) || defined(SUSPECT_QD_PROB) +#include +#endif + +static int use_mcast_ = 0; +static char mcast_groupname[200]; + +struct { + OSCQueue TheQueue; /* The Priority Queue */ + OSCTimeTag lastTimeTag; /* Best approximation to current time */ + Boolean timePassed; /* TRUE if OSCInvokeMessagesThatAreReady() has been + called since the last time OSCBeProductiveWhileWaiting() was. */ + int recvBufSize; /* Size of all receive buffers */ + void *(*InitTimeMalloc)(int numBytes); + void *(*RealTimeMemoryAllocator)(int numBytes); +} globals; + + +/* Data structures */ + +struct OSCPacketBuffer_struct { + char *buf; /* Contents of network packet go here */ + int n; /* Overall size of packet */ + int refcount; /* # queued things using memory from this buffer */ + struct OSCPacketBuffer_struct *nextFree; /* For linked list of free packets */ + + Boolean returnAddrOK; /* Because returnAddr points to memory we need to + store future return addresses, we set this + field to FALSE in situations where a packet + buffer "has no return address" instead of + setting returnAddr to 0 */ + + NetworkReturnAddressPtr returnAddr; + //void *returnAddr; /* Addr of client this packet is from */ + /* This was of type NetworkReturnAddressPtr, but the constness + was making it impossible for me to initialize it. There's + probably a better way that I don't understand. */ + +}; + +/* These are the data objects that are inserted and removed from the + scheduler. The idea is that we can insert a single message or + an entire bundle on the scheduler, and we can leave it in various + states of being parsed and pattern matched. */ + +#define NOT_DISPATCHED_YET ((callbackList) -1) + +typedef struct queuedDataStruct { + OSCTimeTag timetag; /* When this bundle or message is supposed to happen */ + OSCPacketBuffer myPacket; /* Ptr. to buffer this is contained in */ + + enum {MESSAGE, BUNDLE} type; + + union { + struct { + char *bytes; + int length; + } bundle; + + struct { + char *messageName; /* Ptr. into receive buffer */ + int length; /* Includes name and arugments */ + void *args; /* 0 if not yet parsed */ + int argLength; + callbackList callbacks; /* May be NOT_DISPATCHED_YET */ + } message; + } data; + + struct queuedDataStruct *nextFree; /* For linked list of free structures */ +} queuedData; + + + +/* Static procedure declatations */ +static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numReceiveBuffers); +static Boolean InitQueuedData(int numQueuedObjects); +static queuedData *AllocQD(void); +static void FreeQD(queuedData *qd); +static void CallWholeCallbackList(callbackList l, int argLength, void *args, OSCTimeTag when, NetworkReturnAddressPtr returnAddr); +static void InsertBundleOrMessage(char *buf, int n, OSCPacketBuffer packet, OSCTimeTag enclosingTimeTag); +static void ParseBundle(queuedData *qd); +static Boolean ParseMessage(queuedData *qd); +/* static void CheckPacketRefcount(OSCPacketBuffer packet); */ +static void PacketAddRef(OSCPacketBuffer packet); +static void PacketRemoveRef(OSCPacketBuffer packet); + + +/************************************************** + Initialization and memory pre-allocation + **************************************************/ + + +Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t) { + globals.recvBufSize = t->receiveBufferSize; + globals.InitTimeMalloc = t->InitTimeMemoryAllocator; + globals.RealTimeMemoryAllocator = t->RealTimeMemoryAllocator; + + globals.TheQueue = OSCNewQueue(t->numQueuedObjects, t->InitTimeMemoryAllocator); + if (globals.TheQueue == 0) return FALSE; + + globals.lastTimeTag = OSCTT_Immediately(); + globals.timePassed = TRUE; + + if (InitPackets(t->receiveBufferSize, SizeOfNetworkReturnAddress(), + t->numReceiveBuffers) == FALSE) return FALSE; + if (InitQueuedData(t->numQueuedObjects) == FALSE) return FALSE; + if (InitCallbackListNodes(t->numCallbackListNodes, t->InitTimeMemoryAllocator) + == FALSE) return FALSE; + + return TRUE; +} + + +/************************************************** + Managing packet data structures + **************************************************/ + +static struct OSCPacketBuffer_struct *freePackets; + +#ifdef DEBUG_PACKET_MEM +static void PrintPacketFreeList(void) { + struct OSCPacketBuffer_struct *p; + printf("- freePackets:"); + if (freePackets == 0) { + printf(" [none]"); + } + for (p = freePackets; p != 0; p = p->nextFree) { + printf(" %p", p); + } + printf("\n"); +} +#endif + +#define MIN_REASONABLE_RCV_BUFSIZE 128 + +void OSCFreeReceiver(void) +{ + if( freePackets) free(freePackets); + if( globals.TheQueue ) free( globals.TheQueue ); +} + + +static Boolean InitPackets(int receiveBufferSize, int clientAddrSize, int numReceiveBuffers) { + int i; + struct OSCPacketBuffer_struct *allPackets; + + if (receiveBufferSize < MIN_REASONABLE_RCV_BUFSIZE) { + fatal_error("OSCInitReceive: receiveBufferSize of %d is unreasonably small.", + receiveBufferSize); + } + + allPackets = (*(globals.InitTimeMalloc))(numReceiveBuffers * sizeof(*allPackets)); + if (allPackets == 0) return FALSE; + + for (i = 0; i < numReceiveBuffers; ++i) { + allPackets[i].returnAddr = (*(globals.InitTimeMalloc))(clientAddrSize); + if (allPackets[i].returnAddr == 0) return FALSE; + + allPackets[i].buf = (*(globals.InitTimeMalloc))(receiveBufferSize); + if (allPackets[i].buf == 0) return FALSE; + + allPackets[i].nextFree = &(allPackets[i+1]); + } + allPackets[numReceiveBuffers-1].nextFree = ((struct OSCPacketBuffer_struct *) 0); + freePackets = allPackets; + + return TRUE; +} + +char *OSCPacketBufferGetBuffer(OSCPacketBuffer p) { + return p->buf; +} + +int *OSCPacketBufferGetSize(OSCPacketBuffer p) { + return &(p->n); +} + +int OSCGetReceiveBufferSize(void) { + return globals.recvBufSize; +} + +NetworkReturnAddressPtr OSCPacketBufferGetClientAddr(OSCPacketBuffer p) { + return p->returnAddr; +} + + +#ifdef DEBUG +void PrintPacket(OSCPacketBuffer p) { + printf("Packet %p. buf %p, n %d, refcount %d, nextFree %p\n", + p, p->buf, p->n, p->refcount, p->nextFree); +} +#endif + + + +OSCPacketBuffer OSCAllocPacketBuffer(void) { + OSCPacketBuffer result; + if (freePackets == 0) { + /* Could try to call the real-time memory allocator here */ + OSCWarning("OSCAllocPacketBuffer: no free packets!"); + return 0; + } + + result = freePackets; + freePackets = result->nextFree; + result->refcount = 0; + +#ifdef DEBUG_PACKET_MEM + printf("OSCAllocPacketBuffer: allocating %p ", result); + PrintPacketFreeList(); +#endif + + return result; +} + +void OSCFreePacket(OSCPacketBuffer p) { +#ifdef PARANOID + if (p->refcount != 0) { + OSCWarning("OSCFreePacket: %p's refcount is %d!\n", p, p->refcount); + } +#endif + + p->nextFree = freePackets; + freePackets = p; + +#ifdef DEBUG_PACKET_MEM + printf("OSCFreePacket: freed %p ", p); + PrintPacketFreeList(); +#endif + +} + + +/************************************************** + Dealing with OpenSoundControl packets and + making the messages take effect. + **************************************************/ + +static queuedData *freeQDList; + +#ifdef DEBUG_QD_MEM +static void PrintQDFreeList(void) { + static queuedData *p; + printf("- freeQDList:"); + if (freeQDList == 0) { + printf(" [none]"); + } + for (p = freeQDList; p != 0; p = p->nextFree) { + printf(" %p", p); + } + printf("\n"); +} +#endif + +static Boolean InitQueuedData(int numQueuedObjects) { + int i; + queuedData *allQD; + + allQD = (*(globals.InitTimeMalloc))(numQueuedObjects * (sizeof(*allQD))); + if (allQD == 0) return FALSE; + + for (i = 0; i < numQueuedObjects; ++i) { + allQD[i].nextFree = &(allQD[i+1]); + } + allQD[numQueuedObjects-1].nextFree = 0; + freeQDList = &(allQD[0]); + + return TRUE; +} + +static queuedData *AllocQD(void) { + queuedData *result; + + if (freeQDList == 0) { + /* Could try to call realtime malloc() */ + OSCWarning("AllocQD: no QD objects free now; returning 0."); + return 0; + } + + result = freeQDList; + freeQDList = freeQDList->nextFree; + return result; +} + +static void FreeQD(queuedData *qd) { + qd->nextFree = freeQDList; + freeQDList = qd; +} + + +void OSCAcceptPacket(OSCPacketBuffer packet) { + if ((packet->n % 4) != 0) { + OSCProblem("OSC packet size (%d bytes) not a multiple of 4.", packet->n); + DropPacket(packet); + return; + } + +#ifdef DEBUG + printf("OSCAcceptPacket(OSCPacketBuffer %p, buf %p, size %d)\n", + packet, packet->buf, packet->n); +#endif + + /* If the packet came from the user, it's return address is OK. */ + packet->returnAddrOK = TRUE; + + InsertBundleOrMessage(packet->buf, packet->n, packet, OSCTT_Immediately()); + +#ifdef PARANOID + if (packet->refcount == 0) { + if (freePackets != packet) { + fatal_error("OSCAcceptPacket: packet refcount 0, but it's not the head of the free list!"); + } + } +#endif + + OSCInvokeAllMessagesThatAreReady(globals.lastTimeTag); +} + +Boolean OSCBeProductiveWhileWaiting(void) { + /* Here's where we could be clever if an allocation fails. + (I.e., if we're out of QD objects, we should avoid + parsing bundles.) The code isn't that smart yet. */ + + queuedData *qd; + + if (globals.timePassed) { + OSCQueueScanStart(globals.TheQueue); + } + + while (1) { + qd = (queuedData *) OSCQueueScanNext(globals.TheQueue); + if (qd == 0) return FALSE; + + if (qd->type == BUNDLE) { + ParseBundle(qd); + OSCQueueRemoveCurrentScanItem(globals.TheQueue); + return TRUE; + } else { + if (qd->data.message.callbacks == NOT_DISPATCHED_YET) { + if (ParseMessage(qd) == FALSE) { + /* Problem with this message - flush it. */ + DropMessage(qd->data.message.messageName, + qd->data.message.length, + qd->myPacket); + OSCQueueRemoveCurrentScanItem(globals.TheQueue); + PacketRemoveRef(qd->myPacket); + FreeQD(qd); + } + return TRUE; + } + /* The item we found was an already-dispatched message, + so continue the while loop. */ + } + } +} + +Boolean OSCInvokeMessagesThatAreReady(OSCTimeTag now) { + queuedData *x; + OSCTimeTag thisTimeTag; + + globals.lastTimeTag = now; + globals.timePassed = TRUE; + + thisTimeTag = OSCQueueEarliestTimeTag(globals.TheQueue); + + if (OSCTT_Compare(thisTimeTag, now) > 0) { + /* No messages ready yet. */ + return FALSE; + } + +#ifdef DEBUG + printf("OSCInvokeMessagesThatAreReady(%llx) - yes, some are ready; earliest %llx\n", now, thisTimeTag); +#endif + + while (OSCTT_Compare(thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue)) == 0) { + x = (queuedData *) OSCQueueRemoveEarliest(globals.TheQueue); + if (!x) return FALSE; + +#ifdef DEBUG + printf("...Just removed earliest entry from queue: %p, TT %llx, %s\n", + x, x->timetag, x->type == MESSAGE ? "message" : "bundle"); + if (x->type == MESSAGE) { + printf("...message %s, len %d, args %p, arglen %d, callbacks %p\n", + x->data.message.messageName, x->data.message.length, x->data.message.args, + x->data.message.argLength, x->data.message.callbacks); + } else { + if (x->data.bundle.length == 0) { + printf("...bundle is empty.\n"); + } else { + printf("...bundle len %d, first count %d, first msg %s\n", + x->data.bundle.length, *((int *) x->data.bundle.bytes), x->data.bundle.bytes+4); + } + } + PrintPacket(x->myPacket); +#endif + + if (x->type == BUNDLE) { + ParseBundle(x); + } else { + if (x->data.message.callbacks == NOT_DISPATCHED_YET) { + if (ParseMessage(x) == FALSE) { + /* Problem with this message - flush it. */ + PacketRemoveRef(x->myPacket); + FreeQD(x); + continue; + } + } + + CallWholeCallbackList(x->data.message.callbacks, + x->data.message.argLength, + x->data.message.args, + thisTimeTag, + x->myPacket->returnAddrOK ? x->myPacket->returnAddr : 0); + + PacketRemoveRef(x->myPacket); + FreeQD(x); + } + } + + +#ifdef PARANOID + if (OSCTT_Compare(thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue)) > 0) { + fatal_error("OSCInvokeMessagesThatAreReady: corrupt queue!\n" + " just did %llx; earliest in queue is now %llx", + thisTimeTag, OSCQueueEarliestTimeTag(globals.TheQueue)); + } +#endif + + return OSCTT_Compare(OSCQueueEarliestTimeTag(globals.TheQueue), now) <= 0; +} + +void OSCInvokeAllMessagesThatAreReady(OSCTimeTag now) { + while (OSCInvokeMessagesThatAreReady(now)) { + /* Do nothing */ + } +} + +static void CallWholeCallbackList(callbackList l, int argLength, void *args, OSCTimeTag when, + NetworkReturnAddressPtr returnAddr) { + /* In a multithreaded application, this might run in a different thread + than the thread that deals with the priority queue. */ + + callbackList next; + + while (l != 0) { + (*(l->callback))(l->context, argLength, args, when, returnAddr); + next = l->next; + FreeCallbackListNode(l); + l = next; + } +} + +static void InsertBundleOrMessage(char *buf, int n, OSCPacketBuffer packet, OSCTimeTag enclosingTimeTag) { + Boolean IsBundle; + queuedData *qd; + + /* We add the reference first thing so in case any of the upcoming + potential failure situations come we can call PacketRemoveRef, thereby + freeing the packet if necessary. */ + PacketAddRef(packet); + + if ((n % 4) != 0) { + OSCProblem("OSC message or bundle size (%d bytes) not a multiple of 4.", n); + DropMessage(buf, n, packet); + PacketRemoveRef(packet); + return; + } + + if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) { + IsBundle = TRUE; + + if (n < 16) { + OSCProblem("Bundle message too small (%d bytes) for time tag.", n); + DropBundle(buf, n, packet); + PacketRemoveRef(packet); + return; + } + } else { + IsBundle = FALSE; + } + + + qd = AllocQD(); + + if (qd == 0) { + OSCProblem("Not enough memory for queued data!"); + DropBundle(buf, n, packet); + PacketRemoveRef(packet); + return; + } + + qd->myPacket = packet; + qd->type = IsBundle ? BUNDLE : MESSAGE; + + if (IsBundle) { + /* Be careful of 8-byte alignment when copying the time tag. Here's a good + way to get a bus error when buf happens not to be 8-byte aligned: + qd->timetag = *((OSCTimeTag *)(buf+8)); + */ + memcpy(&(qd->timetag), buf+8, sizeof(OSCTimeTag)); + + if (OSCTT_Compare(qd->timetag, enclosingTimeTag) < 0) { + OSCProblem("Time tag of sub-bundle is before time tag of enclosing bundle."); + DropBundle(buf, n, packet); + PacketRemoveRef(packet); + FreeQD(qd); + return; + } + qd->data.bundle.bytes = buf + 16; + qd->data.bundle.length = n - 16; + } else { + qd->timetag = enclosingTimeTag; + qd->data.message.messageName = buf; + qd->data.message.length = n; + qd->data.message.callbacks = NOT_DISPATCHED_YET; + } + + OSCQueueInsert(globals.TheQueue, (OSCSchedulableObject) qd); +} + + +static void ParseBundle(queuedData *qd) { + /* A queued bundle has been removed from the scheduler queue, and now it's + time to parse all the stuff inside it and schedule the enclosed + messages and bundles. Once all the contents of the bundle have been + parsed and scheduled, we trash the bundle, decrementing the packet + count and freeing the QD. */ + + int size; + int i = 0; + + if (qd->type != BUNDLE) { + fatal_error("This can't happen: bundle isn't a bundle!"); + } + + while (i < qd->data.bundle.length) { + size = *((int *) (qd->data.bundle.bytes + i)); + if ((size % 4) != 0) { + OSCProblem("Bad size count %d in bundle (not a multiple of 4).", size); + DropBundle(qd->data.bundle.bytes, qd->data.bundle.length, qd->myPacket); + goto bag; + } + if ((size + i + 4) > qd->data.bundle.length) { + OSCProblem("Bad size count %d in bundle (only %d bytes left in entire bundle).", + size, qd->data.bundle.length-i-4); + DropBundle(qd->data.bundle.bytes, qd->data.bundle.length, qd->myPacket); + goto bag; + } + + /* Recursively handle element of bundle */ + InsertBundleOrMessage(qd->data.bundle.bytes+i+4, size, qd->myPacket, qd->timetag); + i += 4 + size; + } + + if (i != qd->data.bundle.length) { + fatal_error("This can't happen: internal logic error parsing bundle"); + } + +bag: + /* If we got here successfully, we've added to the packet's reference count for + each message or subbundle by calling InsertBundleOrMessage(), so we remove the one + reference for bundle that we just parsed. If we got here by "goto bag", there's a + problem with the bundle so we also want to lose the reference count. */ + + PacketRemoveRef(qd->myPacket); + FreeQD(qd); +} + + +static Boolean ParseMessage(queuedData *qd) { + /* Fill in all the information we'll need to execute the message as + quickly as possible when the time comes. This means figuring out where + the address ends and the arguments begin, and also pattern matching the + address to find the callbacks associated with it. + + The message may be something we have to invoke now, or it may be some + message scheduled for the future that's just waiting on the queue; this + procedure doesn't care. */ + + + char *args; /* char * so we can do pointer subtraction */ + int messageLen; + char *DAAS_errormsg; + + + if (qd->type != MESSAGE) { + fatal_error("This can't happen: message isn't a message!"); + } + + args = OSCDataAfterAlignedString(qd->data.message.messageName, + qd->data.message.messageName+qd->data.message.length, + &DAAS_errormsg); + + if (args == 0) { + OSCProblem("Bad message name string: %s\n", DAAS_errormsg); + DropMessage(qd->data.message.messageName, qd->data.message.length, qd->myPacket); + return FALSE; + } + + qd->data.message.args = args; + messageLen = args - qd->data.message.messageName; + qd->data.message.argLength = qd->data.message.length - messageLen; + + qd->data.message.callbacks = OSCDispatchMessage(qd->data.message.messageName); + + if (qd->data.message.callbacks == 0) { + OSCWarning("Message pattern \"%s\" did not correspond to any address in the synth.", + qd->data.message.messageName); + return FALSE; + } + + return TRUE; +} + +static void PacketAddRef(OSCPacketBuffer packet) { + ++(packet->refcount); +} + +static void PacketRemoveRef(OSCPacketBuffer packet) { + --(packet->refcount); + if (packet->refcount == 0) { + OSCFreePacket(packet); + } +} + + + +/************************************************** + Implementation of procedures declared in + OSC-internal-messages.h + **************************************************/ + +#include + +Boolean OSCSendInternalMessage(char *address, int arglen, void *args) { + return OSCSendInternalMessageWithRSVP(address, arglen, args, 0); +} + +Boolean OSCSendInternalMessageWithRSVP(char *address, int arglen, void *args, + NetworkReturnAddressPtr returnAddr) { + callbackList l = OSCDispatchMessage(address); + + if (l == 0) return FALSE; + + CallWholeCallbackList(l, arglen, args, OSCTT_Immediately(), returnAddr); + return TRUE; +} + + + +Boolean OSCScheduleInternalMessages(OSCTimeTag when, int numMessages, + char **addresses, int *arglens, void **args) { + int i, bufSizeNeeded; + OSCPacketBuffer p; + queuedData *qd; + char *bufPtr; + + + + /* Figure out how big of a buffer we'll need to hold this huge bundle. + We don't store the "#bundle" string or the time tag, just the 4-byte + size counts, the addresses, possible extra null padding for the + addresses, and the arguments. */ + + bufSizeNeeded = 0; + for (i = 0; i < numMessages; ++i) { + bufSizeNeeded += 4 + OSCPaddedStrlen(addresses[i]) + arglens[i]; + } + + if (bufSizeNeeded > OSCGetReceiveBufferSize()) { + return FALSE; + } + + + /* Now try to allocate the data objects to hold these messages */ + qd = AllocQD(); + if (qd == 0) return FALSE; + + p = OSCAllocPacketBuffer(); + if (p == 0) { + FreeQD(qd); + return FALSE; + } + + /* Now fill in the buffer with a fake #bundle message. This is almost like + putting a real #bundle message in the buffer and then calling OSCAcceptPacket, + except that we save a little time and memory by not writing "#bundle" or the time tag, + and by pre-parsing the messages a little. Thus, this code duplicates a lot + of what's in InsertBundleOrMessage() */ + + bufPtr = p->buf; + + for (i = 0; i < numMessages; ++i) { + /* First the size count of this bundle element */ + *((int4 *) bufPtr) = OSCPaddedStrlen(addresses[i]) + arglens[i]; + bufPtr += sizeof(int4); + + /* Then the address */ + bufPtr = OSCPaddedStrcpy(bufPtr, addresses[i]); + + /* Then the arguments */ + memcpy(bufPtr, args[i], arglens[i]); + bufPtr += arglens[i]; + } + +#ifdef PARANOID + if (bufPtr != p->buf+bufSizeNeeded) { + fatal_error("OSCScheduleInternalMessages: internal error"); + } +#endif + + /* Fill in the rest of the packet fields */ + p->n = bufSizeNeeded; + p->returnAddrOK = FALSE; + PacketAddRef(p); + + /* Now fill in the queuedData object */ + qd->timetag = when; + qd->myPacket = p; + qd->type = BUNDLE; + qd->data.bundle.length = bufSizeNeeded; + qd->data.bundle.bytes = p->buf; + + /* Now we can put it into the scheduling queue. */ + OSCQueueInsert(globals.TheQueue, (OSCSchedulableObject) qd); + + return TRUE; +} + +Boolean NetworkPacketWaiting(OSCPacketBuffer packet) { + int n; + NetworkReturnAddressPtr na = OSCPacketBufferGetClientAddr(packet); + +// if( use_mcast_ ) +// { + fd_set fds; + struct timeval no_wait; + int status; + memset( &no_wait, 0, sizeof(no_wait)); + FD_ZERO(&fds); + FD_SET( na->sockfd , &fds ); + status = select( na->sockfd + 1, &fds, 0, 0, &no_wait ); + if(status <= 0) + return FALSE; + if(FD_ISSET( na->sockfd, &fds )) + return TRUE; +// } +// else +// { +// if( ioctl( na->sockfd, FIONREAD, &n, 0)==-1) return FALSE; +// if( n==0 ) return FALSE; +// } +// return TRUE; + return FALSE; +} + +Boolean NetworkReceivePacket( OSCPacketBuffer packet ) { + int n; + NetworkReturnAddressPtr na = OSCPacketBufferGetClientAddr(packet); + + if( use_mcast_ ) + { + n = recv( na->sockfd, packet->buf, 100, 0 ); + if( n<= 0) + return FALSE; + packet->n = n; + } + else + { + n = recvfrom( na->sockfd, packet->buf, 100, 0, + (struct sockaddr*) &(na->cl_addr), &(na->clilen)); + if(n<=0) { + return FALSE; + } + packet->n = n; + } + + return TRUE; +} + +void GoMultiCast( const char *group_name ) +{ + use_mcast_ = 1; + strncpy( mcast_groupname, group_name, strlen(group_name )); +} + +int IsMultiCast( char *dst ) +{ + if(use_mcast_) + sprintf(dst, "%s", mcast_groupname ); + return use_mcast_; +} + +Boolean NetworkStartUDPServer(OSCPacketBuffer packet, int port_id) { + struct sockaddr_in my_addr; + my_addr.sin_family = AF_INET; + my_addr.sin_port = htons(port_id); + my_addr.sin_addr.s_addr = INADDR_ANY; + + memset( &(my_addr.sin_zero), 0, 8); + + if( use_mcast_ ) + { + struct ip_mreq mcast_req; + int on = 1; + int err= 0; + memset( &mcast_req, 0, sizeof(mcast_req)); + packet->returnAddr->sockfd = socket( AF_INET, SOCK_DGRAM, 0); +#ifdef SO_REUSEADDR + setsockopt( packet->returnAddr->sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); +#endif +#ifdef SO_REUSEPORT + setsockopt( packet->returnAddr->sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)); +#endif + err = bind( packet->returnAddr->sockfd, (struct sockaddr*) &my_addr, sizeof( my_addr )); + if( err < 0 ) + return FALSE; + + mcast_req.imr_multiaddr.s_addr = inet_addr( mcast_groupname ); + mcast_req.imr_interface.s_addr = htonl( INADDR_ANY ); + setsockopt( packet->returnAddr->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &mcast_req, sizeof(mcast_req) ); + } + else + { + packet->returnAddr->sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if( bind( packet->returnAddr->sockfd, + (struct sockaddr*) &my_addr, + sizeof(struct sockaddr)) == -1) return FALSE; + + packet->returnAddr->clilen = sizeof(struct sockaddr); + } + return TRUE; +} diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-receive.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-receive.h new file mode 100644 index 00000000..d231390e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-receive.h @@ -0,0 +1,242 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + + +/* + OSC-receive.h + Matt Wright, 11/18/97 + + include OSC-timetag.h and NetworkReturnAddress.h before this file. +*/ + + +/************************************************** + Initialization and memory pre-allocation + **************************************************/ + +/* The memory model used by this module is pre-allocation of fixed-size + objects for network buffers and other internal objects. This preallocated + memory is dynamically managed internally by a custom high-performance memory + allocator. When the preallocated memory runs out, this module calls an + optional realtime memory allocator that you provide. If your memory + allocator gives this module more memory, it will add it to the pool of + objects and never free the memory. If your system does not have a realtime + memory allocator, provide a procedure that always returns 0. + + You will fill an OSCReceiveMemoryTuner struct with the parameters that + determine how memory will be allocated. + + The MemoryAllocator fields are procedures you will provide that allocate + memory. Like malloc(), they take the number of bytes as arguments and return + either a pointer to the new memory or 0 for failure. This memory will never + be freed. + +- The InitTimeMemoryAllocator will be called only at initialization time, + i.e., before OSCInitAddressSpace() returns. If it ever returns 0, that's + a fatal error. + +- The RealTimeMemoryAllocator will be called if, while the application is + running, the address space grows larger than can fit in what was allocated + at initialization time. If the RealTimeMemoryAllocator() returns 0, the + operation attempting to grow the address space will fail. If your system + does not have real-time memory allocation, RealTimeMemoryAllocator should + be a procedure that always returns 0. + + The remaining fields say how much memory to allocate at initialization time: + +- receiveBufferSize is the maximum packet size that can be received. Is the + maximum UDP packet size 4096? OSC clients can send a query to this system + asking for this maximum packet size. + +- numReceiveBuffers determines how many packets at a time can be sitting + on the scheduler with messages waiting to take effect. If all the + receive buffers are tied up like this, you won't be able to receive + new packets. + +- numQueuedObjects is the number of messages and packets that can be sitting + on the scheduler waiting to take effect. + +- Because a message pattern may be dispatched before the message takes effect, + we need memory to store the callback pointers corresponding to a message. + numCallbackListNodes is the number of callbacks that may be stored in this + fashion. It must be at least as large as the maximum number of methods that + any one message pattern may match, but if you want to take advantage of + pre-dispatching, this should be large enough to hold all the callbacks for + all the messages waiting in the scheduler. + +*/ + +struct OSCReceiveMemoryTuner { + void *(*InitTimeMemoryAllocator)(int numBytes); + void *(*RealTimeMemoryAllocator)(int numBytes); + int receiveBufferSize; + int numReceiveBuffers; + int numQueuedObjects; + int numCallbackListNodes; +}; + +/* Given an OSCReceiveMemoryTuner, return the number of bytes of + memory that would be allocated if OSCInitReceive() were called + on it. */ +int OSCReceiveMemoryThatWouldBeAllocated(struct OSCReceiveMemoryTuner *t); + +/* Returns FALSE if it fails to initialize */ +Boolean OSCInitReceive(struct OSCReceiveMemoryTuner *t); + +/************************************************** + Managing packet data structures + **************************************************/ + + +/* You don't get to know what's in an OSCPacketBuffer. */ +typedef struct OSCPacketBuffer_struct *OSCPacketBuffer; + +/* Get an unused packet. Returns 0 if none are free. If you get a packet + with this procedure, it is your responsibility either to call + OSCAcceptPacket() on it (in which case the internals of the OSC Kit free + the OSCPacketBuffer after the last message in it takes effect) or to call + OSCFreePacket() on it. */ +OSCPacketBuffer OSCAllocPacketBuffer(void); + +/* Free. This is called automatically after the last message that was + in the packet is invoked. You shouldn't need to call this unless + you get a packet with OSCAllocPacketBuffer() and then for some reason + decide not to call OSCAcceptPacket() on it. */ +void OSCFreePacket(OSCPacketBuffer p); + +void OSCFreeReceiver(void); + +/* Whatever code actually gets packets from the network should use these + three selectors to access the fields in the packet structure that need + to be filled in with the data from the network. */ + +/* Selector to get the buffer from a packet. This buffer's size will be + equal to the receiveBufferSize you passed to OSCInitReceive(). */ +char *OSCPacketBufferGetBuffer(OSCPacketBuffer p); + +/* Selector to get a pointer to the int that's the size count for the + data currently in a packet. (Not the capacity of the packet's buffer, + but the size of the packet that's actually stored in the buffer.) */ +int *OSCPacketBufferGetSize(OSCPacketBuffer); + +/* Selector to get the client's network address from a packet. This buffer's + size will be equal to the clientAddrSize you passed to OSCInitReceive(). + Note that the NetworkReturnAddressPtr type is full of "const"s, so your + code that fills in the return address will probably have to cast the return + value of this procedure to some non-const type to be able to write into it. */ +NetworkReturnAddressPtr OSCPacketBufferGetClientAddr(OSCPacketBuffer p); + +/* Returns the capacity of packet buffers (the receiveBufferSize you passed + to OSCInitReceive()). */ +int OSCGetReceiveBufferSize(void); + + +/************************************************** + Dealing with OpenSoundControl packets and + making the messages take effect. + **************************************************/ + +/* Call this as soon as a packet comes in from the network. + It will take care of anything that has to happen immediately, + but put off as much as possible of the work of parsing the + packet. (This tries to be as fast as possible in case a + lot of packets come in.) */ +void OSCAcceptPacket(OSCPacketBuffer packet); + +/* Call this during an otherwise idle time. It goes through + everything that's sitting in the OSC scheduler waiting to + happen and does some of the work of parsing, pattern + matching, dispatching, etc., that will have to be done + at some point before the scheduled messages can take + effect. + + The return value indicates whether there is more work of + this sort that could be done. (Each time you call this, + it does only a small unit of this kind of work. If it + returns TRUE and you still have time before the next thing + you have to do, call it again.) */ +Boolean OSCBeProductiveWhileWaiting(void); + +/* Call this whenever enough time has passed that you want to see which + messages are now ready and have them take effect. (For example, in a + synthesizer, you might call this once per synthesis frame, just before + synthesizing the audio for that frame.) + + This procedure finds the earliest time tag of all the queued messages + and invokes *all* of the queued messages with that time tag. (OSC + guarantees that messages with the same tag take effect atomically.) + If there are more messages that are ready, but with a different time + tag, this procedure does not invoke them, but returns TRUE to indicate + that more messages are ready. +*/ +Boolean OSCInvokeMessagesThatAreReady(OSCTimeTag now); + +/* Same thing, but invokes all of the messages whose time has come. */ +void OSCInvokeAllMessagesThatAreReady(OSCTimeTag now); + +Boolean NetworkReceivePacket(OSCPacketBuffer packet); + +Boolean NetworkStartUDPServer(OSCPacketBuffer packet, int port_id); + +Boolean NetworkPacketWaiting(OSCPacketBuffer packet); + +void GoMultiCast(const char *groupname); + +int IsMultiCast( char *dst); + +/************************************************** + How to use this stuff + **************************************************/ + +/* Here's a gross approximation of how your application will invoke the + procedures in this module: + +while (1) { + OSCTimeTag now = CurrentTime(); + do { + if (WeAreSoLateThatWeNeedToDelayOSCMessagesToAvoidACrisis()) break; + } while (OSCInvokeMessagesThatAreReady(now) == TRUE); + + SynthesizeSomeSound(); + if (NetworkPacketWaiting()) { + OSCPacketBuffer p = OSCAllocPacketBuffer(); + if (!p) { + Bummer(); + } else { + NetworkReceivePacket(p); + OSCAcceptPacket(p); + } + } + while (TimeLeftBeforeWeHaveDoSomething()) { + if (!OSCBeProductiveWhileWaiting()) break; + } +} + +*/ + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-string-help.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-string-help.c new file mode 100644 index 00000000..f42086e8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-string-help.c @@ -0,0 +1,123 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-string-help.c + Procedures that could be useful to programmers writing OSC methods that + take string arguments. + + by Matt Wright, 3/19/98 +*/ + +#include /* For Boolean */ +#include +#include +#define STRING_ALIGN_PAD 4 + +char *OSCDataAfterAlignedString(const char *string, const char *boundary, char **errorMsg) { + + int i; + + if ((boundary - string) %4 != 0) { + fatal_error("DataAfterAlignedString: bad boundary\n"); + } + + for (i = 0; string[i] != '\0'; i++) { + if (string + i >= boundary) { + (*errorMsg) = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + } + + /* Now string[i] is the first null character */ + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string + i >= boundary) { + (*errorMsg) = "Unreasonably long string"; + return 0; + } + if (string[i] != '\0') { + (*errorMsg) = "Incorrectly padded string."; + return 0; + } + } + + return (char *) (string+i); +} + +int OSCPaddedStrlen(const char *s) { + int i; + + for (i = 0; *s != '\0'; s++, i++) { + /* do nothing */ + } + + /* Now i is the length with no null bytes. We need 1-4 null bytes, + to make the total length a multiple of 4. So we add 4, as if + we need 4 null bytes, then & 0xfffffffc to round down to the nearest + multiple of 4. */ + + return (i + 4) & 0xfffffffc; +} + +char *OSCPaddedStrcpy(char *target, const char *source) { + while ( (*target++) = (*source++)) { + /* do nothing */ + } + + /* That copied one null byte */ + while (((int) target) % 4 != 0) { + *target = '\0'; + target++; + } + return target; +} + +Boolean OSCParseStringList(const char *result[], int *numStrings, int maxStrings, + const char *args, int numBytes) { + int numFound; + const char *p; + const char *boundary = args + numBytes; + char *errorMessage; + + p = args; + + for (numFound = 0; numFound < maxStrings; ++numFound) { + if (p == boundary) { + *numStrings = numFound; + return TRUE; + } + + result[numFound] = p; + p = OSCDataAfterAlignedString(p, boundary, &errorMessage); + if (p == 0) return FALSE; + } + return FALSE; +} + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-string-help.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-string-help.h new file mode 100644 index 00000000..03cd79c5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-string-help.h @@ -0,0 +1,70 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* OSC-string-help.h + Procedures that could be useful to programmers writing OSC methods that + take string arguments. + + by Matt Wright, 3/19/98 +*/ + +/* Use this to deal with OSC null-padded 4 byte-aligned strings + + The argument is a block of data beginning with a string. The string + has (presumably) been padded with extra null characters so that the + overall length is a multiple of 4 bytes. Return a pointer to the next + byte after the null byte(s). The boundary argument points to the + character after the last valid character in the buffer---if the string + hasn't ended by there, something's wrong. + + If the data looks wrong, return 0, and set *errorMsg */ + +char *OSCDataAfterAlignedString(const char *string, const char *boundary, char **errorMsg); + + +/* Given a normal C-style string with a single padding byte, return the + length of the string including the necessary 1-4 padding bytes. + (Basically strlen()+1 rounded up to the next multiple of 4.) */ +int OSCPaddedStrlen(const char *s); + +/* Copy a given C-style string into the given destination, including the + requisite padding byte(s). Unlike strcpy(), this returns a pointer to + the next character after the copied string's null bytes, like + what OSCDataAfterAlignedString() returns. */ +char *OSCPaddedStrcpy(char *target, const char *source); + + +/* Given an args pointer that should be nothing but a list of strings, fill + result[] with pointers to the beginnings of each string, and set + *numStrings to be the number of strings found. maxStrings gives the size + of the result array. Return FALSE if any strings are malformatted or if + there are more than maxStrings many strings. */ + +Boolean OSCParseStringList(const char *result[], int *numStrings, int maxStrings, + const char *args, int numBytes); diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-struct.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-struct.h new file mode 100644 index 00000000..6e17b15d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-struct.h @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +#ifndef OSCH +#define OSCH +#ifndef TRUE +typedef int Boolean; +#define TRUE 1 +#define FALSE 0 +#endif + + +/* Fixed byte width types */ +typedef int int4; /* 4 byte int */ +typedef struct NetworkReturnAddressStruct_t { + struct sockaddr_in cl_addr; /* client information */ + struct sockaddr_in my_addr; /* us */ + int clilen; + int sockfd; + fd_set readfds; + struct timeval tv; + int fdmax; +} NetworkReturnAddressStruct; + + +typedef struct OSCPacketBuffer_struct { + char *buf; /* Contents of network packet go here */ + int n; /* Overall size of packet */ + int refcount; /* # queued things using memory from this buffer */ + struct OSCPacketBuffer_struct *nextFree; /* For linked list of free packets */ + + Boolean returnAddrOK; /* Because returnAddr points to memory we need to + store future return addresses, we set this + field to FALSE in situations where a packet + buffer "has no return address" instead of + setting returnAddr to 0 */ + + void *returnAddr; /* Addr of client this packet is from */ + /* This was of type NetworkReturnAddressPtr, but the constness + was making it impossible for me to initialize it. There's + probably a better way that I don't understand. */ + +} OSCPacketBuffer; + +struct OSCReceiveMemoryTuner { + void *(*InitTimeMemoryAllocator)(int numBytes); + void *(*RealTimeMemoryAllocator)(int numBytes); + int receiveBufferSize; + int numReceiveBuffers; + int numQueuedObjects; + int numCallbackListNodes; +}; + +#endif diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-timetag.c b/branches/V-1.5.3/veejay-server/libOSC/OSC-timetag.c new file mode 100644 index 00000000..22140691 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-timetag.c @@ -0,0 +1,174 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + + OSC_timeTag.c: library for manipulating OSC time tags + Matt Wright, 5/29/97 + + Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file. + +*/ + +#include +#include +#include + +#ifdef HAS8BYTEINT +#define TWO_TO_THE_32_FLOAT 4294967296.0f + +OSCTimeTag OSCTT_Immediately(void) { + return (OSCTimeTag) 1; +} + +OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) { + return (OSCTimeTag) 0xffffffffffffffff; +} + +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) { + int8 offset = (int8) (secondsOffset * TWO_TO_THE_32_FLOAT); + +/* printf("* OSCTT_PlusSeconds %llx plus %f seconds (i.e., %lld offset) is %llx\n", original, + secondsOffset, offset, original + offset); */ + + return original + offset; +} + +int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) { +#if 0 + printf("***** OSCTT_Compare(%llx, %llx): %d\n", left, right, + (left + +#define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */ +#define TWO_TO_THE_32_OVER_ONE_MILLION 4295 + + +OSCTimeTag OSCTT_CurrentTime(void) { + uint8 result; + uint4 usecOffset; + struct timeval tv; + struct timezone tz; + + BSDgettimeofday(&tv, &tz); + + /* First get the seconds right */ + result = (unsigned) SECONDS_FROM_1900_to_1970 + + (unsigned) tv.tv_sec - + (unsigned) 60 * tz.tz_minuteswest + + (unsigned) (tz.tz_dsttime ? 3600 : 0); + +#if 0 + /* No timezone, no DST version ... */ + result = (unsigned) SECONDS_FROM_1900_to_1970 + + (unsigned) tv.tv_sec; +#endif + + + /* make seconds the high-order 32 bits */ + result = result << 32; + + /* Now get the fractional part. */ + usecOffset = (unsigned) tv.tv_usec * (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION; + /* printf("** %ld microsec is offset %x\n", tv.tv_usec, usecOffset); */ + + result += usecOffset; + +/* printf("* OSCTT_CurrentTime is %llx\n", result); */ + return result; +} + +#else /* __sgi */ + +/* Instead of asking your operating system what time it is, it might be + clever to find out the current time at the instant your application + starts audio processing, and then keep track of the number of samples + output to know how much time has passed. */ + +/* Loser version for systems that have no ability to tell the current time: */ +OSCTimeTag OSCTT_CurrentTime(void) { + return (OSCTimeTag) 1; +} + +#endif /* __sgi */ + + +#else /* Not HAS8BYTEINT */ + +OSCTimeTag OSCTT_CurrentTime(void) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + +OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) { + OSCTimeTag result; + result.seconds = 0xffffffff; + result.fraction = 0xffffffff; + return result; +} + +OSCTimeTag OSCTT_Immediately(void) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + +int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) { + /* Untested! */ + int highResult = left.seconds - right.seconds; + + if (highResult != 0) return highResult; + + return left.fraction - right.fraction; +} + + +#endif /* HAS8BYTEINT */ + diff --git a/branches/V-1.5.3/veejay-server/libOSC/OSC-timetag.h b/branches/V-1.5.3/veejay-server/libOSC/OSC-timetag.h new file mode 100644 index 00000000..7e6cbe62 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/OSC-timetag.h @@ -0,0 +1,91 @@ +/* +Copyright İ 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + + +/* + OSC_timeTag.h: library for manipulating OSC time tags + Matt Wright, 5/29/97 + + Time tags in OSC have the same format as in NTP: 64 bit fixed point, with the + top 32 bits giving number of seconds sinve midnight 1/1/1900 and the bottom + 32 bits giving fractional parts of a second. We represent this by an 8-byte + unsigned long if possible, or else a struct. + + NB: On many architectures with 8-byte ints, it's illegal (like maybe a bus error) + to dereference a pointer to an 8 byte int that's not 8-byte aligned. +*/ + +#ifndef OSC_TIMETAG +#define OSC_TIMETAG + +#ifdef __sgi + #define HAS8BYTEINT + /* You may have to change this typedef if there's some other + way to specify 8 byte ints on your system */ + typedef long long int8; + typedef unsigned long long uint8; + typedef unsigned long uint4; +#else + /* You may have to redefine this typedef if ints on your system + aren't 4 bytes. */ + typedef unsigned int uint4; +#endif + + +#ifdef HAS8BYTEINT + typedef uint8 OSCTimeTag; +#else + typedef struct { + uint4 seconds; + uint4 fraction; + } OSCTimeTag; +#endif + + + +/* Return a time tag representing the current time (as of when this + procedure is called). */ +OSCTimeTag OSCTT_CurrentTime(void); + +/* Return the time tag 0x0000000000000001, indicating to the receiving device + that it should process the message immediately. */ +OSCTimeTag OSCTT_Immediately(void); + +/* Return the time tag 0xffffffffffffffff, a time so far in the future that + it's effectively infinity. */ +OSCTimeTag OSCTT_BiggestPossibleTimeTag(void); + +/* Given a time tag and a number of seconds to add to the time tag, return + the new time tag */ +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset); + +/* Compare two time tags. Return negative if first is < second, 0 if + they're equal, and positive if first > second. */ +int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right); + +#endif /* OSC_TIMETAG */ diff --git a/branches/V-1.5.3/veejay-server/libOSC/libosc.h b/branches/V-1.5.3/veejay-server/libOSC/libosc.h new file mode 100644 index 00000000..ed890b0a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libOSC/libosc.h @@ -0,0 +1,26 @@ +#ifndef _LIBOSC_H_INCLUDED +#define _LIBOSC_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/Makefile.am b/branches/V-1.5.3/veejay-server/libel/Makefile.am new file mode 100644 index 00000000..4f682ab1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/Makefile.am @@ -0,0 +1,15 @@ +# Makefile for veejay + +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/vjmem \ + -I$(top_srcdir)/vjmsg \ + -I$(top_srcdir)/mjpegtools $(FFMPEG_AVUTIL_CFLAGS) $(FFMPEG_AVFORMAT_CFLAGS) $(FFMPEG_AVCODEC_CFLAGS) $(FFMPEG_SWSCALER_CFLAGS) $(PIXBUF_CFLAGS) \ + $(LIBQUICKTIME_CFLAGS) + +VJEL_LIB_FILE = libel.la +noinst_LTLIBRARIES = $(VJEL_LIB_FILE) +libel_la_SOURCES = vj-mmap.c elcache.c avilib.c lav_io.c vj-dv.c rawdv.c pixbuf.c vj-avcodec.c vj-el.c + +EXTRA_DIST = avilib.h elcache.h lav_io.h pixbuf.h \ + rawdv.h vj-avcodec.h vj-dv.h vj-el.h vj-mmap.h diff --git a/branches/V-1.5.3/veejay-server/libel/avilib.c b/branches/V-1.5.3/veejay-server/libel/avilib.c new file mode 100644 index 00000000..9c77ca7e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/avilib.c @@ -0,0 +1,3787 @@ +/* + * avilib.c + * + * Copyright (C) Thomas Östreich - June 2001 + * multiple audio track support Copyright (C) 2002 Thomas Östreich + * + * Original code: + * Copyright (C) 1999 Rainer Johanni + * + * This file is part of transcode, a video stream processing tool + * + * transcode 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, or (at your option) + * any later version. + * + * transcode 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include "avilib.h" +#ifdef STRICT_CHECKING +#include +#endif +#define INFO_LIST + +// add a new riff chunk after XX MB +//#define NEW_RIFF_THRES (1900*1024*1024) +#define NEW_RIFF_THRES (1900*1024*1024) +//#define NEW_RIFF_THRES (10*1024*1024) + +// Maximum number of indices per stream +#define NR_IXNN_CHUNKS 32 +/* There is an experimental kernel patch available at + * http://www.tech9.net/rml/linux/ + * that adds the O_STREAMING flag for open(). Files opened this way will + * bypass the linux buffer cache entirely, so that writing multi-gigabyte files + * with lavrec will not cause everything in memory to get swapped to disk. + * This is highly desirable, hopefuly it will be merged with the mainstream + * kernel. + * + * we leave it out if it's unknown, since its value differs per arch... + */ + + +#ifndef O_STREAMING +#define O_STREAMING 0 +#endif + + +#define DEBUG_ODML +#undef DEBUG_ODML + +/* The following variable indicates the kind of error */ + +long AVI_errno = 0; + +#define MAX_INFO_STRLEN 64 +static char id_str[MAX_INFO_STRLEN]; + +#define FRAME_RATE_SCALE 1000000 + +extern int vj_el_get_decoder_from_fourcc( const char *fourcc ); + + +/******************************************************************* + * * + * Utilities for writing an AVI File * + * * + *******************************************************************/ + +static ssize_t avi_read(int fd, char *buf, size_t len) +{ + ssize_t n = 0; + ssize_t r = 0; + + while (r < len) { + n = read (fd, buf + r, len - r); + if (n == 0) + break; + if (n < 0) { + if (errno == EINTR) + continue; + else + break; + } + + r += n; + } + + return r; +} + +static ssize_t avi_write (int fd, char *buf, size_t len) +{ + ssize_t n = 0; + ssize_t r = 0; + + while (r < len) { + n = write (fd, buf + r, len - r); + if (n < 0) + return n; + + r += n; + } + return r; +} + +/* HEADERBYTES: The number of bytes to reserve for the header */ + +#define HEADERBYTES 2048 + +/* AVI_MAX_LEN: The maximum length of an AVI file, we stay a bit below + the 2GB limit (Remember: 2*10^9 is smaller than 2 GB) */ + +#define AVI_MAX_LEN (UINT_MAX-(1<<20)*16-HEADERBYTES) + +#define PAD_EVEN(x) ( ((x)+1) & ~1 ) + + +/* Copy n into dst as a 4 or 2 byte, little endian number. + Should also work on big endian machines */ + +static void long2str(unsigned char *dst, int32_t n) +{ + dst[0] = (n )&0xff; + dst[1] = (n>> 8)&0xff; + dst[2] = (n>>16)&0xff; + dst[3] = (n>>24)&0xff; +} + +#ifdef WORDS_BIGENDIAN +static void short2str(unsigned char *dst, int32_t n) +{ + dst[0] = (n )&0xff; + dst[1] = (n>> 8)&0xff; +} +#endif + +/* Convert a string of 4 or 2 bytes to a number, + also working on big endian machines */ + +static uint64_t str2ullong(unsigned char *str) +{ + uint64_t r = (str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24)); + uint64_t s = (str[4] | (str[5]<<8) | (str[6]<<16) | (str[7]<<24)); + return ((s<<32)&0xffffffff00000000ULL)|(r&0xffffffffULL); +} + +static uint32_t str2ulong(unsigned char *str) +{ + return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) ); +} +static uint32_t str2ushort(unsigned char *str) +{ + return ( str[0] | (str[1]<<8) ); +} + +// bit 31 denotes a keyframe +static uint32_t str2ulong_len (unsigned char *str) +{ + return str2ulong(str) & 0x7fffffff; +} + + +// if bit 31 is 0, its a keyframe +static uint32_t str2ulong_key (unsigned char *str) +{ + uint32_t c = str2ulong(str); + c &= 0x80000000; + if (c == 0) return 0x10; + else return 0; +} + +/* Calculate audio sample size from number of bits and number of channels. + This may have to be adjusted for eg. 12 bits and stereo */ + +static int avi_sampsize(avi_t *AVI, int j) +{ + int s; + s = ((AVI->track[j].a_bits+7)/8)*AVI->track[j].a_chans; + // if(s==0) s=1; /* avoid possible zero divisions */ + if(s<4) s=4; /* avoid possible zero divisions */ + return s; +} + +/* Add a chunk (=tag and data) to the AVI file, + returns -1 on write error, 0 on success */ + +static int avi_add_chunk(avi_t *AVI, unsigned char *tag, unsigned char *data, int length) +{ + unsigned char c[8]; + char p=0; + + /* Copy tag and length int c, so that we need only 1 write system call + for these two values */ + + veejay_memcpy(c,tag,4); + long2str(c+4,length); + + /* Output tag, length and data, restore previous position + if the write fails */ + + if( avi_write(AVI->fdes,(char *)c,8) != 8 || + avi_write(AVI->fdes,(char *)data,length) != length || + avi_write(AVI->fdes,&p,length&1) != (length&1)) // if len is uneven, write a pad byte + { + lseek(AVI->fdes,AVI->pos,SEEK_SET); + AVI_errno = AVI_ERR_WRITE; + return -1; + } + + /* Update file position */ + + AVI->pos += 8 + PAD_EVEN(length); + + //fprintf(stderr, "pos=%lu %s\n", AVI->pos, tag); + + return 0; +} + +#define OUTD(n) long2str(ix00+bl,n); bl+=4 +#define OUTW(n) ix00[bl] = (n)&0xff; ix00[bl+1] = (n>>8)&0xff; bl+=2 +#define OUTC(n) ix00[bl] = (n)&0xff; bl+=1 +#define OUTS(s) veejay_memcpy(ix00+bl,s,4); bl+=4 + +// this does the physical writeout of the ix## structure +static int avi_ixnn_entry(avi_t *AVI, avistdindex_chunk *ch, avisuperindex_entry *en) +{ + int bl, k; + unsigned int max = ch->nEntriesInUse * sizeof (uint32_t) * ch->wLongsPerEntry + 24; // header + char *ix00 = vj_malloc (max); + char dfcc[5]; + veejay_memcpy (dfcc, ch->fcc, 4); + dfcc[4] = 0; + + bl = 0; + + if (en) { + en->qwOffset = AVI->pos; + en->dwSize = max; + //en->dwDuration = ch->nEntriesInUse -1; // NUMBER OF stream ticks == frames for video/samples for audio + } + +#ifdef DEBUG_ODML + //printf ("ODML Write %s: Entries %ld size %d \n", dfcc, ch->nEntriesInUse, max); +#endif + + //OUTS(ch->fcc); + //OUTD(max); + OUTW(ch->wLongsPerEntry); + OUTC(ch->bIndexSubType); + OUTC(ch->bIndexType); + OUTD(ch->nEntriesInUse); + OUTS(ch->dwChunkId); + OUTD(ch->qwBaseOffset&0xffffffff); + OUTD((ch->qwBaseOffset>>32)&0xffffffff); + OUTD(ch->dwReserved3); + + for (k = 0; k < ch->nEntriesInUse; k++) { + OUTD(ch->aIndex[k].dwOffset); + OUTD(ch->aIndex[k].dwSize); + + } + avi_add_chunk (AVI, ch->fcc, ix00, max); + + free(ix00); + + return 0; +} +#undef OUTS +#undef OUTW +#undef OUTD +#undef OUTC + +// inits a super index structure including its enclosed stdindex +static int avi_init_super_index(avi_t *AVI, unsigned char *idxtag, avisuperindex_chunk **si) +{ + int k; + + avisuperindex_chunk *sil = NULL; + + if ((sil = (avisuperindex_chunk *) vj_malloc (sizeof (avisuperindex_chunk))) == NULL) { + AVI_errno = AVI_ERR_NO_MEM; + return -1; + } + veejay_memset(sil, 0, sizeof (avisuperindex_chunk)); + veejay_memcpy (sil->fcc, "indx", 4); + sil->dwSize = 0; // size of this chunk + sil->wLongsPerEntry = 4; + sil->bIndexSubType = 0; + sil->bIndexType = AVI_INDEX_OF_INDEXES; + sil->nEntriesInUse = 0; // none are in use + veejay_memcpy (sil->dwChunkId, idxtag, 4); + veejay_memset (sil->dwReserved, 0, sizeof (sil->dwReserved)); + + // NR_IXNN_CHUNKS == allow 32 indices which means 32 GB files -- arbitrary + sil->aIndex = vj_malloc (sil->wLongsPerEntry * NR_IXNN_CHUNKS * sizeof (uint32_t)); + if (!sil->aIndex) { + AVI_errno = AVI_ERR_NO_MEM; + return -1; + } + veejay_memset (sil->aIndex, 0, sil->wLongsPerEntry * NR_IXNN_CHUNKS * sizeof (uint32_t)); + + sil->stdindex = vj_malloc (NR_IXNN_CHUNKS * sizeof (avistdindex_chunk *)); + if (!sil->stdindex) { + AVI_errno = AVI_ERR_NO_MEM; + return -1; + } + for (k = 0; k < NR_IXNN_CHUNKS; k++) { + sil->stdindex[k] = vj_malloc (sizeof (avistdindex_chunk)); + veejay_memset(sil->stdindex[k], 0, sizeof (avistdindex_chunk)); + // gets rewritten later + sil->stdindex[k]->qwBaseOffset = (uint64_t)k * NEW_RIFF_THRES; + } + + *si = sil; + + return 0; +} + +// fills an alloc'ed stdindex structure and vj_mallocs some entries for the actual chunks +static int avi_add_std_index(avi_t *AVI, unsigned char *idxtag, unsigned char *strtag, + avistdindex_chunk *stdil) +{ + + veejay_memcpy (stdil->fcc, idxtag, 4); + stdil->dwSize = 4096; + stdil->wLongsPerEntry = 2; //sizeof(avistdindex_entry)/sizeof(uint32_t); + stdil->bIndexSubType = 0; + stdil->bIndexType = AVI_INDEX_OF_CHUNKS; + stdil->nEntriesInUse = 0; + + // cp 00db ChunkId + veejay_memcpy(stdil->dwChunkId, strtag, 4); + + //stdil->qwBaseOffset = AVI->video_superindex->aIndex[ cur_std_idx ]->qwOffset; + + stdil->aIndex = vj_malloc(stdil->dwSize * sizeof (uint32_t) * stdil->wLongsPerEntry); + + if (!stdil->aIndex) { + AVI_errno = AVI_ERR_NO_MEM; + return -1; + } + + + return 0; +} + +static int avi_add_odml_index_entry_core(avi_t *AVI, long flags, off_t pos, unsigned long len, avistdindex_chunk *si) +{ + int cur_chunk_idx; + // put new chunk into index + si->nEntriesInUse++; + cur_chunk_idx = si->nEntriesInUse-1; + + // need to fetch more memory + if (cur_chunk_idx >= si->dwSize) { + si->dwSize += 4096; + si->aIndex = realloc ( si->aIndex, si->dwSize * sizeof (uint32_t) * si->wLongsPerEntry); + } + + if(len>AVI->max_len) AVI->max_len=len; + + // if bit 31 is set, it is NOT a keyframe + if (flags != 0x10) { + len |= 0x80000000; + } + + si->aIndex [ cur_chunk_idx ].dwSize = len; + si->aIndex [ cur_chunk_idx ].dwOffset = + pos - si->qwBaseOffset + 8; + + //printf("ODML: POS: 0x%lX\n", si->aIndex [ cur_chunk_idx ].dwOffset); + + return 0; +} + +static int avi_add_odml_index_entry(avi_t *AVI, unsigned char *tag, long flags, off_t pos, unsigned long len) +{ + char fcc[5]; + + int audio = (strchr (tag, 'w')?1:0); + int video = !audio; + + unsigned int cur_std_idx; + int audtr; + off_t towrite = 0LL; + + if (video) { + + if (!AVI->video_superindex) { + if (avi_init_super_index(AVI, "ix00", &AVI->video_superindex) < 0) return -1; + AVI->video_superindex->nEntriesInUse++; + cur_std_idx = AVI->video_superindex->nEntriesInUse-1; + + if (avi_add_std_index (AVI, "ix00", "00db", AVI->video_superindex->stdindex[ cur_std_idx ]) < 0) + return -1; + } // init + + } // video + + if (audio) { + + fcc[0] = 'i'; fcc[1] = 'x'; fcc[2] = tag[0]; fcc[3] = tag[1]; fcc[4] = '\0'; + if (!AVI->track[AVI->aptr].audio_superindex) { + +#ifdef DEBUG_ODML + printf("ODML: fcc = %s\n", fcc); +#endif + if (avi_init_super_index(AVI, fcc, &AVI->track[AVI->aptr].audio_superindex) < 0) return -1; + + + AVI->track[AVI->aptr].audio_superindex->nEntriesInUse++; + + snprintf(fcc, sizeof(fcc), "ix%02d", AVI->aptr+1); + if (avi_add_std_index (AVI, fcc, tag, AVI->track[AVI->aptr].audio_superindex->stdindex[ + AVI->track[AVI->aptr].audio_superindex->nEntriesInUse - 1 ]) < 0 + ) return -1; + } // init + + } + + towrite = 0; + if (AVI->video_superindex) { + + cur_std_idx = AVI->video_superindex->nEntriesInUse-1; + towrite += AVI->video_superindex->stdindex[cur_std_idx]->nEntriesInUse*8 + + 4+4+2+1+1+4+4+8+4; + if (cur_std_idx == 0) { + towrite += AVI->n_idx*16 + 8; + towrite += HEADERBYTES; + } + } + + for (audtr=0; audtranum; audtr++) { + if (AVI->track[audtr].audio_superindex) { + cur_std_idx = AVI->track[audtr].audio_superindex->nEntriesInUse-1; + towrite += AVI->track[audtr].audio_superindex->stdindex[cur_std_idx]->nEntriesInUse*8 + + 4+4+2+1+1+4+4+8+4; + } + } + towrite += len + (len&1) + 8; + + //printf("ODML: towrite = 0x%llX = %lld\n", towrite, towrite); + + if (AVI->video_superindex && + (off_t)(AVI->pos+towrite) > (off_t)((off_t)NEW_RIFF_THRES*AVI->video_superindex->nEntriesInUse)) { + +// fprintf(stderr, "Adding a new RIFF chunk: %d\n", AVI->video_superindex->nEntriesInUse); + veejay_msg( 2, "Adding a new RIFF chunk: %d", AVI->video_superindex->nEntriesInUse ); + + // rotate ALL indices + AVI->video_superindex->nEntriesInUse++; + cur_std_idx = AVI->video_superindex->nEntriesInUse-1; + + if (AVI->video_superindex->nEntriesInUse > NR_IXNN_CHUNKS) { + veejay_msg(0, "Internal error in avilib - redefine NR_IXNN_CHUNKS (needed=%d, current=%d)", + AVI->video_superindex->nEntriesInUse, NR_IXNN_CHUNKS); + veejay_msg(0, "[avilib dump] cur_std_idx=%d NR_IXNN_CHUNKS=%d" + "POS=%lld towrite=%lld", + cur_std_idx,NR_IXNN_CHUNKS, AVI->pos, towrite); + return -1; + } + + if (avi_add_std_index (AVI, "ix00", "00db", AVI->video_superindex->stdindex[ cur_std_idx ]) < 0) + return -1; + + for (audtr = 0; audtr < AVI->anum; audtr++) { + char aud[5]; + if (!AVI->track[audtr].audio_superindex) { + // not initialized -> no index + continue; + } + AVI->track[audtr].audio_superindex->nEntriesInUse++; + + snprintf(fcc, sizeof(fcc), "ix%02d", audtr+1); + snprintf(aud, sizeof(aud), "0%01dwb", audtr+1); + if (avi_add_std_index (AVI, fcc, aud, AVI->track[audtr].audio_superindex->stdindex[ + AVI->track[audtr].audio_superindex->nEntriesInUse - 1 ]) < 0 + ) return -1; + } + + // write the new riff; + if (cur_std_idx > 0) { + + // dump the _previous_ == already finished index + avi_ixnn_entry (AVI, AVI->video_superindex->stdindex[cur_std_idx - 1], + &AVI->video_superindex->aIndex[cur_std_idx - 1]); + AVI->video_superindex->aIndex[cur_std_idx - 1].dwDuration = + AVI->video_superindex->stdindex[cur_std_idx - 1]->nEntriesInUse - 1; + + for (audtr = 0; audtr < AVI->anum; audtr++) { + + if (!AVI->track[audtr].audio_superindex) { + // not initialized -> no index + continue; + } + avi_ixnn_entry (AVI, AVI->track[audtr].audio_superindex->stdindex[cur_std_idx - 1], + &AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1]); + + AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1].dwDuration = + AVI->track[audtr].audio_superindex->stdindex[cur_std_idx - 1]->nEntriesInUse - 1; + if (AVI->track[audtr].a_fmt == 0x1) { + AVI->track[audtr].audio_superindex->aIndex[cur_std_idx - 1].dwDuration *= + AVI->track[audtr].a_bits*AVI->track[audtr].a_rate*AVI->track[audtr].a_chans/800; + } + } + + // XXX: dump idx1 structure + if (cur_std_idx == 1) { + avi_add_chunk(AVI, (unsigned char *)"idx1", (unsigned char *)AVI->idx, AVI->n_idx*16); + // qwBaseOffset will contain the start of the second riff chunk + } + // Fix the Offsets later at closing time + avi_add_chunk(AVI, (unsigned char *)"RIFF", "AVIXLIST\0\0\0\0movi", 16); + + AVI->video_superindex->stdindex[ cur_std_idx ]->qwBaseOffset = AVI->pos -16 -8; +#ifdef DEBUG_ODML + printf("ODML: RIFF No.%02d at Offset 0x%llX\n", cur_std_idx, AVI->pos -16 -8); +#endif + + for (audtr = 0; audtr < AVI->anum; audtr++) { + if (AVI->track[audtr].audio_superindex) + AVI->track[audtr].audio_superindex->stdindex[ cur_std_idx ]->qwBaseOffset = + AVI->pos -16 -8; + + } + + // now we can be sure + AVI->is_opendml++; + } + + } + + + if (video) { + avi_add_odml_index_entry_core(AVI, flags, AVI->pos, len, + AVI->video_superindex->stdindex[ AVI->video_superindex->nEntriesInUse-1 ]); + + AVI->total_frames++; + } // video + + if (audio) { + avi_add_odml_index_entry_core(AVI, flags, AVI->pos, len, + AVI->track[AVI->aptr].audio_superindex->stdindex[ + AVI->track[AVI->aptr].audio_superindex->nEntriesInUse-1 ]); + } + + + return 0; +} + +// #undef NR_IXNN_CHUNKS + +static int avi_add_index_entry(avi_t *AVI, unsigned char *tag, long flags, unsigned long pos, unsigned long len) +{ + void *ptr; + + if(AVI->n_idx>=AVI->max_idx) { + ptr = realloc((void *)AVI->idx,(AVI->max_idx+4096)*16); + + if(ptr == 0) { + AVI_errno = AVI_ERR_NO_MEM; + return -1; + } + AVI->max_idx += 4096; + AVI->idx = (unsigned char((*)[16]) ) ptr; + } + + /* Add index entry */ + + veejay_memcpy(AVI->idx[AVI->n_idx],tag,4); + long2str(AVI->idx[AVI->n_idx]+ 4,flags); + long2str(AVI->idx[AVI->n_idx]+ 8, pos); + long2str(AVI->idx[AVI->n_idx]+12, len); + + /* Update counter */ + + AVI->n_idx++; + + if(len>AVI->max_len) AVI->max_len=len; + + return 0; +} + +/* Returns 1 if more audio is in that video junk */ +int AVI_can_read_audio(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_WRITE) { return -1; } + if(!AVI->video_index) { return -1; } + if(!AVI->track[AVI->aptr].audio_index) { return -1; } + + // is it -1? the last ones got left out --tibit + //if (AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) { + if (AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks) { + return 0; + } + + if (AVI->video_pos >= AVI->video_frames) return 1; + + if (AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos < AVI->video_index[AVI->video_pos].pos) return 1; + else return 0; +} +/* + AVI_open_output_file: Open an AVI File and write a bunch + of zero bytes as space for the header. + + returns a pointer to avi_t on success, a zero pointer on error +*/ + +avi_t* AVI_open_output_file(char * filename) +{ + avi_t *AVI; + int i; + + unsigned char AVI_header[HEADERBYTES]; + + /* Allocate the avi_t struct and zero it */ + + AVI = (avi_t *) vj_malloc(sizeof(avi_t)); + if(AVI==0) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + veejay_memset((void *)AVI,0,sizeof(avi_t)); + + /* Since Linux needs a long time when deleting big files, + we do not truncate the file when we open it. + Instead it is truncated when the AVI file is closed */ + + // AVI->fdes = open(filename, O_RDWR|O_CREAT|O_BINARY, + // S_IRUSR | S_IWUSR | S_IGRP | S_IROTH); + + AVI->fdes = open(filename, O_RDWR | O_CREAT | O_STREAMING, 0644 ); + + if (AVI->fdes < 0) + { + AVI_errno = AVI_ERR_OPEN; + free(AVI); + return 0; + } + + /* Write out HEADERBYTES bytes, the header will go here + when we are finished with writing */ + + for (i=0;ifdes,(char *)AVI_header,HEADERBYTES); + if (i != HEADERBYTES) + { + close(AVI->fdes); + AVI_errno = AVI_ERR_WRITE; + free(AVI); + return 0; + } + + AVI->pos = HEADERBYTES; + AVI->mode = AVI_MODE_WRITE; /* open for writing */ + + //init + AVI->anum = 0; + AVI->aptr = 0; + + return AVI; +} + +void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor) +{ + /* may only be called if file is open for writing */ + + if(AVI->mode==AVI_MODE_READ) return; + + AVI->width = width; + AVI->height = height; + AVI->fps = fps; + + if(strncmp(compressor, "RGB", 3)==0) { + veejay_memset(AVI->compressor, 0, 4); + } else { + veejay_memcpy(AVI->compressor,compressor,4); + } + + AVI->compressor[4] = 0; + + avi_update_header(AVI); +} + +int AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format) +{ + /* may only be called if file is open for writing */ + + if(AVI->mode==AVI_MODE_READ) return -1; + + //inc audio tracks + AVI->aptr=AVI->anum; + ++AVI->anum; + + if(AVI->anum > AVI_MAX_TRACKS) { + veejay_msg(0, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS); + return -1; + } + + AVI->track[AVI->aptr].a_chans = channels; + AVI->track[AVI->aptr].a_rate = rate; + AVI->track[AVI->aptr].a_bits = bits; + AVI->track[AVI->aptr].a_fmt = format; +// AVI->track[AVI->aptr].mp3rate = mp3rate; + + return avi_update_header(AVI); +} + +#define OUT4CC(s) \ + if(nhb<=HEADERBYTES-4) veejay_memcpy(AVI_header+nhb,s,4); nhb += 4 + +#define OUTLONG(n) \ + if(nhb<=HEADERBYTES-4) long2str(AVI_header+nhb,n); nhb += 4 + +#define OUTSHRT(n) \ + if(nhb<=HEADERBYTES-2) { \ + AVI_header[nhb ] = (n )&0xff; \ + AVI_header[nhb+1] = (n>>8)&0xff; \ + } \ + nhb += 2 + +#define OUTCHR(n) \ + if(nhb<=HEADERBYTES-1) { \ + AVI_header[nhb ] = (n )&0xff; \ + } \ + nhb += 1 + +#define OUTMEM(d, s) \ + { \ + unsigned int s_ = (s); \ + if(nhb <= HEADERBYTES-s_) \ + veejay_memcpy(AVI_header+nhb, (d), s_); \ + nhb += s_; \ + } + + +//ThOe write preliminary AVI file header: 0 frames, max vid/aud size +int avi_update_header(avi_t *AVI) +{ + int njunk, sampsize, hasIndex, ms_per_frame, frate, flag; + int movi_len, hdrl_start, strl_start, j; + unsigned char AVI_header[HEADERBYTES]; + long nhb; + unsigned long xd_size, xd_size_align2; + + //assume max size + movi_len = AVI_MAX_LEN - HEADERBYTES + 4; + + //assume index will be written + hasIndex=1; + + if(AVI->fps < 0.001) { + frate=0; + ms_per_frame=0; + } else { + frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5); + ms_per_frame=(int) (1000000/AVI->fps + 0.5); + } + + /* Prepare the file header */ + + nhb = 0; + + /* The RIFF header */ + + OUT4CC ("RIFF"); + OUTLONG(movi_len); // assume max size + OUT4CC ("AVI "); + + /* Start the header list */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + hdrl_start = nhb; /* Store start position */ + OUT4CC ("hdrl"); + + /* The main AVI header */ + + /* The Flags in AVI File header */ + +#define AVIF_HASINDEX 0x00000010 /* Index at end of file */ +#define AVIF_MUSTUSEINDEX 0x00000020 +#define AVIF_ISINTERLEAVED 0x00000100 +#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */ +#define AVIF_WASCAPTUREFILE 0x00010000 +#define AVIF_COPYRIGHTED 0x00020000 + + OUT4CC ("avih"); + OUTLONG(56); /* # of bytes to follow */ + OUTLONG(ms_per_frame); /* Microseconds per frame */ + //ThOe ->0 + // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */ + OUTLONG(0); + OUTLONG(0); /* PaddingGranularity (whatever that might be) */ + /* Other sources call it 'reserved' */ + flag = AVIF_ISINTERLEAVED; + if(hasIndex) flag |= AVIF_HASINDEX; + if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX; + OUTLONG(flag); /* Flags */ + OUTLONG(0); // no frames yet + OUTLONG(0); /* InitialFrames */ + + OUTLONG(AVI->anum+1); + + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + /* MS calls the following 'reserved': */ + OUTLONG(0); /* TimeScale: Unit used to measure time */ + OUTLONG(0); /* DataRate: Data rate of playback */ + OUTLONG(0); /* StartTime: Starting time of AVI data */ + OUTLONG(0); /* DataLength: Size of AVI data chunk */ + + + /* Start the video stream list ---------------------------------- */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The video stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("vids"); /* Type */ + OUT4CC (AVI->compressor); /* Handler */ + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + OUTLONG(FRAME_RATE_SCALE); /* Scale */ + OUTLONG(frate); /* Rate: Rate/Scale == samples/second */ + OUTLONG(0); /* Start */ + OUTLONG(0); // no frames yet + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(-1); /* Quality */ + OUTLONG(0); /* SampleSize */ + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + // OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + + /* The video stream format */ + + xd_size = AVI->extradata_size; + xd_size_align2 = (AVI->extradata_size+1) & ~1; + + OUT4CC ("strf"); + OUTLONG(40 + xd_size_align2);/* # of bytes to follow */ + OUTLONG(40 + xd_size); /* Size */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ + OUT4CC (AVI->compressor); /* Compression */ + // ThOe (*3) + OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */ + OUTLONG(0); /* XPelsPerMeter */ + OUTLONG(0); /* YPelsPerMeter */ + OUTLONG(0); /* ClrUsed: Number of colors used */ + OUTLONG(0); /* ClrImportant: Number of colors important */ + + // write extradata + if (xd_size > 0 && AVI->extradata) { + OUTMEM(AVI->extradata, xd_size); + if (xd_size != xd_size_align2) { + OUTCHR(0); + } + } + + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + + long2str(AVI_header+strl_start-4,nhb-strl_start); + + + /* Start the audio stream list ---------------------------------- */ + + for(j=0; janum; ++j) { + + sampsize = avi_sampsize(AVI, j); + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The audio stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("auds"); + + // ----------- + // ThOe + OUTLONG(0); /* Format (Optionally) */ + // ----------- + + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + + // ThOe /4 + OUTLONG(sampsize/4); /* Scale */ + OUTLONG(1000*AVI->track[j].mp3rate/8); + OUTLONG(0); /* Start */ + OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */ + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(-1); /* Quality */ + + // ThOe /4 + OUTLONG(sampsize/4); /* SampleSize */ + + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + // OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + + /* The audio stream format */ + + OUT4CC ("strf"); + OUTLONG(16); /* # of bytes to follow */ + OUTSHRT(AVI->track[j].a_fmt); /* Format */ + OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ + OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ + // ThOe + OUTLONG(1000*AVI->track[j].mp3rate/8); + //ThOe (/4) + + OUTSHRT(sampsize/4); /* BlockAlign */ + + + OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ + + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + + long2str(AVI_header+strl_start-4,nhb-strl_start); + } + + /* Finish header list */ + + long2str(AVI_header+hdrl_start-4,nhb-hdrl_start); + + + /* Calculate the needed amount of junk bytes, output junk */ + + njunk = HEADERBYTES - nhb - 8 - 12; + + /* Safety first: if njunk <= 0, somebody has played with + HEADERBYTES without knowing what (s)he did. + This is a fatal error */ + + if(njunk<=0) + { + veejay_msg(0, "%s: # of header bytes too small",__FUNCTION__); + veejay_msg(0, "Somebody has played with HEADERBYTES of this AVI without knowing what (s)he did"); + return -1; + } + + OUT4CC ("JUNK"); + OUTLONG(njunk); + veejay_memset(AVI_header+nhb,0,njunk); + + nhb += njunk; + + /* Start the movi list */ + + OUT4CC ("LIST"); + OUTLONG(movi_len); /* Length of list in bytes */ + OUT4CC ("movi"); + + /* Output the header, truncate the file to the number of bytes + actually written, report an error if someting goes wrong */ + + if ( lseek(AVI->fdes,0,SEEK_SET)<0 || + avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES)!=HEADERBYTES || + lseek(AVI->fdes,AVI->pos,SEEK_SET)<0) + { + AVI_errno = AVI_ERR_CLOSE; + return -1; + } + + return 0; +} + +static int valid_info_tag(char *c) +{ + if (!strncmp(c, "IARL", 4)) return 1; + else if (!strncmp(c, "IART", 4)) return 1; + else if (!strncmp(c, "ICMS", 4)) return 1; + else if (!strncmp(c, "ICMT", 4)) return 1; + else if (!strncmp(c, "ICOP", 4)) return 1; + else if (!strncmp(c, "ICRD", 4)) return 1; + else if (!strncmp(c, "ICRP", 4)) return 1; + else if (!strncmp(c, "IDIM", 4)) return 1; + else if (!strncmp(c, "IDPI", 4)) return 1; + else if (!strncmp(c, "IENG", 4)) return 1; + else if (!strncmp(c, "IGNR", 4)) return 1; + else if (!strncmp(c, "IKEY", 4)) return 1; + else if (!strncmp(c, "ILGT", 4)) return 1; + else if (!strncmp(c, "IMED", 4)) return 1; + else if (!strncmp(c, "INAM", 4)) return 1; + else if (!strncmp(c, "IPLT", 4)) return 1; + else if (!strncmp(c, "IPRD", 4)) return 1; + else if (!strncmp(c, "ISBJ", 4)) return 1; + else if (!strncmp(c, "ISHP", 4)) return 1; + else if (!strncmp(c, "ISRC", 4)) return 1; + else if (!strncmp(c, "ISRF", 4)) return 1; + else if (!strncmp(c, "ITCH", 4)) return 1; + else return 0; + + return 0; +} +// see ../docs/avi_comments.txt +// returns the length of written stream (-1 on error) +static int avi_parse_comments (int fd, char *buf, int space_left) +{ + int len=0, readlen=0, k; + char *data, *c, *d; + struct stat st; + + // safety checks + if (fd<=0 || !buf || space_left<=0) + return -1; + + veejay_memset (buf, 0, space_left); + if (fstat (fd, &st) == -1) { + perror ("stat"); + return -1; + } + + if ( !(data = vj_malloc(st.st_size*sizeof(char)+1)) ) { + fprintf(stderr, "vj_malloc failed\n"); + return -1; + } + + readlen = avi_read ( fd, data, st.st_size); + + //printf("Read %d bytes from %d\n", readlen, fd); + + c = data; + space_left--; + + while (len < space_left) { + if ( !c || *c == '\0') + break; // eof; + else if (*c == '#') { // comment, ignore + c = strchr(c, '\n')+1; + } + else if (*c == '\n') { // empty, ignore + c++; + } + else if (*c == 'I') { + + // do not write ISFT -- this is written by transcode + // and important for debugging. + if (!valid_info_tag(c)) { + // skip this line + while (c && *c && *c != '\n' ) { + c++; + } + continue; + } + + // set d after TAG + d = c+4; + + // find first non-blank (!space or !TAB) + while ( d && *d && (*d == ' ' || *d == ' ')) ++d; + if (!d) break; + + // TAG without argument is fine but ignored + if (*d == '\n' || *d == '\r') { + c = d+1; + if (*c == '\n') ++c; + continue; + } + + k = 0; + while (d[k] != '\r' && d[k] != '\n' && d[k] != '\0') ++k; + if (k>=space_left) return len; + + // write TAG + veejay_memcpy(buf+len,c,4); + len += 4; + + // write length + '\0' + long2str(buf+len, k+1); len += 4; + + // write comment string + veejay_memcpy (buf+len, d, k); + // must be null terminated + *(buf+len+k+1) = '\0'; + + // PAD + if ((k+1)&1) { + k++; + *(buf+len+k+1) = '\0'; + } + len += k+1; + + // advance c + while (*c != '\n' && *c != '\0') ++c; + if (*c != '\0') ++c; + else break; + + } else { + + // ignore junk lines + while (c && *c && *c != '\n' ) { + if (*c == ' ' || *c == ' ') { c++; break; } + c++; + } + if (!c) break; + } + + } + free(data); + + return len; +} + +//SLM +#ifndef S_IRUSR +#define S_IRWXU 00700 /* read, write, execute: owner */ +#define S_IRUSR 00400 /* read permission: owner */ +#define S_IWUSR 00200 /* write permission: owner */ +#define S_IXUSR 00100 /* execute permission: owner */ +#define S_IRWXG 00070 /* read, write, execute: group */ +#define S_IRGRP 00040 /* read permission: group */ +#define S_IWGRP 00020 /* write permission: group */ +#define S_IXGRP 00010 /* execute permission: group */ +#define S_IRWXO 00007 /* read, write, execute: other */ +#define S_IROTH 00004 /* read permission: other */ +#define S_IWOTH 00002 /* write permission: other */ +#define S_IXOTH 00001 /* execute permission: other */ +#endif + +/* + Write the header of an AVI file and close it. + returns 0 on success, -1 on write error. +*/ + +static int avi_close_output_file(avi_t *AVI) +{ + + int ret, njunk, sampsize, hasIndex, ms_per_frame, frate, idxerror, flag; + unsigned long movi_len; + int hdrl_start, strl_start, j; + unsigned char AVI_header[HEADERBYTES]; + long nhb; + unsigned long xd_size, xd_size_align2; + +#ifdef INFO_LIST + long info_len; + long id_len, real_id_len; + long info_start_pos; +// time_t calptr; +#endif + + /* Calculate length of movi list */ + + // dump the rest of the index + if (AVI->is_opendml) { + int cur_std_idx = AVI->video_superindex->nEntriesInUse-1; + int audtr; + +#ifdef DEBUG_ODML + printf("ODML dump the rest indices\n"); +#endif + avi_ixnn_entry (AVI, AVI->video_superindex->stdindex[cur_std_idx], + &AVI->video_superindex->aIndex[cur_std_idx]); + + AVI->video_superindex->aIndex[cur_std_idx].dwDuration = + AVI->video_superindex->stdindex[cur_std_idx]->nEntriesInUse - 1; + + for (audtr = 0; audtr < AVI->anum; audtr++) { + if (!AVI->track[audtr].audio_superindex) { + // not initialized -> no index + continue; + } + avi_ixnn_entry (AVI, AVI->track[audtr].audio_superindex->stdindex[cur_std_idx], + &AVI->track[audtr].audio_superindex->aIndex[cur_std_idx]); + AVI->track[audtr].audio_superindex->aIndex[cur_std_idx].dwDuration = + AVI->track[audtr].audio_superindex->stdindex[cur_std_idx]->nEntriesInUse - 1; + if (AVI->track[audtr].a_fmt == 0x1) { + AVI->track[audtr].audio_superindex->aIndex[cur_std_idx].dwDuration *= + AVI->track[audtr].a_bits*AVI->track[audtr].a_rate*AVI->track[audtr].a_chans/800; + } + } + // The AVI->video_superindex->nEntriesInUse contains the offset + AVI->video_superindex->stdindex[ cur_std_idx+1 ]->qwBaseOffset = AVI->pos; + } + + if (AVI->is_opendml) { + // Correct! + movi_len = AVI->video_superindex->stdindex[ 1 ]->qwBaseOffset - HEADERBYTES+4 - AVI->n_idx*16 - 8; + } else { + movi_len = AVI->pos - HEADERBYTES + 4; + } + + + /* Try to ouput the index entries. This may fail e.g. if no space + is left on device. We will report this as an error, but we still + try to write the header correctly (so that the file still may be + readable in the most cases */ + + idxerror = 0; + hasIndex = 1; + if (!AVI->is_opendml) { + // fprintf(stderr, "pos=%lu, index_len=%ld \n", AVI->pos, AVI->n_idx*16); + ret = avi_add_chunk(AVI, (unsigned char *)"idx1", (unsigned char *)AVI->idx, AVI->n_idx*16); + hasIndex = (ret==0); + //fprintf(stderr, "pos=%lu, index_len=%d\n", AVI->pos, hasIndex); + + if(ret) { + idxerror = 1; + AVI_errno = AVI_ERR_WRITE_INDEX; + } + } + + /* Calculate Microseconds per frame */ + + if(AVI->fps < 0.001) { + frate=0; + ms_per_frame=0; + } else { + frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5); + ms_per_frame=(int) (1000000/AVI->fps + 0.5); + } + + /* Prepare the file header */ + + nhb = 0; + + /* The RIFF header */ + + OUT4CC ("RIFF"); + if (AVI->is_opendml) { + OUTLONG(AVI->video_superindex->stdindex[ 1 ]->qwBaseOffset - 8); /* # of bytes to follow */ + } else { + OUTLONG(AVI->pos - 8); /* # of bytes to follow */ + } + + OUT4CC ("AVI "); + + /* Start the header list */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + hdrl_start = nhb; /* Store start position */ + OUT4CC ("hdrl"); + + /* The main AVI header */ + + /* The Flags in AVI File header */ + +#define AVIF_HASINDEX 0x00000010 /* Index at end of file */ +#define AVIF_MUSTUSEINDEX 0x00000020 +#define AVIF_ISINTERLEAVED 0x00000100 +#define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */ +#define AVIF_WASCAPTUREFILE 0x00010000 +#define AVIF_COPYRIGHTED 0x00020000 + + OUT4CC ("avih"); + OUTLONG(56); /* # of bytes to follow */ + OUTLONG(ms_per_frame); /* Microseconds per frame */ + //ThOe ->0 + // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */ + OUTLONG(0); + OUTLONG(0); /* PaddingGranularity (whatever that might be) */ + /* Other sources call it 'reserved' */ + flag = AVIF_ISINTERLEAVED; + if(hasIndex) flag |= AVIF_HASINDEX; + if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX; + OUTLONG(flag); /* Flags */ + OUTLONG(AVI->video_frames); /* TotalFrames */ + OUTLONG(0); /* InitialFrames */ + + OUTLONG(AVI->anum+1); +// if (AVI->track[0].audio_bytes) +// { OUTLONG(2); } /* Streams */ +// else +// { OUTLONG(1); } /* Streams */ + + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + /* MS calls the following 'reserved': */ + OUTLONG(0); /* TimeScale: Unit used to measure time */ + OUTLONG(0); /* DataRate: Data rate of playback */ + OUTLONG(0); /* StartTime: Starting time of AVI data */ + OUTLONG(0); /* DataLength: Size of AVI data chunk */ + + + /* Start the video stream list ---------------------------------- */ + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The video stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("vids"); /* Type */ + OUT4CC (AVI->compressor); /* Handler */ + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + OUTLONG(FRAME_RATE_SCALE); /* Scale */ + OUTLONG(frate); /* Rate: Rate/Scale == samples/second */ + OUTLONG(0); /* Start */ + OUTLONG(AVI->video_frames); /* Length */ + OUTLONG(AVI->max_len); /* SuggestedBufferSize */ + OUTLONG(0); /* Quality */ + OUTLONG(0); /* SampleSize */ + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + //OUTLONG(0); /* Frame */ + + /* The video stream format */ + + xd_size = AVI->extradata_size; + xd_size_align2 = (AVI->extradata_size+1) & ~1; + + OUT4CC ("strf"); + OUTLONG(40 + xd_size_align2);/* # of bytes to follow */ + OUTLONG(40 + xd_size); /* Size */ + OUTLONG(AVI->width); /* Width */ + OUTLONG(AVI->height); /* Height */ + OUTSHRT(1); OUTSHRT(24); /* Planes, Count */ + OUT4CC (AVI->compressor); /* Compression */ + // ThOe (*3) + OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */ + OUTLONG(0); /* XPelsPerMeter */ + OUTLONG(0); /* YPelsPerMeter */ + OUTLONG(0); /* ClrUsed: Number of colors used */ + OUTLONG(0); /* ClrImportant: Number of colors important */ + + // write extradata if present + if (xd_size > 0 && AVI->extradata) { + OUTMEM(AVI->extradata, xd_size); + if (xd_size != xd_size_align2) { + OUTCHR(0); + } + } + + // dump index of indices for audio + if (AVI->is_opendml) { + + int k; + + OUT4CC(AVI->video_superindex->fcc); + OUTLONG(2+1+1+4+4+3*4 + AVI->video_superindex->nEntriesInUse * (8+4+4)); + OUTSHRT(AVI->video_superindex->wLongsPerEntry); + OUTCHR(AVI->video_superindex->bIndexSubType); + OUTCHR(AVI->video_superindex->bIndexType); + OUTLONG(AVI->video_superindex->nEntriesInUse); + OUT4CC(AVI->video_superindex->dwChunkId); + OUTLONG(0); + OUTLONG(0); + OUTLONG(0); + + + for (k = 0; k < AVI->video_superindex->nEntriesInUse; k++) { + uint32_t r = (AVI->video_superindex->aIndex[k].qwOffset >> 32) & 0xffffffff; + uint32_t s = (AVI->video_superindex->aIndex[k].qwOffset) & 0xffffffff; + + printf("VID NrEntries %d/%ld (%c%c%c%c) |0x%llX|%ld|%ld|\n", k, + (unsigned long)AVI->video_superindex->nEntriesInUse, + AVI->video_superindex->dwChunkId[0], + AVI->video_superindex->dwChunkId[1], + AVI->video_superindex->dwChunkId[2], + AVI->video_superindex->dwChunkId[3], + (unsigned long long)AVI->video_superindex->aIndex[k].qwOffset, + (unsigned long)AVI->video_superindex->aIndex[k].dwSize, + (unsigned long)AVI->video_superindex->aIndex[k].dwDuration + ); + /* + */ + + OUTLONG(s); + OUTLONG(r); + OUTLONG(AVI->video_superindex->aIndex[k].dwSize); + OUTLONG(AVI->video_superindex->aIndex[k].dwDuration); + } + + } + + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + + long2str(AVI_header+strl_start-4,nhb-strl_start); + + /* Start the audio stream list ---------------------------------- */ + + for(j=0; janum; ++j) { + + //if (AVI->track[j].a_chans && AVI->track[j].audio_bytes) + { + unsigned long nBlockAlign = 0; + unsigned long avgbsec = 0; + unsigned long scalerate = 0; + + sampsize = avi_sampsize(AVI, j); + sampsize = AVI->track[j].a_fmt==0x1?sampsize*4:sampsize; + + nBlockAlign = (AVI->track[j].a_rate<32000)?576:1152; + /* + printf("XXX sampsize (%d) block (%ld) rate (%ld) audio_bytes (%ld) mp3rate(%ld,%ld)\n", + sampsize, nBlockAlign, AVI->track[j].a_rate, + (long int)AVI->track[j].audio_bytes, + 1000*AVI->track[j].mp3rate/8, AVI->track[j].mp3rate); + */ + + if (AVI->track[j].a_fmt==0x1) { + sampsize = (AVI->track[j].a_chans<2)?sampsize/2:sampsize; + avgbsec = AVI->track[j].a_rate*sampsize/4; + scalerate = AVI->track[j].a_rate*sampsize/4; + } else { + avgbsec = 1000*AVI->track[j].mp3rate/8; + scalerate = 1000*AVI->track[j].mp3rate/8; + } + + OUT4CC ("LIST"); + OUTLONG(0); /* Length of list in bytes, don't know yet */ + strl_start = nhb; /* Store start position */ + OUT4CC ("strl"); + + /* The audio stream header */ + + OUT4CC ("strh"); + OUTLONG(56); /* # of bytes to follow */ + OUT4CC ("auds"); + + // ----------- + // ThOe + OUTLONG(0); /* Format (Optionally) */ + // ----------- + + OUTLONG(0); /* Flags */ + OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */ + OUTLONG(0); /* InitialFrames */ + + // VBR + if (AVI->track[j].a_fmt == 0x55 && AVI->track[j].a_vbr) { + OUTLONG(nBlockAlign); /* Scale */ + OUTLONG(AVI->track[j].a_rate); /* Rate */ + OUTLONG(0); /* Start */ + OUTLONG(AVI->track[j].audio_chunks); /* Length */ + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(0); /* Quality */ + OUTLONG(0); /* SampleSize */ + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + } else { + OUTLONG(sampsize/4); /* Scale */ + OUTLONG(scalerate); /* Rate */ + OUTLONG(0); /* Start */ + OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */ + OUTLONG(0); /* SuggestedBufferSize */ + OUTLONG(0xffffffff); /* Quality */ + OUTLONG(sampsize/4); /* SampleSize */ + OUTLONG(0); /* Frame */ + OUTLONG(0); /* Frame */ + } + + /* The audio stream format */ + + OUT4CC ("strf"); + + if (AVI->track[j].a_fmt == 0x55 && AVI->track[j].a_vbr) { + + OUTLONG(30); /* # of bytes to follow */ // mplayer writes 28 + OUTSHRT(AVI->track[j].a_fmt); /* Format */ // 2 + OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ // 2 + OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ // 4 + //ThOe/tibit + OUTLONG(1000*AVI->track[j].mp3rate/8); /* maybe we should write an avg. */ // 4 + OUTSHRT(nBlockAlign); /* BlockAlign */ // 2 + OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ // 2 + + OUTSHRT(12); /* cbSize */ // 2 + OUTSHRT(1); /* wID */ // 2 + OUTLONG(2); /* fdwFlags */ // 4 + OUTSHRT(nBlockAlign); /* nBlockSize */ // 2 + OUTSHRT(1); /* nFramesPerBlock */ // 2 + OUTSHRT(0); /* nCodecDelay */ // 2 + + } else if (AVI->track[j].a_fmt == 0x55 && !AVI->track[j].a_vbr) { + + OUTLONG(30); /* # of bytes to follow */ + OUTSHRT(AVI->track[j].a_fmt); /* Format */ + OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ + OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ + //ThOe/tibit + OUTLONG(1000*AVI->track[j].mp3rate/8); + OUTSHRT(sampsize/4); /* BlockAlign */ + OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ + + OUTSHRT(12); /* cbSize */ + OUTSHRT(1); /* wID */ + OUTLONG(2); /* fdwFlags */ + OUTSHRT(nBlockAlign); /* nBlockSize */ + OUTSHRT(1); /* nFramesPerBlock */ + OUTSHRT(0); /* nCodecDelay */ + + } else { + + OUTLONG(18); /* # of bytes to follow */ + OUTSHRT(AVI->track[j].a_fmt); /* Format */ + OUTSHRT(AVI->track[j].a_chans); /* Number of channels */ + OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */ + //ThOe/tibit + OUTLONG(avgbsec); /* Avg bytes/sec */ + OUTSHRT(sampsize/4); /* BlockAlign */ + OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */ + OUTSHRT(0); /* cbSize */ + + } + } + if (AVI->is_opendml) { + + int k ; + + if (!AVI->track[j].audio_superindex) { + // not initialized -> no index + continue; + } + + OUT4CC(AVI->track[j].audio_superindex->fcc); /* "indx" */ + OUTLONG(2+1+1+4+4+3*4 + AVI->track[j].audio_superindex->nEntriesInUse * (8+4+4)); + OUTSHRT(AVI->track[j].audio_superindex->wLongsPerEntry); + OUTCHR(AVI->track[j].audio_superindex->bIndexSubType); + OUTCHR(AVI->track[j].audio_superindex->bIndexType); + OUTLONG(AVI->track[j].audio_superindex->nEntriesInUse); + OUT4CC(AVI->track[j].audio_superindex->dwChunkId); + OUTLONG(0); OUTLONG(0); OUTLONG(0); + + for (k = 0; k < AVI->track[j].audio_superindex->nEntriesInUse; k++) { + uint32_t r = (AVI->track[j].audio_superindex->aIndex[k].qwOffset >> 32) & 0xffffffff; + uint32_t s = (AVI->track[j].audio_superindex->aIndex[k].qwOffset) & 0xffffffff; + + /* + printf("AUD[%d] NrEntries %d/%ld (%c%c%c%c) |0x%llX|%ld|%ld| \n", j, k, + AVI->track[j].audio_superindex->nEntriesInUse, + AVI->track[j].audio_superindex->dwChunkId[0], AVI->track[j].audio_superindex->dwChunkId[1], + AVI->track[j].audio_superindex->dwChunkId[2], AVI->track[j].audio_superindex->dwChunkId[3], + AVI->track[j].audio_superindex->aIndex[k].qwOffset, + AVI->track[j].audio_superindex->aIndex[k].dwSize, + AVI->track[j].audio_superindex->aIndex[k].dwDuration + ); + */ + + OUTLONG(s); + OUTLONG(r); + OUTLONG(AVI->track[j].audio_superindex->aIndex[k].dwSize); + OUTLONG(AVI->track[j].audio_superindex->aIndex[k].dwDuration); + } + } + /* Finish stream list, i.e. put number of bytes in the list to proper pos */ + long2str(AVI_header+strl_start-4,nhb-strl_start); + } + + if (AVI->is_opendml) { + OUT4CC("LIST"); + OUTLONG(16); + OUT4CC("odml"); + OUT4CC("dmlh"); + OUTLONG(4); + OUTLONG(AVI->total_frames); + } + + /* Finish header list */ + + long2str(AVI_header+hdrl_start-4,nhb-hdrl_start); + + + // add INFO list --- (0.6.0pre4) + +#ifdef INFO_LIST + OUT4CC ("LIST"); + + info_start_pos = nhb; + info_len = MAX_INFO_STRLEN + 12; + OUTLONG(info_len); // rewritten later + OUT4CC ("INFO"); + + OUT4CC ("ISFT"); + //OUTLONG(MAX_INFO_STRLEN); + veejay_memset(id_str, 0, MAX_INFO_STRLEN); + + snprintf(id_str, sizeof(id_str), "%s-%s", PACKAGE, VERSION); + real_id_len = id_len = strlen(id_str)+1; + if (id_len&1) id_len++; + + OUTLONG(real_id_len); + + veejay_memset(AVI_header+nhb, 0, id_len); + veejay_memcpy(AVI_header+nhb, id_str, id_len); + nhb += id_len; + + info_len = avi_parse_comments (AVI->comment_fd, AVI_header+nhb, HEADERBYTES - nhb - 8 - 12); + if (info_len <= 0) info_len=0; + + // write correct len + long2str(AVI_header+info_start_pos, info_len + id_len + 4+4+4); + + nhb += info_len; + +// OUT4CC ("ICMT"); +// OUTLONG(MAX_INFO_STRLEN); + +// calptr=time(NULL); +// snprintf(id_str, sizeof(id_str), "\t%s %s", ctime(&calptr), ""); +// veejay_memset(AVI_header+nhb, 0, MAX_INFO_STRLEN); +// veejay_memcpy(AVI_header+nhb, id_str, 25); +// nhb += MAX_INFO_STRLEN; +#endif + + // ---------------------------- + + /* Calculate the needed amount of junk bytes, output junk */ + + njunk = HEADERBYTES - nhb - 8 - 12; + + /* Safety first: if njunk <= 0, somebody has played with + HEADERBYTES without knowing what (s)he did. + This is a fatal error */ + + if(njunk<=0) + { + fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n"); + exit(1); + } + + OUT4CC ("JUNK"); + OUTLONG(njunk); + veejay_memset(AVI_header+nhb,0,njunk); + + nhb += njunk; + + /* Start the movi list */ + + OUT4CC ("LIST"); + OUTLONG(movi_len); /* Length of list in bytes */ + OUT4CC ("movi"); + + /* Output the header, truncate the file to the number of bytes + actually written, report an error if someting goes wrong */ + + if ( lseek(AVI->fdes,0,SEEK_SET)<0 || + avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES)!=HEADERBYTES || + ftruncate(AVI->fdes,AVI->pos)<0 ) + { + AVI_errno = AVI_ERR_CLOSE; + return -1; + } + + + // Fix up the empty additional RIFF and LIST chunks + if (AVI->is_opendml) { + int k = 0; + char f[4]; + unsigned int len; + + for (k=1; kvideo_superindex->nEntriesInUse; k++) { + // the len of the RIFF Chunk + lseek(AVI->fdes, AVI->video_superindex->stdindex[k]->qwBaseOffset+4, SEEK_SET); + len = AVI->video_superindex->stdindex[k+1]->qwBaseOffset - + AVI->video_superindex->stdindex[k]->qwBaseOffset - 8; + long2str(f, len); + avi_write(AVI->fdes, f, 4); + + // len of the LIST/movi chunk + lseek(AVI->fdes, 8, SEEK_CUR); + len -= 12; + long2str(f, len); + avi_write(AVI->fdes, f, 4); + } + } + + + if(idxerror) return -1; + + return 0; +} + +/* + AVI_write_data: + Add video or audio data to the file; + + Return values: + 0 No error; + -1 Error, AVI_errno is set appropriatly; + +*/ + +static int avi_write_data(avi_t *AVI, char *data, unsigned long length, int audio, int keyframe) +{ + int n = 0; + + unsigned char astr[5]; + + // transcode core itself checks for the size -- unneeded and + // does harm to xvid 2pass encodes where the first pass can get + // _very_ large -- tibit. + +#if 0 + /* Check for maximum file length */ + + if ( (AVI->pos + 8 + length + 8 + (AVI->n_idx+1)*16) > AVI_MAX_LEN ) { + AVI_errno = AVI_ERR_SIZELIM; + return -1; + } +#endif + + /* Add index entry */ + + //set tag for current audio track + snprintf((char *)astr, sizeof(astr), "0%1dwb", (int)(AVI->aptr+1)); + + if(audio) { + if (!AVI->is_opendml) n = avi_add_index_entry(AVI,astr,0x10,AVI->pos,length); + n += avi_add_odml_index_entry(AVI,astr,0x10,AVI->pos,length); + } else { + if (!AVI->is_opendml) n = avi_add_index_entry(AVI,(unsigned char *)"00db",((keyframe)?0x10:0x0),AVI->pos,length); + n += avi_add_odml_index_entry(AVI,(unsigned char *)"00db",((keyframe)?0x10:0x0),AVI->pos,length); + } + + if(n) return -1; + + /* Output tag and data */ + + if(audio) + n = avi_add_chunk(AVI,(unsigned char *)astr,data,length); + else + n = avi_add_chunk(AVI,(unsigned char *)"00db",data,length); + + if (n) return -1; + + return 0; +} + +int AVI_write_frame(avi_t *AVI, char *data, long bytes) +{ + int keyframe = 1; //@everything is a keyframe in veejay + off_t pos; + + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + pos = AVI->pos; + + if(avi_write_data(AVI,data,bytes,0,keyframe)) return -1; + + AVI->last_pos = pos; + AVI->last_len = bytes; + AVI->video_frames++; + return 0; +} + +int AVI_dup_frame(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + if(AVI->last_pos==0) return 0; /* No previous real frame */ + if(avi_add_index_entry(AVI,(unsigned char *)"00db",0x10,AVI->last_pos,AVI->last_len)) return -1; + AVI->video_frames++; + AVI->must_use_index = 1; + return 0; +} + +int AVI_write_audio(avi_t *AVI, char *data, long bytes) +{ + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + if( avi_write_data(AVI,data,bytes,1,0) ) return -1; + AVI->track[AVI->aptr].audio_bytes += bytes; + AVI->track[AVI->aptr].audio_chunks++; + return 0; +} + + +int AVI_append_audio(avi_t *AVI, char *data, long bytes) +{ + + // won't work for >2gb + long i, length, pos; + unsigned char c[4]; + + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + // update last index entry: + + --AVI->n_idx; + length = str2ulong(AVI->idx[AVI->n_idx]+12); + pos = str2ulong(AVI->idx[AVI->n_idx]+8); + + //update; + long2str(AVI->idx[AVI->n_idx]+12,length+bytes); + + ++AVI->n_idx; + + AVI->track[AVI->aptr].audio_bytes += bytes; + + //update chunk header + lseek(AVI->fdes, pos+4, SEEK_SET); + long2str(c, length+bytes); + avi_write(AVI->fdes, (char *)c, 4); + + lseek(AVI->fdes, pos+8+length, SEEK_SET); + + i=PAD_EVEN(length + bytes); + + bytes = i - length; + avi_write(AVI->fdes, data, bytes); + AVI->pos = pos + 8 + i; + + return 0; +} + + +long AVI_bytes_remain(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_READ) return 0; + + return ( AVI_MAX_LEN - (AVI->pos + 8 + 16*AVI->n_idx)); +} + +long AVI_bytes_written(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_READ) return 0; + + return (AVI->pos + 8 + 16*AVI->n_idx); +} + +int AVI_set_audio_track(avi_t *AVI, int track) +{ + + if(track < 0 || track + 1 > AVI->anum) return(-1); + + //this info is not written to file anyway + AVI->aptr=track; + return 0; +} + +int AVI_get_audio_track(avi_t *AVI) +{ + return(AVI->aptr); +} + +void AVI_set_audio_vbr(avi_t *AVI, long is_vbr) +{ + AVI->track[AVI->aptr].a_vbr = is_vbr; +} + +long AVI_get_audio_vbr(avi_t *AVI) +{ + return(AVI->track[AVI->aptr].a_vbr); +} + +void AVI_set_comment_fd(avi_t *AVI, int fd) +{ + AVI->comment_fd = fd; +} +int AVI_get_comment_fd(avi_t *AVI) +{ + return AVI->comment_fd; +} + + +/******************************************************************* + * * + * Utilities for reading video and audio from an AVI File * + * * + *******************************************************************/ + +int AVI_close(avi_t *AVI) +{ + int ret; + int j,k; + + /* If the file was open for writing, the header and index still have + to be written */ + + if(AVI->mode == AVI_MODE_WRITE) + ret = avi_close_output_file(AVI); + else + ret = 0; + + /* Even if there happened an error, we first clean up */ + if( AVI->mmap_region ) + mmap_free( AVI->mmap_region ); + + if (AVI->comment_fd>0) + close(AVI->comment_fd); + AVI->comment_fd = -1; + close(AVI->fdes); + if(AVI->idx) free(AVI->idx); + if(AVI->video_index) free(AVI->video_index); + if(AVI->video_superindex && AVI->video_superindex->stdindex) { + for (j = 0; j < NR_IXNN_CHUNKS; j++) { + if (AVI->video_superindex->stdindex[j]) { + if (AVI->video_superindex->stdindex[j]->aIndex) { + free(AVI->video_superindex->stdindex[j]->aIndex); + } + free(AVI->video_superindex->stdindex[j]); + } + } + if(AVI->video_superindex->stdindex) free(AVI->video_superindex->stdindex); + if(AVI->video_superindex->aIndex) free(AVI->video_superindex->aIndex); + free(AVI->video_superindex); + } + + for (j=0; janum; j++) + { + if(AVI->track[j].audio_index) free(AVI->track[j].audio_index); + if(AVI->track[j].audio_superindex) { + // shortcut + avisuperindex_chunk *a = AVI->track[j].audio_superindex; + for (k = 0; k < NR_IXNN_CHUNKS; k++) { + if (a->stdindex && a->stdindex[k]) { + if (a->stdindex[k]->aIndex) { + free(a->stdindex[k]->aIndex); + } + free(a->stdindex[k]); + } + } + if(a->stdindex) free(a->stdindex); + if(a->aIndex) free(a->aIndex); + free(a); + } + } + + if (AVI->bitmap_info_header) + free(AVI->bitmap_info_header); + for (j = 0; j < AVI->anum; j++) + if (AVI->wave_format_ex[j]) + free(AVI->wave_format_ex[j]); + + free(AVI); + AVI=NULL; + + return ret; +} + + +#define ERR_EXIT(x) \ +{ \ + AVI_close(AVI); \ + AVI_errno = x; \ + return 0; \ +} + +avi_t *AVI_open_input_indexfile(char *filename, int getIndex, char *indexfile) +{ + avi_t *AVI=NULL; + + /* Create avi_t structure */ + + AVI = (avi_t *) vj_malloc(sizeof(avi_t)); + if(AVI==NULL) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + veejay_memset((void *)AVI,0,sizeof(avi_t)); + + AVI->mode = AVI_MODE_READ; /* open for reading */ + + /* Open the file */ + +#if defined(SYS_WINDOWS) + AVI->fdes = open(filename,O_RDONLY|O_BINARY); +#else + AVI->fdes = open(filename,O_RDONLY); +#endif + if(AVI->fdes < 0) + { + AVI_errno = AVI_ERR_OPEN; + free(AVI); + return 0; + } + + off_t len = lseek( AVI->fdes, 0, SEEK_END ); + if( len <= (HEADERBYTES+16)) + { + AVI_errno = AVI_ERR_EMPTY; + free(AVI); + return 0; + } + lseek( AVI->fdes,0,SEEK_SET ); + + + AVI->index_file=strdup(indexfile); + AVI_errno = 0; + avi_parse_input_file(AVI, getIndex); + + if (AVI != NULL && !AVI_errno) { + AVI->aptr=0; //reset + } + + if (AVI_errno) + return AVI=NULL; + else + return AVI; +} + +avi_t *AVI_open_indexfd(int fd, int getIndex, char *indexfile) +{ + avi_t *AVI=NULL; + + /* Create avi_t structure */ + + AVI = (avi_t *) vj_malloc(sizeof(avi_t)); + if(AVI==NULL) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + veejay_memset((void *)AVI,0,sizeof(avi_t)); + + AVI->mode = AVI_MODE_READ; /* open for reading */ + + // file alread open + AVI->fdes = fd; + + AVI->index_file=strdup(indexfile); + AVI_errno = 0; + avi_parse_input_file(AVI, getIndex); + + if (AVI != NULL && !AVI_errno) { + AVI->aptr=0; //reset + } + + if (AVI_errno) + return AVI=NULL; + else + return AVI; +} + + +avi_t *AVI_open_input_file(char *filename, int getIndex, int mmap_size) +{ + avi_t *AVI=NULL; + + /* Create avi_t structure */ + + AVI = (avi_t *) vj_calloc(sizeof(avi_t)); + if(AVI==NULL) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + + AVI->mode = AVI_MODE_READ; /* open for reading */ + + /* Open the file */ + + AVI->fdes = open(filename,O_RDONLY); + if(AVI->fdes < 0) + { + AVI_errno = AVI_ERR_OPEN; + free(AVI); + return 0; + } + + AVI_errno = 0; + avi_parse_input_file(AVI, getIndex); + + if (AVI != NULL && !AVI_errno) { + AVI->aptr=0; //reset + } + + if (AVI_errno) + return AVI=NULL; + else + return AVI; +} + +avi_t *AVI_open_fd(int fd, int getIndex, int mmap_size) +{ + avi_t *AVI=NULL; + + /* Create avi_t structure */ + + AVI = (avi_t *) vj_malloc(sizeof(avi_t)); + if(AVI==NULL) + { + AVI_errno = AVI_ERR_NO_MEM; + return 0; + } + veejay_memset((void *)AVI,0,sizeof(avi_t)); + + AVI->mode = AVI_MODE_READ; /* open for reading */ + + // file alread open + AVI->fdes = fd; + + AVI_errno = 0; + avi_parse_input_file(AVI, getIndex); + + if (AVI != NULL && !AVI_errno) { + AVI->aptr=0; //reset + } + + + if(!AVI_errno) + { + long file_size = (long)lseek( AVI->fdes, 0, SEEK_END ); + lseek( AVI->fdes, AVI->movi_start, SEEK_SET ); + AVI->mmap_size = AVI->width * AVI->height * mmap_size; + if(AVI->mmap_size > 0 ) + { + AVI->mmap_region = + mmap_file( AVI->fdes,0,AVI->mmap_size,file_size ); + } + } + + + if (AVI_errno) + return AVI=NULL; + else + return AVI; +} + +// transcode-0.6.8 +// reads a file generated by aviindex and builds the index out of it. + +int avi_parse_index_from_file(avi_t *AVI, char *filename) +{ + char data[100]; // line buffer + FILE *fd = NULL; // read from + off_t pos, len, f_pos, tot_chunks[AVI_MAX_TRACKS]; + int key=0, type; + int vid_chunks=0, aud_chunks[AVI_MAX_TRACKS]; + long line_count=0; + char *c, d; + int i,j; + + for (i=0; ivideo_index) { + free(AVI->video_index); + AVI->video_index = NULL; + } + + for(j=0; janum; ++j) { + if(AVI->track[j].audio_index) { + free(AVI->track[j].audio_index); + } + AVI->track[j].audio_index = NULL; + AVI->track[j].audio_chunks = 0; + } + + if (!(fd = fopen(filename, "r"))) { perror ("avi_parse_index_from_file: fopen"); return -1; } + + // read header + fgets(data, 100, fd); + + if ( strncasecmp(data, "AVIIDX1", 7) != 0) { + fprintf(stderr, "%s: Not an AVI index file\n", filename); + return -1; + } + + // read comment + fgets(data, 100, fd); + f_pos = ftell(fd); + while (fgets(data, 100, fd)) { + d = data[5] - '1'; + if (d == 0) { + vid_chunks++; + } else if (d == 1 || d == 2 || d == 3 || d == 4 || + d == 5 || d == 6 || d == 7 || d == 8 ) { + aud_chunks[d-1]++; + } else + continue; + + line_count++; + } + + AVI->video_frames = vid_chunks; + for(j=0; janum; ++j) AVI->track[j].audio_chunks = aud_chunks[j]; + + if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS); + AVI->video_index = (video_index_entry *) vj_malloc(vid_chunks*sizeof(video_index_entry)); + if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + + for(j=0; janum; ++j) { + if(AVI->track[j].audio_chunks) { + AVI->track[j].audio_index = (audio_index_entry *) vj_malloc(aud_chunks[j]*sizeof(audio_index_entry)); + if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + } + } + + // reset after header + fseek(fd, f_pos, SEEK_SET); + + vid_chunks = 0; + for(j=0; janum; ++j) aud_chunks[j] = tot_chunks[j] = 0; + + while (fgets(data, 100, fd)) { + // this is very slow + // sscanf(data, "%*s %d %*d %*d %lld %lld %d %*f", &type, &pos, &len, &key); + c = strchr (data, ' '); + type = strtol(c+1, &c, 10); + //ch = strtol(c+1, &c, 10); + c = strchr(c+1, ' '); + //chtype= strtol(c+1, &c, 10); + c = strchr(c+1, ' '); + pos = strtoll(c+1, &c, 10); + len = strtol(c+1, &c, 10); + key = strtol(c+1, &c, 10); + //ms = strtod(c+1, NULL); + i = type-1; + + switch (i) { + case 0: // video + AVI->video_index[vid_chunks].key = (off_t)(key?0x10:0); + AVI->video_index[vid_chunks].pos = pos+8; + AVI->video_index[vid_chunks].len = len; + vid_chunks++; + break; + case 1: case 2: case 3: case 4: + case 5: case 6: case 7: case 8: + j=i-1; + AVI->track[j].audio_index[aud_chunks[j]].pos = pos+8; + AVI->track[j].audio_index[aud_chunks[j]].len = len; + AVI->track[j].audio_index[aud_chunks[j]].tot = tot_chunks[j]; + tot_chunks[j] += AVI->track[j].audio_index[aud_chunks[j]].len; + aud_chunks[j]++; + break; + default: + continue; + } + + } + for(j=0; janum; ++j) AVI->track[j].audio_bytes = tot_chunks[j]; + + fclose (fd); + + return 0; +} + +int avi_parse_input_file(avi_t *AVI, int getIndex) +{ + long i, rate, scale, idx_type; + off_t n; + unsigned char *hdrl_data; + long header_offset=0, hdrl_len=0; + long nvi, nai[AVI_MAX_TRACKS], ioff; + long tot[AVI_MAX_TRACKS]; + int j; + int lasttag = 0; + int vids_strh_seen = 0; + int vids_strf_seen = 0; + int auds_strh_seen = 0; + // int auds_strf_seen = 0; + int num_stream = 0; + char data[256]; + off_t oldpos=-1, newpos=-1; + + /* Read first 12 bytes and check that this is an AVI file */ + + if( avi_read(AVI->fdes,data,12) != 12 ) ERR_EXIT(AVI_ERR_READ) + + if( strncasecmp(data ,"RIFF",4) !=0 || + strncasecmp(data+8,"AVI ",4) !=0 ) ERR_EXIT(AVI_ERR_NO_AVI) + + /* Go through the AVI file and extract the header list, + the start position of the 'movi' list and an optionally + present idx1 tag */ + + hdrl_data = 0; + + + while(1) + { + if( avi_read(AVI->fdes,data,8) != 8 ) break; /* We assume it's EOF */ + newpos=lseek(AVI->fdes,0,SEEK_CUR); + if(oldpos==newpos) { + /* This is a broken AVI stream... */ + return -1; + } + oldpos=newpos; + + n = str2ulong((unsigned char *)data+4); + n = PAD_EVEN(n); + + if(strncasecmp(data,"LIST",4) == 0) + { + if( avi_read(AVI->fdes,data,4) != 4 ) ERR_EXIT(AVI_ERR_READ) + n -= 4; + if(strncasecmp(data,"hdrl",4) == 0) + { + hdrl_len = n; + hdrl_data = (unsigned char *) vj_malloc(n); + if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM); + + // offset of header + + header_offset = lseek(AVI->fdes,0,SEEK_CUR); + + if( avi_read(AVI->fdes,(char *)hdrl_data,n) != n ) ERR_EXIT(AVI_ERR_READ) + } + else if(strncasecmp(data,"movi",4) == 0) + { + AVI->movi_start = lseek(AVI->fdes,0,SEEK_CUR); + if (lseek(AVI->fdes,n,SEEK_CUR)==(off_t)-1) break; + } + else + if (lseek(AVI->fdes,n,SEEK_CUR)==(off_t)-1) break; + } + else if(strncasecmp(data,"idx1",4) == 0) + { + /* n must be a multiple of 16, but the reading does not + break if this is not the case */ + + AVI->n_idx = AVI->max_idx = n/16; + AVI->idx = (unsigned char((*)[16]) ) vj_malloc(n); + if(AVI->idx==0) ERR_EXIT(AVI_ERR_NO_MEM) + if(avi_read(AVI->fdes, (char *) AVI->idx, n) != n ) { + free ( AVI->idx); AVI->idx=NULL; + AVI->n_idx = 0; + } + } + else + lseek(AVI->fdes,n,SEEK_CUR); + } + + if(!hdrl_data ) ERR_EXIT(AVI_ERR_NO_HDRL) + if(!AVI->movi_start) ERR_EXIT(AVI_ERR_NO_MOVI) + + /* Interpret the header list */ + + for(i=0;icompressor,hdrl_data+i+4,4); + AVI->compressor[4] = 0; + + // ThOe + AVI->v_codech_off = header_offset + i+4; + + scale = str2ulong(hdrl_data+i+20); + rate = str2ulong(hdrl_data+i+24); + if(scale!=0) AVI->fps = (double)rate/(double)scale; + AVI->video_frames = str2ulong(hdrl_data+i+32); + AVI->video_strn = num_stream; + AVI->max_len = 0; + vids_strh_seen = 1; + lasttag = 1; /* vids */ + } + else if (strncasecmp ((char *)hdrl_data+i,"auds",4) ==0 && ! auds_strh_seen) + { + + //inc audio tracks + AVI->aptr=AVI->anum; + ++AVI->anum; + + if(AVI->anum > AVI_MAX_TRACKS) { + fprintf(stderr, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS); + return(-1); + } + + AVI->track[AVI->aptr].audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, 0); + AVI->track[AVI->aptr].audio_strn = num_stream; + + // if samplesize==0 -> vbr + AVI->track[AVI->aptr].a_vbr = !str2ulong(hdrl_data+i+44); + + AVI->track[AVI->aptr].padrate = str2ulong(hdrl_data+i+24); + + // auds_strh_seen = 1; + lasttag = 2; /* auds */ + + // ThOe + AVI->track[AVI->aptr].a_codech_off = header_offset + i; + + } + else if (strncasecmp (hdrl_data+i,"iavs",4) ==0 && ! auds_strh_seen) { + fprintf(stderr, "AVILIB: error - DV AVI Type 1 no supported\n"); + return (-1); + } + else + lasttag = 0; + num_stream++; + } + else if(strncasecmp(hdrl_data+i,"dmlh",4) == 0) { + AVI->total_frames = str2ulong(hdrl_data+i+8); +#ifdef DEBUG_ODML + fprintf(stderr, "real number of frames %d\n", AVI->total_frames); +#endif + i += 8; + } + else if(strncasecmp((char *)hdrl_data+i,"strf",4)==0) + { + i += 8; + if(lasttag == 1) + { + alBITMAPINFOHEADER bih; + + veejay_memcpy(&bih, hdrl_data + i, sizeof(alBITMAPINFOHEADER)); + AVI->bitmap_info_header = (alBITMAPINFOHEADER *) + vj_malloc(str2ulong((unsigned char *)&bih.bi_size)); + if (AVI->bitmap_info_header != NULL) + veejay_memcpy(AVI->bitmap_info_header, hdrl_data + i, + str2ulong((unsigned char *)&bih.bi_size)); + + AVI->width = str2ulong(hdrl_data+i+4); + AVI->height = str2ulong(hdrl_data+i+8); + vids_strf_seen = 1; + //ThOe + AVI->v_codecf_off = header_offset + i+16; + + veejay_memcpy(AVI->compressor2, hdrl_data+i+16, 4); + AVI->compressor2[4] = 0; + + } + else if(lasttag == 2) + { + alWAVEFORMATEX *wfe; + char *nwfe; + int wfes; + + if ((hdrl_len - i) < sizeof(alWAVEFORMATEX)) + wfes = hdrl_len - i; + else + wfes = sizeof(alWAVEFORMATEX); + wfe = (alWAVEFORMATEX *)vj_malloc(sizeof(alWAVEFORMATEX)); + if (wfe != NULL) { + veejay_memset(wfe, 0, sizeof(alWAVEFORMATEX)); + veejay_memcpy(wfe, hdrl_data + i, wfes); + if (str2ushort((unsigned char *)&wfe->cb_size) != 0) { + nwfe = (char *) + realloc(wfe, sizeof(alWAVEFORMATEX) + + str2ushort((unsigned char *)&wfe->cb_size)); + if (nwfe != 0) { + off_t lpos = lseek(AVI->fdes, 0, SEEK_CUR); + lseek(AVI->fdes, header_offset + i + sizeof(alWAVEFORMATEX), + SEEK_SET); + wfe = (alWAVEFORMATEX *)nwfe; + nwfe = &nwfe[sizeof(alWAVEFORMATEX)]; + avi_read(AVI->fdes, nwfe, + str2ushort((unsigned char *)&wfe->cb_size)); + lseek(AVI->fdes, lpos, SEEK_SET); + } + } + AVI->wave_format_ex[AVI->aptr] = wfe; + } + + AVI->track[AVI->aptr].a_fmt = str2ushort(hdrl_data+i ); + + //ThOe + AVI->track[AVI->aptr].a_codecf_off = header_offset + i; + + AVI->track[AVI->aptr].a_chans = str2ushort(hdrl_data+i+2); + AVI->track[AVI->aptr].a_rate = str2ulong (hdrl_data+i+4); + //ThOe: read mp3bitrate + AVI->track[AVI->aptr].mp3rate = 8*str2ulong(hdrl_data+i+8)/1000; + //:ThOe + AVI->track[AVI->aptr].a_bits = str2ushort(hdrl_data+i+14); + // auds_strf_seen = 1; + } + } + else if(strncasecmp(hdrl_data+i,"indx",4) == 0) { + char *a; + int j; + + if(lasttag == 1) // V I D E O + { + + a = hdrl_data+i; + + AVI->video_superindex = (avisuperindex_chunk *) vj_calloc (sizeof (avisuperindex_chunk)); + veejay_memcpy (AVI->video_superindex->fcc, a, 4); a += 4; + AVI->video_superindex->dwSize = str2ulong(a); a += 4; + AVI->video_superindex->wLongsPerEntry = str2ushort(a); a += 2; + AVI->video_superindex->bIndexSubType = *a; a += 1; + AVI->video_superindex->bIndexType = *a; a += 1; + AVI->video_superindex->nEntriesInUse = str2ulong(a); a += 4; + veejay_memcpy (AVI->video_superindex->dwChunkId, a, 4); a += 4; + + // 3 * reserved + a += 4; a += 4; a += 4; + + if (AVI->video_superindex->bIndexSubType != 0) {fprintf(stderr, "Invalid Header, bIndexSubType != 0\n"); } + + AVI->video_superindex->aIndex = + vj_malloc (AVI->video_superindex->wLongsPerEntry * AVI->video_superindex->nEntriesInUse * sizeof (uint32_t)); + + // position of ix## chunks + for (j=0; jvideo_superindex->nEntriesInUse; ++j) { + AVI->video_superindex->aIndex[j].qwOffset = str2ullong (a); a += 8; + AVI->video_superindex->aIndex[j].dwSize = str2ulong (a); a += 4; + AVI->video_superindex->aIndex[j].dwDuration = str2ulong (a); a += 4; + +#ifdef DEBUG_ODML + printf("[%d] 0x%llx 0x%lx %lu\n", j, + (unsigned long long)AVI->video_superindex->aIndex[j].qwOffset, + (unsigned long)AVI->video_superindex->aIndex[j].dwSize, + (unsigned long)AVI->video_superindex->aIndex[j].dwDuration); +#endif + } + + +#ifdef DEBUG_ODML + printf("FOURCC \"%c%c%c%c\"\n", AVI->video_superindex->fcc[0], AVI->video_superindex->fcc[1], + AVI->video_superindex->fcc[2], AVI->video_superindex->fcc[3]); + printf("LEN \"%ld\"\n", (long)AVI->video_superindex->dwSize); + printf("wLongsPerEntry \"%d\"\n", AVI->video_superindex->wLongsPerEntry); + printf("bIndexSubType \"%d\"\n", AVI->video_superindex->bIndexSubType); + printf("bIndexType \"%d\"\n", AVI->video_superindex->bIndexType); + printf("nEntriesInUse \"%ld\"\n", (long)AVI->video_superindex->nEntriesInUse); + printf("dwChunkId \"%c%c%c%c\"\n", AVI->video_superindex->dwChunkId[0], AVI->video_superindex->dwChunkId[1], + AVI->video_superindex->dwChunkId[2], AVI->video_superindex->dwChunkId[3]); + printf("--\n"); +#endif + + AVI->is_opendml = 1; + + } + else if(lasttag == 2) // A U D I O + { + + a = hdrl_data+i; + + AVI->track[AVI->aptr].audio_superindex = (avisuperindex_chunk *) vj_malloc (sizeof (avisuperindex_chunk)); + veejay_memcpy (AVI->track[AVI->aptr].audio_superindex->fcc, a, 4); a += 4; + AVI->track[AVI->aptr].audio_superindex->dwSize = str2ulong(a); a += 4; + AVI->track[AVI->aptr].audio_superindex->wLongsPerEntry = str2ushort(a); a += 2; + AVI->track[AVI->aptr].audio_superindex->bIndexSubType = *a; a += 1; + AVI->track[AVI->aptr].audio_superindex->bIndexType = *a; a += 1; + AVI->track[AVI->aptr].audio_superindex->nEntriesInUse = str2ulong(a); a += 4; + veejay_memcpy (AVI->track[AVI->aptr].audio_superindex->dwChunkId, a, 4); a += 4; + + // 3 * reserved + a += 4; a += 4; a += 4; + + if (AVI->track[AVI->aptr].audio_superindex->bIndexSubType != 0) {fprintf(stderr, "Invalid Header, bIndexSubType != 0\n"); } + + AVI->track[AVI->aptr].audio_superindex->aIndex = + vj_malloc (AVI->track[AVI->aptr].audio_superindex->wLongsPerEntry * + AVI->track[AVI->aptr].audio_superindex->nEntriesInUse * sizeof (uint32_t)); + + // position of ix## chunks + for (j=0; jtrack[AVI->aptr].audio_superindex->nEntriesInUse; ++j) { + AVI->track[AVI->aptr].audio_superindex->aIndex[j].qwOffset = str2ullong (a); a += 8; + AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwSize = str2ulong (a); a += 4; + AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwDuration = str2ulong (a); a += 4; + +#ifdef DEBUG_ODML + printf("[%d] 0x%llx 0x%lx %lu\n", j, + (unsigned long long)AVI->track[AVI->aptr].audio_superindex->aIndex[j].qwOffset, + (unsigned long)AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwSize, + (unsigned long)AVI->track[AVI->aptr].audio_superindex->aIndex[j].dwDuration); +#endif + } + +#ifdef DEBUG_ODML + printf("FOURCC \"%.4s\"\n", AVI->track[AVI->aptr].audio_superindex->fcc); + printf("LEN \"%ld\"\n", (long)AVI->track[AVI->aptr].audio_superindex->dwSize); + printf("wLongsPerEntry \"%d\"\n", AVI->track[AVI->aptr].audio_superindex->wLongsPerEntry); + printf("bIndexSubType \"%d\"\n", AVI->track[AVI->aptr].audio_superindex->bIndexSubType); + printf("bIndexType \"%d\"\n", AVI->track[AVI->aptr].audio_superindex->bIndexType); + printf("nEntriesInUse \"%ld\"\n", (long)AVI->track[AVI->aptr].audio_superindex->nEntriesInUse); + printf("dwChunkId \"%.4s\"\n", AVI->track[AVI->aptr].audio_superindex->dwChunkId[0]); + printf("--\n"); +#endif + + } + i += 8; + } + else if((strncasecmp(hdrl_data+i,"JUNK",4) == 0) || + (strncasecmp(hdrl_data+i,"strn",4) == 0) || + (strncasecmp(hdrl_data+i,"vprp",4) == 0)){ + i += 8; + // do not reset lasttag + } else + { + i += 8; + lasttag = 0; + } + //printf("adding %ld bytes\n", (long int)n); + + i += n; + } + + free(hdrl_data); + + if(!vids_strh_seen || !vids_strf_seen) ERR_EXIT(AVI_ERR_NO_VIDS) + + AVI->video_tag[0] = AVI->video_strn/10 + '0'; + AVI->video_tag[1] = AVI->video_strn%10 + '0'; + AVI->video_tag[2] = 'd'; + AVI->video_tag[3] = 'b'; + + /* Audio tag is set to "99wb" if no audio present */ + if(!AVI->track[0].a_chans) AVI->track[0].audio_strn = 99; + + { + int i=0; + for(j=0; janum+1; ++j) { + if (j == AVI->video_strn) continue; + AVI->track[i].audio_tag[0] = j/10 + '0'; + AVI->track[i].audio_tag[1] = j%10 + '0'; + AVI->track[i].audio_tag[2] = 'w'; + AVI->track[i].audio_tag[3] = 'b'; + ++i; + } + } + + lseek(AVI->fdes,AVI->movi_start,SEEK_SET); + + /* get index if wanted */ + + if(AVI->index_file && !getIndex) { + int ret; + + ret = avi_parse_index_from_file(AVI, AVI->index_file); + + /* Reposition the file */ + + lseek(AVI->fdes,AVI->movi_start,SEEK_SET); + AVI->video_pos = 0; + return (ret); + + } + if(!getIndex) return(0); + + /* if the file has an idx1, check if this is relative + to the start of the file or to the start of the movi list */ + + idx_type = 0; + + if(AVI->idx) + { + off_t pos, len; + + /* Search the first videoframe in the idx1 and look where + it is in the file */ + + for(i=0;in_idx;i++) + if( strncasecmp((char *)AVI->idx[i],(char *)AVI->video_tag,3)==0 ) break; + if(i>=AVI->n_idx) ERR_EXIT(AVI_ERR_NO_VIDS) + + pos = str2ulong(AVI->idx[i]+ 8); + len = str2ulong(AVI->idx[i]+12); + + lseek(AVI->fdes,pos,SEEK_SET); + if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ) + if( strncasecmp(data,(char *)AVI->idx[i],4)==0 && str2ulong((unsigned char *)data+4)==len ) + { + idx_type = 1; /* Index from start of file */ + } + else + { + lseek(AVI->fdes,pos+AVI->movi_start-4,SEEK_SET); + if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ) + if( strncasecmp(data,(char *)AVI->idx[i],4)==0 && str2ulong((unsigned char *)data+4)==len ) + { + idx_type = 2; /* Index from start of movi list */ + } + } + /* idx_type remains 0 if neither of the two tests above succeeds */ + } + + + if(idx_type == 0 && !AVI->is_opendml && !AVI->total_frames) + { + /* we must search through the file to get the index */ + + lseek(AVI->fdes, AVI->movi_start, SEEK_SET); + + + AVI->n_idx = 0; + + while(1) + { + if( avi_read(AVI->fdes,data,8) != 8 ) break; + n = str2ulong((unsigned char *)data+4); + + /* The movi list may contain sub-lists, ignore them */ + + if(strncasecmp(data,"LIST",4)==0) + { + lseek(AVI->fdes,4,SEEK_CUR); + continue; + } + + /* Check if we got a tag ##db, ##dc or ##wb */ + + if( ( (data[2]=='d' || data[2]=='D') && + (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) + || ( (data[2]=='w' || data[2]=='W') && + (data[3]=='b' || data[3]=='B') ) ) + { + avi_add_index_entry(AVI,(unsigned char *)data,0,lseek(AVI->fdes,0,SEEK_CUR)-8,n); + } + + lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR); + } + idx_type = 1; + } + + // ************************ + // OPENDML + // ************************ + + // read extended index chunks + if (AVI->is_opendml) { + uint64_t offset = 0; + int hdrl_len = 4+4+2+1+1+4+4+8+4; + char *en, *chunk_start; + int k = 0, audtr = 0; + uint32_t nrEntries = 0; + + AVI->video_index = NULL; + + nvi = 0; + for(audtr=0; audtranum; ++audtr) nai[audtr] = tot[audtr] = 0; + + // ************************ + // VIDEO + // ************************ + + for (j=0; jvideo_superindex->nEntriesInUse; j++) { + + // read from file + chunk_start = en = vj_malloc (AVI->video_superindex->aIndex[j].dwSize+hdrl_len); + + if (lseek(AVI->fdes, AVI->video_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { + fprintf(stderr, "(%s) cannot seek to 0x%llx\n", __FILE__, + (unsigned long long)AVI->video_superindex->aIndex[j].qwOffset); + free(chunk_start); + continue; + } + + if (avi_read(AVI->fdes, en, AVI->video_superindex->aIndex[j].dwSize+hdrl_len) <= 0) { + fprintf(stderr, "(%s) cannot read from offset 0x%llx %ld bytes; broken (incomplete) file?\n", + __FILE__, (unsigned long long)AVI->video_superindex->aIndex[j].qwOffset, + (unsigned long)AVI->video_superindex->aIndex[j].dwSize+hdrl_len); + free(chunk_start); + continue; + } + + nrEntries = str2ulong(en + 12); +#ifdef DEBUG_ODML + //printf("[%d:0] Video nrEntries %ld\n", j, nrEntries); +#endif + offset = str2ullong(en + 20); + + // skip header + en += hdrl_len; + nvi += nrEntries; + AVI->video_index = (video_index_entry *) realloc (AVI->video_index, nvi * sizeof (video_index_entry)); + if (!AVI->video_index) { + fprintf(stderr, "AVILIB: out of mem (size = %ld)\n", nvi * sizeof (video_index_entry)); + exit(1); + } + + while (k < nvi) { + + AVI->video_index[k].pos = offset + str2ulong(en); en += 4; + AVI->video_index[k].len = str2ulong_len(en); + AVI->video_index[k].key = str2ulong_key(en); en += 4; + + // completely empty chunk + if (AVI->video_index[k].pos-offset == 0 && AVI->video_index[k].len == 0) { + k--; + nvi--; + } + +#ifdef DEBUG_ODML + /* + printf("[%d] POS 0x%llX len=%d key=%s offset (%llx) (%ld)\n", k, + AVI->video_index[k].pos, + (int)AVI->video_index[k].len, + AVI->video_index[k].key?"yes":"no ", offset, + AVI->video_superindex->aIndex[j].dwSize); + */ +#endif + + k++; + } + + free(chunk_start); + } + + AVI->video_frames = nvi; + // this should deal with broken 'rec ' odml files. + if (AVI->video_frames == 0) { + AVI->is_opendml=0; + goto multiple_riff; + } + + // ************************ + // AUDIO + // ************************ + + for(audtr=0; audtranum; ++audtr) { + + k = 0; + if (!AVI->track[audtr].audio_superindex) { + fprintf(stderr, "(%s) cannot read audio index for track %d\n", __FILE__, audtr); + continue; + } + for (j=0; jtrack[audtr].audio_superindex->nEntriesInUse; j++) { + + // read from file + chunk_start = en = vj_malloc (AVI->track[audtr].audio_superindex->aIndex[j].dwSize+hdrl_len); + + if (lseek(AVI->fdes, AVI->track[audtr].audio_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { + fprintf(stderr, "(%s) cannot seek to 0x%llx\n", __FILE__, (unsigned long long)AVI->track[audtr].audio_superindex->aIndex[j].qwOffset); + free(chunk_start); + continue; + } + + if (avi_read(AVI->fdes, en, AVI->track[audtr].audio_superindex->aIndex[j].dwSize+hdrl_len) <= 0) { + fprintf(stderr, "(%s) cannot read from offset 0x%llx; broken (incomplete) file?\n", + __FILE__,(unsigned long long) AVI->track[audtr].audio_superindex->aIndex[j].qwOffset); + free(chunk_start); + continue; + } + + nrEntries = str2ulong(en + 12); + //if (nrEntries > 50) nrEntries = 2; // XXX +#ifdef DEBUG_ODML + //printf("[%d:%d] Audio nrEntries %ld\n", j, audtr, nrEntries); +#endif + offset = str2ullong(en + 20); + + // skip header + en += hdrl_len; + nai[audtr] += nrEntries; + AVI->track[audtr].audio_index = (audio_index_entry *) realloc (AVI->track[audtr].audio_index, nai[audtr] * sizeof (audio_index_entry)); + + while (k < nai[audtr]) { + + AVI->track[audtr].audio_index[k].pos = offset + str2ulong(en); en += 4; + AVI->track[audtr].audio_index[k].len = str2ulong_len(en); en += 4; + AVI->track[audtr].audio_index[k].tot = tot[audtr]; + tot[audtr] += AVI->track[audtr].audio_index[k].len; + +#ifdef DEBUG_ODML + /* + printf("[%d:%d] POS 0x%llX len=%d offset (%llx) (%ld)\n", k, audtr, + AVI->track[audtr].audio_index[k].pos, + (int)AVI->track[audtr].audio_index[k].len, + offset, AVI->track[audtr].audio_superindex->aIndex[j].dwSize); + */ +#endif + + ++k; + } + + free(chunk_start); + } + + AVI->track[audtr].audio_chunks = nai[audtr]; + AVI->track[audtr].audio_bytes = tot[audtr]; + } + } // is opendml + + else if (AVI->total_frames && !AVI->is_opendml && idx_type==0) { + + // ********************* + // MULTIPLE RIFF CHUNKS (and no index) + // ********************* + + long aud_chunks = 0; +multiple_riff: + + lseek(AVI->fdes, AVI->movi_start, SEEK_SET); + + AVI->n_idx = 0; + + fprintf(stderr, "[avilib] Reconstructing index..."); + + // Number of frames; only one audio track supported + nvi = AVI->video_frames = AVI->total_frames; + nai[0] = AVI->track[0].audio_chunks = AVI->total_frames; + for(j=1; janum; ++j) AVI->track[j].audio_chunks = 0; + + AVI->video_index = (video_index_entry *) vj_malloc(nvi*sizeof(video_index_entry)); + + if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + + for(j=0; janum; ++j) { + if(AVI->track[j].audio_chunks) { + AVI->track[j].audio_index = (audio_index_entry *) vj_malloc((nai[j]+1)*sizeof(audio_index_entry)); + veejay_memset(AVI->track[j].audio_index, 0, (nai[j]+1)*(sizeof(audio_index_entry))); + if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + } + } + + nvi = 0; + for(j=0; janum; ++j) nai[j] = tot[j] = 0; + + aud_chunks = AVI->total_frames; + + while(1) + { + if (nvi >= AVI->total_frames) break; + + if( avi_read(AVI->fdes,data,8) != 8 ) break; + n = str2ulong((unsigned char *)data+4); + + + j=0; + + if (aud_chunks - nai[j] -1 <= 0) { + aud_chunks += AVI->total_frames; + AVI->track[j].audio_index = (audio_index_entry *) + realloc( AVI->track[j].audio_index, (aud_chunks+1)*sizeof(audio_index_entry)); + if (!AVI->track[j].audio_index) { + fprintf(stderr, "Internal error in avilib -- no mem\n"); + AVI_errno = AVI_ERR_NO_MEM; + return -1; + } + } + + /* Check if we got a tag ##db, ##dc or ##wb */ + + // VIDEO + if( + (data[0]=='0' || data[1]=='0') && + (data[2]=='d' || data[2]=='D') && + (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') ) { + + AVI->video_index[nvi].key = 0x0; + AVI->video_index[nvi].pos = lseek(AVI->fdes,0,SEEK_CUR); + AVI->video_index[nvi].len = n; + + /* + fprintf(stderr, "Frame %ld pos %lld len %lld key %ld\n", + nvi, AVI->video_index[nvi].pos, AVI->video_index[nvi].len, (long)AVI->video_index[nvi].key); + */ + nvi++; + lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR); + } + + //AUDIO + else if( + (data[0]=='0' || data[1]=='1') && + (data[2]=='w' || data[2]=='W') && + (data[3]=='b' || data[3]=='B') ) { + + + AVI->track[j].audio_index[nai[j]].pos = lseek(AVI->fdes,0,SEEK_CUR); + AVI->track[j].audio_index[nai[j]].len = n; + AVI->track[j].audio_index[nai[j]].tot = tot[j]; + tot[j] += AVI->track[j].audio_index[nai[j]].len; + nai[j]++; + + lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR); + } + else { + lseek(AVI->fdes,-4,SEEK_CUR); + } + + } + if (nvi < AVI->total_frames) { + fprintf(stderr, "\n[avilib] Uh? Some frames seems missing (%ld/%d)\n", + nvi, AVI->total_frames); + } + + + AVI->video_frames = nvi; + AVI->track[0].audio_chunks = nai[0]; + + for(j=0; janum; ++j) AVI->track[j].audio_bytes = tot[j]; + idx_type = 1; + fprintf(stderr, "done. nvi=%ld nai=%ld tot=%ld\n", nvi, nai[0], tot[0]); + + } // total_frames but no indx chunk (xawtv does this) + + else + + { + // ****************** + // NO OPENDML + // ****************** + + /* Now generate the video index and audio index arrays */ + + nvi = 0; + for(j=0; janum; ++j) nai[j] = 0; + + for(i=0;in_idx;i++) { + + if(strncasecmp((char *)AVI->idx[i],AVI->video_tag,3) == 0) nvi++; + + for(j=0; janum; ++j) if(strncasecmp((char *)AVI->idx[i], AVI->track[j].audio_tag,4) == 0) nai[j]++; + } + + AVI->video_frames = nvi; + for(j=0; janum; ++j) AVI->track[j].audio_chunks = nai[j]; + + + if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS); + AVI->video_index = (video_index_entry *) vj_malloc(nvi*sizeof(video_index_entry)); + if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + + for(j=0; janum; ++j) { + if(AVI->track[j].audio_chunks) { + AVI->track[j].audio_index = (audio_index_entry *) vj_malloc((nai[j]+1)*sizeof(audio_index_entry)); + veejay_memset(AVI->track[j].audio_index, 0, (nai[j]+1)*(sizeof(audio_index_entry))); + if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM); + } + } + + nvi = 0; + for(j=0; janum; ++j) nai[j] = tot[j] = 0; + + ioff = idx_type == 1 ? 8 : AVI->movi_start+4; + + for(i=0;in_idx;i++) { + + //video + if(strncasecmp((char *)AVI->idx[i],AVI->video_tag,3) == 0) { + AVI->video_index[nvi].key = str2ulong(AVI->idx[i]+ 4); + AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff; + AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12); + nvi++; + } + + //audio + for(j=0; janum; ++j) { + + if(strncasecmp((char *)AVI->idx[i],AVI->track[j].audio_tag,4) == 0) { + AVI->track[j].audio_index[nai[j]].pos = str2ulong(AVI->idx[i]+ 8)+ioff; + AVI->track[j].audio_index[nai[j]].len = str2ulong(AVI->idx[i]+12); + AVI->track[j].audio_index[nai[j]].tot = tot[j]; + tot[j] += AVI->track[j].audio_index[nai[j]].len; + nai[j]++; + } + } + } + + + for(j=0; janum; ++j) AVI->track[j].audio_bytes = tot[j]; + + } // is no opendml + + /* Reposition the file */ + + lseek(AVI->fdes,AVI->movi_start,SEEK_SET); + AVI->video_pos = 0; + + AVI->ffmpeg_codec_id = + vj_el_get_decoder_from_fourcc( AVI->compressor ); + + return(0); +} + +long AVI_video_frames(avi_t *AVI) +{ + return AVI->video_frames; +} +int AVI_video_width(avi_t *AVI) +{ + return AVI->width; +} +int AVI_video_height(avi_t *AVI) +{ + return AVI->height; +} +double AVI_frame_rate(avi_t *AVI) +{ + return AVI->fps; +} +char* AVI_video_compressor(avi_t *AVI) +{ + return AVI->compressor2; +} + +long AVI_max_video_chunk(avi_t *AVI) +{ + return AVI->max_len; +} + +int AVI_audio_tracks(avi_t *AVI) +{ + return(AVI->anum); +} + +int AVI_audio_channels(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_chans; +} + +long AVI_audio_mp3rate(avi_t *AVI) +{ + return AVI->track[AVI->aptr].mp3rate; +} + +long AVI_audio_padrate(avi_t *AVI) +{ + return AVI->track[AVI->aptr].padrate; +} + +int AVI_audio_bits(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_bits; +} + +int AVI_audio_format(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_fmt; +} + +long AVI_audio_rate(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_rate; +} + +long AVI_audio_bytes(avi_t *AVI) +{ + return AVI->track[AVI->aptr].audio_bytes; +} + +long AVI_audio_chunks(avi_t *AVI) +{ + return AVI->track[AVI->aptr].audio_chunks; +} + +long AVI_audio_codech_offset(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_codech_off; +} + +long AVI_audio_codecf_offset(avi_t *AVI) +{ + return AVI->track[AVI->aptr].a_codecf_off; +} + +long AVI_video_codech_offset(avi_t *AVI) +{ + return AVI->v_codech_off; +} + +long AVI_video_codecf_offset(avi_t *AVI) +{ + return AVI->v_codecf_off; +} + +long AVI_frame_size(avi_t *AVI, long frame) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(frame < 0 || frame >= AVI->video_frames) return 0; + return(AVI->video_index[frame].len); +} + +long AVI_audio_size(avi_t *AVI, long frame) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(frame < 0 || frame >= AVI->track[AVI->aptr].audio_chunks) return -1; + return(AVI->track[AVI->aptr].audio_index[frame].len); +} + +long AVI_get_video_position(avi_t *AVI, long frame) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(frame < 0 || frame >= AVI->video_frames) return 0; + return(AVI->video_index[frame].pos); +} + + +int AVI_seek_start(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + lseek(AVI->fdes,AVI->movi_start,SEEK_SET); + AVI->video_pos = 0; + return 0; +} + +int AVI_set_video_position(avi_t *AVI, long frame) +{ +#ifdef STRICT_CHECKING + assert( AVI->mode != AVI_MODE_WRITE ); + assert( AVI->video_index ); + assert( frame >= 0 && frame < AVI->video_frames); +#endif +// if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } +// if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } +// if (frame < 0 ) frame = 0; + AVI->video_pos = frame; + return 0; +} + +int AVI_set_audio_bitrate(avi_t *AVI, long bitrate) +{ + if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + + AVI->track[AVI->aptr].mp3rate = bitrate; + return 0; +} + + +long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe) +{ + long n; +#ifdef STRICT_CHECKING + assert( AVI->mode != AVI_MODE_WRITE ); + assert( AVI->video_index ); + assert( AVI->video_pos >= 0 && AVI->video_pos < AVI->video_frames ); +#endif +// if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } +// if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } +// if(AVI->video_pos < 0 || AVI->video_pos >= AVI->video_frames) return -1; + n = AVI->video_index[AVI->video_pos].len; + + *keyframe = (AVI->video_index[AVI->video_pos].key==0x10) ? 1:0; + + if (vidbuf == NULL) { + AVI->video_pos++; + return n; + } + + if( AVI->mmap_region == NULL ) + { + lseek(AVI->fdes, AVI->video_index[AVI->video_pos].pos, SEEK_SET); + if (avi_read(AVI->fdes,vidbuf,n) != n) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + } + else + { + n = mmap_read( AVI->mmap_region, AVI->video_index[ AVI->video_pos].pos, + n, vidbuf ); + } + + + AVI->video_pos++; + + return n; +} + +long AVI_get_audio_position_index(avi_t *AVI) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + return (AVI->track[AVI->aptr].audio_posc); +} + +int AVI_set_audio_position_index(avi_t *AVI, long indexpos) +{ + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + if(indexpos > AVI->track[AVI->aptr].audio_chunks) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + AVI->track[AVI->aptr].audio_posc = indexpos; + AVI->track[AVI->aptr].audio_posb = 0; + + return 0; +} + + +int AVI_set_audio_position(avi_t *AVI, long byte) +{ + long n0, n1, n; + + if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } + if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + + if(byte < 0) byte = 0; + + /* Binary search in the audio chunks */ + + n0 = 0; + n1 = AVI->track[AVI->aptr].audio_chunks; + + while(n0track[AVI->aptr].audio_index[n].tot>byte) + n1 = n; + else + n0 = n; + } + + AVI->track[AVI->aptr].audio_posc = n0; + AVI->track[AVI->aptr].audio_posb = byte - AVI->track[AVI->aptr].audio_index[n0].tot; + + return 0; +} + +long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes) +{ + long nr, left, todo; + off_t pos; + +// if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } +// if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } +#ifdef STRICT_CHECKING + assert( AVI->mode != AVI_MODE_WRITE ); + assert( AVI->track[AVI->aptr].audio_index ); +#endif + nr = 0; /* total number of bytes read */ + + if (bytes==0) { + AVI->track[AVI->aptr].audio_posc++; + AVI->track[AVI->aptr].audio_posb = 0; + lseek(AVI->fdes, 0LL, SEEK_CUR); + } + while(bytes>0) + { + off_t ret; + left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb; + if(left==0) + { + if(AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) return nr; + AVI->track[AVI->aptr].audio_posc++; + AVI->track[AVI->aptr].audio_posb = 0; + continue; + } + if(bytestrack[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb; + if( pos < 0 ) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + if(lseek(AVI->fdes, pos, SEEK_SET) == -1) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + if ( (ret = avi_read(AVI->fdes,audbuf+nr,todo)) != todo) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + bytes -= todo; + nr += todo; + AVI->track[AVI->aptr].audio_posb += todo; + } + + return nr; +} + +long AVI_read_audio_chunk(avi_t *AVI, char *audbuf) +{ + long left; + off_t pos; + +// if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; } +// if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; } + +// if (AVI->track[AVI->aptr].audio_posc+1>AVI->track[AVI->aptr].audio_chunks) return -1; + +#ifdef STRICT_CHECKING + assert( AVI->mode != AVI_MODE_WRITE ); + assert( AVI->track[AVI->aptr].audio_index ); + assert( AVI->track[AVI->aptr].audio_posc+1 <= AVI->track[AVI->aptr].audio_chunks ); +#endif + + left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb; + + if (audbuf == NULL) return left; + + if(left==0) { + AVI->track[AVI->aptr].audio_posc++; + AVI->track[AVI->aptr].audio_posb = 0; + return 0; + } + + pos = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb; + lseek(AVI->fdes, pos, SEEK_SET); + if (avi_read(AVI->fdes,audbuf,left) != left) + { + AVI_errno = AVI_ERR_READ; + return -1; + } + AVI->track[AVI->aptr].audio_posc++; + AVI->track[AVI->aptr].audio_posb = 0; + + return left; +} + +/* AVI_read_data: Special routine for reading the next audio or video chunk + without having an index of the file. */ + +int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf, + char *audbuf, long max_audbuf, + long *len) +{ + +/* + * Return codes: + * + * 1 = video data read + * 2 = audio data read + * 0 = reached EOF + * -1 = video buffer too small + * -2 = audio buffer too small + */ + + off_t n; + char data[8]; + +// if(AVI->mode==AVI_MODE_WRITE) return 0; +#ifdef STRICT_CHECKING + assert( AVI->mode != AVI_MODE_WRITE ); +#endif + while(1) + { + /* Read tag and length */ + + if( avi_read(AVI->fdes,data,8) != 8 ) return 0; + + /* if we got a list tag, ignore it */ + + if(strncasecmp(data,"LIST",4) == 0) + { + lseek(AVI->fdes,4,SEEK_CUR); + continue; + } + + n = PAD_EVEN(str2ulong((unsigned char *)data+4)); + + if(strncasecmp(data,AVI->video_tag,3) == 0) + { + *len = n; + AVI->video_pos++; + if(n>max_vidbuf) + { + lseek(AVI->fdes,n,SEEK_CUR); + return -1; + } + if(avi_read(AVI->fdes,vidbuf,n) != n ) return 0; + return 1; + } + else if(strncasecmp(data,AVI->track[AVI->aptr].audio_tag,4) == 0) + { + *len = n; + if(n>max_audbuf) + { + lseek(AVI->fdes,n,SEEK_CUR); + return -2; + } + if(avi_read(AVI->fdes,audbuf,n) != n ) return 0; + return 2; + break; + } + else + if(lseek(AVI->fdes,n,SEEK_CUR)<0) return 0; + } +} + +/* AVI_print_error: Print most recent error (similar to perror) */ + +char *(avi_errors[]) = +{ + /* 0 */ "avilib - No Error", + /* 1 */ "avilib - AVI file size limit reached", + /* 2 */ "avilib - Error opening AVI file", + /* 3 */ "avilib - Error reading from AVI file", + /* 4 */ "avilib - Error writing to AVI file", + /* 5 */ "avilib - Error writing index (file may still be useable)", + /* 6 */ "avilib - Error closing AVI file", + /* 7 */ "avilib - Operation (read/write) not permitted", + /* 8 */ "avilib - Out of memory (vj_malloc failed)", + /* 9 */ "avilib - Not an AVI file", + /* 10 */ "avilib - AVI file has no header list (corrupted?)", + /* 11 */ "avilib - AVI file has no MOVI list (corrupted?)", + /* 12 */ "avilib - AVI file has no video data", + /* 13 */ "avilib - operation needs an index", + /* 14 */ "avilib - Unkown Error" +}; +static int num_avi_errors = sizeof(avi_errors)/sizeof(char*); + +static char error_string[4096]; + +void AVI_print_error(char *str) +{ + int aerrno; + + aerrno = (AVI_errno>=0 && AVI_errno=0 && AVI_errnoriff.id ,buf+0, 4); + veejay_memcpy(&wave->riff.len ,buf+4, 4); + veejay_memcpy(&wave->riff.wave_id ,buf+8, 4); + + veejay_memcpy(&wave->format.id ,buf+12, 4); + veejay_memcpy(&wave->format.len ,buf+16, 4); + + veejay_memcpy(&wave->common.wFormatTag ,buf+20, 2); + veejay_memcpy(&wave->common.wChannels ,buf+22, 2); + veejay_memcpy(&wave->common.dwSamplesPerSec ,buf+24, 4); + veejay_memcpy(&wave->common.dwAvgBytesPerSec ,buf+28, 4); + veejay_memcpy(&wave->common.wBlockAlign ,buf+32, 2); + veejay_memcpy(&wave->common.wBitsPerSample ,buf+34, 2); + + veejay_memcpy(&wave->data.id ,buf+36, 4); + veejay_memcpy(&wave->data.len ,buf+40, 4); + + + /* + fprintf(stderr, "RIFF: %c%c%c%c| (%d) (%d)\n", + wave->riff.id[0], wave->riff.id[1], wave->riff.id[2], wave->riff.id[3], + sizeof (*wave), sizeof (struct wave_header)); + fprintf(stderr, "WAVE: %c%c%c%c|\n", + wave->riff.wave_id[0], wave->riff.wave_id[1], wave->riff.wave_id[2], wave->riff.wave_id[3]); + fprintf(stderr, "fmt : %c%c%c%c|\n", + wave->format.id[0], wave->format.id[1], wave->format.id[2], wave->format.id[3]); + fprintf(stderr, "data: %c%c%c%c|\n", + wave->data.id[0], wave->data.id[1], wave->data.id[2], wave->data.id[3]); + */ + + if( strncasecmp(wave->riff.id , "RIFF",4) != 0 || + strncasecmp(wave->riff.wave_id, "WAVE",4) != 0 || + strncasecmp(wave->format.id , "fmt ",4) != 0 ) + { + AVI_errno = AVI_ERR_NO_AVI; + return -1; + } + +#ifdef WORDS_BIGENDIAN +#define x_FIXUP(field) \ + ((field) = (sizeof(field) == 4 ? str2ulong((unsigned char*)&(field)) \ + : str2ushort((unsigned char*)&(field)))) + + x_FIXUP(wave->riff.len); + x_FIXUP(wave->format.len); + x_FIXUP(wave->common.wFormatTag); + x_FIXUP(wave->common.wChannels); + x_FIXUP(wave->common.dwSamplesPerSec); + x_FIXUP(wave->common.dwAvgBytesPerSec); + x_FIXUP(wave->common.wBlockAlign); + x_FIXUP(wave->common.wBitsPerSample); + x_FIXUP(wave->data.len); + +#undef x_FIXUP +#endif + + return 0; +} + +int AVI_write_wave_header( int fd, const struct wave_header * wave ) +{ + char buf[44]; + struct wave_header buffer = *wave; + + + +#ifdef WORDS_BIGENDIAN +#define x_FIXUP(field) \ + ((sizeof(field) == 4 ? long2str((unsigned char*)&(field),(field)) \ + : short2str((unsigned char*)&(field),(field)))) + + x_FIXUP(buffer.riff.len); + x_FIXUP(buffer.format.len); + x_FIXUP(buffer.common.wFormatTag); + x_FIXUP(buffer.common.wChannels); + x_FIXUP(buffer.common.dwSamplesPerSec); + x_FIXUP(buffer.common.dwAvgBytesPerSec); + x_FIXUP(buffer.common.wBlockAlign); + x_FIXUP(buffer.common.wBitsPerSample); + x_FIXUP(buffer.data.len); + +#undef x_FIXUP +#endif + + veejay_memcpy(buf+ 0, &buffer.riff.id, 4); + veejay_memcpy(buf+ 4, &buffer.riff.len, 4); + veejay_memcpy(buf+ 8, &buffer.riff.wave_id, 4); + + veejay_memcpy(buf+12, &buffer.format.id, 4); + veejay_memcpy(buf+16, &buffer.format.len, 4); + + veejay_memcpy(buf+20, &buffer.common.wFormatTag, 2); + veejay_memcpy(buf+22, &buffer.common.wChannels, 2); + veejay_memcpy(buf+24, &buffer.common.dwSamplesPerSec, 4); + veejay_memcpy(buf+28, &buffer.common.dwAvgBytesPerSec, 4); + veejay_memcpy(buf+32, &buffer.common.wBlockAlign, 2); + veejay_memcpy(buf+34, &buffer.common.wBitsPerSample, 2); + + veejay_memcpy(buf+36, &buffer.data.id, 4); + veejay_memcpy(buf+40, &buffer.data.len, 4); + + + // write raw data + if( avi_write (fd, buf, sizeof(buf)) != sizeof(buf) ) + { + AVI_errno = AVI_ERR_WRITE; + return -1; + } + + return 0; +} + +size_t AVI_read_wave_pcm_data( int fd, void * buffer, size_t buflen ) +{ + int doneread = avi_read(fd, buffer, buflen); + +#ifdef WORDS_BIGENDIAN + { + char * bufptr = buffer; + size_t i; + char tmp; + + for( i=0; i0 ) + { + buflen = datalen; + if( buflen > sizeof(buffer) ) + { + buflen = sizeof(buffer); + } + + for( i=0; ifdes; +} + +int AVI_video_compressor_type(avi_t *AVI) +{ + return AVI->ffmpeg_codec_id; +} diff --git a/branches/V-1.5.3/veejay-server/libel/avilib.h b/branches/V-1.5.3/veejay-server/libel/avilib.h new file mode 100644 index 00000000..ec53cc4b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/avilib.h @@ -0,0 +1,464 @@ +/* + * avilib.h + * + * Copyright (C) Thomas Östreich - June 2001 + * multiple audio track support Copyright (C) 2002 Thomas Östreich + * + * Original code: + * Copyright (C) 1999 Rainer Johanni + * + * This file is part of transcode, a video stream processing tool + * + * transcode 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, or (at your option) + * any later version. + * + * transcode 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#ifndef AVILIB_H +#define AVILIB_H + +#define AVI_MAX_TRACKS 8 + +typedef struct +{ + off_t key; + off_t pos; + off_t len; +} video_index_entry; + +typedef struct +{ + off_t pos; + off_t len; + off_t tot; +} audio_index_entry; + + +// Index types + + +#define AVI_INDEX_OF_INDEXES 0x00 // when each entry in aIndex + // array points to an index chunk +#define AVI_INDEX_OF_CHUNKS 0x01 // when each entry in aIndex + // array points to a chunk in the file +#define AVI_INDEX_IS_DATA 0x80 // when each entry is aIndex is + // really the data +// bIndexSubtype codes for INDEX_OF_CHUNKS +// +#define AVI_INDEX_2FIELD 0x01 // when fields within frames + // are also indexed + + + +typedef struct _avisuperindex_entry { + uint64_t qwOffset; // absolute file offset + uint32_t dwSize; // size of index chunk at this offset + uint32_t dwDuration; // time span in stream ticks +} avisuperindex_entry; + +typedef struct _avistdindex_entry { + uint32_t dwOffset; // qwBaseOffset + this is absolute file offset + uint32_t dwSize; // bit 31 is set if this is NOT a keyframe +} avistdindex_entry; + +// Standard index +typedef struct _avistdindex_chunk { + char fcc[4]; // ix## + uint32_t dwSize; // size of this chunk + uint16_t wLongsPerEntry; // must be sizeof(aIndex[0])/sizeof(DWORD) + uint8_t bIndexSubType; // must be 0 + uint8_t bIndexType; // must be AVI_INDEX_OF_CHUNKS + uint32_t nEntriesInUse; // + char dwChunkId[4]; // '##dc' or '##db' or '##wb' etc.. + uint64_t qwBaseOffset; // all dwOffsets in aIndex array are relative to this + uint32_t dwReserved3; // must be 0 + avistdindex_entry *aIndex; +} avistdindex_chunk; + + +// Base Index Form 'indx' +typedef struct _avisuperindex_chunk { + char fcc[4]; + uint32_t dwSize; // size of this chunk + uint16_t wLongsPerEntry; // size of each entry in aIndex array (must be 8 for us) + uint8_t bIndexSubType; // future use. must be 0 + uint8_t bIndexType; // one of AVI_INDEX_* codes + uint32_t nEntriesInUse; // index of first unused member in aIndex array + char dwChunkId[4]; // fcc of what is indexed + uint32_t dwReserved[3]; // meaning differs for each index type/subtype. + // 0 if unused + avisuperindex_entry *aIndex; // where are the ix## chunks + avistdindex_chunk **stdindex; // the ix## chunks itself (array) +} avisuperindex_chunk; + + + +typedef struct track_s +{ + + long a_fmt; /* Audio format, see #defines below */ + long a_chans; /* Audio channels, 0 for no audio */ + long a_rate; /* Rate in Hz */ + long a_bits; /* bits per audio sample */ + long mp3rate; /* mp3 bitrate kbs*/ + long a_vbr; /* 0 == no Variable BitRate */ + long padrate; /* byte rate used for zero padding */ + + long audio_strn; /* Audio stream number */ + off_t audio_bytes; /* Total number of bytes of audio data */ + long audio_chunks; /* Chunks of audio data in the file */ + + char audio_tag[4]; /* Tag of audio data */ + long audio_posc; /* Audio position: chunk */ + long audio_posb; /* Audio position: byte within chunk */ + + off_t a_codech_off; /* absolut offset of audio codec information */ + off_t a_codecf_off; /* absolut offset of audio codec information */ + + audio_index_entry *audio_index; + avisuperindex_chunk *audio_superindex; + +} track_t; + +typedef struct +{ + uint32_t bi_size; + uint32_t bi_width; + uint32_t bi_height; + uint16_t bi_planes; + uint16_t bi_bit_count; + uint32_t bi_compression; + uint32_t bi_size_image; + uint32_t bi_x_pels_per_meter; + uint32_t bi_y_pels_per_meter; + uint32_t bi_clr_used; + uint32_t bi_clr_important; +} alBITMAPINFOHEADER; + +typedef struct __attribute__((__packed__)) +{ + uint16_t w_format_tag; + uint16_t n_channels; + uint32_t n_samples_per_sec; + uint32_t n_avg_bytes_per_sec; + uint16_t n_block_align; + uint16_t w_bits_per_sample; + uint16_t cb_size; +} alWAVEFORMATEX; + +typedef struct __attribute__((__packed__)) +{ + uint32_t fcc_type; + uint32_t fcc_handler; + uint32_t dw_flags; + uint32_t dw_caps; + uint16_t w_priority; + uint16_t w_language; + uint32_t dw_scale; + uint32_t dw_rate; + uint32_t dw_start; + uint32_t dw_length; + uint32_t dw_initial_frames; + uint32_t dw_suggested_buffer_size; + uint32_t dw_quality; + uint32_t dw_sample_size; + uint32_t dw_left; + uint32_t dw_top; + uint32_t dw_right; + uint32_t dw_bottom; + uint32_t dw_edit_count; + uint32_t dw_format_change_count; + char sz_name[64]; +} alAVISTREAMINFO; + +typedef struct +{ + + long fdes; /* File descriptor of AVI file */ + long mode; /* 0 for reading, 1 for writing */ + + long width; /* Width of a video frame */ + long height; /* Height of a video frame */ + double fps; /* Frames per second */ + char compressor[8]; /* Type of compressor, 4 bytes + padding for 0 byte */ + char compressor2[8]; /* Type of compressor, 4 bytes + padding for 0 byte */ + long video_strn; /* Video stream number */ + long video_frames; /* Number of video frames */ + char video_tag[4]; /* Tag of video data */ + long video_pos; /* Number of next frame to be read + (if index present) */ + + uint32_t max_len; /* maximum video chunk present */ + + track_t track[AVI_MAX_TRACKS]; // up to AVI_MAX_TRACKS audio tracks supported + + off_t pos; /* position in file */ + long n_idx; /* number of index entries actually filled */ + long max_idx; /* number of index entries actually allocated */ + + off_t v_codech_off; /* absolut offset of video codec (strh) info */ + off_t v_codecf_off; /* absolut offset of video codec (strf) info */ + + uint8_t (*idx)[16]; /* index entries (AVI idx1 tag) */ + + video_index_entry *video_index; + avisuperindex_chunk *video_superindex; /* index of indices */ + int is_opendml; /* set to 1 if this is an odml file with multiple index chunks */ + + off_t last_pos; /* Position of last frame written */ + uint32_t last_len; /* Length of last frame written */ + int must_use_index; /* Flag if frames are duplicated */ + off_t movi_start; + int total_frames; /* total number of frames if dmlh is present */ + + int anum; // total number of audio tracks + int aptr; // current audio working track + int comment_fd; // Read avi header comments from this fd + char *index_file; // read the avi index from this file + + alBITMAPINFOHEADER *bitmap_info_header; + alWAVEFORMATEX *wave_format_ex[AVI_MAX_TRACKS]; + + void* extradata; + unsigned long extradata_size; + + mmap_region_t *mmap_region; + off_t mmap_offset; + size_t mmap_size; + int ffmpeg_codec_id; +} avi_t; + +#define AVI_MODE_WRITE 0 +#define AVI_MODE_READ 1 + +/* The error codes delivered by avi_open_input_file */ + +#define AVI_ERR_SIZELIM 1 /* The write of the data would exceed + the maximum size of the AVI file. + This is more a warning than an error + since the file may be closed safely */ + +#define AVI_ERR_OPEN 2 /* Error opening the AVI file - wrong path + name or file nor readable/writable */ + +#define AVI_ERR_READ 3 /* Error reading from AVI File */ + +#define AVI_ERR_WRITE 4 /* Error writing to AVI File, + disk full ??? */ + +#define AVI_ERR_WRITE_INDEX 5 /* Could not write index to AVI file + during close, file may still be + usable */ + +#define AVI_ERR_CLOSE 6 /* Could not write header to AVI file + or not truncate the file during close, + file is most probably corrupted */ + +#define AVI_ERR_NOT_PERM 7 /* Operation not permitted: + trying to read from a file open + for writing or vice versa */ + +#define AVI_ERR_NO_MEM 8 /* malloc failed */ + +#define AVI_ERR_NO_AVI 9 /* Not an AVI file */ + +#define AVI_ERR_NO_HDRL 10 /* AVI file has no has no header list, + corrupted ??? */ + +#define AVI_ERR_NO_MOVI 11 /* AVI file has no has no MOVI list, + corrupted ??? */ + +#define AVI_ERR_NO_VIDS 12 /* AVI file contains no video data */ + +#define AVI_ERR_NO_IDX 13 /* The file has been opened with + getIndex==0, but an operation has been + performed that needs an index */ + +#define AVI_ERR_EMPTY 14 /* AVI file is empty (header only)*/ + +/* Possible Audio formats */ + +#ifndef WAVE_FORMAT_PCM +#define WAVE_FORMAT_UNKNOWN (0x0000) +#define WAVE_FORMAT_PCM (0x0001) +#define WAVE_FORMAT_ADPCM (0x0002) +#define WAVE_FORMAT_IBM_CVSD (0x0005) +#define WAVE_FORMAT_ALAW (0x0006) +#define WAVE_FORMAT_MULAW (0x0007) +#define WAVE_FORMAT_OKI_ADPCM (0x0010) +#define WAVE_FORMAT_DVI_ADPCM (0x0011) +#define WAVE_FORMAT_DIGISTD (0x0015) +#define WAVE_FORMAT_DIGIFIX (0x0016) +#define WAVE_FORMAT_YAMAHA_ADPCM (0x0020) +#define WAVE_FORMAT_DSP_TRUESPEECH (0x0022) +#define WAVE_FORMAT_GSM610 (0x0031) +#define IBM_FORMAT_MULAW (0x0101) +#define IBM_FORMAT_ALAW (0x0102) +#define IBM_FORMAT_ADPCM (0x0103) +#endif + +avi_t* AVI_open_output_file(char * filename); +void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor); +int AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format); +int AVI_write_frame(avi_t *AVI, char *data, long bytes); +int AVI_dup_frame(avi_t *AVI); +int AVI_write_audio(avi_t *AVI, char *data, long bytes); +int AVI_append_audio(avi_t *AVI, char *data, long bytes); +long AVI_bytes_remain(avi_t *AVI); +int AVI_close(avi_t *AVI); +long AVI_bytes_written(avi_t *AVI); + +avi_t *AVI_open_input_file(char *filename, int getIndex, int mmap_size); +avi_t *AVI_open_input_indexfile(char *filename, int getIndex, char *indexfile); +avi_t *AVI_open_fd(int fd, int getIndex, int mmap_size); +avi_t *AVI_open_indexfd(int fd, int getIndex, char *indexfile); +int avi_parse_input_file(avi_t *AVI, int getIndex); +int avi_parse_index_from_file(avi_t *AVI, char *filename); +long AVI_audio_mp3rate(avi_t *AVI); +long AVI_audio_padrate(avi_t *AVI); +long AVI_video_frames(avi_t *AVI); +int AVI_video_width(avi_t *AVI); +int AVI_video_height(avi_t *AVI); +double AVI_frame_rate(avi_t *AVI); +char* AVI_video_compressor(avi_t *AVI); + +int AVI_audio_channels(avi_t *AVI); +int AVI_audio_bits(avi_t *AVI); +int AVI_audio_format(avi_t *AVI); +long AVI_audio_rate(avi_t *AVI); +long AVI_audio_bytes(avi_t *AVI); +long AVI_audio_chunks(avi_t *AVI); +int AVI_can_read_audio(avi_t *AVI); + +long AVI_max_video_chunk(avi_t *AVI); + +long AVI_frame_size(avi_t *AVI, long frame); +long AVI_audio_size(avi_t *AVI, long frame); +int AVI_seek_start(avi_t *AVI); +int AVI_set_video_position(avi_t *AVI, long frame); +long AVI_get_video_position(avi_t *AVI, long frame); +long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe); + +int AVI_set_audio_position(avi_t *AVI, long byte); +int AVI_set_audio_bitrate(avi_t *AVI, long bitrate); + +long AVI_get_audio_position_index(avi_t *AVI); +int AVI_set_audio_position_index(avi_t *AVI, long indexpos); + +long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes); +long AVI_read_audio_chunk(avi_t *AVI, char *audbuf); + +long AVI_audio_codech_offset(avi_t *AVI); +long AVI_audio_codecf_offset(avi_t *AVI); +long AVI_video_codech_offset(avi_t *AVI); +long AVI_video_codecf_offset(avi_t *AVI); + +int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf, + char *audbuf, long max_audbuf, + long *len); + +void AVI_print_error(char *str); +char *AVI_strerror(void); +char *AVI_syserror(void); + +int AVI_scan(char *name); +int AVI_dump(char *name, int mode); + +char *AVI_codec2str(short cc); +int AVI_file_check(char *import_file); + +void AVI_info(avi_t *avifile); +uint64_t AVI_max_size(void); +int avi_update_header(avi_t *AVI); + +int AVI_set_audio_track(avi_t *AVI, int track); +int AVI_get_audio_track(avi_t *AVI); +int AVI_audio_tracks(avi_t *AVI); + +void AVI_set_audio_vbr(avi_t *AVI, long is_vbr); +long AVI_get_audio_vbr(avi_t *AVI); + +void AVI_set_comment_fd(avi_t *AVI, int fd); +int AVI_get_comment_fd(avi_t *AVI); + +struct riff_struct +{ + uint8_t id[4]; /* RIFF */ + uint32_t len; + uint8_t wave_id[4]; /* WAVE */ +}; + + +struct chunk_struct +{ + uint8_t id[4]; + uint32_t len; +}; + +struct common_struct +{ + uint16_t wFormatTag; + uint16_t wChannels; + uint32_t dwSamplesPerSec; + uint32_t dwAvgBytesPerSec; + uint16_t wBlockAlign; + uint16_t wBitsPerSample; /* Only for PCM */ +}; + +struct wave_header +{ + struct riff_struct riff; + struct chunk_struct format; + struct common_struct common; + struct chunk_struct data; +}; + +// Simple WAV IO +int AVI_read_wave_header( int fd, struct wave_header * wave ); +int AVI_write_wave_header( int fd, const struct wave_header * wave ); +size_t AVI_read_wave_pcm_data( int fd, void * buffer, size_t buflen ); +size_t AVI_write_wave_pcm_data( int fd, const void * buffer, size_t buflen ); +int AVI_video_compressor_type(avi_t *AVI); +int AVI_fileno(avi_t *AVI); + +struct AVIStreamHeader { + long fccType; + long fccHandler; + long dwFlags; + long dwPriority; + long dwInitialFrames; + long dwScale; + long dwRate; + long dwStart; + long dwLength; + long dwSuggestedBufferSize; + long dwQuality; + long dwSampleSize; +}; + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/elcache.c b/branches/V-1.5.3/veejay-server/libel/elcache.c new file mode 100644 index 00000000..33edec37 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/elcache.c @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2002-2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* + Cache frames from file to memory + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif + +typedef struct +{ + int size; + int fmt; + long num; + void *buffer; +} cache_slot_t; + +typedef struct +{ + cache_slot_t **cache; + int len; + long *index; +} cache_t; + +static int cache_free_slot(cache_t *v) +{ + int i; + for( i = 0; i < v->len; i ++ ) + if( v->index[i] == -1 ) return i; + return -1; +} + +static long total_mem_used_ = 0; + +static void cache_claim_slot(cache_t *v, int free_slot, uint8_t *linbuf, long frame_num,int buf_len, int decoder_id) +{ + // create new node + cache_slot_t *data = (cache_slot_t*) vj_malloc(sizeof(cache_slot_t)); + data->size = buf_len; + data->num = frame_num; + data->fmt = decoder_id; + data->buffer = vj_malloc( buf_len ); +#ifdef STRICT_CHECKING + assert( v->index[free_slot] != frame_num ); +#endif + // clear old buffer + if( v->index[free_slot] >= 0 ) + { + cache_slot_t *del_slot = v->cache[free_slot]; + total_mem_used_ -= del_slot->size; + free( del_slot->buffer ); + free( del_slot ); + v->cache[free_slot] = NULL; + } + + veejay_memcpy( data->buffer, linbuf, buf_len ); + v->index[ free_slot ] = frame_num; + v->cache[ free_slot ] = data; + total_mem_used_ += buf_len; +} + +static int cache_find_slot( cache_t *v, long frame_num ) +{ + int i; + int k = 0; + long n = 0; + for( i = 0; i < v->len ; i ++ ) + { + long d = abs( v->index[i] - frame_num ); + if( d > n ) + { n = d; k = i ; } + } + return k; +} + +static int cache_locate_slot( cache_t *v, long frame_num) +{ + int i; + for( i = 0; i < v->len ; i ++ ) + if( v->index[i] == frame_num ) + return i; + return -1; +} + + +void *init_cache( unsigned int n_slots ) +{ + if(n_slots <= 0) + return NULL; + cache_t *v = (cache_t*) vj_calloc(sizeof(cache_t)); + v->len = n_slots; + v->cache = (cache_slot_t**) vj_calloc(sizeof(cache_slot_t*) * v->len ); + if(!v->cache) + { + free(v); + return NULL; + } + v->index = (long*) vj_malloc(sizeof(long) * v->len ); + int n; + for( n = 0; n < v->len ; n ++ ) + v->index[n] = -1; + return (void*) v; +} + +void reset_cache(void *cache) +{ + int i = 0; + cache_t *v = (cache_t*) cache; + + for( i = 0; i < v->len; i ++ ) + { + v->index[i] = -1; + if( v->cache[i] ) + { + total_mem_used_ -= v->cache[i]->size; + if(v->cache[i]->buffer) + free(v->cache[i]->buffer); + free(v->cache[i]); + v->cache[i] = NULL; + } + } +} + +int cache_avail_mb() +{ + return ( total_mem_used_ == 0 ? 0 : total_mem_used_ / (1024 * 1024 )); +} + + +void free_cache(void *cache) +{ + cache_t *v = (cache_t*) cache; + reset_cache( cache ); + free(v->cache); + free(v->index); + free(v); + v = NULL; +} + +void cache_frame( void *cache, uint8_t *linbuf, int buflen, long frame_num , int decoder_id) +{ + cache_t *v = (cache_t*) cache; +#ifdef STRICT_CHECKING + assert( cache != NULL ); + assert( linbuf != NULL ); + assert( buflen > 0 ); + assert( frame_num >= 0 ); +#else + if( buflen <= 0 ) + return; +#endif + int slot_num = cache_free_slot( cache ); + if( slot_num == -1 ) + slot_num = cache_find_slot( v, frame_num ); + +#ifdef STRICT_CHECKING + assert(slot_num >= 0 ); +#endif + cache_claim_slot(v, slot_num, linbuf, frame_num, buflen, decoder_id); +} + +uint8_t *get_cached_frame( void *cache, long frame_num, int *buf_len, int *decoder_id ) +{ + cache_t *v = (cache_t*) cache; + int slot = cache_locate_slot( v, frame_num ); + if( slot == -1 ) + return NULL; + + cache_slot_t *data = v->cache[ slot ]; +#ifdef STRICT_CHECKING + assert( data->size > 0 ); + assert( data->buffer != NULL ); +#endif + + *buf_len = data->size; + *decoder_id = data->fmt; +#ifdef STRICT_CHECKING + assert( data->num == frame_num ); +#endif + return (uint8_t*) data->buffer; +} diff --git a/branches/V-1.5.3/veejay-server/libel/elcache.h b/branches/V-1.5.3/veejay-server/libel/elcache.h new file mode 100644 index 00000000..64f0c649 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/elcache.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002-2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef ELCACHE_H +#define ELCACHE_H + +uint8_t *get_cached_frame( void *cache, long frame_num, int *buf_len, int *decoder_id ); +void cache_frame( void *cache, uint8_t *linbuf, int buflen, long frame_num , int decoder_id); +void free_cache(void *cache); +void *init_cache( unsigned int n_slots ); +void reset_cache(void *cache); +int cache_avail_mb(); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/lav_io.c b/branches/V-1.5.3/veejay-server/libel/lav_io.c new file mode 100644 index 00000000..e9499835 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/lav_io.c @@ -0,0 +1,1969 @@ +/* + * Some routines for handling I/O from/to different video + * file formats (currently AVI, Quicktime and movtar). + * + * These routines are isolated here in an extra file + * in order to be able to handle more formats in the future. + * + * Copyright (C) 2000 Rainer Johanni + * + * 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 +#ifdef STRICT_CHECKING +#include +#endif +//#include +#include +#ifdef USE_GDK_PIXBUF +#include +#endif +#include +#ifdef HAVE_LIBQUICKTIME +#include +#include +#include +#endif +#include +#include +#include +#define QUICKTIME_MJPG_TAG 0x6d6a7067 +extern int vj_el_get_decoder_from_fourcc( const char *fourcc ); + + +extern int AVI_errno; +static int _lav_io_default_chroma = CHROMAUNKNOWN; +static char video_format=' '; +static int internal_error=0; + +#define ERROR_JPEG 1 +#define ERROR_MALLOC 2 +#define ERROR_FORMAT 3 +#define ERROR_NOAUDIO 4 + +static unsigned long jpeg_field_size = 0; +static unsigned long jpeg_quant_offset = 0; +static unsigned long jpeg_huffman_offset = 0; +static unsigned long jpeg_image_offset = 0; +static unsigned long jpeg_scan_offset = 0; +static unsigned long jpeg_data_offset = 0; +static unsigned long jpeg_padded_len = 0; +static unsigned long jpeg_app0_offset = 0; +static unsigned long jpeg_app1_offset = 0; + +uint16_t reorder_16(uint16_t todo, int big_endian); + +#ifdef USE_GDK_PIXBUF +static int output_scale_width = 0; +static int output_scale_height = 0; +static float output_fps = 25.0; +static int output_yuv = 1; // 422 + +void lav_set_project(int w, int h, float f, int fmt) +{ + output_scale_width = w; + output_scale_height = h; + output_fps = f; + output_yuv = fmt; +} +#else +void lav_set_project(int w, int h, float f, int fmt) +{ +} +#endif + +#define M_SOF0 0xC0 +#define M_SOF1 0xC1 +#define M_DHT 0xC4 +#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_DQT 0xDB +#define M_APP0 0xE0 +#define M_APP1 0xE1 + + +#ifdef HAVE_LIBQUICKTIME +/* + put_int4: + Put a 4 byte integer value into a character array as big endian number +*/ + +static void put_int4(unsigned char *buf, int val) +{ + buf[0] = (val >> 24); + buf[1] = (val >> 16); + buf[2] = (val >> 8 ); + buf[3] = (val ); +} +#endif + +//#ifdef SUPPORT_READ_DV2 +//static int check_DV2_input(lav_file_t *lav_fd); +//#endif + +#define TMP_EXTENSION ".tmp" + +/* + get_int2: + get a 2 byte integer value from a character array as big endian number + */ + +static int get_int2(unsigned char *buff) +{ + return (buff[0]*256 + buff[1]); +} + +/* + scan_jpeg: + Scan jpeg data for markers, needed for Quicktime MJPA format + and partly for AVI files. + Taken mostly from Adam Williams' quicktime library + */ + +static int scan_jpeg(unsigned char * jpegdata, long jpeglen, int header_only) +{ + int marker, length; + long p; + + jpeg_field_size = 0; + jpeg_quant_offset = 0; + jpeg_huffman_offset = 0; + jpeg_image_offset = 0; + jpeg_scan_offset = 0; + jpeg_data_offset = 0; + jpeg_padded_len = 0; + jpeg_app0_offset = 0; + jpeg_app1_offset = 0; + + /* The initial marker must be SOI */ + + if (jpegdata[0] != 0xFF || jpegdata[1] != M_SOI) return -1; + + /* p is the pointer within the jpeg data */ + + p = 2; + + /* scan through the jpeg data */ + + while(p=jpeglen) return -1; + } + + /* Get marker code byte, swallowing any duplicate FF bytes */ + while(jpegdata[p] == 0xFF) + { + p++; + if(p>=jpeglen) return -1; + } + + marker = jpegdata[p++]; + + if(p<=jpeglen-2) + length = get_int2(jpegdata+p); + else + length = 0; + + /* We found a marker - check it */ + + if(marker == M_EOI) { jpeg_field_size = p; break; } + + switch(marker) + { + case M_SOF0: + case M_SOF1: + jpeg_image_offset = p-2; + break; + case M_DQT: + if(jpeg_quant_offset==0) jpeg_quant_offset = p-2; + break; + case M_DHT: + if(jpeg_huffman_offset==0) jpeg_huffman_offset = p-2; + break; + case M_SOS: + jpeg_scan_offset = p-2; + jpeg_data_offset = p+length; + if(header_only) return 0; /* we are done with the headers */ + break; + case M_APP0: + if(jpeg_app0_offset==0) jpeg_app0_offset = p-2; + break; + case M_APP1: + if(jpeg_app1_offset==0) jpeg_app1_offset = p-2; + break; + } + + /* The pseudo marker as well as the markers M_TEM (0x01) + and M_RST0 ... M_RST7 (0xd0 ... 0xd7) have no paramters. + M_SOI and M_EOI also have no parameters, but we should + never come here in that case */ + + if(marker == 0 || marker == 1 || (marker >= 0xd0 && marker <= 0xd7)) + continue; + + /* skip length bytes */ + + if(p+length<=jpeglen) + p += length; + else + return -1; + } + + /* We are through parsing the jpeg data, we should have seen M_EOI */ + + if(!jpeg_field_size) return -1; + + /* Check for trailing garbage until jpeglen is reached or a new + M_SOI is seen */ + + while(pavi_fd = 0; + lav_fd->format = format; + lav_fd->interlacing = interlaced ? lav_query_polarity(format):LAV_NOT_INTERLACED; + lav_fd->has_audio = (asize>0 && achans>0); + lav_fd->bps = (asize*achans+7)/8; + lav_fd->is_MJPG = 1; + lav_fd->MJPG_chroma = _lav_io_default_chroma; + + char fourcc[16]; + + int is_avi = 1; + + switch(format) + { + case 'a': + case 'A': + /* Open AVI output file */ + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI MJPEG"); + sprintf(fourcc, "MJPG" ); + break; + case 'c': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI MJPEG-b"); + sprintf(fourcc, "MJPB" ); + break; + case 'l': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI LJPEG"); + sprintf(fourcc, "JPGL"); + break; + case 'L': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI LZO (veejay's fourcc)"); + sprintf(fourcc, "MLZO" ); + break; + case 'v': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI VJ20 (veejay's fourcc)"); + sprintf(fourcc,"VJ20"); + break; + case 'V': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI VJ22 (veejay's fourcc)"); + sprintf(fourcc,"VJ22"); + break; + case 'Y': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI IYUV"); + sprintf(fourcc, "IYUV" ); + break; + case 'P': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI YV16"); + sprintf(fourcc, "YV16"); + break; + case 'D': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI DIV3"); + sprintf(fourcc, "DIV3"); + break; + case 'M': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI MP4V"); + sprintf(fourcc,"MP4V"); + break; + case 'b': + case 'd': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in AVI DVSD"); + sprintf(fourcc, "DVSD"); + break; + + case 'q': + case 'Q': + veejay_msg(VEEJAY_MSG_DEBUG, "\tWriting output file in Quicktime MJPA/JPEG"); + is_avi = 0; + break; + case 'x': + is_avi = 0; + break; + } + + if( is_avi ) + { + lav_fd->avi_fd = AVI_open_output_file(filename); + if(!lav_fd->avi_fd) + { + free(lav_fd); + return NULL; + } + AVI_set_video(lav_fd->avi_fd, width, height, fps, fourcc ); + if (asize) + { + if(AVI_set_audio(lav_fd->avi_fd, achans, arate, asize, WAVE_FORMAT_PCM)==-1) + { + veejay_msg(0, "Too many channels or invalid AVI file"); + lav_close( lav_fd ); + return NULL; + } + } + return lav_fd; + } else { +#ifdef HAVE_LIBQUICKTIME + /* open quicktime output file */ + + /* since the documentation says that the file should be empty, + we try to remove it first */ + remove(filename); + + lav_fd->qt_fd = quicktime_open(filename, 0, 1); + if(!lav_fd->qt_fd) + { + veejay_msg(VEEJAY_MSG_ERROR, "\tCannot open '%s' for writing", filename); + free(lav_fd); + return NULL; + } + if(format=='q') + quicktime_set_video(lav_fd->qt_fd, 1, width, height, fps, + (interlaced ? QUICKTIME_MJPA : QUICKTIME_JPEG)); + else + quicktime_set_video(lav_fd->qt_fd,1, width,height,fps, + QUICKTIME_DV ); + if (asize) + quicktime_set_audio(lav_fd->qt_fd, achans, arate, asize, QUICKTIME_TWOS); + + int has_kf = quicktime_has_keyframes( lav_fd->qt_fd, 0 ); + char *copyright = quicktime_get_copyright( lav_fd->qt_fd ); + char *name = quicktime_get_name( lav_fd->qt_fd ); + char *info = quicktime_get_info( lav_fd->qt_fd ); + + veejay_msg(VEEJAY_MSG_DEBUG, + "(C) %s by %s, %s, has keyframes = %d", copyright,name,info,has_kf ); + + return lav_fd; +#else + veejay_msg(0,"Quicktime not compiled in, cannot use Quicktime."); + internal_error = ERROR_FORMAT; + return NULL; +#endif + + } + if(lav_fd) free(lav_fd); + return NULL; +} + +int lav_close(lav_file_t *lav_file) +{ + int ret = 0; + video_format = lav_file->format; internal_error = 0; /* for error messages */ + switch(video_format) + { +#ifdef SUPPORT_READ_DV2 + case 'b': + if( lav_file->dv_fd ) + { + veejay_msg(VEEJAY_MSG_DEBUG,"\tClosing raw dv file"); + ret = rawdv_close(lav_file->dv_fd); + } + break; +#endif +#ifdef USE_GDK_PIXBUF + case 'x': + if( lav_file->picture ) + { + veejay_msg(VEEJAY_MSG_DEBUG,"\tClosing image file"); + vj_picture_cleanup( lav_file->picture ); + ret = 1; + } + break; +#endif +#ifdef HAVE_LIBQUICKTIME + case 'q': + if( lav_file->qt_fd ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "\tClosing Quicktime file"); + ret = quicktime_close( lav_file->qt_fd ); + } + break; +#endif + default: + if( lav_file->avi_fd ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "\tClosing AVI file"); + ret = AVI_close(lav_file->avi_fd); + } + break; + } + + if(lav_file) free(lav_file); + + lav_file = NULL; + + return ret; +} + +int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count) +{ + int res, n; + uint8_t *jpgdata = NULL; + long jpglen = 0; +#ifdef STRICT_CHECKING + assert( buff != NULL ); +#endif + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return -1; //rawdv, no stream writing support yet +#endif + /* For interlaced video insert the apropriate APPn markers */ +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return -1;//picture +#endif + if(lav_file->interlacing!=LAV_NOT_INTERLACED) + { + switch( lav_file->format ) + { + case 'a': + case 'A': + jpgdata = buff; + jpglen = size; + + /* Loop over both fields */ + + for(n=0;n<2;n++) + { + /* For first field scan entire field, for second field + scan the JPEG header, put in AVI1 + polarity. + Be generous on errors */ + + res = scan_jpeg(jpgdata, size, n); + if (res) + { + internal_error=ERROR_JPEG; + return -1; + } + + if(!jpeg_app0_offset) continue; + + /* APP0 marker should be at least 14+2 bytes */ + if(get_int2(jpgdata+jpeg_app0_offset+2) < 16 ) continue; + + jpgdata[jpeg_app0_offset+4] = 'A'; + jpgdata[jpeg_app0_offset+5] = 'V'; + jpgdata[jpeg_app0_offset+6] = 'I'; + jpgdata[jpeg_app0_offset+7] = '1'; + jpgdata[jpeg_app0_offset+8] = lav_file->format=='a' ? n+1 : 2-n; + + /* Update pointer and len for second field */ + jpgdata += jpeg_padded_len; + jpglen -= jpeg_padded_len; + } + break; +#ifdef HAVE_LIBQUICKTIME + case 'q': + case 'Q': + + jpgdata = buff; + jpglen = size; + + /* Loop over both fields */ + + for(n=0;n<2;n++) + { + /* Scan the entire JPEG field data - APP1 marker MUST be present */ + res = scan_jpeg(jpgdata,jpglen,0); + if(res || !jpeg_app1_offset) { internal_error=ERROR_JPEG; return -1; } + + /* Length of APP1 marker must be at least 40 + 2 bytes */ + if ( get_int2(jpgdata+jpeg_app1_offset+2) < 42) + { internal_error=ERROR_JPEG; return -1; } + + /* Fill in data */ + put_int4(jpgdata+jpeg_app1_offset+ 4,0); + put_int4(jpgdata+jpeg_app1_offset+ 8,QUICKTIME_MJPG_TAG); + put_int4(jpgdata+jpeg_app1_offset+12,jpeg_field_size); + put_int4(jpgdata+jpeg_app1_offset+16,jpeg_padded_len); + put_int4(jpgdata+jpeg_app1_offset+20,n==0?jpeg_padded_len:0); + put_int4(jpgdata+jpeg_app1_offset+24,jpeg_quant_offset); + put_int4(jpgdata+jpeg_app1_offset+28,jpeg_huffman_offset); + put_int4(jpgdata+jpeg_app1_offset+32,jpeg_image_offset); + put_int4(jpgdata+jpeg_app1_offset+36,jpeg_scan_offset); + put_int4(jpgdata+jpeg_app1_offset+40,jpeg_data_offset); + + /* Update pointer and len for second field */ + jpgdata += jpeg_padded_len; + jpglen -= jpeg_padded_len; + } + break; +#endif + + } + } + res = 0; /* Silence gcc */ + for(n=0;nformat) + { + case 'a': + case 'A': + case 'M': + case 'P': + case 'D': + case 'v': + case 'V': + case 'Y': + case 'L': + case 'l': + case 'd': + if(n==0) + res = AVI_write_frame( lav_file->avi_fd, buff, size ); + else + res = AVI_dup_frame( lav_file->avi_fd ); + break; + +#ifdef HAVE_LIBQUICKTIME + case 'q': + case 'Q': + res = quicktime_write_frame( lav_file->qt_fd, buff, size, 0 ); + break; +#endif + default: + res = -1; + break; + + } + } + return res; +} + +int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps) +{ + int res; +#ifdef HAVE_LIBQUICKTIME + int i, j; + int16_t *qt_audio = (int16_t *)buff, **qt_audion; + int channels = lav_audio_channels(lav_file); + + qt_audion = malloc(channels * sizeof (int16_t **)); + for (i = 0; i < channels; i++) + qt_audion[i] = (int16_t *)malloc(samps * lav_file->bps); +#endif + switch(lav_file->format ) + { +#ifdef HAVE_LIBQUICKTIME + case 'q': + case 'Q': + /* Deinterleave the audio into the two channels. */ + for (i = 0; i < samps; i++) + { + for (j = 0; j < channels; j++) + qt_audion[j][i] = qt_audio[(channels*i) + j]; + } + res = lqt_encode_audio_track(lav_file->qt_fd, qt_audion, NULL,samps,0); + for (j = 0; j < channels; j++) + free(qt_audion[j]); + free(qt_audion); + return res; + break; +#endif +#ifdef SUPPORT_READ_DV2 + case 'b': + return 0; +#endif +#ifdef USE_GDK_PIXBUF + case 'x': + return 0; +#endif + default: + return AVI_write_audio( lav_file->avi_fd, buff, samps*lav_file->bps); + } + return 0; +} + +void lav_bogus_set_length( lav_file_t *lav_file , int len ) +{ + lav_file->bogus_len = len; +} + +int lav_bogus_video_length( lav_file_t *lav_file ) +{ + video_format = lav_file->format; + if( lav_file->format == 'x' ) + return lav_file->bogus_len; + return 0; +} + + + +long lav_video_frames(lav_file_t *lav_file) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ + switch(lav_file->format) + { +#ifdef SUPPORT_READ_DV2 + case 'b': + return rawdv_video_frames(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + case 'x': + return lav_file->bogus_len; +#endif +#ifdef HAVE_LIBQUICKTIME + case 'q': + case 'Q': + return quicktime_video_length(lav_file->qt_fd,0); +#endif + default: + return AVI_video_frames( lav_file->avi_fd ); + } + return -1; +} + +int lav_video_width(lav_file_t *lav_file) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ + switch(lav_file->format) + { +#ifdef SUPPORT_READ_DV2 + case 'b': return rawdv_width(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + case 'x': return output_scale_width; +#endif +#ifdef HAVE_LIBQUICKTIME + case 'q': case 'Q': return quicktime_video_width(lav_file->qt_fd,0); +#endif + default: + return AVI_video_width( lav_file->avi_fd); + } + return -1; +} + +int lav_video_height(lav_file_t *lav_file) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ + switch( lav_file->format ) + { +#ifdef SUPPORT_READ_DV2 + case 'b': return rawdv_height( lav_file->dv_fd ); +#endif +#ifdef USE_GDK_PIXBUF + case 'x': return output_scale_height; +#endif +#ifdef HAVE_LIBQUICKTIME + case 'q': case 'Q': return quicktime_video_height(lav_file->qt_fd,0); +#endif + default: + return AVI_video_height(lav_file->avi_fd); + } + return -1; +} + +double lav_frame_rate(lav_file_t *lav_file) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ + switch(lav_file->format) + { +#ifdef SUPPORT_READ_DV2 + case 'b': + return rawdv_fps(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + case 'x': + return output_fps; +#endif +#ifdef HAVE_LIBQUICKTIME + case 'q': case 'Q': + return quicktime_frame_rate(lav_file->qt_fd,0); +#endif + default: + return AVI_frame_rate( lav_file->avi_fd ); + } + return -1; +} + +int lav_video_interlacing(lav_file_t *lav_file) +{ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return rawdv_interlacing(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return LAV_NOT_INTERLACED; +#endif + return lav_file->interlacing; +} + +void lav_video_clipaspect(lav_file_t *lav_file, int *sar_w, int *sar_h) +{ + *sar_w = lav_file->sar_w; + *sar_h = lav_file->sar_h; + return; +} + +int lav_video_is_MJPG(lav_file_t *lav_file) +{ + return lav_file->is_MJPG; +} + +int lav_video_MJPG_chroma(lav_file_t *lav_file) +{ + return lav_file->MJPG_chroma; +} + +int lav_is_yuv_planar( int pix_fmt ) +{ + switch(pix_fmt){ + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUVJ444P: + case PIX_FMT_YUV420P: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV444P: + return 1; + } + return 0; +} + +int lav_video_cmodel( lav_file_t *lav_file) +{ + switch(lav_file->MJPG_chroma) + { + case CHROMA411: + return PIX_FMT_YUV411P; + case CHROMA420: + return PIX_FMT_YUV420P; + case CHROMA422: + return PIX_FMT_YUV422P; + case CHROMA420F: + return PIX_FMT_YUVJ420P; + case CHROMA422F: + return PIX_FMT_YUVJ422P; + case CHROMA444: + return PIX_FMT_YUV444P; + default: + return -1; + } + + return -1; +} + +int lav_video_is_qt( lav_file_t *lav_file) +{ +#ifdef HAVE_LIBQUICK_TIME + if( lav_file->qt_fd) + return 1; +#endif + return 0; +} + + + +int lav_video_compressor_type(lav_file_t *lav_file) +{ +#ifdef SUPPORT_READ_DV2 + if(lav_file->format == 'b') + return rawdv_compressor( lav_file->dv_fd ); +#endif +#ifdef USE_GDK_PIXBUF + if(lav_file->format == 'x') + return 0xffff; +#endif +#ifdef HAVE_LIBQUICKTIME + if(lav_file->format == 'q' || lav_file->format == 'Q') + { + const char *compressor = quicktime_video_compressor(lav_file->qt_fd,0); + return vj_el_get_decoder_from_fourcc( compressor ); + } + // return quicktime_video_compressor(lav_file->qt_fd,0); +#endif + return AVI_video_compressor_type( lav_file->avi_fd ); +} + +const char *lav_video_compressor(lav_file_t *lav_file) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if( video_format == 'b' ) + { + const char *tmp = (const char*) strdup("dvsd"); + return tmp; + } +#endif +#ifdef USE_GDK_PIXBUF + if( video_format == 'x') + { + const char *tmp = (const char*) strdup("PICT"); + return tmp; + } +#endif + if( video_format == 'L' ) + { + return (strdup("mlzo")); + } +#ifdef HAVE_LIBQUICKTIME + if(lav_file->format == 'q' || lav_file->format == 'Q') + return quicktime_video_compressor(lav_file->qt_fd,0); +#endif + return AVI_video_compressor(lav_file->avi_fd); +} + +int lav_audio_channels(lav_file_t *lav_file) +{ + if(!lav_file->has_audio) return 0; + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return rawdv_audio_channels(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 0; +#endif +#ifdef HAVE_LIBQUICKTIME + if(video_format == 'q' || video_format =='Q') + return quicktime_track_channels(lav_file->qt_fd,0); +#endif + return AVI_audio_channels(lav_file->avi_fd); +} + +int lav_audio_bits(lav_file_t *lav_file) +{ + if(!lav_file->has_audio) return 0; + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return rawdv_audio_bits(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x' ) + return 0; +#endif +#ifdef HAVE_LIBQUICKTIME + if(video_format == 'q'|| video_format =='Q') + return quicktime_audio_bits(lav_file->qt_fd,0); +#endif + return (AVI_audio_bits(lav_file->avi_fd)); +} + +long lav_audio_rate(lav_file_t *lav_file) +{ + if(!lav_file->has_audio) return 0; + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format=='b') + return rawdv_audio_rate(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 0; +#endif +#ifdef HAVE_LIBQUICKTIME + if( video_format == 'q'|| video_format =='Q') + return quicktime_sample_rate(lav_file->qt_fd,0); +#endif + return (AVI_audio_rate(lav_file->avi_fd)); +} + +long lav_audio_clips(lav_file_t *lav_file) +{ + if(!lav_file->has_audio) return 0; + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format=='b') + return rawdv_audio_bps(lav_file->dv_fd); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 0; +#endif +#ifdef HAVE_LIBQUICKTIME + if(video_format == 'q'|| video_format == 'Q') + return quicktime_audio_length(lav_file->qt_fd,0); +#endif + return (AVI_audio_bytes(lav_file->avi_fd)/lav_file->bps); +} + +long lav_frame_size(lav_file_t *lav_file, long frame) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return rawdv_frame_size( lav_file->dv_fd ); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 1; +#endif +#ifdef HAVE_LIBQUICKTIME + if( video_format == 'q' || video_format == 'Q') + return quicktime_frame_size(lav_file->qt_fd,frame,0); +#endif + return (AVI_frame_size(lav_file->avi_fd,frame)); +} + +int lav_seek_start(lav_file_t *lav_file) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return rawdv_set_position( lav_file->dv_fd, 0 ); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 1; +#endif +#ifdef HAVE_LIBQUICKTIME + return quicktime_seek_start(lav_file->qt_fd); +#endif + return (AVI_seek_start(lav_file->avi_fd)); +} + +int lav_set_video_position(lav_file_t *lav_file, long frame) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return rawdv_set_position( lav_file->dv_fd, frame ); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 1; +#endif +#ifdef HAVE_LIBQUICKTIME + if(video_format == 'q' || video_format == 'Q') + return quicktime_set_video_position(lav_file->qt_fd,(int64_t)frame,0); +#endif + return (AVI_set_video_position(lav_file->avi_fd,frame)); +} + +int lav_read_frame(lav_file_t *lav_file, uint8_t *vidbuf) +{ + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(lav_file->format == 'b') + { + return rawdv_read_frame( lav_file->dv_fd, vidbuf ); + } +#endif +#ifdef USE_GDK_PIXBUF + if(lav_file->format == 'x') + return -1; +#endif +#ifdef HAVE_LIBQUICKTIME + if(lav_file->format == 'q'|| lav_file->format == 'Q') + return quicktime_read_frame(lav_file->qt_fd,vidbuf,0); +#endif + int kf = 1; + int ret = (AVI_read_frame(lav_file->avi_fd,vidbuf,&kf)); +/* + if(!kf) + { +// veejay_msg(0, "Requested frame is not a keyframe"); + return ret; + } +*/ + return ret; + +} + +#ifdef USE_GDK_PIXBUF +VJFrame *lav_get_frame_ptr( lav_file_t *lav_file ) +{ + if(lav_file->format == 'x') + return vj_picture_get( lav_file->picture ); + return NULL; +} +#else +uint8_t *lav_get_frame_ptr( lav_file_t *lav_file) +{ + return NULL; +} +#endif + +int lav_is_DV(lav_file_t *lav_file) +{ +#ifdef SUPPORT_READ_DV2 + if(lav_file->format == 'b') + return 1; +#endif + return 0; +} + +int lav_set_audio_position(lav_file_t *lav_file, long clip) +{ + if(!lav_file->has_audio) return 0; + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return 0; +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 0; +#endif +#ifdef HAVE_LIBQUICKTIME + if(video_format =='q'|| video_format == 'Q') + quicktime_set_audio_position(lav_file->qt_fd,clip,0); +#endif + return (AVI_set_audio_position(lav_file->avi_fd,clip*lav_file->bps)); +} + +int lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps) +{ + if(!lav_file->has_audio) + { + internal_error = ERROR_NOAUDIO; + return -1; + } +#ifdef SUPPORT_READ_DV2 + if(video_format == 'b') + return rawdv_read_audio_frame( lav_file->dv_fd, audbuf ); +#endif +#ifdef USE_GDK_PIXBUF + if(video_format == 'x') + return 0; +#endif + video_format = lav_file->format; internal_error = 0; /* for error messages */ +#ifdef HAVE_LIBQUICKTIME + if( video_format == 'q' || video_format == 'Q') + { + int64_t last_pos, start_pos; + int res, i, j; + int16_t *qt_audio = (int16_t *)audbuf, **qt_audion; + int channels = lav_audio_channels(lav_file); + uint8_t b0, b1; + qt_audion = malloc(channels * sizeof (int16_t **)); + for (i = 0; i < channels; i++) + qt_audion[i] = (int16_t *)malloc(samps * lav_file->bps); + + start_pos = quicktime_audio_position(lav_file->qt_fd, 0); + lqt_decode_audio_track(lav_file->qt_fd, qt_audion, NULL, samps, 0); + last_pos = lqt_last_audio_position(lav_file->qt_fd, 0); + res = last_pos - start_pos; + if (res <= 0) + goto out; + /* Interleave the channels of audio into the one buffer provided */ + for (i =0; i < res; i++) + { + for (j = 0; j < channels; j++) + qt_audio[(channels*i) + j] = qt_audion[j][i]; + } + + if (lav_detect_endian()) + { + i= 0; + while (i < (2*res) ) + { + b0 = 0; + b1 = 0; + b0 = (qt_audio[i] & 0x00FF); + b1 = (qt_audio[i] & 0xFF00) >> 8; + qt_audio[i] = (b0 <<8) + b1; + i = i +1; + } + } +out: + for (j = 0; j < channels; j++) + free(qt_audion[j]); + free(qt_audion); + return(res); + } +#endif + + int res = AVI_read_audio( lav_file->avi_fd, audbuf, + (samps * lav_file->bps) ); + return res; +} + +int lav_filetype(lav_file_t *lav_file) +{ + return lav_file->format; +} + +lav_file_t *lav_open_input_file(char *filename, int mmap_size) +{ + int n; + char *video_comp = NULL; + unsigned char *frame = NULL; /* Make sure un-init segfaults! */ + long len; + int jpg_height, jpg_width, ncomps, hf[3], vf[3]; + int ierr; + + lav_file_t *lav_fd = (lav_file_t*) vj_malloc(sizeof(lav_file_t)); + + if(lav_fd==0) { internal_error=ERROR_MALLOC; return 0; } + + /* Set lav_fd */ + +#ifdef HAVE_LIBQUICKTIME + char *audio_comp; +#endif + lav_fd->avi_fd = 0; +#ifdef SUPPORT_READ_DV2 + lav_fd->dv_fd = 0; +#endif +#ifdef USE_GDK_PIXBUF + lav_fd->picture = NULL; +#endif + lav_fd->format = 0; + lav_fd->interlacing = LAV_INTER_UNKNOWN; + lav_fd->sar_w = 0; /* (0,0) == unknown */ + lav_fd->sar_h = 0; + lav_fd->has_audio = 0; + lav_fd->bps = 0; + lav_fd->is_MJPG = 0; + lav_fd->MJPG_chroma = CHROMAUNKNOWN; + lav_fd->mmap_size = mmap_size; + + int ret = 0; + + /* open file, check if file is a file */ + struct stat s; + if( stat(filename, &s ) != 0 ) + { + if(lav_fd) free(lav_fd); + veejay_msg(VEEJAY_MSG_ERROR, "Invalid file '%s'. Proper permissions?",filename); + return NULL; + } + + if(!S_ISREG( s.st_mode) ) + { + veejay_msg(VEEJAY_MSG_ERROR, "'%s' is not a regular file",filename); + if(lav_fd) free(lav_fd); + return NULL; + } + + + lav_fd->avi_fd = AVI_open_input_file(filename,1,mmap_size); + + if( lav_fd->avi_fd && AVI_errno == AVI_ERR_EMPTY ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Empty AVI file"); + if(lav_fd) free(lav_fd); + return NULL; + } + else if ( lav_fd->avi_fd && AVI_errno == 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, + "\tFile is AVI" ); + ret =1; + } + + int alt = 0; + + if(lav_fd->avi_fd) + { + ret = 1; + alt = 1; + lav_fd->format = 'a'; + lav_fd->has_audio = (AVI_audio_bits(lav_fd->avi_fd)>0 && + AVI_audio_format(lav_fd->avi_fd)==WAVE_FORMAT_PCM); + video_comp = AVI_video_compressor(lav_fd->avi_fd); + if(video_comp == NULL || strlen(video_comp) <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to read FOURCC from AVI"); + if(lav_fd) free(lav_fd); + return 0; + } + veejay_msg(VEEJAY_MSG_DEBUG, "\tFOURCC is %s", video_comp ); + } + else if( AVI_errno==AVI_ERR_NO_AVI || !lav_fd->avi_fd) + { +#ifdef HAVE_LIBQUICKTIME + if(quicktime_check_sig(filename)) + { + quicktime_pasp_t pasp; + int nfields, detail; + lav_fd->qt_fd = quicktime_open(filename,1,0); + video_format = 'q'; /* for error messages */ + if (!lav_fd->qt_fd) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to open quicktime file"); + free(lav_fd); + return 0; + } + else + veejay_msg(VEEJAY_MSG_DEBUG, "\tOpening Quicktime file"); + lav_fd->avi_fd = NULL; + lav_fd->format = 'q'; + video_comp = quicktime_video_compressor(lav_fd->qt_fd,0); + veejay_msg(VEEJAY_MSG_DEBUG,"\tFile has fourcc '%s'", + video_comp ); + /* We want at least one video track */ + if (quicktime_video_tracks(lav_fd->qt_fd) < 1) + { + veejay_msg(VEEJAY_MSG_ERROR, "At least one video track required"); + lav_close(lav_fd); + internal_error = ERROR_FORMAT; + return 0; + } + /* + * If the quicktime file has the sample aspect atom then use it to set + * the sar values in the lav_fd structure. Hardwired (like everywhere else) + * to only look at track 0. + */ + /* + if (lqt_get_pasp(lav_fd->qt_fd, 0, &pasp) != 0) + { + lav_fd->sar_w = pasp.hSpacing; + lav_fd->sar_h = pasp.vSpacing; + }*/ + /* + * If a 'fiel' atom is present (not guaranteed) then use it to set the + * interlacing type. + */ + + if (lqt_get_fiel(lav_fd->qt_fd, 0, &nfields, &detail) != 0) + { + if (nfields == 2) + { + if (detail == 14 || detail == 6) + lav_fd->interlacing = LAV_INTER_BOTTOM_FIRST; + else if (detail == 9 || detail == 1) + lav_fd->interlacing = LAV_INTER_TOP_FIRST; + else + veejay_msg(VEEJAY_MSG_DEBUG, "Unknown 'detail' in 'fiel' atom: %d", detail); + } + else + lav_fd->interlacing = LAV_NOT_INTERLACED; + } + /* Check for audio tracks */ + lav_fd->has_audio = 0; + if (quicktime_audio_tracks(lav_fd->qt_fd)) + { + audio_comp = quicktime_audio_compressor(lav_fd->qt_fd,0); + if (strncasecmp(audio_comp, QUICKTIME_TWOS,4)==0) + lav_fd->has_audio = 1; + else + veejay_msg(VEEJAY_MSG_WARNING, "Audio compressor '%s' not supported", + audio_comp ); + } + alt = 1; + ret = 1; + } + else + veejay_msg(VEEJAY_MSG_DEBUG, "\tNot a Quicktime file"); +#endif + + +#ifdef SUPPORT_READ_DV2 + if(!alt) + { + ret = 0; + lav_fd->dv_fd = rawdv_open_input_file(filename,mmap_size); + if(lav_fd->dv_fd > 0) + { + lav_fd->MJPG_chroma = rawdv_sampling( lav_fd->dv_fd ); + video_comp = rawdv_video_compressor( lav_fd->dv_fd ); + lav_fd->format = 'b'; + lav_fd->has_audio = 0; + ret = 1; + alt = 1; + veejay_msg(VEEJAY_MSG_DEBUG, + "RAW DV file '%s'", + video_comp ); + } + else + veejay_msg(VEEJAY_MSG_DEBUG, "\tNot a raw dv file"); + } +#endif + #ifdef USE_GDK_PIXBUF + if(!alt) + { + lav_fd->picture = vj_picture_open( (const char*) filename, + output_scale_width, output_scale_height, get_ffmpeg_pixfmt(output_yuv) ); + if(lav_fd->picture) + { + lav_fd->format = 'x'; + lav_fd->has_audio = 0; + lav_fd->bogus_len = (int) output_fps; + video_comp = strdup( "PICT" ); + ret = 1; + alt = 1; + veejay_msg(VEEJAY_MSG_DEBUG, + "\tLoaded image file"); + } + else + veejay_msg(VEEJAY_MSG_DEBUG, + "\tNot a Image file"); + } +#endif + } + + if(ret == 0 || video_comp == NULL || alt == 0) + { + free(lav_fd); + internal_error = ERROR_FORMAT; /* Format not recognized */ + veejay_msg(VEEJAY_MSG_ERROR, "Unable to load file '%s', code=%x, video=%s", filename,ret,video_comp); + return 0; + } + + lav_fd->bps = (lav_audio_channels(lav_fd)*lav_audio_bits(lav_fd)+7)/8; + + if(lav_fd->bps==0) lav_fd->bps=1; /* make it save since we will divide by that value */ + /* if(strlen(video_comp) == 1 ) { + lav_fd->MJPG_chroma = CHROMA422; + lav_fd->format = 'V'; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } +*/ + +#ifdef USE_GDK_PIXBUF + if(strncasecmp(video_comp, "PICT",4) == 0 ) + { + switch(output_yuv) + { + case FMT_420: + case FMT_420F: + lav_fd->MJPG_chroma = CHROMA420; + break; + case FMT_422: + case FMT_422F: + lav_fd->MJPG_chroma = CHROMA422; + break; + default: + lav_fd->MJPG_chroma = CHROMAUNKNOWN; + break; + } + lav_fd->format = 'x'; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } +#endif + + + if( strncasecmp(video_comp, "div3",4)==0 || + strncasecmp(video_comp, "mp43",4)==0 || + strncasecmp(video_comp, "mp42",4)==0 ) + { + lav_fd->MJPG_chroma = CHROMA420; + lav_fd->interlacing = LAV_NOT_INTERLACED; + veejay_msg(VEEJAY_MSG_WARNING, "Playing MS MPEG4v3 DivX Video. (Every frame should be an intra frame)" ); + return lav_fd; + } + + if( strncasecmp(video_comp,"mp4v",4 )==0 || + strncasecmp(video_comp,"fmp4",4 )==0 || + strncasecmp(video_comp,"divx",4 ) == 0 || + strncasecmp(video_comp,"xvid",4 ) == 0 || + strncasecmp(video_comp,"dxsd",4 ) == 0 || + strncasecmp(video_comp,"mp4s",4 ) == 0 || + strncasecmp(video_comp,"m4s2",4 ) == 0 ) + { + lav_fd->format = 'D'; + lav_fd->MJPG_chroma = CHROMA420; + lav_fd->interlacing = LAV_NOT_INTERLACED; + veejay_msg(VEEJAY_MSG_WARNING, "Playing MPEG4 Video (Every frame should be an intra frame)"); + return lav_fd; + } + + if ( strncasecmp(video_comp,"iyuv",4)==0 || + strncasecmp(video_comp,"yv12",4)==0 || + strncasecmp(video_comp,"i420",4)==0) + { + lav_fd->MJPG_chroma = CHROMA420; + lav_fd->format = 'Y'; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } + + if(strncasecmp(video_comp,"vj22",4)==0) + { + lav_fd->MJPG_chroma = CHROMA422F; + lav_fd->format = 'V'; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } + if(strncasecmp(video_comp,"vj20",4)==0) + { + lav_fd->MJPG_chroma = CHROMA420F; + lav_fd->format = 'v'; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } + + if ( strncasecmp(video_comp,"yv16",4)==0 || + strncasecmp(video_comp,"i422",4)==0 || + strncasecmp(video_comp,"hfyu",4)==0) + { + lav_fd->MJPG_chroma = CHROMA422; + lav_fd->format = 'P'; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } + + if( strncasecmp(video_comp, "avc1", 4 ) == 0 || + strncasecmp(video_comp, "h264", 4 ) == 0 || + strncasecmp(video_comp, "x264", 4 ) == 0 || + strncasecmp(video_comp, "davc", 4 ) == 0 ) + { + lav_fd->MJPG_chroma = CHROMA420; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } + + if( strncasecmp( video_comp, "mlzo", 4 ) == 0 ) + { + lav_fd->MJPG_chroma = CHROMA422; + lav_fd->interlacing = LAV_NOT_INTERLACED; + return lav_fd; + } + + if ( strncasecmp(video_comp,"dvsd",4)==0 || + strncasecmp(video_comp,"dvcp",4) ==0 || + strncasecmp(video_comp,"dxsd",4) == 0 || + strncasecmp(video_comp, "dvp",3) == 0 || + strncasecmp(video_comp, "dvhd",4) == 0 || + strncasecmp(video_comp, "dv",2 ) == 0) + { + int gw = lav_video_height( lav_fd ); + if( gw == 480 ) + lav_fd->MJPG_chroma = CHROMA411; + else + lav_fd->MJPG_chroma = CHROMA422; + + lav_fd->interlacing = LAV_INTER_BOTTOM_FIRST; + return lav_fd; + } + + if( strncasecmp(video_comp, "png", 3 ) == 0 || + strncasecmp(video_comp, "mpng",4) == 0 ) + { + lav_fd->MJPG_chroma = CHROMA420; + lav_fd->interlacing = LAV_INTER_UNKNOWN; + return lav_fd; + } + + if( strncasecmp(video_comp, "svq1", 4 ) == 0 || + strncasecmp(video_comp, "svq3", 4 ) == 0 || + strncasecmp(video_comp, "rpza", 4 ) == 0 || + strncasecmp(video_comp, "cyuv", 4 ) == 0 ) + { + lav_fd->MJPG_chroma = CHROMA420; + lav_fd->interlacing = LAV_INTER_UNKNOWN; + return lav_fd; + } + + if ( strncasecmp(video_comp,"mjpg", 4) == 0 || + strncasecmp(video_comp,"mjpa", 4) == 0 || + strncasecmp(video_comp,"jpeg", 4) == 0 || + strncasecmp(video_comp,"mjpb" ,4) == 0 || + strncasecmp(video_comp,"sp5x", 4) == 0 || + strncasecmp(video_comp,"jpgl", 4) == 0 || + strncasecmp(video_comp , "jfif", 4 ) == 0 || + strncasecmp(video_comp, "dmb1", 4)==0 ) + { + lav_fd->MJPG_chroma = CHROMA420; + lav_fd->interlacing = LAV_INTER_UNKNOWN; + lav_fd->is_MJPG = 1; + + /* Make some checks on the video source, we read the first frame for that */ + + ierr = 0; + frame = NULL; + + + int rolls = 5; // try to survive loading broken AVI + int pos = 0; + int success = 0; + while( pos < rolls ) { + if( frame != NULL ) { + free(frame); + frame = NULL; + } + + if( lav_set_video_position(lav_fd, pos ) ) { + pos++; + continue; + } + if( (len = lav_frame_size(lav_fd, pos )) <= 0 ) { + pos++; + continue; + } + + if( (frame = (unsigned char*) malloc(len)) == 0 ) { + ierr = ERROR_MALLOC; + break; + } + if( (lav_read_frame( lav_fd, frame ) <= 0 ) ) { + pos ++; + if( frame ) { free(frame);frame=NULL;} + continue; + } + if( scan_jpeg(frame,len,1) ) { + ierr = ERROR_JPEG; + if( frame ) { free(frame);frame=NULL;} + break; + } + + success = 1; + break; + } + + if(!success) { + goto ERREXIT; + } else { + lav_set_video_position( lav_fd, pos ); + } + + /* if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; + if ( (len = lav_frame_size(lav_fd,0)) <=0 ) goto ERREXIT; + if ( (frame = (unsigned char*) malloc(len)) == 0 ) { ierr=ERROR_MALLOC; goto ERREXIT; } + + if ( lav_read_frame(lav_fd,frame) <= 0 ) goto ERREXIT; + + if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; + if( scan_jpeg(frame, len, 1) ) { ierr=ERROR_JPEG; goto ERREXIT; } + + /* We have to look to the JPEG SOF marker for further information + The SOF marker has the following format: + + FF + C0 + len_hi + len_lo + data_precision + height_hi + height_lo + width_hi + width_lo + num_components + + And then 3 bytes for each component: + + Component id + H, V sampling factors (as nibbles) + Quantization table number + */ + + /* Check if the JPEG has the special 4:2:2 format needed for + some HW JPEG decompressors (the Iomega Buz, for example) */ + + ncomps = frame[jpeg_image_offset + 9]; + if(ncomps==3) + { + for(n=0;n<3;n++) + { + hf[n] = frame[jpeg_image_offset + 10 + 3*n + 1]>>4; + vf[n] = frame[jpeg_image_offset + 10 + 3*n + 1]&0xf; + } + + /* Identify chroma sub-sampling format only 420 and 422 supported + at present...*/ + + + if( hf[0] == 2*hf[1] && hf[0] == 2*hf[2] ) + { + if( vf[0] == vf[1] && vf[0] == vf[2] ) + { + lav_fd->MJPG_chroma = CHROMA422; + } + else if( vf[0] == 2*vf[1] && vf[0] == 2*vf[2] ) + { + lav_fd->MJPG_chroma = CHROMA420; + } + else + { lav_fd->MJPG_chroma = CHROMAUNKNOWN; + } + } + else + { + lav_fd->MJPG_chroma = CHROMAUNKNOWN; + } + } // ncomps + /* Check if video is interlaced */ + + /* height and width are encoded in the JPEG SOF marker at offsets 5 and 7 */ + + jpg_height = get_int2(frame + jpeg_image_offset + 5); + jpg_width = get_int2(frame + jpeg_image_offset + 7); + + if( strncasecmp( frame + 6, "LAVC", 4 ) == 0 ) { + int pf = detect_pixel_format_with_ffmpeg( filename ); + switch(pf) { + case PIX_FMT_YUV422P: lav_fd->MJPG_chroma = CHROMA422;break; + case PIX_FMT_YUVJ422P:lav_fd->MJPG_chroma = CHROMA422F;break; + case PIX_FMT_YUV420P: lav_fd->MJPG_chroma = CHROMA420;break; + case PIX_FMT_YUVJ420P: lav_fd->MJPG_chroma = CHROMA420F;break; + case PIX_FMT_YUV444P: lav_fd->MJPG_chroma = CHROMA444;break; + default: + pf = -1; + break; + } + if( pf >= 0 ) { + lav_fd->interlacing = LAV_NOT_INTERLACED; + if(frame) free(frame); + return lav_fd; + } + } + + /* check height */ + + if( jpg_height == lav_video_height(lav_fd)) + { + lav_fd->interlacing = LAV_NOT_INTERLACED; + } + else if ( jpg_height == lav_video_height(lav_fd)/2 ) + { + + /* Video is interlaced */ + if(lav_fd->format == 'a') + { + /* Check the APP0 Marker, if present */ + + if(jpeg_app0_offset && + get_int2(frame + jpeg_app0_offset + 2) >= 5 && + strncasecmp((char*)(frame + jpeg_app0_offset + 4),"AVI1",4)==0 ) + { + if (frame[jpeg_app0_offset+8]==1) + { + lav_fd->interlacing = LAV_INTER_TOP_FIRST; + } + else + { + lav_fd->interlacing = LAV_INTER_BOTTOM_FIRST; + } + } + else + { + /* There is no default, it really depends on the + application which produced the AVI */ + lav_fd->interlacing = LAV_INTER_UNKNOWN; + } + lav_fd->format = lav_fd->interlacing == LAV_INTER_BOTTOM_FIRST ? 'A' : 'a'; + } // end of interlaced + } + else + { + ierr=ERROR_JPEG; + goto ERREXIT; + } + + if(frame) free(frame); + + return lav_fd; + } + + ierr = ERROR_FORMAT; + veejay_msg(VEEJAY_MSG_ERROR, "Unrecognized format '%s'", video_comp); + +ERREXIT: + lav_close(lav_fd); + if(frame) free(frame); + internal_error = ierr; + veejay_msg(VEEJAY_MSG_ERROR, "%s", lav_strerror()); + return 0; +} + +/* Get size of first field of for a data array containing + (possibly) two jpeg fields */ + +int lav_get_field_size(uint8_t * jpegdata, long jpeglen) +{ + int res; + + res = scan_jpeg(jpegdata,jpeglen,0); + if(res<0) return jpeglen; /* Better than nothing */ + + /* we return jpeg_padded len since this routine is used + for field exchange where alignment might be important */ + + return jpeg_padded_len; +} + +static char error_string[4096]; + +const char *lav_strerror(void) +{ + + switch(internal_error) + { + case ERROR_JPEG: + sprintf(error_string,"Internal: broken JPEG format"); + internal_error = 0; + return error_string; + case ERROR_MALLOC: + sprintf(error_string,"Internal: Out of memory"); + internal_error = 0; + return error_string; + case ERROR_FORMAT: + sprintf(error_string,"Input file format not recognized"); + internal_error = 0; + return error_string; + case ERROR_NOAUDIO: + sprintf(error_string,"Trying to read audio from a video only file"); + internal_error = 0; + return error_string; + } + + switch(video_format) + { + case 'a': + case 'A': + case 'Y': + case 'v': + case 'V': + case 'M': + case 'P': + case 'L': + case 'D': + return AVI_strerror(); + default: + /* No or unknown video format */ + if(errno) strerror(errno); + else sprintf(error_string,"No or unknown video format"); + return error_string; + } +} + + +/* +static int check_DV2_input(lav_file_t *lav_fd) +{ + int ierr = 0; + double len = 0; + unsigned char *frame = NULL; + + lav_fd->is_MJPG = 0; + + + if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; + if ( (len = lav_frame_size(lav_fd,0)) <=0 ) goto ERREXIT; + if ( (frame = (unsigned char*) malloc(len)) == 0 ) { ierr=ERROR_MALLOC; goto ERREXIT; } + + if ( lav_read_frame(lav_fd,frame) <= 0 ) goto ERREXIT; + { + dv_decoder_t *decoder = dv_decoder_new(0,0,0); + dv_parse_header(decoder, frame); + + switch (decoder->system) { + case e_dv_system_525_60: + if (dv_format_wide(decoder)) { + lav_fd->sar_w = 40; + lav_fd->sar_h = 33; + } else { + lav_fd->sar_w = 10; + lav_fd->sar_h = 11; + } + break; + case e_dv_system_625_50: + if (dv_format_wide(decoder)) { + lav_fd->sar_w = 118; + lav_fd->sar_h = 81; + } else { + lav_fd->sar_w = 59; + lav_fd->sar_h = 54; + } + break; + default: + lav_fd->sar_w = 0; + lav_fd->sar_h = 0; + break; + } + veejay_msg(VEEJAY_MSG_DEBUG, "DV System %s (sar w %d sar h %d)", + (decoder->system == e_dv_system_525_60 ? "525-60" : ( decoder->system == e_dv_system_625_50 ? "625-50" : "unknown!")),lav_fd->sar_w,lav_fd->sar_h); + dv_decoder_free(decoder); + } + + if ( lav_set_video_position(lav_fd,0) ) goto ERREXIT; + return 0; + +ERREXIT: + lav_close(lav_fd); + if(frame) free(frame); + if (ierr) internal_error = ierr; + return 1; +} + +*/ + +int lav_fileno(lav_file_t *lav_file) +{ + int res; + + video_format = lav_file->format; + + switch(lav_file->format) + { +#ifdef HAVE_LIBQUICKTIME + case 'q': + case 'Q': + { +#if ( LQT_CODEC_API_VERSION & 0xffff ) > 6 + res = lqt_fileno( (quicktime_t*) lav_file->qt_fd ); +#else + quicktime_t *q = lav_file->qt_fd; + res = (int) fileno( (quicktime_t*) q->stream ); +#endif + } + break; +#endif + default: + res = AVI_fileno(lav_file->avi_fd); + } + + return res; +} + +/* We need this to reorder the 32 bit values for big endian systems */ +uint32_t reorder_32(uint32_t todo, int big_endian) +{ + unsigned char b0, b1, b2, b3; + unsigned long reversed; + + if( big_endian ) + { + b0 = (todo & 0x000000FF); + b1 = (todo & 0x0000FF00) >> 8; + b2 = (todo & 0x00FF0000) >> 16; + b3 = (todo & 0xFF000000) >> 24; + + reversed = (b0 << 24) + (b1 << 16) + (b2 << 8) +b3; + return reversed; + } + return todo; +} +int lav_detect_endian (void) +{ + unsigned int fred; + char *pfred; + + fred = 2 | (1 << (sizeof(int)*8-8)); + pfred = (char *)&fred; + + if (*pfred == 1) + return 1; + else if(*pfred == 2) + return 0; + else + return -1; +} + + + + + + + + + + + + + diff --git a/branches/V-1.5.3/veejay-server/libel/lav_io.h b/branches/V-1.5.3/veejay-server/libel/lav_io.h new file mode 100644 index 00000000..55a7d655 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/lav_io.h @@ -0,0 +1,122 @@ +/* + 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. +*/ + +#ifndef LAV_IO_H +#define LAV_IO_H + +#include +#include +#include +#ifdef SUPPORT_READ_DV2 +#include +#endif +// play with mlt here, avformat producer/several consumers (we can write to) +// for normalized output (720x576/480) , dv1394 capture and playback + +#include + +#define LAV_INTER_UNKNOWN Y4M_UNKNOWN +#define LAV_NOT_INTERLACED Y4M_ILACE_NONE +#define LAV_INTER_TOP_FIRST Y4M_ILACE_TOP_FIRST +#define LAV_INTER_BOTTOM_FIRST Y4M_ILACE_BOTTOM_FIRST + + +/* chroma_format */ +#define CHROMAUNKNOWN 0 +#define CHROMA420 1 +#define CHROMA422 2 +#define CHROMA444 3 +#define CHROMA411 4 +#define CHROMA420F 5 +#define CHROMA422F 6 + +/* raw data format of a single frame */ +#define DATAFORMAT_MJPG 0 +#define DATAFORMAT_DV2 1 +#define DATAFORMAT_YUV420 2 +#define DATAFORMAT_YUV422 3 +#define DATAFORMAT_DIVX 4 +#define DATAFORMAT_MPEG4 5 + +typedef struct +{ + avi_t *avi_fd; +#ifdef SUPPORT_READ_DV2 + dv_t *dv_fd; +#endif + void *qt_fd; + int jpeg_fd; + char *jpeg_filename; +#ifdef USE_GDK_PIXBUF + void *picture; +#endif + int format; + int interlacing; + int sar_w; /* "clip aspect ratio" width */ + int sar_h; /* "clip aspect ratio" height */ + int has_audio; + int bps; + int is_MJPG; + int MJPG_chroma; + int mmap_size; + int bogus_len; +} lav_file_t; + + +int lav_detect_endian (void); +int lav_query_APP_marker(char format); +int lav_query_APP_length(char format); +int lav_query_polarity(char format); +lav_file_t *lav_open_output_file(char *filename, char format, + int width, int height, int interlaced, double fps, + int asize, int achans, long arate); +int lav_close(lav_file_t *lav_file); +int lav_write_frame(lav_file_t *lav_file, uint8_t *buff, long size, long count); +int lav_write_audio(lav_file_t *lav_file, uint8_t *buff, long samps); +long lav_video_frames(lav_file_t *lav_file); +int lav_video_width(lav_file_t *lav_file); +int lav_video_height(lav_file_t *lav_file); +double lav_frame_rate(lav_file_t *lav_file); +int lav_video_interlacing(lav_file_t *lav_file); +void lav_video_clipaspect(lav_file_t *lav_file, int *sar_w, int *sar_h); +int lav_video_is_MJPG(lav_file_t *lav_file); +int lav_is_DV(lav_file_t *lav_file); +int lav_video_MJPG_chroma(lav_file_t *lav_file); +const char *lav_video_compressor(lav_file_t *lav_file); +int lav_video_compressor_type(lav_file_t *lav_file); +int lav_audio_channels(lav_file_t *lav_file); +int lav_audio_bits(lav_file_t *lav_file); +long lav_audio_rate(lav_file_t *lav_file); +long lav_audio_clips(lav_file_t *lav_file); +long lav_frame_size(lav_file_t *lav_file, long frame); +int lav_seek_start(lav_file_t *lav_file); +int lav_set_video_position(lav_file_t *lav_file, long frame); +int lav_read_frame(lav_file_t *lav_file, uint8_t *vidbuf); +int lav_set_audio_position(lav_file_t *lav_file, long clip); +int lav_read_audio(lav_file_t *lav_file, uint8_t *audbuf, long samps); +int lav_filetype(lav_file_t *lav_file); +lav_file_t *lav_open_input_file(char *filename, int mmap_size); +int lav_get_field_size(uint8_t * jpegdata, long jpeglen); +const char *lav_strerror(void); +int lav_fileno( lav_file_t *lav_file ); +void lav_set_default_chroma(int c); +int lav_bogus_video_length( lav_file_t *lav_file ); +void lav_bogus_set_length( lav_file_t *lav_file , int len ); +#ifdef USE_GDK_PIXBUF +VJFrame *lav_get_frame_ptr( lav_file_t *lav_file ); +void lav_set_project( int w, int h, float fps, int shift ); +#endif +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/pixbuf.c b/branches/V-1.5.3/veejay-server/libel/pixbuf.c new file mode 100644 index 00000000..9d146969 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/pixbuf.c @@ -0,0 +1,480 @@ +/* veejay - Linux VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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 +#ifdef USE_GDK_PIXBUF +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#define RUP8(num)(((num)+8)&~8) + +typedef struct +{ + char *filename; + VJFrame *picA; + VJFrame *picB; + VJFrame *img; + uint8_t *space; + int display_w; + int display_h; + int real_w; + int real_h; + int fmt; +} vj_pixbuf_t; + + +typedef struct +{ + char *filename; + char *type; + int out_w; + int out_h; +} vj_pixbuf_out_t; + +static int __initialized = 0; + +extern int get_ffmpeg_pixfmt(int id); + +extern uint8_t *vj_perform_get_preview_buffer(); + +static VJFrame *open_pixbuf( const char *filename, int dst_w, int dst_h, int dst_fmt, + uint8_t *dY, uint8_t *dU, uint8_t *dV ) +{ +#ifdef USE_GDK_PIXBUF + GdkPixbuf *image = + gdk_pixbuf_new_from_file( filename, NULL ); + if(!image) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to load image '%s'", filename); + return NULL; + } + + /* convert image to veejay frame in proper dimensions, free image */ + + int img_fmt = PIX_FMT_RGB24; + if( gdk_pixbuf_get_has_alpha( image )) + img_fmt = PIX_FMT_RGBA; + + VJFrame *dst = yuv_yuv_template( dY, dU, dV, dst_w, dst_h, dst_fmt ); + VJFrame *src = yuv_rgb_template( + (uint8_t*) gdk_pixbuf_get_pixels( image ), + gdk_pixbuf_get_width( image ), + gdk_pixbuf_get_height( image ), + img_fmt // PIX_FMT_RGB24 + ); + int stride = gdk_pixbuf_get_rowstride(image); + + if( stride != src->stride[0] ) + src->stride[0] = stride; + + veejay_msg(VEEJAY_MSG_DEBUG,"Image is %dx%d (src=%d, stride=%d, dstfmt=%d), scaling to %dx%d", + src->width,src->height,img_fmt, stride,dst_fmt,dst->width,dst->height ); + + yuv_convert_any_ac( src, dst, src->format, dst->format ); + + gdk_pixbuf_unref( image ); + + free(src); + + + return dst; +#else + + return NULL; +#endif +} + +void vj_picture_cleanup( void *pic ) +{ + vj_pixbuf_t *picture = ( vj_pixbuf_t*) pic; + if(picture) + { + if( picture->filename ) + free(picture->filename ); + if(picture->img) + free( picture->img ); + if(picture->space) + free(picture->space); + if( picture ) + free(picture); + } + picture = NULL; +} + + +VJFrame *vj_picture_get(void *pic) +{ + if(!pic) + return NULL; + vj_pixbuf_t *picture = (vj_pixbuf_t*) pic; + return picture->img; +} + +int vj_picture_get_height( void *pic ) +{ + vj_pixbuf_t *picture = (vj_pixbuf_t*) pic; + if(!picture) + return 0; + return picture->real_h; +} + +int vj_picture_get_width( void *pic ) +{ + vj_pixbuf_t *picture = (vj_pixbuf_t*) pic; + if(!picture) + return 0; + return picture->real_w; +} + +void *vj_picture_open( const char *filename, int v_outw, int v_outh, int v_outf ) +{ +#ifdef USE_GDK_PIXBUF + vj_pixbuf_t *pic = NULL; + if(filename == NULL ) + { + veejay_msg(0, "No image filename given"); + return NULL; + } + + if(v_outw <= 0 || v_outh <= 0 ) + { + veejay_msg(0, "No image dimensions setup"); + return NULL; + } + + pic = (vj_pixbuf_t*) vj_calloc(sizeof(vj_pixbuf_t)); + if(!pic) + { + veejay_msg(0, "Memory allocation error in %s", __FUNCTION__ ); + return NULL; + } + pic->filename = strdup( filename ); + pic->display_w = v_outw; + pic->display_h = v_outh; + pic->fmt = v_outf; + + int len = v_outw * v_outh; + int ulen = len; + switch( v_outf ) + { + case PIX_FMT_YUV420P: + case PIX_FMT_YUVJ420P: + ulen = len / 4; + break; + case PIX_FMT_YUV422P: + case PIX_FMT_YUVJ422P: + ulen = len / 2; + break; + default: +#ifdef STRICT_CHECKING + assert(0); +#endif + break; + } + + pic->space = (uint8_t*) vj_malloc( sizeof(uint8_t) * (3 * len)); +#ifdef STRICT_CHECKING + assert(pic->space != NULL ); +#endif + pic->img = open_pixbuf( + filename, + v_outw, + v_outh, + v_outf, + pic->space, + pic->space + len, + pic->space + len + ulen ); + if(!pic->img) { + free(pic->space); + return NULL; + } + + return (void*) pic; +#else + return NULL; +#endif +} + +int vj_picture_probe( const char *filename ) +{ + int ret = 0; +#ifdef USE_GDK_PIXBUF + GdkPixbuf *image = + gdk_pixbuf_new_from_file( filename, NULL ); + if(image) + { + ret = 1; + gdk_pixbuf_unref( image ); + } +#endif + return ret; +} + +/* image saving */ +#ifdef USE_GDK_PIXBUF +static void add_if_writeable( GdkPixbufFormat *data, GSList **list) +{ + if( gdk_pixbuf_format_is_writable( data )) + *list = g_slist_prepend( *list, data ); + gchar *name = gdk_pixbuf_format_get_name( data ); + if(name) g_free(name); +} +#endif +char *vj_picture_get_filename( void *pic ) +{ + vj_pixbuf_out_t *p = (vj_pixbuf_out_t*) pic; + if(!p) return NULL; + return p->filename; +} + +void * vj_picture_prepare_save( + const char *filename, char *type, int out_w, int out_h) +{ +#ifdef USE_GDK_PIXBUF + if(!type || !filename ) + { + veejay_msg(0, "Missing filename or file extension"); + return NULL; + } + + vj_pixbuf_out_t *pic = (vj_pixbuf_out_t*) vj_calloc(sizeof(vj_pixbuf_out_t)); + + if(!pic) + return NULL; + + if(filename) + pic->filename = strdup( filename ); + else + pic->filename = NULL; + + if(strncasecmp(type,"jpg",3 ) == 0) + pic->type = strdup("jpeg"); + else + pic->type = strdup( type ); + + pic->out_w = out_w; + pic->out_h = out_h; + + return (void*) pic; +#else + return NULL; +#endif +} + + +#ifdef USE_GDK_PIXBUF +//static void display_if_writeable( GdkPixbufFormat *data, GSList **list) +static void display_if_writeable( gpointer a, gpointer b ) +{ + GdkPixbufFormat *data = (GdkPixbufFormat*) a; + GSList **list = (GSList**) b; + if( gdk_pixbuf_format_is_writable( data )) + *list = g_slist_prepend( *list, data ); + gchar *name = gdk_pixbuf_format_get_name( data ); + if( name ) g_free(name); +} +void vj_picture_display_formats() +{ + GSList *f = gdk_pixbuf_get_formats(); + GSList *res = NULL; + + g_slist_foreach( f, display_if_writeable, &res); + + g_slist_free( f ); + g_slist_free( res ); +} +#endif +static void vj_picture_out_cleanup( vj_pixbuf_out_t *pic ) +{ + if(pic) + { + if(pic->filename) + free(pic->filename); + if(pic->type) + free(pic->type); + free(pic); + } + pic = NULL; +} + +static void *pic_scaler_ = NULL; +static int pic_data_[3] = { 0,0,0}; +static int pic_changed_ = 0; +static sws_template *pic_template_ = NULL; + +void vj_picture_init( void *templ ) +{ + if(!__initialized) + { + // cool stuff +#ifdef USE_GDK_PIXBUF + g_type_init(); + veejay_msg(VEEJAY_MSG_DEBUG, "Using gdk pixbuf %s", gdk_pixbuf_version ); +#endif + __initialized = 1; + } + + pic_template_ = (sws_template*) templ; + pic_template_->flags = yuv_which_scaler(); +} + +int vj_picture_save( void *picture, uint8_t **frame, int w, int h , int fmt ) +{ + int ret = 0; +#ifdef USE_GDK_PIXBUF + vj_pixbuf_out_t *pic = (vj_pixbuf_out_t*) picture; + GdkPixbuf *img_ = gdk_pixbuf_new( GDK_COLORSPACE_RGB, FALSE, 8, w, h ); + + if(!img_) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cant allocate buffer for RGB"); + return 0; + } + + // convert frame to yuv + VJFrame *src = yuv_yuv_template( frame[0],frame[1],frame[2],w,h,fmt ); + VJFrame *dst = yuv_rgb_template( + (uint8_t*) gdk_pixbuf_get_pixels( img_ ), + gdk_pixbuf_get_width( img_ ), + gdk_pixbuf_get_height( img_ ), + PIX_FMT_BGR24 + ); + + yuv_convert_any_ac( src, dst, src->format, dst->format ); + + if( gdk_pixbuf_savev( img_, pic->filename, pic->type, NULL,NULL,NULL)) + { + veejay_msg(VEEJAY_MSG_INFO, "Save frame as %s of type %s", + pic->filename, pic->type ); + ret = 1; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, + "Cant save file as %s (%s) size %d x %d", pic->filename,pic->type, pic->out_w, pic->out_h); + } + + if( img_ ) + gdk_pixbuf_unref( img_ ); + + free(src); + free(dst); + + vj_picture_out_cleanup( pic ); +#endif + return ret; +} + +void vj_picture_free() +{ + +} + +#define pic_has_changed(a,b,c) ( (a == pic_data_[0] && b == pic_data_[1] && c == pic_data_[2] ) ? 0: 1) +#define update_pic_data(a,b,c) { pic_data_[0] = a; pic_data_[1] = b; pic_data_[2] = c;} + +void vj_fast_picture_save_to_mem( VJFrame *frame, int out_w, int out_h, int pixfmt ) +{ + VJFrame *src1 = yuv_yuv_template( frame->data[0],frame->data[1],frame->data[2], + frame->width,frame->height, pixfmt ); + + uint8_t *dest[3]; + dest[0] = vj_perform_get_preview_buffer(); + dest[1] = dest[0] + (out_w * out_h); + dest[2] = dest[1] + ( (out_w * out_h)/4 ); + + + int dst_fmt = (pixfmt == PIX_FMT_YUVJ420P || pixfmt == PIX_FMT_YUVJ422P ? PIX_FMT_YUVJ420P : PIX_FMT_YUV420P ); + VJFrame *dst1 = yuv_yuv_template( dest[0], dest[1], dest[2], out_w, out_h, dst_fmt ); + + pic_changed_ = pic_has_changed( out_w,out_h, pixfmt ); + + if(pic_changed_ || pic_scaler_ == NULL ) + { + if(pic_scaler_) + yuv_free_swscaler( pic_scaler_ ); + pic_scaler_ = yuv_init_swscaler( src1,dst1, pic_template_, yuv_sws_get_cpu_flags()); +#ifdef STRICT_CHECKING + assert( pic_scaler_ != NULL ); +#endif + update_pic_data( out_w, out_h, pixfmt ); + + veejay_memset( dest[0], 0, out_w*out_h); + veejay_memset( dest[1], 128, (out_w*out_h)/4); + veejay_memset( dest[2], 128, (out_w*out_h)/4); + } + +// if( frame->width == out_w && frame->height == out_h ) +// yuv_convert_any_ac( src1, dst1, src1->format, dst1->format ); +// else + yuv_convert_and_scale( pic_scaler_, src1,dst1); + + free(src1); + free(dst1); +} + +void vj_fastbw_picture_save_to_mem( VJFrame *frame, int out_w, int out_h, int pixfmt ) +{ + VJFrame *src1 = yuv_yuv_template( frame->data[0],frame->data[1],frame->data[2], + frame->width,frame->height, pixfmt ); + + uint8_t *planes[3]; + + planes[0] = vj_perform_get_preview_buffer(); + planes[1] = planes[0] + (out_w * out_h ); + planes[2] = planes[1] + (out_w * out_h ); + + VJFrame *dst1 = yuv_yuv_template( planes[0], planes[1], planes[2], + out_w , out_h, PIX_FMT_GRAY8 ); + pic_changed_ = pic_has_changed( out_w,out_h, pixfmt ); + + if(pic_changed_ ) + { + if(pic_scaler_) + yuv_free_swscaler( pic_scaler_ ); + pic_scaler_ = yuv_init_swscaler( src1,dst1, pic_template_, yuv_sws_get_cpu_flags()); + update_pic_data( out_w, out_h, pixfmt ); + } + + + if( frame->width == out_w && frame->height == out_h ) + yuv_convert_any_ac( src1,dst1,src1->format, dst1->format ); + else + yuv_convert_and_scale( pic_scaler_, src1, dst1); + + free(src1); + free(dst1); +} + diff --git a/branches/V-1.5.3/veejay-server/libel/pixbuf.h b/branches/V-1.5.3/veejay-server/libel/pixbuf.h new file mode 100644 index 00000000..493b8be5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/pixbuf.h @@ -0,0 +1,53 @@ +/* veejay - Linux VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_PIXBUF_H +#define VJ_PIXBUF_H +#include +#include +typedef struct +{ + int w; + int h; +} veejay_image_t; + +#ifdef USE_GDK_PIXBUF +void vj_picture_init(void *templ); +void vj_picture_cleanup( void *pic ); +VJFrame *vj_picture_get( void *pic ); +int vj_picture_probe( const char *filename ); +void *vj_picture_open( const char *filename, int v_outw, int v_outh, int v_outf ); +int vj_picture_get_width(void *pic); +int vj_picture_get_height(void *pic); +void vj_picture_display_formats(void); +char *vj_picture_get_filename( void *pic ); +void * vj_picture_prepare_save( const char *filename, char *type, int out_w, int out_h); +int vj_picture_save( void *picture, uint8_t **frame, int w, int h , int fmt ); +void vj_picture_display_formats(void); + +veejay_image_t *vj_picture_save_bw_to_memory( uint8_t **frame, int w, int h , int out_w, int out_h, int fmt ); +veejay_image_t *vj_picture_save_to_memory( uint8_t **frame, int w, int h , int out_w, int out_h, int fmt ); +void vj_fastbw_picture_save_to_mem( VJFrame *f, int out_w, int out_h, int fmt ); +void vj_fast_picture_save_to_mem(VJFrame *f, int out_w, int out_h, int fmt ); + +void vj_picture_free(); + +#endif + + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/rawdv.c b/branches/V-1.5.3/veejay-server/libel/rawdv.c new file mode 100644 index 00000000..429e50b5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/rawdv.c @@ -0,0 +1,330 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#ifdef SUPPORT_READ_DV2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#define DV_PAL_SIZE 144000 +#define DV_NTSC_SIZE 120000 + +static void rawdv_free(dv_t *dv) +{ + if(dv->filename) free(dv->filename); + if(dv->buf) free(dv->buf); + if(dv) free(dv); +} + +int rawdv_close(dv_t *dv) +{ + close(dv->fd); + mmap_free(dv->mmap_region); + rawdv_free( dv); + return 1; +} + +int rawdv_sampling(dv_t *dv) +{ + switch(dv->fmt) + { + case e_dv_sample_411: return 4; + case e_dv_sample_422: return 2; + case e_dv_sample_420: return 1; + } + return 3; +} + +#define DV_HEADER_SIZE 120000 +dv_t *rawdv_open_input_file(const char *filename, int mmap_size) +{ + dv_t *dv = (dv_t*) vj_malloc(sizeof(dv_t)); + if(!dv) return NULL; + memset(dv, 0, sizeof(dv_t)); + dv_decoder_t *decoder = NULL; + + uint8_t *tmp = (uint8_t*) vj_malloc(sizeof(uint8_t) * DV_HEADER_SIZE); + memset( tmp, 0, sizeof(uint8_t) * DV_HEADER_SIZE); + off_t file_size = 0; + int n = 0; + + decoder = dv_decoder_new( 1,0,0); + dv->fd = open( filename, O_RDONLY ); + + if(!dv->fd) + { + dv_decoder_free(decoder); + rawdv_free(dv); + veejay_msg(VEEJAY_MSG_ERROR, "Cannot open '%s'",filename); + if(tmp)free(tmp); + return NULL; + } + /* fseek sometimes lies about filesize - seek to end (lseek returns file offset from start)*/ + file_size = lseek( dv->fd, 0, SEEK_END ); + if( file_size < DV_HEADER_SIZE) + { + dv_decoder_free(decoder); + veejay_msg(VEEJAY_MSG_ERROR, "% is too small! ", filename); + rawdv_free(dv); + if(tmp) free(tmp); + return NULL; + } + /* And back to start offset */ + if( lseek(dv->fd,0, SEEK_SET ) < 0) + { + dv_decoder_free(decoder); + veejay_msg(VEEJAY_MSG_ERROR, "Seek errror"); + rawdv_free(dv); + if(tmp) free(tmp); + return NULL; + } + + dv->mmap_region = NULL; + if( mmap_size > 0 ) // user wants mmap + { + dv->mmap_region = mmap_file( dv->fd, 0, (mmap_size * 720 * 576 * 3), + file_size ); + } + + if( dv->mmap_region == NULL ) + { + if(mmap_size>0) + veejay_msg(VEEJAY_MSG_DEBUG, "Mmap failed - fallback to read"); + n = read( dv->fd, tmp, DV_HEADER_SIZE ); + } + else + { + n = mmap_read( dv->mmap_region, 0, DV_HEADER_SIZE, tmp ); + } + + if( n <= 0 ) + { + dv_decoder_free(decoder); + rawdv_free(dv); + if(tmp) free(tmp); + veejay_msg(VEEJAY_MSG_ERROR, "Cannot read from '%s'", filename); + return NULL; + } + + if( dv_parse_header( decoder, tmp) < 0 ) + { + dv_decoder_free( decoder ); + rawdv_free(dv); + if(tmp) free(tmp); + veejay_msg(VEEJAY_MSG_ERROR, "Cannot parse header"); + return NULL; + } +/* if(decoder->sampling == e_dv_sample_411) + { + dv_decoder_free( decoder ); + rawdv_free(dv); + if(tmp) free(tmp); + return NULL; + }*/ + + + if(dv_is_PAL( decoder ) ) + dv->chunk_size = DV_PAL_SIZE; + else + dv->chunk_size = DV_NTSC_SIZE; + + dv->width = decoder->width; + dv->height = decoder->height; + dv->audio_rate = decoder->audio->frequency; + dv->audio_chans = decoder->audio->num_channels; + dv->audio_qbytes = decoder->audio->quantization; + dv->fps = ( dv_is_PAL( decoder) ? 25.0 : 29.97 ); + dv->size = decoder->frame_size; + dv->num_frames = (file_size - DV_HEADER_SIZE) / dv->size; + dv->fmt = decoder->sampling; +// dv->fmt = ( decoder->sampling == e_dv_sample_422 ? 1 : 0); + dv->buf = (uint8_t*) vj_malloc(sizeof(uint8_t*) * dv->size); + dv->offset = 0; + + veejay_msg(VEEJAY_MSG_DEBUG, + "DV properties %d x %d, %f, %d frames, %d sampling", + dv->width,dv->height, dv->fps, dv->num_frames, + dv->fmt ); + + dv_decoder_free( decoder ); + + if(tmp) + free(tmp); + +/* if(dv->audio_rate) + { + int i; + for( i = 0; i < 4; i ++ ) + dv->audio_buffers[i] = (int16_t*) vj_malloc(sizeof(int16_t) * 2 * DV_AUDIO_MAX_SAMPLES); + }*/ + +/* + veejay_msg(VEEJAY_MSG_DEBUG, + "rawDV: num frames %ld, dimensions %d x %d, at %2.2f in %s", + dv->num_frames, + dv->width, + dv->height, + dv->fps, + (dv->fmt==1?"422":"420")); + veejay_msg(VEEJAY_MSG_DEBUG, + "rawDV: frame size %d, rate %d, channels %d, bits %d", + dv->size, + dv->audio_rate, + dv->audio_chans, + dv->audio_qbytes);*/ + + return dv; +} + + +int rawdv_set_position(dv_t *dv, long nframe) +{ + off_t offset = nframe * dv->size; + + if(nframe <= 0 ) + offset = 0; + else + if(nframe > dv->num_frames) + offset = dv->num_frames * dv->size; + + dv->offset = offset; + + if( lseek( dv->fd, offset, SEEK_SET ) < 0 ) + return -1; + return 0; +} + +int rawdv_read_frame(dv_t *dv, uint8_t *buf ) +{ + int n = 0; + if(dv->mmap_region == NULL) + { + n = read( dv->fd, dv->buf, dv->size ); + memcpy( buf, dv->buf, dv->size ); + } + else + { + n = mmap_read( dv->mmap_region, dv->offset, dv->size, buf ); + } + return n; +} + +int rawdv_read_audio_frame(dv_t *dv, uint8_t *audio ) +{ + + return 0; +/* + int n = dv_decode_full_audio( dv->decoder, dv->buf, dv->audio_buffers ); + // interleave buffers to audio + int n_samples = dv_get_num_samples( dv->decoder ); + int n_chans = dv->audio_chans; + int16_t *ch0 = dv->audio_buffers[0]; + int16_t *ch1 = dv->audio_buffers[1]; + int i,j; + for( i = 0; i < n_samples; i ++ ) + { + *(audio) = *(ch0) & 0xff; + *(audio+1) = (*(ch0) << 8) & 0xff; + *(audio+2) = *(ch1) & 0xff; + *(audio+3) = (*(ch1)<<8) & 0xff; + *(ch0) ++; + *(ch1) ++; + *(audio) += 4; + } + return n_samples * 4; +*/ +} + +int rawdv_video_frames(dv_t *dv) +{ + return dv->num_frames; +} + +int rawdv_width(dv_t *dv) +{ + return dv->width; +} + +int rawdv_height(dv_t *dv) +{ + return dv->height; +} + +double rawdv_fps(dv_t *dv) +{ + return (double) dv->fps; +} + +int rawdv_compressor(dv_t *dv) +{ + return CODEC_ID_DVVIDEO; +} + +char *rawdv_video_compressor(dv_t *dv) +{ + char *res = "dvsd\0"; + return res; +} + +int rawdv_audio_channels(dv_t *dv) +{ + return dv->audio_chans; +} + +int rawdv_audio_bits(dv_t *dv) +{ + return dv->audio_qbytes; +} + +int rawdv_audio_format(dv_t *dv) +{ + // pcm wave format + return (0x0001); +} + +int rawdv_audio_rate(dv_t *dv) +{ + return dv->audio_rate; +} + +int rawdv_audio_bps(dv_t *dv) +{ + return 4; +} + +int rawdv_frame_size(dv_t *dv) +{ + return dv->size; +} + +int rawdv_interlacing(dv_t *dv) +{ + return 0; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/rawdv.h b/branches/V-1.5.3/veejay-server/libel/rawdv.h new file mode 100644 index 00000000..0b130c48 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/rawdv.h @@ -0,0 +1,67 @@ +#ifndef RAWDV_H +#define RAWDV_H +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +typedef struct +{ + int fd; + char *filename; + long num_frames; + int width; + int height; + float fps; + int chunk_size; + long audio_rate; + int audio_chans; + int audio_qbytes; + dv_decoder_t *decoder; + int16_t *audio_buffers[4]; + off_t offset; + uint8_t *buf; + int size; + int fmt; + mmap_region_t *mmap_region; +} dv_t; + +int rawdv_sampling(dv_t *dv); +int rawdv_close(dv_t *dv); +dv_t *rawdv_open_input_file(const char *filename, int mmap_size); +int rawdv_set_position(dv_t *dv, long nframe); +int rawdv_read_frame(dv_t *dv, uint8_t *buf ); +int rawdv_read_audio_frame(dv_t *dv, uint8_t *buf); +int rawdv_video_frames(dv_t *dv); +int rawdv_width(dv_t *dv); +int rawdv_height(dv_t *dv); +double rawdv_fps(dv_t *dv); +int rawdv_compressor(dv_t *dv); +char *rawdv_video_compressor(dv_t *dv); +int rawdv_audio_channels(dv_t *dv); +int rawdv_audio_bits(dv_t *dv); +int rawdv_audio_format(dv_t *dv); +int rawdv_audio_rate(dv_t *dv); +int rawdv_audio_bps(dv_t *dv); +int rawdv_frame_size(dv_t *dv); +int rawdv_interlacing(dv_t *dv); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/vj-avcodec.c b/branches/V-1.5.3/veejay-server/libel/vj-avcodec.c new file mode 100644 index 00000000..8959384c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-avcodec.c @@ -0,0 +1,671 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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 +#ifdef SUPPORT_READ_DV2 +#define __FALLBACK_LIBDV +#include +#endif +#include +#include + + + +//#define YUV420_ONLY_CODEC(id) ( ( id == CODEC_ID_MJPEG || id == CODEC_ID_MJPEGB || id == CODEC_ID_MSMPEG4V3 || id == CODEC_ID_MPEG4) ? 1: 0) + +//#define YUV420_ONLY_CODEC(id) ( (id == CODEC_ID_MSMPEG4V3 || id == CODEC_ID_MPEG4 ) ? 1 : 0 ) + +static int YUV420_ONLY_CODEC(int id ) +{ + switch(id) { + // case CODEC_ID_MJPEG: + // case CODEC_ID_MJPEGB: + case CODEC_ID_MPEG4: + // case CODEC_ID_LJPEG: + case CODEC_ID_MSMPEG4V3: +// case CODEC_ID_SP5X: +// case CODEC_ID_THEORA: +// case CODEC_ID_H264:; + + return 1; + } + return 0; +} + +//from gst-ffmpeg, round up a number +#define GEN_MASK(x) ((1<<(x))-1) +#define ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x)) +#define ROUND_UP_2(x) ROUND_UP_X (x, 1) +#define ROUND_UP_4(x) ROUND_UP_X (x, 2) +#define ROUND_UP_8(x) ROUND_UP_X (x, 3) +#define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x)) + +static int out_pixel_format = FMT_422F; + +char* vj_avcodec_get_codec_name(int codec_id ) +{ + char name[20]; + switch(codec_id) + { + case CODEC_ID_MJPEG: sprintf(name, "MJPEG"); break; + case CODEC_ID_MPEG4: sprintf(name, "MPEG4"); break; + case CODEC_ID_MJPEGB: sprintf(name,"MJPEGB");break; + case CODEC_ID_MSMPEG4V3: sprintf(name, "DIVX"); break; + case CODEC_ID_DVVIDEO: sprintf(name, "DVVideo"); break; + case CODEC_ID_LJPEG: sprintf(name, "LJPEG" );break; + case CODEC_ID_SP5X: sprintf(name, "SP5x"); break; + case CODEC_ID_THEORA: sprintf(name,"Theora");break; + case CODEC_ID_H264: sprintf(name, "H264");break; + case 997 : sprintf(name, "RAW YUV 4:2:2 Planar JPEG"); break; + case 996 : sprintf(name, "RAW YUV 4:2:0 Planar JPEG"); break; + case 995 : sprintf(name, "YUV4MPEG Stream 4:2:2"); break; + case 994 : sprintf(name, "YUV4MPEG Stream 4:2:0"); break; + case 999 : sprintf(name, "RAW YUV 4:2:0 Planar"); break; + case 998 : sprintf(name, "RAW YUV 4:2:2 Planar"); break; + case 900 : sprintf(name, "LZO YUV 4:2:2 Planar"); break; + default: + sprintf(name, "Unknown"); break; + } + char *res = strdup(name); + return res; +} + +uint8_t *vj_avcodec_get_buf( vj_encoder *av ) +{ +#ifdef SUPPORT_READ_DV2 + vj_dv_encoder *dv = av->dv; + switch(av->encoder_id) { + case CODEC_ID_DVVIDEO: + return dv->dv_video; + } +#endif + return av->data[0]; +} + +static vj_encoder *vj_avcodec_new_encoder( int id, editlist *el, char *filename) +{ + vj_encoder *e = (vj_encoder*) vj_calloc(sizeof(vj_encoder)); + if(!e) return NULL; + + int pf = get_ffmpeg_pixfmt( out_pixel_format ); + +#ifdef SUPPORT_READ_DV2 + if( id == CODEC_ID_DVVIDEO ) + { + if(!is_dv_resolution(el->video_width, el->video_height )) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tVideo dimensions do not match required resolution"); + return NULL; + } + else + { + e->dv = (void*)vj_dv_init_encoder( (void*)el , out_pixel_format); + } + } + else { +#endif + e->data[0] = (uint8_t*) vj_calloc(sizeof(uint8_t) * el->video_width * el->video_height * 3 ); + e->data[1] = e->data[0] + el->video_width * el->video_height; + e->data[2] = e->data[1] + el->video_width * el->video_height /2; +#ifdef SUPPORT_READ_DV2 + } +#endif + + if( id == 900 ) + { + e->lzo = lzo_new(); + } + + if( id == 995 || id == 994) { + e->y4m = vj_yuv4mpeg_alloc(el, el->video_width, + el->video_height, + out_pixel_format ); + if( !e->y4m) { + veejay_msg(0, "Error while trying to setup Y4M stream, abort."); + return NULL; + } + + int chroma_val = Y4M_CHROMA_422; + if( id == 994 ) { + chroma_val = Y4M_CHROMA_420MPEG2; + } + + if( vj_yuv_stream_start_write( e->y4m, el,filename,chroma_val )== -1 ) + { + veejay_msg(0, "Unable to write header to YUV4MPEG stream"); + vj_yuv4mpeg_free( e->y4m ); + return NULL; + } + } + + if(id != 998 && id != 999 && id != 900 && id != 997 && id != 996 && id != 995 && id != 994) + { +#ifdef __FALLBACK_LIBDV + if(id != CODEC_ID_DVVIDEO) + { +#endif + e->codec = avcodec_find_encoder( id ); + if(!e->codec) + { + char *descr = vj_avcodec_get_codec_name(id); + veejay_msg(VEEJAY_MSG_ERROR, "Cannot find Encoder codec %s", descr ); + free(descr); + } +#ifdef __FALLBACK_LIBDV + } +#endif + + } + + if( id != 998 && id != 999 && id!= 900 && id != 997 && id != 996 && id != CODEC_ID_DVVIDEO && id != 995 && id != 994 ) + { +#ifdef __FALLBACK_LIBDV + if(id != CODEC_ID_DVVIDEO ) + { +#endif + e->context = avcodec_alloc_context(); + e->context->bit_rate = 2750 * 1024; + e->context->width = el->video_width; + e->context->height = el->video_height; +#if LIBAVCODEC_BUILD > 5010 + e->context->time_base = (AVRational) { 1, el->video_fps }; +#else + e->context->frame_rate = el->video_fps; + e->context->frame_rate_base = 1; +#endif + e->context->qcompress = 0.0; + e->context->qblur = 0.0; + e->context->max_b_frames = 0; + e->context->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + e->context->flags = CODEC_FLAG_QSCALE; + e->context->gop_size = 0; + e->context->sub_id = 0; + e->context->workaround_bugs = FF_BUG_AUTODETECT; + e->context->prediction_method = 0; + e->context->dct_algo = FF_DCT_AUTO; + + e->context->pix_fmt = get_ffmpeg_pixfmt( out_pixel_format ); + + if(YUV420_ONLY_CODEC(id)) + e->context->pix_fmt = ( out_pixel_format == FMT_422F ? PIX_FMT_YUVJ420P : PIX_FMT_YUV420P ); + + pf = e->context->pix_fmt; + + + char *descr = vj_avcodec_get_codec_name( id ); + if ( avcodec_open( e->context, e->codec ) < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot open codec '%s'" , descr ); + if(e->context) free(e->context); + if(e) free(e); + if(descr) free(descr); + return NULL; + } + else + { + veejay_msg(VEEJAY_MSG_DEBUG, "\tOpened encoder %s", descr ); + free(descr); + } +#ifdef __FALLBACK_LIBDV + } +#endif + } + + e->width = el->video_width; + e->height = el->video_height; + e->encoder_id = id; + + + switch(pf) { + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUV422P: + e->shift_y = 0; + e->shift_x = 1; + e->len = el->video_width * el->video_height; + e->uv_len = e->len / 2; + e->out_fmt = (pf == PIX_FMT_YUVJ422P ? FMT_422F : FMT_422 ); + break; + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUV420P: + e->shift_y = 1; + e->shift_x = 1; + e->len = el->video_width * el->video_height; + e->uv_len = e->len / 4; + e->out_fmt = (pf == PIX_FMT_YUVJ420P ? FMT_420F : FMT_420 ); + break; + } + + +/* + if( el->has_audio ) + { + e->audiocodec = avcodec_find_encoder( CODEC_ID_PCM_U8 ); + if(!e->audiocodec) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error initializing audio codec"); + if(e) free(e); + } + e->context->sample_rate = el->audio_rate; + e->context->channels = el->audio_chans; + if( avcodec_open( e->context, e->audiocodec ) < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot open audio context"); + if(e) free(e); + return NULL; + } + + } +*/ + return e; +} +void vj_avcodec_close_encoder( vj_encoder *av ) +{ + if(av) + { + if(av->context) + { + avcodec_close( av->context ); + free(av->context); + av->context = NULL; + } + if(av->data[0]) + free(av->data[0]); + if(av->lzo) + lzo_free(av->lzo); +#ifdef SUPPORT_READ_DV2 + if(av->dv) + vj_dv_free_encoder( (vj_dv_encoder*) av->dv ); +#endif + if(av->y4m) + vj_yuv4mpeg_free( (vj_yuv*) av->y4m ); + free(av); + } + av = NULL; +} + +int vj_avcodec_find_codec( int encoder ) +{ + switch( encoder) + { + case ENCODER_MJPEG: + case ENCODER_QUICKTIME_MJPEG: + return CODEC_ID_MJPEG; + case ENCODER_DVVIDEO: + case ENCODER_QUICKTIME_DV: + return CODEC_ID_DVVIDEO; + case ENCODER_MJPEGB: + return CODEC_ID_MJPEGB; + case ENCODER_LJPEG: + return CODEC_ID_LJPEG; + case ENCODER_YUV420: + return 999; + case ENCODER_YUV422: + return 998; + case ENCODER_YUV422F: + return 997; + case ENCODER_YUV420F: + return 996; + case ENCODER_MPEG4: + return CODEC_ID_MPEG4; + case ENCODER_DIVX: + return CODEC_ID_MSMPEG4V3; + case ENCODER_LZO: + return 900; + case ENCODER_YUV4MPEG: + return 995; + case ENCODER_YUV4MPEG420: + return 994; + default: + veejay_msg(VEEJAY_MSG_DEBUG, "Unknown format %d selected", encoder ); + return 0; + } + return 0; +} + +char vj_avcodec_find_lav( int encoder ) +{ + switch( encoder) + { + case ENCODER_MJPEG: + return 'a'; + case ENCODER_QUICKTIME_MJPEG: + return 'q'; + case ENCODER_DVVIDEO: + return 'd'; + case ENCODER_QUICKTIME_DV: + return 'Q'; + case ENCODER_MJPEGB: + return 'c'; + case ENCODER_LJPEG: + return 'l'; + case ENCODER_YUV420: + return 'Y'; + case ENCODER_YUV422: + return 'P'; + case ENCODER_YUV422F: + return 'V'; + case ENCODER_YUV420F: + return 'v'; + case ENCODER_MPEG4: + return 'M'; + case ENCODER_DIVX: + return 'D'; + case ENCODER_LZO: + return 'L'; + case ENCODER_YUV4MPEG: + case ENCODER_YUV4MPEG420: + return 'S'; + default: + veejay_msg(VEEJAY_MSG_DEBUG, "Unknown format %d selected", encoder ); + return 0; + } + return 0; +} + + +static struct { + const char *descr; + int encoder_id; +} encoder_names[] = { + { "Invalid codec", -1 }, + { "DV2", ENCODER_DVVIDEO }, + { "MJPEG", ENCODER_MJPEG }, + { "LJPEG", ENCODER_LJPEG }, + { "MJPEGB", ENCODER_MJPEGB }, + { "YUV 4:2:2 Planar, 0-255 full range", ENCODER_YUV422F }, + { "YUV 4:2:0 Planar, 0-255 full range", ENCODER_YUV420F }, + { "YUV 4:2:2 Planar, CCIR 601. 16-235/16-240", ENCODER_YUV422 }, + { "YUV 4:2:0 Planar, CCIR 601, 16-235/16-240", ENCODER_YUV420 }, + { "YUV 4:2:2 Planar, LZO compressed (experimental)", ENCODER_LZO }, + { "MPEG4", ENCODER_MPEG4 }, + { "DIVX", ENCODER_DIVX }, + { "Quicktime DV", ENCODER_QUICKTIME_DV }, + { "Quicktime MJPEG", ENCODER_QUICKTIME_MJPEG }, + { "YUV4MPEG Stream 4:2:2", ENCODER_YUV4MPEG }, + { "YUV4MPEG Stream 4:2:0 for MPEG2", ENCODER_YUV4MPEG420 }, + { NULL, 0 } +}; + +const char *vj_avcodec_get_encoder_name( int encoder_id ) +{ + int i; + for( i =1 ; encoder_names[i].descr != NULL ; i ++ ) { + if( encoder_names[i].encoder_id == encoder_id ) { + return encoder_names[i].descr; + } + } + return encoder_names[0].descr; +} + +int vj_avcodec_stop( void *encoder , int fmt) +{ + if(!encoder) + return 0; + vj_encoder *env = (vj_encoder*) encoder; + + if( fmt == 900 ) + { + return 1; + } + + vj_avcodec_close_encoder( env ); + encoder = NULL; + return 1; +} + +void *vj_avcodec_start( editlist *el, int encoder, char *filename ) +{ + int codec_id = vj_avcodec_find_codec( encoder ); + void *ee = NULL; +#ifndef SUPPORT_READ_DV2 + if( codec_id == CODEC_ID_DVVIDEO ) { + veejay_msg(VEEJAY_MSG_ERROR, "No support for DV encoding built in."); + return NULL; + } +#endif + ee = vj_avcodec_new_encoder( codec_id, el ,filename); + if(!ee) + { + veejay_msg(VEEJAY_MSG_ERROR, "\tFailed to start encoder %x",encoder); + return NULL; + } + return ee; +} + + +int vj_avcodec_init( int pixel_format, int verbose) +{ + out_pixel_format = pixel_format; +#ifndef STRICT_CHECKING + av_log_set_level( AV_LOG_QUIET); +#else + av_log_set_level( AV_LOG_VERBOSE ); +#endif + av_register_all(); + + return 1; +} + +int vj_avcodec_free() +{ + return 1; +} + +static void long2str(unsigned char *dst, int32_t n) +{ + dst[0] = (n )&0xff; + dst[1] = (n>> 8)&0xff; + dst[2] = (n>>16)&0xff; + dst[3] = (n>>24)&0xff; +} + + +static int vj_avcodec_lzo( vj_encoder *av, uint8_t *src[3], uint8_t *dst , int buf_len ) +{ + uint8_t *dstI = dst + (3 * 4); + int size1 = 0, size2=0,size3=0; + int i; + + i = lzo_compress( av->lzo, src[0], dstI, &size1 , av->len); + if( i == 0 ) + { + veejay_msg(0,"\tunable to compress Y plane"); + return 0; + } + dstI += size1; + + i = lzo_compress( av->lzo, src[1], dstI, &size2 , av->uv_len ); + if( i == 0 ) + { + veejay_msg(0,"\tunable to compress U plane"); + return 0; + } + + dstI += size2; + i = lzo_compress( av->lzo, src[2], dstI, &size3 , av->uv_len ); + if( i == 0 ) + { + veejay_msg(0,"\tunable to compress V plane"); + return 0; + } + + + long2str( dst, size1 ); + long2str( dst+4,size2); + long2str( dst+8,size3); + + return (size1 + size2 + size3 + 12); +} +static int vj_avcodec_copy_frame( vj_encoder *av, uint8_t *src[3], uint8_t *dst, int in_fmt ) +{ + if(!av) + { + veejay_msg(VEEJAY_MSG_ERROR, "No encoder !!"); + return 0; + } + + if( av->encoder_id == 999 ) + { + uint8_t *dest[3] = { dst, dst + (av->len), dst + (av->len + av->len/4) }; + veejay_memcpy( dest[0], src[0], av->len ); + yuv422to420planar( src,dest, av->width,av->height ); + + if(in_fmt == FMT_422F ) + { + yuv_scale_pixels_from_y( dest[0], av->len ); + yuv_scale_pixels_from_uv( dest[1], av->len/2 ); + } + + return ( av->len + (av->len/2) ); + } + if( av->encoder_id == 996 ) + { + uint8_t *dest[3] = { dst, dst + (av->len), dst + (av->len + av->len/4) }; + veejay_memcpy( dest[0], src[0], av->len ); + yuv422to420planar( src,dest, av->width,av->height ); + + if(in_fmt == FMT_422 ) + { + yuv_scale_pixels_from_ycbcr( dest[0], 16.0f,235.0f, av->len ); + yuv_scale_pixels_from_ycbcr( dest[1], 16.0f,240.0f, av->len/2 ); + } + + return ( av->len + (av->len/2) ); + } + + + if( av->encoder_id == 998 ) + { + uint8_t *dest[3] = { dst, dst + (av->len), dst + (av->len + av->uv_len) }; + + veejay_memcpy( dest[0], src[0],av->len ); + veejay_memcpy( dest[1], src[1],av->uv_len); + veejay_memcpy( dest[2], src[2],av->uv_len ); + + if(in_fmt == FMT_422F ) + { + yuv_scale_pixels_from_y( dest[0], av->len ); + yuv_scale_pixels_from_uv( dest[1], av->uv_len * 2 ); + } + + return ( av->len + av->len ); + } + + if( av->encoder_id == 997 ) + { + uint8_t *dest[3] = { dst, dst + (av->len), dst + (av->len + av->uv_len) }; + + veejay_memcpy( dest[0], src[0],av->len ); + veejay_memcpy( dest[1], src[1],av->uv_len); + veejay_memcpy( dest[2], src[2],av->uv_len ); + + if(in_fmt == FMT_422 ) + { + yuv_scale_pixels_from_ycbcr( dest[0], 16.0f,235.0f, av->len ); + yuv_scale_pixels_from_ycbcr( dest[1], 16.0f,240.0f, av->uv_len * 2 ); + } + + return ( av->len + av->len ); + } + + veejay_msg(VEEJAY_MSG_DEBUG, "Unknown encoder select: %d", av->encoder_id); + + return 0; +} + + + +int vj_avcodec_encode_frame(void *encoder, int nframe,int format, uint8_t *src[3], uint8_t *buf, int buf_len, + int in_fmt) +{ + vj_encoder *av = (vj_encoder*) encoder; + + if(format == ENCODER_LZO ) + return vj_avcodec_lzo( encoder, src, buf, buf_len ); + + if(format == ENCODER_YUV420 || format == ENCODER_YUV422 || format == ENCODER_YUV422F || format == ENCODER_YUV420F) // no compression, just copy + return vj_avcodec_copy_frame( encoder,src, buf, in_fmt ); + + if(format == ENCODER_YUV4MPEG || format == ENCODER_YUV4MPEG420 ) { + if( in_fmt == FMT_422 ) { + vj_yuv_put_frame( av->y4m, src ); + return ( av->width * av->height ) * 2; + } else { + yuv_scale_pixels_from_yuv( src,av->data,av->width*av->height); + vj_yuv_put_frame(av->y4m, av->data ); + return ( av->width * av->height ) * 2; + } + } + +#ifdef __FALLBACK_LIBDV + if(format == ENCODER_DVVIDEO || format == ENCODER_QUICKTIME_DV ) + { + vj_dv_encoder *dv = av->dv; + return vj_dv_encode_frame( dv,src ); + } +#endif + AVFrame pict; + int res=0; + int stride,h2,w2,size,size2,stride2; + veejay_memset( &pict, 0, sizeof(pict)); + + pict.quality = 1; + pict.pts = (int64_t)( (int64_t)nframe ); + pict.data[0] = src[0]; + pict.data[1] = src[1]; + pict.data[2] = src[2]; + + stride = ROUND_UP_4( av->width ); + h2 = ROUND_UP_X( av->height, av->shift_y ); + size = stride * h2; + w2 = DIV_ROUND_UP_X(av->width, av->shift_x); + stride2 = ROUND_UP_4( w2 ); + h2 = DIV_ROUND_UP_X(av->height, av->shift_y ); + size2 = stride2 * h2; + pict.linesize[0] = stride; + pict.linesize[1] = stride2; + pict.linesize[2] = stride2; + + if( YUV420_ONLY_CODEC(av->encoder_id)) { + veejay_memcpy( av->data[0], src[0], av->width * av->height); + yuv422to420planar(src , av->data, av->width,av->height ); + pict.data[0] = av->data[0]; + pict.data[1] = av->data[1]; + pict.data[2] = av->data[2]; + } + + return avcodec_encode_video( av->context, buf, buf_len, &pict ); +} + +int vj_avcodec_encode_audio( void *encoder, int format, uint8_t *src, uint8_t *dst, int len, int nsamples ) +{ + if(format == ENCODER_YUV420 || ENCODER_YUV422 == format) + return 0; + vj_encoder *av = encoder; + int ret = avcodec_encode_audio( av->context, src, len, nsamples ); + return ret; +} diff --git a/branches/V-1.5.3/veejay-server/libel/vj-avcodec.h b/branches/V-1.5.3/veejay-server/libel/vj-avcodec.h new file mode 100644 index 00000000..85d64de5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-avcodec.h @@ -0,0 +1,94 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_AVCODEC_H +#define VJ_AVCODEC_H +#include +#include "vj-el.h" + +#define ENCODER_MJPEG 0 +#define ENCODER_DVVIDEO 1 +#define ENCODER_DIVX 2 +#define ENCODER_MPEG4 3 +#define ENCODER_YUV420 4 +#define ENCODER_YUV422 5 +#define ENCODER_QUICKTIME_DV 6 +#define ENCODER_QUICKTIME_MJPEG 7 +#define ENCODER_LZO 8 +#define ENCODER_YUV420F 9 +#define ENCODER_YUV422F 10 +#define ENCODER_MJPEGB 11 +#define ENCODER_LJPEG 12 +#define ENCODER_YUV4MPEG 13 +#define ENCODER_YUV4MPEG420 14 +#define NUM_ENCODERS 15 + +typedef struct +{ + AVCodec *codec; + AVCodec *audiocodec; + AVFrame *frame; + AVCodecContext *context; + int out_fmt; + int uv_len; + int len; + int sub_sample; + int super_sample; + int encoder_id; + int width; + int height; + uint8_t *data[3]; + void *lzo; + int shift_y; + int shift_x; + void *dv; + void *y4m; +} vj_encoder; + +int vj_avcodec_init(int pix, int verbose); +char vj_avcodec_find_lav(int format); +int vj_avcodec_encode_frame(void *encoder,int nframe, int format, uint8_t *src[3], uint8_t *dst, int dst_len, int pixel_format); +uint8_t *vj_avcodec_get_buf( vj_encoder *av ); +const char *vj_avcodec_get_encoder_name(int encoder); +int vj_avcodec_free(); + +/* color space conversion routines, should go somewhere else someday + together with subsample.c/colorspace.c into some lib + */ + +void yuv_planar_to_rgb24(uint8_t *src[3], int fmt, uint8_t *dst, int w, int h ); + +// from yuv 4:2:0 planar to yuv 4:2:2 planar +int yuv420p_to_yuv422p( uint8_t *Y, uint8_t *Cb, uint8_t *Cr, uint8_t *dst[3], int w, int h ); + +void yuv422p_to_yuv420p2( uint8_t *src[3], uint8_t *dst[3], int w, int h, int f ); + +int yuv420p_to_yuv422p2( uint8_t *sY,uint8_t *sCb, uint8_t *sCr, uint8_t *dst[3], int w, int h ); + +void yuv422p_to_yuv420p3( uint8_t *src, uint8_t *dst[3], int w, int h); + +void *vj_avcodec_start( editlist *el, int encoder, char *filename ); + +int vj_avcodec_stop( void *encoder , int fmt); + +void vj_avcodec_close_encoder( vj_encoder *av ); + + +void yuv_scale_pixels_from_yuv_copy( uint8_t *plane, uint8_t *dst, float min, float max, int len ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/vj-dv.c b/branches/V-1.5.3/veejay-server/libel/vj-dv.c new file mode 100644 index 00000000..de3bf6a7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-dv.c @@ -0,0 +1,462 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +#ifdef SUPPORT_READ_DV2 +#include +#include +#include +#include +#include +#include +#include + +#define NTSC_W 720 +#define NTSC_H 480 +#define PAL_W 720 +#define PAL_H 576 +#define DV_PAL_SIZE 144000 +#define DV_NTSC_SIZE 120000 +#define DV_AUDIO_MAX_SAMPLES 1944 + +#ifdef STRICT_CHECKING +#include +#endif + +int is_dv_resolution(int w, int h) +{ + if( h == NTSC_H && w == NTSC_W ) + return 1; + if( h == PAL_H && w == PAL_W ) + return 1; + return 0; +} + +/* init the dv decoder and decode buffer*/ +vj_dv_decoder *vj_dv_decoder_init(int quality, int width, int height, int pixel_format) +{ + int dv_q = DV_QUALITY_COLOR; + vj_dv_decoder *d = (vj_dv_decoder*)vj_malloc(sizeof(vj_dv_decoder)); + if(!d) return NULL; + d->decoder = dv_decoder_new( 1,1,0 ); + if( quality == 0 ) + dv_q = DV_QUALITY_FASTEST; + if( quality == 1 ) + dv_q = DV_QUALITY_BEST; + + d->decoder->quality = dv_q; + d->dv_video = (uint8_t*) vj_malloc(sizeof(uint8_t) * width * height * 4); + memset( d->dv_video, 0, (width*height*4)); + d->fmt = pixel_format; + d->audio = 0; // audio off + return d; +} + +static sws_template dv_templ; + +/* init the dv encoder and encode buffer */ +vj_dv_encoder *vj_dv_init_encoder(void * edl, int pixel_format) +{ + editlist *el = (editlist*) edl; + vj_dv_encoder *e = (vj_dv_encoder*) vj_malloc(sizeof(vj_dv_encoder)); + if(!e) return NULL; + e->encoder = dv_encoder_new(0,0,0); + e->encoder->isPAL = (el->video_norm == 'p' ? 1 : 0); + e->encoder->is16x9 = (el->video_width / el->video_height >= 1.777 ? 1: 0); + e->encoder->vlc_encode_passes = 3; + e->encoder->static_qno = 0; + e->encoder->force_dct = DV_DCT_AUTO; + e->fmt = pixel_format; + e->buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * + el->video_width * el->video_height * 3 ); + e->dv_video = + (uint8_t *) vj_calloc(sizeof(uint8_t) * + (e->encoder->isPAL ? + DV_PAL_SIZE : DV_NTSC_SIZE)); + + veejay_memset(&dv_templ,0,sizeof(sws_template)); + dv_templ.flags = yuv_which_scaler(); + + e->scaler = NULL; + + return e; +} + + +/* encode frame to dv format, dv frame will be in output_buf */ +int vj_dv_encode_frame(vj_dv_encoder *encoder, uint8_t *input_buf[3]) +{ + + time_t now = time(NULL); + uint8_t *pixels[3]; + int w=0; int h = 0; + if (!input_buf) + return 0; + + // pixels[0] = (uint8_t *) encoder->dv_video; + + + pixels[0] = (uint8_t*) encoder->buffer; + + if (encoder->encoder->isPAL) { + h = PAL_H; + w = PAL_W; + } else { + h = NTSC_H; + w = NTSC_W; + } + + + + pixels[1] = NULL; + pixels[2] = NULL; + + int src_fmt = PIX_FMT_YUVJ422P; + if( encoder->fmt == FMT_422 ) + src_fmt = PIX_FMT_YUV422P; + + VJFrame *src = yuv_yuv_template( input_buf[0],input_buf[1],input_buf[2], + w,h, src_fmt ); + VJFrame *dst = yuv_yuv_template( encoder->buffer,NULL,NULL, + w,h, PIX_FMT_YUYV422); + + + if( encoder->scaler == NULL ) { + encoder->scaler = yuv_init_swscaler( src,dst,&dv_templ, yuv_sws_get_cpu_flags() ); + } + + yuv_convert_and_scale_packed( encoder->scaler, src,dst ); + +// if( encoder->fmt == FMT_422F ) { +// yuy2_scale_pixels_from_yuv( encoder->buffer, w * h ); + // } + + dv_encode_full_frame( encoder->encoder, pixels, e_dv_color_yuv,encoder->dv_video); + dv_encode_metadata(encoder->dv_video, encoder->encoder->isPAL,encoder->encoder->is16x9, &now, 0); + dv_encode_timecode(encoder->dv_video, encoder->encoder->isPAL, 0); + + free(src); + free(dst); + if(encoder->encoder->isPAL) + return DV_PAL_SIZE; + return DV_NTSC_SIZE; +} + + +void vj_dv_free_encoder(vj_dv_encoder *e) +{ + if(e) + { + if(e->encoder) + dv_encoder_free( e->encoder); + if(e->dv_video) + free(e->dv_video); + if(e->buffer) + free(e->buffer); + if(e->scaler) + yuv_free_swscaler(e->scaler); + free(e); + } +} + +void vj_dv_free_decoder(vj_dv_decoder *d) { + if(d->decoder) + dv_decoder_free( d->decoder ); + if(d->dv_video) + free(d->dv_video); + if(d) + free(d); +} + +void vj_dv_decoder_set_audio(vj_dv_decoder *d, int audio) +{ +} + +void vj_dv_decoder_get_audio(vj_dv_decoder *d, uint8_t *audio_buf) +{ + + if(!d->audio) return; + + int n_samples = dv_get_num_samples( d->decoder); +// int channels = dv_get_num_channels( d->decoder ); + int i; + int16_t *ch0 = d->audio_buffers[0]; + int16_t *ch1 = d->audio_buffers[1]; + // convert short to uint8_t, + // interleave audio into single buffer + for(i = 0; i < n_samples; i ++ ) + { + *(audio_buf) = ch0[i] & 0xff; //lo + *(audio_buf+1) = (ch0[i] >> 8) & 0xff; //hi + *(audio_buf+2) = ch1[i] & 0xff; //lo + *(audio_buf+3) = (ch1[i] >> 8) & 0xff; //hi + } + + +} +/* + * + lav_common - some general utility functionality used by multiple + lavtool utilities. + */ +static void frame_YUV422_to_planar_411(uint8_t **output, uint8_t *input, + int width, int height) +{ + int i, j, w4; + uint8_t *y, *cb, *cr; + + w4 = width/4; + y = output[0]; + cb = output[1]; + cr = output[2]; + + for (i=0; idecoder, input_buf) < 0) + { + veejay_msg(0, "Unable to read DV header"); + return -1; + } + if( d->decoder->system == e_dv_system_none ) + { + veejay_msg(0, "No valid PAL or NTSC video frame detected"); + return -1; + } + + char sampling[8]; + switch( d->decoder->sampling ) + { + case e_dv_sample_411: + sprintf(sampling , "4:1:1"); break; + case e_dv_sample_420: + sprintf(sampling, "4:2:0"); break; + case e_dv_sample_422: + sprintf(sampling, "4:2:2"); break; + case e_dv_sample_none: + veejay_msg(0 ,"No sampling format, cant handle this file (yet)"); + return -1; + default: + veejay_msg(0, "Unknown sampling format in DV file"); + return -1; + } + + veejay_msg( VEEJAY_MSG_DEBUG, "\tDetected DV sampling format %s", sampling ); + + if ( d->decoder->sampling == e_dv_sample_422 || d->decoder->sampling == e_dv_sample_411) + return FMT_422; + if( d->decoder->sampling == e_dv_sample_420 ) + return FMT_420; + return -1; +} + +int vj_dv_decode_frame(vj_dv_decoder *d, uint8_t * input_buf, uint8_t * Y, + uint8_t * Cb, uint8_t * Cr, int width, int height, int fmt) +{ + + int pitches[3]; + if (!input_buf) + return 0; + + if (dv_parse_header(d->decoder, input_buf) < 0) + { + veejay_msg(0, "Unable to read DV header"); + return 0; + } + + if( d->decoder->system == e_dv_system_none ) + { + veejay_msg(0, "No valid PAL or NTSC video frame detected"); + return 0; + } + + if( d->decoder->system == e_dv_system_625_50 ) + { + d->yuy2 = 0; + } + else + { + d->yuy2 = 1; + } + + + if (!((d->decoder->num_dif_seqs == 10) + || (d->decoder->num_dif_seqs == 12))) + { + veejay_msg(0, "Dont know how to handle %d dif seqs", + d->decoder->num_dif_seqs ); + return 0; + } +#ifdef STRICT_CHECKING +// if ( d->decoder->sampling == e_dv_sample_420 ) +// assert( d->fmt == FMT_420 || d->fmt == FMT_420F ); +// if ( d->decoder->sampling == e_dv_sample_422 ) +// assert( d->fmt == FMT_422 || d->fmt == FMT_422F ); +#endif + + if ( d->decoder->sampling == e_dv_sample_422 || d->decoder->sampling == + e_dv_sample_411 ) + { + pitches[0] = width * 2; + pitches[1] = 0; + pitches[2] = 0; + int offset = ( d->decoder->sampling == e_dv_sample_411 ? width /4 : width /2) * height; + uint8_t *frame[3] = { Y , Cb, Cr }; + uint8_t *pixels[3] = { d->dv_video, d->dv_video + (width * height), + d->dv_video + (width * height ) + offset }; + + dv_decode_full_frame(d->decoder, input_buf, + e_dv_color_yuv, pixels, pitches); + + //@ this works + VJFrame *src = yuv_yuv_template( d->dv_video, NULL,NULL,width,height,PIX_FMT_YUYV422 ); + VJFrame *dst = yuv_yuv_template( Y,Cb,Cr,width,height, + ( d->fmt == FMT_422 ? PIX_FMT_YUV422P : PIX_FMT_YUVJ422P ) ); + + yuv_convert_any_ac( src,dst, src->format,dst->format ); + free(src); + free(dst); + /* if(d->decoder->sampling == e_dv_sample_422 ) { + frame_YUV422_to_planar( frame, d->dv_video, width, height, 1); + else + frame_YUV422_to_planar_411( frame, d->dv_video, width, height );*/ + + return 1; + } else if( d->decoder->sampling == e_dv_sample_420 ) + { + //remove this + uint8_t *pixels[3]; + pixels[0] = d->dv_video; + pixels[1] = d->dv_video + (width * height); + pixels[2] = d->dv_video + (width * height * 5)/4; + pitches[0] = width * 2; + pitches[1] = 0; + pitches[2] = 0; + + dv_decode_full_frame( d->decoder, input_buf, e_dv_color_yuv, pixels,pitches); + + yuy2toyv16( Y,Cb,Cr, d->dv_video, width ,height ); + + if( yuv_use_auto_ccir_jpeg() && fmt == FMT_422F) { + yuv_scale_pixels_from_ycbcr( + Y, 16.0f, 235.0f, width * height); + yuv_scale_pixels_from_ycbcr( + Cb,16.0f, 240.0f, width * height/2); + yuv_scale_pixels_from_ycbcr( + Cr,16.0f, 240.0f, width * height/2); + } + + return 1; + } + + return 0; +} + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/vj-dv.h b/branches/V-1.5.3/veejay-server/libel/vj-dv.h new file mode 100644 index 00000000..5dd4fa6e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-dv.h @@ -0,0 +1,63 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#ifndef VJ_DV_H +#define VJ_DV_H +#include +#ifdef SUPPORT_READ_DV2 +#include +typedef struct +{ + dv_decoder_t *decoder; + uint8_t *dv_video; + int fmt; + int yuy2; + int audio; + int16_t **audio_buffers; +} vj_dv_decoder; + +typedef struct +{ + dv_encoder_t *encoder; + uint8_t *dv_video; + int fmt; + uint8_t *buffer; + void *scaler; +} vj_dv_encoder; + + +vj_dv_decoder *vj_dv_decoder_init(int quality,int width, int height, int pixel_format); + +vj_dv_encoder *vj_dv_init_encoder(void * el, int pixel_format); + +void vj_dv_decoder_get_audio(vj_dv_decoder *d, uint8_t *audio_buf); + +int vj_dv_scan_frame( vj_dv_decoder *d, uint8_t * input_buf ); + +void vj_dv_decoder_set_audio(vj_dv_decoder *d, int audio); + + +int vj_dv_decode_frame(vj_dv_decoder *d,uint8_t * in, uint8_t * Y, + uint8_t * Cb, uint8_t * Cr, int w, int h, int fmt); + +int vj_dv_encode_frame(vj_dv_encoder *e,uint8_t * in[3]); +void vj_dv_free_encoder(vj_dv_encoder *e); +void vj_dv_free_decoder(vj_dv_decoder *d); +int is_dv_resolution( int w, int h ); +#endif +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/vj-el.c b/branches/V-1.5.3/veejay-server/libel/vj-el.c new file mode 100644 index 00000000..853c458d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-el.c @@ -0,0 +1,2547 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +/* + + + This file contains code-snippets from the mjpegtools' EditList + (C) The Mjpegtools project + + http://mjpeg.sourceforge.net +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SUPPORT_READ_DV2 +#include "rawdv.h" +#include "vj-dv.h" +#endif +#define MAX_CODECS 50 +#define CODEC_ID_YUV420 999 +#define CODEC_ID_YUV422 998 +#define CODEC_ID_YUV422F 997 +#define CODEC_ID_YUV420F 996 +#define CODEC_ID_YUVLZO 900 +#define DUMMY_FRAMES 2 + +//@@ ! +#ifdef STRICT_CHECKING +#include +#endif +static struct +{ + const char *name; +} _chroma_str[] = +{ + { "Unknown" }, // CHROMAUNKNOWN + { "4:2:0" }, + { "4:2:2" }, + { "4:4:4" }, + { "4:1:1" }, + { "4:2:0 full range" }, + { "4:2:2 full range" } +}; + + +static struct +{ + const char *name; + int id; + int pf; +} _supported_codecs[] = +{ + { "vj20", CODEC_ID_YUV420F, -1 }, + { "vj22", CODEC_ID_YUV422F, -1 }, +// { "", CODEC_ID_YUV422F, -1 }, + { "mjpg" , CODEC_ID_MJPEG , 0 }, + { "mjpg" , CODEC_ID_MJPEG , 1 }, + { "mjpb", CODEC_ID_MJPEGB, 0 }, + { "mjpb", CODEC_ID_MJPEGB, 1 }, + { "msmpeg4",CODEC_ID_MPEG4, -1}, + { "fmp4", CODEC_ID_MPEG4, 1}, + { "fmp4", CODEC_ID_MPEG4, 0}, + { "divx" ,CODEC_ID_MSMPEG4V3, -1 }, + { "i420", CODEC_ID_YUV420, -1 }, + { "i422", CODEC_ID_YUV422, -1 }, + { "dmb1", CODEC_ID_MJPEG, 0 }, + { "dmb1", CODEC_ID_MJPEG, 1 }, + { "jpeg", CODEC_ID_MJPEG, 0 }, + { "jpeg", CODEC_ID_MJPEG, 1 }, + { "mjpa", CODEC_ID_MJPEG, 0 }, + { "mjpb", CODEC_ID_MJPEG, 1 }, + { "jfif", CODEC_ID_MJPEG, 0 }, + { "jfif", CODEC_ID_MJPEG, 1 }, + { "png", CODEC_ID_PNG, -1 }, + { "mpng", CODEC_ID_PNG, -1 }, +#if LIBAVCODEC_BUILD > 4680 + { "sp5x", CODEC_ID_SP5X, -1 }, /* sunplus motion jpeg video */ +#endif + { "jpgl", CODEC_ID_MJPEG, 0}, + { "jpgl", CODEC_ID_MJPEG, 1}, + { "dvsd", CODEC_ID_DVVIDEO, -1}, + { "dvcp", CODEC_ID_DVVIDEO, -1}, + { "dv", CODEC_ID_DVVIDEO, -1}, + { "dvhd", CODEC_ID_DVVIDEO, -1}, + { "dvp", CODEC_ID_DVVIDEO, -1}, + { "mp4v", CODEC_ID_MPEG4, -1}, + { "xvid", CODEC_ID_MPEG4, -1}, + { "divx", CODEC_ID_MPEG4, -1}, + { "dxsd", CODEC_ID_MPEG4, -1}, + { "mp4s", CODEC_ID_MPEG4, -1}, + { "m4s2", CODEC_ID_MPEG4, -1}, + { "avc1", CODEC_ID_H264, -1}, + { "h264", CODEC_ID_H264, -1}, + { "x264", CODEC_ID_H264, -1}, + { "davc", CODEC_ID_H264, -1}, + { "div3", CODEC_ID_MSMPEG4V3, -1}, + { "mp43", CODEC_ID_MSMPEG4V3, -1}, + { "mp42", CODEC_ID_MSMPEG4V2, -1}, + { "mpg4", CODEC_ID_MSMPEG4V1, -1}, + { "yuv", CODEC_ID_YUV420, -1}, + { "iyuv", CODEC_ID_YUV420, -1}, + { "i420", CODEC_ID_YUV420, -1}, + { "yv16", CODEC_ID_YUV422, -1}, + { "yv12", CODEC_ID_YUV420, -1}, + { "mlzo", CODEC_ID_YUVLZO, -1}, + { "pict", 0xffff, -1}, + { "hfyu", CODEC_ID_HUFFYUV, -1}, + { "cyuv", CODEC_ID_CYUV, -1}, + { "svq1", CODEC_ID_SVQ1, -1}, + { "svq3", CODEC_ID_SVQ3, -1}, + { "rpza", CODEC_ID_RPZA, -1}, + { NULL , 0, -1}, +}; + +static struct +{ + const char *name; + int id; +} _supported_fourcc[] = +{ + { "vj20", CODEC_ID_YUV420F }, + { "vj22", CODEC_ID_YUV422F }, + { "yv12", CODEC_ID_YUV420 }, + { "mjpg", CODEC_ID_MJPEG }, + { "mjpb", CODEC_ID_MJPEGB }, + { "dmb1", CODEC_ID_MJPEG }, + { "jpeg", CODEC_ID_MJPEG }, + { "mjpa", CODEC_ID_MJPEG }, + { "jfif", CODEC_ID_MJPEG }, + { "png", CODEC_ID_PNG }, + { "mpng", CODEC_ID_PNG }, +#if LIBAVCODEC_BUILD > 4680 + { "sp5x", CODEC_ID_SP5X }, /* sunplus motion jpeg video */ +#endif + { "jpgl", CODEC_ID_MJPEG }, + { "dvsd", CODEC_ID_DVVIDEO}, + { "dv", CODEC_ID_DVVIDEO}, + { "dvhd", CODEC_ID_DVVIDEO}, + { "dvp", CODEC_ID_DVVIDEO}, + { "mp4v", CODEC_ID_MPEG4 }, + { "xvid", CODEC_ID_MPEG4 }, + { "divx", CODEC_ID_MPEG4 }, + { "dxsd", CODEC_ID_MPEG4 }, + { "mp4s", CODEC_ID_MPEG4 }, + { "m4s2", CODEC_ID_MPEG4 }, + { "fmp4", CODEC_ID_MPEG4 }, + { "fmp4", CODEC_ID_MPEG4 }, + { "avc1", CODEC_ID_H264 }, + { "h264", CODEC_ID_H264 }, + { "x264", CODEC_ID_H264 }, + { "davc", CODEC_ID_H264 }, + { "div3", CODEC_ID_MSMPEG4V3 }, + { "divx", CODEC_ID_MPEG4 }, + { "mp43", CODEC_ID_MSMPEG4V3 }, + { "mp42", CODEC_ID_MSMPEG4V2 }, + { "mpg4", CODEC_ID_MSMPEG4V1 }, + { "yuv", CODEC_ID_YUV420 }, + { "iyuv", CODEC_ID_YUV420 }, + { "i420", CODEC_ID_YUV420 }, + { "mlzo", CODEC_ID_YUVLZO }, + { "yv16", CODEC_ID_YUV422 }, + { "pict", 0xffff }, /* invalid fourcc */ + { "hfyu", CODEC_ID_HUFFYUV}, + { "cyuv", CODEC_ID_CYUV }, + { "svq1", CODEC_ID_SVQ1 }, + { "svq3", CODEC_ID_SVQ3 }, + { "rpza", CODEC_ID_RPZA }, + { NULL, 0 } +}; + +static int mmap_size = 0; +static struct { + int i; + char *s; +} pixfmtstr[] = { +{ -1 , "Unknown/Invalid"}, +{ PIX_FMT_YUV420P, "YUVPIX_FMT_YUV420P"}, +{ PIX_FMT_YUV422P, "4:2:2 planar, Y-Cb-Cr ( 422P )"}, +{ PIX_FMT_YUVJ420P, "4:2:0 planar, Y-U-V (420P JPEG)"}, +{ PIX_FMT_YUVJ422P, "4:2:2 planar, Y-U-V (422P JPEG)"}, +{ PIX_FMT_RGB24, "RGB 24 bit"}, +{ PIX_FMT_BGR24, "BGR 24 bit"}, +{ PIX_FMT_YUV444P, "YUV 4:4:4 planar, Y-Cb-Cr (444P)"}, +{ PIX_FMT_YUVJ444P, "YUV 4:4:4 planar, Y-U-V (444P JPEG)"}, +{ PIX_FMT_RGB32, "RGB 32 bit"}, +{ PIX_FMT_BGR32, "BGR 32 bit"}, +{ PIX_FMT_GRAY8, "Greyscale"}, +{ PIX_FMT_RGB32_1, "RGB 32 bit LE"}, +{ 0 , NULL} +}; + +static const char *el_pixfmt_str(int i) +{ + int j; + for( j = 0; pixfmtstr[j].s != NULL ; j ++ ) { + if( i == pixfmtstr[j].i ) + return pixfmtstr[j].s; + } + return pixfmtstr[0].s; +} + +void free_av_packet( AVPacket *pkt ) +{ + if( pkt ) { + if( pkt->destruct ) + pkt->destruct(pkt); + pkt->data = NULL; + pkt->size = 0; + } + pkt = NULL; +} + +typedef struct +{ + AVCodec *codec; // veejay supports only 2 yuv formats internally + AVFrame *frame; + AVCodecContext *context; + uint8_t *tmp_buffer; + uint8_t *deinterlace_buffer[3]; + VJFrame *img; + int fmt; + int ref; + void *sampler; +#ifdef SUPPORT_READ_DV2 + vj_dv_decoder *dv_decoder; +#endif + void *lzo_decoder; +} vj_decoder; + +static vj_decoder *el_codecs[MAX_CODECS]; + +static int _el_get_codec(int id, int in_pix_fmt ) +{ + int i; + for( i = 0; _supported_codecs[i].name != NULL ; i ++ ) + { + if( _supported_codecs[i].id == id) + { + if( _supported_codecs[i].pf == -1) { + return i; + } else if ( _supported_codecs[i].pf == 0 && (in_pix_fmt == FMT_420F || in_pix_fmt == FMT_420)) { + return i; + } else if ( _supported_codecs[i].pf == 1 && (in_pix_fmt == FMT_422F || in_pix_fmt == FMT_422)) { + return i; + } + } + } + return -1; +} +static int _el_get_codec_id( const char *fourcc ) +{ + int i; + for( i = 0; _supported_fourcc[i].name != NULL ; i ++ ) + if( strncasecmp( fourcc, _supported_fourcc[i].name, strlen(_supported_fourcc[i].name) ) == 0 ) { + return _supported_fourcc[i].id; + } + return -1; +} + +int vj_el_get_decoder_from_fourcc( const char *fourcc ) +{ + return _el_get_codec_id( fourcc ); +} + +static void _el_free_decoder( vj_decoder *d ) +{ + if(d) + { + if(d->tmp_buffer) + free( d->tmp_buffer ); + if(d->deinterlace_buffer[0]) + free(d->deinterlace_buffer[0]); + + if(d->context) + { + avcodec_close( d->context ); + free( d->context ); + d->context = NULL; + } + if(d->frame) + free(d->frame); + + if(d->sampler) + subsample_free(d->sampler); + + if(d->img) + free(d->img); + + free(d); + } + d = NULL; +} +#define LARGE_NUM (256*256*256*64) +/* +static int get_buffer(AVCodecContext *context, AVFrame *av_frame){ + vj_decoder *this = (vj_decoder *)context->opaque; + int width = context->width; + int height = context->height; + VJFrame *img = this->img; + avcodec_align_dimensions(context, &width, &height); + + av_frame->opaque = img; + + av_frame->data[0]= img->data[0]; + av_frame->data[1]= img->data[1]; + av_frame->data[2]= img->data[2]; + + av_frame->linesize[0] = img->width; + av_frame->linesize[1] = img->uv_width; + av_frame->linesize[2] = img->uv_width; + + av_frame->age = LARGE_NUM; + + av_frame->type= FF_BUFFER_TYPE_USER; + + return 0; +} +static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){ + VJFrame *img = (VJFrame*)av_frame->opaque; + av_frame->opaque = NULL; +}*/ + +static int el_pixel_format_ = 1; +static int el_len_ = 0; +static int el_uv_len_ = 0; +static int el_uv_wid_ = 0; +static long mem_chunk_ = 0; +static int el_switch_jpeg_ = 0; +long vj_el_get_mem_size() +{ + return mem_chunk_; +} +void vj_el_init_chunk(int size) +{ +//@@ chunk size per editlist + mem_chunk_ = 1024 * size; +} +void vj_el_init(int pf, int switch_jpeg, int dw, int dh, float fps) +{ + int i; + for( i = 0; i < MAX_CODECS ;i ++ ) + el_codecs[i] = NULL; + el_pixel_format_ =pf; +#ifdef STRICT_CHECKING + assert( pf == FMT_422 || pf == FMT_422F ); +#endif + el_switch_jpeg_ = switch_jpeg; + + lav_set_project( dw,dh, fps, pf ); +} + +int vj_el_is_dv(editlist *el) +{ +#ifdef SUPPORT_READ_DV2 + return is_dv_resolution(el->video_width, el->video_height); +#else + return 0; +#endif +} + + +void vj_el_prepare() +{ +// reset_cache( el->cache ); +} + +void vj_el_break_cache( editlist *el ) +{ + if(el) { + if( el->cache ) + free_cache( el->cache ); + el->cache = NULL; + } +} + +static int never_cache_ = 0; +void vj_el_set_caching(int status) +{ + never_cache_ = status; +} + +//@ iterateovers over sample fx chain +void vj_el_setup_cache( editlist *el ) +{ +//@ FIXME: user setting to prevent cache setup! + if(!el->cache && !never_cache_) + { + int n_slots = mem_chunk_ / el->max_frame_size; +// if( n_slots < (el->video_frames - 1) ) + if( n_slots < el->total_frames ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Not caching this EDL to memory (Cachesize too small)"); + veejay_msg(VEEJAY_MSG_DEBUG, "try increasing cache size with -m commandline parameter"); + } + else if( el->max_frame_size > 1024 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "EditList caches at most %d slots (chunk=%d, framesize=%d)", n_slots, mem_chunk_, el->max_frame_size ); + el->cache = init_cache( n_slots ); + } + } +} + +void vj_el_clear_cache( editlist *el ) +{ + if(el->cache) + reset_cache(el->cache); +} + +void vj_el_deinit() +{ + int i; + for( i = 0; i < MAX_CODECS ;i ++ ) + { + if( el_codecs[i] ) + _el_free_decoder( el_codecs[i] ); + } +} + +int vj_el_cache_size() +{ + return cache_avail_mb(); +} + +//@ pixel_format = input pixel format FIXME +vj_decoder *_el_new_decoder( int id , int width, int height, float fps, int pixel_format, int out_fmt) +{ + vj_decoder *d = (vj_decoder*) vj_calloc(sizeof(vj_decoder)); + if(!d) + return NULL; + +#ifdef SUPPORT_READ_DV2 + if( id == CODEC_ID_DVVIDEO ) + d->dv_decoder = vj_dv_decoder_init(1, width, height, pixel_format ); +#endif + if( id == CODEC_ID_YUVLZO ) + { + d->lzo_decoder = lzo_new(); + d->sampler = subsample_init( width ); + } else if( id != CODEC_ID_YUV422 && id != CODEC_ID_YUV420 && id != CODEC_ID_YUV420F && id != CODEC_ID_YUV422F) + { + d->codec = avcodec_find_decoder( id ); + d->context = avcodec_alloc_context(); + d->context->width = width; + d->context->height = height; + d->context->opaque = d; + d->context->palctrl = NULL; + d->frame = avcodec_alloc_frame(); + d->img = (VJFrame*) vj_calloc(sizeof(VJFrame)); + d->img->width = width; + if ( avcodec_open( d->context, d->codec ) < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error initializing decoder %d",id); + _el_free_decoder( d ); + return NULL; + } + } + + d->tmp_buffer = (uint8_t*) vj_malloc(sizeof(uint8_t) * width * height * 4 ); + if(!d->tmp_buffer) + { + free(d); + return NULL; + } + d->fmt = id; + veejay_memset( d->tmp_buffer, 0, width * height * 4 ); + + d->deinterlace_buffer[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * width * height * 3); + if(!d->deinterlace_buffer[0]) { if(d) free(d); return NULL; } + + d->deinterlace_buffer[1] = d->deinterlace_buffer[0] + (width * height ); + d->deinterlace_buffer[2] = d->deinterlace_buffer[0] + (2 * width * height ); + + veejay_memset( d->deinterlace_buffer[0], 0, width * height * 3 ); + + return d; +} + +void vj_el_set_image_output_size(editlist *el, int dw, int dh, float fps, int pf) +{ +/* if( el->video_width <= 0 || el->video_height <= 0 ) + lav_set_project( dw,dh, fps, pf ); + else + lav_set_project( + el->video_width, el->video_height, el->video_fps , el_pixel_format_ ); +*/ +} + +static int _el_probe_for_pixel_fmt( lav_file_t *fd ) +{ +// int old = lav_video_cmodel( fd ); + + int new = test_video_frame( fd, el_pixel_format_ ); + + switch(new) + { + case FMT_422: + veejay_msg(VEEJAY_MSG_DEBUG,"\tPixel format: YUV Planar 4:2:2 [16-235][16-240]"); + break; + case FMT_422F: + veejay_msg(VEEJAY_MSG_DEBUG,"\tPixel format: YUV Planar 4:2:2 [JPEG full range]"); + break; + } + + return new; +} + +int get_ffmpeg_pixfmt( int pf ) +{ + switch( pf ) + { + case FMT_422: + return PIX_FMT_YUV422P; + case FMT_422F: + return PIX_FMT_YUVJ422P; + case 4: + return PIX_FMT_YUV444P; + + } + return PIX_FMT_YUV422P; +} +int get_ffmpeg_shift_size(int fmt) +{ + return 0; +} + + +int open_video_file(char *filename, editlist * el, int preserve_pathname, int deinter, int force, char override_norm) +{ + int i, n, nerr; + int chroma=0; + int _fc; + int decoder_id = 0; + const char *compr_type; + int pix_fmt = -1; + char *realname = NULL; + + if( filename == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "No files to open!"); + return -1; + } + + if (preserve_pathname) + realname = strdup(filename); + else + realname = canonicalize_file_name( filename ); + + if(realname == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot get full path of '%s'", filename); + return -1; + } + + for (i = 0; i < el->num_video_files; i++) + { + if (strncmp(realname, el->video_file_list[i], strlen( el->video_file_list[i])) == 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "File %s already in editlist", realname); + if(realname) free(realname); + return i; + } + } + + if (el->num_video_files >= MAX_EDIT_LIST_FILES) + { + // mjpeg_error_exit1("Maximum number of video files exceeded"); + veejay_msg(VEEJAY_MSG_ERROR,"Maximum number of video files exceeded\n"); + if(realname) free(realname); + return -1; + } + + if (el->num_video_files >= 1) + chroma = el->MJPG_chroma; + + int in_pixel_format = vj_el_pixfmt_to_veejay( + detect_pixel_format_with_ffmpeg( filename )); + + + n = el->num_video_files; + lav_file_t *elfd = lav_open_input_file(filename,mmap_size ); + + el->lav_fd[n] = NULL; + + if (elfd == NULL) + { + veejay_msg(VEEJAY_MSG_ERROR,"Error loading videofile '%s'", realname); + veejay_msg(VEEJAY_MSG_ERROR,"%s",lav_strerror()); + if(realname) free(realname); + return -1; + } + + if(lav_video_frames(elfd) < 2) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cowardly refusing to load video files that contain less than 2 frames"); + if(realname) free(realname); + lav_close(elfd); + return -1; + } + + + _fc = lav_video_MJPG_chroma(elfd); +#ifdef STRICT_CHECKING + if( in_pixel_format >= 0 ) + { + if ( _fc == CHROMA422 ) + assert((in_pixel_format == FMT_420) || (in_pixel_format == FMT_420F) || (in_pixel_format == FMT_422 || in_pixel_format == FMT_422F ) ); + } +#endif + + if( !(_fc == CHROMA422 || _fc == CHROMA420 || _fc == CHROMA444 || _fc == CHROMAUNKNOWN || _fc == CHROMA411 || _fc == CHROMA422F || _fc == CHROMA420F)) + { + veejay_msg(VEEJAY_MSG_ERROR,"Input file %s is not in a valid format (%d)",filename,_fc); + if(realname) free(realname); + lav_close( elfd ); + return -1; + + } + + if(chroma == CHROMAUNKNOWN) + { /* set chroma */ + el->MJPG_chroma = _fc; + chroma = _fc; + } + + pix_fmt = _el_probe_for_pixel_fmt( elfd ); +#ifdef STRICT_CHECKING + //if( in_pixel_format >= 0 ) + // assert( pix_fmt == in_pixel_format ); +#endif + + if(pix_fmt < 0 && in_pixel_format < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to determine pixel format"); + if(elfd) lav_close( elfd ); + if(realname) free(realname); + return -1; + } + + if( pix_fmt < 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING, "(!) Using pixelformat detected by FFmpeg (fallback)"); + pix_fmt = in_pixel_format; + } + + if(el_switch_jpeg_ ) { + switch(pix_fmt) { + case FMT_422F: pix_fmt=FMT_422; break; + case FMT_422: pix_fmt=FMT_422F;break; + } + } + + el->yuv_taste[n] = pix_fmt; + el->lav_fd[n] = elfd; + el->num_frames[n] = lav_video_frames(el->lav_fd[n]); + el->video_file_list[n] = strndup(realname, strlen(realname)); + + /* Debug Output */ + if(n == 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG,"\tFull name: %s", filename, realname); + veejay_msg(VEEJAY_MSG_DEBUG,"\tFrames: %ld", lav_video_frames(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG,"\tWidth: %d", lav_video_width(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG,"\tHeight: %d", lav_video_height(el->lav_fd[n])); + + const char *int_msg; + switch (lav_video_interlacing(el->lav_fd[n])) + { + case LAV_NOT_INTERLACED: + int_msg = "Not interlaced"; + break; + case LAV_INTER_TOP_FIRST: + int_msg = "Top field first"; + break; + case LAV_INTER_BOTTOM_FIRST: + int_msg = "Bottom field first"; + break; + default: + int_msg = "Unknown!"; + break; + } + + if( deinter == 1 && (lav_video_interlacing(el->lav_fd[n]) != LAV_NOT_INTERLACED)) + el->auto_deinter = 1; + + veejay_msg(VEEJAY_MSG_DEBUG,"\tInterlacing: %s", int_msg); + veejay_msg(VEEJAY_MSG_DEBUG,"\tFrames/sec: %f", lav_frame_rate(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG,"\tSampling format: %s", _chroma_str[ lav_video_MJPG_chroma(el->lav_fd[n])].name); + veejay_msg(VEEJAY_MSG_DEBUG,"\tFOURCC: %s",lav_video_compressor(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG,"\tAudio samps: %ld", lav_audio_clips(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG,"\tAudio chans: %d", lav_audio_channels(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG,"\tAudio bits: %d", lav_audio_bits(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG,"\tAudio rate: %ld", lav_audio_rate(el->lav_fd[n])); + } + else + { + veejay_msg(VEEJAY_MSG_DEBUG, "\tFull name %s",realname); + veejay_msg(VEEJAY_MSG_DEBUG, "\tFrames %d", lav_video_frames(el->lav_fd[n])); + veejay_msg(VEEJAY_MSG_DEBUG, "\tDecodes into %s", _chroma_str[ lav_video_MJPG_chroma( el->lav_fd[n]) ]); + } + + nerr = 0; + if (n == 0) { + /* First file determines parameters */ + if(el->is_empty) + { /* Dummy determines parameters */ + if(el->video_height != lav_video_height(el->lav_fd[n])) + nerr++; + if(el->video_width != lav_video_width(el->lav_fd[n])) + nerr++; + } + else + { + el->video_height = lav_video_height(el->lav_fd[n]); + el->video_width = lav_video_width(el->lav_fd[n]); + el->video_inter = lav_video_interlacing(el->lav_fd[n]); + el->video_fps = lav_frame_rate(el->lav_fd[n]); + } + lav_video_clipaspect(el->lav_fd[n], + &el->video_sar_width, + &el->video_sar_height); + + if (!el->video_norm) + { + /* TODO: This guessing here is a bit dubious but it can be over-ridden */ + if (el->video_fps > 24.95 && el->video_fps < 25.05) + el->video_norm = 'p'; + else if (el->video_fps > 29.92 && el->video_fps <= 30.02) + el->video_norm = 'n'; + } + + if (!el->video_norm) + { + if(override_norm == 'p' || override_norm == 'n') + el->video_norm = override_norm; + else + { + veejay_msg(VEEJAY_MSG_ERROR, + "Invalid video norm - override with -N / --norm"); + nerr++; + } + } + + if(!el->is_empty) + { + el->audio_chans = lav_audio_channels(el->lav_fd[n]); + if (el->audio_chans > 2) { + veejay_msg(VEEJAY_MSG_ERROR, "File %s has %d audio channels - cant play that!", + filename,el->audio_chans); + nerr++; + } + + el->has_audio = (el->audio_chans == 0 ? 0: 1); + el->audio_bits = lav_audio_bits(el->lav_fd[n]); + el->audio_rate = lav_audio_rate(el->lav_fd[n]); + el->audio_bps = (el->audio_bits * el->audio_chans + 7) / 8; + } + else + { + if(lav_audio_channels(el->lav_fd[n]) != el->audio_chans || + lav_audio_rate(el->lav_fd[n]) != el->audio_rate || + lav_audio_bits(el->lav_fd[n]) != el->audio_bits ) + nerr++; + else + el->has_audio = 1; + } + } else { + /* All files after first have to match the paramters of the first */ + + if (el->video_height != lav_video_height(el->lav_fd[n]) || + el->video_width != lav_video_width(el->lav_fd[n])) { + veejay_msg(VEEJAY_MSG_ERROR,"File %s: Geometry %dx%d does not match %dx%d.", + filename, lav_video_width(el->lav_fd[n]), + lav_video_height(el->lav_fd[n]), el->video_width, + el->video_height); + nerr++; + + } + if (el->video_inter != lav_video_interlacing(el->lav_fd[n])) { + if(force) + veejay_msg(VEEJAY_MSG_WARNING,"File %s: Interlacing is %d should be %d", + filename, lav_video_interlacing(el->lav_fd[n]), + el->video_inter); + else + veejay_msg(VEEJAY_MSG_ERROR, "File %s: Interlacing is %d should be %d", + filename, lav_video_interlacing(el->lav_fd[n]), + el->video_inter); + + + if(!el->auto_deinter) + { + if(force) + { + veejay_msg(VEEJAY_MSG_WARNING, "(Force loading video) Auto deinterlacing enabled"); + el->auto_deinter = 1; + } + else + { + nerr++; + } + } + } + /* give a warning on different fps instead of error , this is better + for live performances */ + if (fabs(el->video_fps - lav_frame_rate(el->lav_fd[n])) > + 0.0000001) { + veejay_msg(VEEJAY_MSG_WARNING,"File %s: fps is %3.2f , but playing at %3.2f", filename, + lav_frame_rate(el->lav_fd[n]), el->video_fps); + } + /* If first file has no audio, we don't care about audio */ + + if (el->has_audio) { + if( el->audio_rate < 44000 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "File %s: Cannot play %d Hz audio. Use at least 44100 Hz or start with -a0", filename, el->audio_rate); + nerr++; + } + else { + if (el->audio_chans != lav_audio_channels(el->lav_fd[n]) || + el->audio_bits != lav_audio_bits(el->lav_fd[n]) || + el->audio_rate != lav_audio_rate(el->lav_fd[n])) { + veejay_msg(VEEJAY_MSG_ERROR,"File %s: Mismatched audio properties: %d channels , %d bit %ld Hz", + filename, lav_audio_channels(el->lav_fd[n]), + lav_audio_bits(el->lav_fd[n]), + lav_audio_rate(el->lav_fd[n]) ); + nerr++; + } + } + } + + + + + if (nerr) { + if(el->lav_fd[n]) + lav_close( el->lav_fd[n] ); + el->lav_fd[n] = NULL; + if(realname) free(realname); + if(el->video_file_list[n]) + free(el->video_file_list[n]); + el->video_file_list[n] = NULL; + return -1; + } + } + + compr_type = (const char*) lav_video_compressor(el->lav_fd[n]); + + if(!compr_type) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot get codec information from lav file"); + if(el->lav_fd[n]) + lav_close( el->lav_fd[n] ); + el->lav_fd[n] = NULL; + if(realname) free(realname); + if(el->video_file_list[n]) + free(el->video_file_list[n]); + el->video_file_list[n] = NULL; + return -1; + } + // initialze a decoder if needed + decoder_id = _el_get_codec_id( compr_type ); + if(decoder_id > 0 && decoder_id != 0xffff) + { + int c_i = _el_get_codec(decoder_id, el->yuv_taste[n] ); + if(c_i == -1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unsupported codec %s",compr_type); + if( el->lav_fd[n] ) + lav_close( el->lav_fd[n] ); + el->lav_fd[n] = NULL; + if( realname ) free(realname ); + if( el->video_file_list[n]) + free(el->video_file_list[n]); + el->video_file_list[n] = NULL; + return -1; + } + if( el_codecs[c_i] == NULL ) + { + // el_codecs[c_i] = _el_new_decoder( decoder_id, el->video_width, el->video_height, el->video_fps, pix_fmt ); + int ff_pf = get_ffmpeg_pixfmt( el_pixel_format_ ); + el_codecs[c_i] = _el_new_decoder( decoder_id, el->video_width, el->video_height, el->video_fps, el->yuv_taste[ n ],ff_pf ); + if(!el_codecs[c_i]) + { + veejay_msg(VEEJAY_MSG_ERROR,"Cannot initialize %s codec", compr_type); + if( el->lav_fd[n] ) + lav_close( el->lav_fd[n] ); + el->lav_fd[n] = NULL; + if(realname) free(realname); + if( el->video_file_list[n]) + free(el->video_file_list[n]); + el->video_file_list[n] = NULL; + return -1; + } + } + } + + if(decoder_id <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Dont know how to handle %s (fmt %d) %x", compr_type, pix_fmt,decoder_id); + if(realname) free(realname); + if( el->video_file_list[n]) free( el->video_file_list[n] ); + if( el->lav_fd[n] ) + lav_close( el->lav_fd[n]); + el->lav_fd[n] = NULL; + el->video_file_list[n] = NULL; + return -1; + } + + if(realname) + free(realname); + + if(el->is_empty) + { + el->video_frames = el->num_frames[0]; + el->video_frames -= DUMMY_FRAMES; + } + el->is_empty = 0; + el->has_video = 1; + el->num_video_files ++; + el->total_frames = el->video_frames - 1; + return n; +} + +void vj_el_show_formats(void) +{ +#ifdef SUPPORT_READ_DV2 + veejay_msg(VEEJAY_MSG_INFO, + "Video containers: AVI (up to 32gb), RAW DV and Quicktime"); +#else + veejay_msg(VEEJAY_MSG_INFO, + "Video containers: AVI (up to 32gb) and Quicktime"); +#endif + veejay_msg(VEEJAY_MSG_INFO, + "Video fourcc (preferred): mjpg, mjpb, mjpa, dv, dvsd,sp5x,dmb1,dvcp,dvhd, yv16,i420"); + veejay_msg(VEEJAY_MSG_INFO, + "Video codecs (preferred): YV16, I420, Motion Jpeg or Digital Video"); + veejay_msg(VEEJAY_MSG_INFO, + "If the video file is made up out of only I-frames (whole images), you can also decode:"); + veejay_msg(VEEJAY_MSG_INFO, + " mpg4,mp4v,svq3,svq1,rpza,hfyu,mp42,mpg43,davc,div3,x264,h264,avc1,m4s2,divx,xvid"); + veejay_msg(VEEJAY_MSG_INFO, + "Use veejay's internal format YV16 to reduce CPU usage"); + +#ifdef USE_GDK_PIXBUF + veejay_msg(VEEJAY_MSG_INFO, + "Image types supported:"); + vj_picture_display_formats(); +#endif + + + +} + + +static int vj_el_dummy_frame( uint8_t *dst[3], editlist *el ,int pix_fmt) +{ + const int uv_len = (el->video_width * el->video_height) / ( ( (pix_fmt==FMT_422||pix_fmt==FMT_422F) ? 2 : 4)); + const int len = el->video_width * el->video_height; + veejay_memset( dst[0], 16, len ); + veejay_memset( dst[1],128, uv_len ); + veejay_memset( dst[2],128, uv_len ); + return 1; +} + +void vj_el_get_video_fourcc(editlist *el, int num, char *fourcc) +{ + uint64_t n; +// if( num < 0 ) num = 0; else if (num >= el->video_frames ) num = el->video_frames - 1; +#ifdef STRICT_CHECKING + assert( num >= 0 && num <= el->total_frames ); +#else + if (num < 0) + num = 0; + else if (num >= el->video_frames) + num = el->video_frames-1; +#endif + n = el->frame_list[ num ]; + + const char *compr = lav_video_compressor( el->lav_fd[ N_EL_FILE(n) ] ); + snprintf(fourcc,4,"%s", compr ); +} + + +int vj_el_get_file_fourcc(editlist *el, int num, char *fourcc) +{ + if(num >= el->num_video_files) + return 0; + if( fourcc == NULL) + return 0; + + const char *compr = lav_video_compressor( el->lav_fd[num] ); + if(compr == NULL) + return 0; + snprintf(fourcc,4,"%s", compr ); + fourcc[5] = '\0'; + return 1; +} + + +int vj_el_bogus_length( editlist *el, long nframe ) +{ + uint64_t n = 0; + + if( !el->has_video || el->is_empty ) + return 0; + + if( nframe < 0 ) + nframe = 0; + else if (nframe >= el->video_frames ) + nframe = el->video_frames - 1; + + n = el->frame_list[nframe]; + + return lav_bogus_video_length( el->lav_fd[ N_EL_FILE(n) ] ); +} + +int vj_el_set_bogus_length( editlist *el, long nframe, int len ) +{ + uint64_t n = 0; + + if( len <= 0 ) + return 0; + + if( !el->has_video || el->is_empty ) + return 0; + if (nframe < 0) + nframe = 0; + + if (nframe >= el->video_frames) + nframe = el->video_frames-1; + + n = el->frame_list[nframe]; + + if( !lav_bogus_video_length( el->lav_fd[N_EL_FILE(n)] ) ) + return 0; + + lav_bogus_set_length( el->lav_fd[N_EL_FILE(n)], len ); + + return 1; +} + +int vj_el_get_video_frame(editlist *el, long nframe, uint8_t *dst[3]) +{ + if( el->has_video == 0 || el->is_empty ) + { + vj_el_dummy_frame( dst, el, el->pixel_format ); + return 2; + } + + int res = 0; + uint64_t n; + int decoder_id =0; + int c_i = 0; + vj_decoder *d = NULL; + int out_pix_fmt = el->pixel_format; + int in_pix_fmt = out_pix_fmt; + + if (nframe < 0) + nframe = 0; + + if (nframe >= el->video_frames) + nframe = el->video_frames-1; + + n = el->frame_list[nframe]; + + in_pix_fmt = el->yuv_taste[N_EL_FILE(n)]; + + uint8_t *in_cache = NULL; + if(el->cache) + in_cache = get_cached_frame( el->cache, nframe, &res, &decoder_id ); + + if(! in_cache ) + { + res = lav_set_video_position(el->lav_fd[N_EL_FILE(n)], N_EL_FRAME(n)); + decoder_id = lav_video_compressor_type( el->lav_fd[N_EL_FILE(n)] ); + + if (res < 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Error setting video position: %s", + lav_strerror()); + return -1; + } + } + + if( decoder_id == 0xffff ) + { + VJFrame *srci = lav_get_frame_ptr( el->lav_fd[ N_EL_FILE(n) ] ); + if( srci == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error decoding Image %ld", + N_EL_FRAME(n)); + return -1; + } +#ifdef STRICT_CHECKING + assert( dst[0] != NULL && dst[1] != NULL && dst[2] != NULL ); +#endif + veejay_memcpy( dst[0], srci->data[0], el_len_ ); + veejay_memcpy( dst[1], srci->data[1], el_uv_len_ ); + veejay_memcpy( dst[2], srci->data[2], el_uv_len_ ); + return 1; + } + + c_i = _el_get_codec( decoder_id , in_pix_fmt); + if(c_i >= 0 && c_i < MAX_CODECS && el_codecs[c_i] != NULL) + d = el_codecs[c_i]; + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Choked on decoder %x (%d), slot %d",decoder_id,decoder_id, c_i ); + return -1; + } + + if(!in_cache) + { + if( d == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Codec not initlaized"); + return -1; + } + if(lav_filetype( el->lav_fd[N_EL_FILE(n)] ) != 'x') + { + res = lav_read_frame(el->lav_fd[N_EL_FILE(n)], d->tmp_buffer); + if(res > 0 && el->cache) + cache_frame( el->cache, d->tmp_buffer, res, nframe, decoder_id ); + } + } + + uint8_t *data = ( in_cache == NULL ? d->tmp_buffer: in_cache ); + int inter = 0; + int got_picture = 0; + int in_uv_len = 0; + uint8_t *in[3] = { NULL,NULL,NULL }; + + switch( decoder_id ) + { + case CODEC_ID_YUV420: + veejay_memcpy( dst[0], data, el_len_); + in[0] = data; in[1] = data+el_len_ ; in[2] = data + el_len_ + (el_len_/4); + if( el_pixel_format_ == FMT_422F ) { + yuv_scale_pixels_from_ycbcr( in[0],16.0f,235.0f, el_len_ ); + yuv_scale_pixels_from_ycbcr( in[1],16.0f,240.0f, el_len_/2); + } + yuv420to422planar( in , dst, el->video_width,el->video_height ); + return 1; + break; + case CODEC_ID_YUV420F: + veejay_memcpy( dst[0], data, el_len_); + in[0] = data; in[1] = data + el_len_; in[2] = data + el_len_+(el_len_/4); + if( el_pixel_format_ == FMT_422 ) { + yuv_scale_pixels_from_y( dst[0], el_len_ ); + yuv_scale_pixels_from_uv( dst[1], el_len_ / 2 ); + // yuv_scale_pixels_from_yuv( dst[0],16.0f,235.0f, el_len_ ); + // yuv_scale_pixels_from_yuv( dst[1],16.0f,240.0f, el_len_/2); + } + yuv420to422planar( in , dst, el->video_width,el->video_height ); + return 1; + break; + case CODEC_ID_YUV422: + veejay_memcpy( dst[0], data, el_len_); + veejay_memcpy( dst[1], data+el_len_,el_uv_len_); + veejay_memcpy( dst[2], data+el_len_+el_uv_len_, el_uv_len_); + if( el_pixel_format_ == FMT_422F ) { + yuv_scale_pixels_from_ycbcr( dst[0],16.0f,235.0f, el_len_ ); + yuv_scale_pixels_from_ycbcr( dst[1],16.0f,240.0f, el_len_/2); + } + return 1; + break; + case CODEC_ID_YUV422F: + veejay_memcpy( dst[0], data, el_len_); + veejay_memcpy( dst[1], data+el_len_,el_uv_len_); + veejay_memcpy( dst[2], data+el_len_+el_uv_len_, el_uv_len_); + if( el_pixel_format_ == FMT_422 ) { + yuv_scale_pixels_from_y( dst[0], el_len_ ); + yuv_scale_pixels_from_uv( dst[1], el_len_/2); + // yuv_scale_pixels_from_yuv( dst[0],16.0f,235.0f, el_len_ ); + // yuv_scale_pixels_from_yuv( dst[1],16.0f,240.0f, el_len_ ); + } + + return 1; + break; + case CODEC_ID_DVVIDEO: +#ifdef SUPPORT_READ_DV2 + return vj_dv_decode_frame( d->dv_decoder, data, dst[0], dst[1], dst[2], el->video_width,el->video_height, + out_pix_fmt); +#else + return 0; +#endif + break; + case CODEC_ID_YUVLZO: + + if( ( in_pix_fmt == FMT_420F || in_pix_fmt == FMT_420 ) ) { + inter = lzo_decompress420into422(d->lzo_decoder, data,res,dst, el->video_width,el->video_height ); + } + else { + inter = lzo_decompress_el( d->lzo_decoder, data,res, dst,el->video_width*el->video_height); + } + + return inter; + + break; + default: + inter = lav_video_interlacing(el->lav_fd[N_EL_FILE(n)]); + d->img->width = el->video_width; + d->img->uv_width = el->video_width >> 1; + d->img->data[0] = dst[0]; + d->img->data[1] = dst[1]; + d->img->data[2] = dst[2]; + + int decode_len = avcodec_decode_video( + d->context, + d->frame, + &got_picture, + data, + res + ); + + if(!got_picture) + { + veejay_msg(0, "Cannot decode frame ,unable to get whole picture"); + return 0; + } + + if( decode_len <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot decode frame"); + return 0; + } + + int dst_fmt = get_ffmpeg_pixfmt( el_pixel_format_ ); + int src_fmt = d->context->pix_fmt; + if( el_switch_jpeg_ ) { + switch(src_fmt) { + case PIX_FMT_YUV420P:src_fmt=PIX_FMT_YUVJ420P; break; + case PIX_FMT_YUVJ420P:src_fmt=PIX_FMT_YUV420P; break; + case PIX_FMT_YUV422P:src_fmt=PIX_FMT_YUVJ422P; break; + case PIX_FMT_YUVJ422P:src_fmt=PIX_FMT_YUV422P; break; + } + } + + if(!d->frame->opaque) + { + if( el->auto_deinter && inter != LAV_NOT_INTERLACED) + { + AVPicture pict2; + veejay_memset(&pict2,0,sizeof(AVPicture)); + pict2.data[0] = d->deinterlace_buffer[0]; + pict2.data[1] = d->deinterlace_buffer[1]; + pict2.data[2] = d->deinterlace_buffer[2]; + pict2.linesize[1] = el->video_width >> 1; + pict2.linesize[2] = el->video_width >> 1; + pict2.linesize[0] = el->video_width; + avpicture_deinterlace( + &pict2, + (const AVPicture*) d->frame, + src_fmt, + el->video_width, + el->video_height); + + VJFrame *src1 = yuv_yuv_template( d->deinterlace_buffer[0], + d->deinterlace_buffer[1], d->deinterlace_buffer[2], + el->video_width, el->video_height, + src_fmt ); + VJFrame *dst1 = yuv_yuv_template( dst[0],dst[1],dst[2], + el->video_width, el->video_height, + dst_fmt ); + + /* if(! el->scaler ) { + sws_template tmpl; + tmpl.flags = 1; + el->scaler = yuv_init_swscaler( src1,dst1,&tmpl,yuv_sws_get_cpu_flags() ); + } +#ifdef STRICT_CHECKING + assert( el->scaler != NULL ); +#endif + + yuv_convert_and_scale( el->scaler, src1,dst1 ); + */ + yuv_convert_any3( src1,d->frame->linesize,dst1,src1->format,dst1->format); + + free(src1); + free(dst1); + + } + else + { + VJFrame *src1 = yuv_yuv_template( d->frame->data[0], + d->frame->data[1], d->frame->data[2], + el->video_width,el->video_height, + src_fmt ); + VJFrame *dst1 = yuv_yuv_template( dst[0],dst[1],dst[2], + el->video_width,el->video_height, + dst_fmt ); + /* + if(! el->scaler ) { + sws_template tmpl; + tmpl.flags = 1; + el->scaler = yuv_init_swscaler( src1,dst1,&tmpl,yuv_sws_get_cpu_flags() ); + } +#ifdef STRICT_CHECKING + assert( el->scaler != NULL ); +#endif + + yuv_convert_and_scale( el->scaler, src1,dst1 ); + */ + + yuv_convert_any3( src1,d->frame->linesize,dst1,src1->format,dst1->format); + free(src1); + free(dst1); + } + } + else + { + dst[0] = d->frame->data[0]; + dst[1] = d->frame->data[1]; + dst[2] = d->frame->data[2]; + } + return 1; + break; + } + + veejay_msg(VEEJAY_MSG_ERROR, "Error decoding frame %ld", nframe); + return 0; +} + +int detect_pixel_format_with_ffmpeg( const char *filename ) +{ + AVCodec *codec = NULL; + AVCodecContext *codec_ctx = NULL; + AVFormatContext *avformat_ctx = NULL; + AVStream *avformat_stream = NULL; + AVInputFormat *av_input_format = NULL; + AVFormatParameters avf; + AVFrame *av_frame = NULL; + AVPacket pkt; + + int err = av_open_input_file( &avformat_ctx,filename,NULL,0,NULL ); + if(err < 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: Unable to open %s: %d",filename,err ); + return -1; + } + err = av_find_stream_info( avformat_ctx ); + if(err < 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: Stream information found in %s",filename); + av_close_input_file( avformat_ctx ); + return -1; + } + av_read_play(avformat_ctx); + + int i,j; + int n = avformat_ctx->nb_streams; + int vi = -1; + int pix_fmt = -1; + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: File has %d %s", n, ( n == 1 ? "stream" : "streams") ); + + for( i=0; i < n; i ++ ) + { + if( avformat_ctx->streams[i]->codec ) + { + if( avformat_ctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) + { + int sup_codec = 0; + for( j = 0; _supported_codecs[j].name != NULL; j ++ ) { + if( avformat_ctx->streams[i]->codec->codec_id == _supported_codecs[j].id ) { + sup_codec = 1; + goto further; + } + } +further: + if( !sup_codec ) { + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: Unrecognized file %s", + avformat_ctx->streams[i]->codec->codec_name ); + av_close_input_file( avformat_ctx ); + return -1; + } + codec = avcodec_find_decoder( avformat_ctx->streams[i]->codec->codec_id ); + if( codec == NULL ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: Unable to find decoder for codec %s", + avformat_ctx->streams[i]->codec->codec_name); + av_close_input_file( avformat_ctx ); + return -1; + } + vi = i; + break; + } + } + } + + if( vi == -1 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: No video streams found"); + av_close_input_file( avformat_ctx ); + return -1; + } + + codec_ctx = avformat_ctx->streams[vi]->codec; + avformat_stream=avformat_ctx->streams[vi]; + if ( avcodec_open( codec_ctx, codec ) < 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: Unable to open %s decoder (codec %x)", + codec_ctx->codec_name, codec_ctx->codec_id); + return -1; + } + + veejay_memset( &pkt, 0, sizeof(AVPacket)); + AVFrame *f = avcodec_alloc_frame(); + int input_pix_fmt = -1; + + int got_picture = 0; + while( (av_read_frame(avformat_ctx, &pkt) >= 0 ) ) { + avcodec_decode_video( codec_ctx,f,&got_picture, pkt.data, pkt.size ); + + if( got_picture ) { + break; + } + } + + if(!got_picture) { + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg: Error while reading %s", filename ); + av_free(f); + free_av_packet(&pkt); + avcodec_close( codec_ctx ); + av_close_input_file( avformat_ctx ); + return -1; + } + + pix_fmt = codec_ctx->pix_fmt; + + veejay_msg(VEEJAY_MSG_DEBUG, "FFmpeg reports Video [%s] %dx%d. Pixel format: %s Has B frames: %s (%s)", + codec_ctx->codec_name, codec_ctx->width,codec_ctx->height, el_pixfmt_str(codec_ctx->pix_fmt), + (codec_ctx->has_b_frames ? "Yes" : "No"), filename ); + + free_av_packet(&pkt); + avcodec_close( codec_ctx ); + av_close_input_file( avformat_ctx ); + av_free(f); + + return pix_fmt; +} + +int vj_el_pixfmt_to_veejay(int pix_fmt ) { + int input_pix_fmt = -1; + switch( pix_fmt ) { + case PIX_FMT_YUV420P: input_pix_fmt = FMT_420; break; + case PIX_FMT_YUV422P: input_pix_fmt = FMT_422; break; + case PIX_FMT_YUVJ420P: input_pix_fmt = FMT_420F; break; + case PIX_FMT_YUVJ422P: input_pix_fmt = FMT_422F; break; + } + + return input_pix_fmt; +} + +int test_video_frame( lav_file_t *lav,int out_pix_fmt) +{ + int in_pix_fmt = 0; + + int res = lav_set_video_position( lav, 0); + if( res < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error setting frame 0: %s", lav_strerror()); + return -1; + } + + int decoder_id = lav_video_compressor_type( lav ); + + if( decoder_id < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot play that file, unsupported codec"); + return -1; + } + + if(lav_filetype( lav ) == 'x') + { + veejay_msg(VEEJAY_MSG_INFO,"\tIf the image is garbled, please set width and height dimensions (-W and -H) on the commandline."); + return out_pix_fmt; + } + + switch( lav->MJPG_chroma ) + { + case CHROMA420F: + in_pix_fmt = FMT_420F;break; + case CHROMA422F: + in_pix_fmt = FMT_422F;break; + case CHROMA420: + in_pix_fmt = FMT_420; break; + case CHROMA422: + case CHROMA411: + in_pix_fmt = FMT_422; break; + default: + veejay_msg(0 ,"Unsupported pixel format"); + break; + } + vj_decoder *d = _el_new_decoder( + decoder_id, + lav_video_width( lav), + lav_video_height( lav), + (float) lav_frame_rate( lav ), + in_pix_fmt, + out_pix_fmt ); + + if(!d) + { + veejay_msg(VEEJAY_MSG_ERROR, "Choked on decoder %x", decoder_id); + return -1; + } + + res = lav_read_frame( lav, d->tmp_buffer); + + if( res <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error reading frame: %s", lav_strerror()); + _el_free_decoder( d ); + return -1; + } + + int got_picture = 0; + int ret = -1; + int len = 0; + switch( decoder_id ) + { + case CODEC_ID_YUV420F: + ret = FMT_420F; + break; + case CODEC_ID_YUV422F: + ret = FMT_422F; + break; + case CODEC_ID_YUV420: + ret = FMT_420; + break; + case CODEC_ID_YUV422: + ret = FMT_422; + break; + case CODEC_ID_DVVIDEO: +#ifdef SUPPORT_READ_DV2 + ret = vj_dv_scan_frame( d->dv_decoder, d->tmp_buffer );//FIXME + if( ret == FMT_420 || ret == FMT_420F ) + lav->MJPG_chroma = CHROMA420; + else + lav->MJPG_chroma = CHROMA422; +#endif + break; + case CODEC_ID_YUVLZO: + ret = FMT_422; + if ( in_pix_fmt != ret ) + { + //@ correct chroma + if( ret == FMT_420 || ret == FMT_420F ) + lav->MJPG_chroma = CHROMA420; + else + lav->MJPG_chroma = CHROMA422; + } + + break; + default: + + len = avcodec_decode_video( + d->context, + d->frame, + &got_picture, + d->tmp_buffer, + res + ); + + if(!got_picture || len <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to get whole picture"); + ret = -1; + } + else + switch( d->context->pix_fmt ) + { + case PIX_FMT_YUV420P: ret = FMT_420; break; + case PIX_FMT_YUV422P: ret = FMT_422; break; + case PIX_FMT_YUVJ420P:ret = FMT_420F;break; + case PIX_FMT_YUVJ422P:ret = FMT_422F;break; + default: + ret= d->context->pix_fmt; + break; + } + + break; + + } + + _el_free_decoder( d ); + + return ret; +} + + + +int vj_el_get_audio_frame(editlist *el, uint32_t nframe, uint8_t *dst) +{ + long pos, asize; + int ret = 0; + uint64_t n; + int ns0, ns1; + + if(el->is_empty) + { + int ns = el->audio_rate / el->video_fps; + veejay_memset( dst, 0, sizeof(uint8_t) * ns * el->audio_bps ); + return 1; + } + + if (!el->has_audio) + return 0; + if (nframe < 0) + nframe = 0; + + if (nframe >= el->video_frames) + nframe = el->video_frames-1; + + + n = el->frame_list[nframe]; + + /*if( lav_is_DV( el->lav_fd[N_EL_FILE(n)] ) ) + { + lav_set_video_position( el->lav_fd[N_EL_FILE(n)] , nframe ); + return lav_read_audio( el->lav_fd[N_EL_FILE(n)], dst, 0 ); + }*/ + + ns1 = (double) (N_EL_FRAME(n) + 1) * el->audio_rate / el->video_fps; + ns0 = (double) N_EL_FRAME(n) * el->audio_rate / el->video_fps; + + //asize = el->audio_rate / el->video_fps; + pos = nframe * asize; + + ret = lav_set_audio_position(el->lav_fd[N_EL_FILE(n)], ns0); + + if (ret < 0) + { + veejay_msg(0,"Unable to seek to frame position %ld", ns0); + return -1; + } + //mlt need int16_t + ret = lav_read_audio(el->lav_fd[N_EL_FILE(n)], dst, (ns1 - ns0)); + if (ret < 0) + return -1; + return (ns1 - ns0); + +} + +int vj_el_init_420_frame(editlist *el, VJFrame *frame) +{ + if(!el) return 0; + frame->data[0] = NULL; + frame->data[1] = NULL; + frame->data[2] = NULL; + frame->uv_len = (el->video_width>>1) * (el->video_height>>1); + frame->uv_width = el->video_width >> 1; + frame->uv_height = el->video_height >> 1; + frame->len = el->video_width * el->video_height; + frame->shift_v = 1; + frame->shift_h = 1; + frame->width = el->video_width; + frame->height = el->video_height; + frame->ssm = 0; + frame->stride[0] = el->video_width; + frame->stride[1] = frame->stride[2] = frame->stride[0]/2; + frame->format = el_pixel_format_; + return 1; +} + + +int vj_el_init_422_frame(editlist *el, VJFrame *frame) +{ + if(!el) return 0; + frame->data[0] = NULL; + frame->data[1] = NULL; + frame->data[2] = NULL; + frame->uv_len = (el->video_width>>1) * (el->video_height); + frame->uv_width = el->video_width >> 1; + frame->uv_height = el->video_height; + frame->len = el->video_width * el->video_height; + frame->shift_v = 0; + frame->shift_h = 1; + frame->width = el->video_width; + frame->height = el->video_height; + frame->ssm = 0; + frame->stride[0] = el->video_width; + frame->stride[1] = frame->stride[2] = frame->stride[0]/2; + frame->format = el_pixel_format_; + return 1; +} + +int vj_el_get_audio_frame_at(editlist *el, uint32_t nframe, uint8_t *dst, int num ) +{ + // get audio from current frame + n frames + long pos, asize; + int ret = 0; + uint64_t n; + int ns0, ns1; + + if (!el->has_audio) + return 0; + + if (!el->has_video) + { + int size = el->audio_rate / el->video_fps * el->audio_bps; + veejay_memset(dst,0,size); + return size; + } + if (nframe < 0) + nframe = 0; + + if (nframe >= el->video_frames) + nframe = el->video_frames-1; + + n = el->frame_list[nframe]; + + ns1 = (double) (N_EL_FRAME(n) + num) * el->audio_rate / el->video_fps; + ns0 = (double) N_EL_FRAME(n) * el->audio_rate / el->video_fps; + + //asize = el->audio_rate / el->video_fps; + pos = nframe * asize; + ret = lav_set_audio_position(el->lav_fd[N_EL_FILE(n)], ns0); + + if (ret < 0) + return -1; + + //mlt need int16_t + ret = lav_read_audio(el->lav_fd[N_EL_FILE(n)], dst, (ns1 - ns0)); + if (ret < 0) + return -1; + + return (ns1 - ns0); + +} + + +editlist *vj_el_dummy(int flags, int deinterlace, int chroma, char norm, int width, int height, float fps, int fmt) +{ + editlist *el = vj_calloc(sizeof(editlist)); + if(!el) return NULL; + el->MJPG_chroma = chroma; + el->video_norm = norm; + el->is_empty = 1; + el->is_clone = 1; + el->has_audio = 0; + el->audio_rate = 0; + el->audio_bits = 0; + el->audio_bps = 0; + el->audio_chans = 0; + el->num_video_files = 0; + el->video_width = width; + el->video_height = height; + el->video_frames = DUMMY_FRAMES; /* veejay needs at least 2 frames (play and queue next)*/ + el->total_frames = DUMMY_FRAMES-1; + el->video_fps = fps; + el->video_inter = LAV_NOT_INTERLACED; + + /* output pixel format */ + if( fmt == -1 ) + el->pixel_format = el_pixel_format_; + + el->pixel_format = fmt; + + el->auto_deinter = deinterlace; + el->max_frame_size = width*height*3; + el->last_afile = -1; + el->last_apos = 0; + el->frame_list = NULL; + el->has_video = 0; + el->cache = NULL; + el_len_ = el->video_width * el->video_height; + el_uv_len_ = el_len_; + + switch(fmt) + { + case FMT_422: + case FMT_422F: + el_uv_len_ = el_len_ / 2; + el_uv_wid_ = el->video_width; + break; + } + + return el; +} + +editlist *vj_el_init_with_args(char **filename, int num_files, int flags, int deinterlace, int force ,char norm , int fmt) +{ + editlist *el = vj_calloc(sizeof(editlist)); + FILE *fd; + char line[1024]; + uint64_t index_list[MAX_EDIT_LIST_FILES]; + int num_list_files; + long i,nf=0; + int n1=0; + int n2=0; + long nl=0; + uint64_t n =0; + bzero(line,1024); + if(!el) return NULL; + veejay_memset( el, 0, sizeof(editlist) ); + + el->has_video = 1; //assume we get it + el->MJPG_chroma = CHROMA420; + el->is_empty = 0; + /* Check if a norm parameter is present */ + if(!filename[0] || filename == NULL) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tInvalid filename given"); + vj_el_free(el); + return NULL; + } + + if (strcmp(filename[0], "+p") == 0 || strcmp(filename[0], "+n") == 0) + { + el->video_norm = filename[0][1]; + nf = 1; + veejay_msg(VEEJAY_MSG_DEBUG,"Norm set to %s", el->video_norm == 'n' ? "NTSC" : "PAL"); + } + + if(force) + { + veejay_msg(VEEJAY_MSG_WARNING, "Forcing load on interlacing and gop_size"); + } + + for (; nf < num_files; nf++) + { + /* Check if file really exists, is mounted etc... */ + struct stat fileinfo; + if(stat( filename[nf], &fileinfo)!= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to access file '%s'",filename[nf] ); + vj_el_free(el); + return NULL; + } + fd = fopen(filename[nf], "r"); + if (fd <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Error opening %s:", filename[nf]); + vj_el_free(el); + return NULL; + } + + fgets(line, 1024, fd); + if (strcmp(line, "LAV Edit List\n") == 0) + { + /* Ok, it is a edit list */ + veejay_msg(VEEJAY_MSG_DEBUG, "Edit list %s opened", filename[nf]); + /* Read second line: Video norm */ + fgets(line, 1024, fd); + if (line[0] != 'N' && line[0] != 'n' && line[0] != 'P' && line[0] != 'p') + { + veejay_msg(VEEJAY_MSG_ERROR,"Edit list second line is not NTSC/PAL"); + vj_el_free(el); + return NULL; + } + veejay_msg(VEEJAY_MSG_DEBUG,"Edit list norm is %s", line[0] =='N' || line[0] == 'n' ? "NTSC" : "PAL" ); + if (line[0] == 'N' || line[0] == 'n') + { + if (el->video_norm == 'p') + { + veejay_msg(VEEJAY_MSG_WARNING, "Norm already set to PAL, ignoring new norm 'NTSC'"); + } + else el->video_norm = 'n'; + } + else + { + if (el->video_norm == 'n') + { + veejay_msg(VEEJAY_MSG_WARNING,"Norm allready set to NTSC, ignoring new norm PAL"); + } + else + el->video_norm = 'p'; + } + /* read third line: Number of files */ + fgets(line, 1024, fd); + sscanf(line, "%d", &num_list_files); + + veejay_msg(VEEJAY_MSG_DEBUG, "Edit list contains %d files", num_list_files); + /* read files */ + + for (i = 0; i < num_list_files; i++) + { + fgets(line, 1024, fd); + n = strlen(line); + + if (line[n - 1] != '\n') + { + veejay_msg(VEEJAY_MSG_ERROR, "Filename in edit list too long"); + vj_el_free(el); + return NULL; + } + + line[n - 1] = 0; /* Get rid of \n at end */ + + index_list[i] = + open_video_file(line, el, flags, deinterlace,force,norm); + + if(index_list[i]< 0) + { + vj_el_free(el); + return NULL; + } + + /* el->frame_list = (uint64_t *) realloc(el->frame_list, + (el->video_frames + + el->num_frames[i]) * + sizeof(uint64_t)); + if (el->frame_list==NULL) + { + veejay_msg(VEEJAY_MSG_ERROR, "Insufficient memory to allocate frame_list"); + vj_el_free(el); + return NULL; + } + + long x = el->num_frames[i] + el->total_frames; + long j; + for (j = el->video_frames; j < x; j++) + { + el->frame_list[el->video_frames] = EL_ENTRY(n, j); + el->video_frames++; + }*/ + + + } + + /* Read edit list entries */ + + while (fgets(line, 1024, fd)) + { + if (line[0] != ':') + { /* ignore lines starting with a : */ + sscanf(line, "%ld %d %d", &nl, &n1, &n2); + + if (nl < 0 || nl >= num_list_files) + { + veejay_msg(VEEJAY_MSG_ERROR,"Wrong file number in edit list entry"); + vj_el_free(el); + return NULL; + } + if (n1 < 0) + n1 = 0; + if (n2 >= el->num_frames[index_list[nl]]) + n2 = el->num_frames[index_list[nl]]; + if (n2 < n1) + continue; + + el->frame_list = (uint64_t *) realloc(el->frame_list, + (el->video_frames + + n2 - n1 + + 1) * sizeof(uint64_t)); + + if (el->frame_list==NULL) + { + veejay_msg(VEEJAY_MSG_ERROR, "Insufficient memory to allocate frame_list"); + vj_el_free(el); + return NULL; + } + + + for (i = n1; i <= n2; i++) + { + el->frame_list[el->video_frames] = EL_ENTRY( index_list[ nl], i); + + el->video_frames++; + } + } + } /* done reading editlist entries */ + fclose(fd); + } + else + { + /* Not an edit list - should be a ordinary video file */ + fclose(fd); + + n = open_video_file(filename[nf], el, flags, deinterlace,force,norm); + if(n >= 0 ) + { + el->frame_list = (uint64_t *) realloc(el->frame_list, + (el->video_frames + + el->num_frames[n]) * + sizeof(uint64_t)); + if (el->frame_list==NULL) + { + veejay_msg(VEEJAY_MSG_ERROR, "Insufficient memory to allocate frame_list"); + vj_el_free(el); + return NULL; + } + + for (i = 0; i < el->num_frames[n]; i++) + { + el->frame_list[el->video_frames] = EL_ENTRY(n, i); + el->video_frames++; + } + } + } + } + + if( el->num_video_files == 0 || + el->video_width == 0 || el->video_height == 0 || el->video_frames < 2) + { + if( el->video_frames < 2 ) { + veejay_msg(VEEJAY_MSG_ERROR, "\tFile has only %d frame(s)", el->video_frames ); + vj_el_free(el); return NULL; + } + if( el->num_video_files == 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, "\tNo videofiles in EDL"); + vj_el_free(el); return NULL; + } + if( el->video_height == 0 || el->video_width == 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, "\tImage dimensions unknown"); + vj_el_free(el); return NULL; + } + vj_el_free(el); + return NULL; + } + + /* do we have anything? */ + + /* Calculate maximum frame size */ + + for (i = 0; i < el->video_frames; i++) + { + n = el->frame_list[i]; + if(!el->lav_fd[N_EL_FILE(n)] ) + { + veejay_msg(VEEJAY_MSG_ERROR, "\tUnable to read file"); + vj_el_free(el); + return NULL; + } + if (lav_frame_size(el->lav_fd[N_EL_FILE(n)], N_EL_FRAME(n)) > + el->max_frame_size) + el->max_frame_size = + lav_frame_size(el->lav_fd[N_EL_FILE(n)], N_EL_FRAME(n)); + + + } + + /* Pick a pixel format */ + + el->pixel_format = el_pixel_format_; + + /* Help for audio positioning */ + + el->last_afile = -1; + + + //el->auto_deinter = auto_deinter; + //if(el->video_inter != 0 ) el->auto_deinter = 0; + el->auto_deinter = 0; + el->total_frames = el->video_frames - 1; + + el_len_ = el->video_width * el->video_height; + el_uv_len_ = el_len_; + + switch( el_pixel_format_ ) + { + case FMT_422: + case FMT_422F: + el_uv_len_ = el_len_ / 2; + el_uv_wid_ = el->video_width; + break; + } + + return el; +} + + +void vj_el_free(editlist *el) +{ + if(!el) + return; + + int i; + if(el->is_clone) + { + for( i = 0; i < el->num_video_files; i ++ ) + { + if( el->video_file_list[i]) + free(el->video_file_list[i] ); + } + } + else + { + for ( i = 0; i < el->num_video_files; i ++ ) + { + if( el->lav_fd[i] ) + { + lav_close( el->lav_fd[i] ); + el->lav_fd[i] = NULL; + } + if( el->video_file_list[i]) { + free(el->video_file_list[i]); + el->video_file_list[i] = NULL; + } + } + } + + if( el->cache ) + free_cache( el->cache ); + if( el->frame_list ) + free(el->frame_list ); + if( el->scaler ) + yuv_free_swscaler( el->scaler ); + free(el); + + el = NULL; +} + +void vj_el_print(editlist *el) +{ + int i; + char timecode[64]; + char interlacing[64]; + MPEG_timecode_t ttc; + veejay_msg(VEEJAY_MSG_INFO,"EditList settings: Video:%dx%d@%2.2f %s\tAudio:%d Hz/%d channels/%d bits", + el->video_width,el->video_height,el->video_fps,(el->video_norm=='p' ? "PAL" :"NTSC"), + el->audio_rate, el->audio_chans, el->audio_bits); + for(i=0; i < el->num_video_files ; i++) + { + long num_frames = lav_video_frames(el->lav_fd[i]); + MPEG_timecode_t tc; + switch( lav_video_interlacing(el->lav_fd[i])) + { + case LAV_NOT_INTERLACED: + sprintf(interlacing, "Not interlaced"); break; + case LAV_INTER_TOP_FIRST: + sprintf(interlacing,"Top field first"); break; + case LAV_INTER_BOTTOM_FIRST: + sprintf(interlacing, "Bottom field first"); break; + default: + sprintf(interlacing, "Unknown !"); break; + } + + mpeg_timecode(&tc, num_frames, + mpeg_framerate_code( mpeg_conform_framerate( el->video_fps )), + el->video_fps ); + + sprintf( timecode, "%2d:%2.2d:%2.2d:%2.2d", tc.h, tc.m, tc.s, tc.f ); + + veejay_msg(VEEJAY_MSG_INFO, "\tFile %s (%s) with %ld frames (total duration %s)", + el->video_file_list[i], + interlacing, + num_frames, + timecode ); + + } + + mpeg_timecode(&ttc, el->video_frames, + mpeg_framerate_code( mpeg_conform_framerate( el->video_fps )), + el->video_fps ); + + sprintf( timecode, "%2d:%2.2d:%2.2d:%2.2d", ttc.h, ttc.m, ttc.s, ttc.f ); + + + veejay_msg(VEEJAY_MSG_INFO, "\tDuration: %s (%2d hours, %2d minutes)(%ld frames)", timecode,ttc.h,ttc.m,el->video_frames); + + + + +} + +MPEG_timecode_t get_timecode(editlist *el, long num_frames) +{ + MPEG_timecode_t tc; + veejay_memset(&tc,0,sizeof(tc)); + mpeg_timecode(&tc, num_frames, + mpeg_framerate_code( mpeg_conform_framerate( el->video_fps )), + el->video_fps ); + return tc; +} + +int vj_el_get_file_entry(editlist *el, long *start_pos, long *end_pos, long entry ) +{ + if(entry >= el->num_video_files) + return 0; + + int64_t n = (int64_t) entry; + int64_t i = 0; + + if( el->video_file_list[ n ] == NULL ) + return 0; + + *start_pos = 0; + + for( i = 0;i < n ; i ++ ) + *start_pos += el->num_frames[i]; + + *end_pos = (*start_pos + el->num_frames[n] - 1); + + return 1; +} + + + +char *vj_el_write_line_ascii( editlist *el, int *bytes_written ) +{ + if(el == NULL || el->is_empty) + return NULL; + + int num_files = 0; + int64_t oldfile, oldframe, of1,ofr; + int64_t index[MAX_EDIT_LIST_FILES]; //@ TRACE + int64_t n,n1=0; + char *result = NULL; + int64_t j = 0; + int64_t n2 = el->video_frames-1; + char filename[2048]; //@ TRACE + char fourcc[6]; //@ TRACE + +#ifdef STRICT_CHECKING + int dbg_buflen = 0; +#endif + /* get which files are actually referenced in the edit list entries */ + + int est_len = 0; + for (j = 0; j < MAX_EDIT_LIST_FILES; j++) + index[j] = -1; + + for (j = n1; j <= n2; j++) + { + n = el->frame_list[j]; + index[N_EL_FILE(n)] = 1; + } + + num_files = 0; + int nnf = 0; + long len = 0; + + for (j = 0; j < MAX_EDIT_LIST_FILES; j++) + { + if (index[j] >= 0 && el->video_file_list[j] != NULL ) + { + index[j] = (int64_t)num_files; + nnf ++; + len += (strlen(el->video_file_list[j])) + 25 + 20; + num_files ++; + } + } + + + n = el->frame_list[n1]; + oldfile = index[ N_EL_FILE(n) ]; + oldframe = N_EL_FRAME(n); + + n1 = n; + of1 = oldfile; + ofr = oldframe; + + for (j = n1+1; j <= n2; j++) + { + n = el->frame_list[j]; + if ( index[ N_EL_FILE(n) ] != oldfile || + N_EL_FRAME(n) != oldframe + 1 ) { + len += (3*16); + } + oldfile = index[N_EL_FILE(n)]; + oldframe = N_EL_FRAME(n); + } + + n = n1; + oldfile = of1; + oldframe = ofr; + + n1 = 0; + + est_len = 64 + len; + +#ifdef STRICT_CHECKING + dbg_buflen = est_len; +#endif + result = (char*) vj_calloc(sizeof(char) * est_len ); + sprintf(result, "%04d",nnf ); + + for (j = 0; j < MAX_EDIT_LIST_FILES; j++) + { + if (index[j] >= 0 && el->video_file_list[j] != NULL) + { + snprintf(fourcc,sizeof(fourcc),"%s", "????"); + vj_el_get_file_fourcc( el, j, fourcc ); + snprintf(filename,sizeof(filename),"%03d%s%04d%010ld%02d%s", + strlen( el->video_file_list[j] ), + el->video_file_list[j], + (unsigned long) j, + el->num_frames[j], + strlen(fourcc), + fourcc + ); +#ifdef STRICT_CHECKING + dbg_buflen -= strlen(filename); + assert( dbg_buflen > 0); +#endif + veejay_strncat ( result, filename, strlen(filename)); + } + } + + + char first[256]; + char tmpbuf[256]; + snprintf(first,sizeof(first), "%016lld%016lld",oldfile, oldframe); +#ifdef STRICT_CHECKING + dbg_buflen -= strlen(first); + assert( dbg_buflen > 0 ); +#endif + veejay_strncat( result, first, strlen(first) ); + + for (j = n1+1; j <= n2; j++) + { + n = el->frame_list[j]; + if ( index[ N_EL_FILE(n) ] != oldfile || + N_EL_FRAME(n) != oldframe + 1 ) + { + snprintf( tmpbuf,sizeof(tmpbuf), "%016lld%016lld%016lld", + oldframe, + index[N_EL_FILE(n)], + N_EL_FRAME(n) ); +#ifdef STRICT_CHECKING + dbg_buflen -= strlen(tmpbuf); + assert( dbg_buflen > 0 ); +#endif + veejay_strncat( result, tmpbuf, strlen(tmpbuf) ); + } + oldfile = index[N_EL_FILE(n)]; + oldframe = N_EL_FRAME(n); + } + + char last_word[64]; + sprintf(last_word,"%016lld", oldframe); +#ifdef STRICT_CHECKING + dbg_buflen -= 16; + assert( dbg_buflen > 0 ); +#endif + veejay_strncat( result, last_word, 16 ); + + int datalen = strlen(result); + *bytes_written = datalen; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "EL estimated %d bytes, %d remaining bytes, %d used bytes",est_len,dbg_buflen,datalen); +#endif + return result; +} + +int vj_el_write_editlist( char *name, long _n1, long _n2, editlist *el ) +{ + FILE *fd; + int num_files; + int64_t oldfile, oldframe; + int64_t index[MAX_EDIT_LIST_FILES]; + int64_t n; + int64_t n1 = (uint64_t) _n1; + int64_t n2 = (uint64_t) _n2; + int64_t i; + + if(!el) + return 0; + + if(el->is_empty) + { + veejay_msg(VEEJAY_MSG_ERROR, "No frames in EditList" ); + return 0; + } + + if (n1 < 0) + n1 = 0; + + if (n2 >= el->video_frames || n2 < n1) + n2 = el->video_frames - 1; + + fd = fopen(name, "w"); + + if (!fd) + { + veejay_msg(VEEJAY_MSG_ERROR,"Can not open %s - no edit list written!", name); + return 0; + } + + fprintf(fd, "LAV Edit List\n"); + fprintf(fd, "%s\n", el->video_norm == 'n' ? "NTSC" : "PAL"); + + /* get which files are actually referenced in the edit list entries */ + + for (i = 0; i < MAX_EDIT_LIST_FILES; i++) + index[i] = -1; + + for (i = n1; i <= n2; i++) + index[N_EL_FILE(el->frame_list[i])] = 1; + + num_files = 0; + for (i = 0; i < MAX_EDIT_LIST_FILES; i++) + if (index[i] > 0) index[i] = (int64_t)num_files++; + + fprintf(fd, "%d\n", num_files); + for (i = 0; i < MAX_EDIT_LIST_FILES; i++) + if (index[i] >= 0 && el->video_file_list[i] != NULL) + { + fprintf(fd, "%s\n", el->video_file_list[i]); + } + + n = el->frame_list[ n1 ]; + oldfile = index[N_EL_FILE(n)]; + oldframe = N_EL_FRAME(n); + + fprintf(fd, "%lld %lld ", oldfile, oldframe); + for (i = n1 + 1; i <= n2; i++) + { + n = el->frame_list[i]; + if (index[N_EL_FILE(n)] != oldfile + || N_EL_FRAME(n) != oldframe + 1) + { + fprintf(fd, "%lld\n", oldframe); + fprintf(fd, "%lld %lld ",index[N_EL_FILE(n)], N_EL_FRAME(n)); + } + oldfile = index[N_EL_FILE(n)]; + oldframe = N_EL_FRAME(n); + } + n = fprintf(fd, "%lld\n", oldframe); + + /* We did not check if all our prints succeeded, so check at least the last one */ + if (n <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Error writing edit list: "); + return 0; + } + el->total_frames = el->video_frames - 1; + fclose(fd); + + return 1; +} + +void vj_el_frame_cache(int n ) +{ + if(n > 1 || n < 1000) + { + mmap_size = n; + } +} + +editlist *vj_el_soft_clone(editlist *el) +{ + editlist *clone = (editlist*) vj_calloc(sizeof(editlist)); + if(!clone) + return NULL; + clone->is_empty = el->is_empty; + clone->has_video = el->has_video; + clone->video_width = el->video_width; + clone->video_height = el->video_height; + clone->video_fps = el->video_fps; + clone->video_sar_width = el->video_sar_width; + clone->video_sar_height = el->video_sar_height; + clone->video_norm = el->video_norm; + clone->has_audio = el->has_audio; + clone->audio_rate = el->audio_rate; + clone->audio_chans = el->audio_chans; + clone->audio_bits = el->audio_bits; + clone->audio_bps = el->audio_bps; + clone->video_frames = el->video_frames; + clone->total_frames = el->video_frames-1; + clone->num_video_files = el->num_video_files; + clone->max_frame_size = el->max_frame_size; + clone->MJPG_chroma = el->MJPG_chroma; + clone->frame_list = NULL; + clone->last_afile = el->last_afile; + clone->last_apos = el->last_apos; + clone->auto_deinter = el->auto_deinter; + clone->pixel_format = el->pixel_format; + clone->is_clone = 1; + int i; + for( i = 0; i < MAX_EDIT_LIST_FILES; i ++ ) + { + clone->video_file_list[i] = NULL; + clone->lav_fd[i] = NULL; + clone->num_frames[i] = 0; + clone->yuv_taste[i] = 0; + if( el->lav_fd[i] && el->video_file_list[i]) + { + clone->video_file_list[i] = strdup( el->video_file_list[i] ); + clone->lav_fd[i] = el->lav_fd[i]; + clone->num_frames[i] = el->num_frames[i]; + clone->yuv_taste[i] =el->yuv_taste[i]; + } + } + + return clone; +} + +int vj_el_framelist_clone( editlist *src, editlist *dst) +{ + if(!src || !dst) return 0; + if(dst->frame_list) + return 0; + dst->frame_list = (uint64_t*) vj_malloc(sizeof(uint64_t) * src->video_frames ); + if(!dst->frame_list) + return 0; + + veejay_memcpy( + dst->frame_list, + src->frame_list, + (sizeof(uint64_t) * src->video_frames ) + ); + + return 1; +} + +editlist *vj_el_clone(editlist *el) +{ + editlist *clone = (editlist*) vj_el_soft_clone(el); + if(!clone) + return NULL; + + if( vj_el_framelist_clone( el, clone ) ) + return clone; + else + { + if(clone) vj_el_free(clone); + veejay_msg(VEEJAY_MSG_ERROR, "Cannot clone: Memory error?!"); + } + + return clone; +} diff --git a/branches/V-1.5.3/veejay-server/libel/vj-el.h b/branches/V-1.5.3/veejay-server/libel/vj-el.h new file mode 100644 index 00000000..4ffe53d8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-el.h @@ -0,0 +1,152 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_MLT_EL_H +#define VJ_MLT_EL_H +#include +#include +#include +#include +#define N_EL_FRAME(x) ( (x)&0xfffffffffffffLLU ) +#define N_EL_FILE(x) (uint32_t) ( ((x)>>52)&0xfffU ) +/* ((file)&0xfff<<52) */ +#define EL_ENTRY(file,frame) ( ((file)<<52) | ((frame)& 0xfffffffffffffLLU) ) + +//#define FMT_420 0 +//#define FMT_422 1 +//#define MAX_EDITLIST_FILES 4096 + + +typedef struct +{ + int has_video; + int is_empty; + int video_width; + int video_height; + int video_inter; + float video_fps; + int video_sar_width; + int video_sar_height; + char video_norm; + + int has_audio; + long audio_rate; + int audio_chans; + int audio_bits; + int audio_bps; + + long video_frames; + long total_frames; + long num_video_files; + + long max_frame_size; + int MJPG_chroma; + + char *(video_file_list[MAX_EDIT_LIST_FILES]); + lav_file_t *(lav_fd[MAX_EDIT_LIST_FILES]); + int yuv_taste[MAX_EDIT_LIST_FILES]; + + long num_frames[MAX_EDIT_LIST_FILES]; + uint64_t *frame_list; + + int last_afile; + long last_apos; + int auto_deinter; + + int pixel_format; + void *cache; + + int is_clone; + void *scaler; +} editlist; + +int test_video_frame( lav_file_t *lav,int out_pix_fmt); + + +editlist *vj_el_init_with_args(char **filenames, int n, int flags, int deinter, int force, char norm, int fmt); + +int vj_el_cache_size(); + +void vj_el_prepare(void); // reset cache + +void vj_el_init(int out, int sj, int dw, int dh, float fps); + +void vj_el_init_chunk(int n); + +int vj_el_is_dv(editlist *el); + + +void vj_el_free(editlist *el); + +int vj_el_get_audio_frame_at(editlist *el, uint32_t nframe, uint8_t *dst, int speed ); + +int vj_el_append_video_file(editlist *el, char *filename); + +int vj_el_write_editlist( char *filename, long start, long end, editlist *el ); + +int vj_el_get_video_frame(editlist *el, long nframe, uint8_t *dst[3]); + +void vj_el_break_cache( editlist *el ); + +void vj_el_setup_cache( editlist *el ); + +int vj_el_get_audio_frame(editlist *el, uint32_t nframe, uint8_t *dst); + +int vj_el_get_file_fourcc(editlist *el, int num, char *buf); + +void vj_el_print(editlist *el); + +int vj_el_init_420_frame(editlist *el, VJFrame *frame); +int vj_el_init_422_frame(editlist *el, VJFrame *frame); + +void vj_el_frame_cache(int n); + +void vj_el_show_formats(void); + +editlist *vj_el_dummy(int flags, int deinterlace, int chroma, char norm, int width, int height, float fps, int fmt); + +int vj_el_get_file_entry( editlist *el,long *start_pos, long *end_pos, long entry ); + +editlist *vj_el_clone(editlist *el); + +editlist *vj_el_soft_clone(editlist *el); + +int vj_el_framelist_clone( editlist *src, editlist *dst); + +char *vj_el_write_line_ascii( editlist *el, int *bytes_written ); + +void vj_el_deinit(); + +void vj_el_clear_cache( editlist *el ); + +int get_ffmpeg_pixfmt( int pf ); + +void vj_el_set_image_output_size(editlist *el,int w, int h, float fps, int pf); + +int open_video_file(char *filename, editlist * el, int preserve_pathname, int deinter, int force, char override_norm); + +void vj_el_set_caching(int status); + +int vj_el_bogus_length( editlist *el, long nframe ); + +int vj_el_set_bogus_length( editlist *el, long nframe, int len ); + +void vj_el_get_video_fourcc(editlist *el, int num, char *fourcc); + + +#endif diff --git a/branches/V-1.5.3/veejay-server/libel/vj-mmap.c b/branches/V-1.5.3/veejay-server/libel/vj-mmap.c new file mode 100644 index 00000000..c63a2bd6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-mmap.c @@ -0,0 +1,139 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define PADDED(a,m) ( a > 0 ? (a / m->page_size) * m->page_size : 0) + +void mmap_free(mmap_region_t *map) +{ + if(map) + { + if(map->map_start) + munmap_file(map); + free(map); + } + map = NULL; +} + +mmap_region_t * mmap_file(int fd, int offset, int length, int fs) +{ + mmap_region_t *map = (mmap_region_t*) malloc(sizeof( mmap_region_t )); + memset( map, 0, sizeof( mmap_region_t )); + + map->fd = fd; + map->page_size = getpagesize(); + map->map_length = length; + map->map_start = NULL; + map->eof = fs; + map->mem_offset = offset; + remap_file( map, offset ); + veejay_msg(VEEJAY_MSG_DEBUG, "Memory map region is %f Mb", + ( (float) length / 1048576.0 ) ); + return map; +} + + +int is_mapped( mmap_region_t *map, int offset, int size ) +{ + // check if memory is in mapped region + off_t real_offset = PADDED( offset, map ); + size_t padding = offset % map->page_size; + + long rel_o = (map->mem_offset > 0 ? offset - map->mem_offset : offset ); + + if( (rel_o + size) > map->map_length ) + { + return 0; + } + + if( real_offset >= map->start_region && + real_offset + size <= map->end_region ) + return 1; + + return 0; +} + +int remap_file( mmap_region_t *map, int offset ) +{ + size_t padding = offset % map->page_size; + size_t new_length = map->map_length; + size_t real_length = 0; + off_t real_offset = PADDED( offset, map ); + + real_length = (padding + new_length); + if( real_length > map->eof ) + { + real_length = PADDED(map->eof ,map); + } + if(map->map_start != NULL) + { + munmap_file( map ); + } + + map->mem_offset = offset; + map->map_start = mmap( 0, real_length, PROT_READ, MAP_SHARED, map->fd, real_offset ); + if( map->map_start == MAP_FAILED) + { + veejay_msg(VEEJAY_MSG_ERROR, "mmap error %s", strerror(errno)); + return 0; + } + + map->data_start = map->map_start + padding; + + map->start_region = real_offset; + map->end_region = real_length + real_offset; + + return 1; +} + +int munmap_file( mmap_region_t *map ) +{ + if(map->map_start == NULL) + return 1; + + int n = munmap( map->map_start, map->map_length ); + if(n==-1) + { + veejay_msg(VEEJAY_MSG_ERROR, "leaving garbage %s", + strerror(errno)); + } + map->map_start = NULL; + return n; +} + +int mmap_read( mmap_region_t *map,int offset, int bytes, uint8_t *buf ) +{ + size_t padding = offset % map->page_size; + if( !is_mapped( map, offset, bytes )) + { + remap_file( map, offset ); + } + + int rel_offset = (map->mem_offset > 0 ? offset - map->mem_offset : offset ); + + uint8_t *d1 = map->data_start + rel_offset; + veejay_memcpy( buf, d1, bytes ); + return bytes; +} diff --git a/branches/V-1.5.3/veejay-server/libel/vj-mmap.h b/branches/V-1.5.3/veejay-server/libel/vj-mmap.h new file mode 100644 index 00000000..ec07b86a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libel/vj-mmap.h @@ -0,0 +1,53 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#ifndef VJ_MMAP_H +#define VJ_MMAP_H +#include +#include +#include +typedef struct +{ + unsigned char *map_start; /* result of mmap() */ + unsigned char *data_start; /* start of data */ + uint64_t start_region; + uint64_t end_region; + off_t mem_offset; /* start of image */ + int fd; /* file descriptor */ + size_t page_size; /* page size */ + size_t map_length; /* requested map size */ + long eof; /* file size */ +} mmap_region_t; + +// map file portion to memory, return mapped region +mmap_region_t * mmap_file(int fd, int offset, int length, int fs); + +// see if requested boundaries is mapped in memory +int is_mapped( mmap_region_t *map, int offset, int size ); + +// remap a portion of a file in memory +int remap_file( mmap_region_t *map, int offset ); + +// unmap memory +int munmap_file( mmap_region_t *map ); + +void mmap_free(mmap_region_t *map ); + +int mmap_read( mmap_region_t *map, int offset, int bytes, uint8_t *buf); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libhash/Makefile.am b/branches/V-1.5.3/veejay-server/libhash/Makefile.am new file mode 100644 index 00000000..daae4010 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libhash/Makefile.am @@ -0,0 +1,9 @@ +# Makefile for veejay +EXTRA_DIST= hash.h +MAINTAINERCLEANFILES=Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) +HASH_LIB_FILE = libhash.la +noinst_LTLIBRARIES = $(HASH_LIB_FILE) +libhash_la_SOURCES = hash.c + diff --git a/branches/V-1.5.3/veejay-server/libhash/hash.c b/branches/V-1.5.3/veejay-server/libhash/hash.c new file mode 100644 index 00000000..8141447f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libhash/hash.c @@ -0,0 +1,1072 @@ +/* + * Hash Table Data Type + * Copyright (C) 1997 Kaz Kylheku + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Id: hash.c,v 1.36.2.11 2000/11/13 01:36:45 kaz Exp $ + * $Name: kazlib_1_20 $ + */ + +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#include +#define HASH_IMPLEMENTATION +#include "hash.h" + +#ifdef KAZLIB_RCSID +static const char rcsid[] = "$Id: hash.c,v 1.36.2.11 2000/11/13 01:36:45 kaz Exp $"; +#endif + +#define INIT_BITS 6 +#define INIT_SIZE (1UL << (INIT_BITS)) /* must be power of two */ +#define INIT_MASK ((INIT_SIZE) - 1) + +#define next hash_next +#define key hash_key +#define data hash_data +#define hkey hash_hkey + +#define table hash_table +#define nchains hash_nchains +#define nodecount hash_nodecount +#define maxcount hash_maxcount +#define highmark hash_highmark +#define lowmark hash_lowmark +#define compare hash_compare +#define function hash_function +#define allocnode hash_allocnode +#define freenode hash_freenode +#define context hash_context +#define mask hash_mask +#define dynamic hash_dynamic + +#define table hash_table +#define chain hash_chain + +static hnode_t *hnode_alloc(void *context); +static void hnode_free(hnode_t *node, void *context); +static hash_val_t hash_fun_default(const void *key); +static int hash_comp_default(const void *key1, const void *key2); + +int hash_val_t_bit; + +/* + * Compute the number of bits in the hash_val_t type. We know that hash_val_t + * is an unsigned integral type. Thus the highest value it can hold is a + * Mersenne number (power of two, less one). We initialize a hash_val_t + * object with this value and then shift bits out one by one while counting. + * Notes: + * 1. HASH_VAL_T_MAX is a Mersenne number---one that is one less than a power + * of two. This means that its binary representation consists of all one + * bits, and hence ``val'' is initialized to all one bits. + * 2. While bits remain in val, we increment the bit count and shift it to the + * right, replacing the topmost bit by zero. + */ + +static void compute_bits(void) +{ + hash_val_t val = HASH_VAL_T_MAX; /* 1 */ + int bits = 0; + + while (val) { /* 2 */ + bits++; + val >>= 1; + } + + hash_val_t_bit = bits; +} + +/* + * Verify whether the given argument is a power of two. + */ + +static int is_power_of_two(hash_val_t arg) +{ + if (arg == 0) + return 0; + while ((arg & 1) == 0) + arg >>= 1; + return (arg == 1); +} + +/* + * Compute a shift amount from a given table size + */ + +static hash_val_t compute_mask(hashcount_t size) +{ +#ifdef STRICT_CHECKING + assert (is_power_of_two(size)); + assert (size >= 2); +#endif + return size - 1; +} + +/* + * Initialize the table of pointers to null. + */ + +static void clear_table(hash_t *hash) +{ + hash_val_t i; + + for (i = 0; i < hash->nchains; i++) + hash->table[i] = NULL; +} + +/* + * Double the size of a dynamic table. This works as follows. Each chain splits + * into two adjacent chains. The shift amount increases by one, exposing an + * additional bit of each hashed key. For each node in the original chain, the + * value of this newly exposed bit will decide which of the two new chains will + * receive the node: if the bit is 1, the chain with the higher index will have + * the node, otherwise the lower chain will receive the node. In this manner, + * the hash table will continue to function exactly as before without having to + * rehash any of the keys. + * Notes: + * 1. Overflow check. + * 2. The new number of chains is twice the old number of chains. + * 3. The new mask is one bit wider than the previous, revealing a + * new bit in all hashed keys. + * 4. Allocate a new table of chain pointers that is twice as large as the + * previous one. + * 5. If the reallocation was successful, we perform the rest of the growth + * algorithm, otherwise we do nothing. + * 6. The exposed_bit variable holds a mask with which each hashed key can be + * AND-ed to test the value of its newly exposed bit. + * 7. Now loop over each chain in the table and sort its nodes into two + * chains based on the value of each node's newly exposed hash bit. + * 8. The low chain replaces the current chain. The high chain goes + * into the corresponding sister chain in the upper half of the table. + * 9. We have finished dealing with the chains and nodes. We now update + * the various bookeeping fields of the hash structure. + */ + +static void grow_table(hash_t *hash) +{ + hnode_t **newtable; +#ifdef STRICT_CHECKING + assert (2 * hash->nchains > hash->nchains); /* 1 */ +#endif + newtable = realloc(hash->table, + sizeof *newtable * hash->nchains * 2); /* 4 */ + + if (newtable) { /* 5 */ + hash_val_t mask = (hash->mask << 1) | 1; /* 3 */ + hash_val_t exposed_bit = mask ^ hash->mask; /* 6 */ + hash_val_t chain; +#ifdef STRICT_CHECKING + assert (mask != hash->mask); +#endif + for (chain = 0; chain < hash->nchains; chain++) { /* 7 */ + hnode_t *low_chain = 0, *high_chain = 0, *hptr, *next; + + for (hptr = newtable[chain]; hptr != 0; hptr = next) { + next = hptr->next; + + if (hptr->hkey & exposed_bit) { + hptr->next = high_chain; + high_chain = hptr; + } else { + hptr->next = low_chain; + low_chain = hptr; + } + } + + newtable[chain] = low_chain; /* 8 */ + newtable[chain + hash->nchains] = high_chain; + } + + hash->table = newtable; /* 9 */ + hash->mask = mask; + hash->nchains *= 2; + hash->lowmark *= 2; + hash->highmark *= 2; + } +#ifdef STRICT_CHECKING +// assert (hash_verify(hash)); +#endif +} + +/* + * Cut a table size in half. This is done by folding together adjacent chains + * and populating the lower half of the table with these chains. The chains are + * simply spliced together. Once this is done, the whole table is reallocated + * to a smaller object. + * Notes: + * 1. It is illegal to have a hash table with one slot. This would mean that + * hash->shift is equal to hash_val_t_bit, an illegal shift value. + * Also, other things could go wrong, such as hash->lowmark becoming zero. + * 2. Looping over each pair of sister chains, the low_chain is set to + * point to the head node of the chain in the lower half of the table, + * and high_chain points to the head node of the sister in the upper half. + * 3. The intent here is to compute a pointer to the last node of the + * lower chain into the low_tail variable. If this chain is empty, + * low_tail ends up with a null value. + * 4. If the lower chain is not empty, we simply tack the upper chain onto it. + * If the upper chain is a null pointer, nothing happens. + * 5. Otherwise if the lower chain is empty but the upper one is not, + * If the low chain is empty, but the high chain is not, then the + * high chain is simply transferred to the lower half of the table. + * 6. Otherwise if both chains are empty, there is nothing to do. + * 7. All the chain pointers are in the lower half of the table now, so + * we reallocate it to a smaller object. This, of course, invalidates + * all pointer-to-pointers which reference into the table from the + * first node of each chain. + * 8. Though it's unlikely, the reallocation may fail. In this case we + * pretend that the table _was_ reallocated to a smaller object. + * 9. Finally, update the various table parameters to reflect the new size. + */ + +static void shrink_table(hash_t *hash) +{ + hash_val_t chain, nchains; + hnode_t **newtable, *low_tail, *low_chain, *high_chain; +#ifdef STRICT_CHECKING + assert (hash->nchains >= 2); /* 1 */ +#endif + + nchains = hash->nchains / 2; + + for (chain = 0; chain < nchains; chain++) { + low_chain = hash->table[chain]; /* 2 */ + high_chain = hash->table[chain + nchains]; + for (low_tail = low_chain; low_tail && low_tail->next; low_tail = low_tail->next) + ; /* 3 */ + if (low_chain != 0) /* 4 */ + low_tail->next = high_chain; + else if (high_chain != 0) /* 5 */ + hash->table[chain] = high_chain; +#ifdef STRICT_CHECKING + else + assert (hash->table[chain] == NULL); /* 6 */ +#endif + } + newtable = realloc(hash->table, + sizeof *newtable * nchains); /* 7 */ + if (newtable) /* 8 */ + hash->table = newtable; + hash->mask >>= 1; /* 9 */ + hash->nchains = nchains; + hash->lowmark /= 2; + hash->highmark /= 2; +#ifdef STRICT_CHECKING +// assert (hash_verify(hash)); +#endif +} + + +/* + * Create a dynamic hash table. Both the hash table structure and the table + * itself are dynamically allocated. Furthermore, the table is extendible in + * that it will automatically grow as its load factor increases beyond a + * certain threshold. + * Notes: + * 1. If the number of bits in the hash_val_t type has not been computed yet, + * we do so here, because this is likely to be the first function that the + * user calls. + * 2. Allocate a hash table control structure. + * 3. If a hash table control structure is successfully allocated, we + * proceed to initialize it. Otherwise we return a null pointer. + * 4. We try to allocate the table of hash chains. + * 5. If we were able to allocate the hash chain table, we can finish + * initializing the hash structure and the table. Otherwise, we must + * backtrack by freeing the hash structure. + * 6. INIT_SIZE should be a power of two. The high and low marks are always set + * to be twice the table size and half the table size respectively. When the + * number of nodes in the table grows beyond the high size (beyond load + * factor 2), it will double in size to cut the load factor down to about + * about 1. If the table shrinks down to or beneath load factor 0.5, + * it will shrink, bringing the load up to about 1. However, the table + * will never shrink beneath INIT_SIZE even if it's emptied. + * 7. This indicates that the table is dynamically allocated and dynamically + * resized on the fly. A table that has this value set to zero is + * assumed to be statically allocated and will not be resized. + * 8. The table of chains must be properly reset to all null pointers. + */ + +hash_t *hash_create(hashcount_t maxcount, hash_comp_t compfun, + hash_fun_t hashfun) +{ + hash_t *hash; + + if (hash_val_t_bit == 0) /* 1 */ + compute_bits(); + + hash = malloc(sizeof *hash); /* 2 */ + + if (hash) { /* 3 */ + hash->table = malloc(sizeof *hash->table * INIT_SIZE); /* 4 */ + if (hash->table) { /* 5 */ + hash->nchains = INIT_SIZE; /* 6 */ + hash->highmark = INIT_SIZE * 2; + hash->lowmark = INIT_SIZE / 2; + hash->nodecount = 0; + hash->maxcount = maxcount; + hash->compare = compfun ? compfun : hash_comp_default; + hash->function = hashfun ? hashfun : hash_fun_default; + hash->allocnode = hnode_alloc; + hash->freenode = hnode_free; + hash->context = NULL; + hash->mask = INIT_MASK; + hash->dynamic = 1; /* 7 */ + clear_table(hash); /* 8 */ +#ifdef STRICT_CHECKING +// assert (hash_verify(hash)); +#endif + return hash; + } + free(hash); + } + + return NULL; +} + +/* + * Select a different set of node allocator routines. + */ + +void hash_set_allocator(hash_t *hash, hnode_alloc_t al, + hnode_free_t fr, void *context) +{ +#ifdef STRICT_CHECING + assert (hash_count(hash) == 0); + assert ((al == 0 && fr == 0) || (al != 0 && fr != 0)); +#endif + hash->allocnode = al ? al : hnode_alloc; + hash->freenode = fr ? fr : hnode_free; + hash->context = context; +} + +/* + * Free every node in the hash using the hash->freenode() function pointer, and + * cause the hash to become empty. + */ + +void hash_free_nodes(hash_t *hash) +{ + hscan_t hs; + hnode_t *node; + hash_scan_begin(&hs, hash); + while ((node = hash_scan_next(&hs))) { + hash_scan_delete(hash, node); + hash->freenode(node, hash->context); + } + hash->nodecount = 0; + clear_table(hash); +} + +/* + * Obsolescent function for removing all nodes from a table, + * freeing them and then freeing the table all in one step. + */ + +void hash_free(hash_t *hash) +{ +#ifdef KAZLIB_OBSOLESCENT_DEBUG + assert ("call to obsolescent function hash_free()" && 0); +#endif + hash_free_nodes(hash); + hash_destroy(hash); +} + +/* + * Free a dynamic hash table structure. + */ + +void hash_destroy(hash_t *hash) +{ +#ifdef STRICT_CHECKING + assert (hash_val_t_bit != 0); + assert (hash_isempty(hash)); +#endif + free(hash->table); + free(hash); +} + +/* + * Initialize a user supplied hash structure. The user also supplies a table of + * chains which is assigned to the hash structure. The table is static---it + * will not grow or shrink. + * 1. See note 1. in hash_create(). + * 2. The user supplied array of pointers hopefully contains nchains nodes. + * 3. See note 7. in hash_create(). + * 4. We must dynamically compute the mask from the given power of two table + * size. + * 5. The user supplied table can't be assumed to contain null pointers, + * so we reset it here. + */ + +hash_t *hash_init(hash_t *hash, hashcount_t maxcount, + hash_comp_t compfun, hash_fun_t hashfun, hnode_t **table, + hashcount_t nchains) +{ + if (hash_val_t_bit == 0) /* 1 */ + compute_bits(); +#ifdef STRICT_CHECKING + assert (is_power_of_two(nchains)); +#endif + hash->table = table; /* 2 */ + hash->nchains = nchains; + hash->nodecount = 0; + hash->maxcount = maxcount; + hash->compare = compfun ? compfun : hash_comp_default; + hash->function = hashfun ? hashfun : hash_fun_default; + hash->dynamic = 0; /* 3 */ + hash->mask = compute_mask(nchains); /* 4 */ + clear_table(hash); /* 5 */ +#ifdef STRICT_CHECKING +// assert (hash_verify(hash)); +#endif + return hash; +} + +/* + * Reset the hash scanner so that the next element retrieved by + * hash_scan_next() shall be the first element on the first non-empty chain. + * Notes: + * 1. Locate the first non empty chain. + * 2. If an empty chain is found, remember which one it is and set the next + * pointer to refer to its first element. + * 3. Otherwise if a chain is not found, set the next pointer to NULL + * so that hash_scan_next() shall indicate failure. + */ + +void hash_scan_begin(hscan_t *scan, hash_t *hash) +{ + hash_val_t nchains = hash->nchains; + hash_val_t chain; + + scan->table = hash; + + /* 1 */ + + for (chain = 0; chain < nchains && hash->table[chain] == 0; chain++) + ; + + if (chain < nchains) { /* 2 */ + scan->chain = chain; + scan->next = hash->table[chain]; + } else { /* 3 */ + scan->next = NULL; + } +} + +/* + * Retrieve the next node from the hash table, and update the pointer + * for the next invocation of hash_scan_next(). + * Notes: + * 1. Remember the next pointer in a temporary value so that it can be + * returned. + * 2. This assertion essentially checks whether the module has been properly + * initialized. The first point of interaction with the module should be + * either hash_create() or hash_init(), both of which set hash_val_t_bit to + * a non zero value. + * 3. If the next pointer we are returning is not NULL, then the user is + * allowed to call hash_scan_next() again. We prepare the new next pointer + * for that call right now. That way the user is allowed to delete the node + * we are about to return, since we will no longer be needing it to locate + * the next node. + * 4. If there is a next node in the chain (next->next), then that becomes the + * new next node, otherwise ... + * 5. We have exhausted the current chain, and must locate the next subsequent + * non-empty chain in the table. + * 6. If a non-empty chain is found, the first element of that chain becomes + * the new next node. Otherwise there is no new next node and we set the + * pointer to NULL so that the next time hash_scan_next() is called, a null + * pointer shall be immediately returned. + */ + + +hnode_t *hash_scan_next(hscan_t *scan) +{ + hnode_t *next = scan->next; /* 1 */ + hash_t *hash = scan->table; + hash_val_t chain = scan->chain + 1; + hash_val_t nchains = hash->nchains; +#ifdef SRTICT_CHECING + assert (hash_val_t_bit != 0); /* 2 */ +#endif + if (next) { /* 3 */ + if (next->next) { /* 4 */ + scan->next = next->next; + } else { + while (chain < nchains && hash->table[chain] == 0) /* 5 */ + chain++; + if (chain < nchains) { /* 6 */ + scan->chain = chain; + scan->next = hash->table[chain]; + } else { + scan->next = NULL; + } + } + } + return next; +} + +/* + * Insert a node into the hash table. + * Notes: + * 1. It's illegal to insert more than the maximum number of nodes. The client + * should verify that the hash table is not full before attempting an + * insertion. + * 2. The same key may not be inserted into a table twice. + * 3. If the table is dynamic and the load factor is already at >= 2, + * grow the table. + * 4. We take the bottom N bits of the hash value to derive the chain index, + * where N is the base 2 logarithm of the size of the hash table. + */ + +void hash_insert(hash_t *hash, hnode_t *node, const void *key) +{ + hash_val_t hkey, chain; +#ifdef STRICT_CHECKING + assert (hash_val_t_bit != 0); + assert (node->next == NULL); + assert (hash->nodecount < hash->maxcount); /* 1 */ + assert (hash_lookup(hash, key) == NULL); /* 2 */ +#endif + if (hash->dynamic && hash->nodecount >= hash->highmark) /* 3 */ + grow_table(hash); + + hkey = hash->function(key); + chain = hkey & hash->mask; /* 4 */ + + node->key = key; + node->hkey = hkey; + node->next = hash->table[chain]; + hash->table[chain] = node; + hash->nodecount++; +#ifdef STRICT_CHECKING +// assert (hash_verify(hash)); +#endif +} + +/* + * Find a node in the hash table and return a pointer to it. + * Notes: + * 1. We hash the key and keep the entire hash value. As an optimization, when + * we descend down the chain, we can compare hash values first and only if + * hash values match do we perform a full key comparison. + * 2. To locate the chain from among 2^N chains, we look at the lower N bits of + * the hash value by anding them with the current mask. + * 3. Looping through the chain, we compare the stored hash value inside each + * node against our computed hash. If they match, then we do a full + * comparison between the unhashed keys. If these match, we have located the + * entry. + */ + +hnode_t *hash_lookup(hash_t *hash, const void *key) +{ + hash_val_t hkey, chain; + hnode_t *nptr; +#ifdef HAVE_STRICT + assert( hash != NULL ); + assert( key != NULL ); +#endif + hkey = hash->function(key); /* 1 */ + chain = hkey & hash->mask; /* 2 */ + + for (nptr = hash->table[chain]; nptr; nptr = nptr->next) { /* 3 */ + if (nptr->hkey == hkey && hash->compare(nptr->key, key) == 0) + return nptr; + } + + return NULL; +} + +/* + * Delete the given node from the hash table. Since the chains + * are singly linked, we must locate the start of the node's chain + * and traverse. + * Notes: + * 1. The node must belong to this hash table, and its key must not have + * been tampered with. + * 2. If this deletion will take the node count below the low mark, we + * shrink the table now. + * 3. Determine which chain the node belongs to, and fetch the pointer + * to the first node in this chain. + * 4. If the node being deleted is the first node in the chain, then + * simply update the chain head pointer. + * 5. Otherwise advance to the node's predecessor, and splice out + * by updating the predecessor's next pointer. + * 6. Indicate that the node is no longer in a hash table. + */ + +hnode_t *hash_delete(hash_t *hash, hnode_t *node) +{ + hash_val_t chain; + hnode_t *hptr; +#ifdef STRICT_CHECKING + assert (hash_lookup(hash, node->key) == node); /* 1 */ + assert (hash_val_t_bit != 0); +#endif + if (hash->dynamic && hash->nodecount <= hash->lowmark + && hash->nodecount > INIT_SIZE) + shrink_table(hash); /* 2 */ + + chain = node->hkey & hash->mask; /* 3 */ + hptr = hash->table[chain]; + + if (hptr == node) { /* 4 */ + hash->table[chain] = node->next; + } else { + while (hptr->next != node) { /* 5 */ +#ifdef STRICT_CHECKING + assert (hptr != 0); +#endif + hptr = hptr->next; + } +#ifdef STRICT_CHECKING + assert (hptr->next == node); +#endif + hptr->next = node->next; + } + + hash->nodecount--; +#ifdef STRICT_CHECKING +// assert (hash_verify(hash)); +#endif + + node->next = NULL; /* 6 */ + return node; +} + +int hash_alloc_insert(hash_t *hash, const void *key, void *data) +{ + hnode_t *node = hash->allocnode(hash->context); + + if (node) { + hnode_init(node, data); + hash_insert(hash, node, key); + return 1; + } + return 0; +} + +void hash_delete_free(hash_t *hash, hnode_t *node) +{ + hash_delete(hash, node); + hash->freenode(node, hash->context); +} + +/* + * Exactly like hash_delete, except does not trigger table shrinkage. This is to be + * used from within a hash table scan operation. See notes for hash_delete. + */ + +hnode_t *hash_scan_delete(hash_t *hash, hnode_t *node) +{ + hash_val_t chain; + hnode_t *hptr; +#ifdef STRICT_CHECKING + assert (hash_lookup(hash, node->key) == node); + assert (hash_val_t_bit != 0); +#endif + chain = node->hkey & hash->mask; + hptr = hash->table[chain]; + + if (hptr == node) { + hash->table[chain] = node->next; + } else { + while (hptr->next != node) + hptr = hptr->next; + hptr->next = node->next; + } + + hash->nodecount--; +#ifdef STRICT_CHECKING +// assert (hash_verify(hash)); +#endif + node->next = NULL; + + return node; +} + +/* + * Like hash_delete_free but based on hash_scan_delete. + */ + +void hash_scan_delfree(hash_t *hash, hnode_t *node) +{ + hash_scan_delete(hash, node); + hash->freenode(node, hash->context); +} + +/* + * Verify whether the given object is a valid hash table. This means + * Notes: + * 1. If the hash table is dynamic, verify whether the high and + * low expansion/shrinkage thresholds are powers of two. + * 2. Count all nodes in the table, and test each hash value + * to see whether it is correct for the node's chain. + */ + +int hash_verify(hash_t *hash) +{ + hashcount_t count = 0; + hash_val_t chain; + hnode_t *hptr; + + if (hash->dynamic) { /* 1 */ + if (hash->lowmark >= hash->highmark) + return 0; + if (!is_power_of_two(hash->highmark)) + return 0; + if (!is_power_of_two(hash->lowmark)) + return 0; + } + + for (chain = 0; chain < hash->nchains; chain++) { /* 2 */ + for (hptr = hash->table[chain]; hptr != 0; hptr = hptr->next) { + if ((hptr->hkey & hash->mask) != chain) + return 0; + count++; + } + } + + if (count != hash->nodecount) + return 0; + + return 1; +} + +/* + * Test whether the hash table is full and return 1 if this is true, + * 0 if it is false. + */ + +#undef hash_isfull +int hash_isfull(hash_t *hash) +{ + return hash->nodecount == hash->maxcount; +} + +/* + * Test whether the hash table is empty and return 1 if this is true, + * 0 if it is false. + */ + +#undef hash_isempty +int hash_isempty(hash_t *hash) +{ + return hash->nodecount == 0; +} + +static hnode_t *hnode_alloc(void *context) +{ + return malloc(sizeof *hnode_alloc(NULL)); +} + +static void hnode_free(hnode_t *node, void *context) +{ + free(node); +} + + +/* + * Create a hash table node dynamically and assign it the given data. + */ + +hnode_t *hnode_create(void *data) +{ + hnode_t *node = malloc(sizeof *node); + if (node) { + node->data = data; + node->next = NULL; + } + return node; +} + +/* + * Initialize a client-supplied node + */ + +hnode_t *hnode_init(hnode_t *hnode, void *data) +{ + hnode->data = data; + hnode->next = NULL; + return hnode; +} + +/* + * Destroy a dynamically allocated node. + */ + +void hnode_destroy(hnode_t *hnode) +{ + free(hnode); +} + +#undef hnode_put +void hnode_put(hnode_t *node, void *data) +{ + node->data = data; +} + +#undef hnode_get +void *hnode_get(hnode_t *node) +{ + return node->data; +} + +#undef hnode_getkey +const void *hnode_getkey(hnode_t *node) +{ + return node->key; +} + +#undef hash_count +hashcount_t hash_count(hash_t *hash) +{ + return hash->nodecount; +} + +#undef hash_size +hashcount_t hash_size(hash_t *hash) +{ + return hash->nchains; +} + +static hash_val_t hash_fun_default(const void *key) +{ + static unsigned long randbox[] = { + 0x49848f1bU, 0xe6255dbaU, 0x36da5bdcU, 0x47bf94e9U, + 0x8cbcce22U, 0x559fc06aU, 0xd268f536U, 0xe10af79aU, + 0xc1af4d69U, 0x1d2917b5U, 0xec4c304dU, 0x9ee5016cU, + 0x69232f74U, 0xfead7bb3U, 0xe9089ab6U, 0xf012f6aeU, + }; + + const unsigned char *str = key; + hash_val_t acc = 0; + + while (*str) { + acc ^= randbox[(*str + acc) & 0xf]; + acc = (acc << 1) | (acc >> 31); + acc &= 0xffffffffU; + acc ^= randbox[((*str++ >> 4) + acc) & 0xf]; + acc = (acc << 2) | (acc >> 30); + acc &= 0xffffffffU; + } + return acc; +} +/* +static hash_val_t hash_fun_default( const void *key ) +{ + hash_val_t hash = 0; + char *k = (char*) key; + while (*k) + hash = hash * 31 + *k++; + return hash; +}*/ + +static int hash_comp_default(const void *key1, const void *key2) +{ + return strcmp(key1, key2); +} + +#ifdef KAZLIB_TEST_MAIN + +#include +#include +#include + +typedef char input_t[256]; + +static int tokenize(char *string, ...) +{ + char **tokptr; + va_list arglist; + int tokcount = 0; + + va_start(arglist, string); + tokptr = va_arg(arglist, char **); + while (tokptr) { + while (*string && isspace((unsigned char) *string)) + string++; + if (!*string) + break; + *tokptr = string; + while (*string && !isspace((unsigned char) *string)) + string++; + tokptr = va_arg(arglist, char **); + tokcount++; + if (!*string) + break; + *string++ = 0; + } + va_end(arglist); + + return tokcount; +} + +static char *dupstring(char *str) +{ + int sz = strlen(str) + 1; + char *new = malloc(sz); + if (new) + memcpy(new, str, sz); + return new; +} + +static hnode_t *new_node(void *c) +{ + static hnode_t few[5]; + static int count; + + if (count < 5) + return few + count++; + + return NULL; +} + +static void del_node(hnode_t *n, void *c) +{ +} + +int main(void) +{ + input_t in; + hash_t *h = hash_create(HASHCOUNT_T_MAX, 0, 0); + hnode_t *hn; + hscan_t hs; + char *tok1, *tok2, *val; + const char *key; + int prompt = 0; + + char *help = + "a add value to hash table\n" + "d delete value from hash table\n" + "l lookup value in hash table\n" + "n show size of hash table\n" + "c show number of entries\n" + "t dump whole hash table\n" + "+ increase hash table (private func)\n" + "- decrease hash table (private func)\n" + "b print hash_t_bit value\n" + "p turn prompt on\n" + "s switch to non-functioning allocator\n" + "q quit"; + + if (!h) + puts("hash_create failed"); + + for (;;) { + if (prompt) + putchar('>'); + fflush(stdout); + + if (!fgets(in, sizeof(input_t), stdin)) + break; + + switch(in[0]) { + case '?': + puts(help); + break; + case 'b': + printf("%d\n", hash_val_t_bit); + break; + case 'a': + if (tokenize(in+1, &tok1, &tok2, (char **) 0) != 2) { + puts("what?"); + break; + } + key = dupstring(tok1); + val = dupstring(tok2); + + if (!key || !val) { + puts("out of memory"); + free((void *) key); + free(val); + } + + if (!hash_alloc_insert(h, key, val)) { + puts("hash_alloc_insert failed"); + free((void *) key); + free(val); + break; + } + break; + case 'd': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + hn = hash_lookup(h, tok1); + if (!hn) { + puts("hash_lookup failed"); + break; + } + val = hnode_get(hn); + key = hnode_getkey(hn); + hash_scan_delfree(h, hn); + free((void *) key); + free(val); + break; + case 'l': + if (tokenize(in+1, &tok1, (char **) 0) != 1) { + puts("what?"); + break; + } + hn = hash_lookup(h, tok1); + if (!hn) { + puts("hash_lookup failed"); + break; + } + val = hnode_get(hn); + puts(val); + break; + case 'n': + printf("%lu\n", (unsigned long) hash_size(h)); + break; + case 'c': + printf("%lu\n", (unsigned long) hash_count(h)); + break; + case 't': + hash_scan_begin(&hs, h); + while ((hn = hash_scan_next(&hs))) + printf("%s\t%s\n", (char*) hnode_getkey(hn), + (char*) hnode_get(hn)); + break; + case '+': + grow_table(h); /* private function */ + break; + case '-': + shrink_table(h); /* private function */ + break; + case 'q': + exit(0); + break; + case '\0': + break; + case 'p': + prompt = 1; + break; + case 's': + hash_set_allocator(h, new_node, del_node, NULL); + break; + default: + putchar('?'); + putchar('\n'); + break; + } + } + + return 0; +} + +#endif diff --git a/branches/V-1.5.3/veejay-server/libhash/hash.h b/branches/V-1.5.3/veejay-server/libhash/hash.h new file mode 100644 index 00000000..9677632b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libhash/hash.h @@ -0,0 +1,240 @@ +/* + * Hash Table Data Type + * Copyright (C) 1997 Kaz Kylheku + * + * Free Software License: + * + * All rights are reserved by the author, with the following exceptions: + * Permission is granted to freely reproduce and distribute this software, + * possibly in exchange for a fee, provided that this copyright notice appears + * intact. Permission is also granted to adapt this software to produce + * derivative works, as long as the modified versions carry this copyright + * notice and additional notices stating that the work has been modified. + * This source code may be translated into executable form and incorporated + * into proprietary software; there is no requirement for such software to + * contain a copyright notice related to this source. + * + * $Id: hash.h,v 1.1.1.1 2004/10/27 23:48:59 niels Exp $ + * $Name: $ + */ + +#ifndef HASH_H +#define HASH_H + +#include +#ifdef KAZLIB_SIDEEFFECT_DEBUG +#include "sfx.h" +#endif + +/* + * Blurb for inclusion into C++ translation units + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long hashcount_t; +#define HASHCOUNT_T_MAX ULONG_MAX + +typedef unsigned long hash_val_t; +#define HASH_VAL_T_MAX ULONG_MAX + +extern int hash_val_t_bit; + +#ifndef HASH_VAL_T_BIT +#define HASH_VAL_T_BIT ((int) hash_val_t_bit) +#endif + +/* + * Hash chain node structure. + * Notes: + * 1. This preprocessing directive is for debugging purposes. The effect is + * that if the preprocessor symbol KAZLIB_OPAQUE_DEBUG is defined prior to the + * inclusion of this header, then the structure shall be declared as having + * the single member int __OPAQUE__. This way, any attempts by the + * client code to violate the principles of information hiding (by accessing + * the structure directly) can be diagnosed at translation time. However, + * note the resulting compiled unit is not suitable for linking. + * 2. This is a pointer to the next node in the chain. In the last node of a + * chain, this pointer is null. + * 3. The key is a pointer to some user supplied data that contains a unique + * identifier for each hash node in a given table. The interpretation of + * the data is up to the user. When creating or initializing a hash table, + * the user must supply a pointer to a function for comparing two keys, + * and a pointer to a function for hashing a key into a numeric value. + * 4. The value is a user-supplied pointer to void which may refer to + * any data object. It is not interpreted in any way by the hashing + * module. + * 5. The hashed key is stored in each node so that we don't have to rehash + * each key when the table must grow or shrink. + */ + +typedef struct hnode_t { + #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) /* 1 */ + struct hnode_t *hash_next; /* 2 */ + const void *hash_key; /* 3 */ + void *hash_data; /* 4 */ + hash_val_t hash_hkey; /* 5 */ + #else + int hash_dummy; + #endif +} hnode_t; + +/* + * The comparison function pointer type. A comparison function takes two keys + * and produces a value of -1 if the left key is less than the right key, a + * value of 0 if the keys are equal, and a value of 1 if the left key is + * greater than the right key. + */ + +typedef int (*hash_comp_t)(const void *, const void *); + +/* + * The hashing function performs some computation on a key and produces an + * integral value of type hash_val_t based on that key. For best results, the + * function should have a good randomness properties in *all* significant bits + * over the set of keys that are being inserted into a given hash table. In + * particular, the most significant bits of hash_val_t are most significant to + * the hash module. Only as the hash table expands are less significant bits + * examined. Thus a function that has good distribution in its upper bits but + * not lower is preferrable to one that has poor distribution in the upper bits + * but not the lower ones. + */ + +typedef hash_val_t (*hash_fun_t)(const void *); + +/* + * allocator functions + */ + +typedef hnode_t *(*hnode_alloc_t)(void *); +typedef void (*hnode_free_t)(hnode_t *, void *); + +/* + * This is the hash table control structure. It keeps track of information + * about a hash table, as well as the hash table itself. + * Notes: + * 1. Pointer to the hash table proper. The table is an array of pointers to + * hash nodes (of type hnode_t). If the table is empty, every element of + * this table is a null pointer. A non-null entry points to the first + * element of a chain of nodes. + * 2. This member keeps track of the size of the hash table---that is, the + * number of chain pointers. + * 3. The count member maintains the number of elements that are presently + * in the hash table. + * 4. The maximum count is the greatest number of nodes that can populate this + * table. If the table contains this many nodes, no more can be inserted, + * and the hash_isfull() function returns true. + * 5. The high mark is a population threshold, measured as a number of nodes, + * which, if exceeded, will trigger a table expansion. Only dynamic hash + * tables are subject to this expansion. + * 6. The low mark is a minimum population threshold, measured as a number of + * nodes. If the table population drops below this value, a table shrinkage + * will occur. Only dynamic tables are subject to this reduction. No table + * will shrink beneath a certain absolute minimum number of nodes. + * 7. This is the a pointer to the hash table's comparison function. The + * function is set once at initialization or creation time. + * 8. Pointer to the table's hashing function, set once at creation or + * initialization time. + * 9. The current hash table mask. If the size of the hash table is 2^N, + * this value has its low N bits set to 1, and the others clear. It is used + * to select bits from the result of the hashing function to compute an + * index into the table. + * 10. A flag which indicates whether the table is to be dynamically resized. It + * is set to 1 in dynamically allocated tables, 0 in tables that are + * statically allocated. + */ + +typedef struct hash_t { + #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + struct hnode_t **hash_table; /* 1 */ + hashcount_t hash_nchains; /* 2 */ + hashcount_t hash_nodecount; /* 3 */ + hashcount_t hash_maxcount; /* 4 */ + hashcount_t hash_highmark; /* 5 */ + hashcount_t hash_lowmark; /* 6 */ + hash_comp_t hash_compare; /* 7 */ + hash_fun_t hash_function; /* 8 */ + hnode_alloc_t hash_allocnode; + hnode_free_t hash_freenode; + void *hash_context; + hash_val_t hash_mask; /* 9 */ + int hash_dynamic; /* 10 */ + #else + int hash_dummy; + #endif +} hash_t; + +/* + * Hash scanner structure, used for traversals of the data structure. + * Notes: + * 1. Pointer to the hash table that is being traversed. + * 2. Reference to the current chain in the table being traversed (the chain + * that contains the next node that shall be retrieved). + * 3. Pointer to the node that will be retrieved by the subsequent call to + * hash_scan_next(). + */ + +typedef struct hscan_t { + #if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) + hash_t *hash_table; /* 1 */ + hash_val_t hash_chain; /* 2 */ + hnode_t *hash_next; /* 3 */ + #else + int hash_dummy; + #endif +} hscan_t; + +extern hash_t *hash_create(hashcount_t, hash_comp_t, hash_fun_t); +extern void hash_set_allocator(hash_t *, hnode_alloc_t, hnode_free_t, void *); +extern void hash_destroy(hash_t *); +extern void hash_free_nodes(hash_t *); +extern void hash_free(hash_t *); +extern hash_t *hash_init(hash_t *, hashcount_t, hash_comp_t, + hash_fun_t, hnode_t **, hashcount_t); +extern void hash_insert(hash_t *, hnode_t *, const void *); +extern hnode_t *hash_lookup(hash_t *, const void *); +extern hnode_t *hash_delete(hash_t *, hnode_t *); +extern int hash_alloc_insert(hash_t *, const void *, void *); +extern void hash_delete_free(hash_t *, hnode_t *); + +extern void hnode_put(hnode_t *, void *); +extern void *hnode_get(hnode_t *); +extern const void *hnode_getkey(hnode_t *); +extern hashcount_t hash_count(hash_t *); +extern hashcount_t hash_size(hash_t *); + +extern int hash_isfull(hash_t *); +extern int hash_isempty(hash_t *); + +extern void hash_scan_begin(hscan_t *, hash_t *); +extern hnode_t *hash_scan_next(hscan_t *); +extern hnode_t *hash_scan_delete(hash_t *, hnode_t *); +extern void hash_scan_delfree(hash_t *, hnode_t *); + +extern int hash_verify(hash_t *); + +extern hnode_t *hnode_create(void *); +extern hnode_t *hnode_init(hnode_t *, void *); +extern void hnode_destroy(hnode_t *); + +#if defined(HASH_IMPLEMENTATION) || !defined(KAZLIB_OPAQUE_DEBUG) +#ifdef KAZLIB_SIDEEFFECT_DEBUG +#define hash_isfull(H) (SFX_CHECK(H)->hash_nodecount == (H)->hash_maxcount) +#else +#define hash_isfull(H) ((H)->hash_nodecount == (H)->hash_maxcount) +#endif +#define hash_isempty(H) ((H)->hash_nodecount == 0) +#define hash_count(H) ((H)->hash_nodecount) +#define hash_size(H) ((H)->hash_nchains) +#define hnode_get(N) ((N)->hash_data) +#define hnode_getkey(N) ((N)->hash_key) +#define hnode_put(N, V) ((N)->hash_data = (V)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/branches/V-1.5.3/veejay-server/liblzo/Makefile.am b/branches/V-1.5.3/veejay-server/liblzo/Makefile.am new file mode 100644 index 00000000..4c01f669 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/liblzo/Makefile.am @@ -0,0 +1,11 @@ +# Makefile for veejay + +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/vjmem \ + -I$(top_srcdir)/vjmsg + +VJLZO_LIB_FILE = libminilzo.la +noinst_LTLIBRARIES = $(VJLZO_LIB_FILE) +libminilzo_la_SOURCES = minilzo.c lzo.c +EXTRA_DIST= lzoconf.h lzodefs.h lzo.h minilzo.h diff --git a/branches/V-1.5.3/veejay-server/liblzo/lzo.c b/branches/V-1.5.3/veejay-server/liblzo/lzo.c new file mode 100644 index 00000000..c6de22e3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/liblzo/lzo.c @@ -0,0 +1,316 @@ +/* veejay - Linux VeeJay + * (C) 2002-2006 Niels Elburg + * + * + * 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 +#ifdef STRICT_CHECKING +#include +#endif +typedef struct +{ + lzo_byte *wrkmem; + uint8_t *tmp[3]; +} lzot; + +void lzo_free( void *lzo ) +{ + lzot *l = (lzot*) lzo; + if(l) + { + if(l->wrkmem) + free(l->wrkmem); + if(l->tmp[0]) + free(l->tmp[0]); + free(l); + } + l = NULL; +} + +void *lzo_new( ) +{ + lzot *l = (lzot*) vj_calloc(sizeof(lzot)); + if (lzo_init() != LZO_E_OK) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize LZO. Could be buggy compiler"); + free( l ); + return NULL; + } + + l->wrkmem = (lzo_bytep) + vj_calloc( LZO1X_1_MEM_COMPRESS ); + + if(l->wrkmem == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot allocate work memory for LZO1X_1"); + if(l) free(l); + return NULL; + } + veejay_msg(VEEJAY_MSG_DEBUG,"LZO real-time data compression library (v%s, %s).", + lzo_version_string(), lzo_version_date()); + + l->tmp[0] = NULL; + l->tmp[1] = NULL; + l->tmp[2] = NULL; + + return (void*) l; +} + +static uint32_t str2ulong(unsigned char *str) +{ + return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) ); +} + +int lzo_compress( void *lzo, uint8_t *src, uint8_t *plane, unsigned int *size, int ilen ) +{ + lzo_uint out_len =0; + lzo_uint len = ilen; + lzot *l = (lzot*) lzo; + lzo_bytep dst = plane; + lzo_uintp dst_len = (lzo_uintp) size; + lzo_voidp wrkmem = l->wrkmem; + int r = lzo1x_1_compress( src, len, dst, dst_len, wrkmem ); + if( r != LZO_E_OK ) + return 0; + return (*size); +} +long lzo_decompress_el( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst[3], int uv_len) +{ + unsigned int i; + lzo_uint len[3] = { 0,0,0}; + unsigned int mode = 0; + unsigned int sum = 0; + lzot *l = (lzot*) lzo; + lzo_uint result_len = 0; + lzo_uint offset = 16; + len[0] = str2ulong( linbuf ); + len[1] = str2ulong( linbuf+4 ); + len[2] = str2ulong( linbuf+8 ); + mode = str2ulong( linbuf+12 ); + + if(len[1] ==0 && len[2] == 0 ) + mode = 1; + + for( i = 0; i < 3; i ++ ) + { + if( len[i] <= 0 ) + continue; + + const lzo_bytep src = (lzo_bytep) (linbuf+offset); + int r = lzo1x_decompress( src, len[i], dst[i], &result_len, l->wrkmem ); + if( r != LZO_E_OK ) + return 0; + sum += result_len; + offset += len[i]; + + result_len = 0; + } + + if(mode == 1) { + veejay_memset( dst[1],128, uv_len ); + veejay_memset( dst[2],128, uv_len ); + } + + return (long)sum; +} + +long lzo_decompress( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst[3], int uv_len, + uint32_t stride1, uint32_t stride2, uint32_t stride3 ) +{ + unsigned int i; + lzo_uint len[3] = { 0,0,0}; + unsigned int mode = 0; + unsigned int sum = 0; + lzot *l = (lzot*) lzo; + lzo_uint result_len = 0; + lzo_uint offset = 16; + + len[0] = str2ulong( linbuf ); + len[1] = str2ulong( linbuf+4 ); + len[2] = str2ulong( linbuf+8 ); + mode = str2ulong( linbuf+12 ); + + if( len[0] != stride1 || len[1] != stride2 || len[2] != stride3 ) { + veejay_msg(0, "Data corruption."); + return 0; + } + + len[0] = stride1; + len[1] = stride2; + len[2] = stride3; + + if(len[1] ==0 && len[2] == 0 ) + mode = 1; + + for( i = 0; i < 3; i ++ ) + { + if( len[i] <= 0 ) + continue; + + const lzo_bytep src = (lzo_bytep) (linbuf+offset); + int r = lzo1x_decompress( src, len[i], dst[i], &result_len, l->wrkmem ); + if( r != LZO_E_OK ) + return 0; + sum += result_len; + offset += len[i]; + + result_len = 0; + } + + if(mode == 1) { + veejay_memset( dst[1],128, uv_len ); + veejay_memset( dst[2],128, uv_len ); + } + + return (long)sum; +} + +long lzo_decompress422into420( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst[3], int w, int h, + uint32_t stride1, uint32_t stride2, uint32_t stride3 ) +{ + int i; + lzo_uint len[3] = { 0,0,0}; + int sum = 0; + int mode = 0; + lzot *l = (lzot*) lzo; + lzo_uint result_len = 0; + lzo_uint offset = 16; + + len[0] = str2ulong( linbuf ); + len[1] = str2ulong( linbuf+4 ); + len[2] = str2ulong( linbuf+8 ); + mode = str2ulong( linbuf+12 ); + + if( len[0] != stride1 || len[1] != stride2 || len[2] != stride3 ) { + veejay_msg(0, "Data corruption."); + return 0; + } + + len[0] = stride1; + len[1] = stride2; + len[2] = stride3; + +/* + len[0] = str2ulong( linbuf ); + len[1] = str2ulong( linbuf+4 ); + len[2] = str2ulong( linbuf+8 ); + mode = str2ulong( linbuf+12 ); +*/ + + if(len[1] ==0 && len[2] == 0 ) + mode = 1; + + + + if( l->tmp[0] == NULL ) { + l->tmp[0] = vj_malloc(sizeof(uint8_t) * w * h * 3); // will do + l->tmp[1] = l->tmp[0] + w * h; + l->tmp[2] = l->tmp[1] + ( (w>>1)*h); + } + + for( i = 0; i <= 2; i ++ ) + { + if(len[i] <= 0) + continue; + + const lzo_bytep src = (lzo_bytep) (linbuf+offset); + int r = lzo1x_decompress( src, len[i], l->tmp[i], &result_len, l->wrkmem ); + if( r != LZO_E_OK ) + return 0; + sum += result_len; + offset += len[i]; + } + + veejay_memcpy( dst[0], l->tmp[0], w*h); + if( mode == 1 ) { + veejay_memset(dst[1],128,( (w>>1)*h)); + veejay_memset(dst[2],128,( (w>>1)*h)); + } else { + yuv422to420planar( l->tmp, dst, w, h ); + } + return (long)sum; +} +long lzo_decompress420into422( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst[3], int w, int h ) +{ + int i; + lzo_uint len[3] = { 0,0,0}; + int sum = 0; + int mode= 0; + lzot *l = (lzot*) lzo; + lzo_uint result_len = 0; + lzo_uint offset = 16; + + len[0] = str2ulong( linbuf ); + len[1] = str2ulong( linbuf+4 ); + len[2] = str2ulong( linbuf+8 ); + mode = str2ulong( linbuf+12 ); + + if( l->tmp[0] == NULL ) { + l->tmp[0] = vj_malloc(sizeof(uint8_t) * w * h * 3); // will do + l->tmp[1] = l->tmp[0] + ( w * h ); + l->tmp[2] = l->tmp[1] + ( (w>>1) * (h>>1)); + } + + for( i = 0; i <= 2; i ++ ) + { + if( len[i] <= 0 ) + continue; + const lzo_bytep src = (lzo_bytep) (linbuf+offset); + int r = lzo1x_decompress( src, len[i], l->tmp[i], &result_len, l->wrkmem ); + if( r != LZO_E_OK ) + return 0; + sum += result_len; + offset += len[i]; + } + veejay_memcpy( dst[0], l->tmp[0], w*h); + if(mode == 1) { + veejay_memset(dst[1],128,( (w>>1)*h)); + veejay_memset(dst[2],128,( (w>>1)*h)); + } + else { + yuv420to422planar( l->tmp, dst, w, h ); + } + + return (long)sum; +} + + +long lzo_decompress2( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst ) +{ + lzo_uint len = linbuf_len; + lzot *l = (lzot*) lzo; + lzo_uint result_len = 0; + + const lzo_bytep src = (lzo_bytep) linbuf; + int r = lzo1x_decompress( src, len, dst, &result_len, l->wrkmem ); + + if( r != LZO_E_OK ) + return 0; + return (long)result_len; +} + diff --git a/branches/V-1.5.3/veejay-server/liblzo/lzo.h b/branches/V-1.5.3/veejay-server/liblzo/lzo.h new file mode 100644 index 00000000..0f6edf05 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/liblzo/lzo.h @@ -0,0 +1,40 @@ +/* veejay - Linux VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + +#ifndef LZOH +#define LZOH + +void *lzo_new( ); + +void lzo_free( void *lzo ); + +int lzo_compress( void *lzo, uint8_t *src, uint8_t *plane, unsigned int *size, int ilen ); +long lzo_decompress422into420( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst[3], int w, int h, + uint32_t s1, uint32_t s2, uint32_t s3 ); +long lzo_decompress420into422( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst[3], int w, int h ); + + +long lzo_decompress2( void *lzo, uint8_t *linbuf, int linbuf_len, uint8_t *dst ); + +long lzo_decompress_el( void *lzo, uint8_t *linbuf, int linbuf_len,uint8_t *dst[3], int uv_len); + +long lzo_decompress( void *lzo, uint8_t *linbuf, int linbuf_len,uint8_t *dst[3], int uv_len, + uint32_t s1, uint32_t s2, uint32_t s3 ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/liblzo/lzoconf.h b/branches/V-1.5.3/veejay-server/liblzo/lzoconf.h new file mode 100644 index 00000000..614efa1f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/liblzo/lzoconf.h @@ -0,0 +1,415 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H_INCLUDED +#define __LZOCONF_H_INCLUDED + +#define LZO_VERSION 0x2030 +#define LZO_VERSION_STRING "2.03" +#define LZO_VERSION_DATE "Apr 30 2008" + +/* internal Autoconf configuration file - only used when building LZO */ +#include +#include +#include + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* get OS and architecture defines */ +#ifndef __LZODEFS_H_INCLUDED +#include "lzodefs.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// some core defines +************************************************************************/ + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) ((c) + 0U) +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER 1 +# elif defined(__CHECKER__) +# define __LZO_CHECKER 1 +# elif defined(__INSURE__) +# define __LZO_CHECKER 1 +# elif defined(__PURIFY__) +# define __LZO_CHECKER 1 +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* lzo_uint should match size_t */ +#if !defined(LZO_UINT_MAX) +# if defined(LZO_ABI_LLP64) /* WIN64 */ +# if defined(LZO_OS_WIN64) + typedef unsigned __int64 lzo_uint; + typedef __int64 lzo_int; +# else + typedef unsigned long long lzo_uint; + typedef long long lzo_int; +# endif +# define LZO_UINT_MAX 0xffffffffffffffffull +# define LZO_INT_MAX 9223372036854775807LL +# define LZO_INT_MIN (-1LL - LZO_INT_MAX) +# elif defined(LZO_ABI_IP32L64) /* MIPS R5900 */ + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +/* Integral types with 32 bits or more. */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* The larger type of lzo_uint and lzo_uint32. */ +#if (LZO_UINT_MAX >= LZO_UINT32_MAX) +# define lzo_xint lzo_uint +#else +# define lzo_xint lzo_uint32 +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(LZO_HAVE_MM_HUGE_PTR) +# define __LZO_MMODEL_HUGE 1 +# define __LZO_MMODEL __huge +# else +# define __LZO_MMODEL +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_xintp lzo_xint __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * +/* deprecated - use `lzo_bytep' instead of `lzo_byte *' */ +#define lzo_byte unsigned char __LZO_MMODEL + +typedef int lzo_bool; + + +/*********************************************************************** +// function types +************************************************************************/ + +/* name mangling */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# define __LZO_CDECL __lzo_cdecl +#endif + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* __cdecl calling convention for public C and assembly functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_CDECL +#endif + +/* function types */ +typedef int +(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + +typedef int +(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + + +/* Callback interface. Currently only the progress indicator ("nprogress") + * is used, but this may change in a future release. */ + +struct lzo_callback_t; +typedef struct lzo_callback_t lzo_callback_t; +#define lzo_callback_p lzo_callback_t __LZO_MMODEL * + +/* malloc & free function types */ +typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) + (lzo_callback_p self, lzo_uint items, lzo_uint size); +typedef void (__LZO_CDECL *lzo_free_func_t) + (lzo_callback_p self, lzo_voidp ptr); + +/* a progress indicator callback function */ +typedef void (__LZO_CDECL *lzo_progress_func_t) + (lzo_callback_p, lzo_uint, lzo_uint, int); + +struct lzo_callback_t +{ + /* custom allocators (set to 0 to disable) */ + lzo_alloc_func_t nalloc; /* [not used right now] */ + lzo_free_func_t nfree; /* [not used right now] */ + + /* a progress indicator callback function (set to 0 to disable) */ + lzo_progress_func_t nprogress; + + /* NOTE: the first parameter "self" of the nalloc/nfree/nprogress + * callbacks points back to this struct, so you are free to store + * some extra info in the following variables. */ + lzo_voidp user1; + lzo_xint user2; + lzo_xint user3; +}; + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* [not used right now] */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) +#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ + + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) +#endif + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_callback_t)) +LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_bytep _buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_bytep _buf, lzo_uint _len); +LZO_EXTERN(const lzo_uint32p) +lzo_get_crc32_table(void); + +/* misc. */ +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + + +/*********************************************************************** +// deprecated macros - only for backward compatibility with LZO v1.xx +************************************************************************/ + +#if defined(LZO_CFG_COMPAT) + +#define __LZOCONF_H 1 + +#if defined(LZO_ARCH_I086) +# define __LZO_i386 1 +#elif defined(LZO_ARCH_I386) +# define __LZO_i386 1 +#endif + +#if defined(LZO_OS_DOS16) +# define __LZO_DOS 1 +# define __LZO_DOS16 1 +#elif defined(LZO_OS_DOS32) +# define __LZO_DOS 1 +#elif defined(LZO_OS_WIN16) +# define __LZO_WIN 1 +# define __LZO_WIN16 1 +#elif defined(LZO_OS_WIN32) +# define __LZO_WIN 1 +#endif + +#define __LZO_CMODEL +#define __LZO_DMODEL +#define __LZO_ENTRY __LZO_CDECL +#define LZO_EXTERN_CDECL LZO_EXTERN +#define LZO_ALIGN LZO_PTR_ALIGN_UP + +#define lzo_compress_asm_t lzo_compress_t +#define lzo_decompress_asm_t lzo_decompress_t + +#endif /* LZO_CFG_COMPAT */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 et: */ diff --git a/branches/V-1.5.3/veejay-server/liblzo/lzodefs.h b/branches/V-1.5.3/veejay-server/liblzo/lzodefs.h new file mode 100644 index 00000000..18056372 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/liblzo/lzodefs.h @@ -0,0 +1,1807 @@ +/* lzodefs.h -- architecture, OS and compiler specific defines + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if defined(LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif defined(LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if defined(LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && defined(LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if defined(LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif defined(LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif defined(LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if defined(LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif defined(LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif defined(LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif defined(LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline +#endif +#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !defined(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#if !defined(LZO_CFG_NO_INLINE_ASM) +#if defined(LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if !defined(LZO_CFG_NO_UNALIGNED) +#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif /* already included */ + +/* vim:set ts=4 et: */ diff --git a/branches/V-1.5.3/veejay-server/liblzo/minilzo.c b/branches/V-1.5.3/veejay-server/liblzo/minilzo.c new file mode 100644 index 00000000..6a62b31b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/liblzo/minilzo.c @@ -0,0 +1,4112 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif +#include +#include +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if defined(__IBMCPP__) && !defined(__IBMC__) +# define __IBMC__ __IBMCPP__ +#endif +#if defined(__ICL) && defined(_WIN32) && !defined(__INTEL_COMPILER) +# define __INTEL_COMPILER __ICL +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if defined(__INTEL_COMPILER) && defined(__linux__) +# pragma warning(disable: 193) +#endif +#if defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif 0 && defined(__C251__) +# pragma warning disable = 322 +#endif +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if (_MSC_VER >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if 0 +#define LZO_0xffffL 0xfffful +#define LZO_0xffffffffL 0xfffffffful +#else +#define LZO_0xffffL 65535ul +#define LZO_0xffffffffL 4294967295ul +#endif +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-1)) - (o)) << 1) + (o)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +#else +# define LZO_EXTERN_C extern +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if defined(LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif defined(LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__ppc__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif (defined(__mips__) && defined(__psp__)) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) || defined(__MACOS__) +# define LZO_OS_POSIX_MACOSX 1 +# define LZO_INFO_OS_POSIX "macosx" +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + __PATHCC_MINOR__ * 0x100 + __PATHCC_PATCHLEVEL__) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +#elif defined(__INTEL_COMPILER) +# define LZO_CC_INTELC 1 +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_WIN32) || defined(_WIN64) +# define LZO_CC_SYNTAX_MSC 1 +# else +# define LZO_CC_SYNTAX_GNUC 1 +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__llvm__) && defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# else +# define LZO_CC_LLVM (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# endif +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100 + __GNUC_PATCHLEVEL__) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + __GNUC_MINOR__ * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) +# define LZO_CC_IBMC 1 +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(_MSC_VER) +# define LZO_CC_MSC 1 +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#elif defined(__MWERKS__) +# define LZO_CC_MWERKS 1 +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC)+0 > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if (__ZTC__ == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !defined(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if defined(LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_ARCH_IA16 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__thumb__) || (defined(_M_ARM) && defined(_M_THUMB)) +# define LZO_ARCH_ARM 1 +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# if defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 1) +# define LZO_ARCH_ARM_THUMB 1 +# define LZO_INFO_ARCH "arm_thumb" +# elif defined(__CPU_MODE__) && ((__CPU_MODE__)+0 == 2) +# define LZO_INFO_ARCH "arm" +# else +# define LZO_INFO_ARCH "arm" +# endif +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +# define LZO_ARCH_IA16PM 1 +#endif +#if defined(LZO_ARCH_ARM_THUMB) && !defined(LZO_ARCH_ARM) +# error "this should not happen" +#endif +#if defined(LZO_ARCH_I086PM) && !defined(LZO_ARCH_I086) +# error "this should not happen" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "this should not happen" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "this should not happen" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "this should not happen" +# endif +#endif +#if !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "this should not happen" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !defined(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "this should not happen" +# elif (LZO_CC_ZORTECHC) +# else +# error "this should not happen" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#endif +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#endif +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#endif +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#endif +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#endif +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#endif +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__)+0 == (__LONG_LONG_MAX__)+0) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && (_INTEGRAL_MAX_BITS == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && defined(LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if defined(LZO_CFG_NO_LONG_LONG) || defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if (LZO_ARCH_I086) +# define __LZO_WORDSIZE 2 +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "LZO_MM" +# endif +#elif (LZO_ARCH_AVR || LZO_ARCH_Z80) +# define __LZO_WORDSIZE 1 +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define __LZO_WORDSIZE 4 +# define LZO_SIZEOF_VOID_P 4 +# else +# define __LZO_WORDSIZE 2 +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_M16C) +# define __LZO_WORDSIZE 2 +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +# define __LZO_WORDSIZE 8 +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define __LZO_WORDSIZE LZO_SIZEOF_LONG +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#elif (LZO_ARCH_SPU) +# if 0 +# define __LZO_WORDSIZE 16 +# endif +# define LZO_SIZEOF_VOID_P 4 +#else +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_WORDSIZE) +# if defined(__LZO_WORDSIZE) +# define LZO_WORDSIZE __LZO_WORDSIZE +# else +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +# endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#else +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "LZO_MM" +# endif +#else +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#endif +#if defined(LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !defined(LZO_ABI_BIG_ENDIAN) && !defined(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_M68K || LZO_ARCH_S390) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if defined(LZO_ABI_BIG_ENDIAN) && defined(LZO_ABI_LITTLE_ENDIAN) +# error "this should not happen" +#endif +#if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif defined(LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif defined(LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if !defined(__LZO_LIBC_OVERRIDE) +#if defined(LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif defined(LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif defined(LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif defined(LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif defined(LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + __UCLIBC_MINOR__ * 0x100 + __UCLIBC_SUBLEVEL__) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uclibc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + __GLIBC_MINOR__ * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#else +# define __lzo_gnuc_extension__ +#endif +#endif +#if !defined(__lzo_ua_volatile) +# define __lzo_ua_volatile volatile +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#endif +#endif +#if defined(__lzo_alignof) +# define __lzo_HAVE_alignof 1 +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# define __lzo_HAVE_constructor 1 +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# define __lzo_HAVE_destructor 1 +#endif +#if defined(__lzo_HAVE_destructor) && !defined(__lzo_HAVE_constructor) +# error "this should not happen" +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_CILLY || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define __lzo_inline inline +#endif +#endif +#if defined(__lzo_inline) +# define __lzo_HAVE_inline 1 +#else +# define __lzo_inline +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#endif +#endif +#if defined(__lzo_forceinline) +# define __lzo_HAVE_forceinline 1 +#else +# define __lzo_forceinline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_MSC) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#endif +#endif +#if defined(__lzo_noinline) +# define __lzo_HAVE_noinline 1 +#else +# define __lzo_noinline +#endif +#if (defined(__lzo_HAVE_forceinline) || defined(__lzo_HAVE_noinline)) && !defined(__lzo_HAVE_inline) +# error "this should not happen" +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#endif +#endif +#if defined(__lzo_noreturn) +# define __lzo_HAVE_noreturn 1 +#else +# define __lzo_noreturn +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 450) && LZO_CC_SYNTAX_MSC) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800) && LZO_CC_SYNTAX_GNUC) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# define __lzo_HAVE_nothrow 1 +#else +# define __lzo_nothrow +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 600) && LZO_CC_SYNTAX_GNUC) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#endif +#endif +#if defined(__lzo_restrict) +# define __lzo_HAVE_restrict 1 +#else +# define __lzo_restrict +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# define __lzo_HAVE_likely 1 +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_unlikely) +# define __lzo_HAVE_unlikely 1 +#else +# define __lzo_unlikely(e) (e) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int __lzo_unused[1-2*!(sizeof(var)>0)];} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int __lzo_unused[1-2*!(sizeof((int)func)>0)];} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# elif (LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if (0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch(0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1u-2*!(e)]; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-!(e)]; +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) extern int __lzo_cta[1-2*!(e)]; +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-!(e)];} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __lzo_cta_t[1-2*!(e)];} +# endif +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !defined(LZO_CFG_NO_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif (LZO_OS_WIN32 && LZO_CC_GNUC) && defined(__PW32__) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# define LZO_OPT_UNALIGNED64 1 +#elif (LZO_ARCH_ARM && LZO_ARCH_ARM_THUMB) +#elif (LZO_ARCH_ARM) +# define LZO_OPT_AVOID_SHORT 1 +# define LZO_OPT_AVOID_USHORT 1 +#elif (LZO_ARCH_CRIS) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_I386) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(LZO_ABI_BIG_ENDIAN) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_S390) +# define LZO_OPT_UNALIGNED16 1 +# define LZO_OPT_UNALIGNED32 1 +# if (LZO_SIZEOF_SIZE_T == 8) +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#if !defined(LZO_CFG_NO_INLINE_ASM) +#if defined(LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if !defined(LZO_CFG_NO_UNALIGNED) +#if defined(LZO_ABI_NEUTRAL_ENDIAN) || defined(LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(LZO_CFG_NO_INLINE_ASM) +#elif (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +#elif (LZO_CC_INTELC) +# define __LZO_ASM_CLOBBER "memory" +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +#endif +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2030) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +#if defined(LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +# define ACC_LIBC_FREESTANDING 1 +# define ACC_OS_FREESTANDING 1 +#endif +#if defined(LZO_CFG_NO_UNALIGNED) +# define ACC_CFG_NO_UNALIGNED 1 +#endif +#if defined(LZO_ARCH_GENERIC) +# define ACC_ARCH_GENERIC 1 +#endif +#if defined(LZO_ABI_NEUTRAL_ENDIAN) +# define ACC_ABI_NEUTRAL_ENDIAN 1 +#endif +#if defined(LZO_HAVE_CONFIG_H) +# define ACC_CONFIG_NO_HEADER 1 +#endif +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) +# include LZO_CFG_EXTRA_CONFIG_HEADER +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#include "lzo/lzoconf.h" +#endif + +#if (LZO_VERSION < 0x02000) || !defined(__LZOCONF_H_INCLUDED) +# error "version mismatch" +#endif + +#if (LZO_CC_BORLANDC && LZO_ARCH_I086) +# pragma option -h +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +# pragma warning(disable: 4514 4710 4711) +#endif + +#if (LZO_CC_SUNPROC) +# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) +# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) +#endif + +#if defined(__LZO_MMODEL_HUGE) && (!LZO_HAVE_MM_HUGE_PTR) +# error "this should not happen - check defines for __huge" +#endif + +#if defined(__LZO_IN_MINILZO) || defined(LZO_CFG_FREESTANDING) +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define ACC_WANT_ACC_INCD_H 1 +# define ACC_WANT_ACC_INCE_H 1 +# define ACC_WANT_ACC_INCI_H 1 +#elif 1 +# include +#else +# define ACC_WANT_ACC_INCD_H 1 +#endif + +#if (LZO_ARCH_I086) +# define ACC_MM_AHSHIFT LZO_MM_AHSHIFT +# define ACC_PTR_FP_OFF(x) (((const unsigned __far*)&(x))[0]) +# define ACC_PTR_FP_SEG(x) (((const unsigned __far*)&(x))[1]) +# define ACC_PTR_MK_FP(s,o) ((void __far*)(((unsigned long)(s)<<16)+(unsigned)(o))) +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# elif 1 && defined(LZO_OS_OS400) && (LZO_SIZEOF_VOID_P == 16) +# define __LZO_UINTPTR_T_IS_POINTER 1 + typedef char* lzo_uintptr_t; +# define lzo_uintptr_t lzo_uintptr_t +# elif (LZO_SIZEOF_SIZE_T == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t size_t +# elif (LZO_SIZEOF_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long +# elif (LZO_SIZEOF_INT == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned int +# elif (LZO_SIZEOF_LONG_LONG == LZO_SIZEOF_VOID_P) +# define lzo_uintptr_t unsigned long long +# else +# define lzo_uintptr_t size_t +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include +#endif + +#if defined(LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#elif !defined(__LZO_MMODEL_HUGE) +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if defined(LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(__lzo_inline) +# define __lzo_inline +#endif +#if !defined(__lzo_forceinline) +# define __lzo_forceinline +#endif +#if !defined(__lzo_noinline) +# define __lzo_noinline +#endif + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32)(a) * (lzo_uint32)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#if 1 && !defined(LZO_CFG_NO_UNALIGNED) +#if 1 && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if (LZO_SIZEOF_SHORT == 2) +# define LZO_UNALIGNED_OK_2 +# endif +# if (LZO_SIZEOF_INT == 4) +# define LZO_UNALIGNED_OK_4 +# endif +#endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2) +#endif +#if defined(LZO_UNALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +#elif defined(LZO_ALIGNED_OK_4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32) == 4) +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const char __lzo_copyright[]; +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(lzo_uintptr_t) +# if defined(__LZO_MMODEL_HUGE) +# define lzo_uintptr_t unsigned long +# else +# define lzo_uintptr_t acc_uintptr_t +# ifdef __ACC_INTPTR_T_IS_POINTER +# define __LZO_UINTPTR_T_IS_POINTER 1 +# endif +# endif +#endif + +#if (LZO_ARCH_I086) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((ACC_PTR_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((ACC_PTR_FP_OFF(a) | ACC_PTR_FP_OFF(b)) & 3) == 0) +#elif (LZO_MM_PVP) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_8(a) ((((lzo_uintptr_t)(a)) >> 61) == 0) +#define PTR_ALIGNED2_8(a,b) ((((lzo_uintptr_t)(a)|(lzo_uintptr_t)(b)) >> 61) == 0) +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if 0 && (LZO_ARCH_I086) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) + p = (((lzo_uintptr_t)(ACC_PTR_FP_SEG(ptr))) << (16 - ACC_MM_AHSHIFT)) + (ACC_PTR_FP_OFF(ptr)); +#elif (LZO_MM_PVP) + p = (lzo_uintptr_t) (ptr); + p = (p << 3) | (p >> 61); +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if defined(__LZO_UINTPTR_T_IS_POINTER) + size_t n = (size_t) ptr; + n = (((n + size - 1) / size) * size) - n; +#else + lzo_uintptr_t p, n; + p = __lzo_ptr_linear(ptr); + n = (((p + size - 1) / size) * size) - p; +#endif + + assert(size > 0); + assert((long)n >= 0); + assert(n <= size); + return (unsigned)n; +} + +#endif + +/* If you use the LZO library in a product, I would appreciate that you + * keep this copyright string in the executable of your product. + */ + +const char __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Built: " __DATE__ " " __TIME__ " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ +#if (LZO_OS_DOS16 && LZO_CC_TURBOC) + return (lzo_voidp) __lzo_copyright; +#else + return (const lzo_bytep) __lzo_copyright; +#endif +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCMP) + const lzo_hbyte_p p1 = (const lzo_hbyte_p) s1; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) s2; + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMCPY) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMMOVE) + lzo_hbyte_p p1 = (lzo_hbyte_p) dest; + const lzo_hbyte_p p2 = (const lzo_hbyte_p) src; + if (!(len > 0) || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int c, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !defined(HAVE_MEMSET) + lzo_hbyte_p p = (lzo_hbyte_p) s; + if __lzo_likely(len > 0) do + *p++ = (unsigned char) c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, c, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif + +#if !defined(__LZO_IN_MINILZO) + +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) + + ACCCHK_ASSERT_IS_SIGNED_T(lzo_int32) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uint32) + ACCCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + ACCCHK_ASSERT(sizeof(lzo_uint32) >= 4) + +#if !defined(__LZO_UINTPTR_T_IS_POINTER) + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + ACCCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + + ACCCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint32)) + ACCCHK_ASSERT(sizeof(lzo_xint) >= sizeof(lzo_uint)) + ACCCHK_ASSERT(sizeof(lzo_xint) == sizeof(lzo_uint32) || sizeof(lzo_xint) == sizeof(lzo_uint)) + +#endif +#undef ACCCHK_ASSERT + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + union { unsigned char c[2*sizeof(lzo_xint)]; lzo_xint l[2]; } u; + lzo_uintptr_t p; + +#if !defined(LZO_CFG_NO_CONFIG_CHECK) +#if defined(LZO_ABI_BIG_ENDIAN) + u.l[0] = u.l[1] = 0; u.c[sizeof(lzo_xint) - 1] = 128; + r &= (u.l[0] == 128); +#endif +#if defined(LZO_ABI_LITTLE_ENDIAN) + u.l[0] = u.l[1] = 0; u.c[0] = 128; + r &= (u.l[0] == 128); +#endif +#if defined(LZO_UNALIGNED_OK_2) + p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0]; + u.l[0] = u.l[1] = 0; + r &= ((* (const lzo_ushortp) (p+1)) == 0); +#endif +#if defined(LZO_UNALIGNED_OK_4) + p = (lzo_uintptr_t) (const lzo_voidp) &u.c[0]; + u.l[0] = u.l[1] = 0; + r &= ((* (const lzo_uint32p) (p+1)) == 0); +#endif +#endif + + LZO_UNUSED(u); LZO_UNUSED(p); + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define ACC_WANT_ACC_CHK_CH 1 +#undef ACCCHK_ASSERT +#define ACCCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef ACCCHK_ASSERT + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#define do_compress _lzo1x_1_do_compress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include "lzo/lzo1x.h" +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + register const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { + register const lzo_bytep m_pos; + lzo_uint m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if __lzo_likely(m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if __lzo_unlikely(ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = pd(ip, ii); + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_bytep end = in_end; + const lzo_bytep m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = pd(ip, ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if __lzo_unlikely(ip >= ip_end) + break; + } + + *out_len = pd(op, out); + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_bytep op = out; + lzo_uint t; + + if __lzo_unlikely(in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (m_pos < out || m_pos >= op) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (m_pos < out || m_pos >= op - (o)) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_bytep op; + register const lzo_bytep ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + register const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + do { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } while (TEST_IP && TEST_OP); + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = pd(op, out); + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ + diff --git a/branches/V-1.5.3/veejay-server/liblzo/minilzo.h b/branches/V-1.5.3/veejay-server/liblzo/minilzo.h new file mode 100644 index 00000000..0aff50e4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/liblzo/minilzo.h @@ -0,0 +1,106 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x2030 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/branches/V-1.5.3/veejay-server/libsample/Makefile.am b/branches/V-1.5.3/veejay-server/libsample/Makefile.am new file mode 100644 index 00000000..e9ab0637 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libsample/Makefile.am @@ -0,0 +1,9 @@ +# Makefile for veejay + +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/vjmem -I$(top_srcdir)/vjmsg -I$(top_srcdir)/libhash \ + -I$(top_srcdir)/mjpegtools $(FFMPEG_CFLAGS) $(XML2_CFLAGS) +AM_CFLAGS=$(OP_CFLAGS) +SAMPLE_LIB_FILE = libsample.la +noinst_LTLIBRARIES = $(SAMPLE_LIB_FILE) +libsample_la_SOURCES = sampleadm.c +EXTRA_DIST= sampleadm.h diff --git a/branches/V-1.5.3/veejay-server/libsample/sampleadm.c b/branches/V-1.5.3/veejay-server/libsample/sampleadm.c new file mode 100644 index 00000000..8ee109e1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libsample/sampleadm.c @@ -0,0 +1,3509 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg / + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + * + * + * 05/03/2003: Added XML code from Jeff Carpenter ( jrc@dshome.net ) + * 05/03/2003: Included more sample properties in Jeff's code + * Create is used to write the Sample to XML, Parse is used to load from XML + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#define KAZLIB_OPAQUE_DEBUG 1 + +#ifdef HAVE_XML2 +#endif + +#define FOURCC(a,b,c,d) ( (d<<24) | ((c&0xff)<<16) | ((b&0xff)<<8) | (a&0xff) ) + +#define FOURCC_RIFF FOURCC ('R', 'I', 'F', 'F') +#define FOURCC_WAVE FOURCC ('W', 'A', 'V', 'E') +#define FOURCC_FMT FOURCC ('f', 'm', 't', ' ') +#define FOURCC_DATA FOURCC ('d', 'a', 't', 'a') + + +#define VJ_IMAGE_EFFECT_MIN vj_effect_get_min_i() +#define VJ_IMAGE_EFFECT_MAX vj_effect_get_max_i() +#define VJ_VIDEO_EFFECT_MIN vj_effect_get_min_v() +#define VJ_VIDEO_EFFECT_MAX vj_effect_get_max_v() + +static int this_sample_id = 0; /* next available sample id */ +static int next_avail_num = 0; /* available sample id */ +static int initialized = 0; /* whether we are initialized or not */ +static hash_t *SampleHash; /* hash of sample information structs */ +static int avail_num[SAMPLE_MAX_SAMPLES]; /* an array of freed sample id's */ +static void *sample_font_ = NULL; +static int sampleadm_state = SAMPLE_PEEK; /* default state */ + +extern void tagParseStreamFX(char *file, xmlDocPtr doc, xmlNodePtr cur, void *font, void *vp); +extern void tag_writeStream( char *file, int n, xmlNodePtr node, void *font, void *vp ); +extern int vj_tag_size(); + +typedef struct +{ + int active; + int current; + int size; + int *samples; +} seq_t; + +/**************************************************************************************************** + * + * sample_size + * + * returns current sample_id pointer. size is actually this_sample_id - next_avail_num, + * but people tend to use size as in length. + * + ****************************************************************************************************/ +int sample_size() +{ + return this_sample_id; +} + +int sample_verify() { + return hash_verify( SampleHash ); +} + + + +/**************************************************************************************************** + * + * int_hash + * + * internal usage. returns hash_val_t for key + * + ****************************************************************************************************/ +static hash_val_t int_hash(const void *key) +{ + return (hash_val_t) key; +} + + + +/**************************************************************************************************** + * + * int_compare + * + * internal usage. compares keys for hash. + * + ****************************************************************************************************/ +static int int_compare(const void *key1, const void *key2) +{ + return ((int) key1 < (int) key2 ? -1 : + ((int) key1 > (int) key2 ? +1 : 0)); +} + +int sample_update(sample_info *sample, int s1) { + if(s1 <= 0 || s1 >= SAMPLE_MAX_SAMPLES) return 0; + if(sample) { + hnode_t *sample_node = hnode_create(sample); + hnode_put(sample_node, (void*) s1); + hnode_destroy(sample_node); + return 1; + } + return 0; +} + +/* Evil code for edl saving/restoring */ +typedef struct +{ + int fmt; + int deinterlace; + int flags; + int force; + char norm; +} sample_setting; + +static sample_setting __sample_project_settings; +void sample_set_project(int fmt, int deinterlace, int flags, int force, char norm ) +{ + __sample_project_settings.fmt = fmt; + __sample_project_settings.deinterlace = deinterlace; + __sample_project_settings.flags = flags; + __sample_project_settings.force = force; + __sample_project_settings.norm = norm; +} +void *sample_get_dict( int sample_id ) +{ +#ifdef HAVE_FREETYPE + sample_info *si = sample_get(sample_id); + if(si) + return si->dict; +#endif + return NULL; +} + +/**************************************************************************************************** + * + * sample_init() + * + * call before using any other function as sample_skeleton_new + * + ****************************************************************************************************/ +void sample_init(int len, void *font) +{ + if (!initialized) { + int i; + for (i = 0; i < SAMPLE_MAX_SAMPLES; i++) + avail_num[i] = 0; + this_sample_id = 1; /* do not start with zero */ + if (! + (SampleHash = + hash_create(HASHCOUNT_T_MAX, int_compare, int_hash))) { + } + initialized = 1; + veejay_memset( &__sample_project_settings,0,sizeof(sample_setting)); + + } + + sample_font_ = font; +} + +void sample_free() +{ + if(!SampleHash) + return; + hscan_t scan; + hash_scan_begin( &scan, (hash_t*) SampleHash ); + hnode_t *node; + while( (node = hash_scan_next(&scan)) != NULL ) + { + sample_info *info = (sample_info*) node; + sample_del( info->sample_id); + } + hash_free_nodes( SampleHash ); + hash_destroy( SampleHash ); +} + +int sample_set_state(int new_state) +{ + if (new_state == SAMPLE_LOAD || new_state == SAMPLE_RUN + || new_state == SAMPLE_PEEK) { + sampleadm_state = new_state; + } + return sampleadm_state; +} + +int sample_get_state() +{ + return sampleadm_state; +} + +/**************************************************************************************************** + * + * sample_skeleton_new(long , long) + * + * create a new sample, give start and end of new sample. returns sample info block. + * + ****************************************************************************************************/ + +static int _new_id() +{ + /* perhaps we can reclaim a sample id */ + int n; + int id = 0; + for (n = 0; n <= next_avail_num; n++) + { + if (avail_num[n] != 0) + { + id = avail_num[n]; + avail_num[n] = 0; + break; + } + } + if( id == 0 ) + { + if(!this_sample_id) this_sample_id = 1; + id = this_sample_id; + this_sample_id ++; + } + return id; +} + +sample_info *sample_skeleton_new(long startFrame, long endFrame) +{ + char tmp_file[32]; + sample_info *si; + int i, j; + + if (!initialized) { + return NULL; + } + si = (sample_info *) vj_calloc(sizeof(sample_info)); + + if(startFrame < 0) startFrame = 0; + + if(endFrame <= startFrame ) + { + veejay_msg(VEEJAY_MSG_ERROR,"End frame %ld must be greater then start frame %ld", endFrame, startFrame); + return NULL; + } + + if (!si) { + return NULL; + } + + si->sample_id = _new_id(); + snprintf(si->descr,SAMPLE_MAX_DESCR_LEN, "Sample %4d", si->sample_id); + si->first_frame = startFrame; + si->last_frame = endFrame; + si->edit_list = NULL; // clone later + si->soft_edl = 1; + si->speed = 1; + si->looptype = 1; // normal looping + si->audio_volume = 50; + si->marker_start = 0; + si->marker_end = 0; + si->loopcount = 0; + si->encoder_base = (char*) vj_calloc(sizeof(char) * 255); + si->encoder_destination = (char*) vj_calloc(sizeof(char) * 255); + si->effect_toggle = 1; + snprintf(tmp_file,sizeof(tmp_file), "sample_%05d.edl", si->sample_id ); + si->edit_list_file = strdup( tmp_file ); + + sample_eff_chain *sec = (sample_eff_chain*) vj_calloc(sizeof(sample_eff_chain) * SAMPLE_MAX_EFFECTS ); + + /* the effect chain is initially empty ! */ + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) { + si->effect_chain[i] = &sec[i]; + if (si->effect_chain[i] == NULL) { + veejay_msg(VEEJAY_MSG_ERROR, "Error allocating entry %d in Effect Chain for new sample",i); + return NULL; + } + si->effect_chain[i]->effect_id = -1; + si->effect_chain[i]->volume = 50; + si->effect_chain[i]->channel = ( sample_size() <= 0 ? si->sample_id : sample_size()-1); + si->effect_chain[i]->kf = vpn( VEVO_ANONYMOUS_PORT ); + } +#ifdef HAVE_FREETYPE + si->dict = vpn( VEVO_ANONYMOUS_PORT ); +#endif + return si; +} + +int sample_store(sample_info * skel) +{ + hnode_t *sample_node; + if (!skel) + return -1; + sample_node = hnode_create(skel); + if (!sample_node) + return -1; + + if(skel->edit_list) + { + skel->play_length = vj_el_bogus_length( skel->edit_list, 0 ); + } + + if (!sample_exists(skel->sample_id)) { + hash_insert(SampleHash, sample_node, (void *) skel->sample_id); + } else { + hnode_put(sample_node, (void *) skel->sample_id); + } + return 0; +} + +/**************************************************************************************************** + * + * sample_get(int sample_id) + * + * returns sample information struct or NULL on error. + * + ****************************************************************************************************/ + +typedef struct { + int id; + sample_info *si; +} row_t; + +static row_t recent_samples_[12]; +static int recent_ = 0; + +sample_info *sample_get(int sample_id) +{ + sample_info *si; + + int i; + for( i = 0; i < 12; i ++ ) { + if( recent_samples_[i].id == sample_id ) + return recent_samples_[i].si; + } + + hnode_t *sample_node = hash_lookup(SampleHash, (void *) sample_id); + if (sample_node) { + si = (sample_info *) hnode_get(sample_node); + recent_samples_[recent_].si = si; + recent_samples_[recent_].id = sample_id; + recent_ = (recent_+1) % 12; + if(si) return si; + } + return NULL; +} + +/**************************************************************************************************** + * + * sample_exists(int sample_id) + * + * returns 1 if a sample exists in samplehash, or 0 if not. + * + ****************************************************************************************************/ + + +int sample_exists(int sample_id) { + + hnode_t *sample_node; + if (!sample_id) return 0; + + sample_node = hash_lookup(SampleHash, (void*) sample_id); + if (!sample_node) { + return 0; + } + + if(!sample_get(sample_id)) return 0; + return 1; +} +/* +int sample_exists(int sample_id) +{ + if(sample_id < 1 || sample_id > SAMPLE_MAX_SAMPLES) return 0; + return (sample_get(sample_id) == NULL ? 0 : 1); +} +*/ + +int sample_copy(int sample_id) +{ + int i; + sample_info *org, *copy; + if (!sample_exists(sample_id)) + return 0; + org = sample_get(sample_id); + copy = (sample_info*) vj_malloc(sizeof(sample_info)); + veejay_memcpy( copy,org,sizeof(sample_info));\ + + sample_eff_chain *b = vj_malloc(sizeof(sample_eff_chain) * SAMPLE_MAX_EFFECTS ); + + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + { +// copy->effect_chain[i] = +// (sample_eff_chain *) vj_malloc(sizeof(sample_eff_chain)); +// + + copy->effect_chain[i] = &b[i]; + + if (copy->effect_chain[i] == NULL) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error allocating entry %d in Effect Chain for new sample",i); + return 0; + } + veejay_memcpy( copy->effect_chain[i], org->effect_chain[i], sizeof( sample_eff_chain ) ); + } + + copy->sample_id = _new_id(); + + if(org->edit_list) + { + copy->edit_list = vj_el_clone( org->edit_list ); + copy->soft_edl = 1; + } + + if (sample_store(copy) != 0) + return 0; + + return copy->sample_id; +} + +/**************************************************************************************************** + * + * sample_get_startFrame(int sample_id) + * + * returns first frame of sample. + * + ****************************************************************************************************/ +int sample_get_longest(int sample_id) +{ + sample_info *si = sample_get(sample_id); + if(si) + { + int len = (si->last_frame - + si->first_frame ); + int c = 0; + int tmp = 0; + int t=0; + int _id=0; + int speed = abs(si->speed); + if( speed == 0 ) { + veejay_msg(VEEJAY_MSG_WARNING, + "Starting paused sample %d at normal speed", + sample_id); + speed = 1; + } + int duration = len / speed; //how many frames are played of this sample + + if( si->looptype == 2) duration *= 2; // pingpong loop duration + + if( sample_get_framedup(sample_id) > 0 ) + duration *= sample_get_framedup(sample_id); + + for(c=0; c < SAMPLE_MAX_EFFECTS; c++) + { + _id = sample_get_chain_channel(sample_id,c); + t = sample_get_chain_source(sample_id,c); + + if(t==0 && sample_exists(_id)) + { + tmp = sample_get_endFrame( _id) - sample_get_startFrame(_id); + if(tmp>0) + { + tmp = tmp / sample_get_speed(_id); + if(tmp < 0) tmp *= -1; + if(sample_get_looptype(_id)==2) tmp *= 2; //pingpong loop underlying sample + } + if(tmp > duration) duration = tmp; //which one is longer ... + } + } + veejay_msg(VEEJAY_MSG_DEBUG, "Length of sample in video frames: %ld (slow=%d, loop=%d, speed=%d)",duration, + sample_get_framedup(sample_id), si->looptype, si->speed ); + + + return duration; + } + return 0; +} + +int sample_get_startFrame(int sample_id) +{ + sample_info *si = sample_get(sample_id); + if (si) { + if (si->marker_start >= 0 || si->marker_end > 0) + return si->marker_start; + else + return si->first_frame; + } + return -1; +} + +int sample_has_cali_fx(int sample_id) +{ + sample_info *si = sample_get(sample_id); + if(si == NULL) + return -1; + int i; + for( i =0;i < SAMPLE_MAX_EFFECTS; i ++ ) { + if(si->effect_chain[i]->effect_id == 190) + return i; + } + return -1; +} + +void sample_cali_prepare( int sample_id, int slot, int chan ) +{ + sample_info *si = sample_get(sample_id); + if(si == NULL) + return; + vj_tag *tag = vj_tag_get( chan ); + if( tag == NULL || tag->source_type != VJ_TAG_TYPE_CALI ) + return; + int fx_id = vj_effect_real_to_sequence( + si->effect_chain[slot]->effect_id ); + if( fx_id >= 0 ) { + vj_tag_cali_prepare_now( chan, fx_id ); + veejay_msg(VEEJAY_MSG_DEBUG, "Prepared calibration data."); + } +} + + + +int sample_get_el_position( int sample_id, int *start, int *end ) +{ + sample_info *si = sample_get(sample_id); + if(si) + { + *start = si->first_frame; + *end = si->last_frame; + return 1; + } + return -1; +} + + + + +int sample_get_short_info(int sample_id, int *start, int *end, int *loop, int *speed) { + sample_info *si = sample_get(sample_id); + if(si) { + if(si->marker_start >= 0 && si->marker_end > 0) { + *start = si->marker_start; + *end = si->marker_end; + } + else { + *start = si->first_frame; + *end = si->last_frame; + } + *speed = si->speed; + *loop = si->looptype; + return 0; + } + *start = 0; + *end = 0; + *loop = 0; + *speed = 0; + return -1; +} + +int sample_entry_is_rendering(int s1, int position) { + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS || position < 0) + return -1; + return sample->effect_chain[position]->is_rendering; +} + +int sample_entry_set_is_rendering(int s1, int position, int value) { + sample_info *si = sample_get(s1); + if (!si) + return -1; + if( position >= SAMPLE_MAX_EFFECTS || position < 0) return -1; + + si->effect_chain[position]->is_rendering = value; + return ( sample_update( si,s1 )); +} + + +int sample_update_offset(int s1, int n_frame) +{ + int len; + sample_info *si = sample_get(s1); + + if(!si) return -1; + si->offset = (n_frame - si->first_frame); + len = si->last_frame - si->first_frame; + if(si->offset < 0) + { + veejay_msg(VEEJAY_MSG_WARNING,"Sample bounces outside sample by %d frames", + si->offset); + si->offset = 0; + } + if(si->offset > len) + { + veejay_msg(VEEJAY_MSG_WARNING,"Sample bounces outside sample with %d frames", + si->offset); + si->offset = len; + } + return ( sample_update(si,s1)); +} + +int sample_set_manual_fader( int s1, int value) +{ + sample_info *si = sample_get(s1); + if(!si) return -1; + si->fader_active = 2; + si->fader_val = (float) value; + si->fader_inc = 0.0; + si->fader_direction = 0.0; + + /* inconsistency check */ + if(si->effect_toggle == 0) si->effect_toggle = 1; + return (sample_update(si,s1)); + +} + +int sample_set_fader_active( int s1, int nframes, int direction ) { + sample_info *si = sample_get(s1); + if(!si) return -1; + if(nframes <= 0) return -1; + si->fader_active = 1; + + if(direction<0) + si->fader_val = 255.0; + else + si->fader_val = 0.0; + + si->fader_inc = (float) (255.0 / (float) nframes); + si->fader_direction = direction; + si->fader_inc *= si->fader_direction; + /* inconsistency check */ + if(si->effect_toggle == 0) + { + si->effect_toggle = 1; + } + return (sample_update(si,s1)); +} + + +int sample_reset_fader(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + si->fader_active = 0; + si->fader_val = 0; + si->fader_inc = 0; + return (sample_update(si,s1)); +} + +int sample_get_fader_active(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + return (si->fader_active); +} + +float sample_get_fader_val(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + return (si->fader_val); +} + +float sample_get_fader_inc(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + return (si->fader_inc); +} + +int sample_get_fader_direction(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + return si->fader_direction; +} + +int sample_set_fader_val(int s1, float val) { + sample_info *si = sample_get(s1); + if(!si) return -1; + si->fader_val = val; + return (sample_update(si,s1)); +} + +int sample_apply_fader_inc(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + si->fader_val += si->fader_inc; + if(si->fader_val > 255.0 ) si->fader_val = 255.0; + if(si->fader_val < 0.0 ) si->fader_val = 0.0; + sample_update(si,s1); + return (int) (si->fader_val+0.5); +} + + + +int sample_set_fader_inc(int s1, float inc) { + sample_info *si = sample_get(s1); + if(!si) return -1; + si->fader_inc = inc; + return (sample_update(si,s1)); +} + +int sample_marker_clear(int sample_id) { + sample_info *si = sample_get(sample_id); + if (!si) + return -1; + si->marker_start = 0; + si->marker_end = 0; + veejay_msg(VEEJAY_MSG_INFO, "Marker cleared (%d - %d) - (speed=%d)", + si->marker_start, si->marker_end, si->speed); + return ( sample_update(si,sample_id)); +} + +int sample_set_marker_start(int sample_id, int marker) +{ + sample_info *si = sample_get(sample_id); + if (!si) + return -1; + if(si->speed < 0 ) + { + int swap = si->marker_end; + si->marker_end = marker; + si->marker_start = swap; + } + else + { + si->marker_start = marker; + } + return ( sample_update(si,sample_id)); +} + +int sample_set_marker(int sample_id, int start, int end) +{ + sample_info *si = sample_get(sample_id); + if(!si) return 0; + + if( start < si->first_frame ) + return 0; + if( start > si->last_frame ) + return 0; + if( end < si->first_frame ) + return 0; + if( end > si->last_frame ) + return 0; + + si->marker_start = start; + si->marker_end = end; + + return ( sample_update( si , sample_id ) ); +} + +int sample_set_marker_end(int sample_id, int marker) +{ + sample_info *si = sample_get(sample_id); + if (!si) + return -1; + + if(si->speed < 0 ) + { + // mapping in reverse! + int swap = si->marker_start; + si->marker_start = marker; + si->marker_end = swap; + } + else + { + si->marker_end = marker; + } + + return (sample_update(si,sample_id)); +} + +int sample_set_description(int sample_id, char *description) +{ + sample_info *si = sample_get(sample_id); + if (!si) + return -1; + if (!description || strlen(description) <= 0) { + snprintf(si->descr, SAMPLE_MAX_DESCR_LEN, "Sample%04d", si->sample_id ); + } else { + snprintf(si->descr, SAMPLE_MAX_DESCR_LEN, "%s", description); + } + return ( sample_update(si, sample_id)==1 ? 0 : 1); +} + +int sample_get_description(int sample_id, char *description) +{ + sample_info *si; + si = sample_get(sample_id); + if (!si) + return -1; + snprintf(description, SAMPLE_MAX_DESCR_LEN,"%s", si->descr); + return 0; +} + +/**************************************************************************************************** + * + * sample_get_endFrame(int sample_id) + * + * returns last frame of sample. + * + ****************************************************************************************************/ +int sample_get_endFrame(int sample_id) +{ + sample_info *si = sample_get(sample_id); + if (si) { + if (si->marker_end > 0 && si->marker_start >= 0) + return si->marker_end; + else { + return si->last_frame; + } + } + return -1; +} +/**************************************************************************************************** + * + * sample_del( sample_nr ) + * + * deletes a sample from the hash. returns -1 on error, 1 on success. + * + ****************************************************************************************************/ +int sample_verify_delete( int sample_id, int sample_type ) +{ + int i,j; + for( i = 1; i < sample_size()-1; i ++ ) + { + sample_info *s = sample_get(i); + if(s) + { + for( j = 0 ; j < SAMPLE_MAX_EFFECTS; j ++ ) + { + if(s->effect_chain[j]->channel == sample_id && + s->effect_chain[j]->source_type == sample_type ) + { + s->effect_chain[j]->channel = i; + s->effect_chain[j]->source_type = 0; + veejay_msg(VEEJAY_MSG_INFO, "Dereferenced mix entry %d of Sample %d", + j, i ); + sample_update( s, i ); + } + } + } + } + return 1; +} + +int sample_del(int sample_id) +{ + hnode_t *sample_node; + sample_info *si; + si = sample_get(sample_id); + if (!si) + return 0; + + sample_node = hash_lookup(SampleHash, (void *) si->sample_id); + if (sample_node) { + int i; + if(si->soft_edl == 0 && si->edit_list != NULL) + vj_el_break_cache( si->edit_list ); //@ destroy cache, if any + + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + if( si->effect_chain[i]->kf ) + vevo_port_free( si->effect_chain[i]->kf ); + } + //@ *sample_eff_chain -> &addr[0] + if( si->effect_chain[0] ) + free(si->effect_chain[0]); + + if(si->edit_list) + vj_el_free(si->edit_list); + + if(si->encoder_base ) + free(si->encoder_base ); + if(si->encoder_destination ) + free(si->encoder_destination ); + if(si->edit_list_file) + free( si->edit_list_file ); +#ifdef HAVE_FREETYPE +//font ? + if( si->dict ) + vj_font_dictionary_destroy( sample_font_,si->dict ); +#endif + if(si->viewport) { + viewport_destroy(si->viewport); + si->viewport = NULL; + } + free(si); + + /* store freed sample_id */ + avail_num[next_avail_num] = sample_id; + next_avail_num++; + hash_delete(SampleHash, sample_node); + + veejay_msg(VEEJAY_MSG_DEBUG, "Deleted sample %d",sample_id ); + + return 1; + } + + return 0; +} + + +void sample_del_all() +{ + int end = sample_size(); + int i; + for (i = 1; i < end; i++) { + if (sample_exists(i)) { + sample_chain_clear(i); + sample_del(i); + } + } + this_sample_id = 0; +} + +/**************************************************************************************************** + * + * sample_get_effect( sample_nr , position) + * + * returns effect in effect_chain on position X , -1 on error. + * + ****************************************************************************************************/ +int sample_get_effect(int s1, int position) +{ + sample_info *sample = sample_get(s1); + if(position >= SAMPLE_MAX_EFFECTS || position < 0 ) return -1; + if(sample) { + if(sample->effect_chain[position]->e_flag==0) return -1; + return sample->effect_chain[position]->effect_id; + } + return -1; +} + +int sample_get_effect_any(int s1, int position) { + sample_info *sample = sample_get(s1); +#ifdef STRICT_CHECKING + assert( position >= 0 && position < SAMPLE_MAX_EFFECTS ); +#endif + // if(position >= SAMPLE_MAX_EFFECTS || position < 0 ) return -1; + if(sample) { + return sample->effect_chain[position]->effect_id; + } + return -1; +} + +int sample_get_chain_status(int s1, int position) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + return sample->effect_chain[position]->e_flag; +} + +int sample_get_first_mix_offset(int s1, int *parent, int look_for) +{ + sample_info *sample = sample_get(s1); + if(!sample) + return 0; + int p = 0; + for( p = 0; p < SAMPLE_MAX_EFFECTS; p ++ ) + if( sample->effect_chain[p]->frame_offset && sample->effect_chain[p]->source_type == 0 && look_for == + sample->effect_chain[p]->channel) + { + return sample->effect_chain[p]->frame_offset; + } + return 0; +} + + +int sample_get_offset(int s1, int position) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + return sample->effect_chain[position]->frame_offset; +} + +int sample_get_trimmer(int s1, int position) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + return sample->effect_chain[position]->frame_trimmer; +} + +int sample_get_chain_volume(int s1, int position) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + return sample->effect_chain[position]->volume; +} + +int sample_get_chain_audio(int s1, int position) +{ + sample_info *sample = sample_get(s1); + if (sample) { + return sample->effect_chain[position]->a_flag; + } + return -1; +} + +/**************************************************************************************************** + * + * sample_get_looptype + * + * returns the type of loop set on the sample. 0 on no loop, 1 on ping pong + * returns -1 on error. + * + ****************************************************************************************************/ + +int sample_get_looptype(int s1) +{ + sample_info *sample = sample_get(s1); + if (sample) { + return sample->looptype; + } + return 0; +} + +int sample_get_playmode(int s1) +{ + sample_info *sample = sample_get(s1); + if (sample) { + return sample->playmode; + } + return -1; +} + +/******************** + * get depth: 1 means do what is in underlying sample. + *******************/ +int sample_get_depth(int s1) +{ + sample_info *sample = sample_get(s1); + if (sample) + return sample->depth; + return 0; +} + +int sample_set_depth(int s1, int n) +{ + sample_info *sample; + hnode_t *sample_node; + + if (n == 0 || n == 1) { + sample = sample_get(s1); + if (!sample) + return -1; + if (sample->depth == n) + return 1; + sample->depth = n; + sample_node = hnode_create(sample); + if (!sample_node) { + return -1; + } + return 1; + } + return -1; +} +int sample_set_chain_status(int s1, int position, int status) +{ + sample_info *sample; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + sample = sample_get(s1); + if (!sample) + return -1; + sample->effect_chain[position]->e_flag = status; + sample_update(sample,s1); + return 1; +} + +/**************************************************************************************************** + * + * sample_get_speed + * + * returns the playback speed set on the sample. + * returns -1 on error. + * + ****************************************************************************************************/ + +int sample_get_speed(int s1) +{ + sample_info *sample = sample_get(s1); + if (sample) + return sample->speed; + return 0; +} + +int sample_get_framedup(int s1) { + sample_info *sample = sample_get(s1); + if(sample) return sample->dup; + return 0; +} +int sample_get_framedups(int s1) { + sample_info *sample = sample_get(s1); + if(sample) return sample->dups; + return 0; + +} + +int sample_get_effect_status(int s1) +{ + sample_info *sample = sample_get(s1); + if(sample) return sample->effect_toggle; + return 0; +} + +int sample_var( int s1, int *type, int *fader, int *fx, int *rec, int *active ) +{ + sample_info *si = sample_get(s1); + if(!si) return 0; + *type = 0; + *fader = si->fader_active; + *fx = si->effect_toggle; + *rec = si->encoder_active; + *active= 1; + return 1; +} + +/**************************************************************************************************** + * + * sample_get_effect_arg( sample_nr, position, argnr ) + * + * returns the required argument set on position X in the effect_chain of sample Y. + * returns -1 on error. + ****************************************************************************************************/ +int sample_get_effect_arg(int s1, int position, int argnr) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + if (argnr < 0 || argnr > SAMPLE_MAX_PARAMETERS) + return -1; + return sample->effect_chain[position]->arg[argnr]; +} + +int sample_get_selected_entry(int s1) +{ + sample_info *sample; + sample = sample_get(s1); + if(!sample) return -1; + return sample->selected_entry; +} + +int sample_get_all_effect_arg(int s1, int position, int *args, int arg_len, int n_frame) +{ + int i; + sample_info *sample; + sample = sample_get(s1); + if( arg_len == 0) + return 1; + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + if (arg_len < 0 || arg_len > SAMPLE_MAX_PARAMETERS) + return -1; + + if( sample->effect_chain[position]->kf_status ) + { + for( i = 0; i < arg_len; i ++ ) + { + int tmp = 0; + if(!get_keyframe_value( sample->effect_chain[position]->kf, n_frame, i, &tmp ) ) + args[i] = sample->effect_chain[position]->arg[i]; + else + args[i] = tmp; + } + } + else + { + for (i = 0; i < arg_len; i++) { + args[i] = sample->effect_chain[position]->arg[i]; + } + } + return i; +} + +/******************************************** + * sample_has_extra_frame. + * return 1 if an effect on the given chain entry + * requires another frame, -1 otherwise. + */ +int sample_has_extra_frame(int s1, int position) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + if (sample->effect_chain[position]->effect_id == -1) + return -1; + if (vj_effect_get_extra_frame + (sample->effect_chain[position]->effect_id) == 1) + return 1; + return -1; +} + +/**************************************************************************************************** + * + * sample_set_effect_arg + * + * sets an argument ARGNR in the chain on position X of sample Y + * returns -1 on error. + * + ****************************************************************************************************/ + +int sample_set_effect_arg(int s1, int position, int argnr, int value) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + if (argnr < 0 || argnr > SAMPLE_MAX_PARAMETERS) + return -1; + sample->effect_chain[position]->arg[argnr] = value; + return ( sample_update(sample,s1)); +} + +int sample_set_selected_entry(int s1, int position) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + if(position< 0 || position >= SAMPLE_MAX_EFFECTS) return -1; + sample->selected_entry = position; + return (sample_update(sample,s1)); +} + +int sample_set_effect_status(int s1, int status) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + if(status == 1 || status == 0 ) + { + sample->effect_toggle = status; + return ( sample_update(sample,s1)); + } + return -1; +} + +int sample_set_chain_channel(int s1, int position, int input) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + + + + //sample->effect_chain[position]->channel = input; + int src_type = sample->effect_chain[position]->source_type; + // now, reset cache and setup + if( src_type == 0) + { + sample_info *new = sample_get( input ); + + if( sample->effect_chain[position]->channel != input && sample->effect_chain[position]->effect_id > 0) + { + sample_info *old = sample_get( sample->effect_chain[position]->channel ); + if(old) + vj_el_break_cache( old->edit_list ); // no longer needed + + if(new) + vj_el_setup_cache( new->edit_list ); // setup new cache + } + } + sample->effect_chain[position]->channel = input; + + return ( sample_update(sample,s1)); +} + +static int sample_sample_used(sample_info *a, int b ) +{ + int i; + for( i = 0; i < SAMPLE_MAX_EFFECTS; i ++ ) + { + int src_type = a->effect_chain[i]->source_type; + int id = a->effect_chain[i]->channel; + if( src_type == 0 && id == b ) + return 1; + } + return 0; +} + +int sample_stop_playing(int s1, int new_s1) +{ + sample_info *sample = sample_get(s1); + sample_info *newsample = NULL; + if( new_s1 ) + newsample = sample_get(new_s1); + if (!sample) + return 0; + if (new_s1 && !newsample) + return 0; + unsigned int i,j; + + //@ stop playing, if new_s1 + + if( new_s1 == s1 ) + return 1; + + int destroy_s1 = 1; + + if( new_s1 ) + { + for( i = 0; i < SAMPLE_MAX_EFFECTS ; i ++ ) + { + int src_type = newsample->effect_chain[i]->source_type; + int id = newsample->effect_chain[i]->channel; + if( src_type == 0 && id == s1 ) + destroy_s1 = 0; // no need to destroy cache, used by newsample + } + } + + if(destroy_s1) + vj_el_break_cache( sample->edit_list ); // break the cache + + + if( new_s1 ) + { + for( i = 0; i < SAMPLE_MAX_EFFECTS;i++ ) + { + int src_type = sample->effect_chain[i]->source_type; + int id = sample->effect_chain[i]->channel; + if( src_type == 0 && id > 0 ) + { + //@ if ID is not in newsample, + if( !sample_sample_used( newsample, id )) + { + sample_info *second = sample_get( id ); + if(second) //@ get and destroy its cache + vj_el_break_cache( second->edit_list ); + } + } + } + } + + return 1; +} + +int sample_cache_used( int s1 ) +{ + return cache_avail_mb(); +} + +int sample_start_playing(int s1, int no_cache) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + int i; + + if(!no_cache) + vj_el_setup_cache( sample->edit_list ); + + for( i = 0; i < SAMPLE_MAX_EFFECTS; i ++ ) + { + int src_type = sample->effect_chain[i]->source_type; + int id = sample->effect_chain[i]->channel; + if( src_type == 0 && id > 0 && sample->effect_chain[i]->effect_id > 0 ) + { + sample_info *second = sample_get( id ); + if(second) + vj_el_setup_cache( second->edit_list ); + } + } + + return 1; +} + +int sample_is_deleted(int s1) +{ + int i; + for (i = 0; i < next_avail_num; i++) { + if (avail_num[i] == s1) + return 1; + } + return 0; +} + +int sample_set_chain_source(int s1, int position, int input) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + + if( sample->effect_chain[position]->source_type == 0 && + sample->effect_chain[position]->channel > 0 && + sample->effect_chain[position]->effect_id > 0) + { + sample_info *second = sample_get( sample->effect_chain[position]->channel ); + if(second && second->edit_list) + vj_el_clear_cache( second->edit_list ); + sample_info *new = sample_get( input ); + if(new) + vj_el_setup_cache( new->edit_list ); + } + + sample->effect_chain[position]->source_type = input; + return (sample_update(sample,s1)); +} +int sample_load_composite_config( void *compiz, int s1 ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + + int val = 0; + void *temp = composite_load_config( compiz, sample->viewport_config , &val ); + if( temp == NULL || val == -1 ) { +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG,"No composite config for sample %d",s1); +#endif + return 0; + } + + sample->composite = val; + sample->viewport = temp; + sample_update(sample,s1); +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Loaded config for sample %d, mode %d", + s1, val ); +#endif + return sample->composite; +} + +void *sample_get_composite_view(int s1) +{ + sample_info *sample = sample_get(s1); + if(!sample) return NULL; + return sample->viewport; +} +int sample_set_composite_view(int s1, void *vp) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + sample->viewport = vp; + return (sample_update(sample,s1)); +} + +int sample_set_composite(void *compiz, int s1, int composite) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + sample->composite = composite; + if(sample->viewport_config == NULL) { + sample->composite = 1; + return sample_update(sample,s1); + } +#ifdef STRICT_CHECKING + assert( sample->viewport_config != NULL ); + assert( compiz != NULL ); +#endif + composite_add_to_config( compiz, sample->viewport_config, composite ); + + return ( sample_update(sample,s1)); +} + +int sample_get_composite(int s1) +{ + sample_info *sample = sample_get(s1); + if(!sample) return 0; + return sample->composite; +} +/**************************************************************************************************** + * + * sample_set_speed + * + * store playback speed in the sample. + * returns -1 on error. + * + ****************************************************************************************************/ +void sample_loopcount(int s1) +{ + sample_info *sample = sample_get(s1); + if (!sample) return; + sample->loopcount ++; + if(sample->loopcount > 1000000 ) + sample->loopcount = 0; +} +int sample_get_loopcount(int s1) +{ + sample_info *sample = sample_get(s1); + if (!sample) return 0; + + return sample->loopcount; +} +void sample_reset_loopcount(int s1) +{ + sample_info *sample = sample_get(s1); + if (!sample) return; + sample->loopcount = 0; +} + +int sample_set_speed(int s1, int speed) +{ + sample_info *sample = sample_get(s1); + if (!sample) return -1; + int len = sample->last_frame - + sample->first_frame; + if( (speed < -(MAX_SPEED) ) || (speed > MAX_SPEED)) + return -1; + if( speed > len ) + return -1; + if( speed < -(len)) + return -1; + sample->speed = speed; + return ( sample_update(sample,s1)); +} +int sample_set_framedups(int s1, int n) { + sample_info *sample = sample_get(s1); + if(!sample) return -1; + sample->dups = n; + return ( sample_update(sample,s1)); +} + + +int sample_set_framedup(int s1, int n) { + sample_info *sample = sample_get(s1); + if(!sample) return -1; + sample->dup = n; + return ( sample_update(sample,s1)); +} + +int sample_get_chain_channel(int s1, int position) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + return sample->effect_chain[position]->channel; +} + +int sample_get_chain_source(int s1, int position) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + return sample->effect_chain[position]->source_type; +} + +int sample_get_loops(int s1) +{ + sample_info *sample = sample_get(s1); + if (sample) { + return sample->max_loops; + } + return -1; +} +int sample_get_loops2(int s1) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + return sample->max_loops2; +} + +/**************************************************************************************************** + * + * sample_set_looptype + * + * store looptype in the sample. + * returns -1 on error. + * + ****************************************************************************************************/ + +int sample_set_looptype(int s1, int looptype) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + + if (looptype == 3 || looptype == 0 || looptype == 1 || looptype == 2) { + sample->looptype = looptype; + return ( sample_update(sample,s1)); + } + return -1; +} + +int sample_set_playmode(int s1, int playmode) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + + sample->playmode = playmode; + return ( sample_update(sample,s1)); +} + + + +/************************************************************************************************* + * update start frame + * + *************************************************************************************************/ +int sample_set_startframe(int s1, long frame_num) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return 0; + + if( frame_num < 0 ) + return 0; + + if(sample->play_length ) + return 1; //@ simpler to lie + + if(sample->edit_list) + if( frame_num > sample->edit_list->total_frames ) + frame_num = sample->edit_list->total_frames; + + sample->first_frame = frame_num; + if(sample->first_frame >= sample->last_frame ) + sample->first_frame = sample->last_frame-1; + return (sample_update(sample,s1)); +} + +int sample_usable_edl( int s1 ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return 0; + if( sample->play_length ) + return 0; + if( sample->edit_list ) + return 1; + return 0; +} + +int sample_max_video_length(int s1) +{ + sample_info *sample = sample_get(s1); + float fps = 25.0; + if(!sample) return 0; + if(sample->edit_list) + fps = sample->edit_list->video_fps; + + if( sample->play_length ) + return (60 * fps * 6); // 6 minutes + + if( sample->edit_list ) + return (int) sample->edit_list->total_frames; + return 0; +} + +int sample_video_length( int s1 ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return 0; + if( sample->play_length ) + return sample->play_length; + if( sample->edit_list ) + return sample->edit_list->total_frames; + return 0; +} + +int sample_set_endframe(int s1, long frame_num) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return 0; + if(frame_num < 0) + return 0; + + if(sample->play_length) + { +#ifdef STRICT_CHECKING + assert( sample->edit_list != NULL ); +#endif + int new_len = ( frame_num - sample->first_frame ); + if( new_len <= 1 ) + new_len = 1; + sample->last_frame = sample->first_frame + new_len; + + if( vj_el_set_bogus_length( sample->edit_list, 0, new_len ) ) + { + sample->play_length = new_len; + return (sample_update(sample,s1)); + } + return 0; + } + + if(sample->edit_list) + if( frame_num > sample->edit_list->total_frames ) + frame_num = sample->edit_list->total_frames; + + sample->last_frame = frame_num; + + return (sample_update(sample,s1)); +} + +int sample_get_next(int s1) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + return sample->next_sample_id; +} +int sample_set_loops(int s1, int nr_of_loops) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + sample->max_loops = nr_of_loops; + return (sample_update(sample,s1)); +} +int sample_set_loops2(int s1, int nr_of_loops) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + sample->max_loops2 = nr_of_loops; + return (sample_update(sample,s1)); +} + +int sample_get_sub_audio(int s1) +{ + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + return sample->sub_audio; +} + +int sample_set_sub_audio(int s1, int audio) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + if (audio < 0 && audio > 1) + return -1; + sample->sub_audio = audio; + return (sample_update(sample,s1)); +} + +int sample_get_audio_volume(int s1) +{ + sample_info *sample = sample_get(s1); + if (sample) { + return sample->audio_volume; + } + return -1; +} + +int sample_set_audio_volume(int s1, int volume) +{ + sample_info *sample = sample_get(s1); + if (volume < 0) + volume = 0; + if (volume > 100) + volume = 100; + sample->audio_volume = volume; + return (sample_update(sample,s1)); +} + + +int sample_set_next(int s1, int next_sample_id) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + /* just add, do not verify + on module generation, next sample may not yet be created. + checks in parameter set in libveejayvj.c + */ + sample->next_sample_id = next_sample_id; + return (sample_update(sample,s1)); +} + +/**************************************************************************************************** + * + * + * add a new effect to the chain, returns chain index number on success or -1 if + * the requested sample does not exist. + * + ****************************************************************************************************/ + +int sample_chain_malloc(int s1) +{ + sample_info *sample = sample_get(s1); + int i=0; + int e_id = 0; + int sum =0; + if (!sample) + return -1; + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + e_id = sample->effect_chain[i]->effect_id; + if(e_id) + { + if(vj_effect_activate(e_id)) + sum++; + } + } + veejay_msg(VEEJAY_MSG_DEBUG, "Allocated %d effects",sum); + return sum; +} + +int sample_chain_free(int s1) +{ + sample_info *sample = sample_get(s1); + int i=0; + int e_id = 0; + int sum = 0; + if (!sample) + return -1; + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + e_id = sample->effect_chain[i]->effect_id; + if(e_id!=-1) + { + if(vj_effect_initialized(e_id)) + { + vj_effect_deactivate(e_id); + sum++; + } + } + } + return sum; +} + +int sample_chain_reset_kf( int s1, int entry ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return 0; + sample->effect_chain[entry]->kf_status = 0; + if(sample->effect_chain[entry]->kf) + vevo_port_free(sample->effect_chain[entry]->kf ); + sample->effect_chain[entry]->kf = vpn(VEVO_ANONYMOUS_PORT ); + return 1; +} + +int sample_get_kf_tokens( int s1, int entry, int id, int *start, int *end, int *type ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return 0; + return keyframe_get_tokens( sample->effect_chain[entry]->kf, id, start,end,type ); +} + +void *sample_get_kf_port( int s1, int entry ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return NULL; + return sample->effect_chain[entry]->kf; +} + +int sample_get_kf_status( int s1, int entry ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return 0; + return sample->effect_chain[entry]->kf_status; +} + +int sample_chain_set_kf_status( int s1, int entry, int status ) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + sample->effect_chain[entry]->kf_status = status; + return 1; +} + +unsigned char * sample_chain_get_kfs( int s1, int entry, int parameter_id, int *len ) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return NULL; + if ( entry < 0 || entry > SAMPLE_MAX_EFFECTS ) + return NULL; + if( parameter_id < 0 || parameter_id > 9 ) + return NULL; + + unsigned char *data = keyframe_pack( sample->effect_chain[entry]->kf, parameter_id, entry,len ); + if( data ) + return data; + return NULL; +} + +int sample_chain_set_kfs( int s1, int len, unsigned char *data ) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + if( len <= 0 ) + return 0; + + int entry = 0; + if(!keyframe_unpack( data, len, &entry,s1,1 )) + { + veejay_msg(0, "Unable to unpack keyframe packet"); + return -1; + } + return 1; +} +int sample_chain_add(int s1, int c, int effect_nr) +{ + int effect_params = 0, i; + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + if (c < 0 || c >= SAMPLE_MAX_EFFECTS) + return -1; + + if ( effect_nr < VJ_IMAGE_EFFECT_MIN ) return -1; + + if ( effect_nr > VJ_IMAGE_EFFECT_MAX && effect_nr < VJ_VIDEO_EFFECT_MIN ) + return -1; + + if( sample->effect_chain[c]->effect_id != -1 && sample->effect_chain[c]->effect_id != effect_nr ) + { + //verify if the effect should be discarded + if(vj_effect_initialized( sample->effect_chain[c]->effect_id )) + { + // it is using some memory, see if we can free it ... + int i; + int ok = 1; + for(i=(c+1); i < SAMPLE_MAX_EFFECTS; i++) + { + if( sample->effect_chain[i]->effect_id == sample->effect_chain[c]->effect_id) ok = 0; + } + // ok, lets get rid of it. + if( ok ) vj_effect_deactivate( sample->effect_chain[c]->effect_id ); + } + } + + + if(!vj_effect_initialized(effect_nr)) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Effect %s must be initialized now", + vj_effect_get_description(effect_nr)); + if(!vj_effect_activate( effect_nr )) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cant activate %d", effect_nr); + return -1; + } + } + + sample->effect_chain[c]->effect_id = effect_nr; + sample->effect_chain[c]->e_flag = 1; /* effect enabled standard */ + effect_params = vj_effect_get_num_params(effect_nr); + if (effect_params > 0) + { + /* there are parameters, set default values */ + for (i = 0; i < effect_params; i++) + { + int val = vj_effect_get_default(effect_nr, i); + sample->effect_chain[c]->arg[i] = val; + } + } + if (vj_effect_get_extra_frame(effect_nr)) + { + //sample->effect_chain[c]->frame_offset = 0; + sample->effect_chain[c]->frame_trimmer = 0; + + if(s1 > 1) + s1 = s1 - 1; + if(!sample_exists(s1)) s1 = s1 + 1; + + if(sample->effect_chain[c]->channel <= 0) + sample->effect_chain[c]->channel = sample_size()-1; // follow newest + if(sample->effect_chain[c]->source_type < 0) + sample->effect_chain[c]->source_type = 0; + + veejay_msg(VEEJAY_MSG_DEBUG,"Effect %s on entry %d overlaying with sample %d", + vj_effect_get_description(sample->effect_chain[c]->effect_id),c,sample->effect_chain[c]->channel); + } + sample_update(sample,s1); + + return c; /* return position on which it was added */ +} + +int sample_reset_offset(int s1) +{ + sample_info *sample = sample_get(s1); + int i; + if(!sample) return -1; + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + sample->effect_chain[i]->frame_offset = 0; + } + return ( sample_update(sample,s1)); +} + +int sample_set_offset(int s1, int chain_entry, int frame_offset) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + /* set to zero if frame_offset is greater than sample length */ + //if(frame_offset > (sample->last_frame - sample->first_frame)) frame_offset=0; + sample->effect_chain[chain_entry]->frame_offset = frame_offset; + return (sample_update(sample,s1)); +} + +int sample_set_trimmer(int s1, int chain_entry, int trimmer) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + /* set to zero if frame_offset is greater than sample length */ + if (chain_entry < 0 || chain_entry >= SAMPLE_MAX_PARAMETERS) + return -1; + if (trimmer > (sample->last_frame - sample->first_frame)) + trimmer = 0; + if (trimmer < 0 ) trimmer = 0; + sample->effect_chain[chain_entry]->frame_trimmer = trimmer; + + return (sample_update(sample,s1)); +} +int sample_set_chain_audio(int s1, int chain_entry, int val) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + if (chain_entry < 0 || chain_entry >= SAMPLE_MAX_PARAMETERS) + return -1; + sample->effect_chain[chain_entry]->a_flag = val; + return ( sample_update(sample,s1)); +} + +int sample_set_chain_volume(int s1, int chain_entry, int volume) +{ + sample_info *sample = sample_get(s1); + if (!sample) + return -1; + /* set to zero if frame_offset is greater than sample length */ + if (volume < 0) + volume = 100; + if (volume > 100) + volume = 0; + sample->effect_chain[chain_entry]->volume = volume; + return (sample_update(sample,s1)); +} + + + + +/**************************************************************************************************** + * + * sample_chain_clear( sample_nr ) + * + * clear the entire effect chain. + * + ****************************************************************************************************/ + +int sample_chain_clear(int s1) +{ + int i, j; + sample_info *sample = sample_get(s1); + + if (!sample) + return -1; + /* the effect chain is gonna be empty! */ + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) { + if(sample->effect_chain[i]->effect_id != -1) + { + if(vj_effect_initialized( sample->effect_chain[i]->effect_id )) + vj_effect_deactivate( sample->effect_chain[i]->effect_id ); + } + sample->effect_chain[i]->effect_id = -1; + sample->effect_chain[i]->frame_offset = 0; + sample->effect_chain[i]->frame_trimmer = 0; + sample->effect_chain[i]->volume = 0; + sample->effect_chain[i]->a_flag = 0; + if( sample->effect_chain[i]->kf ) + vevo_port_free( sample->effect_chain[i]->kf ); + sample->effect_chain[i]->kf = vpn(VEVO_ANONYMOUS_PORT); + int src_type = sample->effect_chain[i]->source_type; + int id = sample->effect_chain[i]->channel; + if( src_type == 0 && id > 0 ) + { + sample_info *old = sample_get( id ); + if(old) + vj_el_clear_cache(old->edit_list); + } + sample->effect_chain[i]->source_type = 0; + sample->effect_chain[i]->channel = s1; // myself + for (j = 0; j < SAMPLE_MAX_PARAMETERS; j++) + sample->effect_chain[i]->arg[j] = 0; + } + + return (sample_update(sample,s1)); +} + + +/**************************************************************************************************** + * + * sample_chain_size( sample_nr ) + * + * returns the number of effects in the effect_chain + * + ****************************************************************************************************/ +int sample_chain_size(int s1) +{ + int i, e; + + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + e = 0; + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + if (sample->effect_chain[i]->effect_id != -1) + e++; + return e; +} + +/**************************************************************************************************** + * + * sample_chain_get_free_entry( sample_nr ) + * + * returns last available entry + * + ****************************************************************************************************/ +int sample_chain_get_free_entry(int s1) +{ + int i; + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + if (sample->effect_chain[i]->effect_id == -1) + return i; + return -1; +} + + +/**************************************************************************************************** + * + * sample_chain_remove( sample_nr, position ) + * + * Removes an Effect from the chain of sample on entry + * + ****************************************************************************************************/ + +static int _sample_can_free(sample_info *sample, int reserved, int effect_id) +{ + int i; + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + if(i != reserved && effect_id == sample->effect_chain[i]->effect_id) return 0; + } + return 1; +} + +int sample_chain_remove(int s1, int position) +{ + int j; + sample_info *sample; + sample = sample_get(s1); + if (!sample) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + if(sample->effect_chain[position]->effect_id != -1) + { + if(vj_effect_initialized( sample->effect_chain[position]->effect_id) && + _sample_can_free(sample,position, sample->effect_chain[position]->effect_id)) + vj_effect_deactivate( sample->effect_chain[position]->effect_id); + } + sample->effect_chain[position]->effect_id = -1; + sample->effect_chain[position]->frame_offset = 0; + sample->effect_chain[position]->frame_trimmer = 0; + sample->effect_chain[position]->volume = 0; + sample->effect_chain[position]->a_flag = 0; + + if( sample->effect_chain[position]->kf ) + vevo_port_free( sample->effect_chain[position]->kf ); + sample->effect_chain[position]->kf = vpn( VEVO_ANONYMOUS_PORT ); + + int src_type = sample->effect_chain[position]->source_type; + int id = sample->effect_chain[position]->channel; + if( src_type == 0 && id > 0 ) + { + sample_info *old = sample_get( id ); + if(old) + vj_el_clear_cache(old->edit_list); + } + + sample->effect_chain[position]->source_type = 0; + sample->effect_chain[position]->channel = 0; + for (j = 0; j < SAMPLE_MAX_PARAMETERS; j++) + sample->effect_chain[position]->arg[j] = 0; + + return (sample_update(sample,s1)); +} + +int sample_set_loop_dec(int s1, int active) { + sample_info *sample = sample_get(s1); + if(!sample) return -1; + sample->loop_dec = active; + return (sample_update(sample,s1)); +} + +int sample_get_loop_dec(int s1) { + sample_info *sample = sample_get(s1); + if(!sample) return -1; + return sample->loop_dec; +} + +editlist *sample_get_editlist(int s1) +{ + sample_info *sample = sample_get(s1); + if(!sample) return NULL; + return sample->edit_list; +} + +//@ is sample k in fx chain ? +int sample_cached(sample_info *s, int b_sample ) +{ + int i = 0; + for( i = 0; i < SAMPLE_MAX_EFFECTS ;i++ ) + if( s->effect_chain[i]->source_type == 0 && s->effect_chain[i]->channel == b_sample) + return 1; + return 0; +} +void sample_chain_set_kf( int s1,int i, void *port ) +{ + sample_info *sample = sample_get(s1); + if(!sample) return; + sample->effect_chain[i]->kf = port; +} + +int sample_set_editlist(int s1, editlist *edl) +{ + sample_info *sample = sample_get(s1); + if(!sample) return -1; + if(sample->edit_list) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample %d already has EDL", s1 ); + return 0; + } + sample->edit_list = edl; + sample->soft_edl = 1; + return (sample_update(sample,s1)); +} + +int sample_apply_loop_dec(int s1, double fps) { + sample_info *sample = sample_get(s1); + int inc = (int) fps; + if(!sample) return -1; +/* if(sample->loop_dec==1) { + if( (sample->first_frame + inc) >= sample->last_frame) { + sample->first_frame = sample->last_frame-1; + sample->loop_dec = 0; + } + else { + sample->first_frame += (inc / sample->loop_periods); + } + veejay_msg(VEEJAY_MSG_DEBUG, "New starting postions are %ld - %ld", + sample->first_frame, sample->last_frame); + return ( sample_update(sample, s1)); + }*/ + + sample->loop_dec ++; + + return 1; +} + + +/* print sample status information into an allocated string str*/ +//int sample_chain_sprint_status(int s1, int entry, int changed, int r_changed,char *str, +// int frame) +int sample_chain_sprint_status( int s1,int cache,int sa,int ca, int pfps, int frame, int mode,int total_slots, int seq_rec,int curfps, uint32_t lo, uint32_t hi,int macro,char *str ) +{ + sample_info *sample; + sample = sample_get(s1); + + if (!sample) + { +#ifdef STRICT_CHECKING + veejay_msg(0, "Fatal : sample %d is invalid, cannot produce a valid status line", s1 ); +#endif + return -1; + } + int e_a, e_d, e_s; + if( sa && seq_rec) + { + sample_info *rs = sample_get( seq_rec ); + e_a = rs->encoder_active; + e_d = rs->encoder_duration; + e_s = rs->encoder_succes_frames; + } + else + { + e_a = sample->encoder_active; + e_d = sample->encoder_duration; + e_s = sample->encoder_succes_frames; + } + + veejay_sprintf(str,1024, + "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + pfps, + frame, + mode, + s1, + sample->effect_toggle, + sample->first_frame, + sample->last_frame, + sample->speed, + sample->looptype, + e_a, + e_d, + e_s, + sample_size(), + sample->marker_start, + sample->marker_end, + sample->selected_entry, + total_slots, + cache, + curfps, + lo, + hi, + sa, + ca, + (int)( sample->fader_val ), + sample->dup, + macro); + + + + return 0; +} + + +#ifdef HAVE_XML2 +/************************************************************************************************* + * + * UTF8toLAT1() + * + * convert an UTF8 string to ISO LATIN 1 string + * + ****************************************************************************************************/ +unsigned char *UTF8toLAT1(unsigned char *in) +{ + int in_size, out_size; + unsigned char *out; + + if (in == NULL) + return (NULL); + + out_size = in_size = (int) strlen(in) + 1; + out = malloc((size_t) out_size); + + if (out == NULL) { + return (NULL); + } + + if (UTF8Toisolat1(out, &out_size, in, &in_size) != 0) + { + //veejay_msg(VEEJAY_MSG_ERROR, "Cannot convert '%s'", in ); + //free(out); + //return (NULL); + strncpy( out, in, out_size ); + } + + out = realloc(out, out_size + 1); + out[out_size] = 0; /*null terminating out */ + + return (out); +} + +/************************************************************************************************* + * + * ParseArguments() + * + * Parse the effect arguments using libxml2 + * + ****************************************************************************************************/ +void ParseArguments(xmlDocPtr doc, xmlNodePtr cur, int *arg) +{ + xmlChar *xmlTemp = NULL; + unsigned char *chTemp = NULL; + int argIndex = 0; + if (cur == NULL) + return; + + while (cur != NULL && argIndex < SAMPLE_MAX_PARAMETERS) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_ARGUMENT)) + { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + arg[argIndex] = atoi(chTemp); + + argIndex++; + + + + } + if (xmlTemp) + xmlFree(xmlTemp); + if (chTemp) + free(chTemp); + + } + cur = cur->next; + } +} + +static void ParseKeys( xmlDocPtr doc, xmlNodePtr cur, void *port ) +{ + while( cur != NULL ) + { + if(!xmlStrcmp( cur->name, (const xmlChar*) "KEYFRAMES" )) + { + keyframe_xml_unpack( doc, cur->xmlChildrenNode, port ); + } + cur = cur->next; + } +} + + +/************************************************************************************************* + * + * ParseEffect() + * + * Parse an effect using libxml2 + * + ****************************************************************************************************/ +void ParseEffect(xmlDocPtr doc, xmlNodePtr cur, int dst_sample, int start_at) +{ + xmlChar *xmlTemp = NULL; + unsigned char *chTemp = NULL; + int effect_id = -1; + int arg[SAMPLE_MAX_PARAMETERS]; + int i; + int source_type = 0; + int channel = 0; + int frame_trimmer = 0; + int frame_offset = 0; + int e_flag = 0; + int volume = 0; + int a_flag = 0; + int chain_index = 0; + int kf_status = 0; + xmlNodePtr anim = NULL; + + for (i = 0; i < SAMPLE_MAX_PARAMETERS; i++) { + arg[i] = 0; + } + + if (cur == NULL) + return; + + int k = 0; + + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTID)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + effect_id = atoi(chTemp); + free(chTemp); + k ++; + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTPOS)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + chain_index = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_ARGUMENTS)) { + + ParseArguments(doc, cur->xmlChildrenNode, arg); + } + + if( !xmlStrcmp(cur->name, (const xmlChar*) "ANIM" )) + { + anim = cur->xmlChildrenNode; + } + + + /* add source,channel,trimmer,e_flag */ + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTSOURCE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + source_type = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTCHANNEL)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + channel = ( atoi(chTemp) ) + start_at; + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTTRIMMER)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + frame_trimmer = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTOFFSET)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + frame_offset = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTACTIVE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + e_flag = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + + } + + if (!xmlStrcmp + (cur->name, (const xmlChar *) XMLTAG_EFFECTAUDIOFLAG)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + a_flag = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + + } + + if (!xmlStrcmp + (cur->name, (const xmlChar *) XMLTAG_EFFECTAUDIOVOLUME)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + volume = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if(!xmlStrcmp( cur->name, (const xmlChar*) "kf_status" )) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp) + { kf_status = atoi(chTemp); free(chTemp); } + if(xmlTemp) xmlFree(xmlTemp); + } + // xmlTemp and chTemp should be freed after use + xmlTemp = NULL; + chTemp = NULL; + cur = cur->next; + } + + + if (effect_id != -1) { + int j; + if (sample_chain_add(dst_sample, chain_index, effect_id) == -1) { + veejay_msg(VEEJAY_MSG_ERROR, "Error parsing effect %d (pos %d)\n", + effect_id, chain_index); + } + + /* load the parameter values */ + for (j = 0; j < vj_effect_get_num_params(effect_id); j++) { + sample_set_effect_arg(dst_sample, chain_index, j, arg[j]); + } + sample_set_chain_channel(dst_sample, chain_index, channel); + sample_set_chain_source(dst_sample, chain_index, source_type); + + /* set other parameters */ + if (a_flag) { + sample_set_chain_audio(dst_sample, chain_index, a_flag); + sample_set_chain_volume(dst_sample, chain_index, volume); + } + + sample_set_chain_status(dst_sample, chain_index, e_flag); + + sample_set_offset(dst_sample, chain_index, frame_offset); + sample_set_trimmer(dst_sample, chain_index, frame_trimmer); + + sample_info *skel = sample_get(dst_sample); + + if(anim) + { + ParseKeys( doc, anim, skel->effect_chain[ chain_index ]->kf ); + sample_chain_set_kf_status( dst_sample, chain_index, kf_status ); + } + } + +} + +/************************************************************************************************* + * + * ParseEffect() + * + * Parse the effects array + * + ****************************************************************************************************/ +void ParseEffects(xmlDocPtr doc, xmlNodePtr cur, sample_info * skel, int start_at) +{ + int effectIndex = 0; + while (cur != NULL && effectIndex < SAMPLE_MAX_EFFECTS) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECT)) { + ParseEffect(doc, cur->xmlChildrenNode, skel->sample_id, start_at); + effectIndex++; + } + //effectIndex++; + cur = cur->next; + } +} +void ParseCalibration( xmlDocPtr doc, xmlNodePtr cur, sample_info *skel , void *vp) +{ + void *tmp = viewport_load_xml( doc, cur, vp ); + if( tmp ) + skel->viewport_config = tmp; +} + +void LoadCurrentPlaying( xmlDocPtr doc, xmlNodePtr cur , int *id, int *mode ) +{ + unsigned char *chTemp = NULL; + unsigned char *xmlTemp = NULL; + while (cur != NULL) + { + if (!xmlStrcmp(cur->name, (const xmlChar *) "PLAYING_ID")) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1 ); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp) { + int s_id = atoi(chTemp ); + *id = s_id; + xmlFree(chTemp); + } + if( xmlTemp ) free(xmlTemp); + } + + if( !xmlStrcmp(cur->name, (const xmlChar*) "PLAYING_MODE" )) + { + xmlTemp = xmlNodeListGetString( doc,cur->xmlChildrenNode,1 ); + chTemp = UTF8toLAT1( xmlTemp ); + if(chTemp ) { + int s_pm = atoi( chTemp ); + *mode = s_pm; + xmlFree(chTemp); + } + if( xmlTemp ) free(xmlTemp); + } + + cur = cur->next; + } + +} + +void LoadSequences( xmlDocPtr doc, xmlNodePtr cur, void *seq ) +{ + seq_t *s = (seq_t*) seq; + + int i; + xmlChar *xmlTemp = NULL; + unsigned char *chTemp = NULL; + + while (cur != NULL) + { + if (!xmlStrcmp(cur->name, (const xmlChar *) "SEQ_ID")) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + int id = atoi( chTemp ); + s->samples[ s->size ] = id; + s->size ++; + free(chTemp); + } + if( xmlTemp ) + xmlFree(xmlTemp); + } + cur = cur->next; + } + +} + +/************************************************************************************************* + * + * ParseSample() + * + * Parse a sample + * + ****************************************************************************************************/ +xmlNodePtr ParseSample(xmlDocPtr doc, xmlNodePtr cur, sample_info * skel,void *el, void *font, int start_at, void *vp ) +{ + + xmlChar *xmlTemp = NULL; + unsigned char *chTemp = NULL; + xmlNodePtr subs = NULL; + int post_check = 0; + + if(!sample_read_edl( skel )) { + veejay_msg(VEEJAY_MSG_WARNING, "No saved edit decision list '%s' for sample %d", skel->edit_list_file, skel->sample_id ); + if( el == NULL || ((editlist*)el)->video_frames <= 2 ) { + veejay_msg(VEEJAY_MSG_WARNING, "Plainmode is dummy !"); + } + veejay_msg(VEEJAY_MSG_WARNING, "Using plainmode to play sample %d", skel->sample_id ); + post_check = 1; + skel->edit_list = NULL; + } + if(!skel->edit_list) + { + skel->edit_list = el; + skel->soft_edl = 1; + } else { + skel->soft_edl = 0; + } + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_SAMPLEID)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + skel->sample_id = ( atoi(chTemp) ) + start_at; + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if( !xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_BOGUSVIDEO ) ) + { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + skel->play_length = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EDIT_LIST_FILE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + skel->edit_list_file = strdup(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_CHAIN_ENABLED)) + { + xmlTemp = xmlNodeListGetString( doc, cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1( xmlTemp ); + if(chTemp) + { + skel->effect_toggle = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_SAMPLEDESCR)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + snprintf(skel->descr, SAMPLE_MAX_DESCR_LEN,"%s", chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_FIRSTFRAME)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_startframe(skel->sample_id, atol(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_VOL)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_audio_volume(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_LASTFRAME)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_endframe(skel->sample_id, atol(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_SPEED)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_speed(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_FRAMEDUP)) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp) + { + sample_set_framedup(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_LOOPTYPE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_looptype(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_MAXLOOPS)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_loops(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_NEXTSAMPLE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_next(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_DEPTH)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_depth(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_PLAYMODE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_playmode(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name,(const xmlChar *) XMLTAG_FADER_ACTIVE)) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp) { + skel->fader_active = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name,(const xmlChar *) XMLTAG_FADER_VAL)) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp){ + skel->fader_val = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name,(const xmlChar*) XMLTAG_FADER_INC)) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp) { + skel->fader_inc = atof(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name,(const xmlChar*) XMLTAG_FADER_DIRECTION)) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp) { + skel->fader_inc = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if(!xmlStrcmp(cur->name,(const xmlChar*) XMLTAG_LASTENTRY)) { + xmlTemp = xmlNodeListGetString(doc,cur->xmlChildrenNode,1); + chTemp = UTF8toLAT1(xmlTemp); + if(chTemp) { + skel->selected_entry = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + /* + if (!xmlStrcmp(cur->name, (const xmlChar *)XMLTAG_VOLUME)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1( xmlTemp ); + if( chTemp ){ + //sample_set_volume(skel->sample_id, atoi(chTemp )); + } + } + if (!xmlStrcmp(cur->name, (const xmlChar *)XMLTAG_SUBAUDIO)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1( xmlTemp ); + if( chTemp ){ + sample_set_sub_audio(skel->sample_id, atoi(chTemp )); + } + } + */ + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_MARKERSTART)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_marker_start(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_MARKEREND)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + sample_set_marker_end(skel->sample_id, atoi(chTemp)); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + + } + + if(!xmlStrcmp(cur->name, (const xmlChar*) "SUBTITLES" )) + { + subs = cur->xmlChildrenNode; + // vj_font_xml_unpack( doc, cur->xmlChildrenNode, font ); + } + + ParseEffects(doc, cur->xmlChildrenNode, skel, start_at); + + if( !xmlStrcmp( cur->name, (const xmlChar*) "calibration" ) ) { + ParseCalibration( doc, cur->xmlChildrenNode, skel ,vp); + } + + + + // xmlTemp and chTemp should be freed after use + xmlTemp = NULL; + chTemp = NULL; + + cur = cur->next; + } + // if(!sample_read_edl( skel )) +// veejay_msg(VEEJAY_MSG_ERROR, "No EDL '%s' for sample %d", skel->edit_list_file, skel->sample_id ); + + + + return subs; +} + + +/**************************************************************************************************** + * + * sample_readFromFile( filename ) + * + * load samples and effect chain from an xml file. + * + ****************************************************************************************************/ +int sample_read_edl( sample_info *sample ) +{ + char *files[1]; + int res = 0; + files[0] = strdup(sample->edit_list_file); + if(sample->edit_list) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cleanup old editlist"); + vj_el_free(sample->edit_list); + } + sample->edit_list = vj_el_init_with_args( files,1, + __sample_project_settings.flags, + __sample_project_settings.deinterlace, + __sample_project_settings.force, + __sample_project_settings.norm, + __sample_project_settings.fmt ); + + if(sample->edit_list) + { + res = 1; + sample->soft_edl = 0; + } + if(files[0]) + free(files[0]); + + + return res; +} + +int is_samplelist(char *filename) +{ + xmlDocPtr doc; + xmlNodePtr cur; + doc = xmlParseFile(filename); + if (doc == NULL) + return (0); + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) + { + xmlFreeDoc(doc); + return (0); + } + + if (xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_SAMPLES)) + { + xmlFreeDoc(doc); + return (0); + } + + xmlFreeDoc(doc); + + return 1; +} + +void LoadSubtitles( sample_info *skel, char *file, void *font ) +{ + char tmp[512]; + float fps = 25.0; + + sprintf(tmp, "%s-SUB-%d.srt", file,skel->sample_id ); +#ifdef STRICT_CHECKING + assert( skel->dict != NULL ); +#endif + vj_font_load_srt( font, tmp ); +} + +int sample_readFromFile(char *sampleFile, void *vp, void *seq, void *font, void *el,int *id, int *mode) +{ + xmlDocPtr doc; + xmlNodePtr cur; + sample_info *skel; + + /* + * build an XML tree from a the file; + */ + doc = xmlParseFile(sampleFile); + if (doc == NULL) { + return (0); + } + + /* + * Check the document is of the right kind + */ + + int start_at = sample_size()-1; + if( start_at != 0 ) + veejay_msg(VEEJAY_MSG_INFO, "Merging %s into current samplelist, auto number starts at %d", sampleFile, start_at ); + if( vj_tag_size()-1 > 0 ) + veejay_msg(VEEJAY_MSG_INFO, "Existing streams will be deleted (samplelist overrides active streams)"); + + cur = xmlDocGetRootElement(doc); + if (cur == NULL) { + veejay_msg(VEEJAY_MSG_ERROR,"Empty samplelist. Nothing to do.\n"); + xmlFreeDoc(doc); + return (0); + } + + if (xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_SAMPLES)) { + veejay_msg(VEEJAY_MSG_ERROR, "This is not a samplelist: %s", + XMLTAG_SAMPLES); + xmlFreeDoc(doc); + return (0); + } + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_SAMPLE)) { + skel = sample_skeleton_new(0, 1); + sample_store(skel); + if (skel != NULL) { + void *d = vj_font_get_dict(font); + + xmlNodePtr subs = ParseSample( doc, cur->xmlChildrenNode, skel, el, font, start_at ,vp ); + if(subs) + { + LoadSubtitles( skel, sampleFile, font ); + vj_font_xml_unpack( doc, subs, font ); + } + + vj_font_set_dict(font,d); + + } + } + if( !xmlStrcmp( cur->name, (const xmlChar*) "CURRENT" )) { + LoadCurrentPlaying( doc, cur->xmlChildrenNode, id, mode ); + } + + if( !xmlStrcmp( cur->name, (const xmlChar *) "SEQUENCE" )) { + LoadSequences( doc, cur->xmlChildrenNode,seq ); + } + + if( !xmlStrcmp( cur->name, (const xmlChar*) "stream" )) { + tagParseStreamFX( sampleFile, doc, cur->xmlChildrenNode, font,vp ); + } + + cur = cur->next; + } + xmlFreeDoc(doc); + + return (1); +} + +void CreateArguments(xmlNodePtr node, int *arg, int argcount) +{ + int i; + char buffer[100]; + for (i = 0; i < argcount; i++) { + sprintf(buffer, "%d", arg[i]); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_ARGUMENT, + (const xmlChar *) buffer); + } +} + +void CreateKeys( xmlNodePtr node, int argcount, void *port ) +{ + int i; + for( i = 0; i < argcount ; i++ ) + { + xmlNodePtr childnode = xmlNewChild(node, NULL, (const xmlChar*) "KEYFRAMES", NULL); + keyframe_xml_pack( childnode, port, i ); + } +} + +void CreateEffect(xmlNodePtr node, sample_eff_chain * effect, int position) +{ + char buffer[100]; + xmlNodePtr childnode; + + sprintf(buffer, "%d", position); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTPOS, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->effect_id); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTID, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->e_flag); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTACTIVE, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->source_type); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTSOURCE, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->channel); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTCHANNEL, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->frame_offset); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTOFFSET, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->frame_trimmer); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTTRIMMER, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->a_flag); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTAUDIOFLAG, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->volume); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTAUDIOVOLUME, + (const xmlChar *) buffer); + + + sprintf(buffer, "%d", effect->kf_status ); + xmlNewChild(node,NULL,(const xmlChar*) "kf_status", (const xmlChar*) buffer ); + + + childnode = + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_ARGUMENTS, NULL); + CreateArguments(childnode, effect->arg, + vj_effect_get_num_params(effect->effect_id)); + + + childnode = + xmlNewChild(node,NULL,(const xmlChar*) "ANIM", NULL ); + CreateKeys( childnode, vj_effect_get_num_params(effect->effect_id), effect->kf ); + +} + + +void CreateEffects(xmlNodePtr node, sample_eff_chain ** effects) +{ + int i; + xmlNodePtr childnode; + + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) { + if (effects[i]->effect_id != -1) { + childnode = + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECT, + NULL); + CreateEffect(childnode, effects[i], i); + } + } + +} + +void SaveSequences( xmlNodePtr node, void *seq ) +{ + char buffer[100]; + int i = 0; + seq_t *s = (seq_t*) seq; + for( i = 0; i < MAX_SEQUENCES; i ++ ) + { + sprintf(buffer, "%d", s->samples[i] ); + xmlNewChild(node, NULL, (const xmlChar*) "SEQ_ID", + (const xmlChar*) buffer ); + } + +} + +void SaveCurrentPlaying( xmlNodePtr node, int id, int mode ) +{ + char buffer[100]; + sprintf(buffer, "%d", id ); + xmlNewChild(node, NULL, (const xmlChar*) "PLAYING_ID", + (const xmlChar*) buffer ); + sprintf(buffer, "%d", mode ); + xmlNewChild(node,NULL, (const xmlChar*) "PLAYING_MODE", + (const xmlChar*) buffer ); + +} + +void CreateSample(xmlNodePtr node, sample_info * sample, void *font) +{ + char buffer[100]; + xmlNodePtr childnode; + + sprintf(buffer, "%d", sample->sample_id); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_SAMPLEID, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->effect_toggle); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_CHAIN_ENABLED, + (const xmlChar *) buffer); + + if(sample->edit_list_file) + { + sprintf(buffer, "%s", sample->edit_list_file); + xmlNewChild(node, NULL, (const xmlChar*) XMLTAG_EDIT_LIST_FILE, + (const xmlChar*) buffer ); + } + + sprintf(buffer, "%s", sample->descr); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_SAMPLEDESCR, + (const xmlChar *) buffer); + sprintf(buffer, "%ld", sample->first_frame); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_FIRSTFRAME, + (const xmlChar *) buffer); + sprintf(buffer, "%ld", sample->last_frame); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_LASTFRAME, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", sample->play_length ); + xmlNewChild(node, NULL, (const xmlChar*) XMLTAG_BOGUSVIDEO, + (const xmlChar*) buffer ); + sprintf(buffer, "%d", sample->speed); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_SPEED, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->dup); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_FRAMEDUP, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->looptype); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_LOOPTYPE, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->max_loops); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_MAXLOOPS, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->next_sample_id); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_NEXTSAMPLE, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->depth); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_DEPTH, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->playmode); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_PLAYMODE, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->audio_volume); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_VOL, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->marker_start); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_MARKERSTART, + (const xmlChar *) buffer); + sprintf(buffer, "%d", sample->marker_end); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_MARKEREND, + (const xmlChar *) buffer); + + sprintf(buffer,"%d",sample->fader_active); + xmlNewChild(node,NULL,(const xmlChar *) XMLTAG_FADER_ACTIVE, + (const xmlChar *) buffer); + sprintf(buffer,"%f",sample->fader_inc); + xmlNewChild(node,NULL,(const xmlChar *) XMLTAG_FADER_INC, + (const xmlChar *) buffer); + sprintf(buffer,"%f",sample->fader_val); + xmlNewChild(node,NULL,(const xmlChar *) XMLTAG_FADER_VAL, + (const xmlChar *) buffer); + sprintf(buffer,"%d",sample->fader_direction); + xmlNewChild(node,NULL,(const xmlChar *) XMLTAG_FADER_DIRECTION, + (const xmlChar *) buffer); + sprintf(buffer,"%d",sample->selected_entry); + xmlNewChild(node,NULL,(const xmlChar *) XMLTAG_LASTENTRY, + (const xmlChar *)buffer); + + vj_font_xml_pack( node, font ); + + + childnode = + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTS, NULL); + + CreateEffects(childnode, sample->effect_chain); + +} + +/**************************************************************************************************** + * + * sample_writeToFile( filename ) + * + * writes all sample info to a file. + * + ****************************************************************************************************/ +static int sample_write_edl(sample_info *sample) +{ + editlist *edl = sample->edit_list; + if(edl) + { + if(vj_el_write_editlist( sample->edit_list_file, + sample->first_frame, + sample->last_frame, + edl )) + veejay_msg(VEEJAY_MSG_DEBUG, "Saved EDL '%s' of sample %d", + sample->edit_list_file, sample->sample_id ); + return 1; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample %d has no EDL", sample->sample_id ); + } + return 0; +} + +void WriteSubtitles( sample_info *next_sample, void *font, char *file ) +{ + char tmp[512]; + + void *d = vj_font_get_dict( font ); + + sprintf(tmp, "%s-SUB-%d.srt", file,next_sample->sample_id ); + + vj_font_set_dict( font, next_sample->dict ); + + vj_font_save_srt( font, tmp ); + + vj_font_set_dict( font, d ); +} + +void sample_reload_config(void *compiz, int s1, int mode ) +{ + sample_info *sample = sample_get(s1); + if(sample) { + if(sample->viewport_config) { + free(sample->viewport_config); + sample->viewport_config = NULL; + } + if(!sample->viewport_config) { + veejay_msg(VEEJAY_MSG_DEBUG, "Calibrated sample %d",s1); + sample->viewport_config = composite_get_config(compiz,mode); + } + sample->composite = mode; + sample_update(sample,s1); + } +} + +int sample_writeToFile(char *sampleFile, void *vp,void *seq, void *font, int id, int mode) +{ + int i; + char *encoding = "UTF-8"; + sample_info *next_sample; + xmlDocPtr doc; + xmlNodePtr rootnode, childnode; + + doc = xmlNewDoc("1.0"); + rootnode = + xmlNewDocNode(doc, NULL, (const xmlChar *) XMLTAG_SAMPLES, NULL); + xmlDocSetRootElement(doc, rootnode); + + childnode = xmlNewChild( rootnode, NULL, + (const xmlChar*) "SEQUENCE", NULL ); + SaveSequences( childnode, seq ); + + + childnode = xmlNewChild( rootnode, NULL, (const xmlChar*) "CURRENT" , NULL ); + + SaveCurrentPlaying( childnode , id, mode ); + + for (i = 1; i < sample_size(); i++) { + next_sample = sample_get(i); + if (next_sample) { + if(sample_write_edl( next_sample )) + veejay_msg(VEEJAY_MSG_DEBUG ,"Saved sample %d EDL '%s'", next_sample->sample_id, + next_sample->edit_list_file ); + + childnode = + xmlNewChild(rootnode, NULL, + (const xmlChar *) XMLTAG_SAMPLE, NULL); + + WriteSubtitles( next_sample,font, sampleFile ); + + CreateSample(childnode, next_sample, font); + + viewport_save_xml( childnode, next_sample->viewport_config ); + } + } + + int max = vj_tag_size()-1; + i = 0; + for( i = 1; i <= max; i ++ ) + { + childnode = xmlNewChild(rootnode,NULL,(const xmlChar*) "stream", NULL ); + tag_writeStream( sampleFile, i, childnode, font ,vp); + } + + xmlSaveFormatFileEnc( sampleFile, doc, encoding, 1 ); + xmlFreeDoc(doc); + + return 1; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/libsample/sampleadm.h b/branches/V-1.5.3/veejay-server/libsample/sampleadm.h new file mode 100644 index 00000000..149e6677 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libsample/sampleadm.h @@ -0,0 +1,372 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg < nelburg@sourceforge.net> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SAMPLEADM_H +#define SAMPLEADM_H +#include +#include +#include +#include +#include +#ifdef HAVE_XML2 +#include +#include +#endif +#define SAMPLE_MAX_SAMPLES 16384 /* 4096 samples at most */ + +#define SAMPLE_MAX_PARAMETERS 10 /* 10 parameters per effect at most */ +#define SAMPLE_ARG1 0 +#define SAMPLE_ARG2 1 +#define SAMPLE_ARG3 2 +#define SAMPLE_ARG4 3 +#define SAMPLE_ARG5 4 +#define SAMPLE_ARG6 5 +#define SAMPLE_ARG7 6 +#define SAMPLE_ARG8 7 +#define SAMPLE_ARG9 8 +#define SAMPLE_ARG10 9 +#ifdef HAVE_XML2 +#define XMLTAG_RENDER_ENTRY "render_entry" +#define XMLTAG_SAMPLES "veejay_samples" +#define XMLTAG_SAMPLE "sample" +#define XMLTAG_SAMPLEID "sampleid" +#define XMLTAG_SAMPLEDESCR "description" +#define XMLTAG_FIRSTFRAME "startframe" +#define XMLTAG_LASTFRAME "endframe" +#define XMLTAG_EFFECTS "effects" +#define XMLTAG_VOL "volume" +#define XMLTAG_EFFECT "effect" +#define XMLTAG_EFFECTID "effectid" +#define XMLTAG_ARGUMENTS "arguments" +#define XMLTAG_ARGUMENT "argument" +#define XMLTAG_EFFECTSOURCE "source" +#define XMLTAG_EFFECTCHANNEL "channel" +#define XMLTAG_EFFECTTRIMMER "trimmer" +#define XMLTAG_EFFECTOFFSET "offset" +#define XMLTAG_EFFECTACTIVE "active" +#define XMLTAG_EFFECTAUDIOFLAG "use_audio" +#define XMLTAG_EFFECTAUDIOVOLUME "chain_volume" +#define XMLTAG_SPEED "speed" +#define XMLTAG_FRAMEDUP "frameduplicator" +#define XMLTAG_LOOPTYPE "looptype" +#define XMLTAG_MAXLOOPS "maxloops" +#define XMLTAG_NEXTSAMPLE "nextsample" +#define XMLTAG_DEPTH "depth" +#define XMLTAG_PLAYMODE "playmode" +#define XMLTAG_VOLUME "volume" +#define XMLTAG_SUBAUDIO "subaudio" +#define XMLTAG_MARKERSTART "markerstart" +#define XMLTAG_MARKEREND "markerend" +#define XMLTAG_EFFECTPOS "position" +#define XMLTAG_FADER_ACTIVE "chain_fade" +#define XMLTAG_FADER_VAL "chain_fade_value" +#define XMLTAG_FADER_INC "chain_fade_increment" +#define XMLTAG_FADER_DIRECTION "chain_direction" +#define XMLTAG_LASTENTRY "current_entry" +#define XMLTAG_CHAIN_ENABLED "fx" +#define XMLTAG_EDIT_LIST_FILE "editlist_filename" +#define XMLTAG_BOGUSVIDEO "playlength" +#endif +#define SAMPLE_FREEZE_NONE 0 +#define SAMPLE_FREEZE_PAUSE 1 +#define SAMPLE_FREEZE_BLACK 2 + +#define SAMPLE_RENDER_START 1 +#define SAMPLE_RENDER_STOP 0 + +#define SAMPLE_MAX_DESCR_LEN 150 + +enum { + SAMPLE_LOAD = 0, + SAMPLE_RUN = 1, + SAMPLE_PEEK = 2, +}; + + + +typedef struct sample_eff_t { + int effect_id; /* effect ID */ + int e_flag; + + int arg[SAMPLE_MAX_PARAMETERS]; /* array of arguments */ + int frame_offset; + int frame_trimmer; /* sub frame scratcher */ + /* audio settings */ + int a_flag; /* audio enabled/disabled */ + int volume; /* volume of 0-100 of audio */ + int source_type; /* source type to mix with */ + int channel; /* secundary source id */ + int is_rendering; /* is rendering */ + void *kf; /* keyframe values for this entry */ + int kf_status; /* use keyframed values */ +} sample_eff_chain; + + +typedef struct sample_info_t { + int sample_id; /* identifies a unique sample */ + sample_eff_chain *effect_chain[SAMPLE_MAX_EFFECTS]; /* effect chain */ + long first_frame; /* start of sample */ + long last_frame; /* end of sample */ + char descr[SAMPLE_MAX_DESCR_LEN]; + int speed; /* playback speed */ + int looptype; /* pingpong or loop */ + int max_loops; /* max looops before going to */ + int max_loops2; /* count remaining loops */ + int next_sample_id; /* the next sample */ + int depth; /* sample effect chain render depth */ + int source; /* source or tag */ + int channel; /* which channel (which tag) */ + int playmode; /* various playmodes */ + int playmode_frame; + int sub_audio; /* mix underlying sample yes or no */ + int audio_volume; /* volume setting of this sample */ + int marker_start; + int marker_end; + int dup; /* frame duplicator */ + int dups; + int loop_dec; + int loop_periods; + int marker_speed; + int fader_active; + int fader_direction; + float fader_val; + float fader_inc; + int encoder_active; + unsigned long sequence_num; + unsigned long rec_total_bytes; + char *encoder_base; + unsigned long encoder_total_frames; + char *encoder_destination; + int encoder_format; + void *encoder; +// lav_file_t *encoder_file; + void *encoder_file; + long encoder_duration; /* in seconds */ + long encoder_num_frames; + long encoder_succes_frames; + int encoder_width; + int encoder_height; + int encoder_max_size; + int auto_switch; + int selected_entry; + int effect_toggle; + int offset; + int play_length; + int loopcount; + editlist *edit_list; + char *edit_list_file; + int soft_edl; + void *dict; + void *kf; + int composite; + void *viewport_config; + void *viewport; +} sample_info; + +#define SAMPLE_YUV420_BUFSIZE 16 +#define SAMPLE_MAX_DEPTH 4 +#define SAMPLE_DEC_BIBBER 1 +#define SAMPLE_DEC_FREEZE 2 +extern int sample_chain_malloc(int sample_id); +extern int sample_chain_free(int sample_id); +extern int sample_size(); +extern int sample_verify(); +extern void sample_init(int len, void *font); +extern int sample_update(sample_info *sample, int s1); +#ifdef HAVE_XML2 +extern int sample_readFromFile(char *, void *vp, void *ptr, void *font, void *el, int *id, int *mode); +extern int sample_writeToFile(char *, void *vp, void *ptr, void *font, int id, int mode); +#endif +extern int sample_update_offset(int s1, int nframe); +extern int sample_set_state(int new_state); +extern int sample_get_state(); +extern sample_info *sample_skeleton_new(long startFrame, long endFrame); +extern sample_info *sample_get(int sample_id); +extern int sample_store(sample_info * skel); +extern int sample_is_deleted(int s1); +extern int sample_exists(int sample_id); +extern int sample_verify_delete( int sample_id, int sample_type ); +extern int sample_del(int sample_id); +extern void sample_del_all(); +extern int sample_get_startFrame(int sample_id); +extern int sample_get_endFrame(int sample_id); +extern int sample_set_marker_start(int sample_id, int marker); +extern int sample_set_marker_end(int sample_id, int marker); +extern int sample_set_startframe(int s1, long frame_num); +extern int sample_set_endframe(int s1, long frame_num); +extern int sample_set_marker(int s1, int start, int end); +extern int sample_get_longest(int sample_id); +extern int sample_get_playmode(int s1); +extern int sample_set_playmode(int s1, int playmode); +extern int sample_get_loops(int s1); +extern int sample_get_loops2(int s1); +extern int sample_get_next(int s1); +extern int sample_get_depth(int s1); +extern int sample_set_depth(int s1, int n); +extern int sample_set_speed(int s1, int speed); +extern void sample_loopcount(int s1); +extern void sample_reset_loopcount(int s1); +extern int sample_get_loopcount(int s1); +extern int sample_set_composite(void *compiz,int s1, int composite); +extern int sample_get_composite(int s1); +extern int sample_set_framedup(int s1, int n); +extern int sample_get_framedup(int s1); +extern int sample_set_framedups(int s1, int n); +extern int sample_get_framedups(int s1); +extern int sample_marker_clear(int sample_id); +extern int sample_set_looptype(int s1, int looptype); +extern int sample_get_speed(int s1); +extern int sample_get_looptype(int s1); +extern int sample_set_loops(int s1, int nr_of_loops); +extern int sample_set_loops2(int s1, int nr); +extern int sample_set_next(int s1, int next_sample_id); +extern int sample_get_chain_source(int sample_id, int position); +extern int sample_set_chain_source(int sample_id, int position, int source); +extern int sample_get_sub_audio(int s1); +void *sample_get_kf_port( int s1, int entry ); +extern int sample_chain_set_kf_status( int s1, int entry, int status ); +extern int sample_get_kf_status( int s1, int entry ); +extern unsigned char * sample_chain_get_kfs( int s1, int entry, int parameter_id, int *len ); +extern int sample_chain_set_kf_status( int s1, int entry, int status ); +extern int sample_chain_set_kfs( int s1, int len, unsigned char *data ); +extern int sample_chain_reset_kf( int s1, int entry ); +extern int sample_has_cali_fx(int sample_id); +extern void sample_cali_prepare( int sample_id, int slot, int chan ); +extern int sample_set_sub_audio(int s1, int audio); +extern int sample_get_audio_volume(int s1); +extern int sample_set_audio_volume(int s1, int volume); +extern int sample_copy(int s1); +extern int sample_get_effect(int s1, int position); +/* get effect any, even if effect is disabled (required for informational purposes)*/ +extern int sample_get_effect_any(int s1, int position); +extern int sample_get_offset(int s1, int position); +extern int sample_get_first_mix_offset(int s1, int *parent, int look_for ); +/* trimmer is usefull for underlying samples in the effect chain. + you can manual adjust the video/audio sync of the underlying sample */ +extern int sample_get_trimmer(int s1, int position); +extern int sample_set_trimmer(int s1, int position, int trimmer); +extern int sample_get_short_info(int sample_id, int *, int *, int *, int *) ; +extern int sample_get_chain_volume(int s1, int position); + +/* set volume of audio data coming to the chain */ +extern int sample_set_chain_volume(int s1, int position, int volume); + +/* whether to mix underlying sample's audio */ +extern int sample_get_chain_audio(int s1, int position); +extern int sample_has_extra_frame(int s1, int position); +/* mix the audio from entry from the effect chain, if any */ +extern int sample_set_chain_audio(int s1, int position, int flag); + +extern int sample_set_chain_status(int s1, int position, int status); +extern int sample_get_chain_status(int s1, int position); + +extern int sample_set_offset(int s1, int position, int frame_offset); +extern int sample_get_effect_arg(int s1, int position, int argnr); +extern int sample_set_effect_arg(int s1, int position, int argnr, int value); + +extern int sample_get_all_effect_arg(int s1, int position, int *args, + int arg_len, int n_elapsed); +extern int sample_chain_remove(int s1, int position); +extern int sample_chain_clear(int s1); +extern int sample_chain_size(int s1); +extern int sample_chain_get_free_entry(int s1); +extern int sample_chain_add(int s1, int c, int effect_nr); + +/* channel depends on source , it select a channel of a certain video source */ +extern int sample_get_chain_channel(int s1, int position); +extern int sample_set_chain_channel(int s1, int position, int channel); + +//int sample_chain_replace(int s1, int position, int effect_id); + +extern int sample_chain_sprint_status(int s1,int cache,int sa,int ca, int r, int f, int m, int t,int sr,int curfps,uint32_t lo, uint32_t hi, int macro,char *s ); + +extern int sample_set_render_entry(int s1, int entry); +extern int sample_get_render_entry(int s1); + +extern int sample_set_description(int sample_id, char *description); +extern int sample_get_description(int sample_id, char *description); + +extern int sample_entry_is_rendering(int sample_id, int entry); +extern int sample_entry_set_is_rendering(int sample_id, int entry, int value); +extern int sample_get_loop_dec(int s1); +extern int sample_set_loop_dec(int s1, int active); +extern int sample_apply_loop_dec(int s1, double fps); + +extern int sample_set_manual_fader(int s1, int value ); +extern int sample_apply_fader_inc(int s1); +extern int sample_set_fader_active(int s1, int nframes, int direction); +extern int sample_set_fader_val(int s1, float val); +extern int sample_get_fader_active(int s1); +extern float sample_get_fader_val(int s1); +extern float sample_get_fader_inc(int s1); +extern int sample_get_fader_direction(int s1); +extern int sample_reset_fader(int t1); + +extern int sample_reset_offset(int s1); + +extern int sample_get_effect_status(int s1); +extern int sample_get_selected_entry(int s1); + +extern int sample_set_effect_status(int s1, int status); +extern int sample_set_selected_entry(int s1, int position); + +extern int sample_set_editlist( int s1, editlist *edl ); +extern editlist *sample_get_editlist(int s1 ); +extern int sample_get_el_position( int sample_id, int *start, int *end ); + +extern void *sample_get_dict( int sample_id ); + +extern int sample_var( int s1, int *type, int *fader, int *fx, int *rec, int *active ); + +extern void sample_set_project(int fmt, int deinterlace, int flags, int force, char norm ); + +extern int sample_video_length( int s1 ); +extern int sample_usable_edl( int s1 ); + +extern int sample_cache_used( int s1 ); +extern void sample_free(); + +extern int sample_stop_playing(int s1, int new_s1); +extern int sample_start_playing(int s1, int no_cache); +extern int sample_get_kf_tokens( int s1, int entry, int id, int *start,int *end, int *type); +extern unsigned char *UTF8toLAT1(unsigned char *in); +extern int sample_read_edl( sample_info *sample ); + +extern int sample_max_video_length(int s1); + +extern int sample_set_composite_view(int s1, void *vp ); +extern void *sample_get_composite_view(int s1); + +#ifdef HAVE_XML2 +extern void CreateSample(xmlNodePtr node, sample_info * sample, void *font); +extern void CreateEffects(xmlNodePtr node, sample_eff_chain ** effects); +extern void CreateEffect(xmlNodePtr node, sample_eff_chain * effect, int pos); +extern void CreateArguments(xmlNodePtr node, int *arg, int argcount); +extern void CreateKeys(xmlNodePtr node, int argcount, void *port ); +extern xmlNodePtr ParseSample(xmlDocPtr doc, xmlNodePtr cur, sample_info * skel, void *el, void *font, int start_at, void *vp); +extern void ParseEffects(xmlDocPtr doc, xmlNodePtr cur, sample_info * skel, int start_at); +extern void ParseEffect(xmlDocPtr doc, xmlNodePtr cur, int dst_sample, int start_at); +extern void ParseArguments(xmlDocPtr doc, xmlNodePtr cur, int *arg ); +extern void ParseKEys(xmlDocPtr doc, xmlNodePtr cur, void *port); +extern unsigned char *UTF8toLAT1(unsigned char *in); +#endif +void sample_reload_config(void *compiz, int s1, int mode ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libsamplerec/Makefile.am b/branches/V-1.5.3/veejay-server/libsamplerec/Makefile.am new file mode 100644 index 00000000..4d772c80 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libsamplerec/Makefile.am @@ -0,0 +1,13 @@ +# Makefile for veejay + +INCLUDES = -I$(top_srcdir) -I$(includedir)\ + -I$(top_srcdir)/vjmem\ + -I$(top_srcdir)/vjmsg \ + -I$(top_srcdir)/libel \ + -I$(top_srcdir)/mjpegtools \ + $(XML2_CFLAGS) +AM_CFLAGS=$(OP_CFLAGS) +SAMPLEREC_LIB_FILE = libsamplerec.la +noinst_LTLIBRARIES = $(SAMPLEREC_LIB_FILE) +libsamplerec_la_SOURCES = samplerecord.c +EXTRA_DIST = samplerecord.h diff --git a/branches/V-1.5.3/veejay-server/libsamplerec/samplerecord.c b/branches/V-1.5.3/veejay-server/libsamplerec/samplerecord.c new file mode 100644 index 00000000..298ebd88 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libsamplerec/samplerecord.c @@ -0,0 +1,438 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +void sample_reset_encoder(int sample_id); +extern int sufficient_space(int max_size, int nframes); + + +int sample_record_init(int len) +{ + if(len <= 0) return 0; + return 1; +} + +void sample_record_free() +{ +} + +int sample_get_encoded_file(int sample_id, char *description) +{ + sample_info *si; + si = sample_get(sample_id); + if (!si) + return -1; + sprintf(description, "%s", si->encoder_destination ); + return 1; +} + +int sample_get_num_encoded_files(int sample_id) +{ + sample_info *si; + si = sample_get(sample_id); + if(!si) return -1; + return si->sequence_num; +} + +int sample_get_sequenced_file(int sample_id, char *descr, int num, char *ext) +{ + sample_info *si; + si = sample_get(sample_id); + if (!si) + return -1; + + + + sprintf(descr, "%s-%05d.%s", si->encoder_destination, + num, ext); + return 1; + +} + +int sample_get_encoder_format(int sample_id) +{ + sample_info *si; + si = sample_get(sample_id); + if(!si) return -1; + return si->encoder_format; +} + +int sample_try_filename(int sample_id, char *filename, int format) +{ + sample_info *si= sample_get(sample_id); + if(!si) return 0; + + if( filename == NULL ) + snprintf(si->encoder_base, 255, "Sample_%04d", sample_id); + else + snprintf(si->encoder_base,255,"%s",filename); + + + int i = 0; + int len = strlen(si->encoder_base); + for(i=0; i encoder_base[i] == 0x20 ) + si->encoder_base[i] = '_'; + } + + sprintf(si->encoder_destination, "%s-%05ld.avi", + si->encoder_base,si->sequence_num); + + char ext[5]; + switch(format) + { + case ENCODER_DVVIDEO: + sprintf(ext,"dv"); + break; + case ENCODER_YUV4MPEG: + sprintf(ext,"yuv"); + break; + case ENCODER_QUICKTIME_MJPEG: + case ENCODER_QUICKTIME_DV: + sprintf(ext,"mov"); + break; + default: + sprintf(ext,"avi"); + break; + } + sprintf(si->encoder_destination, "%s.%s", si->encoder_base , ext); + + veejay_msg(VEEJAY_MSG_INFO, "Recording to [%s]", si->encoder_destination); + return (sample_update(si,sample_id)); +} + + +static int sample_start_encoder(sample_info *si, editlist *el, int format, long nframes) +{ + char descr[100]; + char cformat = vj_avcodec_find_lav( format ); + + if( cformat == '\0' ) + return -1; + + int sample_id = si->sample_id; + + si->encoder = vj_avcodec_start( el, format, si->encoder_destination ); + if(!si->encoder) + return -1; + + + si->encoder_active = 1; + si->encoder_format = format; + + if(si->encoder_total_frames == 0) + { + si->encoder_duration = nframes; + si->encoder_num_frames = 0; + } + else + { + si->encoder_duration = si->encoder_duration - si->encoder_num_frames; + } + + + si->rec_total_bytes= 0; + si->encoder_succes_frames = 0; + + int tmp = el->video_width * el->video_height; + + if(format==ENCODER_DVVIDEO) + si->encoder_max_size = ( el->video_height == 480 ? 120000: 144000); + else + switch(format) + { + case ENCODER_YUV420: + case ENCODER_YUV420F: + si->encoder_max_size= 2048 + tmp + (tmp/4) + (tmp/4);break; + case ENCODER_YUV422: + case ENCODER_YUV422F: + case ENCODER_YUV4MPEG: + si->encoder_max_size = 2048 + tmp + (tmp/2) + (tmp/2);break; + case ENCODER_LZO: + si->encoder_max_size = (tmp * 3 ); break; + default: + si->encoder_max_size = ( 8 * 65535 ); + break; + } + + si->encoder_width = el->video_width; + si->encoder_height = el->video_height; + + + if( sufficient_space( si->encoder_max_size, nframes ) == 0 ) + { + vj_avcodec_close_encoder( si->encoder ); + si->encoder = NULL; + si->encoder_active = 0; + return -1; + } + + if( cformat != 'S' ) { + + si->encoder_file = (void*)lav_open_output_file(si->encoder_destination,cformat, + el->video_width,el->video_height,el->video_inter, + el->video_fps,el->audio_bits, el->audio_chans, el->audio_rate ); + + if(!si->encoder_file) + { + veejay_msg(VEEJAY_MSG_ERROR,"Cannot write to %s (%s)",si->encoder_destination, + lav_strerror()); + vj_avcodec_close_encoder( si->encoder ); + si->encoder = NULL; + return -1; + } + + } + veejay_msg(VEEJAY_MSG_INFO, "Encoding to %s file [%s]", vj_avcodec_get_encoder_name(format), + si->encoder_destination ); + + veejay_msg(VEEJAY_MSG_DEBUG,"\t%dx%d@%2.2f %d/%d/%d %s >%09d< f=%c", + el->video_width, + el->video_height, + (float) el->video_fps, + el->audio_bits, + el->audio_chans, + el->audio_rate, + (el->video_inter == 1 ? "Full frames" : "Interlaced"), + ( si->encoder_duration - si->encoder_total_frames), + cformat ); + + + sample_update(si,sample_id); + return 0; +} + +int sample_init_encoder(int sample_id, char *filename, int format, editlist *el, + long nframes) { + + sample_info *si; + + if(! sample_try_filename( sample_id, filename,format ) ) + { + return -1; + } + + si = sample_get(sample_id); + if(!si) + { + return -1; + } + if(format < 0 || format > NUM_ENCODERS) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid format!"); + return -1; + } + if(nframes <= 0) return -1; + if(!el) return -1; + + if(si->encoder_active) { + veejay_msg(VEEJAY_MSG_ERROR, "Sample is already encoding to [%s]", + si->encoder_destination); + return -1; + } + + if (sample_start_encoder( si , el, format, nframes ) == 0) + { + return 1; + } + + + return -1; +} + +int sample_continue_record( int s1 ) +{ + sample_info *si = sample_get(s1); + if(!si) return -1; + + if( si->rec_total_bytes == 0) return -1; + if(si->encoder_num_frames > si->encoder_duration) + { + veejay_msg(VEEJAY_MSG_WARNING, "Ready recording %d frames", si->encoder_succes_frames); + + si->encoder_total_frames = 0; + sample_update(si,s1); + return 1; + } + + if ( si->rec_total_bytes >= VEEJAY_FILE_LIMIT) + { + veejay_msg(VEEJAY_MSG_WARNING, "Auto splitting files (max filesize is %ld)", VEEJAY_FILE_LIMIT); + si->sequence_num ++; + si->rec_total_bytes = 0; + + printf(" %d %ld %ld (%ld)%ld \n", + (int)si->sequence_num, + si->rec_total_bytes, + si->encoder_num_frames, + si->encoder_total_frames, + si->encoder_duration); + + si->encoder_total_frames = 0; + sample_update(si,s1); + return 2; + } + + + return 0; +} + +int sample_record_frame(int s1, uint8_t *buffer[3], uint8_t *abuff, int audio_size, int pix_fmt) { + sample_info *si = sample_get(s1); + int buf_len = 0; + if(!si) return -1; + + if(!si->encoder_active) + { + return -1; + } + + buf_len = vj_avcodec_encode_frame(si->encoder, si->encoder_total_frames ++, + si->encoder_format, buffer, vj_avcodec_get_buf(si->encoder), si->encoder_max_size, pix_fmt); + + if(buf_len <= 0) + { + + veejay_msg(VEEJAY_MSG_ERROR, "Cannot encode frame"); + return -1; + } + si->rec_total_bytes += buf_len; + + + //@ if writing to AVI/QT + if( si->encoder_file != NULL ) { + + if(lav_write_frame( (lav_file_t*) si->encoder_file,vj_avcodec_get_buf(si->encoder),buf_len,1)) + { + veejay_msg(VEEJAY_MSG_ERROR, "writing frame, giving up: '%s' (%d bytes buffer)", lav_strerror(), + buf_len); + return 1; + } + + if(audio_size > 0) + { + if(lav_write_audio( (lav_file_t*) si->encoder_file, (uint8_t*)abuff, audio_size)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error writing output audio [%s] (%d)",lav_strerror(),audio_size); + } + si->rec_total_bytes += audio_size; + } + } + + //@ otherwise, encoder must be YUV4MPEG + /* write OK */ + si->encoder_succes_frames ++; + si->encoder_num_frames ++; + + sample_update(si,s1); + + return (sample_continue_record(s1)); +} + + + +int sample_stop_encoder(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + if(si->encoder_active) { + if(si->encoder_file) + lav_close((lav_file_t*)si->encoder_file); + if( si->encoder) + vj_avcodec_stop( si->encoder, si->encoder_format ); + + veejay_msg(VEEJAY_MSG_INFO, "Stopped sample encoder [%s]",si->encoder_destination); + si->encoder_active = 0; + si->encoder_file = NULL; + si->encoder = NULL; + sample_update(si,s1); + + //sample_reset_encoder(s1); + return 1; + } + return 0; +} + + +void sample_reset_encoder(int s1) { + sample_info *si = sample_get(s1); + if(!si) return; + /* added sample */ + si->encoder_active = 0; + si->encoder_format = 0; + si->encoder_succes_frames = 0; + si->encoder_num_frames = 0; + si->encoder_width = 0; + si->encoder_height = 0; + si->encoder_max_size = 0; + si->encoder_active = 0; + si->rec_total_bytes = 0; + si->encoder_duration = 0; + si->encoder_file = NULL; + si->encoder = NULL; + + sample_update(si, s1); +} + +int sample_get_encoded_frames(int s1) { + sample_info *si = sample_get(s1); + if(!si) return -1; + //return ( si->encoder_succes_frames ); + return ( si->encoder_total_frames ); +} + + +int sample_get_total_frames( int s1 ) +{ + sample_info *si = sample_get(s1); + if(!si) return -1; + return ( si->encoder_total_frames ); +} + +int sample_reset_autosplit(int s1) +{ + sample_info *si = sample_get(s1); + if(!si) return -1; + bzero( si->encoder_base, 255 ); + bzero( si->encoder_destination , 255 ); + si->encoder_total_frames = 0; + si->sequence_num = 0; + return (sample_update(si,s1)); +} + +int sample_get_frames_left(int s1) +{ + sample_info *si= sample_get(s1); + if(!si) return 0; + return ( si->encoder_duration - si->encoder_total_frames ); +} + +int sample_encoder_active(int s1) +{ + sample_info *si = sample_get(s1); + if(!si)return 0; + return si->encoder_active; +} diff --git a/branches/V-1.5.3/veejay-server/libsamplerec/samplerecord.h b/branches/V-1.5.3/veejay-server/libsamplerec/samplerecord.h new file mode 100644 index 00000000..f9920832 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libsamplerec/samplerecord.h @@ -0,0 +1,41 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#ifndef SAMPLEREC_H +#define SAMPLEREC_H +#include +#include +int sample_record_init(int len); +int sample_init_encoder(int sample_id, char *filename, int format, editlist *el,long nframes); +int sample_record_frame(int s1, uint8_t *buffer[3], uint8_t *abuff, int audio_size, int pixel_format); +int sample_get_encoder_format(int s1); +int sample_stop_encoder(int s1) ; +int sample_get_encoded_frames(int s1); +int sample_get_encoded_file(int s1, char *dst); +int sample_encoder_active(int s1); +void sample_reset_encoder(int s1); +int sample_get_frames_left(int s1); +int sample_reset_autosplit(int s1); +int sample_get_total_frames( int s1 ); +int sample_get_num_encoded_files(int sample_id); +int sample_get_sequenced_file(int sample_id, char *descr, int num, char *ext); +int sample_try_filename(int sample_id, char *filename, int format); +int sample_continue_record( int s1 ); +void sample_record_free(); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libstream/Makefile.am b/branches/V-1.5.3/veejay-server/libstream/Makefile.am new file mode 100644 index 00000000..07faaf0a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/Makefile.am @@ -0,0 +1,16 @@ +# Makefile for veejay +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/vjmem \ + -I$(top_srcdir)/vjmsg \ + -I$(top_srcdir)/libvjnet/ \ + -I$(top_srcdir)/libhash \ + -I$(top_srcdir)/mjpegtools \ + $(XML2_CFLAGS) \ + $(FFMPEG_CFLAGS) $(PTHREAD_CFLAGS) $(UNICAP_CFLAGS) +STREAM_LIB_FILE = libstream.la +noinst_LTLIBRARIES = $(STREAM_LIB_FILE) +libstream_la_SOURCES = frequencies.c v4lutils.c v4lvideo.c vj-unicap.c vj-yuv4mpeg.c vj-net.c vj-dv1394.c vj-vloopback.c vj-tag.c + +EXTRA_DIST = dv1394.h v4lutils.h vj-dv1394.h vj-tag.h vj-vloopback.h \ + frequencies.h v4lvideo.h vj-net.h vj-unicap.h vj-yuv4mpeg.h diff --git a/branches/V-1.5.3/veejay-server/libstream/dv1394.h b/branches/V-1.5.3/veejay-server/libstream/dv1394.h new file mode 100644 index 00000000..f928e4d5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/dv1394.h @@ -0,0 +1,258 @@ +/* + * dv1394.h - DV input/output over IEEE 1394 on OHCI chips + * Copyright (C)2001 Daniel Maas + * receive, proc_fs by Dan Dennedy + * + * based on: + * video1394.h - driver for OHCI 1394 boards + * Copyright (C)1999,2000 Sebastien Rougeaux + * Peter Schlaile + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef _DV_1394_H +#define _DV_1394_H + +#include +#include + +/* This is the public user-space interface. Try not to break it. */ + +#define DV1394_API_VERSION 0x20011127 + +/* ******************** + ** ** + ** DV1394 API ** + ** ** + ******************** + + There are two methods of operating the DV1394 DV output device. + + 1) + + The simplest is an interface based on write(): simply write + full DV frames of data to the device, and they will be transmitted + as quickly as possible. The FD may be set for non-blocking I/O, + in which case you can use select() or poll() to wait for output + buffer space. + + To set the DV output parameters (e.g. whether you want NTSC or PAL + video), use the DV1394_INIT ioctl, passing in the parameters you + want in a struct dv1394_init. + + Example 1: + To play a raw .DV file: cat foo.DV > /dev/dv1394 + (cat will use write() internally) + + Example 2: + static struct dv1394_init init = { + 0x63, (broadcast channel) + 4, (four-frame ringbuffer) + DV1394_NTSC, (send NTSC video) + 0, 0 (default empty packet rate) + } + + ioctl(fd, DV1394_INIT, &init); + + while(1) { + read( , buf, DV1394_NTSC_FRAME_SIZE ); + write( , buf, DV1394_NTSC_FRAME_SIZE ); + } + + 2) + + For more control over buffering, and to avoid unnecessary copies + of the DV data, you can use the more sophisticated the mmap() interface. + First, call the DV1394_INIT ioctl to specify your parameters, + including the number of frames in the ringbuffer. Then, calling mmap() + on the dv1394 device will give you direct access to the ringbuffer + from which the DV card reads your frame data. + + The ringbuffer is simply one large, contiguous region of memory + containing two or more frames of packed DV data. Each frame of DV data + is 120000 bytes (NTSC) or 144000 bytes (PAL). + + Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES + ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl + or select()/poll() to wait until the frames are transmitted. Next, you'll + need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer + frames are clear (ready to be filled with new DV data). Finally, use + DV1394_SUBMIT_FRAMES again to send the new data to the DV output. + + + Example: here is what a four-frame ringbuffer might look like + during DV transmission: + + + frame 0 frame 1 frame 2 frame 3 + + *--------------------------------------* + | CLEAR | DV data | DV data | CLEAR | + *--------------------------------------* + + + transmission goes in this direction --->>> + + + The DV hardware is currently transmitting the data in frame 1. + Once frame 1 is finished, it will automatically transmit frame 2. + (if frame 2 finishes before frame 3 is submitted, the device + will continue to transmit frame 2, and will increase the dropped_frames + counter each time it repeats the transmission). + + + If you called DV1394_GET_STATUS at this instant, you would + receive the following values: + + n_frames = 4 + active_frame = 1 + first_clear_frame = 3 + n_clear_frames = 2 + + At this point, you should write new DV data into frame 3 and optionally + frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that + it may transmit the new frames. + +*/ + + +/* maximum number of frames in the ringbuffer */ +#define DV1394_MAX_FRAMES 32 + +/* number of *full* isochronous packets per DV frame */ +#define DV1394_NTSC_PACKETS_PER_FRAME 250 +#define DV1394_PAL_PACKETS_PER_FRAME 300 + +/* size of one frame's worth of DV data, in bytes */ +#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME) +#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME) + + +enum pal_or_ntsc { + DV1394_NTSC = 0, + DV1394_PAL +}; + + +/* this is the argument to DV1394_INIT */ +struct dv1394_init { + /* DV1394_API_VERSION */ + unsigned int api_version; + + /* isochronous transmission channel to use */ + unsigned int channel; + + /* number of frames in the ringbuffer. Must be at least 2 + and at most DV1394_MAX_FRAMES. */ + unsigned int n_frames; + + /* send/receive PAL or NTSC video format */ + enum pal_or_ntsc format; + + /* the following are used only for transmission */ + + /* set these to zero unless you want a + non-default empty packet rate (see below) */ + unsigned long cip_n; + unsigned long cip_d; + + /* set this to zero unless you want a + non-default SYT cycle offset (default = 3 cycles) */ + unsigned int syt_offset; +}; + +/* Q: What are cip_n and cip_d? */ + +/* + A: DV video streams do not utilize 100% of the potential bandwidth offered + by IEEE 1394 (FireWire). To achieve the correct rate of data transmission, + DV devices must periodically insert empty packets into the 1394 data stream. + Typically there is one empty packet per 14-16 data-carrying packets. + + Some DV devices will accept a wide range of empty packet rates, while others + require a precise rate. If the dv1394 driver produces empty packets at + a rate that your device does not accept, you may see ugly patterns on the + DV output, or even no output at all. + + The default empty packet insertion rate seems to work for many people; if + your DV output is stable, you can simply ignore this discussion. However, + we have exposed the empty packet rate as a parameter to support devices that + do not work with the default rate. + + The decision to insert an empty packet is made with a numerator/denominator + algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D. + You can alter the empty packet rate by passing non-zero values for cip_n + and cip_d to the INIT ioctl. + + */ + +struct dv1394_status { + /* this embedded init struct returns the current dv1394 + parameters in use */ + struct dv1394_init init; + + /* the ringbuffer frame that is currently being + displayed. (-1 if the device is not transmitting anything) */ + int active_frame; + + /* index of the first buffer (ahead of active_frame) that + is ready to be filled with data */ + unsigned int first_clear_frame; + + /* how many buffers, including first_clear_buffer, are + ready to be filled with data */ + unsigned int n_clear_frames; + + /* how many times the DV output has underflowed + since the last call to DV1394_GET_STATUS */ + unsigned int dropped_frames; + + /* N.B. The dropped_frames counter is only a lower bound on the actual + number of dropped frames, with the special case that if dropped_frames + is zero, then it is guaranteed that NO frames have been dropped + since the last call to DV1394_GET_STATUS. + */ +}; + +/* Get the driver ready to transmit video. pass a struct dv1394_init* as + * the parameter (see below), or NULL to get default parameters */ +#define DV1394_INIT _IOW('#', 0x06, struct dv1394_init) + +/* Stop transmitting video and free the ringbuffer */ +#define DV1394_SHUTDOWN _IO ('#', 0x07) + +/* Submit N new frames to be transmitted, where the index of the first new + * frame is first_clear_buffer, and the index of the last new frame is + * (first_clear_buffer + N) % n_frames */ +#define DV1394_SUBMIT_FRAMES _IO ('#', 0x08) + +/* Block until N buffers are clear (pass N as the parameter) Because we + * re-transmit the last frame on underrun, there will at most be n_frames + * - 1 clear frames at any time */ +#define DV1394_WAIT_FRAMES _IO ('#', 0x09) + +/* Capture new frames that have been received, where the index of the + * first new frame is first_clear_buffer, and the index of the last new + * frame is (first_clear_buffer + N) % n_frames */ +#define DV1394_RECEIVE_FRAMES _IO ('#', 0x0a) + +/* Tell card to start receiving DMA */ +#define DV1394_START_RECEIVE _IO ('#', 0x0b) + +/* Pass a struct dv1394_status* as the parameter */ +#define DV1394_GET_STATUS _IOR('#', 0x0c, struct dv1394_status) + +#endif /* _DV_1394_H */ diff --git a/branches/V-1.5.3/veejay-server/libstream/frequencies.c b/branches/V-1.5.3/veejay-server/libstream/frequencies.c new file mode 100644 index 00000000..d3378a46 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/frequencies.c @@ -0,0 +1,1309 @@ +#include +/* +#include +#include +*/ + +#include "frequencies.h" +/* +#include "grab-ng.h" +*/ + +/* --------------------------------------------------------------------- */ + +/* US broadcast */ +static struct CHANLIST ntsc_bcast[] = { + { "2", 55250 }, + { "3", 61250 }, + { "4", 67250 }, + { "5", 77250 }, + { "6", 83250 }, + { "7", 175250 }, + { "8", 181250 }, + { "9", 187250 }, + { "10", 193250 }, + { "11", 199250 }, + { "12", 205250 }, + { "13", 211250 }, + { "14", 471250 }, + { "15", 477250 }, + { "16", 483250 }, + { "17", 489250 }, + { "18", 495250 }, + { "19", 501250 }, + { "20", 507250 }, + { "21", 513250 }, + { "22", 519250 }, + { "23", 525250 }, + { "24", 531250 }, + { "25", 537250 }, + { "26", 543250 }, + { "27", 549250 }, + { "28", 555250 }, + { "29", 561250 }, + { "30", 567250 }, + { "31", 573250 }, + { "32", 579250 }, + { "33", 585250 }, + { "34", 591250 }, + { "35", 597250 }, + { "36", 603250 }, + { "37", 609250 }, + { "38", 615250 }, + { "39", 621250 }, + { "40", 627250 }, + { "41", 633250 }, + { "42", 639250 }, + { "43", 645250 }, + { "44", 651250 }, + { "45", 657250 }, + { "46", 663250 }, + { "47", 669250 }, + { "48", 675250 }, + { "49", 681250 }, + { "50", 687250 }, + { "51", 693250 }, + { "52", 699250 }, + { "53", 705250 }, + { "54", 711250 }, + { "55", 717250 }, + { "56", 723250 }, + { "57", 729250 }, + { "58", 735250 }, + { "59", 741250 }, + { "60", 747250 }, + { "61", 753250 }, + { "62", 759250 }, + { "63", 765250 }, + { "64", 771250 }, + { "65", 777250 }, + { "66", 783250 }, + { "67", 789250 }, + { "68", 795250 }, + { "69", 801250 }, + + { "70", 807250 }, + { "71", 813250 }, + { "72", 819250 }, + { "73", 825250 }, + { "74", 831250 }, + { "75", 837250 }, + { "76", 843250 }, + { "77", 849250 }, + { "78", 855250 }, + { "79", 861250 }, + { "80", 867250 }, + { "81", 873250 }, + { "82", 879250 }, + { "83", 885250 }, +}; + +/* US cable */ +static struct CHANLIST ntsc_cable[] = { + { "1", 73250 }, + { "2", 55250 }, + { "3", 61250 }, + { "4", 67250 }, + { "5", 77250 }, + { "6", 83250 }, + { "7", 175250 }, + { "8", 181250 }, + { "9", 187250 }, + { "10", 193250 }, + { "11", 199250 }, + { "12", 205250 }, + + { "13", 211250 }, + { "14", 121250 }, + { "15", 127250 }, + { "16", 133250 }, + { "17", 139250 }, + { "18", 145250 }, + { "19", 151250 }, + { "20", 157250 }, + + { "21", 163250 }, + { "22", 169250 }, + { "23", 217250 }, + { "24", 223250 }, + { "25", 229250 }, + { "26", 235250 }, + { "27", 241250 }, + { "28", 247250 }, + { "29", 253250 }, + { "30", 259250 }, + { "31", 265250 }, + { "32", 271250 }, + { "33", 277250 }, + { "34", 283250 }, + { "35", 289250 }, + { "36", 295250 }, + { "37", 301250 }, + { "38", 307250 }, + { "39", 313250 }, + { "40", 319250 }, + { "41", 325250 }, + { "42", 331250 }, + { "43", 337250 }, + { "44", 343250 }, + { "45", 349250 }, + { "46", 355250 }, + { "47", 361250 }, + { "48", 367250 }, + { "49", 373250 }, + { "50", 379250 }, + { "51", 385250 }, + { "52", 391250 }, + { "53", 397250 }, + { "54", 403250 }, + { "55", 409250 }, + { "56", 415250 }, + { "57", 421250 }, + { "58", 427250 }, + { "59", 433250 }, + { "60", 439250 }, + { "61", 445250 }, + { "62", 451250 }, + { "63", 457250 }, + { "64", 463250 }, + { "65", 469250 }, + { "66", 475250 }, + { "67", 481250 }, + { "68", 487250 }, + { "69", 493250 }, + + { "70", 499250 }, + { "71", 505250 }, + { "72", 511250 }, + { "73", 517250 }, + { "74", 523250 }, + { "75", 529250 }, + { "76", 535250 }, + { "77", 541250 }, + { "78", 547250 }, + { "79", 553250 }, + { "80", 559250 }, + { "81", 565250 }, + { "82", 571250 }, + { "83", 577250 }, + { "84", 583250 }, + { "85", 589250 }, + { "86", 595250 }, + { "87", 601250 }, + { "88", 607250 }, + { "89", 613250 }, + { "90", 619250 }, + { "91", 625250 }, + { "92", 631250 }, + { "93", 637250 }, + { "94", 643250 }, + { "95", 91250 }, + { "96", 97250 }, + { "97", 103250 }, + { "98", 109250 }, + { "99", 115250 }, + { "100", 649250 }, + { "101", 655250 }, + { "102", 661250 }, + { "103", 667250 }, + { "104", 673250 }, + { "105", 679250 }, + { "106", 685250 }, + { "107", 691250 }, + { "108", 697250 }, + { "109", 703250 }, + { "110", 709250 }, + { "111", 715250 }, + { "112", 721250 }, + { "113", 727250 }, + { "114", 733250 }, + { "115", 739250 }, + { "116", 745250 }, + { "117", 751250 }, + { "118", 757250 }, + { "119", 763250 }, + { "120", 769250 }, + { "121", 775250 }, + { "122", 781250 }, + { "123", 787250 }, + { "124", 793250 }, + { "125", 799250 }, + + { "T7", 8250 }, + { "T8", 14250 }, + { "T9", 20250 }, + { "T10", 26250 }, + { "T11", 32250 }, + { "T12", 38250 }, + { "T13", 44250 }, + { "T14", 50250 } +}; + +/* US HRC */ +static struct CHANLIST ntsc_hrc[] = { + { "1", 72000 }, + { "2", 54000 }, + { "3", 60000 }, + { "4", 66000 }, + { "5", 78000 }, + { "6", 84000 }, + { "7", 174000 }, + { "8", 180000 }, + { "9", 186000 }, + { "10", 192000 }, + { "11", 198000 }, + { "12", 204000 }, + + { "13", 210000 }, + { "14", 120000 }, + { "15", 126000 }, + { "16", 132000 }, + { "17", 138000 }, + { "18", 144000 }, + { "19", 150000 }, + { "20", 156000 }, + + { "21", 162000 }, + { "22", 168000 }, + { "23", 216000 }, + { "24", 222000 }, + { "25", 228000 }, + { "26", 234000 }, + { "27", 240000 }, + { "28", 246000 }, + { "29", 252000 }, + { "30", 258000 }, + { "31", 264000 }, + { "32", 270000 }, + { "33", 276000 }, + { "34", 282000 }, + { "35", 288000 }, + { "36", 294000 }, + { "37", 300000 }, + { "38", 306000 }, + { "39", 312000 }, + { "40", 318000 }, + { "41", 324000 }, + { "42", 330000 }, + { "43", 336000 }, + { "44", 342000 }, + { "45", 348000 }, + { "46", 354000 }, + { "47", 360000 }, + { "48", 366000 }, + { "49", 372000 }, + { "50", 378000 }, + { "51", 384000 }, + { "52", 390000 }, + { "53", 396000 }, + { "54", 402000 }, + { "55", 408000 }, + { "56", 414000 }, + { "57", 420000 }, + { "58", 426000 }, + { "59", 432000 }, + { "60", 438000 }, + { "61", 444000 }, + { "62", 450000 }, + { "63", 456000 }, + { "64", 462000 }, + { "65", 468000 }, + { "66", 474000 }, + { "67", 480000 }, + { "68", 486000 }, + { "69", 492000 }, + + { "70", 498000 }, + { "71", 504000 }, + { "72", 510000 }, + { "73", 516000 }, + { "74", 522000 }, + { "75", 528000 }, + { "76", 534000 }, + { "77", 540000 }, + { "78", 546000 }, + { "79", 552000 }, + { "80", 558000 }, + { "81", 564000 }, + { "82", 570000 }, + { "83", 576000 }, + { "84", 582000 }, + { "85", 588000 }, + { "86", 594000 }, + { "87", 600000 }, + { "88", 606000 }, + { "89", 612000 }, + { "90", 618000 }, + { "91", 624000 }, + { "92", 630000 }, + { "93", 636000 }, + { "94", 642000 }, + { "95", 900000 }, + { "96", 960000 }, + { "97", 102000 }, + { "98", 108000 }, + { "99", 114000 }, + { "100", 648000 }, + { "101", 654000 }, + { "102", 660000 }, + { "103", 666000 }, + { "104", 672000 }, + { "105", 678000 }, + { "106", 684000 }, + { "107", 690000 }, + { "108", 696000 }, + { "109", 702000 }, + { "110", 708000 }, + { "111", 714000 }, + { "112", 720000 }, + { "113", 726000 }, + { "114", 732000 }, + { "115", 738000 }, + { "116", 744000 }, + { "117", 750000 }, + { "118", 756000 }, + { "119", 762000 }, + { "120", 768000 }, + { "121", 774000 }, + { "122", 780000 }, + { "123", 786000 }, + { "124", 792000 }, + { "125", 798000 }, + + { "T7", 7000 }, + { "T8", 13000 }, + { "T9", 19000 }, + { "T10", 25000 }, + { "T11", 31000 }, + { "T12", 37000 }, + { "T13", 43000 }, + { "T14", 49000 }, +}; + +/* --------------------------------------------------------------------- */ + +/* Canada cable */ +static struct CHANLIST ntsc_cable_ca[] = { + { "2", 61750 }, + { "3", 67750 }, + { "4", 73750 }, + { "5", 83750 }, + { "6", 89750 }, + { "7", 181750 }, + { "8", 187750 }, + { "9", 193750 }, + { "10", 199750 }, + { "11", 205750 }, + { "12", 211750 }, + + { "13", 217750 }, + { "14", 127750 }, + { "15", 133750 }, + { "16", 139750 }, + { "17", 145750 }, + { "18", 151750 }, + { "19", 157750 }, + { "20", 163750 }, + + { "21", 169750 }, + { "22", 175750 }, + { "23", 223750 }, + { "24", 229750 }, + { "25", 235750 }, + { "26", 241750 }, + { "27", 247750 }, + { "28", 253750 }, + { "29", 259750 }, + { "30", 265750 }, + { "31", 271750 }, + { "32", 277750 }, + { "33", 283750 }, + { "34", 289750 }, + { "35", 295750 }, + { "36", 301750 }, + { "37", 307750 }, + { "38", 313750 }, + { "39", 319750 }, + { "40", 325750 }, + { "41", 331750 }, + { "42", 337750 }, + { "43", 343750 }, + { "44", 349750 }, + { "45", 355750 }, + { "46", 361750 }, + { "47", 367750 }, + { "48", 373750 }, + { "49", 379750 }, + { "50", 385750 }, + { "51", 391750 }, + { "52", 397750 }, + { "53", 403750 }, + { "54", 409750 }, + { "55", 415750 }, + { "56", 421750 }, + { "57", 427750 }, + { "58", 433750 }, + { "59", 439750 }, + { "60", 445750 }, + { "61", 451750 }, + { "62", 457750 }, + { "63", 463750 }, + { "64", 469750 }, + { "65", 475750 }, + { "66", 481750 }, + { "67", 487750 }, + { "68", 493750 }, + { "69", 499750 }, + + { "70", 505750 }, + { "71", 511750 }, + { "72", 517750 }, + { "73", 523750 }, + { "74", 529750 }, + { "75", 535750 }, + { "76", 541750 }, + { "77", 547750 }, + { "78", 553750 }, + { "79", 559750 }, + { "80", 565750 }, + { "81", 571750 }, + { "82", 577750 }, + { "83", 583750 }, + { "84", 589750 }, + { "85", 595750 }, + { "86", 601750 }, + { "87", 607750 }, + { "88", 613750 }, + { "89", 619750 }, + { "90", 625750 }, + { "91", 631750 }, + { "92", 637750 }, + { "93", 643750 }, + { "94", 649750 }, + { "95", 97750 }, + { "96", 103750 }, + { "97", 109750 }, + { "98", 115750 }, + { "99", 121750 }, + { "100", 655750 }, + { "101", 661750 }, + { "102", 667750 }, + { "103", 673750 }, + { "104", 679750 }, + { "105", 685750 }, + { "106", 691750 }, + { "107", 697750 }, + { "108", 703750 }, + { "109", 709750 }, + { "110", 715750 }, + { "111", 721750 }, + { "112", 727750 }, + { "113", 733750 }, + { "114", 739750 }, + { "115", 745750 }, + { "116", 751750 }, + { "117", 757750 }, + { "118", 763750 }, + { "119", 769750 }, + { "120", 775750 }, + { "121", 781750 }, + { "122", 787750 }, + { "123", 793750 }, + { "124", 799750 }, + { "125", 805750 } +}; + +/* --------------------------------------------------------------------- */ + +/* JP broadcast */ +static struct CHANLIST ntsc_bcast_jp[] = { + { "1", 91250 }, + { "2", 97250 }, + { "3", 103250 }, + { "4", 171250 }, + { "5", 177250 }, + { "6", 183250 }, + { "7", 189250 }, + { "8", 193250 }, + { "9", 199250 }, + { "10", 205250 }, + { "11", 211250 }, + { "12", 217250 }, + + { "13", 471250 }, + { "14", 477250 }, + { "15", 483250 }, + { "16", 489250 }, + { "17", 495250 }, + { "18", 501250 }, + { "19", 507250 }, + { "20", 513250 }, + { "21", 519250 }, + { "22", 525250 }, + { "23", 531250 }, + { "24", 537250 }, + { "25", 543250 }, + { "26", 549250 }, + { "27", 555250 }, + { "28", 561250 }, + { "29", 567250 }, + { "30", 573250 }, + { "31", 579250 }, + { "32", 585250 }, + { "33", 591250 }, + { "34", 597250 }, + { "35", 603250 }, + { "36", 609250 }, + { "37", 615250 }, + { "38", 621250 }, + { "39", 627250 }, + { "40", 633250 }, + { "41", 639250 }, + { "42", 645250 }, + { "43", 651250 }, + { "44", 657250 }, + + { "45", 663250 }, + { "46", 669250 }, + { "47", 675250 }, + { "48", 681250 }, + { "49", 687250 }, + { "50", 693250 }, + { "51", 699250 }, + { "52", 705250 }, + { "53", 711250 }, + { "54", 717250 }, + { "55", 723250 }, + { "56", 729250 }, + { "57", 735250 }, + { "58", 741250 }, + { "59", 747250 }, + { "60", 753250 }, + { "61", 759250 }, + { "62", 765250 }, +}; + +/* JP cable */ +static struct CHANLIST ntsc_cable_jp[] = { + { "13", 109250 }, + { "14", 115250 }, + { "15", 121250 }, + { "16", 127250 }, + { "17", 133250 }, + { "18", 139250 }, + { "19", 145250 }, + { "20", 151250 }, + + { "21", 157250 }, + { "22", 165250 }, + { "23", 223250 }, + { "24", 231250 }, + { "25", 237250 }, + { "26", 243250 }, + { "27", 249250 }, + { "28", 253250 }, + { "29", 259250 }, + { "30", 265250 }, + { "31", 271250 }, + { "32", 277250 }, + { "33", 283250 }, + { "34", 289250 }, + { "35", 295250 }, + { "36", 301250 }, + { "37", 307250 }, + { "38", 313250 }, + { "39", 319250 }, + { "40", 325250 }, + { "41", 331250 }, + { "42", 337250 }, + { "43", 343250 }, + { "44", 349250 }, + { "45", 355250 }, + { "46", 361250 }, + { "47", 367250 }, + { "48", 373250 }, + { "49", 379250 }, + { "50", 385250 }, + { "51", 391250 }, + { "52", 397250 }, + { "53", 403250 }, + { "54", 409250 }, + { "55", 415250 }, + { "56", 421250 }, + { "57", 427250 }, + { "58", 433250 }, + { "59", 439250 }, + { "60", 445250 }, + { "61", 451250 }, + { "62", 457250 }, + { "63", 463250 }, +}; + +/* --------------------------------------------------------------------- */ + +/* australia */ +static struct CHANLIST pal_australia[] = { + { "0", 46250 }, + { "1", 57250 }, + { "2", 64250 }, + { "3", 86250 }, + { "4", 95250 }, + { "5", 102250 }, + { "5A", 138250 }, + { "6", 175250 }, + { "7", 182250 }, + { "8", 189250 }, + { "9", 196250 }, + { "10", 209250 }, + { "11", 216250 }, + { "28", 527250 }, + { "29", 534250 }, + { "30", 541250 }, + { "31", 548250 }, + { "32", 555250 }, + { "33", 562250 }, + { "34", 569250 }, + { "35", 576250 }, + { "36", 591250 }, + { "39", 604250 }, + { "40", 611250 }, + { "41", 618250 }, + { "42", 625250 }, + { "43", 632250 }, + { "44", 639250 }, + { "45", 646250 }, + { "46", 653250 }, + { "47", 660250 }, + { "48", 667250 }, + { "49", 674250 }, + { "50", 681250 }, + { "51", 688250 }, + { "52", 695250 }, + { "53", 702250 }, + { "54", 709250 }, + { "55", 716250 }, + { "56", 723250 }, + { "57", 730250 }, + { "58", 737250 }, + { "59", 744250 }, + { "60", 751250 }, + { "61", 758250 }, + { "62", 765250 }, + { "63", 772250 }, + { "64", 779250 }, + { "65", 786250 }, + { "66", 793250 }, + { "67", 800250 }, + { "68", 807250 }, + { "69", 814250 }, +}; + +static struct CHANLIST pal_australia_optus[] = { + { "1", 138250 }, + { "2", 147250 }, + { "3", 154250 }, + { "4", 161250 }, + { "5", 168250 }, + { "6", 175250 }, + { "7", 182250 }, + { "8", 189250 }, + { "9", 196250 }, + { "10", 209250 }, + { "11", 216250 }, + { "12", 224250 }, + { "13", 231250 }, + { "14", 238250 }, + { "15", 245250 }, + { "16", 252250 }, + { "17", 259250 }, + { "18", 266250 }, + { "19", 273250 }, + { "20", 280250 }, + { "21", 287250 }, + { "22", 294250 }, + { "23", 303250 }, + { "24", 310250 }, + { "25", 317250 }, + { "26", 324250 }, + { "27", 338250 }, + { "28", 345250 }, + { "29", 352250 }, + { "30", 359250 }, + { "31", 366250 }, + { "32", 373250 }, + { "33", 380250 }, + { "34", 387250 }, + { "35", 394250 }, + { "36", 401250 }, + { "37", 408250 }, + { "38", 415250 }, + { "39", 422250 }, + { "40", 429250 }, + { "41", 436250 }, + { "42", 443250 }, + { "43", 450250 }, + { "44", 457250 }, + { "45", 464250 }, + { "46", 471250 }, + { "47", 478250 }, + { "48", 485250 }, + }; + +/* --------------------------------------------------------------------- */ +/* europe */ + +/* CCIR frequencies */ + +#define FREQ_CCIR_I_III \ + { "E2", 48250 }, \ + { "E3", 55250 }, \ + { "E4", 62250 }, \ + \ + { "S01", 69250 }, \ + { "S02", 76250 }, \ + { "S03", 83250 }, \ + \ + { "E5", 175250 }, \ + { "E6", 182250 }, \ + { "E7", 189250 }, \ + { "E8", 196250 }, \ + { "E9", 203250 }, \ + { "E10", 210250 }, \ + { "E11", 217250 }, \ + { "E12", 224250 } + +#define FREQ_CCIR_SL_SH \ + { "SE1", 105250 }, \ + { "SE2", 112250 }, \ + { "SE3", 119250 }, \ + { "SE4", 126250 }, \ + { "SE5", 133250 }, \ + { "SE6", 140250 }, \ + { "SE7", 147250 }, \ + { "SE8", 154250 }, \ + { "SE9", 161250 }, \ + { "SE10", 168250 }, \ + \ + { "SE11", 231250 }, \ + { "SE12", 238250 }, \ + { "SE13", 245250 }, \ + { "SE14", 252250 }, \ + { "SE15", 259250 }, \ + { "SE16", 266250 }, \ + { "SE17", 273250 }, \ + { "SE18", 280250 }, \ + { "SE19", 287250 }, \ + { "SE20", 294250 } + +#define FREQ_CCIR_H \ + { "S21", 303250 }, \ + { "S22", 311250 }, \ + { "S23", 319250 }, \ + { "S24", 327250 }, \ + { "S25", 335250 }, \ + { "S26", 343250 }, \ + { "S27", 351250 }, \ + { "S28", 359250 }, \ + { "S29", 367250 }, \ + { "S30", 375250 }, \ + { "S31", 383250 }, \ + { "S32", 391250 }, \ + { "S33", 399250 }, \ + { "S34", 407250 }, \ + { "S35", 415250 }, \ + { "S36", 423250 }, \ + { "S37", 431250 }, \ + { "S38", 439250 }, \ + { "S39", 447250 }, \ + { "S40", 455250 }, \ + { "S41", 463250 } + +/* OIRT frequencies */ + +#define FREQ_OIRT_I_III \ + { "R1", 49750 }, \ + { "R2", 59250 }, \ + \ + { "R3", 77250 }, \ + { "R4", 85250 }, \ + { "R5", 93250 }, \ + \ + { "R6", 175250 }, \ + { "R7", 183250 }, \ + { "R8", 191250 }, \ + { "R9", 199250 }, \ + { "R10", 207250 }, \ + { "R11", 215250 }, \ + { "R12", 223250 } + +#define FREQ_OIRT_SL_SH \ + { "SR1", 111250 }, \ + { "SR2", 119250 }, \ + { "SR3", 127250 }, \ + { "SR4", 135250 }, \ + { "SR5", 143250 }, \ + { "SR6", 151250 }, \ + { "SR7", 159250 }, \ + { "SR8", 167250 }, \ + \ + { "SR11", 231250 }, \ + { "SR12", 239250 }, \ + { "SR13", 247250 }, \ + { "SR14", 255250 }, \ + { "SR15", 263250 }, \ + { "SR16", 271250 }, \ + { "SR17", 279250 }, \ + { "SR18", 287250 }, \ + { "SR19", 295250 } + +#define FREQ_UHF \ + { "21", 471250 }, \ + { "22", 479250 }, \ + { "23", 487250 }, \ + { "24", 495250 }, \ + { "25", 503250 }, \ + { "26", 511250 }, \ + { "27", 519250 }, \ + { "28", 527250 }, \ + { "29", 535250 }, \ + { "30", 543250 }, \ + { "31", 551250 }, \ + { "32", 559250 }, \ + { "33", 567250 }, \ + { "34", 575250 }, \ + { "35", 583250 }, \ + { "36", 591250 }, \ + { "37", 599250 }, \ + { "38", 607250 }, \ + { "39", 615250 }, \ + { "40", 623250 }, \ + { "41", 631250 }, \ + { "42", 639250 }, \ + { "43", 647250 }, \ + { "44", 655250 }, \ + { "45", 663250 }, \ + { "46", 671250 }, \ + { "47", 679250 }, \ + { "48", 687250 }, \ + { "49", 695250 }, \ + { "50", 703250 }, \ + { "51", 711250 }, \ + { "52", 719250 }, \ + { "53", 727250 }, \ + { "54", 735250 }, \ + { "55", 743250 }, \ + { "56", 751250 }, \ + { "57", 759250 }, \ + { "58", 767250 }, \ + { "59", 775250 }, \ + { "60", 783250 }, \ + { "61", 791250 }, \ + { "62", 799250 }, \ + { "63", 807250 }, \ + { "64", 815250 }, \ + { "65", 823250 }, \ + { "66", 831250 }, \ + { "67", 839250 }, \ + { "68", 847250 }, \ + { "69", 855250 } + +static struct CHANLIST europe_west[] = { + FREQ_CCIR_I_III, + FREQ_CCIR_SL_SH, + FREQ_CCIR_H, + FREQ_UHF +}; + +static struct CHANLIST europe_east[] = { + FREQ_OIRT_I_III, + FREQ_OIRT_SL_SH, + FREQ_CCIR_I_III, + FREQ_CCIR_SL_SH, + FREQ_CCIR_H, + FREQ_UHF +}; + +static struct CHANLIST pal_italy[] = { + { "A", 53750 }, + { "B", 62250 }, + { "C", 82250 }, + { "D", 175250 }, + { "E", 183750 }, + { "F", 192250 }, + { "G", 201250 }, + { "H", 210250 }, + { "H1", 217250 }, + { "H2", 224250 }, + FREQ_UHF +}; + +static struct CHANLIST pal_ireland[] = { + { "A0", 45750 }, + { "A1", 48000 }, + { "A2", 53750 }, + { "A3", 56000 }, + { "A4", 61750 }, + { "A5", 64000 }, + { "A6", 175250 }, + { "A7", 176000 }, + { "A8", 183250 }, + { "A9", 184000 }, + { "A10", 191250 }, + { "A11", 192000 }, + { "A12", 199250 }, + { "A13", 200000 }, + { "A14", 207250 }, + { "A15", 208000 }, + { "A16", 215250 }, + { "A17", 216000 }, + { "A18", 224000 }, + { "A19", 232000 }, + { "A20", 248000 }, + { "A21", 256000 }, + { "A22", 264000 }, + { "A23", 272000 }, + { "A24", 280000 }, + { "A25", 288000 }, + { "A26", 296000 }, + { "A27", 304000 }, + { "A28", 312000 }, + { "A29", 320000 }, + { "A30", 344000 }, + { "A31", 352000 }, + { "A32", 408000 }, + { "A33", 416000 }, + { "A34", 448000 }, + { "A35", 480000 }, + { "A36", 520000 }, + FREQ_UHF, +}; + +static struct CHANLIST secam_france[] = { + { "K01", 47750 }, + { "K02", 55750 }, + { "K03", 60500 }, + { "K04", 63750 }, + { "K05", 176000 }, + { "K06", 184000 }, + { "K07", 192000 }, + { "K08", 200000 }, + { "K09", 208000 }, + { "K10", 216000 }, + { "KB", 116750 }, + { "KC", 128750 }, + { "KD", 140750 }, + { "KE", 159750 }, + { "KF", 164750 }, + { "KG", 176750 }, + { "KH", 188750 }, + { "KI", 200750 }, + { "KJ", 212750 }, + { "KK", 224750 }, + { "KL", 236750 }, + { "KM", 248750 }, + { "KN", 260750 }, + { "KO", 272750 }, + { "KP", 284750 }, + { "KQ", 296750 }, + { "H01", 303250 }, + { "H02", 311250 }, + { "H03", 319250 }, + { "H04", 327250 }, + { "H05", 335250 }, + { "H06", 343250 }, + { "H07", 351250 }, + { "H08", 359250 }, + { "H09", 367250 }, + { "H10", 375250 }, + { "H11", 383250 }, + { "H12", 391250 }, + { "H13", 399250 }, + { "H14", 407250 }, + { "H15", 415250 }, + { "H16", 423250 }, + { "H17", 431250 }, + { "H18", 439250 }, + { "H19", 447250 }, + FREQ_UHF, +}; + +/* --------------------------------------------------------------------- */ + +static struct CHANLIST pal_newzealand[] = { + { "1", 45250 }, + { "2", 55250 }, + { "3", 62250 }, + { "4", 175250 }, + { "5", 182250 }, + { "6", 189250 }, + { "7", 196250 }, + { "8", 203250 }, + { "9", 210250 }, + { "10", 217250 }, + { "11", 224250 }, + FREQ_UHF, +}; + +/* --------------------------------------------------------------------- */ + +/* China broadcast */ +static struct CHANLIST pal_bcast_cn[] = { + { "1", 49750 }, + { "2", 57750 }, + { "3", 65750 }, + { "4", 77250 }, + { "5", 85250 }, + { "6", 112250 }, + { "7", 120250 }, + { "8", 128250 }, + { "9", 136250 }, + { "10", 144250 }, + { "11", 152250 }, + { "12", 160250 }, + { "13", 168250 }, + { "14", 176250 }, + { "15", 184250 }, + { "16", 192250 }, + { "17", 200250 }, + { "18", 208250 }, + { "19", 216250 }, + { "20", 224250 }, + { "21", 232250 }, + { "22", 240250 }, + { "23", 248250 }, + { "24", 256250 }, + { "25", 264250 }, + { "26", 272250 }, + { "27", 280250 }, + { "28", 288250 }, + { "29", 296250 }, + { "30", 304250 }, + { "31", 312250 }, + { "32", 320250 }, + { "33", 328250 }, + { "34", 336250 }, + { "35", 344250 }, + { "36", 352250 }, + { "37", 360250 }, + { "38", 368250 }, + { "39", 376250 }, + { "40", 384250 }, + { "41", 392250 }, + { "42", 400250 }, + { "43", 408250 }, + { "44", 416250 }, + { "45", 424250 }, + { "46", 432250 }, + { "47", 440250 }, + { "48", 448250 }, + { "49", 456250 }, + { "50", 463250 }, + { "51", 471250 }, + { "52", 479250 }, + { "53", 487250 }, + { "54", 495250 }, + { "55", 503250 }, + { "56", 511250 }, + { "57", 519250 }, + { "58", 527250 }, + { "59", 535250 }, + { "60", 543250 }, + { "61", 551250 }, + { "62", 559250 }, + { "63", 607250 }, + { "64", 615250 }, + { "65", 623250 }, + { "66", 631250 }, + { "67", 639250 }, + { "68", 647250 }, + { "69", 655250 }, + { "70", 663250 }, + { "71", 671250 }, + { "72", 679250 }, + { "73", 687250 }, + { "74", 695250 }, + { "75", 703250 }, + { "76", 711250 }, + { "77", 719250 }, + { "78", 727250 }, + { "79", 735250 }, + { "80", 743250 }, + { "81", 751250 }, + { "82", 759250 }, + { "83", 767250 }, + { "84", 775250 }, + { "85", 783250 }, + { "86", 791250 }, + { "87", 799250 }, + { "88", 807250 }, + { "89", 815250 }, + { "90", 823250 }, + { "91", 831250 }, + { "92", 839250 }, + { "93", 847250 }, + { "94", 855250 }, +}; + +/* --------------------------------------------------------------------- */ +/* South Africa Broadcast */ + +static struct CHANLIST pal_bcast_za[] ={ + { "1", 175250 }, + { "2", 183250 }, + { "3", 191250 }, + { "4", 199250 }, + { "5", 207250 }, + { "6", 215250 }, + { "7", 223250 }, + { "8", 231250 }, + FREQ_UHF +}; + +/* --------------------------------------------------------------------- */ + +static struct CHANLIST argentina[] = { + { "001", 56250 }, + { "002", 62250 }, + { "003", 68250 }, + { "004", 78250 }, + { "005", 84250 }, + { "006", 176250 }, + { "007", 182250 }, + { "008", 188250 }, + { "009", 194250 }, + { "010", 200250 }, + { "011", 206250 }, + { "012", 212250 }, + { "013", 122250 }, + { "014", 128250 }, + { "015", 134250 }, + { "016", 140250 }, + { "017", 146250 }, + { "018", 152250 }, + { "019", 158250 }, + { "020", 164250 }, + { "021", 170250 }, + { "022", 218250 }, + { "023", 224250 }, + { "024", 230250 }, + { "025", 236250 }, + { "026", 242250 }, + { "027", 248250 }, + { "028", 254250 }, + { "029", 260250 }, + { "030", 266250 }, + { "031", 272250 }, + { "032", 278250 }, + { "033", 284250 }, + { "034", 290250 }, + { "035", 296250 }, + { "036", 302250 }, + { "037", 308250 }, + { "038", 314250 }, + { "039", 320250 }, + { "040", 326250 }, + { "041", 332250 }, + { "042", 338250 }, + { "043", 344250 }, + { "044", 350250 }, + { "045", 356250 }, + { "046", 362250 }, + { "047", 368250 }, + { "048", 374250 }, + { "049", 380250 }, + { "050", 386250 }, + { "051", 392250 }, + { "052", 398250 }, + { "053", 404250 }, + { "054", 410250 }, + { "055", 416250 }, + { "056", 422250 }, + { "057", 428250 }, + { "058", 434250 }, + { "059", 440250 }, + { "060", 446250 }, + { "061", 452250 }, + { "062", 458250 }, + { "063", 464250 }, + { "064", 470250 }, + { "065", 476250 }, + { "066", 482250 }, + { "067", 488250 }, + { "068", 494250 }, + { "069", 500250 }, + { "070", 506250 }, + { "071", 512250 }, + { "072", 518250 }, + { "073", 524250 }, + { "074", 530250 }, + { "075", 536250 }, + { "076", 542250 }, + { "077", 548250 }, + { "078", 554250 }, + { "079", 560250 }, + { "080", 566250 }, + { "081", 572250 }, + { "082", 578250 }, + { "083", 584250 }, + { "084", 590250 }, + { "085", 596250 }, + { "086", 602250 }, + { "087", 608250 }, + { "088", 614250 }, + { "089", 620250 }, + { "090", 626250 }, + { "091", 632250 }, + { "092", 638250 }, + { "093", 644250 }, +}; + +/* --------------------------------------------------------------------- */ + +struct CHANLISTS chanlists[] = { + { "us-bcast", ntsc_bcast, CHAN_COUNT(ntsc_bcast) }, + { "us-cable", ntsc_cable, CHAN_COUNT(ntsc_cable) }, + { "us-cable-hrc", ntsc_hrc, CHAN_COUNT(ntsc_hrc) }, + { "japan-bcast", ntsc_bcast_jp, CHAN_COUNT(ntsc_bcast_jp) }, + { "japan-cable", ntsc_cable_jp, CHAN_COUNT(ntsc_cable_jp) }, + { "europe-west", europe_west, CHAN_COUNT(europe_west) }, + { "europe-east", europe_east, CHAN_COUNT(europe_east) }, + { "italy", pal_italy, CHAN_COUNT(pal_italy) }, + { "newzealand", pal_newzealand, CHAN_COUNT(pal_newzealand) }, + { "australia", pal_australia, CHAN_COUNT(pal_australia) }, + { "ireland", pal_ireland, CHAN_COUNT(pal_ireland) }, + { "france", secam_france, CHAN_COUNT(secam_france) }, + { "china-bcast", pal_bcast_cn, CHAN_COUNT(pal_bcast_cn) }, + { "southafrica", pal_bcast_za, CHAN_COUNT(pal_bcast_za) }, + { "argentina", argentina, CHAN_COUNT(argentina) }, + { "canada-cable", ntsc_cable_ca, CHAN_COUNT(ntsc_cable_ca) }, + { "australia-optus", pal_australia_optus, CHAN_COUNT(pal_australia_optus) }, + { NULL, NULL, 0 } /* EOF */ +}; + +/* +struct STRTAB chanlist_names[] = { + { 0, "us-bcast" }, + { 1, "us-cable" }, + { 2, "us-cable-hrc" }, + { 3, "japan-bcast" }, + { 4, "japan-cable" }, + { 5, "europe-west" }, + { 6, "europe-east" }, + { 7, "italy" }, + { 8, "newzealand" }, + { 9, "australia" }, + { 10, "ireland" }, + { 11, "france" }, + { 12, "china-bcast" }, + { 13, "southafrica" }, + { 14, "argentina" }, + { 15, "canada-cable" }, + { 16, "australia-optus" }, + { -1, NULL } +}; + +int chantab = 5; +struct CHANLIST *chanlist = europe_west; +int chancount = CHAN_COUNT(europe_west); + +*/ diff --git a/branches/V-1.5.3/veejay-server/libstream/frequencies.h b/branches/V-1.5.3/veejay-server/libstream/frequencies.h new file mode 100644 index 00000000..2801c6b5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/frequencies.h @@ -0,0 +1,119 @@ +/* + * Worldwide channel/frequency list + * + * Nathan Laredo (laredo@broked.net) + * + * Frequencies are given in kHz + */ + +#ifndef __FREQUENCIES_H__ +#define __FREQUENCIES_H__ + +#define NTSC_AUDIO_CARRIER 4500 +#define PAL_AUDIO_CARRIER_I 6000 +#define PAL_AUDIO_CARRIER_BGHN 5500 +#define PAL_AUDIO_CARRIER_MN 4500 +#define PAL_AUDIO_CARRIER_D 6500 +#define SEACAM_AUDIO_DKK1L 6500 +#define SEACAM_AUDIO_BG 5500 +/* NICAM 728 32-kHz, 14-bit digital stereo audio is transmitted in 1ms frames + containing 8 bits frame sync, 5 bits control, 11 bits additional data, and + 704 bits audio data. The bit rate is reduced by transmitting only 10 bits + plus parity of each 14 bit sample, the largest sample in a frame determines + which 10 bits are transmitted. The parity bits for audio samples also + specify the scaling factor used for that channel during that frame. The + companeded audio data is interleaved to reduce the influence of dropouts + and the whole frame except for sync bits is scrambled for spectrum shaping. + Data is modulated using QPSK, at below following subcarrier freqs */ +#define NICAM728_PAL_BGH 5850 +#define NICAM728_PAL_I 6552 + +/* COMPREHENSIVE LIST OF FORMAT BY COUNTRY + (M) NTSC used in: + Antigua, Aruba, Bahamas, Barbados, Belize, Bermuda, Bolivia, Burma, + Canada, Chile, Colombia, Costa Rica, Cuba, Curacao, Dominican Republic, + Ecuador, El Salvador, Guam Guatemala, Honduras, Jamaica, Japan, + South Korea, Mexico, Montserrat, Myanmar, Nicaragua, Panama, Peru, + Philippines, Puerto Rico, St Christopher and Nevis, Samoa, Suriname, + Taiwan, Trinidad/Tobago, United States, Venezuela, Virgin Islands + (B) PAL used in: + Albania, Algeria, Australia, Austria, Bahrain, Bangladesh, Belgium, + Bosnia-Herzegovinia, Brunei Darussalam, Cambodia, Cameroon, Croatia, + Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, Finland, Germany, + Ghana, Gibraltar, Greenland, Iceland, India, Indonesia, Israel, Italy, + Jordan, Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysa, Maldives, + Malta, Nepal, Netherlands, New Zeland, Nigeria, Norway, Oman, Pakistan, + Papua New Guinea, Portugal, Qatar, Sao Tome and Principe, Saudi Arabia, + Seychelles, Sierra Leone, Singapore, Slovenia, Somali, Spain, + Sri Lanka, Sudan, Swaziland, Sweden, Switzeland, Syria, Thailand, + Tunisia, Turkey, Uganda, United Arab Emirates, Yemen + (N) PAL used in: (Combination N = 4.5MHz audio carrier, 3.58MHz burst) + Argentina (Combination N), Paraguay, Uruguay + (M) PAL (525/60, 3.57MHz burst) used in: + Brazil + (G) PAL used in: + Albania, Algeria, Austria, Bahrain, Bosnia/Herzegovinia, Cambodia, + Cameroon, Croatia, Cyprus, Denmark, Egypt, Ethiopia, Equatorial Guinea, + Finland, Germany, Gibraltar, Greenland, Iceland, Israel, Italy, Jordan, + Kenya, Kuwait, Liberia, Libya, Luxembourg, Malaysia, Monaco, + Mozambique, Netherlands, New Zealand, Norway, Oman, Pakistan, + Papa New Guinea, Portugal, Qatar, Romania, Sierra Leone, Singapore, + Slovenia, Somalia, Spain, Sri Lanka, Sudan, Swaziland, Sweeden, + Switzerland, Syria, Thailand, Tunisia, Turkey, United Arab Emirates, + Yemen, Zambia, Zimbabwe + (D) PAL used in: + China, North Korea, Romania, Czech Republic + (H) PAL used in: + Belgium + (I) PAL used in: + Angola, Botswana, Gambia, Guinea-Bissau, Hong Kong, Ireland, Lesotho, + Malawi, Nambia, Nigeria, South Africa, Tanzania, United Kingdom, + Zanzibar + (B) SECAM used in: + Djibouti, Greece, Iran, Iraq, Lebanon, Mali, Mauritania, Mauritus, + Morocco + (D) SECAM used in: + Afghanistan, Armenia, Azerbaijan, Belarus, Bulgaria, + Estonia, Georgia, Hungary, Zazakhstan, Lithuania, Mongolia, Moldova, + Russia, Slovak Republic, Ukraine, Vietnam + (G) SECAM used in: + Greecem Iran, Iraq, Mali, Mauritus, Morocco, Saudi Arabia + (K) SECAM used in: + Armenia, Azerbaijan, Bulgaria, Estonia, Georgia, + Hungary, Kazakhstan, Lithuania, Madagascar, Moldova, Poland, Russia, + Slovak Republic, Ukraine, Vietnam + (K1) SECAM used in: + Benin, Burkina Faso, Burundi, Chad, Cape Verde, Central African + Republic, Comoros, Congo, Gabon, Madagascar, Niger, Rwanda, Senegal, + Togo, Zaire + (L) SECAM used in: + France +*/ + +/* --------------------------------------------------------------------- */ + +struct CHANLIST { + char *name; + int freq; +}; + +struct CHANLISTS { + char *name; + struct CHANLIST *list; + int count; +}; + +#define CHAN_COUNT(x) (sizeof(x)/sizeof(struct CHANLIST)) + +/* --------------------------------------------------------------------- */ + +extern struct CHANLISTS chanlists[]; +/* +extern struct STRTAB chanlist_names[]; + +extern int chantab; +extern struct CHANLIST *chanlist; +extern int chancount; +*/ + +#endif /* __FREQUENCIES_H__ */ diff --git a/branches/V-1.5.3/veejay-server/libstream/v4lutils.c b/branches/V-1.5.3/veejay-server/libstream/v4lutils.c new file mode 100644 index 00000000..8f0dfbfb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/v4lutils.c @@ -0,0 +1,592 @@ +/* + * v4lutils - utility library for Video4Linux + * Copyright (C) 2001-2002 FUKUCHI Kentaro + * + * v4lutils.c: utility functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define DEFAULT_DEVICE "/dev/video" + +#define STRBUF_LENGTH 1024 + +#ifdef STRICT_CHECKING +static int v4l_debug = 1; /* 1 = print debug message */ +#else +static int v4l_debug = 0; +#endif +extern int errno; +static int v4lperror_level = V4L_PERROR_ALL; + +/* + * v4lperror - inhouse perror. + * + */ + +/* + * v4lopen - open the v4l device. + * + * name: device file + * vd: v4l device object + */ +int v4lopen(char *name, v4ldevice *vd) +{ + int i; + + if(name == NULL) + name = DEFAULT_DEVICE; + +// if(v4l_debug) veejay_msg(0, "v4lopen:open..."); + if((vd->fd = open(name,O_RDWR)) < 0) { + // veejay_msg(0, "v4lopen: failed to open %s: %s", name, strerror(errno)); + return -1; + } + if(v4lgetcapability(vd)) + return -1; + +// if(v4l_debug) veejay_msg(0, "v4lopen:VIDIOCGCHAN..."); + for(i=0;icapability.channels;i++) { + vd->channel[i].channel = i; + if(ioctl(vd->fd, VIDIOCGCHAN, &(vd->channel[i])) < 0) { + veejay_msg(0,"v4lopen:VIDIOCGCHAN %s", strerror(errno)); + return -1; + } + } + v4lgetpicture(vd); + pthread_mutex_init(&vd->mutex, NULL); +// if(v4l_debug) veejay_msg(0, "v4lopen:quit"); + return 0; +} + +/* + * v4lclose - close v4l device + * + * vd: v4l device object + */ +int v4lclose(v4ldevice *vd) +{ +// if(v4l_debug) veejay_msg(0, "v4lclose:close..."); + close(vd->fd); +// if(v4l_debug) veejay_msg(0, "v4lclose:quit"); + return 0; +} + +/* + * v4lgetcapability - get the capability of v4l device + * + * vd: v4l device object + */ +int v4lgetcapability(v4ldevice *vd) +{ +// if(v4l_debug) veejay_msg(0, "v4lgetcapability:VIDIOCGCAP..."); + if(ioctl(vd->fd, VIDIOCGCAP, &(vd->capability)) < 0) { + veejay_msg(0, "v4lopen:VIDIOCGCAP %s", strerror(errno)); + return -1; + } +// if(v4l_debug) veejay_msg(0, "v4lgetcapability:quit"); + return 0; +} + +/* + * v4lsetdefaultnorm - set default norm and reset parameters + * + * vd: v4l device object + * norm: default norm + */ +int v4lsetdefaultnorm(v4ldevice *vd, int norm) +{ + int i; + + for(i=0;icapability.channels;i++) { + v4lsetchannelnorm(vd, i, norm); + } + if(v4lgetcapability(vd)) + return -1; + if(v4lgetpicture(vd)) + return -1; + return 0; +} + +/* + * v4lgetsubcapture - get current status of subfield capturing + * + * vd: v4l device object + */ +int v4lgetsubcapture(v4ldevice *vd) +{ + if(ioctl(vd->fd, VIDIOCGCAPTURE, &(vd->capture)) < 0) { + veejay_msg(0, "v4lgetsubcapture:VIDIOCGCAPTURE %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lsetsubcapture - set parameters for subfield capturing + * + * vd: v4l device object + * x,y: coordinate of source rectangle to grab + * width: width of source rectangle to grab + * height: height of source rectangle to grab + * decimation: decimation to apply + * flags: flag setting for grabbing odd/even frames + */ +int v4lsetsubcapture(v4ldevice *vd, int x, int y, int width, int height, int decimation, int flags) +{ + vd->capture.x = x; + vd->capture.y = y; + vd->capture.width = width; + vd->capture.height = height; + vd->capture.decimation = decimation; + vd->capture.flags = flags; + if(ioctl(vd->fd, VIDIOCGCAPTURE, &(vd->capture)) < 0) { + veejay_msg(0, "v4lsetsubcapture:VIDIOCSCAPTURE %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lgetframebuffer - get current status of frame buffer + * + * vd: v4l device object + */ +int v4lgetframebuffer(v4ldevice *vd) +{ + if(ioctl(vd->fd, VIDIOCGFBUF, &(vd->buffer)) < 0) { + veejay_msg(0, "v4lgetframebuffer:VIDIOCGFBUF %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lsetframebuffer - set parameters of frame buffer + * + * vd: v4l device object + * base: base PHYSICAL address of the frame buffer + * width: width of the frame buffer + * height: height of the frame buffer + * depth: color depth of the frame buffer + * bpl: number of bytes of memory between the start of two adjacent lines + */ +int v4lsetframebuffer(v4ldevice *vd, void *base, int width, int height, int depth, int bpl) +{ + vd->buffer.base = base; + vd->buffer.width = width; + vd->buffer.height = height; + vd->buffer.depth = depth; + vd->buffer.bytesperline = bpl; + if(ioctl(vd->fd, VIDIOCSFBUF, &(vd->buffer)) < 0) { + veejay_msg(0, "v4lsetframebuffer:VIDIOCSFBUF %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4loverlaystart - activate overlay capturing + * + * vd: v4l device object + */ +int v4loverlaystart(v4ldevice *vd) +{ + if(ioctl(vd->fd, VIDIOCCAPTURE, 1) < 0) { + veejay_msg(0, "v4loverlaystart:VIDIOCCAPTURE %s", strerror(errno)); + return -1; + } + vd->overlay = 1; + return 0; +} + +/* + * v4loverlaystop - stop overlay capturing + * + * vd: v4l device object + */ +int v4loverlaystop(v4ldevice *vd) +{ + if(ioctl(vd->fd, VIDIOCCAPTURE, 0) < 0) { + veejay_msg(0,"v4loverlaystop:VIDIOCCAPTURE %s", strerror(errno)); + return -1; + } + vd->overlay = 0; + return 0; +} + +/* + * v4lsetchannel - select the video source + * + * vd: v4l device object + * ch: the channel number + */ +int v4lsetchannel(v4ldevice *vd, int ch) +{ + if(ioctl(vd->fd, VIDIOCSCHAN, &(vd->channel[ch])) < 0) { + veejay_msg(0,"v4lsetchannel:VIDIOCSCHAN %s", strerror(errno)); + return -1; + } + return 0; +} + +int v4lmaxchannel(v4ldevice *vd) +{ + return vd->capability.channels; +} + +/* + * v4lsetfreq - set the frequency of tuner + * + * vd: v4l device object + * ch: frequency in KHz + */ +int v4lsetfreq(v4ldevice *vd, int freq) +{ + unsigned long longfreq=(freq*16)/1000; + if(ioctl(vd->fd, VIDIOCSFREQ, &longfreq) < 0) { + veejay_msg(0, "v4lsetfreq:VIDIOCSFREQ %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lsetchannelnorm - set the norm of channel + * + * vd: v4l device object + * ch: the channel number + * norm: PAL/NTSC/OTHER (see videodev.h) + */ +int v4lsetchannelnorm(v4ldevice *vd, int ch, int norm) +{ + vd->channel[ch].norm = norm; + return 0; +} + +/* + * v4lgetpicture - get current properties of the picture + * + * vd: v4l device object + */ +int v4lgetpicture(v4ldevice *vd) +{ + if(ioctl(vd->fd, VIDIOCGPICT, &(vd->picture)) < 0) { + veejay_msg(0, "v4lgetpicture:VIDIOCGPICT %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lsetpicture - set the image properties of the picture + * + * vd: v4l device object + * br: picture brightness + * hue: picture hue + * col: picture color + * cont: picture contrast + * white: picture whiteness + */ +int v4lsetpicture(v4ldevice *vd, int br, int hue, int col, int cont, int white) +{ + if(br>=0) + vd->picture.brightness = br; + if(hue>=0) + vd->picture.hue = hue; + if(col>=0) + vd->picture.colour = col; + if(cont>=0) + vd->picture.contrast = cont; + if(white>=0) + vd->picture.whiteness = white; + if(ioctl(vd->fd, VIDIOCSPICT, &(vd->picture)) < 0) { + veejay_msg(0, "v4lsetpicture:VIDIOCSPICT %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lsetpalette - set the palette for the images + * + * vd: v4l device object + * palette: palette + */ +int v4lsetpalette(v4ldevice *vd, int palette) +{ + vd->picture.palette = palette; + vd->mmap.format = palette; + if(ioctl(vd->fd, VIDIOCSPICT, &(vd->picture)) < 0) { +// veejay_msg(0, "v4lsetpalette:VIDIOCSPICT %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lgetmbuf - get the size of the buffer to mmap + * + * vd: v4l device object + */ +int v4lgetmbuf(v4ldevice *vd) +{ + if(ioctl(vd->fd, VIDIOCGMBUF, &(vd->mbuf))<0) { + veejay_msg(0, "v4lgetmbuf:VIDIOCGMBUF %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lmmap - initialize mmap interface + * + * vd: v4l device object + */ +int v4lmmap(v4ldevice *vd) +{ + if(v4lgetmbuf(vd)<0) + return -1; + if((vd->map = mmap(0, vd->mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED, vd->fd, 0)) < 0) { + veejay_msg(0, "v4lmmap:mmap %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lmunmap - free memory area for mmap interface + * + * vd: v4l device object + */ +int v4lmunmap(v4ldevice *vd) +{ + if(munmap(vd->map, vd->mbuf.size) < 0) { + veejay_msg(0,"v4lmunmap:munmap %s", strerror(errno)); + return -1; + } + return 0; +} + +/* + * v4lgrabinit - set parameters for mmap interface + * + * vd: v4l device object + * width: width of the buffer + * height: height of the buffer + */ +int v4lgrabinit(v4ldevice *vd, int width, int height) +{ + vd->mmap.width = width; + vd->mmap.height = height; + vd->mmap.format = vd->picture.palette; + vd->frame = 0; + vd->framestat[0] = 0; + vd->framestat[1] = 0; + return 0; +} + +/* + * v4lgrabstart - activate mmap capturing + * + * vd: v4l device object + * frame: frame number for storing captured image + */ +int v4lgrabstart(v4ldevice *vd, int frame) +{ +// if(v4l_debug) +// veejay_msg(VEEJAY_MSG_DEBUG, "v4lgrabstart: grab frame %d.",frame); + if(vd->framestat[frame]) { + veejay_msg(VEEJAY_MSG_DEBUG, "v4lgrabstart: frame %d is already used to grab.", frame); + } + vd->mmap.frame = frame; + if(ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap)) < 0) { + veejay_msg(VEEJAY_MSG_DEBUG,"v4lgrabstart:VIDIOCMCAPTURE %s", strerror(errno)); + return -1; + } + vd->framestat[frame] = 1; + return 0; +} + +/* + * v4lsync - wait until mmap capturing of the frame is finished + * + * vd: v4l device object + * frame: frame number + */ +int v4lsync(v4ldevice *vd, int frame) +{ +// if(v4l_debug) veejay_msg(VEEJAY_MSG_DEBUG, "v4lsync: sync frame %d.",frame); + if(vd->framestat[frame] == 0) { + veejay_msg(VEEJAY_MSG_DEBUG, "v4lsync: grabbing to frame %d is not started.", frame); + } + if(ioctl(vd->fd, VIDIOCSYNC, &frame) < 0) { + veejay_msg(0,"v4lsync:VIDIOCSYNC %s", strerror(errno)); + return -1; + } + vd->framestat[frame] = 0; + return 0; +} + +/* + * v4llock - lock the Video4Linux device object + * + * vd: v4l device object + */ +int v4llock(v4ldevice *vd) +{ + return pthread_mutex_lock(&vd->mutex); +} + +/* + * v4lunlock - unlock the Video4Linux device object + * + * vd: v4l device object + */ +int v4lunlock(v4ldevice *vd) +{ + return pthread_mutex_unlock(&vd->mutex); +} + +/* + * v4ltrylock - lock the Video4Linux device object (non-blocking mode) + * + * vd: v4l device object + */ +int v4ltrylock(v4ldevice *vd) +{ + return pthread_mutex_trylock(&vd->mutex); +} + +/* + * v4lsyncf - flip-flop sync + * + * vd: v4l device object + */ +int v4lsyncf(v4ldevice *vd) +{ + return v4lsync(vd, vd->frame); +} + +/* + * v4lgrabf - flip-flop grabbing + * + * vd: v4l device object + */ +int v4lgrabf(v4ldevice *vd) +{ + int f; + + f = vd->frame; + vd->frame = vd->frame ^ 1; + return v4lgrabstart(vd, f); +} + +/* + * v4lgetaddress - returns a offset addres of buffer for mmap capturing + * + * vd: v4l device object + */ +unsigned char *v4lgetaddress(v4ldevice *vd) +{ + return (vd->map + vd->mbuf.offsets[vd->frame]); +} + +/* + * v4lreadframe - grab one frame by calling read system call + * vd: v4l device object + * buf: buffer where a grabbed imaged is stored + */ + +int v4lreadframe(v4ldevice *vd, unsigned char *buf) +{ + /* to do */ + return -1; +} + +char *v4lgetdevicename( v4ldevice *vd ) { + return vd->capability.name; +} + + +/* + * v4lprint - print v4l device object + * + * vd: v4l device object + */ +void v4lprint(v4ldevice *vd) +{ + veejay_msg(VEEJAY_MSG_INFO,"Capture device: %s in %dx%d - %x",vd->capability.name, + vd->mmap.width,vd->mmap.height,vd->picture.palette); + veejay_msg(VEEJAY_MSG_DEBUG,"Video channels: %d",vd->capability.channels); + veejay_msg(VEEJAY_MSG_DEBUG,"Max resolution: %dx%d",vd->capability.maxwidth,vd->capability.maxheight); + veejay_msg(VEEJAY_MSG_DEBUG,"Min resolution: %dx%d",vd->capability.minwidth, vd->capability.minheight); + veejay_msg(VEEJAY_MSG_DEBUG,"Device type:"); + if(vd->capability.type & VID_TYPE_CAPTURE) veejay_msg(VEEJAY_MSG_DEBUG,"VID_TYPE_CAPTURE,"); + if(vd->capability.type & VID_TYPE_OVERLAY) veejay_msg(VEEJAY_MSG_DEBUG,"VID_TYPE_OVERLAY,"); + if(vd->capability.type & VID_TYPE_CLIPPING) veejay_msg(VEEJAY_MSG_DEBUG,"VID_TYPE_CLIPPING,"); + if(vd->capability.type & VID_TYPE_FRAMERAM) veejay_msg(VEEJAY_MSG_DEBUG,"VID_TYPE_FRAMERAM,"); + if(vd->capability.type & VID_TYPE_SCALES) veejay_msg(VEEJAY_MSG_DEBUG,"VID_TYPE_SCALES,"); + if(vd->capability.type & VID_TYPE_MONOCHROME) veejay_msg(VEEJAY_MSG_DEBUG,"VID_TYPE_MONOCHROME,"); + if(vd->capability.type & VID_TYPE_SUBCAPTURE) veejay_msg(VEEJAY_MSG_DEBUG,"VID_TYPE_SUBCAPTURE,"); + veejay_msg(VEEJAY_MSG_DEBUG,"Device Status:"); + veejay_msg(VEEJAY_MSG_DEBUG,"\tDepth: %d",vd->picture.depth); + veejay_msg(VEEJAY_MSG_DEBUG,"\tPalette:%x",vd->picture.palette); + veejay_msg(VEEJAY_MSG_DEBUG,"\tWidth:%d",vd->mmap.width); + veejay_msg(VEEJAY_MSG_DEBUG,"\tHeight:%d",vd->mmap.height); + veejay_msg(VEEJAY_MSG_DEBUG,"\tNorm: %s", v4lvideo_templ_get_norm_str( vd->channel[0].norm )); + veejay_msg(VEEJAY_MSG_DEBUG,"\tBuffer size: %08x",vd->mbuf.size); + veejay_msg(VEEJAY_MSG_DEBUG,"\tNum buffers: %d",vd->mbuf.frames); + veejay_msg(VEEJAY_MSG_DEBUG,"\t offsets[0]: %08x",vd->mbuf.offsets[0]); + veejay_msg(VEEJAY_MSG_DEBUG,"\t offsets[1]: %08x",vd->mbuf.offsets[1]); +} + +/* + * v4lseterrorlevel - enable/disable perror message output + * + * flag: V4L_PERROR_NONE or V4L_PERROR_ALL(default) + */ +void v4lseterrorlevel(int flag) +{ + v4lperror_level = flag; +} + +/* + * v4ldebug - enable/disable debug message output + * + * flag: 0 = disable / 1 = enable + */ +void v4ldebug(int flag) +{ + veejay_msg(0, "debug: %d",flag); + v4l_debug = flag; +} diff --git a/branches/V-1.5.3/veejay-server/libstream/v4lutils.h b/branches/V-1.5.3/veejay-server/libstream/v4lutils.h new file mode 100644 index 00000000..a9518c07 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/v4lutils.h @@ -0,0 +1,97 @@ +/* + * v4lutils - utility library for Video4Linux + * Copyright (C) 2001-2002 FUKUCHI Kentaro + * + * v4lutils.h: header file + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef __V4LUTILS_H__ +#define __V4LUTILS_H__ + +#include +#include +#include + +/* + * Error message displaying level + */ +#define V4L_PERROR_NONE (0) +#define V4L_PERROR_ALL (1) + +/* + * Video4Linux Device Structure + */ +struct _v4ldevice +{ + int fd; + struct video_capability capability; + struct video_channel channel[10]; + struct video_picture picture; + struct video_clip clip; + struct video_window window; + struct video_capture capture; + struct video_buffer buffer; + struct video_mmap mmap; + struct video_mbuf mbuf; + struct video_unit unit; + unsigned char *map; + pthread_mutex_t mutex; + int frame; + int framestat[2]; + int overlay; +}; + +typedef struct _v4ldevice v4ldevice; + +extern int v4lopen(char *, v4ldevice *); +extern int v4lclose(v4ldevice *); +extern int v4lgetcapability(v4ldevice *); +extern int v4lsetdefaultnorm(v4ldevice *, int); +extern int v4lgetsubcapture(v4ldevice *); +extern int v4lsetsubcapture(v4ldevice *, int, int, int, int, int, int); +extern int v4lgetframebuffer(v4ldevice *); +extern int v4lsetframebuffer(v4ldevice *, void *, int, int, int, int); +extern int v4loverlaystart(v4ldevice *); +extern int v4loverlaystop(v4ldevice *); +extern int v4lsetchannel(v4ldevice *, int); +extern int v4lmaxchannel(v4ldevice *); +extern int v4lsetfreq(v4ldevice *,int); +extern int v4lsetchannelnorm(v4ldevice *vd, int, int); +extern int v4lgetpicture(v4ldevice *); +extern int v4lsetpicture(v4ldevice *, int, int, int, int, int); +extern int v4lsetpalette(v4ldevice *, int); +extern int v4lgetmbuf(v4ldevice *); +extern int v4lmmap(v4ldevice *); +extern int v4lmunmap(v4ldevice *); +extern int v4lgrabinit(v4ldevice *, int, int); +extern int v4lgrabstart(v4ldevice *, int); +extern int v4lsync(v4ldevice *, int); +extern int v4llock(v4ldevice *); +extern int v4ltrylock(v4ldevice *); +extern int v4lunlock(v4ldevice *); +extern int v4lsyncf(v4ldevice *); +extern int v4lgrabf(v4ldevice *); +extern unsigned char *v4lgetaddress(v4ldevice *); +extern int v4lreadframe(v4ldevice *, unsigned char *); +extern void v4lprint(v4ldevice *); +extern void v4lseterrorlevel(int); +extern void v4ldebug(int); +extern char *v4lgetdevicename(v4ldevice *); + +#endif /* __V4LUTILS_H__ */ diff --git a/branches/V-1.5.3/veejay-server/libstream/v4lvideo.c b/branches/V-1.5.3/veejay-server/libstream/v4lvideo.c new file mode 100644 index 00000000..e4249da7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/v4lvideo.c @@ -0,0 +1,1186 @@ +/* + * Linux VeeJay + * V4l1 driver , classic stuff + * Copyright(C)2008 Niels Elburg + * uses v4lutils - utility library for Video4Linux + * Copyright (C) 2001-2002 FUKUCHI Kentaro + + * 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 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif + +typedef struct _normlist +{ + char name[10]; + int type; +} normlist; + + +static normlist normlists[] = +{ + {"ntsc" , VIDEO_MODE_NTSC}, + {"pal" , VIDEO_MODE_PAL}, + {"secam" , VIDEO_MODE_SECAM}, + {"auto" , VIDEO_MODE_AUTO}, +/* following values are supproted by bttv driver. */ + {"pal-nc" , 3}, + {"pal-m" , 4}, + {"pal-n" , 5}, + {"ntsc-jp", 6}, + {"", -1} +}; + + +typedef struct { + int w; + int h; + int palette; + int src_fmt; + int dst_fmt; + int native; + VJFrame *src; + VJFrame *dst; +} v4lprocessing; + +typedef struct { + v4ldevice vd; + int video_width; + int video_height; + int video_area; + int video_channel; + int video_norm; + int video_palette; + int has_tuner; + int freqtable; + int tvchannel; + char *video_file; + int brightness; + int hue; + int colour; + int contrast; + int white; + void *converter; + int max_width; + int max_height; + int min_width; + int min_height; + int composite; + sws_template sws_templ; + void *scaler; + v4lprocessing *info; + int native; + int jpeglen; + int active; + int has_video; + int dps; + int grabbing; +} v4lvideo_t; + + +typedef struct { + char *filename; + int width; + int height; + int palette; + int norm; + int channel; + int frequency; + int composite; + void *v4l; + pthread_mutex_t mutex; + pthread_t thread; + pthread_attr_t attr; + int status; + uint8_t *frame_buffer; + uint8_t *temp_buffer; + int len; + int uvlen; + int pause; + int error; +} v4lvideo_template_t; + +static void __v4lvideo_destroy( void *vv ); +static const char *get_palette_name( int v4l ); +static int __v4lvideo_grabstart( void *vv ); +static int __v4lvideo_grabstop(void *vv); +static void __v4lvideo_copy_framebuffer_to(v4lvideo_t *v1, v4lvideo_template_t *v2, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV ); +int v4lvideo_grab_check( v4lvideo_t *v, int palette ); +static int v4lvideo_set_grabformat( v4lvideo_t *v, int palette ); +static int __v4lvideo_init( v4lvideo_t *v, char* file, int channel, int norm, int freq, int dst_w, int dst_h, int dst_palette ); + +static void *device_list_ = NULL; +static int device_count_ = 0; +static int max_device_ = 0; + + + +void *v4lvideo_init( char* file, int channel, int norm, int freq, int dst_w, int dst_h, int dst_palette ) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vj_calloc(sizeof(v4lvideo_template_t)); + v->filename = strdup(file); + v->channel = channel; + v->norm = norm; + v->frequency= freq; + v->width = dst_w; + v->height = dst_h; + v->palette = dst_palette; + v->len = dst_w * dst_h; + if( dst_palette == VIDEO_PALETTE_YUV422P ) { + v->uvlen = (dst_w/2) * dst_h; + } else if (dst_palette == VIDEO_PALETTE_YUV420) { + v->uvlen = (dst_w/2) * (dst_h/2); + } else { + veejay_msg(0, "Wrong palette: %s", get_palette_name(dst_palette)); + free(v); + return NULL; + } + v->frame_buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * 8 * v->width * v->height); + v->temp_buffer = v->frame_buffer + (4 * v->width * v->height ); + pthread_mutex_init( &(v->mutex), NULL ); + + return v; +} +#ifdef STRICT_CHECKING +static void lock__(v4lvideo_template_t *t, const char *f, int line) { + pthread_mutex_lock(&(t->mutex)); +} +static void unlock__(v4lvideo_template_t *t, const char *f, int line) { + pthread_mutex_unlock(&(t->mutex)); +} +#define lock_(t) lock__(t,__FUNCTION__,__LINE__) +#define unlock_(t) unlock__(t, __FUNCTION__ ,__LINE__) + +#else +static void lock_(v4lvideo_template_t *t) +{ + pthread_mutex_lock( &(t->mutex )); +} +static void unlock_(v4lvideo_template_t *t) +{ + pthread_mutex_unlock( &(t->mutex )); +} +#endif + +int v4lvideo_templ_get_palette( int p ) +{ + switch(p) { + case FMT_420: case FMT_420F: + return VIDEO_PALETTE_YUV420P; + case FMT_422: case FMT_422F: + return VIDEO_PALETTE_YUV422P; + default: + return -1; + } + return -1; +} + +char *v4lvideo_templ_get_norm_str( int id ) { + int i; + for( i = 0; normlists[i].type != -1; i ++ ) { + if( normlists[i].type == id ) + return normlists[i].name; + } + return "?"; +} + +int v4lvideo_templ_get_norm( const char *name ) +{ + int i; + + for(i=0; normlists[i].type != -1; i++) { + if(strcasecmp(name, normlists[i].name) == 0) { + return normlists[i].type; + } + } + + return -1; +} + +int v4lvideo_templ_getfreq( const char *name ) +{ + int i; + + for(i=0; chanlists[i].name; i++) { + if(strcmp(name, chanlists[i].name) == 0) { + return i; + } + } + + return -1; +} + +int v4lvideo_templ_num_devices() +{ + return device_count_; +} +#define VIDEO_PALETTE_JPEG 64 //fun +static struct { + const int id; + const char *name; + const int ff; +} palette_descr_[] = +{ + { VIDEO_PALETTE_JPEG, "JPEG Compressed", PIX_FMT_YUVJ420P }, + { VIDEO_PALETTE_RGB24 , "RGB 24 bit", PIX_FMT_BGR24 }, + { VIDEO_PALETTE_YUV422P , "YUV 4:2:2 Planar", PIX_FMT_YUVJ422P }, + { VIDEO_PALETTE_YUV420P , "YUV 4:2:0 Planar", PIX_FMT_YUVJ420P }, + { VIDEO_PALETTE_YUYV, "YUYV 4:2:2 Packed", PIX_FMT_YUYV422 }, + { VIDEO_PALETTE_UYVY, "UYVY 4:2:2 Packed", PIX_FMT_UYVY422 }, + { VIDEO_PALETTE_RGB32 , "RGB 32 bit", PIX_FMT_RGB32 }, + + { -1, "Unsupported colour space", -1}, +}; +//@fixme: 16-235 yuv +// +static int is_YUV(int a) { + if( a == VIDEO_PALETTE_YUV422P || + a == VIDEO_PALETTE_YUV420P || + a == VIDEO_PALETTE_YUV422 || + a == VIDEO_PALETTE_YUYV || + a == VIDEO_PALETTE_UYVY ) + return 1; + return 0; +} + +static v4lvideo_t* v4lvideo_templ_try( int num ) +{ + char *refname = (char*) vj_calloc(sizeof(char) * 100); + v4lvideo_t *v = (v4lvideo_t*) vj_calloc(sizeof(v4lvideo_t)); + if(!v || !refname) { + if(v) free(v); + if(refname) free(refname); + return NULL; + } + snprintf(refname,100,"/dev/video%d",num); + if( v4lopen(refname,&(v->vd)) ) { + free(v); + free(refname); + return NULL; + } + v4lgetcapability( &(v->vd)); + free(refname); + return v; +} + +static int get_ffmpeg_palette( int v4l ) +{ + int i = 0; + while( palette_descr_[i].id != -1 ) { + if( palette_descr_[i].id == v4l ) + return palette_descr_[i].ff; + i++; + } + return -1; +} + +static const char *get_palette_name( int v4l ) +{ + int i = 0; + while( palette_descr_[i].id != -1 ) { + if( palette_descr_[i].id == v4l ) + return palette_descr_[i].name; + i++; + } + return NULL; +} + +static int v4lvideo_fun(v4lvideo_t *v, int w, int h, int palette, int *cap_palette, int *is_jpeg_frame ) +{ + int i = 0; + int supported_palette = -1; + int native = 0; + + int is_jpeg[2] = {0,0}; +#ifdef STRICT_CHECKING + assert( v != NULL ); +#endif + while( palette_descr_[i].id != -1 ) { + if(palette_descr_[i].id == VIDEO_PALETTE_JPEG ) { + i ++; + continue; + } + + if(v4lvideo_grab_check( v, palette_descr_[i].id ) == 0 ) { + uint8_t *tmp = (uint8_t*) vj_malloc(sizeof(uint8_t) * v->video_width * v->video_height * 4 ); + veejay_msg(VEEJAY_MSG_DEBUG, "Checking if device outputs in JPEG ..."); + __v4lvideo_grabstart(v); + if(v4lvideo_syncframe(v) == 0 ) { + uint8_t *src = v4lgetaddress(&(v->vd)); + uint8_t *dst[3] = { tmp , tmp + (v->video_width*v->video_height), + tmp + (2 * v->video_width * v->video_height) }; + unsigned short *ptr = (unsigned short *)( src ); + int count = (ssize_t)((unsigned int)(ptr[0])<<3); + int len = decode_jpeg_raw( src+2, count,0,420,v->video_width,v->video_height,dst[0],dst[1],dst[2] ); + if(len >= 0 ) { + is_jpeg[0] = 1; + is_jpeg[1] = palette_descr_[i].id; + veejay_msg(VEEJAY_MSG_DEBUG, "Device outputs in JPEG, but says %s", + palette_descr_[i].name ); + supported_palette = VIDEO_PALETTE_JPEG; + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "%s seems to be okay, using it ...", palette_descr_[i].name ); + supported_palette = palette_descr_[i].id; + } + } + __v4lvideo_grabstop(v); + free(tmp); + break; + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "No support for %s", palette_descr_[i].name ); + } + i++; + } + + *cap_palette = is_jpeg[1]; + *is_jpeg_frame = is_jpeg[0]; + + return supported_palette; +} + +static v4lprocessing *v4lvideo_get_processing( v4lvideo_t *v, int w, int h, int palette, int *cap_palette ) +{ + int i = 0; + int supported_palette = -1; + int native = 0; + int arr[2] = {0,0}; + int skip = 0; + int fun = v4lvideo_fun(v, w,h,palette, &(arr[0]), &(arr[1]) ); + if( fun < 0 ) { + veejay_msg(VEEJAY_MSG_WARNING, "Frame grabcheck failed ..." ); + } else { + if( fun == VIDEO_PALETTE_JPEG ) { + veejay_msg(VEEJAY_MSG_WARNING, "Grabbing JPEG from video device"); +#ifdef STRICT_CHECKING + assert( arr[0] == 1 ); +#endif + skip = 1; + supported_palette = fun; + *cap_palette = arr[1]; + } + } + + + if(!skip) { + while( palette_descr_[i].id != -1 ) { + if(v4lvideo_grab_check( v, palette_descr_[i].id ) == 0 ) { + supported_palette = palette_descr_[i].id; + veejay_msg(VEEJAY_MSG_DEBUG, "Device supports %s", + palette_descr_[i].name ); + break; + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "No support for %s", palette_descr_[i].name ); + } + i++; + } + } + + if( supported_palette == -1 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Did not find any supported video palette"); + return NULL; + } + + v4lprocessing *p = (v4lprocessing*) vj_calloc(sizeof(v4lprocessing)); + p->src_fmt = get_ffmpeg_palette( supported_palette ); + p->dst_fmt = get_ffmpeg_palette( palette ); +#ifdef STRICT_CHECKING + assert( p->src_fmt != -1 ); + assert( p->dst_fmt != -1 ); +#endif + + int max_w = v->vd.capability.maxwidth; + int min_w = v->vd.capability.minwidth; + int max_h = v->vd.capability.maxheight; + int min_h = v->vd.capability.minheight; + + int src_w = w; + int src_h = h; + if( src_w > max_w ) src_w = max_w; else if ( src_w < min_w ) src_w = min_w; + if( src_h > max_h ) src_h = max_h; else if ( src_h < min_h ) src_h = min_h; + + p->w = src_w; + p->h = src_h; + + if( palette == supported_palette && w == p->w && h == p->h) { + veejay_msg(VEEJAY_MSG_DEBUG, "No color space conversion required for this device."); + native = 1; + } + + if( is_YUV( supported_palette )) { + p->src = yuv_yuv_template( NULL,NULL,NULL,p->w,p->h,p->src_fmt ); + } + else { + if( supported_palette != VIDEO_PALETTE_JPEG ) { + //p->src = yuv_rgb_template( NULL, p->w,p->h, p->src_fmt ); + char *swaprgb = getenv("VEEJAY_SWAP_RGB"); + if(swaprgb!=NULL) { + int val = atoi(swaprgb); + if( val == 1 ) { + if( p->src_fmt == PIX_FMT_BGR24 ) + p->src_fmt = PIX_FMT_RGB24; + else if ( p->src_fmt == PIX_FMT_RGB24 ) + p->src_fmt = PIX_FMT_BGR24; + veejay_msg(VEEJAY_MSG_DEBUG, "Swapped RGB format to %s", + (p->src_fmt==PIX_FMT_RGB24? "RGB" : "BGR" )); + } + } + p->src = yuv_rgb_template( NULL, p->w,p->h, p->src_fmt ); + } + else { + native = 2; + p->src = yuv_yuv_template( NULL, NULL,NULL, p->w, p->h, p->src_fmt ); + } + } + p->native = native; + + p->dst = yuv_yuv_template( NULL,NULL,NULL, w, h, p->dst_fmt ); + + if(!skip) + *cap_palette = supported_palette; + + veejay_msg(VEEJAY_MSG_DEBUG, + "Capture device info: %dx%d - %dx%d src=%s,dst=%s, is_YUV=%d, native =%d ", + min_w,min_h,max_w,max_h, get_palette_name(supported_palette), get_palette_name(palette), is_YUV(supported_palette), native ); + + return p; +} + +char **v4lvideo_templ_get_devices(int *num) +{ +#ifdef STRICT_CHECKING + assert( device_list_ != NULL ); +#endif + char **items = (char**) vevo_list_properties( device_list_ ); + char filename[200]; + int error = 0; + int len = 0; + int i; + if( items == NULL ) + return NULL; + + for( i = 0; items[i] != NULL ; i ++ ) { + error = vevo_property_get( device_list_,items[i], 0, NULL ); + if( error == VEVO_NO_ERROR ) + len ++; + } + + if( len == 0 ) { + free(items); + return NULL; + } + + char **result = (char**) vj_calloc(sizeof(char*) * (len+1)); + char tmp[1024]; + for( i = 0; items[i] != NULL ; i ++ ) { + error = vevo_property_get(device_list_,items[i],0,NULL); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + size_t name_len = vevo_property_element_size( device_list_, items[i], 0 ); + char *name = (char*) vj_calloc(name_len); + vevo_property_get( device_list_, items[i], 0, &name ); + snprintf(filename,sizeof(filename),"/dev/video%s",items[i]); + snprintf(tmp,sizeof(tmp),"%03d%s%03d%s",strlen(name),name,strlen(filename),filename); + result[i] = strdup(tmp); + + free(items[i]); + } + free(items); + *num = device_count_; + + return result; +} + +void v4lvideo_templ_init() +{ + device_list_ = vpn( VEVO_ANONYMOUS_PORT ); + int max = 128; + int i; + char key[64]; + for( i = 0; i < max ;i ++ ) { + v4lvideo_t *v = v4lvideo_templ_try(i); + if(!v) + continue; + char *name = v4lgetdevicename( &(v->vd)); + snprintf(key,sizeof(key), "%d",i); + int error = vevo_property_set( device_list_, key, VEVO_ATOM_TYPE_STRING, 1,&name ); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + veejay_msg(VEEJAY_MSG_DEBUG, "Detected %s as device /dev/video/%d",name,i); + device_count_ ++; + + if( i > max_device_ ) + max_device_ = i; + v4lclose( &(v->vd)); + free(v); + } + +} + + + +static int __v4lvideo_init( v4lvideo_t *v, char *file, int channel, int norm, int freq, int dst_w, int dst_h, int dst_palette ) +{ + if(file==NULL) + return -1; + + if ( v4lopen(file, &(v->vd)) ) { + //veejay_msg(0, "Unable to open capture device '%s' (no such device?)", + // file ); + return -1; + } + + v->video_file = strdup(file); + v->video_channel = channel; + v->video_norm = norm; + v->video_palette = 0; + + v4lsetdefaultnorm( &(v->vd), norm ); + v4lgetcapability( &(v->vd)); + + if( !(v->vd.capability.type & VID_TYPE_CAPTURE )) { + veejay_msg(0, "This device seems not to support video capturing."); + return -1; + } + + if( (v->vd.capability.type & VID_TYPE_TUNER )) { + v->has_tuner = 1; + v->freqtable = freq; + v->tvchannel = 0; + v4lvideo_setfreq(v,0); + } + + v->max_width = v->vd.capability.maxwidth; + v->min_width = v->vd.capability.minwidth; + v->max_height = v->vd.capability.maxheight; + v->min_height = v->vd.capability.minheight; + + int w = dst_w; + int h = dst_h; + if( w < v->min_width ) w = v->min_width ; else if ( w > v->max_width ) + w = v->max_width; + if( h < v->min_height ) h = v->min_height; else if ( h > v->max_height ) + h = v->max_height; + + v->video_width = w; + v->video_height= h; + v->video_area = w * h; + + if ( v4lmaxchannel( &(v->vd) ) ) { + if( v4lsetchannel( &(v->vd) , channel ) ) { + v4lclose(&(v->vd)); + return -1; + } + } + + if( v4lmmap( &(v->vd)) ) { + veejay_msg(0, "mmap interface is not supported by this driver."); + v4lclose(&(v->vd)); + return -1; + } + + if( v4lgrabinit( &(v->vd), v->video_width,v->video_height ) ) { + v4lclose(&(v->vd)); + return -1; + } + + + if( v->vd.mbuf.frames < 2 ) { + v4lclose( &(v->vd)); + return -1; + } + + /* detect pixel format */ + + v->info = v4lvideo_get_processing( v, dst_w, dst_h, dst_palette, &(v->video_palette) ); + if(v->info == NULL ) { + veejay_msg(0, "No support for this device."); + v4lclose(&(v->vd)); + return -1; + } + + if( v4lvideo_set_grabformat(v,v->video_palette)) { + v4lclose(&(v->vd)); + veejay_msg(0, "Can't find a supported pixelformat."); + return -1; + } + + v4lgetpicture( &(v->vd)); + + v->brightness = v->vd.picture.brightness; + v->hue = v->vd.picture.hue; + v->colour = v->vd.picture.colour; + v->contrast = v->vd.picture.contrast; + v->white = v->vd.picture.whiteness; + + veejay_memset( &(v->sws_templ), 0,sizeof(sws_template)); + v->sws_templ.flags = yuv_which_scaler(); + + v->native = v->info->native; + +#ifdef STRICT_CHECKING + assert(v->info != NULL); +#endif + + return 1; +} + +void v4lvideo_set_paused(void *vv, int pause) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + v->pause = pause; +} + +int v4lvideo_is_paused(void *vv ) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + return v->pause; +} + +int v4lvideo_is_active( void *vv ) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + if( v->v4l == NULL ) + return 0; + return v->status; +} + +void v4lvideo_destroy( void *vv ) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + if(v) { + if(v->frame_buffer ) + free(v->frame_buffer); + free(v); + v = NULL; + } +} + +static void __v4lvideo_destroy( void *vv ) +{ + v4lvideo_t *v = (v4lvideo_t*) vv; + if( v ) { + v4lmunmap( &(v->vd)); + v4lclose( &(v->vd)); + if( v->scaler ) yuv_free_swscaler( v->scaler ); + if( v->info ) { + free(v->info->dst); + free(v->info->src); + free(v->info); + } + free(v->video_file); + + free(v); + v = NULL; + } +} + +static int v4lvideo_set_grabformat( v4lvideo_t *v, int palette ) +{ + return v4lsetpalette( &(v->vd), palette ); +} + +int v4lvideo_grab_check(v4lvideo_t *v, int palette ) { + int ret=0; + v4lseterrorlevel( V4L_PERROR_NONE ); + if( v4lvideo_set_grabformat(v, palette ) ) { +#ifdef STRICT_CHECKING + veejay_msg(0,"%s: wrong palette %s", __FUNCTION__,get_palette_name( palette) ); +#endif + ret = -1; + goto VIDEOEXIT; + } + + if( v4lgrabstart( &(v->vd),0) < 0 ) { +#ifdef STRICT_CHECKING + veejay_msg(0, "%s: Unable to start grabbing.", __FUNCTION__ ); +#endif + ret = -1; + goto VIDEOEXIT; + } + ret = v4lsync( &(v->vd),0); + return ret; +VIDEOEXIT: +#ifdef STRICT_CHECKING + veejay_msg(0, "%s: Bail", __FUNCTION__ ); +#endif + v4lseterrorlevel( V4L_PERROR_ALL ); + return ret; +} + +static void __v4lvideo_draw_error_pattern(v4lvideo_template_t *v, + uint8_t *dstY, uint8_t *dstU, uint8_t *dstV) +{ + lock_(v); + veejay_memset( dstY, 0, v->len ); + veejay_memset( dstU, 128, v->uvlen ); + veejay_memset( dstV, 128, v->uvlen ); + unlock_(v); +} + +static void *v4lvideo_grabber_thread( void * vv ) +{ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + v4lvideo_template_t *i = (v4lvideo_template_t*) vv; + v4lvideo_t *v = (v4lvideo_t*) vj_calloc(sizeof(v4lvideo_t)); + i->v4l = (void*) v; + + if( __v4lvideo_init( v, i->filename, i->channel, i->norm,i->frequency, i->width, i->height, i->palette ) < 0 ) { + veejay_msg(0, "Unable to open capture device '%s' in %dx%d - %s", + i->filename, v->video_width,v->video_height,get_palette_name(v->video_palette) ); + i->error = 1; +#ifdef STRICT_CHECKING + veejay_msg(0,"%s: Giving up, unable to open %s, channel %d, norm %x, %dx%d palette %x", + __FUNCTION__, i->filename , i->channel, i->norm, i->width, i->height, i->palette ); +#endif + pthread_exit(NULL); + return NULL; + } + + veejay_msg(VEEJAY_MSG_INFO, "Capture device looks ready to go!"); + v4lprint( &(v->vd)); + +/* if( __v4lvideo_grabstart( v ) != 0 ) { + veejay_msg(0, "Unable to start grabbing from device '%s'", i->filename); + pthread_exit(NULL); + return NULL; + }*/ + + uint8_t *dstY = i->frame_buffer; + uint8_t *dstU = i->frame_buffer + v->info->dst->len; + uint8_t *dstV = i->frame_buffer + v->info->dst->len + v->info->dst->uv_len; + + v->active = 1; + int retry = 4; + int flag = 0; + + veejay_msg(VEEJAY_MSG_DEBUG, "Capture device thread enters inner loop"); +RESTART: + while( v->active ) { +PAUSED: + if( i->pause ) { + lock_(i); + if(v->grabbing) { + __v4lvideo_grabstop( v ); + } + unlock_(i); + usleep( 20000 ); + goto PAUSED; + } else { + if(!v->grabbing) { + lock_(i); + veejay_msg(VEEJAY_MSG_DEBUG, "Trying to start capturing."); + __v4lvideo_grabstart(v); + unlock_(i); + goto RESTART; + } + } + + + if(v->grabbing) { + flag = v4lvideo_syncframe(v); + + if(flag==0) { + __v4lvideo_copy_framebuffer_to( v,i, dstY, dstU, dstV ); + } + + if(flag == -1) { + if( retry == 0 ) { + veejay_msg(0,"Giving up on this device."); + v->active = 0; + goto CAPTURE_STOP; + } else { + veejay_msg(0,"Error syncing frame from capture device!"); + retry --; + } + } + + v4lvideo_grabframe(v); + goto RESTART; + } + + +/* + if(!v->grabbing || flag < 0 ) { + __v4lvideo_draw_error_pattern( i, dstY, dstU,dstV ); + }*/ + } + if(v->grabbing) + __v4lvideo_grabstop(v); +CAPTURE_STOP: + v4lvideo_destroy(v); + + veejay_msg(0, "Stopped grabbing from device '%s'", i->filename); + i->status = 0; + pthread_exit(NULL); + return NULL; +} +int v4lvideo_grabstop( void *vv ) +{ + v4lvideo_template_t *t = (v4lvideo_template_t*) vv; + lock_( vv ); + v4lvideo_t *v = (v4lvideo_t*) t->v4l; + v->active = 0; + unlock_(vv); + t->status = 0; + return 0; +} + +int v4lvideo_grabstart( void *vv ) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + pthread_attr_init(&(v->attr) ); + pthread_attr_setdetachstate(&(v->attr), PTHREAD_CREATE_DETACHED ); + + int err = pthread_create( &(v->thread), NULL, + v4lvideo_grabber_thread, v ); + + pthread_attr_destroy( &(v->attr) ); + + if( err == 0 ) + { + v->status = 1; + return 0; + } + return -1; +} + +static int __v4lvideo_grabstart( void *vv ) +{ + v4lvideo_t *v = (v4lvideo_t*) vv; +#ifdef STRICT_CHECKING + void *ptr = (void*) &(v->vd); + assert( ptr != NULL ); + assert( v->video_width > 0 ); + assert( v->video_height > 0 ); +// assert( v->info != NULL ); +#endif + + v->vd.frame = 0; + if( v4lgrabstart( &(v->vd), 0 ) < 0 ) { + veejay_msg(0, "Failed to grab frame 0"); + return -1; + } + if( v4lgrabstart( &(v->vd), 1 ) < 0 ) { + veejay_msg(0, "Failed to grab frame 1"); + return -1; + } + v->grabbing = 1; + return 0; +} + +static int __v4lvideo_grabstop( void *vv ) +{ + v4lvideo_t *v = (v4lvideo_t*) vv; + if( v->vd.framestat[v->vd.frame] ) { + if(v4lsync( &(v->vd), v->vd.frame ) < 0 ) + return -1; + } + if( v->vd.framestat[v->vd.frame ^ 1 ]) { + if(v4lsync( &(v->vd), v->vd.frame ^ 1 ) < 0 ) + return -1; + } + v->grabbing = 0; + return 0; +} + +int v4lvideo_syncframe(void *vv) +{ + v4lvideo_t *v = (v4lvideo_t*) vv; + return v4lsyncf( &(v->vd)); +} + +int v4lvideo_grabframe( void *vv ) +{ + v4lvideo_t *v = (v4lvideo_t*) vv; + return v4lgrabf( &(v->vd)); +} + +int v4lvideo_copy_framebuffer_to( void *vv, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV ) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + if(!v->status) { + return -1; + } + + lock_(v); + if(!v->v4l ) { + unlock_(v); + return 0; + } +#ifdef STRICT_CHECKING + assert( v->v4l != NULL ); +#endif + v4lvideo_t *v1 = (v4lvideo_t*) v->v4l; + if( v1->has_video ) { + uint8_t *src = v->frame_buffer; + veejay_memcpy( dstY, src, v->len ); + veejay_memcpy( dstU, src+v->len, v->uvlen ); + veejay_memcpy( dstV, src+v->len + v->uvlen, v->uvlen ); + } else { + // damage per second: some devices need a *long* time to settle + if( (v1->dps%25)== 1 && v->error == 0) + veejay_msg(VEEJAY_MSG_INFO, "Capture device is initializing, just a moment ..."); + v1->dps++; + unlock_(v); + return 0; + } + unlock_(v); + return 1; +} + +static void __v4lvideo_copy_framebuffer_to(v4lvideo_t *v1, v4lvideo_template_t *v2, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV ) +{ + uint8_t *src = NULL; +#ifdef STRICT_CHECKING + assert(v1->info != NULL ); +#endif + if( v1->native == 1 ) { + src = v4lgetaddress(&(v1->vd)); + /* lock_(v2); + uint8_t *srcin[3] = { src, src + v2->len, src + v2->len + v2->uvlen }; + uint8_t *dstout[3]= { dstY,dstU,dstV }; + if( yuv_use_auto_ccir_jpeg() ) { + yuv_scale_pixels_from_ycbcr2( srcin, dstout,v2->len ); + } else { + veejay_memcpy( dstY, src, v2->len ); + veejay_memcpy( dstU, src + v2->len, v2->uvlen); + veejay_memcpy( dstV, src + v2->len + v2->uvlen, v2->uvlen ); + }*/ + VJFrame *srcf = v1->info->src; + VJFrame *dstf = v1->info->dst; + dstf->data[0] = dstY; + dstf->data[1] = dstU; + dstf->data[2] = dstV; + if(!v1->scaler) + v1->scaler = + yuv_init_swscaler( srcf,dstf,&(v1->sws_templ), yuv_sws_get_cpu_flags()); + lock_(v2); + yuv_convert_and_scale( v1->scaler, srcf, dstf ); + v1->has_video = 1; + + unlock_(v2); + + } else if ( v1->native == 2 ) { + src = v4lgetaddress(&(v1->vd)); + // lock_(v2); + uint8_t *tmp[3] = { + v2->temp_buffer, + v2->temp_buffer + v2->len , + v2->temp_buffer + v2->len + v2->len }; + uint8_t *dst[3] = { dstY, dstU, dstV }; + VJFrame *srcf = v1->info->src; + VJFrame *dstf = v1->info->dst; + unsigned short *ptr = (unsigned short *)( src ); + int count = (ssize_t)((unsigned int)(ptr[0])<<3); + int len = decode_jpeg_raw( src+2, count,0,420,srcf->width,srcf->height,tmp[0],tmp[1],tmp[2] ); + //420 dat + if(!v1->scaler) + v1->scaler = + yuv_init_swscaler( srcf,dstf,&(v1->sws_templ), yuv_sws_get_cpu_flags()); + + dstf->data[0] = dstY; + dstf->data[1] = dstU; + dstf->data[2] = dstV; + srcf->data[0] = tmp[0]; + srcf->data[1] = tmp[1]; + srcf->data[2] = tmp[2]; + lock_(v2); + yuv_convert_and_scale( v1->scaler, srcf, dstf ); + v1->has_video = 1; + + unlock_(v2); + } else { + VJFrame *srcf = v1->info->src; + VJFrame *dstf = v1->info->dst; + + dstf->data[0] = dstY; + dstf->data[1] = dstU; + dstf->data[2] = dstV; + +/* if( is_YUV( v1->video_palette ) ) { + src = v4lgetaddress(&(v1->vd)); + srcf->data[0] = src; + srcf->data[1] = src + srcf->len; + srcf->data[2] = src + srcf->len + srcf->uv_len; +#ifdef STRICT_CHECKING + assert(0); +#endif + + } else {*/ + srcf->data[0] = v4lgetaddress(&(v1->vd)); + if(!v1->scaler) + v1->scaler = + yuv_init_swscaler( srcf,dstf,&(v1->sws_templ), yuv_sws_get_cpu_flags()); + + lock_(v2); + yuv_convert_and_scale_from_rgb( v1->scaler, srcf, dstf ); + v1->has_video = 1; + + unlock_(v2); + // } + } +// v1->has_video = 1; +} + + +int v4lvideo_setfreq( void *vv, int f ) +{ + v4lvideo_t *v = (v4lvideo_t*) vv; + if(v->has_tuner && (v->freqtable >= 0 ) ) { + v->tvchannel += f; + while( v->tvchannel < 0 ) { + v->tvchannel += chanlists[v->freqtable].count; + } + v->tvchannel %= chanlists[v->freqtable].count; + + return v4lsetfreq( &(v->vd), chanlists[v->freqtable].list[v->tvchannel].freq ); + } + return 0; +} +#define MAXVAL 65535 +int v4lvideo_get_brightness( void *vvv ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + return v->brightness; +} +int v4lvideo_get_hue( void *vvv ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + return v->hue; +} +int v4lvideo_get_colour( void *vvv ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + return v->colour; +} +int v4lvideo_get_contrast( void *vvv ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + return v->contrast; +} +int v4lvideo_get_white(void *vvv) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + return v->white; +} + + +void v4lvideo_set_brightness( void *vvv, int x ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + if( x < 0 ) v = 0; else if ( x > MAXVAL ) x = MAXVAL; + + v->brightness = x; + v4lsetpicture( &(v->vd), v->brightness,-1,-1,-1,-1); +} +void v4lvideo_set_hue( void *vvv, int x ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + if( x < 0 ) x = 0; else if (x > MAXVAL ) x = MAXVAL; + + v->hue = x; + v4lsetpicture( &(v->vd), -1,v->hue,-1,-1,-1); +} +void v4lvideo_set_colour( void *vvv, int x ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + if( x < 0 ) x = 0; else if ( x > MAXVAL ) x = MAXVAL; + + v->colour = x; + v4lsetpicture( &(v->vd), -1,-1,v->colour,-1,-1); +} +void v4lvideo_set_contrast( void *vvv, int x ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + if( x < 0 ) x = 0; else if ( x > MAXVAL ) x = MAXVAL; + + v->contrast = x; + v4lsetpicture( &(v->vd), -1,-1,-1,v->contrast,-1); +} +void v4lvideo_set_white( void *vvv, int x ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + if( x < 0 ) x = 0; else if ( x > MAXVAL ) x = MAXVAL; + + v->contrast = x; + v4lsetpicture( &(v->vd), -1,-1,-1,-1, x); +} + + +int v4lvideo_change_channel( void *vvv, int channel ) +{ + v4lvideo_template_t *vv = (v4lvideo_template_t*) vvv; + v4lvideo_t *v = (v4lvideo_t*) vv->v4l; + int ret = 0; + int maxch; + + maxch = v4lmaxchannel( &(v->vd)); + if( channel < 0 ) channel = 0; + if( channel > maxch ) channel = maxch; + + v4lvideo_grabstop( vv ); + if( v4lsetchannel( &(v->vd), channel ) ) ret = -1; + v->video_channel = channel; + v4lvideo_grabstart(vv); + return ret; +} + +void v4lvideo_set_composite_status( void *vv, int status ) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + v->composite = status; +} + +int v4lvideo_get_composite_status( void *vv) +{ + v4lvideo_template_t *v = (v4lvideo_template_t*) vv; + return v->composite; +} + diff --git a/branches/V-1.5.3/veejay-server/libstream/v4lvideo.h b/branches/V-1.5.3/veejay-server/libstream/v4lvideo.h new file mode 100644 index 00000000..ed27c01c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/v4lvideo.h @@ -0,0 +1,68 @@ +/* + * Linux VeeJay + * V4l1 driver , classic stuff + * Copyright(C)2008 Niels Elburg + * uses v4lutils - utility library for Video4Linux + * Copyright (C) 2001-2002 FUKUCHI Kentaro + + * 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 + */ + + + +#ifndef KENTARO_V4L_UTILS +#define KENTARO_V4L_UTILS +int v4lvideo_is_paused(void *vv ); +void v4lvideo_set_paused(void *vv, int pause); +int v4lvideo_templ_get_norm( const char *name ); +int v4lvideo_templ_getfreq( const char *name ); +int v4lvideo_templ_num_devices(); +int v4lvideo_templ_get_palette( int p ); +char *v4lvideo_templ_get_norm_str(int id ); + +char **v4lvideo_templ_get_devices(int *num); + +void *v4lvideo_init( char* file, int channel, int norm, int freq, int w, int h, int palette ); +void v4lvideo_destroy( void *vv ); + +int v4lvideo_grabstart( void *vv ); + +int v4lvideo_grabstop( void *vv ); +int v4lvideo_syncframe(void *vv); +int v4lvideo_grabframe( void *vv ); +//uint8_t *v4lvideo_getaddress( void *vv ); +int v4lvideo_copy_framebuffer_to( void *vv, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV ); + +int v4lvideo_setfreq( void *vv, int f ); + +int v4lvideo_get_brightness( void *vv ); +int v4lvideo_get_hue( void *vv ); +int v4lvideo_get_colour( void *vv ); +int v4lvideo_get_contrast( void *vv ); +int v4lvideo_get_white(void *vv); +void v4lvideo_set_brightness( void *vv, int x ); +void v4lvideo_set_hue( void *vv, int x ); +void v4lvideo_set_colour( void *vv, int x ); +void v4lvideo_set_constrast( void *vv, int x ); +void v4lvideo_set_white(void *vv, int x ); + +int v4lvideo_change_channel( void *vv, int channel ); + +// veejay specific +void v4lvideo_set_composite_status( void *vv, int status ); +int v4lvideo_get_composite_status( void *vv ); + + +#endif + diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-dv1394.c b/branches/V-1.5.3/veejay-server/libstream/vj-dv1394.c new file mode 100644 index 00000000..ac7e512f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-dv1394.c @@ -0,0 +1,229 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +/* + inspired by ffmpeg/ffmpeg/libavformat/dv1394.c + dv1394 has no audio apparently ... +*/ +#include +#include +#include +#include +#ifdef SUPPORT_READ_DV2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define DV_PAL_SIZE 144000 +#define DV_NTSC_SIZE 120000 + + +#define DV1394_DEFAULT_CHANNEL 63 +#define DV1394_DEFAULT_CARD 0 +#define DV1394_RING_FRAMES 10 + +static int vj_dv1394_reset(vj_dv1394 *v ) +{ + struct dv1394_init init; + init.channel = v->channel; + init.api_version = DV1394_API_VERSION; + init.n_frames = DV1394_RING_FRAMES; + init.format = v->norm; + + if( ioctl( v->handle, DV1394_INIT, &init ) < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot initialize ieee1394 device"); + return 0; + } + v->done = v->avail = 0; + return 1; +} + +static int vj_dv1394_start(vj_dv1394 *v ) +{ + /* enable receiver */ + if( ioctl( v->handle, DV1394_START_RECEIVE, 0) < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot start receiver"); + return 0; + } + return 1; +} + +vj_dv1394 *vj_dv1394_init(void *e, int channel, int quality) +{ + editlist *el = (editlist*)e; + + if(el->video_width != 720 && ( el->video_height != 576 || el->video_height != 480) ) + { + veejay_msg(VEEJAY_MSG_ERROR, "No software scaling to %d x %d",el->video_width, + el->video_height); + return NULL; + } + + vj_dv1394 *v = (vj_dv1394*)vj_malloc(sizeof(vj_dv1394)); + + v->map_size = (el->video_norm == 'p' ? DV_PAL_SIZE: DV_NTSC_SIZE); + v->handle = -1; + v->width = el->video_width; + v->height = el->video_height; + v->norm = (el->video_norm == 'p' ? DV1394_PAL: DV1394_NTSC ); + v->handle = open( "/dev/dv1394", O_RDONLY); + v->channel = channel == -1 ? DV1394_DEFAULT_CHANNEL : channel; + v->index = 0; + v->quality = quality; + if( v->handle <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "opening /dev/dv1394'"); + if(v) free(v); + return NULL; + } + if( vj_dv1394_reset(v) <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to initialize DV interface"); + close(v->handle); + if(v) free(v); + return NULL; + } + + v->map = mmap( NULL, v->map_size * DV1394_RING_FRAMES, PROT_READ, + MAP_PRIVATE, v->handle, 0); + if(v->map == MAP_FAILED) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to mmap dv ring buffer"); + close(v->handle); + if(v)free(v); + return NULL; + } + if( vj_dv1394_start(v) <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to start capturing"); + if(v)free(v); + close(v->handle); + return NULL; + } + + + v->decoder = (void*)vj_dv_decoder_init( v->quality,v->width,v->height, el->pixel_format ); + if(!v->decoder) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to initailize DV decoder"); + } + + return v; +} + + +void vj_dv1394_close(vj_dv1394 *v) +{ + if(v) + { + if( ioctl( v->handle, DV1394_SHUTDOWN, 0) < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to shutdown dv1394"); + } + if( munmap( v->map, v->map_size * DV1394_RING_FRAMES ) < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to munmap dv1394 ring buffer"); + } + close(v->handle); + if(v->decoder) + vj_dv_free_decoder( (vj_dv_decoder*) v->decoder ); + free(v); + } + +} + +int vj_dv1394_read_frame(vj_dv1394 *v, uint8_t *frame[3], uint8_t *audio, int fmt) +{ + if( !v->avail ) + { + struct dv1394_status s; + struct pollfd p; + if( v->done ) + { + /* request more frames */ + if( ioctl( v->handle, DV1394_RECEIVE_FRAMES, v->done ) < 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Ring buffer overflow,reset"); + vj_dv1394_reset( v ); + vj_dv1394_start( v ); + } + v->done = 0; + } + +restart_poll: + p.fd = v->handle; + p.events = POLLIN | POLLERR | POLLHUP; + if( poll(&p, 1, -1 ) < 0 ) + { + if( errno == EAGAIN || errno == EINTR ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Waiting for DV"); + goto restart_poll; + } + veejay_msg(VEEJAY_MSG_ERROR, "Poll failed"); + return 0; + } + + if( ioctl( v->handle, DV1394_GET_STATUS, &s ) < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to get status"); + return 0; + } + s.active_frame, s.first_clear_frame, + + v->avail = s.n_clear_frames; + v->index = s.first_clear_frame; + v->done = 0; + + if( s.dropped_frames ) + { + veejay_msg(VEEJAY_MSG_ERROR, "dv1394: frame drop detected %d", + s.dropped_frames); + // vj_dv1394_reset( v ); + // vj_dv1394_start( v ); + } + } + + if(!vj_dv_decode_frame( + (vj_dv_decoder*) v->decoder, + v->map + (v->index * v->map_size), + frame[0],frame[1],frame[2], + v->width, + v->height, fmt )) + { + veejay_msg(VEEJAY_MSG_ERROR, "decoding DV frame"); + return 0; + } + + v->index = (v->index + 1) % DV1394_RING_FRAMES; + v->done ++ ; + v->avail --; + + return 1; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-dv1394.h b/branches/V-1.5.3/veejay-server/libstream/vj-dv1394.h new file mode 100644 index 00000000..a7eb641f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-dv1394.h @@ -0,0 +1,46 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ + +#ifndef VJDV1394 +#define VJDV1394 + + +typedef struct +{ + int handle; + int map_size; + uint8_t *map; + int width; + int height; + int channel; + int norm; + int avail; + int done; + int index; + int quality; + void *decoder; +} vj_dv1394; + +vj_dv1394* vj_dv1394_init(void *el, int channel_nr, int quality); + +void vj_dv1394_close( vj_dv1394 *v ); + +int vj_dv1394_read_frame( vj_dv1394 *v, uint8_t *frame[3] , uint8_t *audio, int fmt ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-net.c b/branches/V-1.5.3/veejay-server/libstream/vj-net.c new file mode 100644 index 00000000..611364eb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-net.c @@ -0,0 +1,437 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2006 Niels Elburg + * + * 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 + */ + +#define THREAD_START 0 +#define THREAD_STOP 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define _POSIX_C_SOURCE 199309 +#include + + +#ifdef STRICT_CHECKING +#include +#endif +typedef struct +{ + pthread_mutex_t mutex; + pthread_t thread; + vj_client *remote; + int state; + int have_frame; + int error; + int grab; + int repeat; +} threaded_t; + +static void lock_(threaded_t *t, const char *f, int line) +{ +// veejay_msg(0,"lock thread by %s, line %d",f,line); + pthread_mutex_lock( &(t->mutex )); +} + +static void unlock_(threaded_t *t, const char *f, int line) +{ +// veejay_msg(0,"unlock thread by %s, line %d",f,line); + pthread_mutex_unlock( &(t->mutex )); +} + +#define lock( t ) lock_( t, __FUNCTION__, __LINE__ ) +#define unlock( t ) unlock_( t, __FUNCTION__ , __LINE__ ) + +#define MS_TO_NANO(a) (a *= 1000000) +static void net_delay(long nsec, long sec ) +{ + struct timespec ts; + ts.tv_sec = sec; + ts.tv_nsec = MS_TO_NANO( nsec); + nanosleep( &ts, NULL ); +} + + +void *reader_thread(void *data) +{ + vj_tag *tag = (vj_tag*) data; + threaded_t *t = tag->priv; + vj_client *v = t->remote; + int ret = 0; + char buf[16]; +#ifdef STRICT_CHECKING + assert( v != NULL ); +#endif + + sprintf(buf, "%03d:;", VIMS_GET_FRAME); + + int retrieve = 0; + + for( ;; ) + { + int error = 0; + int pollres = 0; + int res = 0; + if( t->state == 0 ) + { + vj_client_close(v); + pthread_exit( &(t->thread)); + return NULL; + } + + lock(t); + + if( t->grab && tag->source_type == VJ_TAG_TYPE_NET && retrieve == 0 ) { + ret = vj_client_send( v, V_CMD, buf ); + if( ret < 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, + "%s:%d failed to query frame", + tag->source_name, + tag->video_channel ); + + error = 1; + } + else + { + t->grab = 0; + } + } + + if( tag->source_type == VJ_TAG_TYPE_NET ) + { + res = vj_client_poll(v, V_CMD ); + if( ret ) + { + retrieve = 1; + } else if ( ret < 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, + "%s:%d failed to poll frame", + tag->source_name, + tag->video_channel ); + error = 1; + } + + } else if (tag->source_type == VJ_TAG_TYPE_MCAST ) + { + error = 0; + retrieve = 1; + res = 1; + } + + long wait_time = 20; + + if(!error && retrieve) + { + if( res ) + { + ret = vj_client_read_i ( v, tag->socket_frame,tag->socket_len ); + if( ret <= 0 ) + { + // if( tag->source_type == VJ_TAG_TYPE_NET ) + // { + veejay_msg(VEEJAY_MSG_DEBUG, + "%s:%d failed to read frame", + tag->source_name, + tag->video_channel ); + error = 1; + // } + // else + // { + // wait_time += 10; + // } + ret = 0; + } + else + { + t->have_frame = ret; + t->grab = 1; + retrieve =0; + } + } + else + { + if(tag->source_type == VJ_TAG_TYPE_MCAST ) + wait_time = 25; + } + } + unlock(t); + + if( wait_time ) + { + if ( wait_time > 40 ) + wait_time = 15; + net_delay( wait_time,0 ); + wait_time = 0; + } + + if( error ) + { + int success = 0; + vj_client_close( v ); + + net_delay( 0,3 ); + + if(tag->source_type == VJ_TAG_TYPE_MCAST ) + success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel ); + else + success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); + + if( success <= 0 ) + { + wait_time = 4000; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Tried to connect to %s:%d code=%d", tag->source_name,tag->video_channel,success); +#endif + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Connecton re-established with %s:%d",tag->source_name, + tag->video_channel + 5); + } + + t->grab = 0; + retrieve = 0; + } + } + return NULL; +} + + + +void *net_threader( ) +{ + threaded_t *t = (threaded_t*) vj_calloc(sizeof(threaded_t)); + return (void*) t; +} + +int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] ) +{ + threaded_t *t = (threaded_t*) tag->priv; + vj_client *v = t->remote; + const uint8_t *buf = tag->socket_frame; + + lock(t); + if( t->state == 0 || t->error ) + { + if(t->repeat < 0) + veejay_msg(VEEJAY_MSG_INFO, "Connection closed with remote host"); + t->repeat++; + unlock(t); + return 0; + } + + //@ color space convert frame + int len = v->cur_width * v->cur_height; + int uv_len = len; + switch(v->cur_fmt) + { + case FMT_420: + case FMT_420F: + uv_len=len/4; + break; + default: + uv_len=len/2; + break; + } + + if(t->have_frame == 1 ) + { + veejay_memcpy(buffer[0], tag->socket_frame, len ); + veejay_memcpy(buffer[1], tag->socket_frame+len, uv_len ); + veejay_memcpy(buffer[2], tag->socket_frame+len+uv_len, uv_len ); + t->grab = 1; + unlock(t); + return 1; + } + else if(t->have_frame == 2 ) + { + int b_len = v->in_width * v->in_height; + int buvlen = b_len; + switch(v->in_fmt) + { + case FMT_420: + case FMT_420F: + buvlen = b_len/4; + break; + default: + buvlen = b_len/2; + break; + } + + int tmp_fmt = get_ffmpeg_pixfmt( v->in_fmt ); + + VJFrame *a = yuv_yuv_template( tag->socket_frame, tag->socket_frame + b_len, tag->socket_frame+b_len+buvlen, + v->in_width,v->in_height, tmp_fmt); + VJFrame *b = yuv_yuv_template( buffer[0],buffer[1], buffer[2], + v->cur_width,v->cur_height,get_ffmpeg_pixfmt(v->cur_fmt)); + yuv_convert_any_ac(a,b, a->format,b->format ); + free(a); + free(b); + } + t->grab = 1; + + unlock(t); + return 1; +} + +int net_thread_start(vj_client *v, vj_tag *tag) +{ + int success = 0; + int res = 0; + + if(tag->source_type == VJ_TAG_TYPE_MCAST ) + success = vj_client_connect( v,NULL,tag->source_name,tag->video_channel ); + else + success = vj_client_connect_dat( v, tag->source_name,tag->video_channel ); + + if( success <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to establish connection with %s on port %d", + tag->source_name, tag->video_channel + 5); + return 0; + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Connecton established with %s:%d",tag->source_name, + tag->video_channel + 5); + } + + threaded_t *t = (threaded_t*)tag->priv; + + pthread_mutex_init( &(t->mutex), NULL ); + v->lzo = lzo_new(); + t->repeat = 0; + t->have_frame = 0; + t->error = 0; + t->state = 1; + t->remote = v; + t->grab = 1; + + + if( tag->source_type == VJ_TAG_TYPE_MCAST ) + { + char start_mcast[8]; + + int gs = 0; + char *gs_str = getenv( "VEEJAY_MCAST_GREYSCALE" ); + if( gs_str ) { + gs = atoi(gs_str); + if(gs < 0 || gs > 1 ) + gs = 0; + } + + snprintf(start_mcast,sizeof(start_mcast), "%03d:%d;", VIMS_VIDEO_MCAST_START,gs); + + veejay_msg(VEEJAY_MSG_DEBUG, "Request mcast stream from %s port %d", + tag->source_name, tag->video_channel); + + res = vj_client_send( v, V_CMD, start_mcast ); + if( res <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to send to %s port %d", + tag->source_name, tag->video_channel ); + return 0; + } + else + veejay_msg(VEEJAY_MSG_INFO, "Requested mcast stream from Veejay group %s port %d", + tag->source_name, tag->video_channel ); + } + int p_err = pthread_create( &(t->thread), NULL, &reader_thread, (void*) tag ); + if( p_err ==0) + + { + veejay_msg(VEEJAY_MSG_INFO, "Created new %s threaded stream with Veejay host %s port %d", + tag->source_type == VJ_TAG_TYPE_MCAST ? + "multicast" : "unicast", tag->source_name,tag->video_channel); + return 1; + } + + return 0; +} + +void net_thread_stop(vj_tag *tag) +{ + char mcast_stop[6]; + threaded_t *t = (threaded_t*)tag->priv; + int ret = 0; + lock(t); + + if(tag->source_type == VJ_TAG_TYPE_MCAST) + { + sprintf(mcast_stop, "%03d:;", VIMS_VIDEO_MCAST_STOP ); + ret = vj_client_send( t->remote , V_CMD, mcast_stop); + if(ret) + veejay_msg(VEEJAY_MSG_INFO, "Stopped multicast stream"); + } + if(tag->source_type == VJ_TAG_TYPE_NET) + { + sprintf(mcast_stop, "%03d:;", VIMS_CLOSE ); + ret = vj_client_send( t->remote, V_CMD, mcast_stop); + if(ret) + veejay_msg(VEEJAY_MSG_INFO, "Stopped unicast stream"); + } + + t->state = 0; + + unlock(t); + + pthread_mutex_destroy( &(t->mutex)); + + veejay_msg(VEEJAY_MSG_INFO, "Disconnected from Veejay host %s:%d", tag->source_name, + tag->video_channel); +} + +int net_already_opened(const char *filename, int n, int channel) +{ + char sourcename[255]; + int i; + for (i = 1; i < n; i++) + { + if (vj_tag_exists(i) ) + { + vj_tag_get_source_name(i, sourcename); + if (strcasecmp(sourcename, filename) == 0) + { + vj_tag *tt = vj_tag_get( i ); + if( tt->source_type == VJ_TAG_TYPE_NET || tt->source_type == VJ_TAG_TYPE_MCAST ) + { + if( tt->video_channel == channel ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Already streaming from %s:%p in stream %d", + filename,channel, tt->id); + return 1; + } + } + } + } + } + return 0; +} + + + diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-net.h b/branches/V-1.5.3/veejay-server/libstream/vj-net.h new file mode 100644 index 00000000..1734c6c2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-net.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2006 Niels Elburg + * + * 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 + */ + +#ifndef NETINSTR_HH +#define NETINSTR_HH + +int net_already_opened(const char *filname, int n, int chan); +void net_thread_stop(vj_tag *tag); +int net_thread_start(vj_client *v, vj_tag *tag); +void net_thread_remote(void *priv, void *p ); +int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3]); + +void net_thread_exit(vj_tag *tag); +void *net_threader( ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-tag.c b/branches/V-1.5.3/veejay-server/libstream/vj-tag.c new file mode 100644 index 00000000..81b5b3ce --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-tag.c @@ -0,0 +1,4097 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#define VIDEO_PALETTE_YUV420P 15 +#define VIDEO_PALETTE_YUV422P 13 + +#ifdef USE_GDK_PIXBUF +#include +#endif + +#ifdef SUPPORT_READ_DV2 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNICAP +#include +#endif +#include +#include +#ifdef HAVE_FREETYPE +#include +#endif +#include + +static veejay_t *_tag_info = NULL; +static hash_t *TagHash = NULL; +static int this_tag_id = 0; +static vj_tag_data *vj_tag_input; +static int next_avail_tag = 0; +static int avail_tag[SAMPLE_MAX_SAMPLES]; +static int last_added_tag = 0; +static int video_driver_ = -1; // V4lUtils +#ifdef HAVE_UNICAP +static void *unicap_data_= NULL; +#endif +//forward decl + +int _vj_tag_new_net(vj_tag *tag, int stream_nr, int w, int h,int f, char *host, int port, int p, int ty ); +int _vj_tag_new_yuv4mpeg(vj_tag * tag, int stream_nr, editlist * el); + +extern void dummy_rgb_apply(VJFrame *frame, int width, int height, int r, int g, int b); +extern int sufficient_space(int max_size, int nframes); +extern unsigned char *UTF8toLAT1(unsigned char *in); + +typedef struct +{ + uint8_t *data; + uint8_t *bf; + uint8_t *lf; + uint8_t *mf; + int uv_len; + int len; + double mean[3]; +} cali_tag_t; + +#define CALI_DARK 0 +#define CALI_LIGHT 1 +#define CALI_FLAT 2 +#define CALI_BUF 4 +#define CALI_MFLAT 3 + +static uint8_t *cali_get(vj_tag *tag, int type, int len, int uv_len ) { + uint8_t *p = tag->blackframe; + switch(type) { + case CALI_DARK: + return p; //@ start of dark current + case CALI_LIGHT: + return p + (len + (2*uv_len)); //@ start of light frame + case CALI_FLAT: + return p + (2*(len + (2*uv_len))); //@ start of master frame + case CALI_MFLAT: + return p + (3*(len + (2*uv_len))); //@ processing buffer + case CALI_BUF: + return p + (4*(len + (2*uv_len))); + } + return NULL; +} + +static uint8_t *_temp_buffer[3]={NULL,NULL,NULL}; +static VJFrame _tmp; +void vj_tag_free(void) +{ + int i; + for( i = 0; i < 3 ; i ++ ) + { + if( _temp_buffer[i] ) + free( _temp_buffer[i] ); + _temp_buffer[i] = NULL; + } + + vj_tag_close_all(); + + if( vj_tag_input) + free(vj_tag_input); + +#ifdef HAVE_UNICAP + vj_unicap_deinit(unicap_data_); +#endif +} + + + + +int vj_tag_get_last_tag() { + return last_added_tag; +} + +int vj_tag_true_size() +{ + return (this_tag_id - next_avail_tag); +} + + +int vj_tag_size() +{ + return this_tag_id; +} + +void vj_tag_set_veejay_t(void *info) { + _tag_info = (veejay_t*)info; +} + +static hash_val_t int_tag_hash(const void *key) +{ + return (hash_val_t) key; +} + +static int int_tag_compare(const void *key1, const void *key2) +{ + return ((int) key1 < (int) key2 ? -1 : + ((int) key1 > (int) key2 ? +1 : 0) + ); + +} + +vj_tag *vj_tag_get(int id) +{ + if (id <= 0 || id > this_tag_id) { + return NULL; + } + hnode_t *tag_node = hash_lookup(TagHash, (void *) id); + if (!tag_node) { + return NULL; + } + return (vj_tag *) hnode_get(tag_node); +} + +int vj_tag_put(vj_tag * tag) +{ + hnode_t *tag_node; + if (!tag) + return 0; + tag_node = hnode_create(tag); + if (!tag_node) + return 0; + + + if (!vj_tag_exists(tag->id)) { + hash_insert(TagHash, tag_node, (void *) tag->id); + } else { + hnode_put(tag_node, (void *) tag->id); + hnode_destroy(tag_node); + + } + return 1; +} + +static int vj_tag_update(vj_tag *tag, int id) { + if(tag) { + hnode_t *tag_node = hnode_create(tag); + if(!tag_node) return -1; + hnode_put(tag_node, (void*) id); + hnode_destroy(tag_node); + return 1; + } + return -1; +} + +int vj_tag_num_devices() +{ +#ifdef HAVE_UNICAP + return vj_unicap_num_capture_devices( unicap_data_ ); +#else + return v4lvideo_templ_num_devices(); +#endif +} + +char *vj_tag_scan_devices( void ) +{ + const char *default_str = "000000"; + int num = 0; + int i; + int len = 6; +#ifdef HAVE_UNICAP + char **device_list = vj_unicap_get_devices(unicap_data_, &num); +#else + char **device_list = v4lvideo_templ_get_devices(&num); +#endif + if(!device_list) + return strdup(default_str); + + for( i = 0; device_list[i] != NULL ;i++ ) + len += strlen( device_list[i] ); + + char *n = (char*) vj_calloc(sizeof(char) * (len+1) ); + char *p = n + 6; + + sprintf(n, "%06d", (len-6) ); + for( i = 0; device_list[i] != NULL ;i++ ) + { + int str_len = strlen(device_list[i]); + veejay_memcpy( p, device_list[i], str_len); + p += str_len; + free(device_list[i]); + } + free(device_list); + return n; +} + +int vj_tag_get_width() { + return vj_tag_input->width; +} +int vj_tag_get_height() { + return vj_tag_input->height; +} +int vj_tag_get_uvlen() { + return vj_tag_input->uv_len; +} + +int vj_tag_init(int width, int height, int pix_fmt, int video_driver) +{ + int i; + TagHash = hash_create(HASHCOUNT_T_MAX, int_tag_compare, int_tag_hash); + if (!TagHash || width <= 0 || height <= 0) + return -1; + vj_tag_input = (vj_tag_data *) vj_malloc(sizeof(vj_tag_data)); + if (vj_tag_input == NULL) { + veejay_msg(VEEJAY_MSG_ERROR, + "Error Allocating Memory for stream data\n"); + return -1; + } + this_tag_id = 0; + vj_tag_input->width = width; + vj_tag_input->height = height; + vj_tag_input->depth = 3; + vj_tag_input->pix_fmt = pix_fmt; + video_driver_ = video_driver; +#ifndef HAVE_UNICAP + video_driver_ = 1; +#endif + + vj_tag_input->uv_len = (width*height) / 2; + + memset( &_tmp, 0, sizeof(VJFrame)); + _tmp.len = width * height; +#ifdef HAVE_UNICAP + unicap_data_= (void*) vj_unicap_init(); +#endif + _temp_buffer[0] = (uint8_t*) vj_malloc(sizeof(uint8_t)*width*height); + _temp_buffer[1] = (uint8_t*) vj_malloc(sizeof(uint8_t)*width*height); + _temp_buffer[2] = (uint8_t*) vj_malloc(sizeof(uint8_t)*width*height); + + + _tmp.uv_width = width; + _tmp.uv_height = height/2; + _tmp.uv_len = width * (height/2); + + for(i=0; i < SAMPLE_MAX_SAMPLES; i++) { + avail_tag[i] = 0; + } + + v4lvideo_templ_init(); + + return 0; +} + +void vj_tag_record_init(int w, int h) +{ +} + +int _vj_tag_new_net(vj_tag *tag, int stream_nr, int w, int h,int f, char *host, int port, int p, int type ) +{ + vj_client *v; + if( !host ) { + veejay_msg(0, "No hostname given"); + return 0; + } + if( port <= 0 ) { + veejay_msg(0, "Port number %d invalid", port ); + return 0; + } + if(stream_nr < 0 || stream_nr > VJ_TAG_MAX_STREAM_IN) + { + veejay_msg(0, "Unable to create more network streams (%d reached)", + VJ_TAG_MAX_STREAM_IN ); + return 0; + } + + vj_tag_input->net[stream_nr] = vj_client_alloc(w,h,f); + v = vj_tag_input->net[stream_nr]; + if(!v) + { + veejay_msg(0, "Memory allocation error while creating network stream"); + return 0; + } + char tmp[255]; + bzero(tmp,255); + snprintf(tmp,sizeof(tmp)-1, "%s %d", host, port ); + tag->extra = (void*) strdup(tmp); + + v->planes[0] = w * h; + int fmt= vj_tag_input->pix_fmt; + v->planes[1] = v->planes[0] / 2; + v->planes[2] = v->planes[0] / 2; + + if( tag->socket_ready == 0 ) + { + tag->socket_frame = (uint8_t*) vj_calloc(sizeof(uint8_t) * w * h * 3); + tag->socket_len = w * h * 3; + if(!tag->socket_frame) + { + veejay_msg(VEEJAY_MSG_ERROR, "Insufficient error to allocate memory for Network Stream"); + return 0; + } + tag->socket_ready = 1; + } + + return 1; +} + +static struct { + const char *name; +} video_norm_[] = +{ + "pal", + "ntsc", + "auto", + NULL +}; + +int _vj_tag_new_unicap( vj_tag * tag, int stream_nr, int width, int height, int device_num, + char norm, int palette,int pixfmt, int freq, int channel, int has_composite, int driver) +{ + char refname[100]; + const char *selected_video_norm = video_norm_[2].name; + + if (stream_nr < 0 || stream_nr > vj_tag_num_devices()) + { + return 0; + } + + snprintf(refname,sizeof(refname), "/dev/video%d",device_num ); // freq->device_num + + switch(norm) { + case 'P': + case 'p': + selected_video_norm = video_norm_[0].name; break; + case 'n': case 'N': + selected_video_norm = video_norm_[1].name; break; + default: + break;//auto + } + + tag->capture_type = driver; + veejay_msg(VEEJAY_MSG_INFO, "Open capture device with %s", + ( driver == 1 ? "Effectv V4lutils" : "Unicap" ) ); + if( tag->capture_type == 1 ) { + vj_tag_input->unicap[stream_nr] = v4lvideo_init( refname, channel, + v4lvideo_templ_get_norm( selected_video_norm ), + freq, + width, height, palette ); + v4lvideo_set_composite_status( vj_tag_input->unicap[stream_nr] ,has_composite ); + if( vj_tag_input->unicap[stream_nr] == NULL ) { + veejay_msg(0, "Unable to open device %s", refname ); + return 0; + } + sprintf(refname, "%d",channel ); + tag->extra = strdup(refname); + veejay_msg(VEEJAY_MSG_DEBUG, "Using V4lutils from EffecTV"); + return 1; + } else { +#ifdef HAVE_UNICAP + vj_tag_input->unicap[stream_nr] = vj_unicap_new_device( unicap_data_, device_num ); + if(!vj_tag_input->unicap[stream_nr] ) + { + veejay_msg(0,"Unable to open device %d", device_num); + return 0; + } + if(!vj_unicap_configure_device( vj_tag_input->unicap[stream_nr] , + pixfmt, width,height, has_composite)) + { + veejay_msg(0,"Unable to configure device %d",channel); + vj_unicap_free_device( unicap_data_,vj_tag_input->unicap[stream_nr] ); + return 0; + } + else + veejay_msg(VEEJAY_MSG_DEBUG, "Configured device %d with Unicap", channel); + sprintf(refname, "%d",channel ); + tag->extra = strdup(refname); + + char **props = vj_unicap_get_list( vj_tag_input->unicap[stream_nr] ); + int i; + double v = 0.0; + for( i = 0; props[i] != NULL ; i ++ ) { + if(strncasecmp("video norm", props[i],10 ) == 0 ) { + if( norm == 'p' || norm == 'P' ) + vj_unicap_select_value(vj_tag_input->unicap[tag->index],UNICAP_PAL,0); + else + vj_unicap_select_value( vj_tag_input->unicap[tag->index],UNICAP_NTSC,0 ); + } + else if (strncasecmp( "video source", props[i], 12 ) == 0 ) + { + int cha = channel + UNICAP_SOURCE0; + if(cha <=UNICAP_SOURCE4) + vj_unicap_select_value( vj_tag_input->unicap[tag->index], + cha,0 ); + } + free(props[i]); + } + free(props); +#else + veejay_msg(VEEJAY_MSG_ERROR, "Unicap support not compiled in."); + return 0; +#endif + } + //set channel + + return 1; +} + +#ifdef USE_GDK_PIXBUF +int _vj_tag_new_picture( vj_tag *tag, int stream_nr, editlist *el) +{ + int stop = 0; + if(stream_nr < 0 || stream_nr > VJ_TAG_MAX_STREAM_IN) return 0; + vj_picture *p = NULL; + + if( vj_picture_probe( tag->source_name ) == 0 ) + return 0; + + p = (vj_picture*) vj_malloc(sizeof(vj_picture)); + if(!p) + return 0; + memset(p, 0, sizeof(vj_picture)); + + vj_tag_input->picture[stream_nr] = p; + + veejay_msg(VEEJAY_MSG_INFO, "Opened [%s] , %d x %d @ %2.2f fps ", + tag->source_name, + el->video_width, el->video_height, el->video_fps ); + + return 1; +} +#endif + +uint8_t *vj_tag_get_cali_buffer(int t1, int type, int *total, int *plane, int *planeuv) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return NULL; + + int w = vj_tag_input->width; + int h = vj_tag_input->height; + int len = (w*h); + int uv_len = vj_tag_input->uv_len; + + *total = len + (2*uv_len); + *plane = len; + *planeuv= uv_len; + return cali_get(tag,type,w*h,uv_len); +} + +static int cali_write_file( char *file, vj_tag *tag , editlist *el) +{ + FILE *f = fopen( file, "w" ); + if(!f) { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to open '%s' for writing",file ); + return 0; + } + + char header[256]; + int w = vj_tag_input->width; + int h = vj_tag_input->height; + int len = (w*h); + int uv_len = vj_tag_input->uv_len; + + char fileheader[256]; + + snprintf(header,sizeof(header),"%08d %08d %08d %08d %g %g %g", + w, + h, + len, + uv_len, + tag->mean[0], + tag->mean[1], + tag->mean[2] ); + + int offset = 4 + strlen(header); + + snprintf(fileheader,sizeof(fileheader), "%03d %s",offset,header ); + + if( fwrite( fileheader,strlen(fileheader),1, f ) <= 0 ) { + veejay_msg(0 ,"Error while writing file header."); + return 0; + } + int n = 0; + + //@ write dark current frame + if( (n=fwrite( tag->blackframe,sizeof(uint8_t), len + uv_len + uv_len, f )) <= 0 ) { + goto CALIERR; + } + if( n != (len+uv_len + uv_len)) + goto CALIERR; + + uint8_t *lightframe = cali_get(tag,CALI_LIGHT,w*h,uv_len); + if( (n=fwrite( lightframe,sizeof(uint8_t), len + uv_len + uv_len, f )) <= 0 ) { + goto CALIERR; + } + if( n != (len+uv_len+uv_len)) + goto CALIERR; + + uint8_t *masterframe = cali_get(tag,CALI_FLAT,w*h,uv_len); + if( (n=fwrite( masterframe, sizeof(uint8_t), len + uv_len + uv_len, f )) <= 0 ) { + goto CALIERR; + } + if( n != (len+uv_len+uv_len)) + goto CALIERR; + + fclose(f); + + return 1; +CALIERR: + fclose(f); + veejay_msg(0, "File write error."); + + + return 0; +} + +int vj_tag_cali_write_file( int t1, char *name, editlist *el ) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return 0; + if(tag->source_type != VJ_TAG_TYPE_V4L) { + veejay_msg(0, "Stream is not of type Video4Linux"); + return 0; + } + if(tag->noise_suppression == 0 ) { + veejay_msg(0, "Stream %d is not yet calibrated.", t1 ); + return 0; + } + if(tag->noise_suppression != V4L_BLACKFRAME_PROCESS ) { + veejay_msg(0, "Please finish calibration first."); + return 0; + } + if(! cali_write_file( name, tag, el ) ) { + return 0; + } + return 1; +} + + +static int cali_read_file( cali_tag_t *p, char *file,editlist *el ) +{ + FILE *f = fopen( file , "r" ); + if( f == NULL ) { + return 0; + } + + char buf[256]; + + char *header = fgets( buf, sizeof(buf), f ); + int w = 0; + int h = 0; + int len = 0; + int uv_len = 0; + int offset = 0; + + int Euv_len = vj_tag_input->uv_len; + + double mean[3]; + + if(sscanf(header, "%3d %8d %8d %8d %8d %lf %lf %lf",&offset, &w,&h,&len,&uv_len, + &mean[0],&mean[1],&mean[2] ) != 8 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid header."); + return 0; + } + + if( w != el->video_width || h != el->video_height ) { + veejay_msg(VEEJAY_MSG_ERROR, "Dimensions do not match, abort."); + fclose(f); + return 0; + } + + if( len != (w*h)) { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid length for plane Y"); + fclose(f); + return 0; + } + + if( Euv_len != uv_len ) { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid length for planes UV"); + fclose(f); + return 0; + } + + p->data = (uint8_t*) vj_malloc(sizeof(uint8_t) * 3 * (len+uv_len+uv_len)); + p->bf = p->data; + p->lf = p->data + (len + (2*uv_len)); + p->mf = p->lf + (len + (2*uv_len)); + + p->uv_len = uv_len; + p->len = len; + p->mean[0] = mean[0]; + p->mean[1] = mean[1]; + p->mean[2] = mean[2]; + + veejay_memset( p->data,0, 3 * (len+(2*uv_len))); + + int n = 0; + + if( (n=fread( p->bf, 1, (len+2*uv_len), f )) <= 0 ) { + goto CALIREADERR; + } + + if( (n=fread( p->lf,1, (len+2*uv_len), f )) <= 0 ) { + goto CALIREADERR; + } + + if( (n=fread( p->mf,1, (len+2*uv_len),f)) <= 0 ) { + goto CALIREADERR; + } + + veejay_msg(VEEJAY_MSG_INFO, "Image calibration data loaded."); + + return 1; + +CALIREADERR: + veejay_msg(VEEJAY_MSG_ERROR, "Only got %d bytes.",n); + return 0; +} + +int _vj_tag_new_cali( vj_tag *tag, int stream_nr, editlist *el ) +{ + if(stream_nr < 0 || stream_nr > VJ_TAG_MAX_STREAM_IN) return 0; + + cali_tag_t *p = NULL; + + p = (cali_tag_t*) vj_malloc(sizeof(cali_tag_t)); + if(!p) + return 0; + memset(p, 0, sizeof(cali_tag_t)); + + if(!cali_read_file( p, tag->source_name,el ) ) { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to find dark frame '%s'", tag->source_name ); + free(p); + return 0; + } + + vj_tag_input->cali[stream_nr] = (void*)p; + + veejay_msg(VEEJAY_MSG_INFO, "Image Cailbration files ready."); + + return 1; +} + +uint8_t *vj_tag_get_cali_data( int t1, int what ) { + vj_tag *tag = vj_tag_get(t1); + if(tag == NULL) + return NULL; + int w = vj_tag_input->width; + int h = vj_tag_input->height; + int uv_len = vj_tag_input->uv_len; + switch(what) { + case 0: + return tag->blackframe; + case 1: + return tag->blackframe + ((w*h)+(2*uv_len)); + case 2: + return tag->blackframe + 2 * ((w*h)+(2*uv_len)); + } + return NULL; +} + +int _vj_tag_new_yuv4mpeg(vj_tag * tag, int stream_nr, editlist * el) +{ + if (stream_nr < 0 || stream_nr > VJ_TAG_MAX_STREAM_IN) + return 0; + vj_tag_input->stream[stream_nr] = vj_yuv4mpeg_alloc(el,el->video_width,el->video_height, _tag_info->pixel_format); + + if(vj_tag_input->stream[stream_nr] == NULL) + return 0; + + if(vj_yuv_stream_start_read(vj_tag_input->stream[stream_nr],tag->source_name, + el->video_width, el->video_height) != 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Unable to read from %s",tag->source_name); + vj_yuv4mpeg_free( vj_tag_input->stream[stream_nr] ); + return 0; + } + return 1; +} +#ifdef SUPPORT_READ_DV2 +int _vj_tag_new_dv1394(vj_tag *tag, int stream_nr, int channel,int quality, editlist *el) +{ + vj_tag_input->dv1394[stream_nr] = vj_dv1394_init( (void*) el, channel,quality); + if(vj_tag_input->dv1394[stream_nr]) + { + veejay_msg(VEEJAY_MSG_INFO, "DV1394 ready for capture"); +// vj_dv_decoder_set_audio( vj_tag_input->dv1394[stream_nr], el->has_audio); + return 1; + } + return 0; +} +#endif + +void *vj_tag_get_dict( int t1 ) +{ +#ifdef HAVE_FREETYPE + vj_tag *tag = vj_tag_get(t1); + if(tag) + return tag->dict; +#endif + return NULL; +} + +int vj_tag_set_stream_color(int t1, int r, int g, int b) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return 0; + if(tag->source_type != VJ_TAG_TYPE_COLOR) + return 0; + + veejay_msg(VEEJAY_MSG_DEBUG,"Set stream %d color %d,%d,%d",t1, + r,g, b ); + + tag->color_r = r; + tag->color_g = g; + tag->color_b = b; + + return (vj_tag_update(tag,t1)); +} + +int vj_tag_get_composite(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + return tag->composite; +} + +int vj_tag_get_stream_color(int t1, int *r, int *g, int *b ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return 0; + if(tag->source_type != VJ_TAG_TYPE_COLOR) + return 0; + + *r = tag->color_r; + *g = tag->color_g; + *b = tag->color_b; + + return 1; +} + +int vj_tag_composite(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + if(tag->source_type != VJ_TAG_TYPE_V4L ) + return 0; +#ifdef HAVE_UNICAP + if(tag->capture_type==0) + return vj_unicap_composite_status( vj_tag_input->unicap[ tag->index ] ); +#endif + if(tag->capture_type==1) + return v4lvideo_get_composite_status( vj_tag_input->unicap[tag->index]); + return 0; +} + +// for network, filename /channel is passed as host/port num +int vj_tag_new(int type, char *filename, int stream_nr, editlist * el, + int pix_fmt, int channel , int extra , int has_composite) +{ + int i, j; + int palette; + int w = el->video_width; + int h = el->video_height; /* FIXME */ + int id = 0; + int n; + char sourcename[255]; + + vj_tag *tag; + + if( this_tag_id == 0) + { + this_tag_id = 1; // first tag + } + n = this_tag_id; + /* see if we are already using the source */ + if( type == VJ_TAG_TYPE_NET || type == VJ_TAG_TYPE_MCAST ) + { + if(net_already_opened( filename,n, channel )) + { + veejay_msg(0, "There is already a unicast connection to %s: %d", filename, channel ); + return -1; + } + } + tag = (vj_tag *) vj_calloc(sizeof(vj_tag)); + if(!tag) + { + veejay_msg(0, "Memory allocation error"); + return -1; + } + + tag->source_name = (char *) vj_calloc(sizeof(char) * 255); + if (!tag->source_name) + { + veejay_msg(0, "Memory allocation error"); + return -1; + } + + /* see if we can reclaim some id */ + for(i=0; i <= next_avail_tag; i++) { + if(avail_tag[i] != 0) { + hnode_t *tag_node; + tag_node = hnode_create(tag); + if (!tag_node) + { + veejay_msg(0, "Unable to find available ID"); + return -1; + } + id = avail_tag[i]; + avail_tag[i] = 0; + hash_insert(TagHash, tag_node, (void *) id); + break; + } + } + + + if(id==0) { + tag->id = this_tag_id; + this_tag_id++; + } + else { + tag->id = id; + } + + tag->extra = NULL; + tag->next_id = 0; + tag->nframes = 0; + tag->video_channel = channel; + tag->source_type = type; + tag->index = stream_nr; + tag->active = 0; + tag->n_frames = 50; + tag->sequence_num = 0; + tag->encoder_format = 0; + tag->encoder_active = 0; + tag->encoder_max_size = 0; + tag->encoder_succes_frames = 0; + tag->encoder_duration = 0; + tag->encoder_width = 0; + tag->encoder_height = 0; + tag->encoder_num_frames = 0; + tag->method_filename = (filename == NULL ? NULL :strdup(filename)); + tag->rec_total_bytes = 0; + tag->encoder_total_frames = 0; + tag->source = 0; + tag->fader_active = 0; + tag->fader_val = 0.0; + tag->fader_inc = 0.0; + tag->fader_direction = 0; + tag->selected_entry = 0; + tag->depth = 0; + tag->effect_toggle = 1; /* same as for samples */ + tag->socket_ready = 0; + tag->socket_frame = NULL; + tag->socket_len = 0; + tag->color_r = 0; + tag->color_g = 0; + tag->color_b = 0; + tag->opacity = 0; + tag->priv = NULL; + + if(type == VJ_TAG_TYPE_MCAST || type == VJ_TAG_TYPE_NET) + tag->priv = net_threader(); + + palette = v4lvideo_templ_get_palette( pix_fmt ); + + switch (type) { + case VJ_TAG_TYPE_V4L: + sprintf(tag->source_name, "%s", filename ); +//FIXME + veejay_msg(VEEJAY_MSG_DEBUG, "V4l: %s",filename); + +/* +int _vj_tag_new_unicap( vj_tag * tag, int stream_nr, int width, int height, int device_num, + char norm, int palette,int pixfmt, int freq, int channel, int has_composite) + +*/ + if (!_vj_tag_new_unicap( tag, + stream_nr,w,h, + extra, // device num + el->video_norm, + palette, + pix_fmt, + 0, + channel, + has_composite, + video_driver_ )) + { + veejay_msg(0, "Unable to open capture stream '%dx%d' (norm=%c,format=%x,device=%d,channel=%d)", + w,h,el->video_norm, pix_fmt, extra,channel ); + return -1; + } + break; + case VJ_TAG_TYPE_MCAST: + case VJ_TAG_TYPE_NET: + sprintf(tag->source_name, "%s", filename ); + if( _vj_tag_new_net( tag,stream_nr, w,h,pix_fmt, filename, channel ,palette,type) != 1 ) + return -1; + break; + case VJ_TAG_TYPE_DV1394: +#ifdef SUPPORT_READ_DV2 + sprintf(tag->source_name, "/dev/dv1394/%d", channel); + if( _vj_tag_new_dv1394( tag, stream_nr,channel,1,el ) == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "error opening dv1394"); + return -1; + } + tag->active = 1; + break; +#else + veejay_msg(VEEJAY_MSG_DEBUG, "libdv not enabled at compile time"); + return -1; +#endif +#ifdef USE_GDK_PIXBUF + case VJ_TAG_TYPE_PICTURE: + sprintf(tag->source_name, "%s", filename); + if( _vj_tag_new_picture(tag, stream_nr, el) != 1 ) + return -1; + break; +#endif + case VJ_TAG_TYPE_CALI: + sprintf(tag->source_name,"%s",filename); + if(_vj_tag_new_cali( tag,stream_nr,el) != 1 ) + return -1; + break; + case VJ_TAG_TYPE_YUV4MPEG: + sprintf(tag->source_name, "%s", filename); + if (_vj_tag_new_yuv4mpeg(tag, stream_nr, el) != 1) + { + if(tag->source_name) free(tag->source_name); + if(tag) free(tag); + return -1; + } + tag->active = 1; + break; + case VJ_TAG_TYPE_COLOR: + sprintf(tag->source_name, "[%d,%d,%d]", + tag->color_r,tag->color_g,tag->color_b ); + tag->active = 1; + break; + + default: + veejay_msg(0, "Stream type %d invalid", type ); + return -1; + } + + vj_tag_get_by_type( tag->source_type, tag->descr); + + /* effect chain is empty */ + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + { + tag->effect_chain[i] = + (sample_eff_chain *) vj_calloc(sizeof(sample_eff_chain)); + tag->effect_chain[i]->effect_id = -1; + tag->effect_chain[i]->e_flag = 0; + tag->effect_chain[i]->frame_trimmer = 0; + tag->effect_chain[i]->frame_offset = 0; + tag->effect_chain[i]->volume = 0; + tag->effect_chain[i]->a_flag = 0; + tag->effect_chain[i]->channel = 0; + tag->effect_chain[i]->source_type = 1; + tag->effect_chain[i]->is_rendering = 0; + for (j = 0; j < SAMPLE_MAX_PARAMETERS; j++) { + tag->effect_chain[i]->arg[j] = 0; + } + tag->effect_chain[i]->kf_status = 0; + tag->effect_chain[i]->kf = vpn( VEVO_ANONYMOUS_PORT ); + } + if (!vj_tag_put(tag)) + { + veejay_msg(0, "Unable to store stream"); + return -1; + } + last_added_tag = tag->id; + +#ifdef HAVE_FREETYPE + tag->dict = vpn(VEVO_ANONYMOUS_PORT ); +#endif + return (int)(tag->id); +} + + +int vj_tag_is_deleted(int id) { + int i; + for (i = 0; i < next_avail_tag; i++) { + if (avail_tag[i] == id) + return 1; + } + return 0; +} + +int vj_tag_exists(int id) +{ + if (!id) + return 0; + if (!vj_tag_get(id)) + return 0; + return 1; +} + +int vj_tag_clear_chain(int id) +{ + int i = 0; + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) { + if (vj_tag_chain_remove(id, i) == -1) + return -1; + } + return 1; +} + +int vj_tag_verify_delete(int id, int type ) +{ + int i,j; + for( i = 1; i < vj_tag_size()-1; i ++ ) + { + vj_tag *s = vj_tag_get(i); + if(s) + { + for( j = 0 ; j < SAMPLE_MAX_EFFECTS; j ++ ) + { + if(s->effect_chain[j]->channel == id && + s->effect_chain[j]->source_type == type ) + { + s->effect_chain[j]->channel = i; + s->effect_chain[j]->source_type = 1; + veejay_msg(VEEJAY_MSG_INFO, "Dereferenced mix entry %d of Stream %d", + j, i ); + vj_tag_update( s, i ); + } + } + } + } + return 1; +} + +int vj_tag_del(int id) +{ + hnode_t *tag_node; + vj_tag *tag; + int i; + tag = vj_tag_get(id); + if(!tag) + return 0; +#ifdef HAVE_TRUETYPE + vj_font_dictionary_destroy(_tag_info->font ,tag->dict); +#endif + + if(tag->extra) + free(tag->extra); + + /* stop streaming in first */ + switch(tag->source_type) { +#ifdef HAVE_UNICAP + case VJ_TAG_TYPE_V4L: +#ifdef HAVE_UNICAP + if(!tag->capture_type) + vj_unicap_free_device(unicap_data_, vj_tag_input->unicap[tag->index] ); +#endif + if(tag->capture_type==1) + v4lvideo_destroy( vj_tag_input->unicap[tag->index] ); + if(tag->blackframe) + free(tag->blackframe); + if( tag->bf ) free(tag->bf); + if( tag->bfu ) free(tag->bfu); + if( tag->bfv ) free(tag->bfv); + if( tag->lf ) free(tag->lf); + if( tag->lfu ) free(tag->lfu); + if( tag->lfv ) free(tag->lfv); + + break; +#endif + case VJ_TAG_TYPE_YUV4MPEG: + veejay_msg(VEEJAY_MSG_INFO,"Closing yuv4mpeg file %s (Stream %d)", + tag->source_name,id); + vj_yuv_stream_stop_read(vj_tag_input->stream[tag->index]); +// vj_yuv4mpeg_free( vj_tag_input->stream[tag->index]); + break; +#ifdef SUPPORT_READ_DV2 + case VJ_TAG_TYPE_DV1394: + vj_dv1394_close( vj_tag_input->dv1394[tag->index] ); + break; +#endif +#ifdef USE_GDK_PIXBUF + case VJ_TAG_TYPE_PICTURE: + veejay_msg(VEEJAY_MSG_INFO, "Closing picture stream %s", tag->source_name); + vj_picture *pic = vj_tag_input->picture[tag->index]; + if(pic) + { + vj_picture_cleanup( pic->pic ); + free( pic ); + } + vj_tag_input->picture[tag->index] = NULL; + break; +#endif + case VJ_TAG_TYPE_CALI: + { + cali_tag_t *pic = (cali_tag_t*) vj_tag_input->cali[tag->index]; + if(pic) { + if(pic->lf) free(pic->data); + free(pic); + } + vj_tag_input->cali[tag->index] = NULL; + } + break; + case VJ_TAG_TYPE_MCAST: + case VJ_TAG_TYPE_NET: + net_thread_stop(tag); + if(vj_tag_input->net[tag->index]) + { + vj_client_close( vj_tag_input->net[tag->index] ); + vj_tag_input->net[tag->index] = NULL; + } + break; + } + + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + vevo_port_free( tag->effect_chain[i]->kf ); + } + tag_node = hash_lookup(TagHash, (void *) tag->id); + if(tag_node) + { + if(tag->encoder_active) + vj_tag_stop_encoder( tag->id ); + if(tag->source_name) free(tag->source_name); + if(tag->method_filename) free(tag->method_filename); + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + if (tag->effect_chain[i]) + free(tag->effect_chain[i]); + + if(tag->socket_frame) + free(tag->socket_frame); + if(tag->viewport) + viewport_destroy(tag->viewport); + + free(tag); + tag = NULL; + avail_tag[ next_avail_tag] = id; + next_avail_tag++; + hash_delete(TagHash, tag_node); + return 1; + } + return -1; +} + +void vj_tag_close_all() { + int n=vj_tag_size()-1; + int i; + vj_tag *tag; + + for(i=1; i < n; i++) { + tag = vj_tag_get(i); + if(tag) { + if(vj_tag_del(i)) veejay_msg(VEEJAY_MSG_DEBUG, "Deleted stream %d", i); + } + } + +} + +int vj_tag_get_n_frames(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + return tag->n_frames; +} + +int vj_tag_set_n_frames( int t1, int n ) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + tag->n_frames = n; + return ( vj_tag_update(tag, t1)); +} + +int vj_tag_load_composite_config( void *compiz, int t1 ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return -1; + + int val = 0; + void *temp = composite_load_config( compiz, tag->viewport_config, &val ); + if(temp == NULL || val == -1 ) + return 0; + + tag->composite = val; + tag->viewport = temp; + vj_tag_update(tag,t1); + return tag->composite; +} + +void vj_tag_reload_config( void *compiz, int t1, int mode ) +{ + vj_tag *tag = vj_tag_get(t1); + if(tag) { + if(tag->viewport_config) { + free(tag->viewport_config); + tag->viewport_config = NULL; + } + if(!tag->viewport_config) { + tag->viewport_config = composite_get_config( compiz, mode ); + } + tag->composite = mode; + vj_tag_update(tag, t1); + } +} +void *vj_tag_get_composite_view( int t1 ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return NULL; + return tag->viewport; +} +int vj_tag_set_composite_view( int t1, void *vp ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + tag->viewport = vp; + return (vj_tag_update(tag,t1)); +} + +int vj_tag_set_composite( void *compiz,int t1, int n ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + tag->composite = n; + if( tag->viewport_config == NULL ) { + tag->composite = 1; + return (vj_tag_update(tag,t1)); + } +#ifdef STRICT_CHECKING + assert( tag->viewport_config != NULL ); +#endif + composite_add_to_config( compiz, tag->viewport_config, n ); + + return (vj_tag_update(tag,t1)); +} + +int vj_tag_get_effect(int t1, int position) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + if (tag->effect_chain[position]->e_flag == 0) + return -1; + return tag->effect_chain[position]->effect_id; +} + +float vj_tag_get_fader_val(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return ( tag->fader_val ); +} + + +int vj_tag_set_description(int t1, char *description) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + if(!description || strlen(description) <= 0 ) + snprintf( tag->descr, TAG_MAX_DESCR_LEN, "%s","Untitled"); + else + snprintf( tag->descr, TAG_MAX_DESCR_LEN, "%s", description ); + return ( vj_tag_update(tag, t1)) ; +} + +int vj_tag_get_description( int t1, char *description ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + snprintf( description ,TAG_MAX_DESCR_LEN, "%s", tag->descr ); + return 1; +} + +int vj_tag_set_manual_fader(int t1, int value ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + tag->fader_active = 2; + tag->fader_inc = 0.0; + tag->fader_val = (float)value; + return (vj_tag_update(tag,t1)); +} + +float vj_tag_get_fader_inc(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return (tag->fader_inc); +} + +int vj_tag_reset_fader(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + tag->fader_active = 0; + tag->fader_inc = 0.0; + tag->fader_val = 0.0; + return (vj_tag_update(tag,t1)); +} + +int vj_tag_set_fader_val(int t1, float val) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + tag->fader_val = val; + return ( vj_tag_update(tag,t1)); +} + +int vj_tag_get_fader_active(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return (tag->fader_active); +} + +int vj_tag_get_fader_direction(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return (tag->fader_direction); +} + +int vj_tag_apply_fader_inc(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + tag->fader_val += tag->fader_inc; + if(tag->fader_val > 255.0 ) tag->fader_val = 255.0; + if(tag->fader_val < 0.0) tag->fader_val = 0.0; + vj_tag_update(tag,t1); + if(tag->fader_direction) return tag->fader_val; + return (255-tag->fader_val); +} + +int vj_tag_set_fader_active(int t1, int nframes , int direction) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(nframes <= 0) return -1; + tag->fader_active = 1; + if(direction<0) + tag->fader_val = 255.0; + else + tag->fader_val = 0.0; + tag->fader_val = 0.0; + tag->fader_inc = (float) (255.0 / (float)nframes ); + tag->fader_direction = direction; + tag->fader_inc *= direction; + if(tag->effect_toggle == 0 ) + tag->effect_toggle = 1; + return ( vj_tag_update(tag, t1)); +} + +int vj_tag_stop_encoder(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) + { + veejay_msg(VEEJAY_MSG_ERROR, "Tag %d does not exist", t1); + return -1; + } + if(tag->encoder_active) { + if(tag->encoder_file) + lav_close(tag->encoder_file); + if(tag->encoder) + vj_avcodec_stop( tag->encoder, tag->encoder_format ); + tag->encoder = NULL; + tag->encoder_file = NULL; + tag->encoder_active = 0; + return (vj_tag_update(tag,t1)); + } + + return 0; +} + +void vj_tag_reset_encoder(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return; + tag->encoder_format = 0; + tag->encoder_succes_frames = 0; + tag->encoder_num_frames = 0; + tag->encoder_width = 0; + tag->encoder_height = 0; + tag->encoder_max_size = 0; + tag->encoder_active = 0; + tag->rec_total_bytes = 0; + + vj_tag_update(tag,t1); +} + +int vj_tag_get_encoded_file(int t1, char *description) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + sprintf(description, "%s", tag->encoder_destination ); + return 1; +} + +int vj_tag_get_num_encoded_files(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return tag->sequence_num; +} + +int vj_tag_get_encoder_format(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return tag->encoder_format; +} + +int vj_tag_get_sequenced_file(int t1, char *descr, int num, char *ext) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + sprintf(descr, "%s-%05d.%s", tag->encoder_destination,num,ext ); + return 1; +} + + +int vj_tag_try_filename(int t1, char *filename, int format) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + { + return 0; + } + if(filename != NULL) + { + snprintf(tag->encoder_base, 255, "%s", filename); + } + char ext[5]; + switch(format) + { + case ENCODER_QUICKTIME_DV: + case ENCODER_QUICKTIME_MJPEG: + sprintf(ext, "mov"); + break; + case ENCODER_YUV4MPEG: + sprintf(ext, "yuv"); + break; + case ENCODER_DVVIDEO: + sprintf(ext,"dv"); + break; + default: + sprintf(ext,"avi"); + break; + } + + sprintf(tag->encoder_destination, "%s-%03d.%s", tag->encoder_base, (int)tag->sequence_num, ext); + return (vj_tag_update(tag,t1)); +} + + + +static int vj_tag_start_encoder(vj_tag *tag, int format, long nframes) +{ + char cformat = vj_avcodec_find_lav( format ); + int sample_id = tag->id; + + tag->encoder = vj_avcodec_start( _tag_info->edit_list , format, tag->encoder_destination ); + if(!tag->encoder) + { + veejay_msg(0, "Unable to use selected encoder, please choose another."); + return 0; + } + tag->encoder_active = 1; + tag->encoder_format = format; + + int tmp = _tag_info->edit_list->video_width * _tag_info->edit_list->video_height; + + if(format==ENCODER_DVVIDEO) + tag->encoder_max_size = ( _tag_info->edit_list->video_height == 480 ? 120000: 144000); + else + switch(format) + { + case ENCODER_YUV420: + case ENCODER_YUV420F: + tag->encoder_max_size = 2048 + tmp + (tmp/4) + (tmp/4);break; + case ENCODER_YUV422: + case ENCODER_YUV422F: + case ENCODER_YUV4MPEG: + tag->encoder_max_size = 2048 + tmp + (tmp/2) + (tmp/2);break; + case ENCODER_LZO: + tag->encoder_max_size = tmp * 3; break; + default: + tag->encoder_max_size = ( 4 * 65535 ); + break; + } + + if(tag->encoder_total_frames == 0) + { + tag->encoder_duration = nframes ; + tag->encoder_num_frames = 0; + } + else + { + tag->encoder_duration = tag->encoder_duration - tag->encoder_num_frames; + } + + if( sufficient_space( tag->encoder_max_size, tag->encoder_num_frames ) == 0 ) + { + vj_avcodec_close_encoder(tag->encoder ); + tag->encoder_active = 0; + tag->encoder = NULL; + return 0; + } + + if( cformat != 'S' ) { + tag->encoder_file = lav_open_output_file( + tag->encoder_destination, + cformat, + _tag_info->edit_list->video_width, + _tag_info->edit_list->video_height, + _tag_info->edit_list->video_inter, + _tag_info->edit_list->video_fps, + 0, + 0, + 0 + ); + + + if(!tag->encoder_file) + { + veejay_msg(VEEJAY_MSG_ERROR,"Cannot write to %s (No permissions?)",tag->encoder_destination); + if(tag->encoder) + vj_avcodec_close_encoder( tag->encoder ); + tag->encoder = NULL; + tag->encoder_active = 0; + return 0; + } + } + + veejay_msg(VEEJAY_MSG_INFO, "Recording to file [%s] %ldx%ld@%2.2f %d/%d/%d >%09ld<", + tag->encoder_destination, + _tag_info->edit_list->video_width, + _tag_info->edit_list->video_height, + (float) _tag_info->edit_list->video_fps, + 0,0,0, + (long)( tag->encoder_duration - tag->encoder_total_frames) + ); + + + tag->rec_total_bytes= 0; + tag->encoder_succes_frames = 0; + tag->encoder_width = _tag_info->edit_list->video_width; + tag->encoder_height = _tag_info->edit_list->video_height; + + return vj_tag_update(tag,sample_id); +} + + + +int vj_tag_init_encoder(int t1, char *filename, int format, long nframes ) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + + if(tag->encoder_active) + { + veejay_msg(VEEJAY_MSG_ERROR, "Already recording Stream %d to [%s]",t1, tag->encoder_destination); + return 0; + } + + if(!vj_tag_try_filename( t1,filename,format)) + { + return 0; + } + if(nframes <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "It makes no sense to encode for %ld frames", nframes); + return 0; + } + /* todo: clean this mess up */ + + return vj_tag_start_encoder( tag,format, nframes ); +} + +int vj_tag_continue_record( int t1 ) +{ + vj_tag *si = vj_tag_get(t1); + if(!si) return -1; + + if( si->rec_total_bytes == 0) return 0; + + if(si->encoder_num_frames >= si->encoder_duration) + { + veejay_msg(VEEJAY_MSG_INFO, "Ready recording %ld frames", si->encoder_succes_frames); + si->encoder_total_frames = 0; + vj_tag_update(si, t1 ); + return 1; + } + + // 2 GB barrier + if (si->rec_total_bytes >= VEEJAY_FILE_LIMIT) + { + veejay_msg(VEEJAY_MSG_INFO, "Auto splitting files (reached internal 2GB barrier)"); + si->sequence_num ++; + si->rec_total_bytes = 0; + // si->encoder_duration + // reset some variables + + printf(" %d %ld %d (%ld)%ld \n", + (int)si->sequence_num, + si->rec_total_bytes, + si->encoder_num_frames, + si->encoder_total_frames, + si->encoder_duration); + + si->encoder_total_frames = 0; + vj_tag_update(si,t1); + return 2; + } + + + return 0; + +} +int vj_tag_set_brightness(int t1, int value) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + if(value < 0 || value > 65535) + { + veejay_msg(VEEJAY_MSG_ERROR,"Brightness valid range is 0 - 65535"); + return 0; + } + else + { + if(tag->capture_type==1) + v4lvideo_set_brightness( vj_tag_input->unicap[tag->index], value ); +#ifdef HAVE_UNICAP + else + vj_unicap_select_value( vj_tag_input->unicap[tag->index],UNICAP_BRIGHTNESS,(double)value); +#endif + } + return 1; +} +int vj_tag_set_white(int t1, int value) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(value < 0 || value > 65535) + { + veejay_msg(VEEJAY_MSG_ERROR,"White valid range is 0 - 65535"); + return -1; + } + else + { + if(tag->capture_type==1) + v4lvideo_set_white( vj_tag_input->unicap[tag->index],value ); +#ifdef HAVE_UNICAP + else + vj_unicap_select_value( vj_tag_input->unicap[tag->index],UNICAP_WHITE,(double) value ); +#endif + } + return 1; +} + +int vj_tag_set_hue(int t1, int value) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(value < 0 || value > 65535) + { + veejay_msg(VEEJAY_MSG_ERROR,"Hue valid range is 0 - 65535"); + return -1; + } + else + { + if(tag->capture_type==1) + v4lvideo_set_hue( vj_tag_input->unicap[tag->index], value ); +#ifdef HAVE_UNICAP + else + vj_unicap_select_value( vj_tag_input->unicap[tag->index],UNICAP_HUE, (double)value ); +#endif + } + return 1; +} +int vj_tag_set_contrast(int t1,int value) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(value < 0 || value > 65535) + { + veejay_msg(VEEJAY_MSG_ERROR,"Contrast valid range is 0 - 65535"); + return -1; + } + else + { + if(tag->capture_type==1) + v4lvideo_set_contrast( vj_tag_input->unicap[tag->index], value ); +#ifdef HAVE_UNICAP + else + vj_unicap_select_value( vj_tag_input->unicap[tag->index],UNICAP_CONTRAST, (double) value); +#endif + } + return 1; +} +int vj_tag_set_color(int t1, int value) +{ + vj_tag *tag = vj_tag_get(t1); + + if(!tag) return -1; + if(value < 0 || value > 65535) + { + veejay_msg(VEEJAY_MSG_ERROR,"Contrast valid range is 0 - 65535"); + return -1; + } + else + { + if(tag->capture_type==1) + v4lvideo_set_colour( vj_tag_input->unicap[tag->index], value ); +#ifdef HAVE_UNICAP + else + vj_unicap_select_value( vj_tag_input->unicap[tag->index], UNICAP_COLOR, (double)value); +#endif + } + return 1; +} + + +int vj_tag_get_v4l_properties(int t1, + int *brightness, int *contrast, int *hue, int *color, int *white ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(tag->source_type!=VJ_TAG_TYPE_V4L) + { + return -1; + } + + if(tag->capture_type == 1 ) { + *brightness = v4lvideo_get_brightness( vj_tag_input->unicap[tag->index] ); + *contrast = v4lvideo_get_contrast( vj_tag_input->unicap[tag->index] ); + *hue = v4lvideo_get_hue( vj_tag_input->unicap[tag->index] ); + *color = v4lvideo_get_colour( vj_tag_input->unicap[tag->index] ); + *white = v4lvideo_get_white( vj_tag_input->unicap[tag->index] ); + return 0; + } +#ifdef HAVE_UNICAP + if( tag->capture_type == 0 ) { + char **props = vj_unicap_get_list( vj_tag_input->unicap[tag->index] ); + int i; + for( i = 0; props[i] != NULL ; i ++ ) + { + double dvalue = 0.0; + vj_unicap_get_value( vj_tag_input->unicap[tag->index] , + props[i], VEVO_ATOM_TYPE_DOUBLE, &dvalue ); + if(strncasecmp( props[i], "brightness",8) == 0 ) { + *brightness = (int) dvalue; + } else if(strncasecmp( props[i], "hue",3 ) == 0 ) { + *hue = (int) dvalue; + } else if( strncasecmp( props[i], "contrast", 8) == 0 ){ + *contrast = (int) dvalue; + } else if (strncasecmp( props[i], "white", 5 ) == 0 ){ + *white = (int) dvalue; + } else if (strncasecmp( props[i], "color",5 ) == 0 ){ + *color = (int) dvalue; + } + free(props[i]); + } + free(props); + } +#endif + return 0; +} + +int vj_tag_get_effect_any(int t1, int position) { + vj_tag *tag = vj_tag_get(t1); + if(!tag ) + return 0; +#ifdef STRICT_CHECKING + assert( position >= 0 && position < SAMPLE_MAX_EFFECTS ); +#endif + return tag->effect_chain[position]->effect_id; +} + +int vj_tag_chain_malloc(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + int i=0; + int e_id = 0; + int sum =0; +#ifdef STRICT_CHECKING + assert( tag != NULL ); +#endif + + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + e_id = tag->effect_chain[i]->effect_id; + if(e_id!=-1) + { + if(!vj_effect_initialized(e_id)) + { + sum ++; + vj_effect_activate(e_id); + } + } + } + return sum; +} + +int vj_tag_chain_free(int t1) +{ + vj_tag *tag = vj_tag_get(t1); +#ifdef STRICT_CHECKING + assert(tag != NULL ); +#endif + int i=0; + int e_id = 0; + int sum = 0; + + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + e_id = tag->effect_chain[i]->effect_id; + if(e_id!=-1) + { + if(vj_effect_initialized(e_id)) + { + vj_effect_deactivate(e_id); + sum++; + } + } + } + return sum; +} + +int vj_tag_chain_reset_kf( int s1, int entry ) +{ + vj_tag *tag = vj_tag_get(s1); + if (!tag) return -1; + tag->effect_chain[entry]->kf_status = 0; + if(tag->effect_chain[entry]->kf) + vevo_port_free( tag->effect_chain[entry]->kf); + tag->effect_chain[entry]->kf = vpn( VEVO_ANONYMOUS_PORT ); + return 1; +} + +int vj_tag_get_kf_status(int s1, int entry ) +{ + vj_tag *tag = vj_tag_get(s1); + if (!tag) + return 0; + return tag->effect_chain[entry]->kf_status; +} +int vj_tag_get_kf_tokens( int s1, int entry, int id, int *start,int *end, int *type) +{ + vj_tag *tag = vj_tag_get(s1); + if (!tag) + return 0; + return keyframe_get_tokens( tag->effect_chain[entry]->kf,id, start,end,type); +} + + +int vj_tag_chain_set_kf_status( int s1, int entry, int status ) +{ + vj_tag *tag = vj_tag_get(s1); + if (!tag) return -1; + tag->effect_chain[entry]->kf_status = status; + return 1; +} + +unsigned char *vj_tag_chain_get_kfs( int s1, int entry, int parameter_id, int *len ) +{ + vj_tag *tag = vj_tag_get(s1); + if (!tag) + return NULL; + if ( entry < 0 || entry > SAMPLE_MAX_EFFECTS ) + return NULL; + if( parameter_id < 0 || parameter_id > 9 ) + return NULL; + + unsigned char *data = keyframe_pack( tag->effect_chain[entry]->kf, parameter_id,entry, len ); + if( data ) + return data; + return NULL; +} + +void *vj_tag_get_kf_port( int s1, int entry ) +{ + vj_tag *tag = vj_tag_get(s1); + if(!tag) return NULL; + return tag->effect_chain[entry]->kf; +} + + +int vj_tag_chain_set_kfs( int s1, int len, unsigned char *data ) +{ + vj_tag *tag = vj_tag_get(s1); + if (!tag) return -1; + if( len <= 0 ) + { + veejay_msg(0, "Invalid keyframe packet length"); + return -1; + } + + int entry = 0; + if(!keyframe_unpack( data, len, &entry,s1,0) ) + { + veejay_msg(0, "Unable to unpack keyframe packet"); + return -1; + } + + if ( entry < 0 || entry > SAMPLE_MAX_EFFECTS ) + { + veejay_msg(0, "Invalid FX entry in KF packet"); + return -1; + } + + return 1; +} + + + +int vj_tag_set_effect(int t1, int position, int effect_id) +{ + int params, i; + vj_tag *tag = vj_tag_get(t1); + + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + + if( tag->effect_chain[position]->effect_id != -1 && tag->effect_chain[position]->effect_id != effect_id ) + { + //verify if the effect should be discarded + if(vj_effect_initialized( tag->effect_chain[position]->effect_id )) + { + // it is using some memory, see if we can free it ... + int ok = 1; + for(i=(position+1); i < SAMPLE_MAX_EFFECTS; i++) + { + if( tag->effect_chain[i]->effect_id == tag->effect_chain[position]->effect_id) ok = 0; + } + // ok, lets get rid of it. + if( ok ) vj_effect_deactivate( tag->effect_chain[position]->effect_id ); + } + } + + if (!vj_effect_initialized(effect_id)) + { + if(vj_effect_activate( effect_id ) == -1) return -1; + } + + tag->effect_chain[position]->effect_id = effect_id; + tag->effect_chain[position]->e_flag = 1; + params = vj_effect_get_num_params(effect_id); + if (params > 0) { + for (i = 0; i < params; i++) { + int val = 0; + val = vj_effect_get_default(effect_id, i); + tag->effect_chain[position]->arg[i] = val; + } + } + if (vj_effect_get_extra_frame(effect_id)) { + if(tag->effect_chain[position]->source_type < 0) + tag->effect_chain[position]->source_type = tag->source_type; + if(tag->effect_chain[position]->channel <= 0 ) + tag->effect_chain[position]->channel = t1; + } + + if (!vj_tag_update(tag,t1)) + return -1; + return position; +} + +int vj_tag_has_cali_fx( int t1 ) { + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + int i; + for( i = 0; i < SAMPLE_MAX_EFFECTS; i ++ ) { + if( tag->effect_chain[i]->effect_id == VJ_IMAGE_EFFECT_CALI ) + return i; + } + return -1; +} + +void vj_tag_cali_prepare_now( int t1, int fx_id ) { + vj_tag *tag = vj_tag_get(t1); + if(tag==NULL) + return; + if(tag->source_type != VJ_TAG_TYPE_CALI ) + return; + cali_tag_t *p = (cali_tag_t*) vj_tag_input->cali[tag->index]; + if( p == NULL ) + return; + if( fx_id <= 0) + return; + + cali_prepare( vj_effect_get_data(fx_id), + p->mean[0], + p->mean[1], + p->mean[2], + p->data, + vj_tag_input->width * vj_tag_input->height, + vj_tag_input->uv_len ); + +} + +void vj_tag_cali_prepare( int t1 , int pos, int cali_tag) { + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return; + vj_tag *tagc = vj_tag_get(cali_tag); + if(!tagc) + return; + if(tagc->source_type != VJ_TAG_TYPE_CALI) + return; + int fx_id = vj_effect_real_to_sequence( tag->effect_chain[pos]->effect_id ); + if (fx_id >= 0 ) { + vj_tag_cali_prepare_now( cali_tag, fx_id ); + } +} + +int vj_tag_get_chain_status(int t1, int position) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + return tag->effect_chain[position]->e_flag; +} + +int vj_tag_set_chain_status(int t1, int position, int status) +{ + vj_tag *tag = vj_tag_get(t1); + + if (position >= SAMPLE_MAX_EFFECTS) + return -1; + tag->effect_chain[position]->e_flag = status; + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + +int vj_tag_get_trimmer(int t1, int position) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return 0; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return 0; + return tag->effect_chain[position]->frame_trimmer; +} + +int vj_tag_set_trimmer(int t1, int position, int trim) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + tag->effect_chain[position]->frame_trimmer = trim; + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + +int vj_tag_get_all_effect_args(int t1, int position, int *args, + int arg_len, int n_frame) +{ + int i = 0; + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (arg_len == 0 ) + return 1; + if (!args) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + if (arg_len < 0 || arg_len > SAMPLE_MAX_PARAMETERS) + return -1; + + if( tag->effect_chain[position]->kf_status ) + { +#ifdef STRICT_CHECKING + assert( tag->effect_chain[position]->kf != NULL ); +#endif + for( i =0;i effect_chain[position]->kf, n_frame, i ,&tmp ) ) + args[i] = tag->effect_chain[position]->arg[i]; + else + args[i] = tmp; + } + } + else + { + for( i = 0; i < arg_len; i ++ ) + args[i] = tag->effect_chain[position]->arg[i]; + } + + return 1; +} + +int vj_tag_get_effect_arg(int t1, int position, int argnr) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + if (argnr < 0 || argnr > SAMPLE_MAX_PARAMETERS) + return -1; + + return tag->effect_chain[position]->arg[argnr]; +} + +int vj_tag_set_effect_arg(int t1, int position, int argnr, int value) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + if (argnr < 0 || argnr > SAMPLE_MAX_PARAMETERS) + return -1; + + tag->effect_chain[position]->arg[argnr] = value; + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + +int vj_tag_get_type(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + return tag->source_type; +} + +int vj_tag_get_logical_index(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + return tag->index; +} + +int vj_tag_set_logical_index(int t1, int stream_nr) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + tag->index = stream_nr; + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + +int vj_tag_get_depth(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + return tag->index; +} + +int vj_tag_disable(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(tag->active == 0) + { + veejay_msg(VEEJAY_MSG_INFO, "Already inactive"); + return 1; + } + if(tag->source_type == VJ_TAG_TYPE_NET || tag->source_type == VJ_TAG_TYPE_MCAST) + { + net_thread_stop( tag ); + } + if(tag->source_type == VJ_TAG_TYPE_V4L ) + { + if( tag->capture_type == 1 ) { + if(v4lvideo_is_active(vj_tag_input->unicap[tag->index] ) ) + v4lvideo_set_paused( vj_tag_input->unicap[tag->index] , 1 ); + // if(v4lvideo_is_active(vj_tag_input->unicap[tag->index] )) + // v4lvideo_grabstop(vj_tag_input->unicap[tag->index]); + } +#ifdef HAVE_UNICAP + if( tag->capture_type == 0 ) + vj_unicap_set_pause( vj_tag_input->unicap[tag->index], 1 ); +#endif + } + +#ifdef USE_GDK_PIXBUF + if(tag->source_type == VJ_TAG_TYPE_PICTURE ) + { + vj_picture *pic = vj_tag_input->picture[tag->index]; + if(pic) + { + vj_picture_cleanup( pic->pic ); + } + vj_tag_input->picture[tag->index] = pic; + } +#endif + tag->active = 0; + if(!vj_tag_update(tag,t1)) return -1; + return 1; +} + +int vj_tag_enable(int t1) { + vj_tag *tag = vj_tag_get(t1); +#ifdef STRICT_CHECKING + assert( tag != NULL ); +#endif + if( tag->source_type == VJ_TAG_TYPE_V4L ) + { + if(tag->capture_type == 1 ) { + if(!v4lvideo_is_active( vj_tag_input->unicap[tag->index] ) ) { + if(v4lvideo_grabstart( vj_tag_input->unicap[tag->index] ) == 0 ) + { + tag->active = 1; + veejay_msg(VEEJAY_MSG_INFO,"Started continues capturing"); + } else { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to start grabbing."); + } + } else { + if(v4lvideo_is_paused( vj_tag_input->unicap[tag->index] ) ) + v4lvideo_set_paused( vj_tag_input->unicap[tag->index],0); + tag->active = 1; + } + } +#ifdef HAVE_UNICAP + if(tag->capture_type == 0 ) { + int sta = vj_unicap_status( vj_tag_input->unicap[tag->index]); + if( sta == 0 ) + tag->active = vj_unicap_start_capture( vj_tag_input->unicap[tag->index]); + if( vj_unicap_get_pause( vj_tag_input->unicap[tag->index] ) ) + vj_unicap_set_pause( vj_tag_input->unicap[tag->index] , 0 ); + } +#endif + vj_tag_update(tag,t1); + return 1; + } + if(tag->source_type == VJ_TAG_TYPE_NET || tag->source_type == VJ_TAG_TYPE_MCAST ) + { + if(!net_thread_start(vj_tag_input->net[tag->index], tag)) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Unable to start thread"); + return 1; + } + } +#ifdef USE_GDK_PIXBUF + if( tag->source_type == VJ_TAG_TYPE_PICTURE ) + { + vj_picture *p = vj_tag_input->picture[ tag->index ]; + p->pic = vj_picture_open( tag->source_name, + vj_tag_input->width, vj_tag_input->height, + vj_tag_input->pix_fmt ); + + if(!p->pic) + return -1; + + vj_tag_input->picture[tag->index] = p; + veejay_msg(VEEJAY_MSG_DEBUG, "Streaming from picture '%s'", tag->source_name ); + } +#endif + tag->active = 1; + if(!vj_tag_update(tag,t1)) return -1; + return 1; +} + +int vj_tag_set_depth(int t1, int depth) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + tag->depth = depth; + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + + +int vj_tag_set_active(int t1, int active) +{ + vj_tag *tag; + tag = vj_tag_get(t1); + if (!tag) + return -1; + + if(active == tag->active) + return 1; + + switch (tag->source_type) { + case VJ_TAG_TYPE_V4L: + + if(tag->capture_type == 1 ) { + if(active) { + if( !v4lvideo_is_active( vj_tag_input->unicap[tag->index] ) ) { + if(v4lvideo_grabstart( vj_tag_input->unicap[tag->index] ) < 0 ) { + active = 1; + veejay_msg(VEEJAY_MSG_INFO, "Started grabbing "); + } else { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to start grabbing."); + active = 0; + } + } else { + if( v4lvideo_is_paused( vj_tag_input->unicap[tag->index] ) ) + v4lvideo_set_paused( vj_tag_input->unicap[tag->index], 0 ); + } + } + else { + if( !v4lvideo_is_paused( vj_tag_input->unicap[tag->index] ) ) + v4lvideo_set_paused( vj_tag_input->unicap[tag->index], 1 ); + } + } +#ifdef HAVE_UNICAP + else { + if(active) { + int sta =vj_unicap_status( vj_tag_input->unicap[tag->index]); + if(sta == 0 ) + active = vj_unicap_start_capture( vj_tag_input->unicap[tag->index]); + if(active ) { + if( vj_unicap_get_pause( vj_tag_input->unicap[ tag->index] ) ) + vj_unicap_set_pause( vj_tag_input->unicap[tag->index] , 0 ); + } + } else { + if( !vj_unicap_get_pause( vj_tag_input->unicap[ tag->index ] ) ) + vj_unicap_set_pause( vj_tag_input->unicap[tag->index] , 1 ); + } + } +#endif + tag->active = active; + break; + case VJ_TAG_TYPE_YUV4MPEG: + if(active==0) + { + tag->active = 0; + vj_yuv_stream_stop_read( vj_tag_input->stream[tag->index]); + } + break; + case VJ_TAG_TYPE_MCAST: + case VJ_TAG_TYPE_NET: + case VJ_TAG_TYPE_PICTURE: + if(active == 1 ) + vj_tag_enable( t1 ); + else + vj_tag_disable( t1 ); + break; + default: + tag->active = active; + break; + } + + if (!vj_tag_update(tag,t1)) + return -1; + + return 1; +} + +int vj_tag_get_active(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + return tag->active; +} + +int vj_tag_set_chain_channel(int t1, int position, int channel) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + tag->effect_chain[position]->channel = channel; + + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + +int vj_tag_get_chain_channel(int t1, int position) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + return tag->effect_chain[position]->channel; +} +int vj_tag_set_chain_source(int t1, int position, int source) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + tag->effect_chain[position]->source_type = source; + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + +int vj_tag_get_chain_source(int t1, int position) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if (position < 0 || position >= SAMPLE_MAX_EFFECTS) + return -1; + return tag->effect_chain[position]->source_type; +} + +int vj_tag_chain_size(int t1) +{ + int i; + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + for (i = SAMPLE_MAX_EFFECTS - 1; i != 0; i--) { + if (tag->effect_chain[i]->effect_id != -1) + return i; + } + return 0; +} + +int vj_tag_get_effect_status(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return tag->effect_toggle; +} +int vj_tag_get_selected_entry(int t1) { + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + return tag->selected_entry; +} + +int vj_tag_set_effect_status(int t1, int status) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(status==1 || status==0) + { + tag->effect_toggle = status; + return ( vj_tag_update(tag,t1)); + } + return -1; +} + +int vj_tag_set_selected_entry(int t1, int position) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return -1; + if(position < 0 || position >= SAMPLE_MAX_EFFECTS) return -1; + tag->selected_entry = position; + return (vj_tag_update(tag,t1)); +} + +static int vj_tag_chain_can_delete(vj_tag *tag, int s_pos, int e_id) +{ + int i; + for(i=0; i < SAMPLE_MAX_EFFECTS;i++) + { + // effect is on chain > 1 + if(e_id == tag->effect_chain[i]->effect_id && i != s_pos) + { + return 0; + } + } + return 1; +} +int vj_tag_chain_remove(int t1, int index) +{ + int i; + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + if( tag->effect_chain[index]->effect_id != -1) + { + if( vj_effect_initialized( tag->effect_chain[index]->effect_id ) && + vj_tag_chain_can_delete(tag, index, tag->effect_chain[index]->effect_id)) + vj_effect_deactivate( tag->effect_chain[index]->effect_id ); + + if( tag->effect_chain[index]->kf ) + vevo_port_free(tag->effect_chain[index]->kf ); + tag->effect_chain[index]->kf = vpn(VEVO_ANONYMOUS_PORT); + } + + if (tag->effect_chain[index]->effect_id != -1) { + tag->effect_chain[index]->effect_id = -1; + tag->effect_chain[index]->e_flag = 0; + for (i = 0; i < SAMPLE_MAX_PARAMETERS; i++) { + vj_tag_set_effect_arg(t1, index, i, 0); + } + } + if (!vj_tag_update(tag,t1)) + return -1; + return 1; +} + + +void vj_tag_get_source_name(int t1, char *dst) +{ + vj_tag *tag = vj_tag_get(t1); + if (tag) { + sprintf(dst, tag->source_name); + } else { + vj_tag_get_description( tag->source_type, dst ); + } +} + +void vj_tag_get_method_filename(int t1, char *dst) +{ + vj_tag *tag = vj_tag_get(t1); + if (tag) { + if(tag->method_filename != NULL) sprintf(dst, tag->method_filename); + } +} + + +void vj_tag_get_by_type(int type, char *description ) +{ + switch (type) { + case VJ_TAG_TYPE_COLOR: + sprintf(description, "Solid" ); + break; + case VJ_TAG_TYPE_NONE: + sprintf(description, "%s", "EditList"); + break; + case VJ_TAG_TYPE_MCAST: + sprintf(description, "%s", "Multicast"); + break; + case VJ_TAG_TYPE_NET: + sprintf(description, "%s", "Unicast"); + break; +#ifdef USE_GDK_PIXBUF + case VJ_TAG_TYPE_PICTURE: + sprintf(description, "%s", "GdkPixbuf"); + break; +#endif + case VJ_TAG_TYPE_V4L: + sprintf(description, "%s", "Video4Linux"); + break; +#ifdef SUPPORT_READ_DV2 + case VJ_TAG_TYPE_DV1394: + sprintf(description, "%s", "DV1394"); + break; +#endif + case VJ_TAG_TYPE_YUV4MPEG: + sprintf(description, "%s", "YUV4MPEG"); + break; + case VJ_TAG_TYPE_CALI: + sprintf(description, "%s", "Image Calibration"); + break; + } + +} + +void vj_tag_get_descriptive(int id, char *description) +{ + vj_tag *tag = vj_tag_get(id); + if(!tag) + { + sprintf(description, "invalid"); + } + else + { + vj_tag_get_by_type( tag->source_type, description ); + } +} + +/* this method tries to find a tag of given type */ +int vj_tag_by_type(int type) +{ + int min; + for (min = 1; min < this_tag_id; ++min) { + if (vj_tag_get_type(min) == type) + return min; + } + return 0; +} + + + +int vj_tag_set_offset(int t1, int chain_entry, int frame_offset) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + /* set to zero if frame_offset is greater than sample length */ + if (frame_offset < 0) + frame_offset = 0; + + tag->effect_chain[chain_entry]->frame_offset = frame_offset; + if (!vj_tag_update(tag,t1)) + return 0; + return 1; +} + +int vj_tag_get_offset(int t1, int chain_entry) +{ + vj_tag *tag = vj_tag_get(t1); + if (!tag) + return -1; + + return tag->effect_chain[chain_entry]->frame_offset; +} + +int vj_tag_get_encoded_frames(int s1) { + vj_tag *si = vj_tag_get(s1); + if(!si) return -1; + return ( si->encoder_succes_frames ); + //return ( si->encoder_total_frames ); +} + +long vj_tag_get_duration(int s1) +{ + vj_tag *t = vj_tag_get(s1); + if(!t) return -1; + return ( t->encoder_duration ); +} + + +long vj_tag_get_total_frames( int s1 ) +{ + vj_tag *si = vj_tag_get(s1); + if(!si) return -1; + return ( si->encoder_total_frames ); +// return si->encoder_succes_frames; +} + +int vj_tag_reset_autosplit(int s1) +{ + vj_tag *si = vj_tag_get(s1); + if(!si) return -1; + bzero( si->encoder_base, 255 ); + bzero( si->encoder_destination , 255 ); + si->sequence_num = 0; + return (vj_tag_update(si,s1)); +} + +int vj_tag_get_frames_left(int s1) +{ + vj_tag *si= vj_tag_get(s1); + if(!si) return 0; + return ( si->encoder_duration - si->encoder_total_frames ); +} + +int vj_tag_encoder_active(int s1) +{ + vj_tag *si = vj_tag_get(s1); + if(!si)return 0; + return si->encoder_active; +} + +int vj_tag_var(int t1, int *type, int *fader, int *fx_sta , int *rec_sta, int *active ) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) return 0; + *fader = tag->fader_active; + *fx_sta = tag->effect_toggle; + *rec_sta = tag->encoder_active; + *type = tag->source_type; + *active = tag->active; + return 1; +} + +int vj_tag_record_frame(int t1, uint8_t *buffer[3], uint8_t *abuff, int audio_size,int pixel_format) { + vj_tag *tag = vj_tag_get(t1); + int buf_len = 0; + if(!tag) return -1; + + if(!tag->encoder_active) return -1; + + /* + int buf_len = encode_jpeg_raw( tag->encoder_buf, tag->encoder_max_size, 100, 0,0,tag->encoder_width, + tag->encoder_height, buffer[0], buffer[1], buffer[2]); + */ + + buf_len = vj_avcodec_encode_frame( tag->encoder, tag->encoder_total_frames ++, tag->encoder_format, buffer, vj_avcodec_get_buf(tag->encoder), tag->encoder_max_size, pixel_format); + if(buf_len <= 0 ) + { + return -1; + } + tag->rec_total_bytes += buf_len; + + + if(tag->encoder_file ) { + if(lav_write_frame(tag->encoder_file, vj_avcodec_get_buf(tag->encoder), buf_len,1)) + { + veejay_msg(VEEJAY_MSG_ERROR, "writing frame, giving up :[%s]", lav_strerror()); + return -1; + } + + if(audio_size > 0) + { + if(lav_write_audio(tag->encoder_file, abuff, audio_size)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error writing output audio [%s]",lav_strerror()); + } + tag->rec_total_bytes += ( audio_size * _tag_info->edit_list->audio_bps); + } + } + /* write OK */ + tag->encoder_succes_frames ++; + tag->encoder_num_frames ++; + + vj_tag_update(tag,t1); + + return (vj_tag_continue_record(t1)); +} + +int vj_tag_get_audio_frame(int t1, uint8_t *dst_buffer) +{ + return 0; +} + + +/* ccd image calibration + */ + +static uint8_t *blackframe_new( int w, int h, int uv_len, uint8_t *Y, uint8_t *U, uint8_t *V, int median_radius, vj_tag *tag ) { + uint8_t *buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * 5 * ((w*h) + 2 * uv_len )); + if(buf == NULL) { + veejay_msg(0,"Insufficient memory to initialize calibration."); + return NULL; + } + veejay_memset( buf, 0, sizeof(uint8_t) * 5 * ((w*h)+2*uv_len)); + tag->blackframe = buf; +#ifdef STRICT_CHECKING + assert( uv_len == ( (w/2) * h )); +#endif + const int chroma=127; + + tag->lf = (double*) vj_malloc(sizeof(double) * (w*h)); + tag->lfu= (double*) vj_malloc(sizeof(double) *uv_len); + tag->lfv= (double*) vj_malloc(sizeof(double) *uv_len); + + tag->bf = (double*) vj_malloc(sizeof(double) * (w*h)); + tag->bfu= (double*) vj_malloc(sizeof(double) * uv_len); + tag->bfv= (double*) vj_malloc(sizeof(double) * uv_len); + + if(median_radius== 0 ) { + int i; + for(i = 0; i < (w*h); i ++ ) { + tag->lf[i] = 0.0f; + tag->bf[i] = 0.0f + (double) Y[i]; + } + for(i = 0; i < uv_len; i ++ ) { + tag->lfu[i] = 0.0f; + tag->lfv[i] = 0.0f; + tag->bfu[i] = 0.0f + (double) (U[i] - chroma); + tag->bfv[i] = 0.0f + (double) (V[i] - chroma); + } + + } else { + uint8_t *ptr = cali_get(tag,CALI_BUF,w*h,uv_len); + ctmf( Y, ptr, w,h,w,w,median_radius,1,512*1024); + ctmf( U, ptr + (w*h),w/2,h,w/2,w/2,median_radius,1,512*1024); + ctmf( V, ptr + (w*h)+uv_len,w/2,h,w/2,w/2,median_radius,1,512*1024); + int i; + for(i = 0; i < (w*h); i ++ ) { + tag->lf[i] = 0.0f; + tag->bf[i] = 0.0f + (double) ptr[i]; + } + uint8_t *ptru = ptr + (w*h); + uint8_t *ptrv = ptru + uv_len; + for(i = 0; i < uv_len; i ++ ) { + tag->lfu[i] = 0.0f; + tag->lfv[i] = 0.0f; + tag->bfu[i] = 0.0f + (double) (ptru[i] - chroma); + tag->bfv[i] = 0.0f + (double) (ptrv[i] - chroma); + } + + } + + return buf; +} + +static void blackframe_process( uint8_t *Y, uint8_t *U, uint8_t *V, int w, int h, int uv_len, int median_radius, vj_tag *tag ) +{ + int i; + uint8_t *bf = cali_get(tag,CALI_DARK,w*h,uv_len); + const int chroma = 127; + double *blackframe = tag->bf; + double *blackframeu= tag->bfu; + double *blackframev= tag->bfv; + + //@ YUV = input frame + if( median_radius > 0 ) { + bf = cali_get(tag,CALI_BUF,w*h,uv_len); + } + + uint8_t *bu = bf + (w*h); + uint8_t *bv = bu + uv_len; + + uint8_t *srcY = Y; + uint8_t *srcU = U; + uint8_t *srcV = V; + + if( median_radius > 0 ) { + ctmf( Y, bf, w,h,w,w,median_radius,1,512*1024); + ctmf( U, bu, w/2,h,w/2,w/2,median_radius,1,512*1024); + ctmf( V, bv, w/2,h,w/2,w/2,median_radius,1,512*1024); + srcY = bf; + srcU = bu; + srcV = bv; + } + + for( i = 0; i < (w*h); i ++ ) { + blackframe[i] += srcY[i]; + } + for( i =0 ; i < uv_len; i ++ ) { + blackframeu[i] += (double) ( srcU[i] - chroma ); + blackframev[i] += (double) ( srcV[i] - chroma ); + } +} +static void whiteframe_new(uint8_t *buf, int w, int h, int uv_len, uint8_t *Y, uint8_t *U, uint8_t *V, int median_radius, vj_tag *tag ) { + int i; + uint8_t *bf = cali_get( tag,CALI_DARK,w*h,uv_len); + uint8_t *bu = bf + (w*h); + uint8_t *bv = bu + uv_len; + int p; + const int chroma = 127; + + double mean_of_y = 0.0; + double mean_of_u = 0.0f; + double mean_of_v = 0.0f; + + + if(median_radius > 0 ) { + uint8_t *ptr = cali_get(tag,CALI_BUF,w*h,uv_len); + ctmf( Y, ptr, w,h,w,w,median_radius,1,512*1024); + ctmf( U, ptr + (w*h),w/2,h,w/2,w/2,median_radius,1,512*1024); + ctmf( V, ptr + (w*h)+uv_len,w/2,h,w/2,w/2,median_radius,1,512*1024); + int i; + for(i = 0; i < (w*h); i ++ ) { + tag->lf[i] = 0.0f + (double) ptr[i] - bf[i]; + mean_of_y += tag->lf[i]; + } + uint8_t *ptru = ptr + (w*h); + uint8_t *ptrv = ptru + uv_len; + for(i = 0; i < uv_len; i ++ ) { + tag->lfu[i] = 0.0f + (double) (ptru[i] - chroma) - (bu[i]-chroma); + mean_of_u += tag->lfu[i]; + tag->lfv[i] = 0.0f + (double) (ptrv[i] - chroma) - (bv[i]-chroma); + mean_of_v += tag->lfv[i]; + } + } else { + for(i = 0; i < (w*h); i ++ ) { //@FIXME subtract dark current + p = Y[i] - bf[i]; + if( p < 0 ) p = 0; + tag->lf[i] = 0.0f + (double)p; + mean_of_y += p; + } + for(i = 0; i < uv_len; i ++ ) { + p = ( (U[i]-chroma) - (bu[i]-chroma)); + tag->lfu[i] = 0.0f + (double)p; + mean_of_u += p; + p = ( (V[i]-chroma) - (bv[i]-chroma)); + tag->lfv[i] = 0.0f + (double) p; + mean_of_v += p; + } + + } + + mean_of_y = mean_of_y / (w*h); + + tag->tabmean[0][ tag->bf_count - 1 ] = mean_of_y; + + mean_of_u = mean_of_u / uv_len; + mean_of_v = mean_of_v / uv_len; + +} + +static void whiteframe_process( uint8_t *Y, uint8_t *U, uint8_t *V, int w, int h, int uv_len, int median_radius, vj_tag *tag) +{ + int i; + const int chroma = 127; + + double *lightframe = tag->lf; + double *lightframe_u = tag->lfu; + double *lightframe_v = tag->lfv; + + uint8_t *bf = cali_get( tag,CALI_DARK,w*h,uv_len); + uint8_t *bu = bf + (w*h); + uint8_t *bv = bu + uv_len; + double mean_of_y = 0.0; + double mean_of_u = 0.0f; + double mean_of_v = 0.0f; + + + //@ YUV = input frame + if( median_radius > 0 ) { + uint8_t *dbf = cali_get( tag,CALI_BUF,w*h,uv_len ); + uint8_t *dbu = dbf + (w*h); + uint8_t *dbv = dbu + uv_len; + ctmf( Y, dbf, w,h,w,w,median_radius,1,512*1024); + for( i = 0; i < (w*h); i ++ ) { + lightframe[i] += (double)(dbf[i] - bf[i]); + mean_of_y += lightframe[i]; + } + ctmf( U, dbu, w/2,h,w/2,w/2,median_radius,1,512*1024); + ctmf( V, dbv, w/2,h,w/2,w/2,median_radius,1,512*1024); + for( i =0 ; i < uv_len; i ++ ) { + lightframe_u[i] += (double) ( dbu[i]-chroma ) - ( bu[i]-chroma); + mean_of_u += lightframe_u[i]; + lightframe_v[i] += (double) ( dbv[i]-chroma ) - ( bv[i]-chroma); + mean_of_v += lightframe_v[i]; + } + + } else { + int p; + //@ should subtract dark current, FIXME + for( i = 0; i < (w*h); i ++ ) { + p = Y[i] - bf[i]; + if( p < 0 ) + p = 0; + lightframe[i] += (double) p; + mean_of_y += p; + } + for( i =0 ; i < uv_len; i ++ ) { + p = ((U[i]-chroma)-(bu[i]-chroma)); + lightframe_u[i] += (double) p; + mean_of_u += p; + p = ((V[i]-chroma)-(bv[i]-chroma)); + lightframe_v[i] += (double) p; + mean_of_v += p; + } + } + + mean_of_y = mean_of_y / (w*h); + mean_of_u = mean_of_u / uv_len; + mean_of_v = mean_of_v / uv_len; + tag->tabmean[0][ tag->bf_count - 1 ] = mean_of_y; +} + +static void master_lightframe(int w,int h, int uv_len, vj_tag *tag) +{ + int i; + int duration =tag->cali_duration -1; + uint8_t *bf = cali_get(tag,CALI_LIGHT,w*h,uv_len); + uint8_t *bu = bf + (w*h); + uint8_t *bv = bu + uv_len; + + int len = w*h; + int v; + + double *sY = tag->lf; + double *sU = tag->lfu; + double *sV = tag->lfv; + const int chroma = 127; + + + double sum = 0.0; + + for( i = 0; i < len; i ++ ) { + if( sY[i] <= 0 ) + bf[i] = 0; + else + { + bf[i] = (uint8_t) ( sY[i] / duration ); + } + sum += bf[i]; + } + + sum = sum / len; + + for( i = 0; i cali_duration - 1; + uint8_t *bf = cali_get(tag,CALI_DARK,w*h,uv_len); + uint8_t *bu = bf + (w*h); + uint8_t *bv = bu + uv_len; + int len = w*h; + int v; + double *sY = tag->bf; + double *sU = tag->bfu; + double *sV = tag->bfv; + const int chroma = 127; + for( i = 0; i < len; i ++ ) { + if( sY[i] <= 0 ) + bf[i] = 0; + else + { + bf[i] = (uint8_t) ( sY[i] / duration ); + } + } + + for( i = 0; i mean[0] = mean_y; + tag->mean[1] = mean_u; + tag->mean[2] = mean_v; + +} + +static void blackframe_subtract( vj_tag *tag, uint8_t *Y, uint8_t *U, uint8_t *V, int w, int h, int uv_len,int use_light,const double mean_y,const double mean_u,const double mean_v ) +{ + int i; + uint8_t *bf = cali_get(tag, CALI_DARK,w*h,uv_len); + uint8_t *u = bf + (w*h); + uint8_t *v = u + uv_len; + + uint8_t *wy = cali_get(tag, CALI_FLAT,w*h,uv_len); + uint8_t *wu = wy + (w*h); + uint8_t *wv = wu + uv_len; + uint8_t *bu = bf + (w*h); + uint8_t *bv = bu + uv_len; + int min_Y = get_pixel_range_min_Y(); + const int chroma = 127; + + int d=0; + double p = 0.0; + const double dmean_y = (double) mean_y; + const double dmean_u = (double) mean_u; + const double dmean_v = (double) mean_v; + //@ process master flat image + + if( use_light ) { + for( i = 0; i <(w*h); i ++ ) { + p = (double) wy[i] /dmean_y; + if( p != 0.0 ) + d = (int) ( ( (double)Y[i] - bf[i]) / p); + else + d = 0.0f; //Y[i] - bf[i]; + + if( d < 0 ) d = 0; else if ( d > 255 ) d = 255; + + Y[i] = (uint8_t) d; + + } + + int d1=0; + for( i =0 ; i < uv_len; i ++ ) + { + p = (double) wu[i] / dmean_u; + d1 = (double) ( chroma + ((U[i] - chroma) - (bu[i]-chroma))); + if( d1 == 0 ) + d = chroma; + else + d = (int) ( d1 / p ); + + if ( d < 0 ) { d = 0; } else if ( d > 255 ) { d = 255;} + + U[i] = (uint8_t) d; + + p = ( wv[i] / dmean_v ); + d1 = ( double) (chroma + ((V[i] - chroma) - (bv[i]-chroma))); + if( d1 == 0 ) + d= chroma; + else + d = (int) ( d1 / p ); + if( d < 0 ) { d = 0; } else if ( d > 255 ) { d= 255; } + V[i] = (uint8_t) d; + } + + } else { + //@ just show result of frame - dark current + for( i = 0; i <(w*h); i ++ ) { + p = ( Y[i] - bf[i] ); + if( p < 0 ) + Y[i] = 0; + else + Y[i] = p; + } + for( i = 0; i < uv_len; i ++ ) { + p = U[i] - bu[i]; + if( p < 0 ) + U[i] = chroma; + else + U[i] = p; + + p = V[i] - bv[i]; + if( p < 0 ) + V[i] = chroma; + else + V[i] = p; + } + } + + + + +} + +#define V4L_WHITEFRAME 4 +#define V4L_WHITEFRAME_NEXT 5 +#define V4L_WHITEFRAME_PROCESS 6 +int vj_tag_grab_blackframe(int t1, int duration, int median_radius , int mode) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return 0; + if( tag->source_type != VJ_TAG_TYPE_V4L ) { + veejay_msg(VEEJAY_MSG_INFO, "Source is not a video device."); + return 0; + } + + if( duration <= 0 ) + return 0; + + if( median_radius <= 0 ) { + median_radius = 0; + } + + veejay_msg(VEEJAY_MSG_INFO, "Creating %s (%d frames) median=%d",(mode==0?"Blackframe":"Lightframe"),duration, median_radius ); + + tag->noise_suppression = (mode == 0 ? V4L_BLACKFRAME : V4L_WHITEFRAME ); + tag->median_radius = median_radius; + tag->bf_count = duration; + tag->has_white = (mode == 1 ? 1 :0); + return 1; +} +int vj_tag_drop_blackframe(int t1) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return 0; + if( tag->source_type != VJ_TAG_TYPE_V4L ) { + veejay_msg(VEEJAY_MSG_INFO, "Source is not a video device."); + return 0; + } + if( tag->blackframe ) { + tag->noise_suppression = -1; + veejay_msg(VEEJAY_MSG_INFO, "Black Frame dropped."); + } + + return 1; +} + + + +int vj_tag_get_frame(int t1, uint8_t *buffer[3], uint8_t * abuffer) +{ + vj_tag *tag = vj_tag_get(t1); + if(!tag) + return -1; + + const int width = vj_tag_input->width; + const int height = vj_tag_input->height; + const int uv_len = vj_tag_input->uv_len; + const int len = (width * height); + + + switch (tag->source_type) + { + case VJ_TAG_TYPE_V4L: + if( tag->capture_type == 1 ) { + int res = v4lvideo_copy_framebuffer_to(vj_tag_input->unicap[tag->index],buffer[0],buffer[1],buffer[2]); + if( res <= 0 ) { + veejay_memset( buffer[0], 0, len ); + veejay_memset( buffer[1], 128, uv_len ); + veejay_memset( buffer[2], 128, uv_len ); + } + } +#ifdef HAVE_UNICAP + else { + if(vj_unicap_status(vj_tag_input->unicap[tag->index]) ) + vj_unicap_grab_frame( vj_tag_input->unicap[tag->index], buffer, width,height ); + } +#endif + switch( tag->noise_suppression ) { + case V4L_BLACKFRAME: + tag->cali_duration = tag->bf_count; + blackframe_new(width,height,uv_len,buffer[0],buffer[1],buffer[2],tag->median_radius,tag); + tag->tabmean[0] = (double*) vj_malloc(sizeof(double)* tag->cali_duration); + if(tag->blackframe == NULL ) { + tag->noise_suppression = 0; + } else { + tag->bf_count --; + tag->noise_suppression = V4L_BLACKFRAME_NEXT; + if(tag->bf_count==0) { + master_blackframe(width,height,uv_len,tag); + tag->noise_suppression = V4L_BLACKFRAME_PROCESS; + veejay_msg(VEEJAY_MSG_INFO, "Please create a lightframe (white)"); + } + } + //@ grab black frame + break; + case V4L_WHITEFRAME: + tag->cali_duration = tag->bf_count; + if(!tag->blackframe) { + veejay_msg(0, "Please start with a black frame first (Put cap on lens)"); + tag->noise_suppression = 0; + break; + } + whiteframe_new( tag->blackframe,width,height,uv_len,buffer[0],buffer[1],buffer[2],tag->median_radius, tag); + tag->bf_count --; + tag->noise_suppression = V4L_WHITEFRAME_NEXT; + if(tag->bf_count <= 0 ) { + tag->noise_suppression = V4L_BLACKFRAME_PROCESS; + master_lightframe( width,height,uv_len,tag ); + master_flatframe( width,height,uv_len, tag ); + veejay_msg(VEEJAY_MSG_DEBUG, "Master flat frame."); + } + break; + case V4L_WHITEFRAME_NEXT: + whiteframe_process(buffer[0],buffer[1],buffer[2],width,height,uv_len,tag->median_radius,tag ); + tag->bf_count --; + if( tag->bf_count <= 0 ) { + tag->noise_suppression = V4L_BLACKFRAME_PROCESS; + master_lightframe( width,height,uv_len,tag); + master_flatframe( width,height,uv_len, tag ); + veejay_msg(VEEJAY_MSG_DEBUG, "Master flat frame"); + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "Whiteframe %d",tag->bf_count ); + } + break; + case V4L_BLACKFRAME_NEXT: + blackframe_process( buffer[0],buffer[1],buffer[2],width,height,uv_len, tag->median_radius,tag ); + if( tag->bf_count <= 0 ) { + tag->noise_suppression = 0; + master_blackframe(width,height,uv_len,tag); + veejay_msg(VEEJAY_MSG_INFO, "Please create a lightframe."); + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "Blackframe %d", tag->bf_count ); + tag->bf_count --; + } + break; + case V4L_BLACKFRAME_PROCESS: + blackframe_subtract( tag,buffer[0],buffer[1],buffer[2],width,height,uv_len, tag->has_white , tag->mean[0],tag->mean[1],tag->mean[2]); + break; + case -1: + if( tag->blackframe ) { + free(tag->blackframe); + tag->blackframe = NULL; + tag->noise_suppression = 0; + } + if( tag->bf ) free(tag->bf); + if( tag->bfu ) free(tag->bfu); + if( tag->bfv ) free(tag->bfv); + if( tag->lf ) free(tag->lf); + if( tag->lfu ) free(tag->lfu); + if( tag->lfv ) free(tag->lfv); + if( tag->tabmean[0]) free(tag->tabmean[0]); + break; + //@ process black frame + default: + break; + } + if( tag->noise_suppression != 0 && tag->noise_suppression != 6 && tag->noise_suppression != 3 ) + veejay_msg(VEEJAY_MSG_DEBUG, "Calibration step %d of %d", tag->bf_count, tag->cali_duration ); + + return 1; + break; + case VJ_TAG_TYPE_CALI: + { + cali_tag_t *p = (cali_tag_t*)vj_tag_input->cali[tag->index]; + if(p) { + veejay_memcpy(buffer[0], p->mf, len ); + veejay_memcpy(buffer[1], p->mf + len, uv_len ); + veejay_memcpy(buffer[2], p->mf + len + uv_len, uv_len); + } + } + break; +#ifdef USE_GDK_PIXBUF + case VJ_TAG_TYPE_PICTURE: + { + vj_picture *p = vj_tag_input->picture[tag->index]; + if(!p) + { + veejay_msg(VEEJAY_MSG_ERROR, "Picture never opened"); + vj_tag_disable(t1); + return -1; + } + VJFrame *pframe = vj_picture_get( p->pic ); + veejay_memcpy(buffer[0],pframe->data[0], len); + veejay_memcpy(buffer[1],pframe->data[1], uv_len); + veejay_memcpy(buffer[2],pframe->data[2], uv_len); + } + break; +#endif + case VJ_TAG_TYPE_MCAST: + case VJ_TAG_TYPE_NET: + if(!net_thread_get_frame( tag,buffer )) + return 0; + return 1; + break; + case VJ_TAG_TYPE_YUV4MPEG: + if(vj_yuv_get_frame(vj_tag_input->stream[tag->index], _temp_buffer) != 0) + { + vj_tag_set_active(t1,0); + return -1; + } + + yuv420to422planar( _temp_buffer, buffer, width,height ); + veejay_memcpy( buffer[0],_temp_buffer[0],width * height ); + return 1; + + break; +#ifdef SUPPORT_READ_DV2 + case VJ_TAG_TYPE_DV1394: + vj_dv1394_read_frame( vj_tag_input->dv1394[tag->index], buffer , abuffer,vj_tag_input->pix_fmt); + break; +#endif + + case VJ_TAG_TYPE_COLOR: + _tmp.len = len; + _tmp.uv_len = uv_len; + _tmp.data[0] = buffer[0]; + _tmp.data[1] = buffer[1]; + _tmp.data[2] = buffer[2]; + dummy_rgb_apply( &_tmp, width, height, + tag->color_r,tag->color_g,tag->color_b ); + break; + + case VJ_TAG_TYPE_NONE: + break; + default: + break; + } + return 1; +} + + +//int vj_tag_sprint_status(int tag_id, int entry, int changed, char *str) +int vj_tag_sprint_status( int tag_id,int cache,int sa, int ca, int pfps,int frame, int mode,int ts,int curfps, uint32_t lo, uint32_t hi, int macro, char *str ) +{ + vj_tag *tag; + tag = vj_tag_get(tag_id); +#ifdef STRICT_CHECKING + assert( tag != NULL ); +#endif + //if (!tag) + //return -1; + + veejay_sprintf(str, 1024, + "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + pfps, + frame, + mode, + tag_id, + tag->effect_toggle, + tag->color_r, // no start, but color + tag->color_g, // no end, + tag->color_b, // no speed, + 0, // no looping + tag->encoder_active, + tag->encoder_duration, + tag->encoder_succes_frames, + vj_tag_size()-1, + tag->source_type, // no markers + tag->n_frames, // no markers + tag->selected_entry, + ts, + cache, + curfps, + lo, + hi, + sa, + ca, + (int)(tag->fader_val), + 0, + macro); + return 0; +} + +#ifdef HAVE_XML2 +static void tagParseArguments(xmlDocPtr doc, xmlNodePtr cur, int *arg) +{ + xmlChar *xmlTemp = NULL; + unsigned char *chTemp = NULL; + int argIndex = 0; + if (cur == NULL) + return; + + while (cur != NULL && argIndex < SAMPLE_MAX_PARAMETERS) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_ARGUMENT)) + { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + arg[argIndex] = atoi(chTemp); + argIndex++; + } + + if (xmlTemp) + xmlFree(xmlTemp); + if (chTemp) + free(chTemp); + + } + // xmlTemp and chTemp should be freed after use + xmlTemp = NULL; + chTemp = NULL; + cur = cur->next; + } +} +static int tagParseKeys( xmlDocPtr doc, xmlNodePtr cur, void *port ) +{ + if(!cur) + return 0; + + while (cur != NULL) + { + if( !xmlStrcmp( cur->name, (const xmlChar*) "KEYFRAMES" )) + { + keyframe_xml_unpack( doc, cur->xmlChildrenNode, port ); + } + cur = cur->next; + } + return 1; +} + +static void tagParseEffect(xmlDocPtr doc, xmlNodePtr cur, int dst_sample) +{ + xmlChar *xmlTemp = NULL; + unsigned char *chTemp = NULL; + int effect_id = -1; + int arg[SAMPLE_MAX_PARAMETERS]; + int i; + int source_type = 0; + int channel = 0; + int frame_trimmer = 0; + int frame_offset = 0; + int e_flag = 0; + int volume = 0; + int anim= 0; + int a_flag = 0; + int chain_index = 0; + + for (i = 0; i < SAMPLE_MAX_PARAMETERS; i++) { + arg[i] = 0; + } + + if (cur == NULL) + return; + + // int k = 0; + // void *ports[8]; + // veejay_memset( ports,0,sizeof(ports)); + + + xmlNodePtr curarg = cur; + + while (cur != NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTID)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + effect_id = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTPOS)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + chain_index = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTSOURCE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + source_type = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTCHANNEL)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + channel = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTTRIMMER)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + frame_trimmer = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTOFFSET)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + frame_offset = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) "kf_status")) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + anim = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTACTIVE)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + e_flag = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + + } + + if (!xmlStrcmp + (cur->name, (const xmlChar *) XMLTAG_EFFECTAUDIOFLAG)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + a_flag = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + + } + + if (!xmlStrcmp + (cur->name, (const xmlChar *) XMLTAG_EFFECTAUDIOVOLUME)) { + xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + volume = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + } + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_ARGUMENTS)) { + tagParseArguments(doc, cur->xmlChildrenNode, arg ); + } + + // xmlTemp and chTemp should be freed after use + xmlTemp = NULL; + chTemp = NULL; + cur = cur->next; + } + + if (effect_id != -1) { + int j; + int res = vj_tag_set_effect( dst_sample, chain_index, effect_id ); + + if(res < 0 ) + veejay_msg(VEEJAY_MSG_ERROR, "Error parsing effect %d (pos %d) to stream %d\n", + effect_id, chain_index, dst_sample); + + + /* load the parameter values */ + for (j = 0; j < vj_effect_get_num_params(effect_id); j++) { + vj_tag_set_effect_arg(dst_sample, chain_index, j, arg[j]); + } + vj_tag_set_chain_channel(dst_sample, chain_index, channel); + vj_tag_set_chain_source(dst_sample, chain_index, source_type); + + vj_tag_set_chain_status(dst_sample, chain_index, e_flag); + + vj_tag_set_offset(dst_sample, chain_index, frame_offset); + vj_tag_set_trimmer(dst_sample, chain_index, frame_trimmer); + + j = 0; + vj_tag *t = vj_tag_get( dst_sample ); + while (curarg != NULL) + { + if(!xmlStrcmp(curarg->name,(const xmlChar*)"ANIM")) + { + if(t->effect_chain[chain_index]->effect_id > 0) + { + if(tagParseKeys( doc, curarg->xmlChildrenNode, t->effect_chain[chain_index]->kf)) + { + veejay_msg(VEEJAY_MSG_INFO, "Animating FX %d on entry %d (status=%d)", t->effect_chain[chain_index]->effect_id, j,anim); + vj_tag_chain_set_kf_status(dst_sample, chain_index, anim ); + } + j++; + } + } + curarg = curarg->next; + } + + } + + + +} + +/************************************************************************************************* + * + * ParseEffect() + * + * Parse the effects array + * + ****************************************************************************************************/ +static void tagParseEffects(xmlDocPtr doc, xmlNodePtr cur, int dst_stream) +{ + int effectIndex = 0; + while (cur != NULL && effectIndex < SAMPLE_MAX_EFFECTS) { + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECT)) { + tagParseEffect(doc, cur->xmlChildrenNode, dst_stream); + effectIndex++; + } + //effectIndex++; + cur = cur->next; + } +} + +void tagParseCalibration( xmlDocPtr doc, xmlNodePtr cur, int dst_sample , void *vp) +{ + vj_tag *t = vj_tag_get( dst_sample ); + void *tmp = viewport_load_xml( doc, cur, vp ); + if( tmp ) + t->viewport_config = tmp; +} + +/************************************************************************************************* + * + * ParseSample() + * + * Parse a sample + * + ****************************************************************************************************/ + +static int tag_get_int_xml( xmlDocPtr doc, xmlNodePtr cur, const xmlChar *key ) +{ + xmlChar *xmlTemp = xmlNodeListGetString( doc, cur->xmlChildrenNode,1); + char *chTemp = UTF8toLAT1( xmlTemp ); + int res = 0; + if(chTemp) + { + res = atoi(chTemp); + free(chTemp); + } + if(xmlTemp) xmlFree(xmlTemp); + return res; +} + +static char *tag_get_char_xml( xmlDocPtr doc, xmlNodePtr cur, const xmlChar *key ) +{ + xmlChar *xmlTemp = xmlNodeListGetString( doc, cur->xmlChildrenNode,1); + char *chTemp = UTF8toLAT1( xmlTemp ); + int res = 0; + if(xmlTemp) xmlFree(xmlTemp); + return chTemp; +} + +void tagParseStreamFX(char *sampleFile, xmlDocPtr doc, xmlNodePtr cur, void *font, void *vp) +{ + + xmlChar *xmlTemp = NULL; + unsigned char *chTemp = NULL; + + int fx_on=0, id=0, source_id=0, source_type=0; + char *source_file = NULL; + char *extra_data = NULL; + int col[3] = {0,0,0}; + int fader_active=0, fader_val=0, fader_dir=0, opacity=0, nframes=0; +#ifdef STRICT_CHECKING + assert( _tag_info != NULL ); +#endif + + xmlNodePtr fx[32]; + veejay_memset( fx, 0, sizeof(fx)); + int k = 0; + + xmlNodePtr subs = NULL; + xmlNodePtr cali = NULL; + void *d = vj_font_get_dict( font ); + void *viewport_config = NULL; + + while (cur != NULL) + { + if( !xmlStrcmp(cur->name, (const xmlChar*) XMLTAG_SAMPLEID )) + id = tag_get_int_xml(doc,cur,XMLTAG_SAMPLEID ); + if( !xmlStrcmp(cur->name, (const xmlChar*) "source_id" ) ) + source_id = tag_get_int_xml(doc,cur,"source_id" ); + if( !xmlStrcmp(cur->name, (const xmlChar*) "source_type" ) ) + source_type = tag_get_int_xml(doc,cur,"source_type" ); + if( !xmlStrcmp(cur->name, (const xmlChar*) "source_file" ) ) + source_file = tag_get_char_xml(doc,cur, "source_file"); + if( !xmlStrcmp(cur->name, (const xmlChar*) "extra_data" )) + extra_data = tag_get_char_xml(doc,cur, "extra_data"); + + if(! xmlStrcmp(cur->name, (const xmlChar*) "red" ) ) + col[0] = tag_get_int_xml( doc,cur, "red" ); + if(! xmlStrcmp(cur->name, (const xmlChar*) "green" ) ) + col[1] = tag_get_int_xml( doc, cur, "green" ); + if(! xmlStrcmp(cur->name, (const xmlChar*) "blue" )) + col[2] = tag_get_int_xml( doc, cur, "blue" ); + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_CHAIN_ENABLED)) + fx_on = tag_get_int_xml(doc,cur, XMLTAG_CHAIN_ENABLED ); + if (!xmlStrcmp(cur->name,(const xmlChar *) XMLTAG_FADER_ACTIVE)) + fader_active = tag_get_int_xml(doc,cur, XMLTAG_FADER_ACTIVE); + if (!xmlStrcmp(cur->name,(const xmlChar *) XMLTAG_FADER_VAL)) + fader_val = tag_get_int_xml( doc,cur,XMLTAG_FADER_VAL ); + if (!xmlStrcmp(cur->name,(const xmlChar*) XMLTAG_FADER_DIRECTION)) + fader_dir = tag_get_int_xml( doc, cur, XMLTAG_FADER_DIRECTION ); + if (!xmlStrcmp(cur->name,(const xmlChar*) "opacity" ) ) + opacity = tag_get_int_xml( doc, cur, "opacity"); + if (!xmlStrcmp(cur->name,(const xmlChar*) "nframes" ) ) + nframes = tag_get_int_xml(doc, cur, "nframes" ); + + if (!xmlStrcmp(cur->name, (const xmlChar*) "SUBTITLES" )) + subs = cur->xmlChildrenNode; + + if (!xmlStrcmp(cur->name, (const xmlChar*) "calibration" )) + cali = cur->xmlChildrenNode; + + if (!xmlStrcmp(cur->name, (const xmlChar *) XMLTAG_EFFECTS)) { + fx[k] = cur->xmlChildrenNode; + k++; + } + + cur = cur->next; + } + + if( id > 0 ) + { + int zer = 0; + + if( source_type == VJ_TAG_TYPE_V4L && extra_data ) + sscanf( extra_data, "%d",&zer ); + + vj_tag_del( id ); + + int n_id = vj_tag_new( source_type, source_file, _tag_info->nstreams,_tag_info->current_edit_list, + _tag_info->pixel_format, source_id,zer, _tag_info->settings->composite ); + + if(n_id > 0 ) + { + vj_tag *tag = vj_tag_get( n_id ); +#ifdef STRICT_CHECKING + assert( tag != NULL ); +#endif + tag->id = id; + tag->effect_toggle = fx_on; + tag->fader_active = fader_active; + tag->fader_val = fader_val; + tag->fader_direction = fader_dir; + tag->opacity = opacity; + tag->nframes = nframes; + tag->viewport_config = viewport_config; + vj_tag_update( tag, id ); + + switch( source_type ) + { + case VJ_TAG_TYPE_COLOR: + vj_tag_set_stream_color( id, col[0],col[1],col[2] ); + break; + } + + if( subs ) + { + char tmp[512]; + sprintf(tmp, "%s-SUB-s%d.srt", sampleFile, id ); +#ifdef STRICT_CHECKING + assert(tag->dict != NULL); +#endif + vj_font_set_dict( font, tag->dict ); + + vj_font_load_srt( font, tmp ); + + vj_font_xml_unpack( doc,subs, font ); + } + + if( cali ) + { + tagParseCalibration( doc, cali, id, vp ); + } + + int q; + for( q = 0; q < k ; q ++ ) + { + if(fx[q] ) + tagParseEffects(doc, fx[q], id ); + } + } + } + + vj_font_set_dict( font, d ); + +} + + + +static void tagCreateArguments(xmlNodePtr node, int *arg, int argcount) +{ + int i; + char buffer[100]; + for (i = 0; i < argcount; i++) { + sprintf(buffer, "%d", arg[i]); + xmlNewChild( node, NULL, (const xmlChar*) XMLTAG_ARGUMENT, + (const xmlChar*) buffer ); + } +} + +static void tagCreateKeys(xmlNodePtr node, int argcount, void *port ) +{ + int i; + for ( i = 0; i < argcount ; i ++ ) + { + xmlNodePtr childnode = xmlNewChild( node, NULL,(const xmlChar*) "KEYFRAMES",NULL ); + keyframe_xml_pack( childnode, port, i ); + } +} + +static void tagCreateEffect(xmlNodePtr node, sample_eff_chain * effect, int position) +{ + char buffer[100]; + xmlNodePtr childnode; + + sprintf(buffer, "%d", position); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTPOS, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->effect_id); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTID, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->e_flag); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTACTIVE, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->source_type); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTSOURCE, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->channel); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTCHANNEL, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->frame_offset); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTOFFSET, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->frame_trimmer); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTTRIMMER, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->a_flag); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTAUDIOFLAG, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->volume); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTAUDIOVOLUME, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", effect->kf_status ); + xmlNewChild(node,NULL,(const xmlChar*) "kf_status", (const xmlChar*)buffer); + + childnode = + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_ARGUMENTS, NULL); + tagCreateArguments(childnode, effect->arg, + vj_effect_get_num_params(effect->effect_id)); + + childnode = + xmlNewChild(node, NULL, (const xmlChar*) "ANIM", NULL ); + tagCreateKeys( childnode, vj_effect_get_num_params(effect->effect_id), effect->kf ); +} + +static void tagCreateEffects(xmlNodePtr node, sample_eff_chain ** effects) +{ + int i; + xmlNodePtr childnode; + + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) { + if (effects[i]->effect_id != -1) { + childnode = + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECT, + NULL); + tagCreateEffect(childnode, effects[i], i); + } + } + +} + +void tagCreateStream(xmlNodePtr node, vj_tag *tag, void *font, void *vp) +{ + char buffer[100]; + + sprintf(buffer, "%d", tag->id); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_SAMPLEID, + (const xmlChar *) buffer); + sprintf(buffer, "%d", tag->effect_toggle); + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_CHAIN_ENABLED, + (const xmlChar *) buffer); + + sprintf(buffer, "%d", tag->source_type ); + xmlNewChild(node,NULL,(const xmlChar*) "source_type", (const xmlChar*) buffer ); + + sprintf(buffer, "%d", tag->video_channel ); + xmlNewChild(node,NULL,(const xmlChar*) "source_id", (const xmlChar*) buffer ); + + sprintf(buffer, "%s", tag->source_name ); + xmlNewChild(node,NULL,(const xmlChar*) "source_file", (const xmlChar*) buffer ); + + if(tag->extra ) + { + sprintf(buffer, "%s", (char*)tag->extra ); + xmlNewChild(node, NULL,(const xmlChar) "extra_data", (const xmlChar*) buffer ); + } + sprintf(buffer, "%d", tag->color_r ); + xmlNewChild(node,NULL,(const xmlChar*) "red", (const xmlChar*) buffer ); + sprintf(buffer, "%d", tag->color_g ); + xmlNewChild(node,NULL,(const xmlChar*) "green", (const xmlChar*) buffer ); + sprintf(buffer, "%d", tag->color_b ); + xmlNewChild(node,NULL,(const xmlChar*) "blue", (const xmlChar*) buffer ); + + sprintf(buffer, "%d", tag->nframes ); + xmlNewChild(node, NULL, (const xmlChar*) "nframes", (const xmlChar*) buffer ); + + sprintf(buffer, "%d", tag->opacity ); + xmlNewChild( node, NULL, (const xmlChar*) "opacity", (const xmlChar*) buffer ); + + vj_font_xml_pack( node, font ); + + viewport_save_xml( node, tag->viewport_config ); + + xmlNodePtr childnode = + xmlNewChild(node, NULL, (const xmlChar *) XMLTAG_EFFECTS, NULL); + + tagCreateEffects(childnode, tag->effect_chain); + +} + +void tag_writeStream( char *file, int n, xmlNodePtr node, void *font, void *vp ) +{ + vj_tag *tag = vj_tag_get(n); + if(!tag) { + veejay_msg(VEEJAY_MSG_ERROR, "Stream %d does not exist", n); + return; + } + char tmp[512]; + void *d = vj_font_get_dict( font ); + sprintf(tmp, "%s-SUB-s%d.srt", file,tag->id ); + + if( tag->dict ) + { + vj_font_set_dict( font, tag->dict ); + vj_font_save_srt( font, tmp ); + + vj_font_set_dict( font, d ); + } + + tagCreateStream(node, tag , font,vp); +} + + + + +#endif diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-tag.h b/branches/V-1.5.3/veejay-server/libstream/vj-tag.h new file mode 100644 index 00000000..d4f94709 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-tag.h @@ -0,0 +1,350 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_TAG_H +#define VJ_TAG_H + +#define VJ_TAG_TYPE_CALI 6 +#define VJ_TAG_TYPE_PICTURE 5 +#define VJ_TAG_TYPE_COLOR 4 +#define VJ_TAG_TYPE_VLOOPBACK 3 +#define VJ_TAG_TYPE_V4L 2 +#define VJ_TAG_TYPE_YUV4MPEG 1 +#define VJ_TAG_TYPE_NONE 0 +#define VJ_TAG_TYPE_SHM 11 +#define VJ_TAG_TYPE_NET 13 +#define VJ_TAG_TYPE_MCAST 14 +#define VJ_TAG_MAX_V4L 16 +#define VJ_TAG_MAX_STREAM_IN 255 +#define VJ_TAG_TYPE_DV1394 17 +#define VJ_TAG_TYPE_AVFORMAT 12 +#define TAG_MAX_DESCR_LEN 150 +#include +#include +#include +#include +#include +#ifdef USE_GDK_PIXBUF +typedef struct +{ + void *pic; +} vj_picture; +#endif + +typedef struct { + void *unicap[VJ_TAG_MAX_STREAM_IN]; + vj_yuv *stream[VJ_TAG_MAX_STREAM_IN]; + vj_client *net[VJ_TAG_MAX_STREAM_IN]; + vj_dv1394 *dv1394[VJ_TAG_MAX_STREAM_IN]; +#ifdef USE_GDK_PIXBUF + vj_picture *picture[VJ_TAG_MAX_STREAM_IN]; +#endif + void *cali[VJ_TAG_MAX_STREAM_IN]; + int width; + int height; + int depth; + int pix_fmt; + int uv_len; +} vj_tag_data; + +typedef struct { + int id; +// char description[100]; + sample_eff_chain *effect_chain[SAMPLE_MAX_EFFECTS]; + int next_id; + int nframes; + int source_type; + char *source_name; + char *method_filename; + int index; + int depth; + int active; + int source; + int video_channel; + int capture_type; + int encoder_active; + unsigned long sequence_num; + unsigned long rec_total_bytes; +// char *encoder_base; + unsigned long encoder_total_frames; +// char *encoder_destination; + char encoder_base[256]; + char encoder_destination[256]; + char descr[TAG_MAX_DESCR_LEN]; + int encoder_format; + void *encoder; + lav_file_t *encoder_file; + long encoder_duration; /* in seconds */ + long encoder_num_frames; + long encoder_succes_frames; + int encoder_width; + int encoder_height; + int encoder_max_size; + int color_r; + int color_g; + int color_b; + int opacity; + int fader_active; + int fader_direction; + float fader_val; + float fader_inc; + int selected_entry; + int effect_toggle; + int socket_ready; + int socket_len; + uint8_t *socket_frame; + int n_frames; + void *priv; + void *extra; + void *dict; + char padding[4]; + int composite; + void *viewport_config; + void *viewport; + int noise_suppression; + uint8_t *blackframe; + int bf_count; + int median_radius; + int has_white; + double *tabmean[3]; + double mean[3]; + double *bf; + double *bfu; + double *bfv; + double *lf; + double *lfu; + double *lfv; + int cali_duration; +} vj_tag; + +#define V4L_BLACKFRAME 1 +#define V4L_BLACKFRAME_NEXT 2 +#define V4L_BLACKFRAME_PROCESS 3 + +void *vj_tag_get_dict( int id ); +int vj_tag_set_composite(void *compiz,int id, int n); +int vj_tag_get_composite(int t1); +int vj_tag_chain_malloc(int e); +int vj_tag_chain_free(int e); +int vj_tag_get_v4l_properties(int t1,int *brightness, int *contrast, int *hue,int *color, int *white ); +int vj_tag_init(int w, int h, int pix_fmt, int driver); +int vj_tag_get_n_frames(int t1); +int vj_tag_set_n_frames(int t1, int n_frames); +int vj_tag_get_last_tag(); + +void vj_tag_free(void); +/* Change color of solid stream*/ +int vj_tag_set_stream_color(int t1, int r, int g, int b); +int vj_tag_get_stream_color(int t1, int *r, int *g, int *b ); +/* create a new tag, type is yuv4mpeg or v4l + stream_nr indicates which stream to take of the same type + */ +int vj_tag_new(int type, char *filename, int stream_nr, editlist * el, + int pix_fmt, int channel, int extra, int has_composite); + +/* return 1 if tag exists , 0 otherwise*/ +int vj_tag_exists(int id); + +/* return 1 if tag gets deleted, 0 on error */ +int vj_tag_del(int id); + +int vj_tag_verify_delete(int id, int type ); + +/* return -1 if there is no effect or if it is disabled, otherwise a positive value */ +int vj_tag_get_effect(int t1, int position); + +int vj_tag_size(); + +vj_tag *vj_tag_get(int id); +/* always return effect (-1 = empty) */ +int vj_tag_get_effect_any(int t1, int position); + +/* return -1 on error, otherwise argument gets updated */ +int vj_tag_set_effect(int t1, int position, int effect_id); + +/* return -1 on error, or return e_flag (effect enabled/disabled 1/0)*/ +int vj_tag_get_chain_status(int t1, int position); + +/* return -1 on error, otherwise set new status */ +int vj_tag_set_chain_status(int t1, int position, int new_status); + +/* return 0 on error, other value is trimmer (0 = no trim anyway) */ +int vj_tag_get_trimmer(int t1, int poisition); + +/* return -1 on error, or 1 on succes */ +int vj_tag_set_trimmer(int t1, int position, int value); + +//int vj_tag_get_video_palette(int t1); + +//int vj_tag_set_video_palette(int t1, int video_palette); + +/* return -1 on error or 1 on sucess. tag's effect parameters get copied into args + args must be initialized. + */ +int vj_tag_get_all_effect_args(int t1, int position, int *args, + int arg_len, int n_frame); + +int vj_tag_get_effect_arg(int t1, int p, int arg); + +/* return -1 on error, 1 on success */ +int vj_tag_set_effect_arg(int t1, int position, int argnr, int value); + +/* return -1 on error, 1 on sucess */ +int vj_tag_get_type(int t1); + +/* returns number of tags */ + +int vj_tag_get_logical_index(int t1); + +int vj_tag_clear_chain(int id); + +int vj_tag_get_depth(int t1); + +int vj_tag_set_depth(int t1, int depth); + +int vj_tag_set_active(int t1, int active); + +int vj_tag_get_active(int t1); + +int vj_tag_chain_size(int t1); + +int vj_tag_chain_remove(int t1, int index); + +int vj_tag_set_chain_channel(int t1, int position, int channel); + +int vj_tag_get_chain_channel(int t1, int position); + +void vj_tag_get_source_name(int t1, char *dst); + +int vj_tag_get_chain_source(int t1, int position); + +int vj_tag_set_chain_source(int t1, int position, int source); + +void vj_tag_get_descriptive(int type, char *dst); + +int vj_tag_by_type(int type); + +int vj_tag_get_offset(int t1, int entry); + +int vj_tag_set_offset(int t1, int entry, int offset); + +//int vj_tag_record_frame(int t1, uint8_t *buffer[3]); + +int vj_tag_get_frame(int t1, uint8_t *buffer[3], uint8_t *abuf); + +int vj_tag_get_audio_frame(int t1, uint8_t *dst ); + +int vj_tag_enable(int t1); + +int vj_tag_disable(int t1); + +int vj_tag_sprint_status(int tag_id, int cache,int sa, int ca, int r, int f, int m, int t,int curfps, uint32_t lo, uint32_t hi, int macro,char *str ); + +//int vj_tag_init_encoder(int t1, char *filename, int format, +// int w, int h, double fps, long seconds, int autoplay); + +uint8_t *vj_tag_get_cali_buffer(int t1, int type, int *total, int *len, int *uvlen); +int vj_tag_stop_encoder(int t1); +int vj_tag_set_brightness(int t1, int value); +int vj_tag_set_contrast(int t1, int value); +int vj_tag_set_color(int t1, int value); +int vj_tag_set_hue(int t1, int value); +int vj_tag_set_white(int t1, int value); +int vj_tag_set_saturation(int t1, int value); +void vj_tag_set_veejay_t(void *info); + +int vj_tag_set_manual_fader(int t1, int value ); + +int vj_tag_get_fader_direction(int t1); +int vj_tag_set_fader_active(int t1, int nframes, int direction); +int vj_tag_set_fade_to_tag(int t1, int t2); +int vj_tag_set_fade_to_sample(int t1, int s1); +int vj_tag_set_fader_val(int t1, float val); +int vj_tag_apply_fader_inc(int t1); +int vj_tag_get_fader_active(int t1); +float vj_tag_get_fader_val(int t1); +float vj_tag_get_fader_inc(int t1); +int vj_tag_reset_fader(int t1); + +int vj_tag_get_effect_status(int s1); +int vj_tag_get_selected_entry(int s1); + +int vj_tag_set_effect_status(int s1, int status); +int vj_tag_set_selected_entry(int s1, int position); +void vj_tag_close_all(); + +int vj_tag_composite(int t1); + +int vj_tag_init_encoder(int t1, char *filename, int format, long nframes); +int vj_tag_record_frame(int t1, uint8_t *buffer[3], uint8_t *abuff, int audio_size, int pixel_format); +int vj_tag_get_encoded_frames(int t1); +long vj_tag_get_total_frames(int t1); +long vj_tag_get_duration(int t1); +int vj_tag_reset_autosplit(int t1); +int vj_tag_get_frames_left(int t1); +int vj_tag_encoder_active(int t1); +int vj_tag_get_num_encoded_files(int t1); +int vj_tag_get_encoder_format(int t1); +int vj_tag_get_sequenced_file( int t1, char *descr, int num, char *ext); +int vj_tag_try_filename(int t1, char *filename, int format); +int vj_tag_get_encoded_file(int t1, char *descr); +void vj_tag_reset_encoder( int t1 ); +void vj_tag_record_init(int w, int h); +void vj_tag_get_method_filename(int t1, char *dst); +int vj_tag_get_last_tag(void); +int vj_tag_put( vj_tag *tag ); +int vj_tag_is_deleted(int id); +void vj_tag_close_all(); +int vj_tag_continue_record( int t1 ); +int vj_tag_set_logical_index(int t1, int stream_nr); +int vj_tag_set_description(int t1, char *descr); +int vj_tag_get_description(int t1, char *descr); +void vj_tag_get_by_type( int type, char *descr ); +int vj_tag_get_width(); +int vj_tag_get_height(); +int vj_tag_get_uvlen(); +void vj_tag_cali_prepare_now(int a, int b); +int vj_tag_chain_set_kfs( int s1, int len, unsigned char *data ); +unsigned char * vj_tag_chain_get_kfs( int s1, int entry, int parameter_id, int *len ); +int vj_tag_get_kf_status(int t1, int entry); +int vj_tag_chain_set_kf_status( int s1, int entry, int status ); +int vj_tag_chain_reset_kf( int s1, int entry ); +int vj_tag_var(int t1, int *type, int *fader, int *fx_sta , int *rec_sta, int *active ); +int vj_tag_true_size(); +void *vj_tag_get_kf_port( int s1, int entry ); + +char *vj_tag_scan_devices( void ); +int vj_tag_get_kf_tokens( int s1, int entry, int id, int *start,int *end, int *type); +int vj_tag_grab_blackframe(int t1, int duration, int median_radius,int mode ); +int vj_tag_drop_blackframe(int t1); +int vj_tag_num_devices(); + +void vj_tag_reload_config( void *compiz, int t1, int mode ); + +void *vj_tag_get_composite_view(int t1); +int vj_tag_set_composite_view(int t1, void *v); +int vj_tag_cali_write_file( int id, char *name, editlist *el ); + +#ifdef HAVE_XML2 +void tag_writeStream( char *file, int n, xmlNodePtr node, void *font, void *vp); +void tagCreateStream(xmlNodePtr node, vj_tag *tag, void *font, void *vp); +void tagCreateStreamFX(xmlNodePtr node, vj_tag *tag); +void tagParseStreamFX(char *file, xmlDocPtr doc, xmlNodePtr cur, void *font, + void *vp); +#endif +#endif diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-unicap.c b/branches/V-1.5.3/veejay-server/libstream/vj-unicap.c new file mode 100644 index 00000000..26178cae --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-unicap.c @@ -0,0 +1,1478 @@ +/* veejay - Linux VeeJay Unicap interface + * (C) 2002-2006 Niels Elburg + * + * + * 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 +#ifdef HAVE_UNICAP +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif + +#define BUFFERS 4 + +typedef struct +{ + unicap_handle_t handle; + unicap_device_t device; + unicap_format_t format_spec; + unicap_format_t format; + unicap_data_buffer_t buffer; + unicap_data_buffer_t mbuf[BUFFERS]; + pthread_mutex_t mutex; + pthread_t thread; + pthread_attr_t attr; + uint8_t *priv_buf; + int state; + int deviceID; + int sizes[3]; + int active; + int rgb; + void *sampler; + char *ctrl[16]; + int option[16]; + int ready; + int frame_size; + int pause; + int dst_width; + int dst_height; + int src_width; + int src_height; + int dst_fmt; + int src_fmt; + int src_sizes[3]; + int dst_sizes[3]; + sws_template template; + void *scaler; + int composite; +} vj_unicap_t; + +static struct { + int i; + char *s; +} pixstr[] = { + {PIX_FMT_YUV420P, "YUVPIX_FMT_YUV420P"}, +{ PIX_FMT_YUV422P, "4:2:2 planar, Y-Cb-Cr ( 422P )"}, +{ PIX_FMT_YUVJ420P, "4:2:0 planar, Y-U-V (420P JPEG)"}, +{ PIX_FMT_YUVJ422P, "4:2:2 planar, Y-U-V (422P JPEG)"}, +{ PIX_FMT_RGB24, "RGB 24 bit"}, +{ PIX_FMT_BGR24, "BGR 24 bit"}, +{ PIX_FMT_YUV444P, "YUV 4:4:4 planar, Y-Cb-Cr (444P)"}, +{ PIX_FMT_YUVJ444P, "YUV 4:4:4 planar, Y-U-V (444P JPEG)"}, +{ PIX_FMT_RGB32, "RGB 32 bit"}, +{ PIX_FMT_BGR32, "BGR 32 bit"}, +{ PIX_FMT_GRAY8, "Greyscale"}, +{ PIX_FMT_RGB32_1, "RGB 32 bit LE"}, +{ 0 , NULL} + +}; + + +static const char *unicap_pf_str(int i) +{ + int j; + for( j = 0; pixstr[j].s != NULL ; j ++ ) { + if( i == pixstr[j].i ) + return pixstr[j].s; + } + return NULL; +} + +static void unicap_report_error( vj_unicap_t *v, char *err_msg ) +{ + + veejay_msg(0,"%s: %s", err_msg, v->device.identifier ); + veejay_msg(VEEJAY_MSG_DEBUG, + "Capture device delivers in %s, %dx%d strides=%d,%d,%d", + unicap_pf_str(v->src_fmt), v->src_width,v->src_height,v->src_sizes[0],v->src_sizes[1],v->src_sizes[2]); + veejay_msg(VEEJAY_MSG_DEBUG, + "System expects %s, %dx%d, strides=%d,%d,%d", + unicap_pf_str(v->dst_fmt), v->dst_width,v->dst_height,v->dst_sizes[0],v->dst_sizes[1],v->dst_sizes[2]); + +} + +typedef struct +{ + unicap_handle_t handle; + unicap_device_t device; + unicap_format_t format_spec; + unicap_format_t format; + unicap_data_buffer_t buffer; + void *device_list; + int num_devices; + int devices[16]; +} unicap_driver_t; + +static void *unicap_reader_thread(void *data); +static int vj_unicap_start_capture_( void *vut ); +static int vj_unicap_stop_capture_( void *vut ); +extern int get_ffmpeg_pixfmt( int id ); +static void vj_unicap_new_frame_cb( unicap_event_t event, unicap_handle_t handle, + unicap_data_buffer_t *ready_buffer, vj_unicap_t *v ); + +#ifdef STRICT_CHECKING +static void lock__(vj_unicap_t *t, const char *f, int line) { + pthread_mutex_lock(&(t->mutex)); +} +static void unlock__(vj_unicap_t *t, const char *f, int line) { + pthread_mutex_unlock(&(t->mutex)); +} +#define lock_(t) lock__(t,__FUNCTION__,__LINE__) +#define unlock_(t) unlock__(t, __FUNCTION__ ,__LINE__) + +#else +static void lock_(vj_unicap_t *t) +{ + pthread_mutex_lock( &(t->mutex )); +} +static void unlock_(vj_unicap_t *t) +{ + pthread_mutex_unlock( &(t->mutex )); +} +#endif + +static int vj_unicap_scan_enumerate_devices(void *unicap) +{ + int i=0; + unicap_driver_t *ud = (unicap_driver_t*) unicap; + char key[64]; + + memset( &(ud->device) , 0, sizeof(unicap_device_t)); + + unicap_void_device(&(ud->device)); + + + while( SUCCESS( unicap_enumerate_devices( NULL, &(ud->device), i )) ) + { + char *device_name = strdup( ud->device.identifier ); + void *device_port = vpn( VEVO_ANONYMOUS_PORT ); + char *device_location = strdup( ud->device.device ); + int error = vevo_property_set( device_port, + "name", + VEVO_ATOM_TYPE_STRING, + 1, + &device_name); + + veejay_msg( VEEJAY_MSG_DEBUG, "\tDevice %d: %s (%s)", i, ud->device.identifier, device_location ); + +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + sprintf(key ,"%d", i ); + error = vevo_property_set( ud->device_list, key, VEVO_ATOM_TYPE_PORTPTR,1,&device_port ); + +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + error = vevo_property_set( device_port, + "device", + VEVO_ATOM_TYPE_STRING, + 1, + &device_location ); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + + free( device_location ); + free(device_name); + i++; + } + return i; +} + + +char **vj_unicap_get_devices(void *unicap, int *n_dev) +{ + int i,j=0; + unicap_driver_t *ud = (unicap_driver_t*) unicap; + char **result = NULL; + + if( ud->num_devices <= 0 ) + { + veejay_msg(0, "I didn't find any capture devices"); + return NULL; + } + + char **items = vevo_list_properties( ud->device_list ); + if(! items ) + { + veejay_msg(0, "Empty list of capture devices"); + return NULL; + } + + int len = 1; + int error = 0; + for ( i = 0; items[i] != NULL ; i ++ ) + { + error = vevo_property_get( ud->device_list,items[i], 0, NULL ); + if( error == VEVO_NO_ERROR ) + len ++; + } + + result = vj_calloc( sizeof(char*) * len ); + for( i = 0; items[i] != NULL ; i ++ ) + { + void *port = NULL; + error = vevo_property_get( ud->device_list, items[i], 0, &port ); + if( error == VEVO_NO_ERROR ) + { + size_t name_len = vevo_property_element_size( port, "name", 0 ); + char *name = (char*) vj_calloc( name_len ); + vevo_property_get( port, "name",0,&name ); + name_len = vevo_property_element_size( port, "device", 0 ); + char *loc = (char*) vj_calloc( name_len ); + vevo_property_get( port, "device", 0, &loc ); + int new_len = strlen(loc) + strlen(name) + 8; + + char *text = vj_calloc( new_len ); + snprintf(text, new_len, "%03d%s%03d%s",strlen(name), name,strlen(loc), loc ); + + free(name); + free(loc); + + result[j] = strdup(text ); + free(text); + j++; + } + free(items[i]); + } + free(items ); + + *n_dev = j; + return result; +} + +void *vj_unicap_init(void) +{ + unicap_driver_t *ud = (unicap_driver_t*) vj_calloc(sizeof(unicap_driver_t)); + ud->device_list = vpn( VEVO_ANONYMOUS_PORT ); + ud->num_devices = vj_unicap_scan_enumerate_devices( (void*) ud ); + veejay_msg(1, "Found %d capture devices on this system", ud->num_devices); + return ud; +} + +void vj_unicap_deinit(void *dud ) +{ + unicap_driver_t *ud = (unicap_driver_t*) dud; + if( ud ) + { + vevo_port_recursive_free( ud->device_list ); + free(ud); + } + dud = NULL; +} + +int vj_unicap_property_is_menu( void *ud, char *key ) +{ + unicap_property_t property; + unicap_property_t property_spec; + int i; + unicap_void_property( &property_spec ); + unicap_void_property( &property ); + vj_unicap_t *vut = (vj_unicap_t*) ud; + unicap_lock_properties( vut->handle ); + + for( i = 0; SUCCESS( unicap_enumerate_properties( vut->handle, + &property_spec, &property, i ) ); i ++ ) + { + unicap_void_property( &property ); + + unicap_get_property( vut->handle, &property); + if( strcmp( property.identifier, key ) == 0 ) + { + unicap_unlock_properties( vut->handle); + if( property.type == UNICAP_PROPERTY_TYPE_MENU ) + return 1; + else + return 0; + } + } + unicap_unlock_properties( vut->handle); + return 0; +} +int vj_unicap_property_is_range( void *ud, char *key ) +{ + unicap_property_t property; + unicap_property_t property_spec; + int i; + unicap_void_property( &property_spec ); + unicap_void_property( &property ); + vj_unicap_t *vut = (vj_unicap_t*) ud; + unicap_lock_properties( vut->handle ); + + for( i = 0; SUCCESS( unicap_enumerate_properties( vut->handle, + &property_spec, &property, i ) ); i ++ ) + { + unicap_get_property( vut->handle, &property); + if( strcmp( property.identifier, key ) == 0 ) + { + unicap_unlock_properties( vut->handle); + if( property.type == UNICAP_PROPERTY_TYPE_RANGE ) + return 1; + else + return 0; + } + } + unicap_unlock_properties( vut->handle); + return 0; +} + +int vj_unicap_select_value( void *ud, int key, double attr ) +{ + unicap_property_t property; + unicap_property_t property_spec; + int i; + unicap_void_property( &property_spec ); + unicap_void_property( &property ); + vj_unicap_t *vut = (vj_unicap_t*) ud; + + if(! vut->ctrl[key] ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Capture device %s has no property %x", + vut->device.identifier, key ); + return 0; + } + + unicap_lock_properties( vut->handle ); + + for( i = 0; SUCCESS( unicap_enumerate_properties( vut->handle, + &property_spec, &property, i ) ); i ++ ) + { + unicap_get_property( vut->handle, &property); + if( strcmp( property.identifier, vut->ctrl[key] ) == 0 ) + { + if( property.type == UNICAP_PROPERTY_TYPE_MENU ) + { + int idx = vut->option[ key ]; + veejay_strncpy( property.menu_item, property.menu.menu_items[idx], strlen( property.menu.menu_items[idx]) ); + unicap_set_property( vut->handle, &property ); + unicap_unlock_properties( vut->handle ); + return 1; + } + if( property.type == UNICAP_PROPERTY_TYPE_RANGE ) + { + double fval = attr; + if(fval < property.range.min) + fval = property.range.min; + else if(fval > property.range.max) + fval = property.range.max; + property.value = fval; + unicap_set_property( vut->handle, &property ); + unicap_unlock_properties( vut->handle ); + return 1; + } + } + } + unicap_unlock_properties( vut->handle ); + + return 0; +} + +int vj_unicap_get_range( void *ud, char *key, double *min , double *max ) +{ + unicap_property_t property; + unicap_property_t property_spec; + int i; + unicap_void_property( &property_spec ); + unicap_void_property( &property ); + vj_unicap_t *vut = (vj_unicap_t*) ud; + unicap_lock_properties( vut->handle ); + + for( i = 0; SUCCESS( unicap_enumerate_properties( vut->handle, + &property_spec, &property, i ) ); i ++ ) + { + // memset( &property,0,sizeof(unicap_property_t)); + unicap_get_property( vut->handle, &property); + + if( strcasecmp( property.identifier, key ) == 0 ) + { + + if( property.type == UNICAP_PROPERTY_TYPE_MENU ) + { + *min = 0.0; + *max = (double) property.menu.menu_item_count; + unicap_unlock_properties( vut->handle ); + + return 1; + } + if( property.type == UNICAP_PROPERTY_TYPE_RANGE ) + { + *min = property.range.min; + *max = property.range.max; + unicap_unlock_properties( vut->handle ); + + return 1; + } + } + } + unicap_unlock_properties( vut->handle ); + + return 0; +} + +char **vj_unicap_get_list( void *ud ) +{ + unicap_property_t property; + unicap_property_t property_spec; + int i; + unicap_void_property( &property_spec ); + vj_unicap_t *vut = (vj_unicap_t*) ud; + unicap_lock_properties( vut->handle ); + + for( i = 0; SUCCESS( unicap_enumerate_properties( vut->handle, + &property_spec, &property, i ) ); i ++ ) + { + } + + int n = i; + + char **res = (char**) vj_calloc(sizeof(char*) * (n+1) ); + + for( i = 0;i < n; i ++ ) + { + if( SUCCESS( unicap_enumerate_properties(vut->handle, + &property_spec,&property,i ) ) ) + { + res[i] = strdup( property.identifier ); + } + } + + unicap_unlock_properties( vut->handle ); + + return res; +} + + +int vj_unicap_get_value( void *ud, char *key, int atom_type, void *value ) +{ + unicap_property_t property; + unicap_property_t property_spec; + int i; + unicap_void_property( &property_spec ); + vj_unicap_t *vut = (vj_unicap_t*) ud; + unicap_lock_properties( vut->handle ); + + for( i = 0; SUCCESS( unicap_enumerate_properties( vut->handle, + &property_spec, &property, i ) ); i ++ ) + { + unicap_get_property( vut->handle, &property); + + if( strcmp( property.identifier, key ) != 0 ) + continue; + + if( property.type == UNICAP_PROPERTY_TYPE_MENU ) + { +#ifdef STRICT_CHECKING + assert( atom_type == VEVO_ATOM_TYPE_DOUBLE ); +#endif + int n = property.menu.menu_item_count; + int j; + for( j =0; j < n; j ++ ) + { + if( strcmp( property.menu_item, property.menu.menu_items[j] ) == 0 ) + { + double *dval = value; + *dval = (double) j; + unicap_unlock_properties( vut->handle ); + + return 1; + } + } + } + if( property.type == UNICAP_PROPERTY_TYPE_RANGE ) + { +#ifdef STRICT_CHECKING + assert( atom_type == VEVO_ATOM_TYPE_DOUBLE ); +#endif + double *dval = value; + *dval = property.value; + unicap_unlock_properties( vut->handle ); + + return 1; + } + } + unicap_unlock_properties( vut->handle ); + + return 0; +} + +int vj_unicap_num_capture_devices( void *dud ) +{ + unicap_driver_t *ud = (unicap_driver_t*) dud; + return ud->num_devices; +} + +void *vj_unicap_new_device( void *dud, int device_id ) +{ + unicap_driver_t *ud = (unicap_driver_t*) dud; + if( ud->num_devices <= 0 ) + { + veejay_msg(0, "I didn't find any capture devices"); + return NULL; + } + if( ud->devices[ device_id ] ) + { + veejay_msg(0, "Device ID %d already openened in use by Veejay"); + return NULL; + } + + if( device_id < 0 || device_id >= ud->num_devices ) + { + veejay_msg(0, "I only found %d devices, requested: %d", ud->num_devices,device_id ); + return NULL; + } + + veejay_msg(VEEJAY_MSG_DEBUG, "Trying to open Capture Device %d", device_id); + + vj_unicap_t *vut = (vj_unicap_t*) vj_calloc(sizeof(vj_unicap_t)); + veejay_memset(vut->ctrl, 0 , sizeof(char*) *16 ); + veejay_memset(vut->option,0, sizeof(int) * 16 ); + vut->deviceID = device_id; + + if( !SUCCESS( unicap_enumerate_devices( NULL, &(vut->device), device_id ) ) ) + { + veejay_msg(0, "Failed to get info for device '%s'\n", vut->device.identifier ); + free(vut); + return NULL; + } + + if( !SUCCESS( unicap_open( &(vut->handle), &(vut->device) ) ) ) + { + veejay_msg(0, "Failed to open capture device '%s'\n", vut->device.identifier ); + free(vut); + return NULL; + } + + ud->devices[ vut->deviceID ] = 1; + veejay_msg(2, "Using device '%s'", vut->device.identifier); + + pthread_mutex_init( &(vut->mutex), NULL ); + + return (void*) vut; +} +static unsigned int +get_fourcc(char * fourcc) +{ + return ((((unsigned int)(fourcc[0])<<0)| + ((unsigned int)(fourcc[1])<<8)| + ((unsigned int)(fourcc[2])<<16)| + ((unsigned int)(fourcc[3])<<24))); +} + +static inline int get_shift_size(int fmt) +{ + switch(fmt) + { + case FMT_420: + case FMT_420F: + return 1; + case FMT_422: + case FMT_422F: + return 1; + default: + break; + } + return 0; +} + +int vj_unicap_composite_status(void *ud ) +{ + vj_unicap_t *vut = (vj_unicap_t*) ud; + return vut->composite; +} + + +int vj_unicap_configure_device( void *ud, int pixel_format, int w, int h, int composite ) +{ + vj_unicap_t *vut = (vj_unicap_t*) ud; + unsigned int fourcc = 0; + int found_native = 0; + int i; + unicap_lock_properties( vut->handle ); + + unicap_void_format( &(vut->format_spec)); + unicap_void_format( &(vut->format) ); + + vut->composite = composite; + vut->dst_fmt = get_ffmpeg_pixfmt( pixel_format ); + vut->src_fmt = get_ffmpeg_pixfmt( pixel_format ); + vut->format.buffer_type = UNICAP_BUFFER_TYPE_USER; + vut->template.flags = yuv_which_scaler(); + vut->scaler = NULL; + + switch( pixel_format ) { + case FMT_420: + case FMT_420F: + fourcc = get_fourcc("YU12" );break; + case FMT_422: + case FMT_422F: + fourcc = get_fourcc("422P");break; + } + +/* if( vut->composite ) { + switch(vut->composite) { + case 1: + vut->dst_fmt = PIX_FMT_YUV444P; + break; + case 2: + vut->dst_fmt = PIX_FMT_GRAY8; + break; + } + }*/ + + for( i = 0; SUCCESS( unicap_enumerate_formats( vut->handle, NULL, &(vut->format), i ) ); i ++ ) + { + if( fourcc == vut->format.fourcc ) + { + veejay_msg(VEEJAY_MSG_INFO, "Found native colorspace '%s'", vut->format.identifier); + found_native = 1; + break; + } + if( vut->format.fourcc == get_fourcc("RGB3") || vut->format.fourcc == get_fourcc("BGR3") ) + break; + } + + int maxw = vut->format.max_size.width; + int maxh = vut->format.max_size.height; + int minw = vut->format.min_size.width; + int minh = vut->format.min_size.height; + int search = 0; + int j = 0; + + if( w > maxw || h > maxh ) { + veejay_msg(VEEJAY_MSG_WARNING, "%s does not support %dx%d, using %dx%d instead with a software scaler.", + vut->device.identifier, w,h,maxw,maxh ); + search = 1; + } else { + vut->src_width = w; + vut->src_height= h; + vut->dst_width = w; + vut->dst_height = h; + vut->dst_sizes[0] = vut->dst_width * vut->dst_height; + + if ( vut->format.fourcc == get_fourcc("422P" ) ) { + vut->src_sizes[0] = vut->src_width * vut->src_height; + vut->src_sizes[1] = vut->src_sizes[0]/2; + vut->src_sizes[2] = vut->src_sizes[1]/2; + vut->src_fmt = PIX_FMT_YUV422P; + vut->frame_size = vut->src_sizes[0] + vut->src_sizes[1] + vut->src_sizes[2]; + } else if ( vut->format.fourcc == get_fourcc("420P")) { + vut->src_sizes[0] = vut->src_width * vut->src_height; + vut->src_sizes[1] = vut->src_sizes[0]/4; + vut->src_sizes[2] = vut->src_sizes[1]/4; + vut->src_fmt = PIX_FMT_YUV420P; + vut->frame_size = vut->src_sizes[0] + vut->src_sizes[1] + vut->src_sizes[2]; + } + vut->format.buffer_size = vut->frame_size; + vut->format.size.width = vut->src_width; + vut->format.size.height = vut->src_height; + + if(vut->frame_size<=0 ) + search = 1; + } + + if( search || !SUCCESS( unicap_set_format( vut->handle, &(vut->format) ) ) ) + { + int try_format[10] = { maxw,maxh,720,576,640,480,320,240, minw,minh }; + int good = 0; + for( i = 0; i < 10 ; i +=2 ) { + vut->src_width = try_format[i]; + vut->src_height= try_format[i+1]; + vut->dst_width = w; + vut->dst_height = h; + vut->dst_sizes[0] = vut->dst_width * vut->dst_height; + + if ( vut->format.fourcc == get_fourcc("422P" ) ) { + vut->src_sizes[0] = vut->src_width * vut->src_height; + vut->src_sizes[1] = vut->src_sizes[0]/2; + vut->src_sizes[2] = vut->src_sizes[1]/2; + vut->src_fmt = PIX_FMT_YUV422P; + vut->frame_size = vut->src_sizes[0] + vut->src_sizes[1] + vut->src_sizes[2]; + } else if ( vut->format.fourcc == get_fourcc("420P")) { + vut->src_sizes[0] = vut->src_width * vut->src_height; + vut->src_sizes[1] = vut->src_sizes[0]/4; + vut->src_sizes[2] = vut->src_sizes[1]/4; + vut->src_fmt = PIX_FMT_YUV420P; + vut->frame_size = vut->src_sizes[0] + vut->src_sizes[1] + vut->src_sizes[2]; + } else if( ( vut->format.fourcc == get_fourcc("RGB3") ) + || (vut->format.fourcc == get_fourcc("BGR3") ) ) { + vut->src_sizes[0] = vut->src_width * 3; + vut->src_sizes[1] = 0; vut->src_sizes[2] = 0; + vut->src_fmt = PIX_FMT_RGB24; + vut->rgb = 1; + if(vut->format.fourcc == get_fourcc("BGR3") ) + vut->src_fmt = PIX_FMT_BGR24; + vut->frame_size = vut->src_width * vut->src_height * 3; + }/* else if ( (vut->format.fourcc == get_fourcc("RGB4") ) || + (vut->format.fourcc == get_fourcc("BGR4") ) ) { + vut->src_sizes[0] = vut->src_width * 4; + vut->src_sizes[1] = 0; vut->src_sizes[2] = 0; + vut->src_fmt = PIX_FMT_RGB32; + vut->rgb = 1; + if(vut->format.fourcc == get_fourcc("BGR4") ) + vut->src_fmt = PIX_FMT_BGR32; + vut->frame_size = vut->src_width * vut->src_height * 4; + } */ +#ifdef STRICT_CHECKING + else { + veejay_msg(0, "Invalid pixel format: %s", vut->format.identifier); + assert( 0 ); + } +#endif + + vut->format.buffer_size = vut->frame_size; + vut->format.size.width = vut->src_width; + vut->format.size.height = vut->src_height; + + if( SUCCESS( unicap_set_format( vut->handle, &(vut->format)) ) ) + { + veejay_msg(VEEJAY_MSG_WARNING, + "(OK) Source %dx%d in %s , Dest %dx%d in %s (%d bytes framebuffer)", + vut->src_width,vut->src_height,vut->format.identifier,vut->dst_width, + vut->dst_height, unicap_pf_str(vut->dst_fmt), + vut->format.buffer_size ); + + good = 1; + break; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, + "(FAIL) Source %dx%d in %s , Dest %dx%d in %s (%d bytes framebuffer)", + vut->src_width,vut->src_height,vut->format.identifier,vut->dst_width, + vut->dst_height, unicap_pf_str(vut->dst_fmt), + vut->format.buffer_size ); + } + } + + if(!good) { + veejay_msg(VEEJAY_MSG_ERROR,"Cannot configure capture device %s", vut->format.identifier ); + unicap_unlock_properties( vut->handle ); + return 0; + } + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Okay, Capture device delivers %s image, %d x %d %d bytes buffer", + vut->format.identifier, vut->format.size.width,vut->format.size.height, + vut->format.buffer_size ); + + vut->src_width = vut->format.size.width; + vut->src_height= vut->format.size.height; + vut->dst_width = w; + vut->dst_height = h; + vut->dst_sizes[0] = vut->dst_width * vut->dst_height; + if ( vut->format.fourcc == get_fourcc("422P" ) ) { + vut->src_sizes[0] = vut->src_width * vut->src_height; + vut->src_sizes[1] = vut->src_sizes[0]/2; + vut->src_sizes[2] = vut->src_sizes[1]/2; + vut->src_fmt = PIX_FMT_YUV422P; + vut->frame_size = vut->src_sizes[0] + vut->src_sizes[1] + vut->src_sizes[2]; + } else if ( vut->format.fourcc == get_fourcc("420P")) { + vut->src_sizes[0] = vut->src_width * vut->src_height; + vut->src_sizes[1] = vut->src_sizes[0]/4; + vut->src_sizes[2] = vut->src_sizes[1]/4; + vut->src_fmt = PIX_FMT_YUV420P; + vut->frame_size = vut->src_sizes[0] + vut->src_sizes[1] + vut->src_sizes[2]; + } else if( ( vut->format.fourcc == get_fourcc("RGB3") ) + || (vut->format.fourcc == get_fourcc("BGR3") ) ) { + vut->src_sizes[0] = vut->src_width * 3; + vut->src_sizes[1] = 0; vut->src_sizes[2] = 0; + vut->src_fmt = PIX_FMT_RGB24; + vut->rgb = 1; + if(vut->format.fourcc == get_fourcc("BGR3") ) + vut->src_fmt = PIX_FMT_BGR24; + vut->frame_size = vut->src_width * vut->src_height * 3; + } +#ifdef STRICT_CHECKING + else { + veejay_msg(0, "Invalid pixel format: %s", vut->format.identifier); + assert( 0 ); + } +#endif + + vut->format.buffer_size = vut->frame_size; + vut->format.size.width = vut->src_width; + vut->format.size.height = vut->src_height; + + if( SUCCESS( unicap_set_format( vut->handle, &(vut->format)) ) ) + { + veejay_msg(VEEJAY_MSG_WARNING, + "(OK) Source %dx%d in %s , Dest %dx%d in %s (%d bytes framebuffer)", + vut->src_width,vut->src_height,vut->format.identifier,vut->dst_width, + vut->dst_height, unicap_pf_str(vut->dst_fmt), + vut->format.buffer_size ); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, + "(FAIL) Source %dx%d in %s , Dest %dx%d in %s (%d bytes framebuffer)", + vut->src_width,vut->src_height,vut->format.identifier,vut->dst_width, + vut->dst_height, unicap_pf_str(vut->dst_fmt), + vut->format.buffer_size ); + return 0; + } + + + + } + +/* if(vut->composite) { + vut->dst_sizes[1] = vut->dst_sizes[0]; + vut->dst_sizes[2] = vut->dst_sizes[0]; + } else */ + if(pixel_format == FMT_420F || pixel_format == FMT_420 ) { + vut->dst_sizes[1] = vut->dst_sizes[0]/4; + vut->dst_sizes[2] = vut->dst_sizes[1]; + } else { + vut->dst_sizes[1] = vut->dst_sizes[0]/2; + vut->dst_sizes[2] = vut->dst_sizes[1]; + } + + +// buffer alloced + char **properties = vj_unicap_get_list( vut ); + if(!properties) + { + veejay_msg(0, "No properties for this capture device ?!"); + unicap_unlock_properties( vut->handle ); + return 1; + } + + for( i = 0; properties[i] != NULL && i < 16; i ++ ) + { + if(strncasecmp( properties[i], "brightness",10 ) == 0 ) { + vut->ctrl[UNICAP_BRIGHTNESS] = strdup( properties[i] ); + } else if (strncasecmp( properties[i], "color", 5 ) == 0 ) { + vut->ctrl[UNICAP_COLOR] = strdup( properties[i]); + } else if (strncasecmp( properties[i], "saturation", 10 ) == 0 ) { + vut->ctrl[UNICAP_SATURATION] = strdup( properties[i] ); + } else if (strncasecmp( properties[i], "hue", 3 ) == 0 ) { + vut->ctrl[UNICAP_HUE] = strdup( properties[i] ); + } else if(strncasecmp( properties[i], "white", 5) == 0 ) { + vut->ctrl[UNICAP_WHITE] = strdup(properties[i]); + } else if (strncasecmp( properties[i], "contrast", 8 ) == 0 ) { + vut->ctrl[UNICAP_CONTRAST] = strdup( properties[i] ); + } else if (strncasecmp( properties[i], "video source",12) == 0 ) { + unicap_property_t p; + unicap_void_property( &p ); + strcpy( p.identifier, properties[i] );//, strlen( properties[i])); + unicap_get_property( vut->handle, &p ); + for(j=0;joption[UNICAP_SOURCE0+j] = j; + vut->ctrl[UNICAP_SOURCE0+j] = strdup(properties[i]); + } + }else if (strncasecmp( properties[i], "video norm",10) == 0 ) { + unicap_property_t p; + unicap_void_property( &p ); + strcpy( p.identifier, properties[i] ); //, strlen(i)); + unicap_get_property( vut->handle, &p ); + for(j=0;jctrl[UNICAP_PAL] = strdup(properties[i]); + vut->option[UNICAP_PAL] = j; + } + else if( strncasecmp( p.menu.menu_items[j], "ntsc", 4 ) == 0 ) + { + vut->ctrl[UNICAP_NTSC] = strdup(properties[i]); + vut->option[UNICAP_NTSC] = j; + } + } + } + + free( properties[i]); + } + free(properties); + + + unicap_unlock_properties( vut->handle ); + + return 1; +} + +int vj_unicap_start_capture( void *vut ) +{ + vj_unicap_t *v = (vj_unicap_t*) vut; +#ifdef STRICT_CHECKING + assert( v->priv_buf == NULL ); + assert( v->active == 0 ); +#endif + + veejay_msg(VEEJAY_MSG_INFO,"Preparing to capture from device %s", v->device.identifier ); +#ifndef USE_UNICAP_CB + pthread_attr_init(&(v->attr) ); + pthread_attr_setdetachstate(&(v->attr), PTHREAD_CREATE_DETACHED ); + + int err = pthread_create( &(v->thread), NULL, + unicap_reader_thread, vut ); + + pthread_attr_destroy( &(v->attr) ); + + if( err == 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "Spawned new capture thread for device %s", v->device.identifier ); + return 1; + } + v->state = 0; + veejay_msg(VEEJAY_MSG_ERROR, + "Unable to start capture thread for device %s: %s", v->device.identifier, strerror(err)); + return 0; +#else + if(!vj_unicap_start_capture_(vut)) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to start capture thread for device %s", + v->device.identifier ); + else + { + veejay_msg(VEEJAY_MSG_INFO, "Capturing from device %s", v->device.identifier ); + return 1; + } + + return 0; +#endif +} + +int vj_unicap_stop_capture( void *vut ) +{ + vj_unicap_t *v = (vj_unicap_t*) vut; + + veejay_msg(VEEJAY_MSG_INFO, "Stopping capture from device %s", v->device.identifier ); +#ifndef USE_UNICAP_CB + lock_ ( vut ); + v->state = 0; + unlock_( vut ); + + usleep( 200 * 1000 ); //@ bad way to sync threads + + lock_( vut ); + if( v->active ) + veejay_msg(VEEJAY_MSG_INFO, "Capture thread still running. Cancel %s", v->device.identifier); + unlock_(vut); + pthread_cancel( v->thread ); + + if(v->active) + { + veejay_msg(VEEJAY_MSG_WARNING, "Cleaning up capture thread from device %s",v->device.identifier); + vj_unicap_stop_capture_( vut ); + } +#else + //@todo +#endif + return 1; +} + + + + +static int vj_unicap_start_capture_( void *vut ) +{ + vj_unicap_t *v = (vj_unicap_t*) vut; +#ifdef STRICT_CHECKING + assert( v->priv_buf == NULL ); + assert( v->buffer.data == NULL ); + assert( v->active == 0 ); + assert( v->state == 0 ); +#endif + int i; + + if( v->src_width == v->dst_width && v->src_height == v->dst_height ) { + v->priv_buf = (uint8_t*) vj_calloc( v->dst_width * v->dst_height * 4 * sizeof(uint8_t) ); + v->buffer.data = vj_malloc( v->frame_size * sizeof(uint8_t) ); + if(!v->rgb){ + veejay_memset( v->buffer.data, 0, v->src_sizes[1] ); + veejay_memset( v->buffer.data + v->src_sizes[0], 128, v->src_sizes[1] + v->src_sizes[2]); + } else { + veejay_memset( v->buffer.data, 0, v->src_sizes[0]); + } + for( i = 0; i < BUFFERS; i ++ ) + { + veejay_memset( &(v->mbuf[i]),0x0, sizeof(unicap_data_buffer_t)); + v->mbuf[i].data = vj_malloc(v->frame_size * sizeof(uint8_t)); + } + + } else { +#ifdef STRICT_CHECKING + assert( v->dst_width > 0 ); + assert( v->dst_height > 0 ); + assert( v->frame_size > 0 ); +#endif + v->priv_buf = (uint8_t*) vj_calloc( v->dst_width * v->dst_height * 4 * sizeof(uint8_t) ); + v->buffer.data = vj_calloc( v->format.buffer_size * sizeof(uint8_t) * 2 ); + for( i = 0; i < BUFFERS; i ++ ) + { + veejay_memset( &(v->mbuf[i]),0x0, sizeof(unicap_data_buffer_t)); + v->mbuf[i].data = vj_calloc(v->format.buffer_size * sizeof(uint8_t)); + } + + + } + + + v->buffer.buffer_size = v->format.buffer_size; + +#ifdef USE_UNICAP_CB + unicap_register_callback( v->handle, UNICAP_EVENT_NEW_FRAME, + (unicap_callback_t) vj_unicap_new_frame_cb, &v ); +#endif + if( !SUCCESS( unicap_start_capture( v->handle ) ) ) + { + free(v->priv_buf); + v->priv_buf = NULL; + unicap_report_error(v, "Failed to start capture on device" ); + return 0; + } +#ifndef USE_UNICAP_CB +/* if( ! SUCCESS( unicap_queue_buffer( v->handle, &(v->buffer) )) ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "%s:%d Failed to queue buffer ",__FUNCTION__,__LINE__); + free(v->priv_buf); + v->priv_buf = NULL; + return 0; + } +*/ + for( i = 0; i < BUFFERS; i ++ ) { + + if( ! SUCCESS( unicap_queue_buffer( v->handle, &(v->mbuf[i]) )) ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "%s:%d Failed to queue buffer ",__FUNCTION__,__LINE__); + free(v->priv_buf); + v->priv_buf = NULL; + return 0; + } + } +#endif + v->active = 1; +#ifdef USE_UNICAP_CB + v->state = 1; + veejay_msg(VEEJAY_MSG_INFO,"Started capture from device %s", v->device.identifier ); +#else + veejay_msg(VEEJAY_MSG_INFO, "Thread: started capture from device %s", v->device.identifier ); +#endif + return 1; +} + +int vj_unicap_get_pause( void *vut ) { + vj_unicap_t *v = (vj_unicap_t*) vut; + return v->pause; +} + +void vj_unicap_set_pause( void *vut , int status ) { + vj_unicap_t *v = (vj_unicap_t*) vut; + lock_(vut); + v->pause = status; + unlock_(vut); +} + +int vj_unicap_grab_frame( void *vut, uint8_t *buffer[3], const int width, const int height ) +{ + vj_unicap_t *v = (vj_unicap_t*) vut; +// lock_( vut ); + + if(v->active == 0 || v->state == 0 ) + { +// unlock_(vut); + return 0; + } + + if( v->pause ) + { +// unlock_(vut); + return 1; + } + +#ifdef STRICT_CHECKING + assert(v->priv_buf != NULL ); +#endif +//veejay_msg(0, "Copy captured frame:%dx%d, sizes=%d,%d,%d,dst=%d,%d,%d,rgb=%d", +// v->src_width,v->src_height,v->sizes[0],v->sizes[1],v->sizes[2], +// v->dst_sizes[0],v->dst_sizes[1],v->dst_sizes[2],v->rgb ); + lock_(vut); + if( v->src_width == v->dst_width && v->src_height == v->dst_height ) + { + uint8_t *src[3]; + int y = v->sizes[0]; + int u = v->sizes[1]; + int uu = v->sizes[2]; + + if( !v->rgb ) { + src[0] = v->priv_buf; + src[1] = v->priv_buf + v->sizes[0]; + src[2] = v->priv_buf + v->sizes[0] + v->sizes[1]; + } else { + src[0] = v->priv_buf; + src[1] = v->priv_buf + v->dst_sizes[0]; + src[2] = v->priv_buf + v->dst_sizes[0] + v->dst_sizes[1]; + u = v->dst_sizes[1]; + uu = v->dst_sizes[2]; + y = v->dst_sizes[0]; + } + veejay_memcpy( buffer[0], src[0], y ); + veejay_memcpy( buffer[1], src[1], u ); + veejay_memcpy( buffer[2], src[2], uu ); + } else { + uint8_t *src[3] = { + v->priv_buf, + v->priv_buf + v->dst_sizes[0], + v->priv_buf + v->dst_sizes[0] + v->dst_sizes[1] }; + veejay_memcpy( buffer[0], src[0], v->dst_sizes[0] ); + veejay_memcpy( buffer[1], src[1], v->dst_sizes[1] ); + veejay_memcpy( buffer[2], src[2], v->dst_sizes[2] ); + } + + unlock_(vut); + return 1; +} +#ifndef USE_UNICAP_CB + +static void print_fps( ) +{ + static struct timeval next,current; + static int count = 0; + suseconds_t usec; + + if( count == 0 ) + { + gettimeofday(&next, NULL); + next.tv_sec += 1; + } + + count++; + + gettimeofday(¤t, NULL); + + if( timercmp( &next, ¤t, <= ) ) + { + printf( "FPS: %d\n", count ); + count = 0; + } +} + +int vj_unicap_grab_a_frame( void *vut ) +{ + vj_unicap_t *v = (vj_unicap_t*) vut; + unicap_data_buffer_t *ready_buffer = NULL; + uint8_t *buffer[3]; + int i; + if( v->src_width == v->dst_width && v->src_height == v->dst_height ) + { + buffer[0] = v->priv_buf; + buffer[1] = v->priv_buf + v->sizes[0]; + buffer[2] = v->priv_buf + v->sizes[0] + v->sizes[1]; + } else { + buffer[0] = v->priv_buf; + buffer[1] =v->priv_buf + v->dst_sizes[0]; + buffer[2] =v->priv_buf + v->dst_sizes[0] + v->dst_sizes[1]; + } + + if(!v->active) + { + veejay_msg(VEEJAY_MSG_ERROR, "Capture not started on device %d", v->deviceID); + return 0; + } + + int buffers_ready = 0; + + if( v->state == 0 || v->active == 0 ) + { + return 0; + } + + + if(!SUCCESS(unicap_poll_buffer( v->handle, &buffers_ready ) ) ) { + buffers_ready = 1; + } + + if( buffers_ready == 0 ) + return 0; + + for( i = 0; i < buffers_ready-1; i ++ ) { + if(! SUCCESS(unicap_wait_buffer(v->handle, &ready_buffer ) )) + { + veejay_msg(VEEJAY_MSG_WARNING, "Failed to wait for buffer from device %s", + v->device.identifier ); + return 1; + } + unicap_queue_buffer( v->handle, ready_buffer ); + } + + if( (!SUCCESS(unicap_wait_buffer(v->handle,&ready_buffer ) ) ) ) { + veejay_msg(0, "Failed to wait for buffer on device"); + return 1; + } + + if( ready_buffer->buffer_size <= 0 ) + { + veejay_msg(0, "Unicap returned a buffer of size 0!"); + return 0; + } + + if(!ready_buffer->data ) + { + veejay_msg(0, "Unicap returned a NULL buffer!"); + return 0; + } + //print_fps(); + lock_(vut); + if(!v->rgb) + { + if( v->src_width == v->dst_width && v->src_height == v->dst_height ) + { + veejay_memcpy( buffer[0], ready_buffer->data, v->sizes[0] ); + veejay_memcpy( buffer[1], ready_buffer->data + v->sizes[0], v->sizes[1] ); + veejay_memcpy( buffer[2], ready_buffer->data + v->sizes[0] +v->sizes[1] , v->sizes[2]); + } + else { + VJFrame *srci = yuv_yuv_template( ready_buffer->data, + ready_buffer->data + v->src_sizes[0], + ready_buffer->data + v->src_sizes[0] + v->src_sizes[1], + v->src_width, + v->src_height, v->src_fmt ); + VJFrame *dsti = yuv_yuv_template( buffer[0],buffer[1],buffer[2], + v->dst_width,v->dst_height, v->dst_fmt ); + if(!v->scaler) { + v->scaler = yuv_init_swscaler( srci,dsti,&(v->template),yuv_sws_get_cpu_flags()); + } + + yuv_convert_and_scale( v->scaler, srci,dsti ); + free(srci); + free(dsti); + } + } + else + { + if( v->src_width == v->dst_width && v->src_height == v->dst_height ) + { + VJFrame *srci = yuv_rgb_template( ready_buffer->data, v->src_width,v->src_height, v->src_fmt ); + VJFrame *dsti = yuv_yuv_template( v->priv_buf, + v->priv_buf + v->dst_sizes[0], + v->priv_buf + v->dst_sizes[0] + v->dst_sizes[1], + v->dst_width, + v->dst_height, + v->dst_fmt ); + if(!v->scaler) { + v->scaler = yuv_init_swscaler( srci,dsti,&(v->template),yuv_sws_get_cpu_flags()); + } + yuv_convert_and_scale_from_rgb( v->scaler, srci,dsti ); + + + free(srci); + free(dsti); + } + else { + VJFrame *srci = yuv_rgb_template( ready_buffer->data, v->src_width,v->src_height, v->src_fmt ); + VJFrame *dsti = yuv_yuv_template( v->priv_buf, + v->priv_buf + v->dst_sizes[0], + v->priv_buf + v->dst_sizes[0] + v->dst_sizes[1], + v->dst_width,v->dst_height, v->dst_fmt ); + if(!v->scaler) { + v->scaler = yuv_init_swscaler( srci,dsti,&(v->template),yuv_sws_get_cpu_flags()); + } + yuv_convert_and_scale_from_rgb( v->scaler, srci,dsti ); + free(srci); + free(dsti); + } + } + unlock_(vut); + + if( ! SUCCESS( unicap_queue_buffer( v->handle, ready_buffer) )) + { + veejay_msg(VEEJAY_MSG_DEBUG, "%s:%d Failed to queue buffer ",__FUNCTION__,__LINE__); + return 0; + } + if(v->dst_fmt == PIX_FMT_GRAY8) { + veejay_memset( buffer[1], 128, v->dst_sizes[0]); + veejay_memset( buffer[2], 128, v->dst_sizes[0]); + } + + return 1; +} +#else +static void vj_unicap_new_frame_cb( unicap_event_t event, unicap_handle_t handle, + unicap_data_buffer_t *ready_buffer, vj_unicap_t *v ) +{ +veejay_msg(0, "%s: wait",__FUNCTION__); + lock_(v); + + uint8_t *buffer[3] = + { + v->priv_buf, + v->priv_buf + v->sizes[0], + v->priv_buf + v->sizes[0] + v->sizes[1] + }; + + if( v->deinterlace ) + { + } + else + { + if(!v->rgb) + { + veejay_memcpy( buffer[0], ready_buffer->data, v->sizes[0] ); + veejay_memcpy( buffer[1], ready_buffer->data + v->sizes[0], v->sizes[1] ); + veejay_memcpy( buffer[2], ready_buffer->data + v->sizes[0] +v->sizes[1] , v->sizes[2]); + } + else + { + VJFrame *srci = yuv_rgb_template( ready_buffer->data, v->src_width,v->src_height, vut->src_fmt ); + VJFrame *dsti = yuv_yuv_template( buffer[0],buffer[1],buffer[2], v->dst_width,v->dst_height, vut->dst_fmt ); + + yuv_convert_any_ac(srci,dsti, srci->format, dsti->format ); + + free(srci); + free(dsti); + } + } + unlock_(v); +} +#endif + + +static int vj_unicap_stop_capture_( void *vut ) +{ + vj_unicap_t *v = (vj_unicap_t*) vut; + + + if( !SUCCESS( unicap_stop_capture( v->handle ) ) ) + { + veejay_msg(0,"Failed to stop capture on device: %s\n", v->device.identifier ); + } + + if(v->priv_buf) + free(v->priv_buf); + if(v->buffer.data) + free(v->buffer.data); + v->priv_buf = NULL; + v->buffer.data = NULL; + v->active = 0; + v->state = 0; + veejay_msg(VEEJAY_MSG_INFO, "Stopped capture from device %s", + v->device.identifier ); + return 1; +} + +int vj_unicap_status(void *vut) +{ + if(!vut) return 0; + vj_unicap_t *v = (vj_unicap_t*) vut; + return v->active; +} + +#ifndef USE_UNICAP_CB +static void unicap_delay(long nsec ) +{ + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = nsec * 1000000; + nanosleep( &ts, NULL ); +} + + +static void *unicap_reader_thread(void *data) +{ + vj_unicap_t *v = (vj_unicap_t*) data; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + + if(! vj_unicap_start_capture_( data ) ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Thread:Unable to start capture from device %s", v->device.identifier); + if(v->priv_buf) + free(v->priv_buf); + if(v->buffer.data) + free(v->buffer.data); + if(v->scaler) + yuv_free_swscaler(v->scaler); + v->priv_buf = NULL; + v->buffer.data = NULL; + v->active = 0; + v->state = 0; + v->scaler = NULL; + pthread_exit(NULL); + return NULL; + } + + v->state = 1; // thread run + //long s = 85000; + while( v->state ) + { + if( v->active ) + { + if(vj_unicap_grab_a_frame( data )==0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to grab a frame from capture device %d", v->deviceID); + v->state = 0; + } + // unicap_delay( s ); + } + } + + veejay_msg(VEEJAY_MSG_INFO, "Thread was told to stop capturing from device %d", v->deviceID); + vj_unicap_stop_capture_(data); + + pthread_exit(NULL); + + return NULL; +} +#endif +void vj_unicap_free_device( void *dud, void *vut ) +{ + vj_unicap_t *v = (vj_unicap_t*) vut; + unicap_driver_t *d = (unicap_driver_t*) dud; + + if( v->active ) + vj_unicap_stop_capture( vut ); + + d->devices[ v->deviceID ] = 0; + + if( v->handle ) + { + if( !SUCCESS( unicap_close( v->handle ) ) ) + { + veejay_msg(0, "Failed to close the device: %s\n", v->device.identifier ); + } + } + + int i = 0; + for( i = 0 ; i < 16 ; i ++ ) + { + if(v->ctrl[i]) + free(v->ctrl[i]); + } + + free( v ); + v = NULL; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-unicap.h b/branches/V-1.5.3/veejay-server/libstream/vj-unicap.h new file mode 100644 index 00000000..fae7d256 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-unicap.h @@ -0,0 +1,54 @@ +/* veejay - Linux VeeJay Unicap interface + * (C) 2002-2006 Niels Elburg + * + * + * 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. + */ +#ifndef VJUNICAPHH +#define VJUNICAPHH +void *vj_unicap_init(void); +void vj_unicap_deinit(void *dud ); +int vj_unicap_num_capture_devices( void *dud ); +char **vj_unicap_get_devices(void *unicap, int *n); +void *vj_unicap_new_device( void *ud, int device_id ); +int vj_unicap_configure_device( void *ud, int pixel_format, int w, int h, int composite ); +int vj_unicap_start_capture( void *vut ); +int vj_unicap_grab_frame( void *vut, uint8_t *buffer[3], const int w, const int h ); +int vj_unicap_stop_capture( void *vut ); +int vj_unicap_composite_status(void *ud ); +int vj_unicap_status(void *vut); +void vj_unicap_free_device( void *dud, void *vut ); +char **vj_unicap_get_list( void *ud ); +int vj_unicap_get_value( void *ud, char *key, int atom_type, void *value ); +int vj_unicap_select_value( void *ud, int key, double ); + +void vj_unicap_set_pause( void *vut , int status ); +int vj_unicap_get_pause( void *vut ); + +#define UNICAP_BRIGHTNESS 0 +#define UNICAP_COLOR 1 +#define UNICAP_SATURATION 2 +#define UNICAP_HUE 3 +#define UNICAP_CONTRAST 4 +#define UNICAP_SOURCE0 5 +#define UNICAP_SOURCE1 6 +#define UNICAP_SOURCE2 7 +#define UNICAP_SOURCE3 8 +#define UNICAP_SOURCE4 9 +#define UNICAP_PAL 10 +#define UNICAP_NTSC 11 +#define UNICAP_WHITE 12 +#endif + diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-vloopback.c b/branches/V-1.5.3/veejay-server/libstream/vj-vloopback.c new file mode 100644 index 00000000..b3d31be7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-vloopback.c @@ -0,0 +1,492 @@ +/* veejay - Linux VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + +/* + Put vloopback back in place + Re-used large portions of dc1394_vloopback.c + from Dan Dennedy + +*/ + +/* + vloopback pusher (using pipes) + If someone wants to implement mmap, add SIGIO to the signal catcher + and use mutexes for asynchronosouly handling IO. I am too lazy. + */ + +#include +#ifdef HAVE_V4L +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define VLOOPBACK_MMAP 0 // commented out +#define VLOOPBACK_PIPE 1 +#define VLOOPBACK_N_BUFS 2 + +typedef struct +{ + char *dev_name; /* device name */ + int palette; /* palette from vjframe */ + int width; + int height; + int norm; + int mode; /* PAL or NTSC */ + int fd; + int size; /* size of image out_buf */ + uint8_t *out_buf; + uint8_t *out_map; /* mmap segment */ +} vj_vloopback_t; + + +/* Open the vloopback device */ + +void *vj_vloopback_open(const char *device_name, int norm, int mode, + int w, int h, int pixel_format) +{ + void *ret = NULL; + vj_vloopback_t *v = (vj_vloopback_t*) vj_malloc(sizeof(vj_vloopback_t)); + if(!v) return ret; + + memset(v , 0, sizeof(vj_vloopback_t )); + + v->fd = open( device_name, O_RDWR, S_IRUSR|S_IWUSR ); + v->norm = norm; + v->mode = mode; + v->width = w; + v->height = h; + v->palette = (pixel_format == 1 ? VIDEO_PALETTE_YUV422P : + VIDEO_PALETTE_YUV420P ); + + if(!v->fd) + { + if(v) free(v); + veejay_msg(VEEJAY_MSG_ERROR, "Cannot open vloopback %s", + device_name ); + return ret; + } + + v->dev_name = strdup( device_name ); + + ret = (void*) v; + + veejay_msg(VEEJAY_MSG_DEBUG, + "Vloopback %s size %d x %d, palette YUV42%sP", + v->dev_name, + v->width, + v->height, + (pixel_format == 1 ? "2" : "0" ) ); + + return (void*) ret; +} + +int vj_vloopback_get_mode( void *vloop ) +{ + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + return v->mode; +} + +/* write mode*/ +int vj_vloopback_start_pipe( void *vloop ) +{ + struct video_capability caps; + struct video_window win; + struct video_picture pic; + + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + + if(!v) return 0; + + if(v->mode != VLOOPBACK_PIPE) + veejay_msg(VEEJAY_MSG_ERROR,"Program error"); + + /* the out_palette defines what format ! */ + + /* get capabilities */ + if( ioctl( v->fd, VIDIOCGCAP, &caps ) < 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Cant get video capabilities"); + return 0; + } + /* get picture */ + if( ioctl( v->fd, VIDIOCGPICT, &pic ) < 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Cant get video picture"); + return 0; + } + /* set palette */ + pic.palette = v->palette; + if( ioctl( v->fd, VIDIOCSPICT, &pic ) < 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Cant set video picture (palette %d)",v->palette); + return 0; + } + /* set window */ + win.width = v->width; + win.height = v->height; + if( ioctl( v->fd, VIDIOCSWIN, &win ) < 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG ,"Cant set video window %d x %d", + v->width,v->height ); + return 0; + } + + int len = v->width * v->height ; + int vshift = (v->palette == + VIDEO_PALETTE_YUV422P ? 0 : 1 ); + int uv_len = (v->width >> 1 ) * (v->height >> vshift); + + v->size = len + (2 * uv_len); + + veejay_msg(VEEJAY_MSG_DEBUG, + "vloopback pipe (Y plane %d bytes, UV plane %d bytes) H=%d, V=%d", + len,uv_len,1,vshift ); + + v->out_buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * v->size ); + + memset(v->out_buf, 0 , v->size ); + + if(!v->out_buf) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cant allocate sufficient memory for vloopback"); + return 0; + } + return 1; +} + +int vj_vloopback_write_pipe( void *vloop ) +{ + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + if(!v) return 0; + int res = write( v->fd, v->out_buf, v->size ); + if(res <= 0) + return 0; + return 1; +} + +int vj_vloopback_fill_buffer( void *vloop, uint8_t **frame ) +{ + // write frame to v->out_buf (veejay_memcpy) + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + if(!v) return 0; + + int len = v->width * v->height ; + int hshift = (v->palette == + VIDEO_PALETTE_YUV422P ? 0 : 1 ); + int uv_len = (v->width >> hshift ) * (v->height >> 1); + + // copy data to linear buffer */ + veejay_memcpy( v->out_buf, frame[0], len ); + + veejay_memcpy( v->out_buf + len, + frame[1], uv_len ); + veejay_memcpy( v->out_buf + len + uv_len, + frame[2], uv_len ); + + return 1; +} + +/* +int vj_vloopback_start_mmap( void *vloop ) +{ + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + if(!v) + return 0; + + + int len = v->width * v->height ; + int hshift = (v->palette == + VIDEO_PALETTE_YUV422P ? 0 : 1 ); + int uv_len = (v->width >> hshift ) * (v->height >> 1); + v->size = len + (2 * uv_len); + v->out_buf = (uint8_t*) vj_malloc( + sizeof(uint8_t) * v->size * VLOOPBACK_N_BUFS ); + + if(!v->out_buf) + return 0; + + v->out_map = mmap( 0, (v->size * VLOOPBACK_N_BUFS), PROT_READ| PROT_WRITE, + MAP_SHARED, v->fd , 0 ); + if( v->out_map == (uint8_t*) -1 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot mmap memory"); + return 0; + } + veejay_msg(VEEJAY_MSG_ERROR, "%s", __FUNCTION__ ); + return 1; +} + +int vj_vloopback_write_mmap( void *vloop, int frame ) +{ + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + veejay_memcpy( v->out_map + (v->size * frame), v->out_buf, v->size ); + return 1; +} + +int vj_vloopback_ioctl( void *vloop, unsigned long int cmd, void *arg ) +{ + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + veejay_msg(VEEJAY_MSG_INFO, "%s %d / %d", + __FUNCTION__, __LINE__ , cmd); + + switch(cmd) + { + case VIDIOCGCAP: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + struct video_capability *cap = arg; + sprintf( cap->name, "Veejay Digital Sampler"); + cap->type = VID_TYPE_CAPTURE; + cap->channels = 1; + cap->audios = 0; + cap->maxwidth = v->width; + cap->maxheight = v->height; + cap->minwidth = v->width; + cap->minheight = v->height; + break; + } + case VIDIOCGTUNER: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + struct video_tuner *tuner = arg; + sprintf( tuner->name, "Veejay Digital Sampler"); + tuner->tuner = 0; + tuner->rangelow = 0; + tuner->rangehigh = 0; + tuner->flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC; + tuner->mode = (v->norm ? VIDEO_MODE_PAL : VIDEO_MODE_NTSC); + tuner->signal = 0; + break; + } + case VIDIOCGCHAN: + { + struct video_channel *vidchan=arg; + vidchan->channel = 0; + vidchan->flags = 0; + vidchan->tuners = 0; + vidchan->type = VIDEO_TYPE_CAMERA; + strcpy(vidchan->name, "Veejay Dummy channel"); + break; + } + case VIDIOCGPICT: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + struct video_picture *vidpic=arg; + + vidpic->colour = 0xffff; + vidpic->hue = 0xffff; + vidpic->brightness = 0xffff; + vidpic->contrast = 0xffff; + vidpic->whiteness = 0xffff; + + vidpic->palette = v->palette; + vidpic->depth = ( + v->palette == VIDEO_PALETTE_YUV420P ? + 12 : 16 ); + break; + } + case VIDIOCSPICT: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + struct video_picture *vidpic=arg; + if(vidpic->palette != v->palette ) + veejay_msg(VEEJAY_MSG_ERROR, + "requested palette %d, but only using %d now", + vidpic->palette, v->palette ); + return 1; + } + + case VIDIOCCAPTURE: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + break; + } + + case VIDIOCGWIN: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + struct video_window *vidwin=arg; + + vidwin->x=0; + vidwin->y=0; + vidwin->width=v->width; + vidwin->height=v->height; + vidwin->chromakey=0; + vidwin->flags=0; + vidwin->samplecount=0; + break; + } + case VIDIOCSWIN: + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot change size ! "); + break; + } + + case VIDIOCGMBUF: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + struct video_mbuf *vidmbuf=arg; + int i; + + vidmbuf->size = v->size; + vidmbuf->frames = VLOOPBACK_N_BUFS; + + for (i=0; i < VLOOPBACK_N_BUFS; i++) + vidmbuf->offsets[i] = i * vidmbuf->size; + vidmbuf->size *= vidmbuf->frames; + break; + } + + case VIDIOCMCAPTURE: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + struct video_mmap *vidmmap=arg; + + if ( vidmmap->format != v->palette ) + { + veejay_msg(VEEJAY_MSG_ERROR, "capture palette not current palette!"); + return 1; + } + + if (vidmmap->height != v->height || + vidmmap->width != v->width) { + veejay_msg(VEEJAY_MSG_ERROR, "caputure: invalid size %dx%d\n", vidmmap->width, vidmmap->height ); + return 1; + } + break; + } + case VIDIOCSYNC: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + struct video_mmap *vidmmap=arg; + if(!vj_vloopback_write_mmap( vloop, vidmmap->frame )) + return 1; + break; + } + default: + { + veejay_msg(VEEJAY_MSG_INFO, "%s %d", + __FUNCTION__, __LINE__ ); + + veejay_msg(VEEJAY_MSG_ERROR, "ioctl %ld unhandled\n", cmd & 0xff); + break; + } + + + } + return 0; +} +*/ +void vj_vloopback_close( void *vloop ) +{ + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + if(v) + { + if(v->fd) + close( v->fd ); + if(v->out_buf) + free(v->out_buf); +/* if(v->out_map) + munmap( v->out_map, + v->size * VLOOPBACK_N_BUFS );*/ + free(v); + } +} + +/* +void vj_vloopback_signal_handler( void *vloop, int sig_no ) +{ + int size,ret; + unsigned long int cmd; + struct pollfd ufds; + char ioctlbuf[1024]; + + vj_vloopback_t *v = (vj_vloopback_t*) vloop; + + if(sig_no != SIGIO ) + return; + + + ufds.fd = v->fd; + ufds.events = POLLIN; + ufds.revents = 0; + + poll( &ufds, 1, 10 ); // 10 ms too small ? + + if( !ufds.revents & POLLIN ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Received signal but got negative on poll"); + return; + } + + size = read( v->fd, ioctlbuf, 1024 ); + if( size >= sizeof( unsigned long int )) + { + veejay_memcpy( &cmd, ioctlbuf, sizeof(unsigned long int)); + if( cmd == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Client closed device"); + return; + } + ret = vj_vloopback_ioctl( vloop, cmd, ioctlbuf + sizeof( unsigned long int )); + if(ret) + { + memset( ioctlbuf + sizeof( unsigned long int ), 1024 - sizeof( unsigned long int ),0xff); + veejay_msg(VEEJAY_MSG_ERROR, + "IOCTL %d unsuccessfull", cmd & 0xff); + } + ioctl( v->fd, cmd, ioctlbuf + sizeof( unsigned long int )); + } + return ; +} +*/ +#endif + diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-vloopback.h b/branches/V-1.5.3/veejay-server/libstream/vj-vloopback.h new file mode 100644 index 00000000..3d38e657 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-vloopback.h @@ -0,0 +1,42 @@ +/* veejay - Linux VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ + + + +void *vj_vloopback_open(const char *device_name, int norm, int mode, + int w, int h, int pixel_format); +// if using write mode +int vj_vloopback_start_pipe( void *vloop ); +int vj_vloopback_write_pipe( void *vloop ); + +// resfresh buffer every cycle +int vj_vloopback_fill_buffer( void *vloop, uint8_t **image ); + +// if using mmap mode +//int vj_vloopback_start_mmap( void *vloop ); + +//int vj_vloopback_ioctl( void *vloop, unsigned long int cmd, void *arg ); +void vj_vlooopback_close( void *vloop ); + +int vj_vloopback_get_mode( void *vloop ); +void vj_vloopback_close( void *vloop ); + + +//void vj_vloopback_signal_handler( void *vloop, int sig_no ); + diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-yuv4mpeg.c b/branches/V-1.5.3/veejay-server/libstream/vj-yuv4mpeg.c new file mode 100644 index 00000000..3bc685ee --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-yuv4mpeg.c @@ -0,0 +1,499 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +/* the audio routines are placed here + because its a feature i need. needs to be removed or put elsewhere. +*/ + + +#define L_FOURCC(a,b,c,d) ( (d<<24) | ((c&0xff)<<16) | ((b&0xff)<<8) | (a&0xff) ) + +#define L_FOURCC_RIFF L_FOURCC ('R', 'I', 'F', 'F') +#define L_FOURCC_WAVE L_FOURCC ('W', 'A', 'V', 'E') +#define L_FOURCC_FMT L_FOURCC ('f', 'm', 't', ' ') +#define L_FOURCC_DATA L_FOURCC ('d', 'a', 't', 'a') + +typedef struct { + unsigned long rifftag; + unsigned long rifflen; + unsigned long wavetag; + unsigned long fmt_tag; + unsigned long fmt_len; + unsigned short wFormatTag; + unsigned short nChannels; + unsigned long nSamplesPerSec; + unsigned long nAvgBytesPerSec; + unsigned short nBlockAlign; + unsigned short wBitsPerSample; + unsigned long datatag; + unsigned long datalen; +} t_wave_hdr; + +t_wave_hdr *wave_hdr; + +int bytecount = 0; + +vj_yuv *vj_yuv4mpeg_alloc(editlist * el, int w, int h, int out_pixel_format) +{ + vj_yuv *yuv4mpeg = (vj_yuv *) vj_calloc(sizeof(vj_yuv)); + if(!yuv4mpeg) return NULL; + yuv4mpeg->sar = y4m_sar_UNKNOWN; + yuv4mpeg->dar = y4m_dar_4_3; + y4m_accept_extensions( 1 ); + y4m_init_stream_info(&(yuv4mpeg->streaminfo)); + y4m_init_frame_info(&(yuv4mpeg->frameinfo)); + yuv4mpeg->width = w; + yuv4mpeg->height = h; + yuv4mpeg->audio_rate = el->audio_rate; + yuv4mpeg->video_fps = el->video_fps; + yuv4mpeg->has_audio = el->has_audio; + yuv4mpeg->audio_bits = el->audio_bps; + if( out_pixel_format == FMT_422F || out_pixel_format == FMT_420F ) { + yuv4mpeg->is_jpeg = 1; + } else { + yuv4mpeg->is_jpeg = 0; + } + yuv4mpeg->chroma = Y4M_CHROMA_422; //@ default + yuv4mpeg->scaler = NULL; + return yuv4mpeg; +} + +void vj_yuv4mpeg_free(vj_yuv *v) { + if(v) { + if( v->scaler ) { + yuv_free_swscaler( v->scaler ); + v->scaler = NULL; + } + if(v->buf[0] != NULL ) + free(v->buf[0]); + free(v); + } +} + +static int vj_yuv_stream_start_read1(vj_yuv * yuv4mpeg, int fd, int width, int height); + +int vj_yuv_stream_start_read(vj_yuv * yuv4mpeg, char *filename, int width, + int height) { + int fd = open(filename,O_RDONLY); + if(!fd) { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to open video stream %s\n", filename); + return -1; + } + return vj_yuv_stream_start_read1( yuv4mpeg, fd, width,height ); +} + +int vj_yuv_stream_start_read_fd( vj_yuv *yuv4mpeg, int fd, int width,int height ) +{ + return vj_yuv_stream_start_read1( yuv4mpeg,fd,width,height ); +} + +static int vj_yuv_stream_start_read1(vj_yuv * yuv4mpeg, int fd, int width, + int height) +{ + int i, w, h; + + yuv4mpeg->fd = fd; + + i = y4m_read_stream_header(yuv4mpeg->fd, &(yuv4mpeg->streaminfo)); + if (i != Y4M_OK) { + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg: %s", y4m_strerr(i)); + return -1; + } + + w = y4m_si_get_width(&(yuv4mpeg->streaminfo)); + h = y4m_si_get_height(&(yuv4mpeg->streaminfo)); + + yuv4mpeg->chroma = y4m_si_get_chroma( &(yuv4mpeg->streaminfo) ); + + if( yuv4mpeg->chroma != Y4M_CHROMA_422 ) { + yuv4mpeg->buf[0] = vj_calloc( sizeof(uint8_t) * w * h * 4 ); + yuv4mpeg->buf[1] = yuv4mpeg->buf[0] + (w*h); + yuv4mpeg->buf[2] = yuv4mpeg->buf[1] + (w*h); + yuv4mpeg->buf[3] = yuv4mpeg->buf[2] + (w*h); + } + + int plane_count = y4m_si_get_plane_count( &(yuv4mpeg->streaminfo) ); + + veejay_msg(VEEJAY_MSG_DEBUG, "Frame: %dx%d, number of planes: %d, chroma: %s", + w,h,plane_count, y4m_chroma_keyword( yuv4mpeg->chroma )); + + for( i =0; i < plane_count ; i ++ ) { + yuv4mpeg->plane_w[i] = y4m_si_get_plane_width( &(yuv4mpeg->streaminfo), i); + yuv4mpeg->plane_h[i] = y4m_si_get_plane_height( &(yuv4mpeg->streaminfo), i); + yuv4mpeg->plane_size[i] = y4m_si_get_plane_length( &(yuv4mpeg->streaminfo), i ); + veejay_msg(VEEJAY_MSG_DEBUG, + "\tPlane %d: %dx%d, length=%d", + i, + yuv4mpeg->plane_w[i], + yuv4mpeg->plane_h[i], + yuv4mpeg->plane_size[i] ); + } + + + + if( w != width || h != height ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Video dimensions: %d x %d must match %d x %d. Stream cannot be opened", w, h, + width, height); + return -1; + } + + return 0; +} + +uint8_t *vj_yuv_get_buf( void *v ) { + vj_yuv *y = (vj_yuv*)v; + return y->buf; +} + +int vj_yuv_stream_write_header(vj_yuv * yuv4mpeg, editlist * el, int out_chroma) +{ + int i = 0; + y4m_si_set_width(&(yuv4mpeg->streaminfo), yuv4mpeg->width); + y4m_si_set_height(&(yuv4mpeg->streaminfo), yuv4mpeg->height); + y4m_si_set_interlace(&(yuv4mpeg->streaminfo), Y4M_ILACE_NONE); + y4m_si_set_chroma( &(yuv4mpeg->streaminfo), out_chroma ); + y4m_si_set_framerate(&(yuv4mpeg->streaminfo), + mpeg_conform_framerate(el->video_fps)); + + yuv4mpeg->chroma = out_chroma; +yuv4mpeg->buf[0] = vj_calloc(sizeof(uint8_t) * yuv4mpeg->width * yuv4mpeg->height * 4 ); + yuv4mpeg->buf[1] = yuv4mpeg->buf[0] + yuv4mpeg->width * yuv4mpeg->height; + yuv4mpeg->buf[2] = yuv4mpeg->buf[1] + yuv4mpeg->width * yuv4mpeg->height; + yuv4mpeg->buf[3] = yuv4mpeg->buf[2] + yuv4mpeg->width * yuv4mpeg->height; + if (!Y4M_RATIO_EQL(yuv4mpeg->sar, y4m_sar_UNKNOWN)) { + yuv4mpeg->sar.n = el->video_sar_width; + yuv4mpeg->sar.d = el->video_sar_height; + y4m_si_set_sampleaspect(&(yuv4mpeg->streaminfo), yuv4mpeg->sar); + } else { + y4m_ratio_t dar2 = y4m_guess_sar(yuv4mpeg->width, + yuv4mpeg->height, + yuv4mpeg->dar); + y4m_si_set_sampleaspect(&(yuv4mpeg->streaminfo), dar2); + } + + i = y4m_write_stream_header(yuv4mpeg->fd, &(yuv4mpeg->streaminfo)); + + y4m_log_stream_info(2, "yuv4mpeg: ", &(yuv4mpeg->streaminfo)); + if (i != Y4M_OK) + return -1; + + return 0; +} + +int vj_yuv_stream_open_pipe(vj_yuv *yuv4mpeg, char *filename,editlist *el) +{ + yuv4mpeg->fd = open(filename,O_WRONLY,0600); + if(!yuv4mpeg->fd) return 0; + return 1; +} +int vj_yuv_stream_header_pipe(vj_yuv *yuv4mpeg,editlist *el) +{ + yuv4mpeg->has_audio = el->has_audio; + vj_yuv_stream_write_header(yuv4mpeg, el,FMT_420); + + //if (el->has_audio) { +// if (!vj_yuv_write_wave_header(el, filename)) +// return 0; + // } + return 1; +} + +int vj_yuv_stream_start_write(vj_yuv * yuv4mpeg,editlist *el, char *filename, int outchroma) +{ +#ifdef STRICT_CHECKING + assert( filename != NULL ); + assert( strlen(filename) > 3 ); +#endif + //if(mkfifo( filename, 0600)!=0) return -1; + /* if the file exists gamble and simply append, + if it does not exist write header + + */ + struct stat sstat; + + if(strncasecmp( filename, "stdout", 6) == 0) + { + yuv4mpeg->fd = 1; + } + else + { + if(strncasecmp(filename, "stderr", 6) == 0) + { + yuv4mpeg->fd = 2; + } + else + { + if (stat(filename, &sstat) == 0) + { + if (S_ISREG(sstat.st_mode)) + { + /* the file is a regular file */ + yuv4mpeg->fd = open(filename, O_APPEND | O_WRONLY, 0600); + if (!yuv4mpeg->fd) + return -1; + } + else + { + if (S_ISFIFO(sstat.st_mode)) + veejay_msg(VEEJAY_MSG_INFO, "Waiting for a program to open %s", filename); + yuv4mpeg->fd = open(filename,O_WRONLY,0600); + if(!yuv4mpeg->fd) return 0; + + } + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Creating YUV4MPEG regular file '%s'", + filename); + yuv4mpeg->fd = open(filename, O_CREAT | O_WRONLY, 0600); + if (!yuv4mpeg->fd) + return -1; + } + } + + } + + if( vj_yuv_stream_write_header(yuv4mpeg, el, outchroma) < 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Error while writing y4m header."); + return -1; + } + + yuv4mpeg->has_audio = el->has_audio; + + return 0; +} + +void vj_yuv_stream_stop_write(vj_yuv * yuv4mpeg) +{ + y4m_fini_stream_info(&(yuv4mpeg->streaminfo)); + y4m_fini_frame_info(&(yuv4mpeg->frameinfo)); + close(yuv4mpeg->fd); +} + +void vj_yuv_stream_stop_read(vj_yuv * yuv4mpeg) +{ + y4m_fini_stream_info(&(yuv4mpeg->streaminfo)); + y4m_fini_frame_info(&(yuv4mpeg->frameinfo)); + close(yuv4mpeg->fd); + yuv4mpeg->sar = y4m_sar_UNKNOWN; + yuv4mpeg->dar = y4m_dar_4_3; + if( yuv4mpeg->scaler ) { + yuv_free_swscaler( yuv4mpeg->scaler ); + yuv4mpeg->scaler = NULL; + } + if( yuv4mpeg->buf[0] ) { + free(yuv4mpeg->buf[0]); + yuv4mpeg->buf[0] = NULL; + } + +} + +static int vj_yuv_restart(vj_yuv *yuv4mpeg ) +{ + y4m_stream_info_t dummy; + if( lseek( yuv4mpeg->fd , 0, SEEK_SET ) < 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Error seeking to start of y4m stream."); + return -1; + } + + //@ read out header + int i = y4m_read_stream_header(yuv4mpeg->fd, &dummy); + if (i != Y4M_OK) { + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg: %s", y4m_strerr(i)); + return -1; + } + + return 0; +} + +int vj_yuv_get_frame(vj_yuv * yuv4mpeg, uint8_t *dst[3]) +{ + int i; +// playing in CCIR + if( yuv4mpeg->chroma == Y4M_CHROMA_422 && yuv4mpeg->is_jpeg == 0 ) { + i = y4m_read_frame(yuv4mpeg->fd, &(yuv4mpeg->streaminfo),&(yuv4mpeg->frameinfo), dst); + if (i != Y4M_OK) + { + if( i == Y4M_ERR_EOF ) { + if( vj_yuv_restart( yuv4mpeg ) == 0 ) + { + i = y4m_read_frame(yuv4mpeg->fd, &(yuv4mpeg->streaminfo),&(yuv4mpeg->frameinfo), dst); + if ( i == Y4M_OK ) + return 0; + } + } + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg %s", y4m_strerr(i)); + return -1; + } + return 0; +// in JPEG + } else if ( yuv4mpeg->chroma == Y4M_CHROMA_422 && yuv4mpeg->is_jpeg == 1 ) { + i = y4m_read_frame(yuv4mpeg->fd, &(yuv4mpeg->streaminfo),&(yuv4mpeg->frameinfo), dst); + if (i != Y4M_OK) + { + if( i == Y4M_ERR_EOF ) { + if( vj_yuv_restart( yuv4mpeg ) == 0 ) { + i = y4m_read_frame( yuv4mpeg->fd,&(yuv4mpeg->streaminfo),&(yuv4mpeg->frameinfo),dst ); + if( i == Y4M_OK ) { + yuv_scale_pixels_from_ycbcr( dst[0], 16.0f, 235.0f, yuv4mpeg->width * yuv4mpeg->height ); + yuv_scale_pixels_from_ycbcr( dst[1], 16.0f, 240.0f, (yuv4mpeg->width * yuv4mpeg->height) / 2 ); + return 0; + + } + } + } + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg %s", y4m_strerr(i)); + return -1; + } + yuv_scale_pixels_from_ycbcr( dst[0], 16.0f, 235.0f, yuv4mpeg->width * yuv4mpeg->height ); + yuv_scale_pixels_from_ycbcr( dst[1], 16.0f, 240.0f, (yuv4mpeg->width * yuv4mpeg->height) / 2 ); + return 0; + } +// not 422 + if( yuv4mpeg->chroma != Y4M_CHROMA_422 ) { + i = y4m_read_frame(yuv4mpeg->fd, &(yuv4mpeg->streaminfo),&(yuv4mpeg->frameinfo), yuv4mpeg->buf); + if( i != Y4M_OK ) { + if( i == Y4M_ERR_EOF ) { + if( vj_yuv_restart( yuv4mpeg ) == 0 ) { + i = y4m_read_frame(yuv4mpeg->fd,&(yuv4mpeg->streaminfo),&(yuv4mpeg->frameinfo),yuv4mpeg->buf); + if( i != Y4M_OK ) { + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg %s", y4m_strerr(i)); + return -1; + } + } + } + else { + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg %s", y4m_strerr(i)); + return -1; + } + } + + int src_fmt; + switch( yuv4mpeg->chroma ) { + case Y4M_CHROMA_420JPEG: + src_fmt = PIX_FMT_YUVJ420P; break; + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + src_fmt = PIX_FMT_YUV420P; break; + case Y4M_CHROMA_422: + src_fmt = PIX_FMT_YUV422P; break; + case Y4M_CHROMA_444: + src_fmt = PIX_FMT_YUV444P; break; + case Y4M_CHROMA_411: + src_fmt = PIX_FMT_YUV411P; break; + case Y4M_CHROMA_MONO: + src_fmt = PIX_FMT_GRAY8; break; + default: + veejay_msg(0, "Can't handle chroma '%s'", y4m_chroma_keyword( yuv4mpeg->chroma )); + return -1; + break; + } + + VJFrame *srcf = yuv_yuv_template( yuv4mpeg->buf[0], yuv4mpeg->buf[1], yuv4mpeg->buf[2],yuv4mpeg->width,yuv4mpeg->height, src_fmt ); + + VJFrame *dstf = yuv_yuv_template( dst[0],dst[1],dst[2], yuv4mpeg->width,yuv4mpeg->height, PIX_FMT_YUV422P ); + + if(!yuv4mpeg->scaler) { + sws_template sws_tem; + memset(&sws_tem, 0,sizeof(sws_template)); + sws_tem.flags = yuv_which_scaler(); + yuv4mpeg->scaler = yuv_init_swscaler( srcf,dstf, &sws_tem, yuv_sws_get_cpu_flags()); + if(!yuv4mpeg->scaler) { + free(srcf); free(dstf); + return -1; + } + } + + yuv_convert_and_scale( yuv4mpeg->scaler, srcf, dstf ); + + + free(srcf); + free(dstf); + + if (yuv4mpeg->is_jpeg == 1 ) { + yuv_scale_pixels_from_ycbcr( dst[0], 16.0f, 235.0f, yuv4mpeg->width * yuv4mpeg->height ); + yuv_scale_pixels_from_ycbcr( dst[1], 16.0f, 240.0f, (yuv4mpeg->width * yuv4mpeg->height) / 2 ); + } + return 0; + } + + return -1; +} + +int vj_yuv_get_aframe(vj_yuv * yuv4mpeg, uint8_t * audio) +{ + return 0; /*un used */ + +} + +int vj_yuv_put_frame(vj_yuv * vjyuv, uint8_t ** src) +{ + int i; + if (!vjyuv->fd) { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid file descriptor for y4m stream"); + return -1; + } +//@ assumes caller responsibility for jpeg/ccir: see vj-avcodec.c + if( vjyuv->chroma == Y4M_CHROMA_422 ) { + i = y4m_write_frame(vjyuv->fd, &(vjyuv->streaminfo),&(vjyuv->frameinfo), src); + if (i != Y4M_OK) { + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg: %s", y4m_strerr(i)); + return -1; + } + + return 0; + } + else { + if( vjyuv->chroma == Y4M_CHROMA_420JPEG || vjyuv->chroma == Y4M_CHROMA_420MPEG2 ) { + uint8_t *frame[3] = { src[0], vjyuv->buf[1], vjyuv->buf[2] }; + yuv422to420planar( src, vjyuv->buf, vjyuv->width, vjyuv->height ); + i = y4m_write_frame(vjyuv->fd, &(vjyuv->streaminfo),&(vjyuv->frameinfo),frame); + if (i != Y4M_OK) { + veejay_msg(VEEJAY_MSG_ERROR, "yuv4mpeg: %s", y4m_strerr(i)); + return -1; + } + return 0; + } + + } + return -1; +} +int vj_yuv_put_aframe(uint8_t * audio, editlist * el, int len) +{ + int i = 0; + return i; +} diff --git a/branches/V-1.5.3/veejay-server/libstream/vj-yuv4mpeg.h b/branches/V-1.5.3/veejay-server/libstream/vj-yuv4mpeg.h new file mode 100644 index 00000000..41c9f56c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libstream/vj-yuv4mpeg.h @@ -0,0 +1,77 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_YUV4MPEG_H +#define VJ_YUV4MPEG_H +#include +#include + +typedef struct { + y4m_stream_info_t streaminfo; + y4m_frame_info_t frameinfo; + y4m_ratio_t sar; + y4m_ratio_t dar; + int plane_w[4]; + int plane_h[4]; + int plane_size[4]; + int chroma; + int width; + int height; + int fd; + int has_audio; + int audio_bits; + float video_fps; + long audio_rate; + void *scaler; + uint8_t *buf[4]; + int is_jpeg; +} vj_yuv; + +vj_yuv *vj_yuv4mpeg_alloc(editlist * el, int dst_w, int dst_h, int out_pix_fmt); + + +uint8_t *vj_yuv_get_buf( void *v ); + +void vj_yuv4mpeg_free(vj_yuv *v) ; + +int vj_yuv_stream_start_read_fd( vj_yuv *, int fd, int width,int height ); + +int vj_yuv_stream_start_read(vj_yuv *, char *, int width, int height); + +int vj_yuv_stream_write_header(vj_yuv * yuv4mpeg, editlist * el, int outchroma); + +int vj_yuv_stream_start_write(vj_yuv *,editlist *, char *, int); + +void vj_yuv_stream_stop_read(vj_yuv * yuv4mpeg); + +void vj_yuv_stream_stop_write(vj_yuv * yuv4mpeg); + +int vj_yuv_get_frame(vj_yuv *, uint8_t **); + +int vj_yuv_put_frame(vj_yuv * vjyuv, uint8_t **); + +int vj_yuv_get_aframe(vj_yuv * vjyuv, uint8_t * audio); + +int vj_yuv_put_aframe(uint8_t * audio, editlist *el, int len); + +int vj_yuv_write_wave_header(editlist * el, char *outfile); + +int vj_yuv_stream_open_pipe(vj_yuv *, char *, editlist *el); + +int vj_yuv_stream_header_pipe( vj_yuv *, editlist *el ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvevo/Makefile.am b/branches/V-1.5.3/veejay-server/libvevo/Makefile.am new file mode 100644 index 00000000..527ce7ce --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvevo/Makefile.am @@ -0,0 +1,10 @@ +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)/libvevo -I$(includedir) -I$(top_srcdir)/libhash -I$(top_srcdir)/libvjmem -I$(top_srcdir)/libvjmsg + +VEVO_LIB_FILE = libvevo.la +pkginclude_HEADERS = libvevo.h lowlevel.h pool.h vevo.h +noinst_LTLIBRARIES = $(VEVO_LIB_FILE) + +libvevo_la_SOURCES = pool.c vevo.c + diff --git a/branches/V-1.5.3/veejay-server/libvevo/libvevo.h b/branches/V-1.5.3/veejay-server/libvevo/libvevo.h new file mode 100644 index 00000000..90622a4c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvevo/libvevo.h @@ -0,0 +1,141 @@ +/* +Copyright (c) 2004-2007 N.Elburg + + This is vevo, veejay video objects. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef LIBVEVO +#define LIBVEVO + +#include +#include + +typedef void vevo_port_t; + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +#ifdef STRICT_CHECKING +#define vpn(type) vevo_port_new( type, __FUNCTION__ , __LINE__ ) +#else +#define vpn(type) vevo_port_new( type ) +#endif + +int vevo_property_num_elements( vevo_port_t *p, const char *key); + +int vevo_property_atom_type( vevo_port_t *p, const char *key); + +size_t vevo_property_element_size( vevo_port_t * p, const char *key, const int idx); + +#ifdef STRICT_CHECKING +vevo_port_t *vevo_port_new( int port_type, const char *func, int line_no ); +#else +vevo_port_t *vevo_port_new(int port_type); +#endif +int vevo_property_soft_reference(vevo_port_t * p, const char *key); + +void vevo_strict_init(); + +int vevo_port_verify( vevo_port_t *port ); + +void vevo_port_free( vevo_port_t *port ); + +int vevo_property_set(vevo_port_t * p, const char *key, int atom_type, int num_elements, void *src); + +int vevo_union_ports( void *port_a, void *port_b, int filter_type ); + +int vevo_property_get(vevo_port_t * p, const char *key, int idx, void *dst); + +char **vevo_list_properties(vevo_port_t * p); + +void vevo_port_recursive_free(vevo_port_t *p ); + +void vevo_port_dump( vevo_port_t *p ); + +char *vevo_format_kind( vevo_port_t *port, const char *key ); + +char *vevo_format_property( vevo_port_t *port, const char *key ); + +void vevo_report_stats(); + +int vevo_property_del(vevo_port_t * p, const char *key ); + +char **vevo_port_deepen_namespace( void *port, char *path); + +char **vevo_port_recurse_namespace( vevo_port_t *port, const char *base ); + +void *vevo_port_register( vevo_port_t *in, vevo_port_t *ref ); + +char *vevo_sprintf_property( vevo_port_t *port, const char *key ); + +int vevo_sscanf_property( vevo_port_t *port, const char *s); + +char **vevo_sprintf_port( vevo_port_t *port ); + +int vevo_sscanf_port( vevo_port_t *port, const char *s ); + +int vevo_special_union_ports( void *port_a, void *port_b ); + +int vevo_property_from_string( vevo_port_t *port, const char *s, const char *key, int n_elem, int type); + +char *vevo_sprintf_property_value( vevo_port_t *port, const char *key); + +char *vevo_property_get_string( void *port, const char *key ); + +void vevo_strict_init(); + +#define VEVO_ATOM_TYPE_VOIDPTR 65 +#define VEVO_ATOM_TYPE_INT 1 +#define VEVO_ATOM_TYPE_DOUBLE 2 +#define VEVO_ATOM_TYPE_STRING 4 +#define VEVO_ATOM_TYPE_BOOL 3 +#define VEVO_ATOM_TYPE_PORTPTR 66 +#define VEVO_ATOM_TYPE_HIDDEN 50 +#define VEVO_ATOM_TYPE_UINT64 5 + +#define VEVO_NO_ERROR 0 +#define VEVO_ERROR_MEMORY_ALLOCATION 1 +#define VEVO_ERROR_PROPERTY_READONLY 2 +#define VEVO_ERROR_NOSUCH_ELEMENT 3 +#define VEVO_ERROR_NOSUCH_PROPERTY 4 +#define VEVO_ERROR_WRONG_ATOM_TYPE 5 +#define VEVO_ERROR_TOO_MANY_INSTANCES 6 +#define VEVO_ERROR_HARDWARE 7 +#define VEVO_ERROR_PROPERTY_EMPTY 8 + + +#define VEVO_PORT_POOL 1041 +#define VEVO_ANONYMOUS_PORT -1 + +#define VEVO_PROPERTY_READONLY (1<<1) +#define VEVO_PROPERTY_SOFTREF (1<<2) +#define VEVO_PROPERTY_PROTECTED (1<<10) + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvevo/lowlevel.h b/branches/V-1.5.3/veejay-server/libvevo/lowlevel.h new file mode 100644 index 00000000..d7d7dc89 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvevo/lowlevel.h @@ -0,0 +1,36 @@ +/* +Copyright (c) 2004-2005 N.Elburg + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef VEVO_LOW_LEVEL_H +#define VEVO_LOW_LEVEL_H +/* Mediation layer structures, provided by this host */ +typedef struct { + int type; + void *value; + size_t size; +} atom_t; +#endif diff --git a/branches/V-1.5.3/veejay-server/libvevo/pool.c b/branches/V-1.5.3/veejay-server/libvevo/pool.c new file mode 100644 index 00000000..456cbed7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvevo/pool.c @@ -0,0 +1,291 @@ +/* +Copyright (c) 2004-2005 N.Elburg + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + /** \defgroup mem_pool Efficient Object Caching + * + * To reduce the overhead of malloc/free when allocating and freeing many small objects + * I keep a linked list of Spaces. Each Space holds a continuous + * memory area that is of size ROUNDS_PER_MAG * sizeof(type). This area is divided + * into ROUND_PER_MAG chunks. The malloc() replacement pops a round from the stack, + * whilst the free() replacement pushes a round back to the stack. + * The stack size is limited to ROUNDS_PER_MAG + * When the stack is full, a new magazine is allocated and added to the linked list + * of magazines. + * + * This is basically how the slab allocator works in a linux kernel +*/ +#include +#include +#include +#include +#include +#include "pool.h" + +#ifdef STRICT_CHECKING +#include +#endif + +//! \typedef space_t structure +/*! The space_t structure is a linked list of spaces. + Each space has a magazine that can hold up to ROUNDS_PER_MAG rounds. + The magazine is a stack. + Each round in the magazine is of a fixed size + */ +typedef struct +{ + unsigned char *area; /*!< Pointer to memory space containing ROUNDS_PER_MAG objects */ + unsigned char **mag; /*!< A magazine is a ROUNDS_PER_MAG-element array of pointers to objects */ + int rounds; /*!< Available rounds*/ + void *next; /*!< Pointer to next space */ +} space_t; + +//! \typedef pool_t structure +/*! The pool_t structure is a pool of spaces + * Each pool has 1 or more spaces. + */ +typedef struct +{ + space_t **spaces; /*!< array of spaces */ + space_t *space; /*!< single space */ +} pool_t; + +//!Allocate a new space of a fixed size +/*! + \param bs size in bytes + \return New space that holds ROUNDS_PER_MAG rounds + */ +static space_t *alloc_space( size_t bs ) +{ + int k; + unsigned char *p; + space_t *s; + s = (space_t*) vj_malloc(sizeof(space_t)); +#ifdef STRICT_CHECKING + assert( s != NULL ); +#endif + s->area = vj_malloc(bs * ROUNDS_PER_MAG); + s->mag = vj_malloc( sizeof(void*) * (ROUNDS_PER_MAG + 1) ); + p = s->area; + for( k = 0; k <= ROUNDS_PER_MAG ;k ++ ) + { + s->mag[k] = p; + p += bs; + } + s->rounds = ROUNDS_PER_MAG; + s->next = NULL; + return s; +} + +//! Allocate a new pool with spaces of various fixed sizes +/*! + \param prop_size size in bytes of vevo_property_t + \param stor_size size in bytes of vevo_storage_t + \param atom_size size in bytes of atom_t + \param index_size size in bytes of prop_node_t + \return A new pool that holds various fixed sized Spaces + */ +void *vevo_pool_init(size_t prop_size,size_t stor_size, size_t atom_size, size_t index_size) +{ + unsigned int Msize = Mend + 1; + pool_t *p = (pool_t*) vj_malloc(sizeof(pool_t)); +#ifdef STRICT_CHECKING + assert( p != NULL ); +#endif + p->space = NULL; + p->spaces = (space_t**) vj_malloc(sizeof(space_t*) * Msize ); + p->spaces[M4b] = alloc_space( sizeof(int32_t) ); + p->spaces[M8b] = alloc_space( sizeof(double) ); + p->spaces[Mpb] = alloc_space( sizeof(void*) ); + p->spaces[M64b] = alloc_space(sizeof(uint64_t) ); + p->spaces[Mprop] = alloc_space( prop_size ); + p->spaces[Mstor] = alloc_space( stor_size ); + p->spaces[Matom] = alloc_space( atom_size ); + p->spaces[Midx] = alloc_space( index_size ); + p->spaces[Mend] = NULL; + return (void*)p; +} + +//! Allocate a new pool with a single space of a fixed size +/*! + \param node_size size in bytes of a single block + \return A new pool with a single space + */ +void *vevo_pool_slice_init( size_t node_size ) +{ + pool_t *p = (pool_t*) malloc(sizeof(pool_t)); + p->spaces = NULL; + p->space = alloc_space( node_size ); + return p; +} + +//! Get a pointer to the starting address of an unused block. Pops a round from the magazine and creates a new space if magazine is empty. +/*! + \param p pointer to pool_t structure + \param bs size of block to allocate + \param k base type of block to allocate + \return pointer to free block + */ +void *vevo_pool_alloc( void *p, size_t bs, unsigned int k ) +{ + pool_t *pool = (pool_t*) p; + space_t *space = pool->spaces[k]; + if( space->rounds == 0 ) + { // no more rounds to fire, create a new magazine and add it to the list + space_t *m = alloc_space( bs ); + m->next = space; + pool->spaces[k] = m; + space = m; + } + void **mag = (void**)pool->spaces[k]->mag; + return mag[ --space->rounds ]; +} + +//! Pushes a round to a magazine that is not full +/*! + \param p pointer to pool_t structure + \param ptr pointer to address of block + \param k base type of block to allocate + */ +void vevo_pool_free( void *p, void *ptr, unsigned int k ) +{ + pool_t *pool = (pool_t*) p; + unsigned int n = pool->spaces[k]->rounds; + space_t *space = pool->spaces[k]; + unsigned char **mag = space->mag; + if( n == ROUNDS_PER_MAG ) + { + space_t *l = space; + while( l != NULL ) + { + if( l->rounds < ROUNDS_PER_MAG ) + { + mag = l->mag; + mag[ l->rounds ++ ] = ptr; + return; + } + l = l->next; + } + } + mag[ space->rounds++ ] = ptr; +} + +//! Destroy a pool and all spaces. Frees all used memory +/*! + \param p pointer to pool_t structure + */ +void vevo_pool_destroy( void *p ) +{ + pool_t *pool = (pool_t*) p; + space_t **nS = pool->spaces; + int i ; + for( i = 0 ; nS[i] != NULL ; i ++ ) + { + space_t *n = pool->spaces[i]; + space_t *k = NULL; + while( n != NULL ) + { + k = n; + free( k->area ); + free( k->mag ); + n = k->next; + free( k ); + } + } + free( nS ); + free( pool ); +} + +//! Destroy a pool and the space it holds. Frees all used memory +/*! + \param p pointer to pool_t structure + */ +void vevo_pool_slice_destroy( void *p ) +{ + pool_t *pool = (pool_t*) p; + space_t *s = pool->space; + space_t *n = NULL; + while( s != NULL ) + { + n = s; + free( n->area ); + free( n->mag ); + s = n->next; + free( n ); + } + free( pool->space ); + free( pool ); +} + +//! Get a pointer to the starting address of an unused block. Pops a round from the magazine and creates a new space if magazine is empty. +/*! + \param p pointer to pool_t structure + \param bs size of block to allocate + \return pointer to free block + */ +void *vevo_pool_slice_alloc( void *p, size_t bs ) +{ + pool_t *pool = (pool_t*) p; + space_t *space = pool->space; + if( space->rounds == 0 ) + { // no more rounds to fire, create a new magazine and add it to the list + space_t *m = alloc_space( bs ); + m->next = space; + pool->space = m; + space = m; + } + void **mag =(void**) pool->space->mag; + return mag[ --space->rounds ]; +} + +//! Pushes a round to a magazine that is not full +/*! + \param p pointer to pool_t structure + \param ptr pointer to address of block + */ +void vevo_pool_slice_free( void *p, void *ptr ) +{ + pool_t *pool = (pool_t*) p; + unsigned int n = pool->space->rounds; + space_t *space = pool->space; + void **mag = (void**)space->mag; + if( n == ROUNDS_PER_MAG ) + { + space_t *l = space; + while( l != NULL ) + { + if( l->rounds < ROUNDS_PER_MAG ) + { + mag = (void**)l->mag; + mag[ l->rounds ++ ] = ptr; + return; + } + l = l->next; + } + } + mag[ space->rounds++ ] = ptr; +} diff --git a/branches/V-1.5.3/veejay-server/libvevo/pool.h b/branches/V-1.5.3/veejay-server/libvevo/pool.h new file mode 100644 index 00000000..fd252670 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvevo/pool.h @@ -0,0 +1,70 @@ +/*Copyright (c) 2004-2005 N.Elburg + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef POOLM +#define POOLM +#define ROUNDS_PER_MAG 16 + +#define M4b 0 +#define M8b 1 +#define Mpb 2 +#define Mstor 3 +#define Matom 4 +#define Midx 5 +#define Mprop 6 +#define M64b 7 +#define Mend 8 + +void *vevo_pool_alloc( void *pool, size_t bs, unsigned int k ); +void vevo_pool_free( void *pool, void *ptr, unsigned int k ); +void *vevo_pool_init(size_t property_size, size_t stor_size, size_t atom_size, size_t index_size); +void vevo_pool_destroy( void *p ); +void vevo_pool_slice_destroy( void *p ); +void *vevo_pool_slice_init( size_t node_size ); +void *vevo_pool_slice_alloc( void *pool, size_t bs); +void vevo_pool_slice_free( void *pool, void *ptr ); + +#define vevo_pool_alloc_property(type,pool) vevo_pool_alloc(pool,sizeof(type),Mprop ) +#define vevo_pool_alloc_storage(type,pool) vevo_pool_alloc( pool, sizeof(type),Mstor ) +#define vevo_pool_alloc_atom(type,pool) vevo_pool_alloc( pool, sizeof(type), Matom ) +#define vevo_pool_alloc_node(type,pool) vevo_pool_alloc( pool, sizeof(type), Midx ) +#define vevo_pool_alloc_int(type,pool) vevo_pool_alloc( pool,sizeof(type), M4b ) +#define vevo_pool_alloc_ptr(type,pool) vevo_pool_alloc( pool,sizeof(type), Mpb ) +#define vevo_pool_alloc_dbl(type,pool) vevo_pool_alloc( pool,sizeof(type), M8b ) +#define vevo_pool_alloc_64b(type,pool) vevo_pool_alloc( pool,sizeof(type), M64b ) + +#define vevo_pool_free_property(pool,ptr) vevo_pool_free(pool,ptr,Mprop ) +#define vevo_pool_free_storage( pool,ptr ) vevo_pool_free( pool, ptr, Mstor ) +#define vevo_pool_free_atom( pool,ptr ) vevo_pool_free( pool, ptr, Matom ) +#define vevo_pool_free_node( pool,ptr ) vevo_pool_free( pool, ptr, Midx ) +#define vevo_pool_free_int( pool,ptr ) vevo_pool_free( pool,ptr, M4b ) +#define vevo_pool_free_ptr( pool,ptr ) vevo_pool_free( pool,ptr, Mpb ) +#define vevo_pool_free_dbl( pool,ptr ) vevo_pool_free( pool,ptr,M8b ) +#define vevo_pool_free_64b( pool,ptr ) vevo_pool_free( pool,ptr,M64b ) + + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvevo/vevo.c b/branches/V-1.5.3/veejay-server/libvevo/vevo.c new file mode 100644 index 00000000..e952460b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvevo/vevo.c @@ -0,0 +1,2766 @@ +/* +Copyright (c) 2004-2005 N.Elburg + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** \defgroup VeVo Veejay Video Objects + * + * VeVo provides a data model for handling dynamic + * objects in runtime. + * + * Features: + * -# Efficient object caching with reference counting + * -# Generic per object properties with set/get functions + * -# Fast hashing of keys + * + * To distinguish between objects as in object oriented programming, + * Ports are introduced. A Port is a container of properties. + * + * A property is a tupple of a value and an unique key. + * A key is a human friendly name for a Property. Internally a list + * of mnenomics is kept to translate the human friendly name into a numeric value + * that uniquely identifies an object. + * + * Types of values: + * -# int32_t VEVO_ATOM_TYPE_INT + * -# char* VEVO_ATOM_TYPE_STRING + * -# void* VEVO_ATOM_TYPE_VOIDPTR + * -# void* VEVO_ATOM_TYPE_PORTPTR + * -# int32_t VEVO_ATOM_TYPE_BOOLEAN + * -# uint64_t VEVO_ATOM_TYPE_UINT64 + * + * + * + * Values of type STRING must always be NULL-terminated, vevo creates + * a dynamic copy on both set and get functions. + * + * Values of type VOIDPTR must always be freed by caller. + * + * Values of type PORTPTR will be cleaned up by vevo when no longer needed. + * + * Depending on the type of port that is constructed + * -# the port uses a linked list of objects + * -# the port uses a hash table of objects + * -# the port's type is stored as "type" + * -# the port's type is not stored (anonymous port) + * + * A Port has no limit on the amounts of properties it can hold. + * Vevo can recursivly walk all ports and free them, except for + * those Properties that are of the VEVO_ATOM_TYPE_VOIDPTR + * + * Vevo will complain about: + * -# Ports that have never been freed + * -# Ports that have not been allocated by vevo + * -# Ports that have already been freed + * + * This library is not complete, it contains some loose ends: + * - sscanf/ printf + * - vevo_num_properties + * +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif + +#include +#define PORT_TYPE_PLUGIN_INFO 1 +#define PORT_TYPE_FILTER_CLASS 2 +#define PORT_TYPE_FILTER_INSTANCE 3 +#define PORT_TYPE_CHANNEL_TEMPLATE 4 +#define PORT_TYPE_PARAMETER_TEMPLATE 5 +#define PORT_TYPE_CHANNEL 6 +#define PORT_TYPE_PARAMETER 7 +#define PORT_TYPE_GUI 8 + + +//! \typedef atom_t +/*! \brief atom + * + * the atom_t structure + */ +typedef struct { + int type; + void *value; + size_t size; +} atom_t; + +//! \typedef vevo_storage_t +/*! \brief atom storage + * + * + * the vevo_storage_t structure holds one or more elements + * and some bookkeeping information + */ +typedef struct { + int atom_type; /*!< atom type */ + union { /*! \union elements one or more atoms */ + atom_t *atom; + atom_t **array; + } elements; + int num_elements; /*!< number of atoms */ + int flags; /*!< special flags */ + int softlink; /*! < protected, use to indicate soft link */ +} vevo_storage_t; + +//! \typedef vevo_property_t +/*! \brief tupple of key | object storage + * + * + * the vevo_property_t structure binds a key to a vevo_storage_t structure + */ +typedef struct { + vevo_storage_t *st; + uint32_t key; + void *next; +} vevo_property_t; + +//! \typedef port_index_t +/*! \brief mnemonics of key | hash value pairs + * + * + * the port_index_t keeps a mnemonic of key to hash code + */ +typedef struct { + const char *key; + uint32_t hash_code; /* vevo uses a integer representation of key, eliminates strcmp */ + void *next; +} port_index_t; + +//! \typedef __vevo_port_t +/*! \brief top level container + * + * + * the __vevo_port_t is the top level structure + */ +typedef struct { + hash_t *table; /*!< hashtable to store pairs of key | value */ + vevo_property_t *list; /*!< linked list to store pairs of key | value */ + port_index_t *index; /*!< mnemonic table of key to hashcode */ + void *pool; /*!< pointer to pool_t object caching */ +} __vevo_port_t; + + +//! \var port_ref_ Book keeping of allocated and freed ports +/*#ifdef STRICT_CHECKING +static vevo_port_t *port_ref_ = NULL; +#endif*/ +static size_t atom_sizes_[100]; + +//! Check if an object is soft referenced +/*! + \param p port + \param name of object + \return TRUE if an object is soft referenced + */ +static int vevo_property_is_soft_referenced(vevo_port_t * p, const char *key ); + +//! Recursivly free all ports +/*! +\param sorted_port port to collect all atoms of type VEVO_ATOM_TYPE_PORTPTR in port p + \param p input port + */ +static void vevo_port_recurse_free( vevo_port_t *sorted_port, vevo_port_t *p ); +static char *vevo_scan_token_( const char *s ); +static const char *vevo_split_token_q( const char *s, const char delim, char *buf, int buf_len ); + + +static const char *vevo_split_token_( const char *s, const char delim, char *buf, int buf_len ); + + +//! Construct a new vevo_property_t +/*! + \param port port + \param hash_key hash value + \param stor vevo_storage_t + */ +static vevo_property_t *prop_node_new(__vevo_port_t *port, uint32_t hash_key, + vevo_storage_t * stor) +{ + vevo_property_t *p = + (vevo_property_t*) vevo_pool_alloc_property( vevo_property_t, port->pool ); + // (vevo_property_t *) vevo_malloc(sizeof(vevo_property_t)); + p->st = stor; + p->key = hash_key; + p->next = NULL; + return p; +} + +//! Destroy a property +/*! + \param port port + \param p property to free + */ +static void prop_node_free(__vevo_port_t *port,vevo_property_t * p) +{ + if (p) { + //free(p); + vevo_pool_free_property( port->pool, p ); + } + p = NULL; +} +//! Append a property to the linked list of properties +/*! + \param p port + \param key hash value + \param t vevo_storage_t + */ +static vevo_property_t *prop_node_append(vevo_port_t * p, uint32_t key, + vevo_storage_t * t) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + vevo_property_t *node = prop_node_new(port,key, t); + vevo_property_t *next; + vevo_property_t *list = port->list; + if (list == NULL) + port->list = node; + else { + while (list != NULL) { + next = list->next; + if (next == NULL) { + list->next = node; + return node; + } + list = next; + } + } + return node; +} + +//! Get a property from a port +/*! + \param port + \param key hash value + */ +static vevo_property_t *prop_node_get(vevo_port_t * p, uint32_t key) +{ + __vevo_port_t *port = (__vevo_port_t *) p; +#ifdef STRICT_CHECKING + assert( port != NULL ); +#endif + vevo_property_t *l = port->list; + while (l != NULL) { + if (key == l->key) + return l; + l = l->next; + } + return NULL; +} + +//! Construct a new mnemonic +/*! + \param port port + \param key name of property + \param hash_key calculated hash value + \return port_index_t new mmemonic + */ +static port_index_t *port_node_new(__vevo_port_t *port,const char *key, uint32_t hash_key) +{ + // port_index_t *i = (port_index_t *) vevo_malloc(sizeof(port_index_t)); + port_index_t *i = (port_index_t *) vevo_pool_alloc_node( + port_index_t, port->pool ); +#ifdef STRICT_CHECKING + assert(i != NULL); + assert(key != NULL); + assert(hash_key != 0); +#endif + i->key = strdup(key); + i->hash_code = hash_key; + i->next = NULL; + return i; +} + +//! Destroy a mnemonic from the list of key | hash value pairs +/*! + \param port port + \param node mnemonic to destroy + */ +static void port_node_free(__vevo_port_t *port,port_index_t * node) +{ + if (node) { + if (node->key) + free((void *) node->key); +// free(node); + vevo_pool_free_node( port->pool,(void*)node ); + } + node = NULL; +} + +//! Add a mnemonic to the list of key | hash value pairs +/*! + \param p port + \param key name of property + \param hash_key calculated hash value + */ +static void port_node_append(vevo_port_t * p, const char *key, + uint32_t hash_key) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + assert(key != NULL); + assert(hash_key != 0); +#endif + __vevo_port_t *port = (__vevo_port_t *) p; + port_index_t *node = port_node_new(p,key, hash_key); + port_index_t *next; + port_index_t *list = port->index; + if (list == NULL) + port->index = node; + else { + while (list != NULL) { + next = list->next; + if (next == NULL) { + list->next = node; + break; + } + list = next; + } + } +} + +#define PROPERTY_KEY_SIZE 128 + +//! \define property_exists Check if a property exists +#define property_exists( port, key ) hash_lookup( (hash_t*) port->table, (const void*) key ) + +//! \define atom_store__ store atom +#define atom_store__(value) {\ +for (i = 0; i < d->num_elements; i++)\ + d->elements.array[i] = vevo_put_atom(port, &value[i], v ); } + +//! \define array_load__ get a value from an array of atom +#define array_load__(value) {\ +for( i = 0; i < t->num_elements ; i ++ )\ + memcpy( &value[i], t->elements.array[i]->value, t->elements.array[i]->size ); } + +//! Construct a new vevo_storage_t object +/*! + \param port port + \return vevo_storage_t a new vevo_storage_t object +*/ +static vevo_storage_t *vevo_new_storage(__vevo_port_t *port ); +/* +static int vevo_port_ref_verify( vevo_port_t *p) ; +*/ +//! Copy a value into a new atom +/*! + \param port port + \param src address of value to store + \param n number of elements to store + \param d vevo_storage_t destination + \param v atom type + */ +static void +storage_put_atom_value(__vevo_port_t * port, void *src, int n, + vevo_storage_t * d, int v); + +//! Calculate a hash value from a given string +/*! + \param str string + \return calculated hash value + */ +static inline uint32_t hash_key_code( const char *str ) +{ + uint32_t hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +//! Flag a property as soft referenced. Use to avoid freeing a linked pointer. +/*! + \param p port + \param key property to soft reference + \return error code + */ +int vevo_property_soft_reference(vevo_port_t * p, const char *key) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); + if (!port->table) { + vevo_property_t *node = NULL; + if ((node = prop_node_get(port, hash_key)) != NULL) { + node->st->softlink = 1; + return VEVO_NO_ERROR; + } + } else { + hnode_t *node = NULL; + if ((node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node); + stor->softlink = 1; + hnode_put( node, (void*) hash_key ); + return VEVO_NO_ERROR; + } + + } + + return VEVO_NO_ERROR; +} + + +//! Flag a property as read-only. Use to avoid overriding the value +/*! + \param p port + \param key property to set as readonly + \return error code + */ +static int vevo_property_finalize(vevo_port_t * p, const char *key) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); + if (!port->table) { + vevo_property_t *node = NULL; + if ((node = prop_node_get(port, hash_key)) != NULL) { + node->st->flags |= VEVO_PROPERTY_READONLY; + return VEVO_NO_ERROR; + } + } else { + hnode_t *node = NULL; + if ((node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node); + stor->flags |= VEVO_PROPERTY_READONLY; + hnode_t *new_node = hnode_create((void *) stor); + hnode_put(new_node, (void *) hash_key); + hnode_destroy(new_node); + return VEVO_NO_ERROR; + } + } + return VEVO_NO_ERROR; +} + +static int vevo_property_exists( vevo_port_t *p, const char *key) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + + uint32_t hash_key = hash_key_code(key); + if (!port->table) { + vevo_property_t *node = NULL; + if ((node = prop_node_get(port, hash_key)) != NULL) + return 1; + } else { + hnode_t *node = NULL; + if ((node = property_exists(port, hash_key)) != NULL) + return 1; + } + return 0; +} + +//! Local add, add a property to the list of properties and finalize if needed +/*! + \param p port + \param finalize set property readonly TRUE or FALSE + \param key property name + \param atom_type atom type + \param num_elements number of atoms + \param src address of source variable + */ +static void vevo_port_add_property( vevo_port_t *p,int finalize, const char *key,int atom_type, int num_elements, void * src ) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + + uint32_t hash_key = hash_key_code(key); + vevo_storage_t *stor = vevo_new_storage(p); + storage_put_atom_value(port, src, num_elements, stor, atom_type); + if(finalize) + stor->flags |= VEVO_PROPERTY_READONLY; + port_node_append(port, key, hash_key); + if (!port->table) + prop_node_append(port, hash_key, stor); + else + hash_insert( (hash_t*) port->table, + hnode_create(stor),(const void*) hash_key ); +} + +//! Finalize a port. Add it to the reference list and register port type +/*! + \param port port to finalize + \param port_type port type + */ +static void vevo_port_finalize( vevo_port_t *port, int port_type ) +{ +/* +#ifdef STRICT_CHECKING + if( port_type != VEVO_PORT_REFERENCES ) + { + int ref = 1; + char ref_key[64]; + sprintf(ref_key,"%p",port ); + vevo_property_set( port_ref_, ref_key, VEVO_ATOM_TYPE_INT, 1, &ref ); + } +#endif +*/ + if( port_type <= 1024 && port_type > 0 ) + vevo_port_add_property( port, 1,"type",VEVO_ATOM_TYPE_INT,1, &port_type ); +} + +//! Copy a value from an atom to an address +/*! + \param t vevo_storage_t source + \param idx element at + \param dst destination address + \return error code + */ + + +static int atom_get_value(vevo_storage_t * t, int idx, void *dst) +{ +#ifdef STRICT_CHECKING + assert(t != NULL); +#endif + atom_t *atom = NULL; + + if (t->num_elements == 1 && idx == 0) + { + atom = t->elements.atom; +#ifdef STRICT_CHECKING + assert( atom != NULL ); +#endif + } + + if (t->num_elements > 1 && idx >= 0 && idx <= t->num_elements) + { + atom = t->elements.array[idx]; +#ifdef STRICT_CHECKING + assert( atom != NULL ); +#endif + } + + if( t->num_elements == 0 && idx == 0 ) + { + atom = t->elements.atom; +#ifdef STRICT_CHECKING + assert( atom != NULL ); +#endif + return VEVO_ERROR_PROPERTY_EMPTY; + } + + + if (!atom) + return VEVO_ERROR_NOSUCH_ELEMENT; + + if (atom->size <= 0) + return VEVO_NO_ERROR; + + if( dst == NULL ) + return VEVO_NO_ERROR; + + if (t->atom_type != VEVO_ATOM_TYPE_STRING) { +#ifdef STRICT_CHECKING + assert( atom->size > 0 ); +#endif + memcpy(dst, atom->value, atom->size); + } else { + char **ptr = (char **) dst; + char *p = *ptr; +#ifdef STRICT_CHECKING + assert( (atom->size-1) > 0 ); +#endif + memcpy(p, atom->value, (atom->size - 1)); + p[atom->size - 1] = '\0'; + } + return VEVO_NO_ERROR; +} + +//! Get the byte size of an atom +/*! + \param atom_type atom type + \return byte size + */ +static size_t vevo_atom_size(int atom_type) +{ + return atom_sizes_[atom_type]; + return 0; +} + +//! Construct a new Atom +/*! + \param port port + \param atom_type type of atom to construct + \param atom_size byte size of atom + \return atom_t new atom + */ +static atom_t *vevo_new_atom(__vevo_port_t * port, int atom_type, + size_t atom_size) +{ + atom_t *atom = (atom_t *) vevo_pool_alloc_atom( atom_t , port->pool ); +#ifdef STRICT_CHECKING + assert(atom != NULL); +#endif + atom->size = atom_size; + atom->type = atom_type; + if(atom_type == VEVO_ATOM_TYPE_STRING ) + atom->value = (atom_size > 0 ?(void*)malloc(atom_size):NULL); + else + { if(atom_type == VEVO_ATOM_TYPE_DOUBLE ) { + atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_dbl(double,port->pool ): NULL); + } else if( atom_type == VEVO_ATOM_TYPE_VOIDPTR || atom_type == VEVO_ATOM_TYPE_PORTPTR ) { + atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_ptr(void*,port->pool ): NULL ); + } else if( atom_type == VEVO_ATOM_TYPE_UINT64 ) { + atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_64b(uint64_t,port->pool) : NULL ); + } else { + atom->value = (atom_size > 0 ? (void*) vevo_pool_alloc_int(int32_t, port->pool ): NULL ); + } + } +#ifdef STRICT_CHECING + assert(atom != NULL); +#endif + return atom; +} + +//! Destroy an atom +/*! + \param port port + \param atom atom_t to destroy + */ +static void vevo_free_atom(__vevo_port_t *port,atom_t * atom) +{ +#ifdef STRICT_CHECKING + assert(atom != NULL); +#endif + if (atom) { + if(atom->value) + switch( atom->type ) + { + case VEVO_ATOM_TYPE_VOIDPTR: + case VEVO_ATOM_TYPE_PORTPTR: + vevo_pool_free_ptr( port->pool, atom->value ); + break; + case VEVO_ATOM_TYPE_INT: + case VEVO_ATOM_TYPE_BOOL: + vevo_pool_free_int( port->pool, atom->value ); + break; + case VEVO_ATOM_TYPE_DOUBLE: + vevo_pool_free_dbl( port->pool,atom->value ); + break; + case VEVO_ATOM_TYPE_UINT64: + vevo_pool_free_64b( port->pool,atom->value ); + break; + case VEVO_ATOM_TYPE_STRING: + free( atom->value ); + break; + } + vevo_pool_free_atom( port->pool, atom ); + } + atom = NULL; +} + +//! Copy a value from address into a new Atom +/*! + \param port port + \param dst destination address + \param atom_type type of atom + */ +static atom_t *vevo_put_atom(__vevo_port_t * port, void *dst, + int atom_type) +{ + atom_t *atom = NULL; + size_t atom_size = vevo_atom_size(atom_type); + + if (atom_type == VEVO_ATOM_TYPE_STRING) { + char **s = (char **) dst; + atom_size = strlen(*s) + 1; + atom = vevo_new_atom(port, atom_type, atom_size); + if (atom_size > 0) + memcpy(atom->value, *s, (atom_size - 1)); + } else { + +#ifdef STRICT_CHECKING + assert(atom_size > 0); + assert(dst != NULL); +#endif + atom = vevo_new_atom(port, atom_type, atom_size); +#ifdef STRICT_CHECING + assert(atom != NULL); + assert(atom->value != NULL); +#else + if (!atom) + return NULL; +#endif + memcpy(atom->value, dst, atom_size); + } + return atom; +} + + +//! Copy N values from address into a new Atom +/*! + \param port port + \param src source address + \param n number of elements + \param d vevo_storage_t + \param v type of atom + */ + +static void +storage_put_atom_value(__vevo_port_t * port, void *src, int n, + vevo_storage_t * d, int v) +{ + int i; +#ifdef STRICT_CHECKING + if (n > 0) + assert((src != NULL)); +#endif + if (d->num_elements >= 0) { + if (d->num_elements >= 0 && d->num_elements <= 1) { +#ifdef STRICT_CHECKING + if( d->num_elements == 1 ) + assert( d->elements.atom != NULL ); + if( d->num_elements == 0 ) + assert( d->elements.atom == NULL ); +#endif + if (d->elements.atom) + vevo_free_atom(port,d->elements.atom); + } else if (d->num_elements > 1) { + if (d->elements.array) { + for (i = 0; i < d->num_elements; i++) + vevo_free_atom(port,d->elements.array[i]); + free(d->elements.array); + } + } + } + + d->atom_type = v; + d->num_elements = n; + + switch (n) { + case 0: + d->elements.atom = vevo_new_atom(port, v, vevo_atom_size(v)); + break; + case 1: + d->elements.atom = vevo_put_atom(port, src, v); + break; + default: + d->elements.array = (atom_t **) malloc(sizeof(atom_t *) * n); + if (d->atom_type == VEVO_ATOM_TYPE_DOUBLE) { + double *value = (double *) src; + atom_store__(value); + } else { + if (d->atom_type == VEVO_ATOM_TYPE_INT + || d->atom_type == VEVO_ATOM_TYPE_BOOL) { + int32_t *value = (int *) src; + atom_store__(value); + } else if(d->atom_type == VEVO_ATOM_TYPE_UINT64) { + uint64_t *value = (uint64_t*) src; + atom_store__(value); + } else { + void **value = (void **) src; + atom_store__(value); + } + } + break; + } +} + +//! Construct a new vevo_storage_t object +/*! + \param port Port + \return vevo_storage_t + */ +static vevo_storage_t *vevo_new_storage( __vevo_port_t *port) +//static inline vevo_storage_t *vevo_new_storage(int num_elements) +{ + vevo_storage_t *d = + (vevo_storage_t*) vevo_pool_alloc_storage( vevo_storage_t, port->pool ); +// (vevo_storage_t *) vevo_malloc(sizeof(vevo_storage_t)); +#ifdef HAVE_STRICT + assert(d != NULL); +#endif + memset( d, 0, sizeof(vevo_storage_t)); + return d; +} + +//! Destroy a vevo_storage_t object +/*! + \param port port + \param t vevo_storage_t to destroy + */ +static void vevo_free_storage(__vevo_port_t *port,vevo_storage_t * t) +{ + if (t) { + if (t->num_elements > 1) { + int i; + for (i = 0; i < t->num_elements; i++) + { +#ifdef STRICT_CHECKING + assert( t->elements.array[i] != NULL ); +#endif + vevo_free_atom(port,t->elements.array[i]); + } + free(t->elements.array); + } + if (t->num_elements <= 1) + { +#ifdef STRICT_CHECKING + assert( t->elements.atom != NULL ); +#endif + vevo_free_atom(port,t->elements.atom); + + } +// free(t); + vevo_pool_free_storage( port->pool, t ); + } + t = NULL; +} + +//! Cast a key into a hashing value +/*! + \param key hash key code + \return hash value + */ +static hash_val_t int_hash(const void *key) +{ + return (hash_val_t) key; +} + +//! Compare two keys +/*! + \param key1 key1 + \param key2 key2 + \return error code if keys are unequal + */ +static int key_compare(const void *key1, const void *key2) +{ + return ((const uint32_t) key1 == (const uint32_t) key2 ? 0 : 1); +} + +//! Get the number of elements in an Atom +/*! + \param p port + \param key property name + \return Number of elements + */ +int vevo_property_num_elements(vevo_port_t * p, const char *key) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + assert(key != NULL); +#endif + if(!p) return -1; + + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); + + if (!port->table) { + vevo_property_t *node; + if ((node = prop_node_get(port, hash_key)) != NULL) + return node->st->num_elements; + } else { + hnode_t *node = NULL; + if ((node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node); + if (stor) + return stor->num_elements; + } + } + return -1; +} + +//! Get the atom type of a Property +/*! + \param p Port + \param key Property name + \return Atom type + */ +int vevo_property_atom_type(vevo_port_t * p, const char *key) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + assert(key != NULL); +#endif + __vevo_port_t *port = (__vevo_port_t *) p; +#ifdef STRICT_CHECKING + assert(port != NULL); +#endif + uint32_t hash_key = hash_key_code(key); + + if (!port->table) { + vevo_property_t *node; + if ((node = prop_node_get(port, hash_key)) != NULL) + return node->st->atom_type; + } else { + hnode_t *node = NULL; +#ifdef STRICT_CHECKING + assert(port->table != NULL); +// assert(hash_verify(port->table) != 0); +#endif + + if ((node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node); + if (stor) + return stor->atom_type; + } + } + return -1; +} + +//! Return size of an Atom at a given index +/*! + \param p Port + \param key Property name + \param idx Index + \return Byte size of value at Index + */ +size_t +vevo_property_element_size(vevo_port_t * p, const char *key, + const int idx) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + assert(key != NULL); + assert(idx >= 0); +#endif + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); +#ifdef STRICT_CHECKING + assert( port ); +#endif + if (!port->table) { + vevo_property_t *node; + if ((node = prop_node_get(port, hash_key)) != NULL) { +#ifdef STRICT_CHECKING + if (idx > 0) + assert(idx < node->st->num_elements); +#endif + if (node->st->num_elements == 1) + return node->st->elements.atom->size; + else if (node->st->num_elements > 1) + return node->st->elements.array[idx]->size; + return 0; + } + } else { + hnode_t *node = NULL; + if ((node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *stor = (vevo_storage_t *) hnode_get(node); +#ifdef STRICT_CHECKING + assert(idx <= stor->num_elements); +#endif + //todo: sum all element sizes for index of -1 + if (stor->num_elements == 1) { + return stor->elements.atom->size; + } else if (stor->num_elements > 1) { + return stor->elements.array[idx]->size; + } else { + if (stor->num_elements == 0) + return 0; + } + } + } + + return -1; +} + +//! Construct a new Port +/*! + \param port_type Type of Port to Create. Port types <= 1024 are typed, > 1024 are anonymous ports. + \return A New Port + */ +#ifndef STRICT_CHECKING +vevo_port_t *vevo_port_new(int port_type) +{ + __vevo_port_t *port = (__vevo_port_t *) malloc(sizeof(__vevo_port_t)); + + port->index = NULL; + port->list = NULL; + port->table = NULL; + port->pool = vevo_pool_init( sizeof(vevo_property_t),sizeof( vevo_storage_t ), sizeof( atom_t ) , sizeof( port_index_t ) ); +/* If the port type is a Livido port this or that */ + if ( (port_type >= 1 && port_type <= 50) || port_type < 0) + port->list = NULL; + else + port->table = hash_create(HASHCOUNT_T_MAX, key_compare, int_hash); + + vevo_port_finalize (port, port_type ); + return (vevo_port_t *) port; +} +#else +vevo_port_t *vevo_port_new(int port_type, const char *func, int line_num) +{ + __vevo_port_t *port = (__vevo_port_t *) malloc(sizeof(__vevo_port_t)); + +#ifdef STRICT_CHECKING + assert(port != NULL); +#endif + port->index = NULL; + port->list = NULL; + port->table = NULL; + port->pool = vevo_pool_init( sizeof(vevo_property_t),sizeof( vevo_storage_t ), sizeof( atom_t ) , sizeof( port_index_t ) ); +/* If the port type is a Livido port this or that */ + if ( (port_type >= 1 && port_type <= 50) || port_type < 0) + port->list = NULL; + else + port->table = hash_create(HASHCOUNT_T_MAX, key_compare, int_hash); + + vevo_port_finalize (port, port_type ); + +/* char har[1024]; + sprintf(har,"%s::%d", func,line_num ); + vevo_property_set( port, har, VEVO_ATOM_TYPE_HIDDEN,0,NULL); + */ + return (vevo_port_t *) port; +} + +#endif + +//! Initialize VeVo. Set up bookkeeping information to track Port construction and destruction +void vevo_strict_init() +{ +/* +#ifdef STRICT_CHECKING + port_ref_ = vevo_port_new( VEVO_PORT_REFERENCES, __FUNCTION__,__LINE__ ); +#endif +*/ + memset( atom_sizes_,0,sizeof(atom_sizes_) ); + atom_sizes_[1] = sizeof(int32_t); + atom_sizes_[2] = sizeof(double); + atom_sizes_[3] = sizeof(int32_t); + atom_sizes_[4] = sizeof(char*); + atom_sizes_[5] = sizeof(uint64_t); + atom_sizes_[65] = sizeof(void*); + atom_sizes_[66] = sizeof(vevo_port_t*); +} + +//! Destroy a Port +/*! + \param p (local) Port to destroy + */ +static void vevo_port_free_(vevo_port_t * p) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + + if (port->table) { + if (!hash_isempty((hash_t *) port->table)) { + hscan_t scan; + hash_scan_begin(&scan, (hash_t *) port->table); + hnode_t *node; + + while ((node = hash_scan_next(&scan)) != NULL) { + vevo_storage_t *stor = NULL; + stor = hnode_get(node); +#ifdef STRICT_CHECKING + assert(stor != NULL); + assert(node != NULL); + assert((const char *) hnode_getkey(node) != NULL); +#endif + vevo_free_storage(port,stor); + } + hash_free_nodes((hash_t *) port->table); + hash_destroy((hash_t *) port->table); + } + } + else + { + vevo_property_t *l = port->list; + vevo_property_t *n; + while (l != NULL) { + n = l->next; + vevo_free_storage(port,l->st); + prop_node_free(port,l); + l = n; + } + } + + port_index_t *l = port->index; + port_index_t *n = NULL; + while (l != NULL) { + n = l->next; + port_node_free(port,l); + l = n; + } + + vevo_pool_destroy( port->pool ); + + free(port); + p = port = NULL; +} + +//! Verify if Vevo has allocated a given Port +/*! + \param port Port to verify + \return error code + */ +int vevo_port_verify( vevo_port_t *port ) +{/* +#ifdef STRICT_CHECKING + if( port == port_ref_ ) + return 1; + char pkey[32]; + sprintf(pkey, "%p",port); + + int ref_count = 0; + int error = vevo_property_get( port_ref_, pkey, 0, &ref_count ); + + if( error != 0 ) + { + //veejay_msg(0, "%s: Port '%s' not allocated by vevo_port_new()", __FUNCTION__, pkey ); + return 0; + } + + if( error == VEVO_ERROR_NOSUCH_ELEMENT || error == + VEVO_ERROR_NOSUCH_PROPERTY ) + { + //veejay_msg(0, "%s: Port '%s' does not exist" ); + return 0; + } + + if( ref_count == 0 ) + { + //veejay_msg(0, "%s: Port %s has a reference count of 0 ",__FUNCTION__, pkey); + return 0; + } +#endif +*/ + return 1; +} + +//! Destroy a Port +/*! + \param p Port to destroy + */ + +void vevo_port_free( vevo_port_t *port ) +{ + if(!port) + { + veejay_msg(0, "Port invalid in free()"); +#ifdef STRICT_CHECKING + assert(0); +#endif + return; + } +/* +#ifdef STRICT_CHECKING + char pkey[32]; + sprintf(pkey, "%p",port); + if( port == port_ref_ ) + { + dec_ref = 0; + vevo_port_free_( port ); + } + if( dec_ref) + { + error = vevo_property_get( port_ref_, pkey, 0, &ref_count ); + if( error != VEVO_NO_ERROR ) + { + // veejay_msg(0, "%s: Port '%s' not allocated by vevo_port_new()", __FUNCTION__, pkey ); + assert(0); + } + if( ref_count == 0 ) + { + // veejay_msg(0, "%s: Port '%s' has a reference count of 0 (already freed)", __FUNCTION__, pkey ); + assert(0); + } + if( ref_count > 1 ) + { + // veejay_msg(0, "%s: Port '%s' has a reference count of %d", __FUNCTION__,pkey,ref_count); + return; + } + ref_count --; + assert( ref_count == 0 ); + vevo_property_set( port_ref_, pkey, VEVO_ATOM_TYPE_INT,1,&ref_count ); + vevo_port_free_( port ); + } +#else +*/ + vevo_port_free_(port ); +/* +#endif +*/ +} + +//! Check if a Property is soft referenced +/*! + \param p Port + \param key Property name + \return error code + */ +static int +vevo_property_is_soft_referenced(vevo_port_t * p, + const char *key ) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + assert( key != NULL ); +#endif + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); +#ifdef STRICT_CHECKING + assert( port != NULL ); +#endif + if (!port->table) { + vevo_property_t *pnode = NULL; + if ((pnode = prop_node_get(port, hash_key)) != NULL) { + return pnode->st->softlink; + } + } else { + hnode_t *old_node = NULL; + if ((old_node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *oldstor = + (vevo_storage_t *) hnode_get(old_node); + return oldstor->softlink; + } + } + return 0; +} + +//! Store a value as a new Property or overwrite existing value +/*! + \param p Port + \param key Property name + \param atom_type Atom type + \param num_elements Number of elements + \param src Source address + \return error code + */ +int +vevo_property_set(vevo_port_t * p, + const char *key, + int atom_type, int num_elements, void *src) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + //@ no self referencing + assert( src != p ); + if( num_elements > 0 ) assert( src != NULL ); + assert( key != NULL ); + if( atom_type != VEVO_ATOM_TYPE_HIDDEN ) + assert( vevo_atom_size(atom_type) > 0 ); +#endif + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); + int new = 1; + void *node = NULL; +#ifdef STRICT_CHECKING + assert( port != NULL ); +#endif + if (!port->table) { + vevo_property_t *pnode = NULL; + if ((pnode = prop_node_get(port, hash_key)) != NULL) { +#ifdef STRICT_CHECKING + if (pnode->st->atom_type != atom_type) + return VEVO_ERROR_WRONG_ATOM_TYPE; + if (pnode->st->flags & VEVO_PROPERTY_READONLY) + { + return VEVO_ERROR_PROPERTY_READONLY; + } +#endif + vevo_free_storage(port,pnode->st); + //prop_node_free(pnode); + new = 0; + node = (void *) pnode; + } + } else { + hnode_t *old_node = NULL; + if ((old_node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *oldstor = + (vevo_storage_t *) hnode_get(old_node); +#ifdef STRICT_CHECKING + if (oldstor->atom_type != atom_type) + return VEVO_ERROR_WRONG_ATOM_TYPE; + + if (oldstor->flags & VEVO_PROPERTY_READONLY) + return VEVO_ERROR_PROPERTY_READONLY; +#endif + vevo_free_storage(port,oldstor); + + hash_delete((hash_t *) port->table, old_node); + hnode_destroy(old_node); + new = 0; + } + } + vevo_storage_t *stor = vevo_new_storage(port); + + storage_put_atom_value(port, src, num_elements, stor, atom_type); + + if (new) { + port_node_append(port, key, hash_key); + if (!port->table) + node = (void *) prop_node_append(port, hash_key, stor); + } +#ifdef STRICT_CHECKING + assert(stor != NULL); +#endif + + if (!port->table) { +#ifdef STRICT_CHECKING + assert(node != NULL); +#endif + if (!new) { + vevo_property_t *current = (vevo_property_t *) node; + current->st = stor; + } + } else { + hnode_t *node2 = hnode_create(stor); + +#ifdef STRICT_CHECKING + assert(node2 != NULL); + assert(!hash_isfull((hash_t *) port->table)); + assert(!property_exists(port, hash_key)); +#endif + + hash_insert((hash_t *) port->table, node2, + (const void *) hash_key); + } + + return VEVO_NO_ERROR; +} + +//! Get a value from a Property +/*! + \param p Port + \param key Property name + \param idx Index + \param dst Destination address + \return error code + */ +int +vevo_property_get(vevo_port_t * p, const char *key, int idx, void *dst) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + assert( key != NULL ); + assert( idx >= 0 ); +#endif + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); + + if (!port->table) { + vevo_property_t *node = NULL; + if ((node = prop_node_get(port, hash_key)) != NULL) { + // if (dst == NULL) + // return VEVO_NO_ERROR; + // else + return atom_get_value(node->st, idx, dst); + } + } else { + hnode_t *node = NULL; + if ((node = property_exists(port, hash_key)) != NULL) { + // if (dst == NULL) + // return VEVO_NO_ERROR; + // else + return atom_get_value((vevo_storage_t *) hnode_get(node), + idx, dst); + } + } + + return VEVO_ERROR_NOSUCH_PROPERTY; +} + +//! List all properties in a Port +/*! + \param p Port + \return Null terminated list of property names + */ +char **vevo_list_properties(vevo_port_t * p) +{ + if(!p) return NULL; + + __vevo_port_t *port = (__vevo_port_t *) p; + if(!port->index) + return NULL; +#ifdef STRICT_CHECKING + assert(port != NULL); +#endif + char **list = NULL; + +#ifdef STRICT_CHECKING + int nn = 1; + if (port->table) + nn += hash_count((hash_t *) port->table); + else { + vevo_property_t *c = port->list; + while (c != NULL) { + c = c->next; + nn++; + } + } +#endif + + int n = 1; // null terminated list of keys + int i = 0; +#ifdef STRICT_CHECKING + assert( port->index != NULL ); +#endif + port_index_t *l = port->index; + while (l != NULL) { + l = l->next; + n++; + } + +#ifdef STRICT_CHECKING + if( n != nn ) + veejay_msg(0, "%s:%s (%p) Expected %d properties but there are %d", + __FILE__,__FUNCTION__,p,nn, n ); + assert(nn == n); +#endif + + list = (char **) malloc(sizeof(char *) * n); + if (!list) + return NULL; + + l = (port_index_t *) port->index; + i = 0; + while (l != NULL) { +#ifdef STRICT_CHECKING + if( vevo_property_atom_type( p, l->key ) != VEVO_ATOM_TYPE_HIDDEN ) + { +#endif + list[i] = (char *) strdup(l->key); +#ifdef STRICT_CHECING + assert(list[i] != NULL); +#endif + i++; +#ifdef STRICT_CHECKING + } +#endif + + l = l->next; + //i++; + } + list[i] = NULL; + + return list; +} + +int vevo_num_properties(vevo_port_t * p) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + if(!port->index) + return 0; + + int n = 0; + port_index_t *l = port->index; + while (l != NULL) { + l = l->next; + n++; + } + + return n; +} + + +//! Check if this Port holds an Atom of some type +/*! + \param p Port + \param atype Atom type + \return error code +*/ +static int vevo_scan_for_atom( vevo_port_t *p, int atype ) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + if(!p) return 0; + + if( port->table) + { + hnode_t *node; + hscan_t scan; + vevo_storage_t *s; +#ifdef STRICT_CHECKING + assert( port->table != NULL ); +#endif + hash_scan_begin( &scan,(hash_t*) port->table ); + + while((node=hash_scan_next(&scan)) != NULL) + { + s = hnode_get(node); + if( s->atom_type == atype ) + return 1; + } + } + else + { + vevo_property_t *l = port->list; + vevo_property_t *n; + vevo_storage_t *s; + while( l != NULL ) + { + n = l->next; + s = l->st; + + if( s->atom_type == atype ) + return 1; + + l = n; + } + } + return 0; +} + +//! List all Properties in a Port that match Atom type +/*! + \param p Port + \param atype Atom type + \return List of vevo_storage_t + */ +static vevo_storage_t **vevo_list_nodes_(vevo_port_t * p, int atype) +{ + __vevo_port_t *port = (__vevo_port_t *) p; + if(!p) return NULL; + + int n = 256; // null terminated list of keys + int i = 0; + + vevo_storage_t **list = (vevo_storage_t**)malloc(sizeof(vevo_storage_t*) * n ); + memset(list,0,sizeof(vevo_storage_t*) * n ); + + if( port->table) + { + hnode_t *node; + hscan_t scan; + vevo_storage_t *s; + hash_scan_begin( &scan,(hash_t*) port->table ); + while((node=hash_scan_next(&scan)) != NULL) + { + s = hnode_get(node); + if( (s && s->atom_type == atype) || atype == 0) + { + int type = 0; + int ec = atom_get_value(s, 0, &type); + if( ec == VEVO_NO_ERROR && !s->softlink ) + list[i++] = s; + } + } + } + else + { + vevo_property_t *l = port->list; + vevo_property_t *n; + vevo_storage_t *s; + while( l != NULL ) + { + n = l->next; + s = l->st; + + if( s->atom_type == atype || atype == 0 ) + { + int type = 0; + int ec = atom_get_value(l->st, 0, &type); + /* if( (type != PORT_TYPE_FILTER_CLASS || + type != PORT_TYPE_CHANNEL_TEMPLATE || + type != PORT_TYPE_PARAMETER_TEMPLATE || + type != PORT_TYPE_PLUGIN_INFO ) && + ec != VEVO_ERROR_PROPERTY_EMPTY && + !(s->flags & VEVO_PROPERTY_SOFTREF)) + */ + if( ec == VEVO_NO_ERROR && !s->softlink ) + list[i++] = s; + } + l = n; + } + } +#ifdef STRICT_CHECKING + assert( i < 256 ); +#endif + return list; +} + +//! Report statistics and free bookkeeping information +void vevo_report_stats() +{ +/* +#ifdef STRICT_CHECKING + if( port_ref_ ) + { + int errs = vevo_port_ref_verify( port_ref_ ); + if(errs > 0) + veejay_msg(0,"%d VEVO ports are still referenced",errs); + vevo_port_free( port_ref_ ); + } +#endif*/ +} + +static int vevo_port_get_port( void *port, vevo_storage_t *item, void *res ) +{ + if (item->flags & VEVO_PROPERTY_SOFTREF) + return -1; + if(item->num_elements == 1 ) + atom_get_value( item, 0, res ); + return item->num_elements; +} + +//! Add a Port to the reference port or create a new reference port +/*! + \param in Input port + \param ref Reference Port + \return New port or Input port + */ +void *vevo_port_register( vevo_port_t *in, vevo_port_t *ref ) +{ + void *port = in; + const void *store = ref; +#ifndef STRICT_CHECKING + if(!port) + port = vevo_port_new( VEVO_PORT_POOL ); +#else + if(!port) + port = vevo_port_new( VEVO_PORT_POOL, __FUNCTION__, __LINE__ ); +#endif + char pkey[32]; + +#ifdef STRICT_CHECKING + assert( vevo_port_verify( port ) == 1 ); +#endif + + if(store) + { + sprintf(pkey,"%p", ref); + vevo_property_set( port, pkey,VEVO_ATOM_TYPE_PORTPTR, 1 , &ref ); + } + return port; +} + +//! Merge 2 Ports, A + B = AB. Only for properties that have atom VOIDPTR +/**! all in port_a is added to port_b + \param port Port A + \param port Port B + \return Error code + */ +int vevo_union_ports( void *port_a, void *port_b, int filter_type ) +{ + __vevo_port_t *A = (__vevo_port_t *) port_a; + __vevo_port_t *B = (__vevo_port_t *) port_b; + + if(!A || !B ) + return 1; + + char **Ea = vevo_list_properties( port_a ); + int i; + int error; + for( i = 0; Ea[i] != NULL; i ++ ) + { + if(!vevo_property_exists( port_b, Ea[i] )&& vevo_property_atom_type( port_a, Ea[i] ) == + filter_type ) + { +#ifdef STRICT_CHECKING + int n = vevo_property_num_elements( port_b, Ea[i] ); + // clone elements! + assert( n <= 1 ); +#endif + void *v = NULL; + error = vevo_property_get( port_a, Ea[i], 0, &v ); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + error = vevo_property_set( port_b, Ea[i], + VEVO_ATOM_TYPE_VOIDPTR,1, &v ); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + } + free( Ea[i] ); + } + free( Ea ); + + return 0; +} + +//! Adds all elements in port_b of type VOIDPTR to port_a. Key value tupple is reversed. +/*! + * \param port Port A + \param port Port B + \return Error code + */ + +int vevo_special_union_ports( void *port_a, void *port_b ) +{ + __vevo_port_t *A = (__vevo_port_t *) port_a; + __vevo_port_t *B = (__vevo_port_t *) port_b; + + if(!A || !B ) + return 0; + + // port_a contains only slots + + char **Ea = vevo_list_properties( port_a ); + int i; + int error; + if(!Ea) + return 0; + + for( i = 0; Ea[i] != NULL; i ++ ) + { + void *value = NULL; + char key[64]; + + int atom_type = vevo_property_atom_type( port_a, Ea[i] ); + if( atom_type == VEVO_ATOM_TYPE_VOIDPTR ) + { + error = vevo_property_get( port_a, Ea[i], 0, &value ); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + sprintf(key, "%p", value ); + + if(!vevo_property_exists( port_b, key )) + { + error = vevo_property_set( port_b, key, VEVO_ATOM_TYPE_VOIDPTR,1,&value ); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + } + } + free( Ea[i] ); + } + free( Ea ); + return 0; +} +//! Recursivly destroy a Port and all sub ports +/**! + \param port Port to destroy + */ +void vevo_port_recursive_free( vevo_port_t *port ) +{ + if(!port) + return; + void *sor = vevo_port_register( NULL,NULL ); +#ifdef STRICT_CHECKING + assert( sor != NULL ); +#endif + vevo_port_recurse_free( sor, port ); +#ifdef STRICT_CHECKING + assert( sor != NULL ); +#endif + int i; + vevo_storage_t **item = vevo_list_nodes_( sor, VEVO_ATOM_TYPE_PORTPTR ); + if(!item) + { + vevo_port_free(sor); +#ifdef STRICT_CHECKING + assert( 0 ); +#endif + return; + } +#ifdef STRICT_CHECKING + assert( item != NULL ); + int n_freed = 0; +#endif + for( i = 0; item[i] != NULL ; i ++ ) + { + void *sub_port = NULL; + + int ec = atom_get_value( item[i],0,&sub_port ); + if( ec == VEVO_NO_ERROR ) + { +#ifdef STRICT_CHECKING + assert(sub_port != NULL); + n_freed++; +#endif + vevo_port_free( sub_port ); + } + } + free(item); + vevo_port_free( sor ); +} + + +char **vevo_port_deepen_namespace( void *port, char *path) +{ +#ifdef STRICT_CHECKING + assert( port != NULL ); + assert( path != NULL ); +#endif + char **top_level = vevo_list_properties(port); + int k; + int num = 0; + if(!top_level) + { + return 0; + } + num = vevo_num_properties(port ); + + if( num == 0 ) + { + return NULL; + } + char **res = (char**) malloc( sizeof(char*) * (num+1)); + memset(res,0,sizeof(char*) * (num+1)); + int n = 0; + + for( k = 0; top_level[k] != NULL ; k ++ ) + { + int atom_type = vevo_property_atom_type( port, top_level[k] ); + if( atom_type != VEVO_ATOM_TYPE_VOIDPTR && atom_type != VEVO_ATOM_TYPE_PORTPTR ) + { + int len = strlen(path) + 2; + len += strlen( top_level[k] ); + res[n] = (char*) malloc(sizeof(char) * len ); + snprintf(res[n],len,"%s/%s",path,top_level[k]); + n++; + } + free(top_level[k]); + } + free(top_level); + res[n] = NULL; + return res; +} + +char **vevo_port_recurse_namespace( vevo_port_t *port, const char *base ) + +{ + + char **top_level = vevo_list_properties(port); + if(!top_level) + return NULL; + int k; + int num = 0; + for( k = 0; top_level[k] != NULL ; k ++ ) + { + int atom_type = vevo_property_atom_type( port, top_level[k] ); + if( atom_type == VEVO_ATOM_TYPE_PORTPTR ) + { + void *p = NULL; + int error = vevo_property_get( port, top_level[k],0,&p ); + if( error == VEVO_NO_ERROR ) + { +#ifdef STRICT_CHECKING + assert( p != NULL ); +#endif + num += vevo_num_properties(p); + } + } + else if (atom_type != VEVO_ATOM_TYPE_VOIDPTR) + num++; + } + +#ifdef STRICT_CHECKING + assert( num > 0 ); +#endif + + char **namespace = (char**) vj_malloc(sizeof(char*) * (num+1) ); +#ifdef STRICT_CHECKING + assert( namespace != NULL ); +#endif + memset(namespace, 0,sizeof(char*) * (num+1)); + + int methods = 0; + int error; + for( k = 0; top_level[k] != NULL ; k ++ ) + { +#ifdef STRICT_CHECKING + assert( methods <= num ); +#endif + int atom_type = vevo_property_atom_type( port, top_level[k] ); + char path[256]; + + sprintf(path, "%s", base); + + if( atom_type == VEVO_ATOM_TYPE_PORTPTR ) + { + void *exp = NULL; + error = vevo_property_get( port, top_level[k],0,&exp ); +#ifdef STRICT_CHECKING + assert( error == VEVO_NO_ERROR ); +#endif + strcat( path, "/" ); + strcat( path, top_level[k] ); + + char **ns = vevo_port_deepen_namespace( exp, path ); + if( ns ) + { + int j; + for( j = 0; ns[j] != NULL ; j ++ ) + { + namespace[methods] = strdup( ns[j]); + methods++; + free(ns[j]); + } + free(ns); + } + } + else if( atom_type != VEVO_ATOM_TYPE_VOIDPTR ) + { + strcat( path, "/" ); + strcat( path, top_level[k] ); + namespace[ methods ] = strdup( path ); + methods ++; + } + free(top_level[k]); + } + free(top_level); + return namespace; +} +//! Flatten all ports and return list of ports to be destroyed +/*! + \param sorted_port Reference Port + \param p Top level Port to scan + */ +static void vevo_port_recurse_free( vevo_port_t *sorted_port, vevo_port_t *p ) +{ +#ifdef STRICT_CHECKING + assert( p != NULL ); +#endif + vevo_storage_t **item = vevo_list_nodes_( p, VEVO_ATOM_TYPE_PORTPTR ); + if(!item) + { + free(item); + return; + } + + vevo_port_register( sorted_port, p ); + int i; + for( i = 0; item[i] != NULL ; i ++ ) + { + void *q = NULL; + int n = vevo_port_get_port( p, item[i], &q ); + + if( n == 1 && q != NULL ) + { + if(!vevo_scan_for_atom( q, VEVO_ATOM_TYPE_PORTPTR )) + vevo_port_register( sorted_port,q ); + else + vevo_port_recurse_free( sorted_port,q ); + } + else + { + if( n > 1 ) + { + int k = 0; + for( k = 0; k < item[i]->num_elements; k ++ ) + { + void *qq = NULL; + atom_get_value( item[i], k, &qq ); + if(!vevo_scan_for_atom(qq,VEVO_ATOM_TYPE_PORTPTR )) + vevo_port_register( sorted_port,qq ); + else + vevo_port_recurse_free( sorted_port,qq ); + } + } + } + + } + free(item); +} + +//! Run over port reference port and verify that all ports have been freed +/*! + \param p pointer to reference port + \return error code +*/ + +static int vevo_port_ref_verify( vevo_port_t *p) +{ + int err = 0; +/* +#ifdef STRICT_CHECKING + char **item = NULL; + int i; + int ref_count = 0; + item = vevo_list_properties( p ); + if( item == NULL ) + { + veejay_msg(0, "%s: No properties in %p",p); + return 1; + } + for( i = 0; item[i] != NULL ; i ++ ) + { + int error = vevo_property_get( port_ref_,item[i],0,&ref_count); + + if( error == VEVO_ERROR_PROPERTY_EMPTY ) + ref_count = 0; + else + { + if( error != VEVO_NO_ERROR ) + { + veejay_msg(0, "Port '%p' reference unexpected error %d)", item[i],error ); + err++; + } + } + + if( ref_count != 0 ) + { + void *which_port = NULL; + error = vevo_property_get( port_ref_, item[i],0, &which_port ); + if( error ) + veejay_msg(0, "Port '%s' retrieval returns error %d", item[i],error ); +// else +// veejay_msg(0, "Reference to Port %s exists, but may be invalid", item[i]); +// veejay_msg(0, "Port '%s' reference count is %d",item[i], ref_count); + err++; + } + ref_count = 1; + free(item[i]); + } + free(item); +#endif + return err; +*/ + return 1; +} +static char *vevo_property_get_str( vevo_port_t *port, const char *key ) +{ + size_t len = vevo_property_element_size( port, key, 0 ); + char *ret = NULL; + if(len<=0) return NULL; + ret = (char*) malloc(sizeof(char) * len ); + vevo_property_get( port, key, 0, &ret ); + return ret; +} + +static char *vevo_format_inline_property( vevo_port_t *port, int n_elem, int type ) +{ + char *res = NULL; + char token[5]; + bzero(token,5); + switch(type) + { + case VEVO_ATOM_TYPE_INT: + token[0] = 'd'; + break; + case VEVO_ATOM_TYPE_BOOL: + token[0] = 'b'; + break; + case VEVO_ATOM_TYPE_UINT64: + token[0] = 'D'; + break; + case VEVO_ATOM_TYPE_STRING: + token[0] = 's'; + break; + case VEVO_ATOM_TYPE_DOUBLE: + token[0] = 'g'; + break; + + } + + if( token[0]) + { + int len = n_elem * strlen(token) + 1; + res = (char*) calloc(1, sizeof(char) * len ); + int i; + for( i =0; i < n_elem; i ++ ) + strncat( res,token,strlen(token) ); + } + return res; +} + +char *vevo_format_property( vevo_port_t *port, const char *key ) +{ + char *res = NULL; + char token[5]; + int atom_type = vevo_property_atom_type( port, key ); + + int n_elem = vevo_property_num_elements( port, key ); + + if( n_elem <= 0 ) + n_elem = 1; + + bzero(token,5); + + switch( atom_type ) + { + case VEVO_ATOM_TYPE_INT: + case VEVO_ATOM_TYPE_BOOL: + token[0] = 'd'; + break; + case VEVO_ATOM_TYPE_UINT64: + token[0] = 'D'; + break; + case VEVO_ATOM_TYPE_DOUBLE: + token[0] = 'g'; + break; + case VEVO_ATOM_TYPE_STRING: + token[0] = 's'; + break; + case VEVO_ATOM_TYPE_VOIDPTR: + token[0] = 'x'; + break; + case VEVO_ATOM_TYPE_PORTPTR: + token[0] = 'p'; + break; + default: + token[0] = 'g'; + break; + } + + if( token[0]) + { + int len = n_elem * strlen(token) + 1; + res = (char*) calloc(1, sizeof(char) * len ); + int i; + for( i =0; i < n_elem; i ++ ) + strncat( res,token,strlen(token) ); + } + + return res; + +} +char *vevo_format_kind( vevo_port_t *port, const char *key ) +{ + char *res = NULL; + char token[5]; + int atom_type = vevo_property_atom_type( port, key ); + + bzero(token,5); + + switch( atom_type ) + { + case VEVO_ATOM_TYPE_INT: + case VEVO_ATOM_TYPE_BOOL: + token[0] = 'd'; + break; + case VEVO_ATOM_TYPE_UINT64: + token[0] = 'D'; + break; + case VEVO_ATOM_TYPE_DOUBLE: + token[0] = 'g'; + break; + case VEVO_ATOM_TYPE_STRING: + token[0] = 's'; + break; + case VEVO_ATOM_TYPE_VOIDPTR: + token[0] = 'x'; + break; + case VEVO_ATOM_TYPE_PORTPTR: + token[0] = 'p'; + break; + default: + token[0] = 'g'; + break; + } + + if( token[0]) + { + res = strdup( token ); + } + + return res; + +} + + +static const char *vevo_split_token_( const char *s, const char delim, char *buf, int buf_len ) +{ + const char *c = s; + int n = 0; + while(*c && n < buf_len) + { + *c++; + n++; + + if( *c == delim ) + { + strncpy( buf,s,n ); + return c+1; + } + } + return NULL; +} + +static char *vevo_scan_token_( const char *s ) +{ + const char *c = s; + int n = 0; + int ld = 0; + int fk = 0; + while( *c ) + { + if(*c == ':') + ld = n + 1; + if(*c == '=' && ld > 0) + { + fk = 1; + break; + } + *c++; + n++; + } + char *res = NULL; + + if( ld > 0 && fk ) + res = strndup( s, ld ); + + return res; +} + +static const char *vevo_split_token_q( const char *s, const char delim, char *buf, int buf_len ) +{ + const char *c = s; + int n = 0; + + if( *c != '"' ) + return NULL; + + while(*c && n < buf_len) + { + *c++; + n++; + + if( *c == delim && n > 2) + { + strncpy( buf,s+1,n-1 ); + return c; + } + } + return NULL; +} + +//! Write all keys and values in character string to a port' +/*! + \param port Port + \param s Character string + \return Error Code + */ +int vevo_sscanf_port( vevo_port_t *port, const char *s ) +{ + + const char *ptr = s; + int len = strlen(s); + int i = 0; + while( len > 0 ) + { + char *token = vevo_scan_token_(ptr); + int token_len; + if( token ) + { + token_len = strlen(token); + if(vevo_sscanf_property( port, token )) + i++; + } + else + { + token_len = len; + if(vevo_sscanf_property( port, ptr )) + i++; + } + len -= token_len; + ptr += token_len; + } + return i; +} +//! Read a key and value from a character string into a Port' +/*! + \param port Port + \param s character string + \return error code + */ +#define MAX_ELEMENTS 64 +int vevo_sscanf_property( vevo_port_t *port, const char *s) +{ + int done = 0; + char key[PROPERTY_KEY_SIZE]; + bzero(key, PROPERTY_KEY_SIZE ); + const char *value = vevo_split_token_(s, '=', key, PROPERTY_KEY_SIZE ); + if(value==NULL) + return 0; + + char *format = vevo_format_property( port, key ); + int atom = vevo_property_atom_type( port, key ); + + if( format == NULL ) + return done; + if(atom==-1) + atom = VEVO_ATOM_TYPE_DOUBLE; + //@ if a property does not exist, DOUBLE is assumed + //@ DOUBLE is valid for all sample's of type capture. + + uint64_t i64_val[MAX_ELEMENTS]; + int32_t i32_val[MAX_ELEMENTS]; + double dbl_val[MAX_ELEMENTS]; + char *str_val[MAX_ELEMENTS]; + + int cur_elem = 0; + int n = 0; + + const char *p = value; + char *fmt = format; + while( *fmt != '\0' ) + { + char arg[256]; + bzero(arg,256); + + if( *fmt == 's' ) + p = vevo_split_token_q( p, ':', arg, 1024 ); + else + p = vevo_split_token_( p, ':', arg, 1024 ); + + if( p == NULL ) + return 0; + + if( arg[0] != ':' ) + { + switch(*fmt) + { + case 'd': + n = sscanf( arg, "%d", &(i32_val[cur_elem])); + break; + case 'D': + n = sscanf( arg, "%lld", &(i64_val[cur_elem])); + break; + case 'g': + n = sscanf( arg, "%lf", &(dbl_val[cur_elem])); + break; + case 's': + str_val[cur_elem] = strdup( arg ); + n = 1; + break; + default: + n = 0; + break; + } + } + else + { + n = 0; + } + + *fmt++; + cur_elem ++; + } + + void *ptr = NULL; + if( n > 0 ) + switch( *format ) + { + case 'd': + ptr = &(i32_val[0]); + break; + case 'D': + ptr = &(i64_val[0]); + break; + case 'g': + ptr = &(dbl_val[0]); + break; + case 's': + ptr = &(str_val[0]); + break; + } + + int error = 0; + + //veejay_msg(0, "Set: '%s' : %d, %g", key,n, dbl_val[0] ); + + if( n == 0 ) + error = vevo_property_set( port, key, atom, 0, NULL ); + else + error = vevo_property_set( port, key, atom, cur_elem, ptr ); + + if( error == VEVO_NO_ERROR ) + done = 1; + return done; +} + +//! Write all properties in a port to a new character string in the form 'key=[value:value:value]:' +/*! + \param port Port + \return A new character string + */ +char **vevo_sprintf_port( vevo_port_t *port ) +{ + int i; + int k = 0; + int num = vevo_num_properties(port); + if( num == 0 ) + return NULL; + + char **keys = vevo_list_properties(port ); + + char **res = (char**) calloc(1, sizeof(char*) * (num+1) ); + + for( i = 0; keys[i] != NULL; i ++ ) + { + char *buf = vevo_sprintf_property(port, keys[i]); + char *p = buf; + if(buf) + { + res[k++] = strdup( buf ); + free(p); + } + free(keys[i]); + + } + res[num] = NULL; + + free(keys); + + return res; +} +//! Write property value to a new character string in the form 'key=[value:value:value]:' +/*! + \param port Port + \param key Property to write + \return A new character string + */ + +char *vevo_sprintf_property_value( vevo_port_t *port, const char *key) +{ + char tmp[512]; + int n = vevo_property_num_elements( port, key ); + if( n <= 0 ) + return NULL; + int i; + int size = 0; + int atom = vevo_property_atom_type( port , key ); + + bzero(tmp,512); + + if(atom == VEVO_ATOM_TYPE_INT || atom == VEVO_ATOM_TYPE_BOOL) + { + int *a = (int*) malloc(sizeof(int) * n ); + for( i = 0; i < n ; i ++ ) + if( vevo_property_get( port, key, i, &(a[i]) ) != VEVO_NO_ERROR) + { + free(a); + return NULL; + } + else + { + char val[16]; + sprintf(val, "%4d", a[i]); + strcat( tmp, val ); + strcat( tmp, " "); + } + free(a); + } else if (atom == VEVO_ATOM_TYPE_DOUBLE ) + { + double *a = (double*) malloc(sizeof(double) * n ); + for( i = 0; i < n; i ++ ) + if( vevo_property_get( port, key, i , &(a[i])) != VEVO_NO_ERROR) + { + free(a); + return NULL; + } + else + { + char val[16]; + sprintf(val, "%04.2g", a[i]); + strcat( tmp, val ); + strcat( tmp, " " ); + } + free(a); + } else + return NULL; + + return strdup( tmp ); +} + + +#define PROP_MAX_LEN 1024 +#define PROP_ARG_LEN 256 +char *vevo_sprintf_property( vevo_port_t *port, const char *key ) +{ + char *format = vevo_format_property( port, key ); + if( format == NULL ) + return NULL; + char *res = (char*) calloc( 1, sizeof(char) * PROP_MAX_LEN ); + int n_elems = 0; + + int32_t i32_val = 0; + uint64_t i64_val = 0; + double dbl_val = 0.0; + char *str_val = NULL; + int error = 0; + int nerr = 0; + int size = PROP_MAX_LEN; + + void *vport = NULL; + + sprintf(res, "%s=", key ); + + while( *format && nerr == 0) + { + char tmp[1024]; + bzero(tmp,256); + switch(*format) + { + case 'd': + error = vevo_property_get(port,key,n_elems,&i32_val); + if( error == VEVO_NO_ERROR ) { + sprintf(tmp, "%d:", i32_val ); + } else if (error == VEVO_ERROR_PROPERTY_EMPTY ) { + tmp[0] = ':'; + } else + nerr ++; + break; + case 'D': + error = vevo_property_get(port,key,n_elems,&i64_val); + if( error == VEVO_NO_ERROR ) { + sprintf(tmp, "%lld:", i64_val ); + } else if( error == VEVO_ERROR_PROPERTY_EMPTY ) { + tmp[0] = ':'; + } else + nerr ++; + break; + case 'g': + error = vevo_property_get(port,key,n_elems,&dbl_val); + if( error == VEVO_NO_ERROR ) { + sprintf(tmp, "%g:", dbl_val ); + } else if ( error == VEVO_ERROR_PROPERTY_EMPTY ) { + tmp[0] = ':'; + } else + nerr ++; + break; + case 's': + str_val = vevo_property_get_str( port, key ); + if(str_val) + { + tmp[0] = '\"'; + strncat(tmp+1,str_val,250); + int n = strlen(tmp); + tmp[n] = '\"'; + tmp[n+1] = ':'; + } + else + { + tmp[0] = '\"'; + tmp[1] = '\"'; + tmp[2] = ':'; + } + str_val = NULL; + break; + case 'x': + break; + case 'p': + { + int num = 0; + if(n_elems == 0 ) + { + error = vevo_property_get(port,key,0,&vport ); + if(error == VEVO_NO_ERROR ) + num = vevo_num_properties(vport); + } + + if( num > 0 ) + { + char **pstr = vevo_sprintf_port( vport ); + if(pstr) + { + int k; + + sprintf(tmp, "[%s",key); + + for( k = 0; pstr[k] != NULL; k ++ ) + { + strncat(tmp, pstr[k], strlen(pstr[k])); + free(pstr[k]); + } + free(pstr); + + int n = strlen(tmp); + tmp[n] =']'; + tmp[n+1] = ':'; + } + } + } + break; + } + *format++; + n_elems++; + + if( nerr ) + break; + + size -= strlen(tmp); + if(size > 0) + strcat(res, tmp ); + else + nerr++; + } + + if( nerr ) + { + if( res ) free(res); + res = NULL; + } + return res; +} +int vevo_property_from_string( vevo_port_t *port, const char *s, const char *key, int n_elem, int type) +{ + int done = 0; + char *format = vevo_format_inline_property( port, n_elem, type ); + + if( format == NULL ) + return done; + + uint64_t i64_val[MAX_ELEMENTS]; + int32_t i32_val[MAX_ELEMENTS]; + double dbl_val[MAX_ELEMENTS]; + char *str_val[MAX_ELEMENTS]; + + int cur_elem = 0; + int n = 0; + const char *p = s; + char *fmt = format; + while( *fmt != '\0' ) + { + char arg[256]; + bzero(arg,256); + + if( *fmt == 's' ) + p = vevo_split_token_q( p, ':', arg, 1024 ); + else + p = vevo_split_token_( p, ':', arg, 1024 ); + + if( p == NULL ) + { + veejay_msg(0,"Invalid value. Use 'value:' "); + free(format); + return 0; + } + if( arg[0] != ':' ) + { + switch(*fmt) + { + case 'd': + case 'b': + n = sscanf( arg, "%d", &(i32_val[cur_elem])); + break; + case 'D': + n = sscanf( arg, "%lld", &(i64_val[cur_elem])); +#ifdef STRICT_CHECKING + assert( n == 1 ); +#endif + break; + case 'g': + n = sscanf( arg, "%lf", &(dbl_val[cur_elem])); + break; + case 's': + str_val[cur_elem] = strdup( arg ); + n = 1; + break; + default: + n = 0; + break; + } + } + else + { + n = 0; + } + + *fmt++; + cur_elem ++; + } + + void *ptr = NULL; + if( n > 0 ) + switch( *format ) + { + case 'd': + case 'b': + ptr = &(i32_val[0]); + break; + case 'D': + ptr = &(i64_val[0]); + break; + case 'g': + ptr = &(dbl_val[0]); + break; + case 's': + ptr = &(str_val[0]); + break; + } + + int error = 0; + if( n == 0 ) + error = vevo_property_set( port, key, type, 0, NULL ); + else + { +#ifdef STRICT_CHECKING + assert( port != NULL ); + assert( ptr != NULL ); +#endif + error = vevo_property_set( port, key, type, cur_elem, ptr ); + } + if( error == VEVO_NO_ERROR ) + done = 1; + free(format); + return done; +} + +char *vevo_property_get_string( void *port, const char *key ) +{ + size_t len = vevo_property_element_size( port, key, 0 ); + char *ret = NULL; + if(len<=0) return NULL; + + if( vevo_property_get( port, key,0,NULL ) != VEVO_NO_ERROR ) + return NULL; + +#ifdef STRICT_CHECKING + assert( vevo_property_atom_type( port, key ) == VEVO_ATOM_TYPE_STRING ); +#endif + ret = (char*) vj_malloc(sizeof(char) * len ); + vevo_property_get( port, key, 0, &ret ); + return ret; +} + + +int +vevo_property_del(vevo_port_t * p, + const char *key ) +{ +#ifdef STRICT_CHECKING + assert(p != NULL); + //@ no self referencing + assert( key != NULL ); +#endif + __vevo_port_t *port = (__vevo_port_t *) p; + uint32_t hash_key = hash_key_code(key); + void *node = NULL; + if (!port->table) { + veejay_msg(0, "Is LIst"); + vevo_property_t *pnode = NULL; + if ((pnode = prop_node_get(port, hash_key)) != NULL) { + vevo_free_storage(port,pnode->st); + prop_node_free(port,pnode); + //node = (void *) pnode; + } + } else { + veejay_msg(0, "Is Hash"); + hnode_t *old_node = NULL; + if ((old_node = property_exists(port, hash_key)) != NULL) { + vevo_storage_t *oldstor = + (vevo_storage_t *) hnode_get(old_node); + vevo_free_storage(port,oldstor); + hash_delete((hash_t *) port->table, old_node); + hnode_destroy(old_node); + } + } + + port_index_t *l = port->index; + port_index_t *n = NULL; + while (l != NULL) { + n = l->next; + if( (uint32_t) l->key == hash_key ) + port_node_free(port,l); + l = n; + } + + return VEVO_NO_ERROR; +} + diff --git a/branches/V-1.5.3/veejay-server/libvevo/vevo.h b/branches/V-1.5.3/veejay-server/libvevo/vevo.h new file mode 100644 index 00000000..33b636a4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvevo/vevo.h @@ -0,0 +1,73 @@ +/* +Copyright (c) 2004-2005 N.Elburg + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +# ifndef VEVO_H_INCLUDED +# define VEVO_H_INCLUDED + +#include +#include +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#define VEVO_FF_PORT 10 // free frame port +#define VEVO_FF_PARAM_PORT 11 // free frame parameter port + +#define VEVO_FR_PORT 20 // frei0r port +#define VEVO_FR_PARAM_PORT 21 // frei0r parameter port + +#define VEVO_LIVIDO_PORT 30 // livido port +#define VEVO_LIVIDO_PARAM_PORT 31 // livido parameter port +#define VEVO_ILLEGAL 100 + +#define VEVO_EVENT_PORT 321 + +#define VEVO_VJE_PORT 32 + + +#define VEVO_CACHE_PORT 40 // linked list +#define VEVO_PORT_REFERENCES 1040 // hash +#define VEVO_SAMPLE_PORT 2035 // sample +#define VEVO_SAMPLE_BANK_PORT 2036 // bank + +#define VEVO_VJE_INSTANCE_PORT 33 + +#define HAVE_LIVIDO_PORT_T +typedef void livido_port_t; +# endif + + +#define LIVIDO_ATOM_TYPE_INT VEVO_ATOM_TYPE_INT +#define LIVIDO_ATOM_TYPE_DOUBLE VEVO_ATOM_TYPE_DOUBLE +#define LIVIDO_ATOM_TYPE_BOOLEAN VEVO_ATOM_TYPE_BOOL +#define LIVIDO_ATOM_TYPE_STRING VEVO_ATOM_TYPE_STRING +#define LIVIDO_ATOM_TYPE_VOIDPTR VEVO_ATOM_TYPE_VOIDPTR +#define LIVIDO_ATOM_TYPE_PORTPTR VEVO_ATOM_TYPE_PORTPTR + diff --git a/branches/V-1.5.3/veejay-server/libvje/Makefile.am b/branches/V-1.5.3/veejay-server/libvje/Makefile.am new file mode 100644 index 00000000..3b028c66 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/Makefile.am @@ -0,0 +1,91 @@ +# Makefile for veejay + +MAINTAINERCLEANFILES=Makefile.in +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/vjmem -I$(top_srcdir)/vjmsg $(FFMPEG_CFLAGS) $(GLIB_CFLAGS) + +AM_CFLAGS = $(OP_CFLAGS) -freg-struct-return + +pkginclude_HEADERS=vje.h + +EXTRA_DIST = internal.h plugload.h vje.h +EXTRA_DIST += effects/autoeq.h effects/crosspixel.h effects/mask.h effects/rawval.h \ + effects/average.h effects/cutstop.h effects/maskstop.h effects/reflection.h \ + effects/baltantv.h effects/deinterlace.h effects/mirrors2.h effects/revtv.h \ + effects/bathroom.h effects/dices.h effects/mirrors.h effects/rgbchannel.h \ + effects/bgsubtract.h effects/diff.h effects/morphology.h effects/rgbkey.h \ + effects/binaryoverlays.h effects/diffimg.h effects/motionblur.h effects/rgbkeysmooth.h \ + effects/blob.h effects/diffmap.h effects/motionmap.h effects/ripple.h \ + effects/boids.h effects/dissolve.h effects/mtracer.h effects/rippletv.h \ + effects/borders.h effects/distort.h effects/negatechannel.h effects/rotozoom.h \ + effects/bwselect.h effects/dither.h effects/negation.h effects/scratcher.h \ + effects/cartonize.h effects/dummy.h effects/neighbours2.h effects/sinoids.h \ + effects/chameleonblend.h effects/dupmagic.h effects/neighbours3.h effects/slice.h \ + effects/chameleon.h effects/emboss.h effects/neighbours4.h effects/slicer.h \ + effects/chromamagick.h effects/enhancemask.h effects/neighbours5.h effects/smear.h \ + effects/chromapalette.h effects/fibdownscale.h effects/neighbours.h effects/smuck.h \ + effects/chromascratcher.h effects/fisheye.h effects/nervous.h effects/softblur.h \ + effects/chromium.h effects/flare.h effects/noiseadd.h effects/solarize.h \ + effects/colflash.h effects/flip.h effects/noisepencil.h effects/split.h \ + effects/colmorphology.h effects/frameborder.h effects/opacityadv.h effects/swirl.h \ + effects/coloradjust.h effects/gamma.h effects/opacity.h effects/iris.h effects/texmap.h \ + effects/color.h effects/ghost.h effects/opacitythreshold.h effects/threshold.h \ + effects/colorhis.h effects/greyselect.h effects/overclock.h effects/timedistort.h \ + effects/colormap.h effects/isolate.h effects/pencilsketch.h effects/tracer.h \ + effects/colorshift.h effects/keyselect.h effects/photoplay.h effects/transform.h \ + effects/common.h effects/killchroma.h effects/picinpic.h effects/tripplicity.h \ + effects/complexinvert.h effects/lumablend.h effects/pixelate.h effects/uvcorrect.h \ + effects/complexsaturate.h effects/lumakey.h effects/posterize.h effects/videoplay.h \ + effects/complexsync.h effects/lumamagick.h effects/radcor.h effects/videowall.h \ + effects/complexthreshold.h effects/lumamask.h effects/radialblur.h effects/waterrippletv.h \ + effects/constantblend.h effects/magicmirror.h effects/radioactive.h effects/whiteframe.h \ + effects/contourextract.h effects/magicoverlays.h effects/raster.h effects/widthmirror.h \ + effects/contrast.h effects/magicscratcher.h effects/rawman.h effects/zoom.h effects/iris.h effects/cali.h effects/median.h + +EXTRA_DIST += specs/FreeFrame.h specs/frei0r.h + +EXTRA_DIST += transitions/3bar.h transitions/fadecolorrgb.h transitions/transblend.h transitions/transline.h \ + transitions/vbar.h transitions/fadecolor.h transitions/slidingdoor.h transitions/transcarot.h \ + transitions/transop.h transitions/wipe.h + +EXTRA_DIST += ctmf/ctmf.h + +VJE_LIB_FILE = libvje.la +noinst_LTLIBRARIES = $(VJE_LIB_FILE) + +libvje_la_SOURCES = plugload.c vj-effect.c vj-effman.c effects/common.c \ + ctmf/ctmf.c \ + effects/diff.c effects/fibdownscale.c effects/killchroma.c \ + effects/lumamagick.c effects/autoeq.c effects/colorhis.c \ + effects/mirrors.c effects/colormap.c effects/negatechannel.c effects/negation.c \ + effects/overclock.c effects/dissolve.c effects/opacity.c effects/iris.c effects/posterize.c \ + effects/dither.c effects/dices.c effects/emboss.c effects/flip.c \ + effects/revtv.c effects/softblur.c effects/zoom.c effects/split.c effects/widthmirror.c \ + effects/frameborder.c effects/dummy.c effects/rawman.c effects/rawval.c \ + effects/smuck.c effects/transform.c effects/borders.c effects/colflash.c \ + effects/rgbkey.c effects/solarize.c effects/mirrors2.c effects/timedistort.c \ + effects/whiteframe.c effects/deinterlace.c effects/lumakey.c effects/chameleon.c \ + effects/coloradjust.c effects/gamma.c effects/reflection.c effects/rotozoom.c \ + transitions/transblend.c transitions/slidingdoor.c effects/color.c \ + transitions/transline.c transitions/transop.c transitions/transcarot.c \ + transitions/fadecolor.c effects/lumablend.c effects/chromamagick.c \ + transitions/fadecolorrgb.c effects/magicoverlays.c effects/binaryoverlays.c \ + effects/pencilsketch.c effects/chameleonblend.c effects/diffimg.c \ + effects/swirl.c effects/chromium.c effects/uvcorrect.c effects/chromapalette.c \ + effects/radialblur.c effects/fisheye.c effects/raster.c effects/smear.c effects/magicmirror.c \ + effects/lumamask.c effects/pixelate.c effects/colorshift.c effects/scratcher.c effects/opacitythreshold.c \ + effects/opacityadv.c effects/rgbkeysmooth.c effects/mask.c effects/distort.c effects/motionmap.c \ + transitions/wipe.c effects/magicscratcher.c effects/chromascratcher.c \ + effects/tracer.c effects/mtracer.c effects/dupmagic.c effects/keyselect.c \ + effects/greyselect.c effects/bwselect.c effects/complexsaturate.c \ + effects/complexthreshold.c effects/complexinvert.c effects/complexsync.c \ + effects/isolate.c transitions/vbar.c transitions/3bar.c effects/enhancemask.c effects/noiseadd.c \ + effects/contrast.c effects/motionblur.c effects/sinoids.c effects/average.c effects/slicer.c \ + effects/ripple.c effects/waterrippletv.c effects/water.c effects/noisepencil.c effects/bathroom.c effects/slice.c \ + effects/crosspixel.c effects/diffmap.c effects/threshold.c effects/morphology.c effects/colmorphology.c \ + effects/ghost.c effects/blob.c effects/radcor.c effects/boids.c effects/nervous.c \ + effects/cartonize.c effects/tripplicity.c effects/neighbours.c effects/neighbours2.c\ + effects/neighbours3.c effects/neighbours4.c effects/neighbours5.c effects/cutstop.c\ + effects/contourextract.c effects/texmap.c effects/maskstop.c effects/photoplay.c effects/videoplay.c effects/rgbchannel.c \ + effects/videowall.c effects/flare.c effects/radioactive.c effects/baltantv.c effects/constantblend.c effects/picinpic.c effects/bgsubtract.c effects/cali.c effects/median.c + + diff --git a/branches/V-1.5.3/veejay-server/libvje/ctmf/ctmf.c b/branches/V-1.5.3/veejay-server/libvje/ctmf/ctmf.c new file mode 100644 index 00000000..2722e1b6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/ctmf/ctmf.c @@ -0,0 +1,433 @@ +/* + * ctmf.c - Constant-time median filtering + * Copyright (C) 2006 Simon Perreault + * + * Reference: S. Perreault and P. Hİbert, "Median Filtering in Constant Time", + * IEEE Transactions on Image Processing, September 2007. + * + * This program has been obtained from http://nomis80.org/ctmf.html. No patent + * covers this program, although it is subject to the following license: + * + * 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 3 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, see . + * + * Contact: + * Laboratoire de vision et syst¨mes numİriques + * Pavillon Adrien-Pouliot + * Universitİ Laval + * Sainte-Foy, Quİbec, Canada + * G1K 7P4 + * + * perreaul@gel.ulaval.ca + */ + +/* Standard C includes */ +#include +#include +#include +#include + +/* Type declarations */ +#ifdef _MSC_VER +#include +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef UINT32 uint32_t; +#pragma warning( disable: 4799 ) +#else +#include +#endif + +/* Intrinsic declarations */ +#if defined(__SSE2__) || defined(__MMX__) +#if defined(__SSE2__) +#include +#elif defined(__MMX__) +#include +#endif +#if defined(__GNUC__) +#include +#elif defined(_MSC_VER) +#include +#endif +#elif defined(__ALTIVEC__) +#include +#endif + +/* Compiler peculiarities */ +#if defined(__GNUC__) +#include +#define inline __inline__ +#define align(x) __attribute__ ((aligned (x))) +#elif defined(_MSC_VER) +#define inline __inline +#define align(x) __declspec(align(x)) +#else +#define inline +#define align(x) +#endif + +#ifndef MIN +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) < (b) ? (b) : (a)) +#endif + +/** + * This structure represents a two-tier histogram. The first tier (known as the + * "coarse" level) is 4 bit wide and the second tier (known as the "fine" level) + * is 8 bit wide. Pixels inserted in the fine level also get inserted into the + * coarse bucket designated by the 4 MSBs of the fine bucket value. + * + * The structure is aligned on 16 bytes, which is a prerequisite for SIMD + * instructions. Each bucket is 16 bit wide, which means that extra care must be + * taken to prevent overflow. + */ +typedef struct align(16) +{ + uint16_t coarse[16]; + uint16_t fine[16][16]; +} Histogram; + +/** + * HOP is short for Histogram OPeration. This macro makes an operation \a op on + * histogram \a h for pixel value \a x. It takes care of handling both levels. + */ +#define HOP(h,x,op) \ + h.coarse[x>>4] op; \ + *((uint16_t*) h.fine + x) op; + +#define COP(c,j,x,op) \ + h_coarse[ 16*(n*c+j) + (x>>4) ] op; \ + h_fine[ 16 * (n*(16*c+(x>>4)) + j) + (x & 0xF) ] op; + +/** + * Adds histograms \a x and \a y and stores the result in \a y. Makes use of + * SSE2, MMX or Altivec, if available. + */ +#if defined(__SSE2__) +static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) +{ + *(__m128i*) &y[0] = _mm_add_epi16( *(__m128i*) &y[0], *(__m128i*) &x[0] ); + *(__m128i*) &y[8] = _mm_add_epi16( *(__m128i*) &y[8], *(__m128i*) &x[8] ); +} +#elif defined(__MMX__) +static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) +{ + *(__m64*) &y[0] = _mm_add_pi16( *(__m64*) &y[0], *(__m64*) &x[0] ); + *(__m64*) &y[4] = _mm_add_pi16( *(__m64*) &y[4], *(__m64*) &x[4] ); + *(__m64*) &y[8] = _mm_add_pi16( *(__m64*) &y[8], *(__m64*) &x[8] ); + *(__m64*) &y[12] = _mm_add_pi16( *(__m64*) &y[12], *(__m64*) &x[12] ); +} +#elif defined(__ALTIVEC__) +static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) +{ + *(vector unsigned short*) &y[0] = vec_add( *(vector unsigned short*) &y[0], *(vector unsigned short*) &x[0] ); + *(vector unsigned short*) &y[8] = vec_add( *(vector unsigned short*) &y[8], *(vector unsigned short*) &x[8] ); +} +#else +static inline void histogram_add( const uint16_t x[16], uint16_t y[16] ) +{ + int i; + for ( i = 0; i < 16; ++i ) { + y[i] += x[i]; + } +} +#endif + +/** + * Subtracts histogram \a x from \a y and stores the result in \a y. Makes use + * of SSE2, MMX or Altivec, if available. + */ +#if defined(__SSE2__) +static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) +{ + *(__m128i*) &y[0] = _mm_sub_epi16( *(__m128i*) &y[0], *(__m128i*) &x[0] ); + *(__m128i*) &y[8] = _mm_sub_epi16( *(__m128i*) &y[8], *(__m128i*) &x[8] ); +} +#elif defined(__MMX__) +static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) +{ + *(__m64*) &y[0] = _mm_sub_pi16( *(__m64*) &y[0], *(__m64*) &x[0] ); + *(__m64*) &y[4] = _mm_sub_pi16( *(__m64*) &y[4], *(__m64*) &x[4] ); + *(__m64*) &y[8] = _mm_sub_pi16( *(__m64*) &y[8], *(__m64*) &x[8] ); + *(__m64*) &y[12] = _mm_sub_pi16( *(__m64*) &y[12], *(__m64*) &x[12] ); +} +#elif defined(__ALTIVEC__) +static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) +{ + *(vector unsigned short*) &y[0] = vec_sub( *(vector unsigned short*) &y[0], *(vector unsigned short*) &x[0] ); + *(vector unsigned short*) &y[8] = vec_sub( *(vector unsigned short*) &y[8], *(vector unsigned short*) &x[8] ); +} +#else +static inline void histogram_sub( const uint16_t x[16], uint16_t y[16] ) +{ + int i; + for ( i = 0; i < 16; ++i ) { + y[i] -= x[i]; + } +} +#endif + +static inline void histogram_muladd( const uint16_t a, const uint16_t x[16], + uint16_t y[16] ) +{ + int i; + for ( i = 0; i < 16; ++i ) { + y[i] += a * x[i]; + } +} + +static void ctmf_helper( + const unsigned char* const src, unsigned char* const dst, + const int width, const int height, + const int src_step, const int dst_step, + const int r, const int cn, + const int pad_left, const int pad_right + ) +{ + const int m = height, n = width; + int i, j, k, c; + const unsigned char *p, *q; + + Histogram H[4]; + uint16_t *h_coarse, *h_fine, luc[4][16]; + + assert( src ); + assert( dst ); + assert( r >= 0 ); + assert( width >= 2*r+1 ); + assert( height >= 2*r+1 ); + assert( src_step != 0 ); + assert( dst_step != 0 ); + + /* SSE2 and MMX need aligned memory, provided by _mm_malloc(). */ +#if defined(__SSE2__) || defined(__MMX__) + h_coarse = (uint16_t*) _mm_malloc( 1 * 16 * n * cn * sizeof(uint16_t), 16 ); + h_fine = (uint16_t*) _mm_malloc( 16 * 16 * n * cn * sizeof(uint16_t), 16 ); + memset( h_coarse, 0, 1 * 16 * n * cn * sizeof(uint16_t) ); + memset( h_fine, 0, 16 * 16 * n * cn * sizeof(uint16_t) ); +#else + h_coarse = (uint16_t*) calloc( 1 * 16 * n * cn, sizeof(uint16_t) ); + h_fine = (uint16_t*) calloc( 16 * 16 * n * cn, sizeof(uint16_t) ); +#endif + + /* First row initialization */ + for ( j = 0; j < n; ++j ) { + for ( c = 0; c < cn; ++c ) { + COP( c, j, src[cn*j+c], += r+1 ); + } + } + for ( i = 0; i < r; ++i ) { + for ( j = 0; j < n; ++j ) { + for ( c = 0; c < cn; ++c ) { + COP( c, j, src[src_step*i+cn*j+c], ++ ); + } + } + } + + for ( i = 0; i < m; ++i ) { + + /* Update column histograms for entire row. */ + p = src + src_step * MAX( 0, i-r-1 ); + q = p + cn * n; + for ( j = 0; p != q; ++j ) { + for ( c = 0; c < cn; ++c, ++p ) { + COP( c, j, *p, -- ); + } + } + + p = src + src_step * MIN( m-1, i+r ); + q = p + cn * n; + for ( j = 0; p != q; ++j ) { + for ( c = 0; c < cn; ++c, ++p ) { + COP( c, j, *p, ++ ); + } + } + + /* First column initialization */ + memset( H, 0, cn*sizeof(H[0]) ); + memset( luc, 0, cn*sizeof(luc[0]) ); + if ( pad_left ) { + for ( c = 0; c < cn; ++c ) { + histogram_muladd( r, &h_coarse[16*n*c], H[c].coarse ); + } + } + for ( j = 0; j < (pad_left ? r : 2*r); ++j ) { + for ( c = 0; c < cn; ++c ) { + histogram_add( &h_coarse[16*(n*c+j)], H[c].coarse ); + } + } + for ( c = 0; c < cn; ++c ) { + for ( k = 0; k < 16; ++k ) { + histogram_muladd( 2*r+1, &h_fine[16*n*(16*c+k)], &H[c].fine[k][0] ); + } + } + + for ( j = pad_left ? 0 : r; j < (pad_right ? n : n-r); ++j ) { + for ( c = 0; c < cn; ++c ) { + const uint16_t t = 2*r*r + 2*r; + uint16_t sum = 0, *segment; + int b; + + histogram_add( &h_coarse[16*(n*c + MIN(j+r,n-1))], H[c].coarse ); + + /* Find median at coarse level */ + for ( k = 0; k < 16 ; ++k ) { + sum += H[c].coarse[k]; + if ( sum > t ) { + sum -= H[c].coarse[k]; + break; + } + } + assert( k < 16 ); + + /* Update corresponding histogram segment */ + if ( luc[c][k] <= j-r ) { + memset( &H[c].fine[k], 0, 16 * sizeof(uint16_t) ); + for ( luc[c][k] = j-r; luc[c][k] < MIN(j+r+1,n); ++luc[c][k] ) { + histogram_add( &h_fine[16*(n*(16*c+k)+luc[c][k])], H[c].fine[k] ); + } + if ( luc[c][k] < j+r+1 ) { + histogram_muladd( j+r+1 - n, &h_fine[16*(n*(16*c+k)+(n-1))], &H[c].fine[k][0] ); + luc[c][k] = j+r+1; + } + } + else { + for ( ; luc[c][k] < j+r+1; ++luc[c][k] ) { + histogram_sub( &h_fine[16*(n*(16*c+k)+MAX(luc[c][k]-2*r-1,0))], H[c].fine[k] ); + histogram_add( &h_fine[16*(n*(16*c+k)+MIN(luc[c][k],n-1))], H[c].fine[k] ); + } + } + + histogram_sub( &h_coarse[16*(n*c+MAX(j-r,0))], H[c].coarse ); + + /* Find median in segment */ + segment = H[c].fine[k]; + for ( b = 0; b < 16 ; ++b ) { + sum += segment[b]; + if ( sum > t ) { + dst[dst_step*i+cn*j+c] = 16*k + b; + break; + } + } + assert( b < 16 ); + } + } + } + +#if defined(__SSE2__) || defined(__MMX__) + _mm_empty(); + _mm_free(h_coarse); + _mm_free(h_fine); +#else + free(h_coarse); + free(h_fine); +#endif +} + +/** + * \brief Constant-time median filtering + * + * This function does a median filtering of an 8-bit image. The source image is + * processed as if it was padded with zeros. The median kernel is square with + * odd dimensions. Images of arbitrary size may be processed. + * + * To process multi-channel images, you must call this function multiple times, + * changing the source and destination adresses and steps such that each channel + * is processed as an independent single-channel image. + * + * Processing images of arbitrary bit depth is not supported. + * + * The computing time is O(1) per pixel, independent of the radius of the + * filter. The algorithm's initialization is O(r*width), but it is negligible. + * Memory usage is simple: it will be as big as the cache size, or smaller if + * the image is small. For efficiency, the histograms' bins are 16-bit wide. + * This may become too small and lead to overflow as \a r increases. + * + * \param src Source image data. + * \param dst Destination image data. Must be preallocated. + * \param width Image width, in pixels. + * \param height Image height, in pixels. + * \param src_step Distance between adjacent pixels on the same column in + * the source image, in bytes. + * \param dst_step Distance between adjacent pixels on the same column in + * the destination image, in bytes. + * \param r Median filter radius. The kernel will be a 2*r+1 by + * 2*r+1 square. + * \param cn Number of channels. For example, a grayscale image would + * have cn=1 while an RGB image would have cn=3. + * \param memsize Maximum amount of memory to use, in bytes. Set this to + * the size of the L2 cache, then vary it slightly and + * measure the processing time to find the optimal value. + * For example, a 512 kB L2 cache would have + * memsize=512*1024 initially. + */ +void ctmf( + const unsigned char* const src, unsigned char* const dst, + const int width, const int height, + const int src_step, const int dst_step, + const int r, const int cn, const long unsigned int memsize + ) +{ + /* + * Processing the image in vertical stripes is an optimization made + * necessary by the limited size of the CPU cache. Each histogram is 544 + * bytes big and therefore I can fit a limited number of them in the cache. + * That number may sometimes be smaller than the image width, which would be + * the number of histograms I would need without stripes. + * + * I need to keep histograms in the cache so that they are available + * quickly when processing a new row. Each row needs access to the previous + * row's histograms. If there are too many histograms to fit in the cache, + * thrashing to RAM happens. + * + * To solve this problem, I figure out the maximum number of histograms + * that can fit in cache. From this is determined the number of stripes in + * an image. The formulas below make the stripes all the same size and use + * as few stripes as possible. + * + * Note that each stripe causes an overlap on the neighboring stripes, as + * when mowing the lawn. That overlap is proportional to r. When the overlap + * is a significant size in comparison with the stripe size, then we are not + * O(1) anymore, but O(r). In fact, we have been O(r) all along, but the + * initialization term was neglected, as it has been (and rightly so) in B. + * Weiss, "Fast Median and Bilateral Filtering", SIGGRAPH, 2006. Processing + * by stripes only makes that initialization term bigger. + * + * Also, note that the leftmost and rightmost stripes don't need overlap. + * A flag is passed to ctmf_helper() so that it treats these cases as if the + * image was zero-padded. + */ + int stripes = (int) ceil( (double) (width - 2*r) / (memsize / sizeof(Histogram) - 2*r) ); + int stripe_size = (int) ceil( (double) ( width + stripes*2*r - 2*r ) / stripes ); + + int i; + + for ( i = 0; i < width; i += stripe_size - 2*r ) { + int stripe = stripe_size; + /* Make sure that the filter kernel fits into one stripe. */ + if ( i + stripe_size - 2*r >= width || width - (i + stripe_size - 2*r) < 2*r+1 ) { + stripe = width - i; + } + + ctmf_helper( src + cn*i, dst + cn*i, stripe, height, src_step, dst_step, r, cn, + i == 0, stripe == width - i ); + + if ( stripe == width - i ) { + break; + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/ctmf/ctmf.h b/branches/V-1.5.3/veejay-server/libvje/ctmf/ctmf.h new file mode 100644 index 00000000..5268f973 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/ctmf/ctmf.h @@ -0,0 +1,19 @@ +#ifndef CTMF_H +#define CTMF_H + +#ifdef __cplusplus +extern "C" { +#endif + +void ctmf( + const unsigned char* src, unsigned char* dst, + int width, int height, + int src_step_row, int dst_step_row, + int r, int channels, unsigned long memsize + ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/autoeq.c b/branches/V-1.5.3/veejay-server/libvje/effects/autoeq.c new file mode 100644 index 00000000..c7c192e8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/autoeq.c @@ -0,0 +1,93 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "autoeq.h" +#include +#include "common.h" +vj_effect *autoeq_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->defaults[0] = 0; // y only, v only, u only, all + ve->defaults[1] = 200; // intensity + ve->defaults[2] = 132; // strength + + ve->description = "Automatic Histogram Equalizer"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Channel (Y,U,V,All)","Intensity","Strength"); + return ve; +} + +static void *histogram_ = NULL; + +int autoeq_malloc(int w, int h) +{ + if( histogram_ ) + veejay_histogram_del(histogram_); + histogram_ = veejay_histogram_new(); + return 1; +} + +void autoeq_free() +{ + if( histogram_ ) + veejay_histogram_del(histogram_); + histogram_ = NULL; +} + + +void autoeq_apply( VJFrame *frame, int width, int height, int val, int intensity, int strength) +{ + if( val == 0 ) + { + VJFrame tmp; + veejay_memcpy( &tmp, frame, sizeof(VJFrame)); + tmp.data[0] = (uint8_t*) vj_malloc( sizeof(uint8_t) * frame->len ); + veejay_memcpy( tmp.data[0], frame->data[0], frame->len ); + + veejay_histogram_draw( histogram_,&tmp, frame, intensity, strength ); + + veejay_memset( frame->data[1], 128, frame->uv_len ); + veejay_memset( frame->data[2], 128, frame->uv_len ); + + free(tmp.data[0]); + } + else + { + veejay_histogram_analyze( histogram_, frame, 0 ); + veejay_histogram_equalize( histogram_, frame, intensity, strength ); + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/autoeq.h b/branches/V-1.5.3/veejay-server/libvje/effects/autoeq.h new file mode 100644 index 00000000..9ac16fef --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/autoeq.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef AUTOEQ_H +#define AUTOEQ_H +#include +#include +#include + +vj_effect *autoeq_init(int w, int h); +int autoeq_malloc(int w , int h ); +void autoeq_free( ); +void autoeq_apply( VJFrame *frame, int width, int height, int val, int intensity, int strength); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/average.c b/branches/V-1.5.3/veejay-server/libvje/effects/average.c new file mode 100644 index 00000000..9872c859 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/average.c @@ -0,0 +1,70 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "average.h" +#include "common.h" +vj_effect *average_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 100; + ve->defaults[0] = 1; + ve->description = "Average"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value"); + return ve; +} + +void average_apply(VJFrame *frame, int width, int height, int val) +{ + unsigned int i; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + int a,b; + + for (i = 0; i < len; i++) { + a = Y[i]; + b = ((val-1) * a + a)/val; + Y[i] = CLAMP_Y(b); + } + + for (i = 0; i < uv_len; i++) { + a = Cb[i]; + b = ((val-1) * a + a)/val; + Cb[i] = CLAMP_UV(b); + a = Cr[i]; + b = ((val-1) * a + a )/val; + Cr[i] = CLAMP_UV(b); + } +} +void average_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/average.h b/branches/V-1.5.3/veejay-server/libvje/effects/average.h new file mode 100644 index 00000000..9312abeb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/average.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef AVERAGE_H +#define AVERAGE_H +#include +#include +#include + +vj_effect *average_init(); +void average_apply(VJFrame *src, int width, int height, int val); +void average_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/balls.c b/branches/V-1.5.3/veejay-server/libvje/effects/balls.c new file mode 100644 index 00000000..96c92f67 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/balls.c @@ -0,0 +1,456 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* Copyright (C) 2002-2003 W.P. van Paassen - peter@paassen.tmfweb.nl + + 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; see the file COPYING. If not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + + blob , originally from the demo effect collection + extended to video boids. the boids are an implementation of + Craig Reynolds's BOIDS behavioral algorithm + (http://www.vergenet.net/~conrad/boids/pseudocode.html) + + p0: radius + p1: number of blobs + p2: shape (rect,circle) + p3: influence boids trying to fly towards centre of mass of neighbouring boids + p4: influence boids trying to keep a small distance away from other boids + p5: influence boids trying to match velocity with near boids + p6: speed limiter + p7: home position distance to center point + + added optional flock rules: + + limiting speed + +*/ + +#include +#include +#include +#include +#include "common.h" +#include "blob.h" + + +typedef struct +{ + short x; // x + short y; // y + double vx; // velocity x + double vy; // velocity y +} blob_t; + +#define DEFAULT_RADIUS 16 +#define DEFAULT_NUM 100 + +#define BLOB_RECT 0 +#define BLOB_CIRCLE 1 + +static blob_t *blobs_; +static uint8_t **blob_; +static uint8_t *blob_image_; + +static int blob_ready_ = 0; +static int blob_radius_ = 16; +static int blob_dradius_ = 0; +static int blob_sradius_ = 0; +static int blob_num_ = 100; +static int blob_type_ = 1; +static int blob_home_radius_= 203; + +vj_effect *boids_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 8; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = w/2; // radius + ve->limits[0][1] = 2; + ve->limits[1][1] = 256; // num blobs + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; // shape + ve->limits[0][3] = 0; + ve->limits[1][3] = 100; // m1 + ve->limits[0][4] = 0; + ve->limits[1][4] = 100; // m2 + ve->limits[0][5] = 0; + ve->limits[1][5] = 100; // m3 + ve->limits[0][6] = 1; + ve->limits[1][6] = 100; + ve->limits[0][7] = 1; + ve->limits[1][7] = 360; + ve->defaults[0] = DEFAULT_RADIUS; + ve->defaults[1] = DEFAULT_NUM; + ve->defaults[2] = 1; + ve->defaults[3] = 1; + ve->defaults[4] = 0; + ve->defaults[5] = 0; + ve->defaults[6] = 199; + ve->defaults[7] = w/4; + + ve->description = "Video Boids"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user =0; + ve->param_description = vje_build_param_list( ve->num_params, "Radius", "Blobs", "Shape", "Cohesion","Seperation","Alignment","Speed", "Home Radius"); + return ve; +} + + + + +static void blob_home_position( int blob_id, int w, int h , double v[2] ) +{ + double theta = 360.0 / ( (double) blob_num_ ) * blob_id; + double rad = (theta / 180.0 ) * M_PI; + double ratio = (w/h); + double cx = ( double )( w/ 2); + double cy = ( double )( h/ 2) * ratio; + v[0] = cx + cos(rad) * blob_home_radius_; + v[1] = cy + sin(rad) * blob_home_radius_; +} + +static void blob_init_( blob_t *b , int blob_id, int w , int h) +{ + double v[2]; + + blob_home_position( blob_id,w,h,v ); + + b->x = v[0]; + b->y = v[1]; + b->vx = 0.01; + b->vy = 0.01; +} +// FIXME private +int boids_malloc(int w, int h) +{ + int j,i; + double frac; + int dist_sqrt; + + if(blob_radius_ <= 0) + return 0; + + blob_dradius_ = blob_radius_ * 2; + blob_sradius_ = blob_radius_ * blob_radius_; + + blob_ = (uint8_t**) vj_malloc(sizeof(uint8_t*) * blob_dradius_ ); + for(i = 0; i < blob_dradius_ ; i ++ ) + { + blob_[i] = (uint8_t*) vj_calloc(sizeof(uint8_t) * blob_dradius_ ); + if(!blob_[i]) return 0; + } + + blobs_ = (blob_t*) vj_calloc(sizeof(blob_t) * blob_num_ ); + if(!blobs_ ) return 0; + + blob_image_ = (uint8_t*) vj_calloc(sizeof(uint8_t) * w * h ); + if(!blob_image_) return 0; + + + for( i = -blob_radius_ ; i < blob_radius_ ; ++ i ) + { + for( j = -blob_radius_ ; j < blob_radius_ ; ++ j ) + { + dist_sqrt = i * i + j * j; + if( dist_sqrt < blob_sradius_ ) + { + frac = (double) (sqrt(dist_sqrt)) / (double) blob_sradius_; + blob_[i + blob_radius_][j + blob_radius_] = 0xff; + } + else + { + blob_[i + blob_radius_][j + blob_radius_ ] = 0x0; // was 0 + } + } + } + + for( i = 0; i < blob_num_ ; i ++ ) + { + blob_init_( blobs_ + i ,i, w , h ); + } + + veejay_memset( blob_image_ , 0 , w * h ); + + blob_ready_ = 1; + + return 1; +} + + +void boids_free() +{ + int i; + for (i = 0; i < blob_dradius_ ; i ++ ) + if( blob_[i] ) free( blob_[i] ); + if(blobs_) + free(blobs_); + if(blob_image_) + free(blob_image_); +} + +typedef void (*blob_func)(int s, int width); + +static int blob_collision( blob_t b, blob_t this ) +{ + int dx = this.x - b.x; + int dy = this.y - b.y; + double dvx = this.vx - b.vx; + double dvy = this.vy - b.vy; + double D = dx * dx + dy * dy; + + if( abs( dx ) > this.d || abs(dy) > this.d ) + return 0; + if( D > this.d2 ) + return 0; + + + double mag = dvx * dx + dvy * dy; + + if( mag > 0 ) + return 0; + + mag /= D; + + double ovx = dx * mag; + double ovy = dy * mag; + + + this.vx -= ovx; + this.vy -= ovy; + + b.vx += ovx; + b.vy += ovy; + + return 1; +} + +static void blob_render_circle(int s, int width) +{ + int i,j; + for( i = 0; i < blob_dradius_ ; ++ i ) + { + for( j = 0; j < blob_dradius_ ; ++ j) + { + if( blob_image_[ s + j ] + blob_[i][j] > 255 ) + blob_image_[s + j] = 0xff; + else + blob_image_[s + j] += blob_[i][j]; + } + s += width; + } +} + +static void blob_render_rect(int s, int width) +{ + int i,j; + for( i = 0; i < blob_dradius_ ; ++ i ) + { + for( j = 0; j < blob_dradius_ ; ++ j) + { + blob_image_[s + j] = 0xff; + } + s += width; + } +} + +static blob_func blob_render(void) +{ + if( blob_type_ == BLOB_RECT) + return blob_render_rect; + return blob_render_circle; +} + + +// calculate center of mass +static void boid_rule1_( int boid_id, double v1[2] ) +{ + int i; + double v[2] = { 0.0, 0.0 }; + for( i = 0; i < blob_num_ ; i ++ ) + { + if( i != boid_id ) + { + v[0] += (double) blobs_[i].x; + v[1] += (double) blobs_[i].y; + } + } + v[0] = v[0] / ( (double) blob_num_ - 1 ); + v[1] = v[1] / ( (double) blob_num_ - 1 ); + v1[0] = (v[0] - ((double)blobs_[boid_id].x)) / 100.0; + v1[1] = (v[1] - ((double)blobs_[boid_id].y)) / 100.0; +} + + +// try to keep a small distance away from other blobs +static void boid_rule2_( int boid_id, double v1[2] ) +{ + double v[2] = {0.0 , 0.0}; + int i; + for( i = 0; i < blob_num_; i ++ ) + { + if( i != boid_id) + { + // find nearby blob + double d = ( blobs_[boid_id].x - blobs_[i].x ) * ( blobs_[boid_id].x - blobs_[i].x ) + + ( blobs_[boid_id].y - blobs_[i].y ) * ( blobs_[boid_id].y - blobs_[i].y ); + + if( d < blob_sradius_ ) + { + v[0] = v[0] - ((double) ( blobs_[boid_id].x - blobs_[i].x )); + v[1] = v[1] - ((double) ( blobs_[boid_id].y - blobs_[i].y )); + } + } + } + v1[0] = v[0]; + v1[1] = v[1]; +} + +// try to match velocity with near blobs +static void boid_rule3_( int boid_id, double v1[2] ) +{ + double v[2] = { 0.0, 0.0 }; + int i; + for( i = 0; i < blob_num_; i ++ ) + { + if( boid_id != i ) + { + v[0] = v[0] + blobs_[i].vx; + v[1] = v[1] + blobs_[i].vy; + } + } + v1[0] = v[0] /( (double)( blob_num_ -1 )); + v1[0] = ( v[0] - blobs_[boid_id].vx ) / 8; + v1[1] = v[1] /( (double)( blob_num_ -1 )); + v1[1] = ( v[1] - blobs_[boid_id].vy ) / 8; +} + +static void boid_rule4_( int boid_id, int vlim ) +{ + // speed limiter + if( blobs_[boid_id].vx > vlim ) + blobs_[boid_id].vx = ( blobs_[boid_id].vx / fabs( blobs_[boid_id].vx) ) * vlim; + if( blobs_[boid_id].vy > vlim ) + blobs_[boid_id].vy = ( blobs_[boid_id].vy / fabs( blobs_[boid_id].vy) ) * vlim; +} + +void boids_apply(VJFrame *frame, + int width, int height, int radius, int num, int shape, int m1, int m2, int m3, int speed, int home_radius ) +{ + const int len = frame->len; + uint8_t *srcY = frame->data[0]; + uint8_t *srcCb= frame->data[1]; + uint8_t *srcCr= frame->data[2]; + int s,i,j,k; + const double M1 = ( (m1==0? 0.0 : m1/100.0) ); + const double M2 = ( (m2==0? 0.0 : m2/100.0) ); + const double M3 = ( (m3==0? 0.0 : m3/100.0) ); + + blob_func f = blob_render(); + + blob_type_ = shape; + + if( radius != blob_radius_ || num != blob_num_ ) + { // reinitialize + blob_radius_ = radius; + blob_num_ = num; + boids_free(); + boids_malloc(width,height); + } + + if( home_radius != blob_home_radius_ ) + { + blob_home_radius_ = home_radius; + for( i = 0; i < blob_num_ ; i ++ ) + blob_init_(blobs_ + i , i, width, height); + } + + // move boid to new positions + for( i = 0; i < blob_num_; i ++) + { + double v1[2],v2[2],v3[2]; + + boid_rule1_( i, v1 ); + boid_rule2_( i, v2 ); + boid_rule3_( i, v3 ); + + v1[0] *= M1; + v1[1] *= M1; + v2[0] *= M2; + v2[1] *= M2; + v3[0] *= M3; + v3[1] *= M3; + + blobs_[i].vx = blobs_[i].vx + v1[0] + v2[0] + v3[0]; + blobs_[i].vy = blobs_[i].vy + v1[1] + v2[1] + v3[1]; + + boid_rule4_( i, speed * speed ); + + blobs_[i].x = blobs_[i].x + (short) blobs_[i].vx; + blobs_[i].y = blobs_[i].y + (short) blobs_[i].vy; + + } + + // fill blob + for( k = 0; k < blob_num_ ; k ++ ) + { + if( (blobs_[k].x > 0) && + (blobs_[k].x < (width - blob_dradius_)) && + (blobs_[k].y > 0) && + (blobs_[k].y < (height - blob_dradius_)) ) + { + s = blobs_[k].x + blobs_[k].y * width; + f(s,width); + } + else + { + blob_init_( blobs_ + k,k,width ,height ); + } + } + + // project blob onto video frame + for(i = 0; i < len ; i ++ ) + { + if( blob_image_[i] == 0x0 ) + { + srcY[i] = 16; + srcCb[i] = 128; + srcCr[i] = 128; + } + blob_image_[i] = 0x0; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/baltantv.c b/branches/V-1.5.3/veejay-server/libvje/effects/baltantv.c new file mode 100644 index 00000000..872ac00d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/baltantv.c @@ -0,0 +1,123 @@ +/* + * Linux VeeJay + * + * EffecTV - Realtime Digital Video Effector + * Copyright (C) 2001-2006 FUKUCHI Kentaro + * + * BaltanTV - like StreakTV, but following for a long time + * Copyright (C) 2001-2002 FUKUCHI Kentaro + * Ported to veejay by Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "baltantv.h" +#include "common.h" + +vj_effect *baltantv_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 16; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->defaults[0] = 8; + ve->defaults[1] = 0; + ve->description = "BaltanTV (EffecTV)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Stride", "Mode" ); + return ve; +} + +static unsigned int plane_ = 0; + +#define PLANES 64 + +static uint8_t *planetable_ = NULL; + +int baltantv_malloc(int w, int h) +{ + if( planetable_ ) + free(planetable_ ); + planetable_ = (uint8_t*) vj_malloc( sizeof(uint8_t*) * PLANES * (w * h )); + if(!planetable_) { + veejay_msg(0,"Not enough memory to allocate %d planes of size %dx%d", PLANES,w,h); + return 0; + } + + return 1; +} + +void baltantv_free() +{ + plane_ = 0; + if(planetable_) + free(planetable_); + planetable_ = NULL; +} + +void baltantv_apply( VJFrame *frame, int width, int height, int stride, int mode) +{ + unsigned int i,cf; + const int len = (width * height); + uint8_t *Y = frame->data[0]; + uint8_t *pDst = planetable_ + (plane_ * frame->len); + + for( i = 0; i < len ; i ++ ) + pDst[i] = (Y[i] >> 2 ); + + cf = plane_ & (stride-1); + + uint8_t *pSrc[4] = { + planetable_ + (cf * frame->len), + planetable_ + ((cf+stride) * frame->len), + planetable_ + ((cf+stride*2) * frame->len), + planetable_ + ((cf+stride*3) * frame->len) + }; + + if( mode == 0 ) + { + for( i = 0; i < len; i ++ ) + { + Y[i] = pSrc[0][i] + + pSrc[1][i] + + pSrc[2][i] + + pSrc[3][i]; + pDst[i] = (Y[i] >> 2 ); + } + } + else + { + for( i = 0; i < len ; i++ ) + { + Y[i] = pSrc[0][i] + + pSrc[1][i] + + pSrc[2][i] + + pSrc[3][i]; + } + } + plane_ ++; + + plane_ = plane_ & (PLANES-1); +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/baltantv.h b/branches/V-1.5.3/veejay-server/libvje/effects/baltantv.h new file mode 100644 index 00000000..7c0f5a3b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/baltantv.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BALTAN_TVH +#define BALTAN_TVH +#include +#include +#include + +vj_effect *baltantv_init(int w, int h); +void baltantv_apply( VJFrame *frame, int width, int height, int stride, int mode); +int baltantv_malloc(int w, int h ); +void baltantv_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/bathroom.c b/branches/V-1.5.3/veejay-server/libvje/effects/bathroom.c new file mode 100644 index 00000000..67238d26 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/bathroom.c @@ -0,0 +1,177 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +/* + shift pixels in row/column to get a 'bathroom' window look. Use the parameters + to set the distance and mode + + */ +#include +#include +#include +#include +#include +#include "bathroom.h" +#include "common.h" +static uint8_t *bathroom_frame[3]; + +vj_effect *bathroom_init(int width,int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->limits[0][1] = 1; + ve->limits[1][1] = 64; + ve->defaults[0] = 1; + ve->defaults[1] = 32; + ve->description = "Bathroom Window"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "H or V", "Value" ); + return ve; +} + +static int n__ = 0; +static int N__ = 0; +// FIXME private + +int bathroom_malloc(int width, int height) +{ + bathroom_frame[0] = (uint8_t*)vj_yuvalloc( width, height ); + if(!bathroom_frame[0]) return 0; + + bathroom_frame[1] = bathroom_frame[0] + (width * height ); + bathroom_frame[2] = bathroom_frame[1] + (width * height ); + n__ = 0; + N__ = 0; + return 1; +} + +void bathroom_free() { + if(bathroom_frame[0]) + free(bathroom_frame[0]); + bathroom_frame[0] = NULL; + bathroom_frame[1] = NULL; + bathroom_frame[2] = NULL; +} + +void bathroom_verti_apply(VJFrame *frame, int width, int height, int val) +{ + unsigned int i; + const unsigned int len = frame->len; + unsigned int y_val = val; + unsigned int x,y; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + veejay_memcpy( bathroom_frame[0], Y, len); + veejay_memcpy( bathroom_frame[1], Cb, len); + veejay_memcpy( bathroom_frame[2], Cr, len); + + if( y_val <= 0 ) + y_val = 1; + + for(y=0; y < height;y++) { + for(x=0; x >1)) + (y*width); + if(i < 0) i = 0; + if(i >= len) i = len-1; + Y[y*width+x] = bathroom_frame[0][i]; + Cb[y*width+x] = bathroom_frame[1][i]; + Cr[y*width+x] = bathroom_frame[2][i]; + } + } + +} + + +void bathroom_hori_apply(VJFrame *frame, int width, int height, int val) +{ + unsigned int i; + unsigned int len = (width * height); + unsigned int y_val = val; + unsigned int tmp = 0; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + unsigned int x,y; + veejay_memcpy( bathroom_frame[0], Y, len); + veejay_memcpy( bathroom_frame[1], Cb, len); + veejay_memcpy( bathroom_frame[2], Cr, len); + + for(y=0; y < height;y++) { + for(x=0; x >1)) + x; + //while(i < 0) i += width; + + if( i < 0 ) i = 0; else if ( i >= len ) i = (len-1); + + Y[(y*width)+x] = bathroom_frame[0][i]; + Cb[(y*width)+x] = bathroom_frame[1][i]; + Cr[(y*width)+x] = bathroom_frame[2][i]; + } + } + +} + +void bathroom_apply(VJFrame *frame, int width, int height, int mode, int val) { + + int interpolate = 1; + int tmp1 = val; + int tmp2 = 0; + int motion = 0; + if(motionmap_active()) + { + motionmap_scale_to( 64, 64, 1, 1, &tmp1, &tmp2, &n__, &N__ ); + motion = 1; + } + else + { + N__ = 0; + n__ = 0; + } + if( n__ == N__ || n__ == 0 ) + interpolate = 0; + + switch(mode) + { + case 1: bathroom_hori_apply(frame,width,height,tmp1); break; + case 0: bathroom_verti_apply(frame,width,height,tmp1); break; + } + + if( interpolate ) + { + motionmap_interpolate_frame( frame, N__,n__ ); + } + + if(motion) + { + motionmap_store_frame( frame ); + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/bathroom.h b/branches/V-1.5.3/veejay-server/libvje/effects/bathroom.h new file mode 100644 index 00000000..6cbded97 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/bathroom.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BATHROOM_H +#define BATHROOM_H +#include +#include +#include + +vj_effect *bathroom_init(int w, int h); +int bathroom_malloc(int w, int h); +void bathroom_free(); +void bathroom_apply(VJFrame *Frame, int width, int height,int mode, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/bgsubtract.c b/branches/V-1.5.3/veejay-server/libvje/effects/bgsubtract.c new file mode 100644 index 00000000..2a9561d3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/bgsubtract.c @@ -0,0 +1,137 @@ +/* + * Linux VeeJay + * + * Copyright(C)2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "bgsubtract.h" +#include "common.h" +#include +#include +#include +#include "softblur.h" +static uint8_t *static_bg = NULL; + +vj_effect *bgsubtract_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; /* threshold */ + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; /* mode */ + ve->limits[1][1] = 1; + + ve->defaults[0] = 45; + ve->defaults[1] = 0; + + ve->description = "Substract background (static, requires bg mask)"; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 1; + ve->user_data = NULL; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Mode"); + return ve; +} + +#define rup8(num)(((num)+8)&~8) +int bgsubtract_malloc(int width, int height) +{ + if(static_bg == NULL) + static_bg = (uint8_t*) vj_calloc( rup8( width + width * height * sizeof(uint8_t)) ); + return 1; +} + +void bgsubtract_free(void *d) +{ + if( static_bg ) + free(static_bg ); + static_bg = NULL; +} + +int bgsubtract_prepare(uint8_t *map[3], int width, int height) +{ + if(!static_bg ) + { + return 0; + } + + //@ copy the iamge + veejay_memcpy( static_bg, map[0], (width*height)); + + VJFrame tmp; + veejay_memset( &tmp, 0, sizeof(VJFrame)); + tmp.data[0] = static_bg; + tmp.width = width; + tmp.height = height; + + //@ 3x3 blur + softblur_apply( &tmp, width,height,0); + + veejay_msg(2, "Substract background: Snapped background frame"); + return 1; +} + +static void binarify( uint8_t *dst, uint8_t *bg, uint8_t *src,int threshold,int reverse, const int len ) +{ + int i; + + if(!reverse) + for( i = 0; i < len; i ++ ) { + if ( abs(bg[i] - src[i]) >= threshold ) + dst[i] = 0xff; + else + dst[i] = 0; + } + else + for( i = 0; i < len; i ++ ) { + if ( abs(bg[i] - src[i]) >= threshold ) + dst[i] = 0; + else + dst[i] = 0xff; + } +} + +void bgsubtract_apply(VJFrame *frame,int width, int height, int threshold, int mode ) +{ + VJFrame tmp; + veejay_memset( &tmp, 0, sizeof(VJFrame)); + tmp.data[0] = frame->data[0]; + tmp.width = width; + tmp.height = height; + + //@ 3x3 blur + softblur_apply( &tmp, width,height,0); + + if ( mode == 0 ) { + binarify( frame->data[0], static_bg,frame->data[0], threshold, 0, width*height ); + } else if ( mode == 1 ) { + binarify( frame->data[0], static_bg, frame->data[0], threshold, 1,width*height ); + } + + veejay_memset( frame->data[1], 128, frame->uv_len ); + veejay_memset( frame->data[2], 128, frame->uv_len ); + +} + + + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/bgsubtract.h b/branches/V-1.5.3/veejay-server/libvje/effects/bgsubtract.h new file mode 100644 index 00000000..bfb79da5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/bgsubtract.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BGSUBTRACT_H +#define BGSUBTRACT_H +#include +#include +#include + +vj_effect *bgsubtract_init(int width, int height); +void bgsubtract_free(void *d); +int bgsubtract_malloc(int w, int h); +int bgsubtract_prepare(uint8_t *map[3], int w, int h); +void bgsubtract_apply(VJFrame *frame,int width,int height,int mode, int threshold); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/binaryoverlays.c b/branches/V-1.5.3/veejay-server/libvje/effects/binaryoverlays.c new file mode 100644 index 00000000..b1fbce98 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/binaryoverlays.c @@ -0,0 +1,317 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "binaryoverlays.h" +#include + +vj_effect *binaryoverlay_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + ve->description = "Binary Overlays"; + ve->limits[0][0] = 0; + ve->limits[1][0] = 10; + ve->extra_frame = 1; + ve->sub_format = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode"); + return ve; +} + +/* rename methods in lumamagick and chromamagick */ + +static void _binary_not_and( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = ~(Y[i]) & ~(Y2[i]); + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + (~(Cb[i]-128) & ~(Cb2[i]-128)); + Cr[i] = 128 + (~(Cr[i]-128) & ~(Cr2[i]-128)); + } +} +static void _binary_not_xor( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = ~(Y[i]) ^ ~(Y2[i]); + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + (~(Cb[i]-128) ^ ~(Cb2[i]-128)); + Cr[i] = 128 + (~(Cr[i]-128) ^ ~(Cr2[i]-128)); + } +} + +static void _binary_not_or( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = ~(Y[i]) | ~(Y2[i]); + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + ( ~(Cb[i]-128) | ~(Cb2[i]-128) ); + Cr[i] = 128 + (~(Cr[i]-128) | ~(Cr2[i]-128) ); + } +} + +// this is also sub, sub = A & ~(B) +static void _binary_not_and_lh( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + int i; + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + for(i=0; i < len; i++) + { + Y[i] = Y[i] & ~(Y2[i]); + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + (Cb[i]-128 & ~(Cb2[i])); + Cr[i] = 128 + (Cr[i] & ~(Cr2[i])); + } +} +static void _binary_not_xor_lh( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = Y[i] ^ ~(Y2[i]); + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + ( Cb[i]-128 ^ ~(Cb2[i]-128 )); + Cr[i] = 128 + ( Cr[i]-128 ^ ~(Cr2[i]-128)); + } +} + +static void _binary_not_or_lh( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = Y[i] | ~(Y2[i]); + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + ( Cb[i]-128 | ~(Cb2[i]-128)); + Cr[i] = 128 + ( Cr[i]-128 | ~(Cr2[i]-128)); + } +} +static void _binary_not_and_rh( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = ~(Y[i]) & Y2[i]; + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + ( ~(Cb[i]-128) & Cb2[i]-128); + Cr[i] = 128 + ( ~(Cr[i]-128) & Cr2[i]-128); + } +} +static void _binary_not_xor_rh( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = ~(Y[i]) ^ Y2[i]; + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + ( ~(Cb[i]-128) ^ Cb2[i]-128); + Cr[i] = 128 + (~(Cr[i]-128) ^ Cr2[i]-128); + } +} + +static void _binary_not_or_rh( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int i; + for(i=0; i < len; i++) + { + Y[i] = ~(Y[i]) | Y2[i]; + } + for(i=0; i < uv_len; i++) + { + Cb[i] = 128 + ( ~(Cb[i]-128) | Cb2[i]-128); + Cr[i] = 128 + ( ~(Cr[i]-128) | Cr2[i]-128); + } +} + + + + +static void _binary_or( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + + int i; + for(i=0; i < len; i++) + Y[i] = Y[i] | Y2[i]; + for(i=0; i < uv_len; i++) + { + Cb[i] = Cb[i] | Cb2[i]; + Cr[i] = Cr[i] | Cr2[i]; + } +} +static void _binary_and( VJFrame *frame, VJFrame *frame2, int w, int h ) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + + int i; + for(i=0; i < len; i++) + Y[i] = Y[i] & Y2[i]; + for(i=0; i < uv_len; i++) + { + Cb[i] = Cb[i] & Cb2[i]; + Cr[i] = Cr[i] & Cr2[i]; + } +} + + + +void binaryoverlay_apply( VJFrame *frame, VJFrame *frame2, int w, int h, int mode ) +{ + switch(mode) + { + case 0: _binary_not_and( frame,frame2,w,h ); break;// not a and not b + case 1: _binary_not_or( frame,frame2,w,h); break; // not a or not b + case 2: _binary_not_xor( frame,frame2,w,h); break; // not a xor not b + case 3: _binary_not_and_lh( frame,frame2,w,h ); break; // a and not b + case 4: _binary_not_or_lh( frame,frame2,w,h); break; // a or not b + case 5: _binary_not_xor_lh( frame,frame2,w,h); break; // a xor not b + case 6: _binary_not_and_rh (frame,frame2,w,h); break; // a and not b + case 7: _binary_not_or_rh( frame,frame2,w,h); break; // a or not b + case 8: _binary_or( frame,frame2,w,h); break; // a or b + case 9: _binary_and( frame,frame2,w,h); break; // a and b + case 10: _binary_not_xor_rh(frame,frame2,w,h); break; + } +} + +void binaryoverlay_free() {} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/binaryoverlays.h b/branches/V-1.5.3/veejay-server/libvje/effects/binaryoverlays.h new file mode 100644 index 00000000..63eb2842 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/binaryoverlays.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BINARYOVERLAYS_H +#define BINARYOVERLAYS_H +#include +#include +#include + +vj_effect *binaryoverlay_init(int w, int h); + +void binaryoverlay_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n); + +void magicoverlays_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/blob.c b/branches/V-1.5.3/veejay-server/libvje/effects/blob.c new file mode 100644 index 00000000..59ffede0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/blob.c @@ -0,0 +1,275 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* Copyright (C) 2002-2003 W.P. van Paassen - peter@paassen.tmfweb.nl + + 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; see the file COPYING. If not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + + blob , originally from the demo effect collection + easily modified to videoblob + p0: radius + p1: number of blobs + p2: speed + p3: shape (rect,circle) + + the number of blobs and size of radius determine amount of work for cpu. + +*/ + +#include +#include +#include +#include +#include "common.h" +#include "blob.h" + +typedef struct +{ + short x; + short y; +} blob_t; + +#define DEFAULT_RADIUS 16 +#define DEFAULT_NUM 50 + +#define BLOB_RECT 0 +#define BLOB_CIRCLE 1 + +static blob_t *blobs_; +static uint8_t **blob_; +static uint8_t *blob_image_; +static int blob_ready_ = 0; +static int blob_radius_ = 16; +static int blob_dradius_ = 0; +static int blob_sradius_ = 0; +static int blob_num_ = 50; +static int blob_type_ = 1; + +vj_effect *blob_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 360; // radius + ve->limits[0][1] = 1; + ve->limits[1][1] = 100; // num blobs + ve->limits[0][2] = 1; + ve->limits[1][2] = 100; // speed + ve->limits[0][3] = 0; + ve->limits[1][3] = 1; // shape + ve->defaults[0] = DEFAULT_RADIUS; + ve->defaults[1] = DEFAULT_NUM; + ve->defaults[2] = 50; + ve->defaults[3] = 1; + ve->description = "Video Blobs"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user =0; + ve->param_description = vje_build_param_list( ve->num_params, "Radius", "Blobs", "Speed" , "Shape"); + return ve; +} +static void blob_init_( blob_t *b , int w , int h) +{ + b->x = (w >> 1) - blob_radius_; + b->y = (h >> 1) - blob_radius_; +} +// FIXME private +int blob_malloc(int w, int h) +{ + int j,i; + double frac; + int dist_sqrt; + + if(blob_radius_ <= 0) + return 0; + + blob_dradius_ = blob_radius_ * 2; + blob_sradius_ = blob_radius_ * blob_radius_; + + blob_ = (uint8_t**) vj_malloc(sizeof(uint8_t*) * blob_dradius_ ); + for(i = 0; i < blob_dradius_ ; i ++ ) + { + blob_[i] = (uint8_t*) vj_calloc(sizeof(uint8_t) * blob_dradius_ ); + if(!blob_[i]) return 0; + } + + blobs_ = (blob_t*) vj_calloc(sizeof(blob_t) * blob_num_ ); + if(!blobs_ ) return 0; + + blob_image_ = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!blob_image_) return 0; + + for( i = -blob_radius_ ; i < blob_radius_ ; ++ i ) + { + for( j = -blob_radius_ ; j < blob_radius_ ; ++ j ) + { + dist_sqrt = i * i + j * j; + if( dist_sqrt < blob_sradius_ ) + { + frac = (double) (sqrt(dist_sqrt)) / (double) blob_sradius_; + blob_[i + blob_radius_][j + blob_radius_] = 0xff; + } + else + { + blob_[i + blob_radius_][j + blob_radius_ ] = 0x0; // was 0 + } + } + } + + for( i = 0; i < blob_num_ ; i ++ ) + { + blob_init_( blobs_ + i , w , h ); + } + + veejay_memset( blob_image_ , 0 , w * h ); + + blob_ready_ = 1; + + return 1; +} + + +void blob_free() +{ + int i; + for (i = 0; i < blob_dradius_ ; i ++ ) + if( blob_[i] ) free( blob_[i] ); + if(blobs_) + free(blobs_); + if(blob_image_) + free(blob_image_); + blobs_ = NULL; + blob_image_ = NULL; +} + +typedef void (*blob_func)(int s, int width); + +static void blob_render_circle(int s, int width) +{ + int i,j; + for( i = 0; i < blob_dradius_ ; ++ i ) + { + for( j = 0; j < blob_dradius_ ; ++ j) + { + if( blob_image_[ s + j ] + blob_[i][j] > 255 ) + blob_image_[s + j] = 0xff; + else + blob_image_[s + j] += blob_[i][j]; + } + s += width; + } +} + +static void blob_render_rect(int s, int width) +{ + int i,j; + for( i = 0; i < blob_dradius_ ; ++ i ) + { + for( j = 0; j < blob_dradius_ ; ++ j) + { + blob_image_[s + j] = 0xff; + } + s += width; + } +} + +static blob_func blob_render(void) +{ + if( blob_type_ == BLOB_RECT) + return &blob_render_rect; + return &blob_render_circle; +} + +void blob_apply(VJFrame *frame, + int width, int height, int radius, int num, int speed, int shape) +{ + const int len = frame->len; + uint8_t *srcY = frame->data[0]; + uint8_t *srcCb= frame->data[1]; + uint8_t *srcCr= frame->data[2]; + int i,k; + int s; + double max = speed / 10.0; + blob_func f = blob_render(); + + blob_type_ = shape; + + if( radius != blob_radius_ || num != blob_num_ ) + { // reinitialize + blob_radius_ = radius; + blob_num_ = num; + blob_free(); + blob_malloc(width,height); + } + + // move blob + for( i = 0; i < blob_num_; i ++) + { + blobs_[i].x += -2 + (int) ( max * (rand()/(RAND_MAX+1.0))); + blobs_[i].y += -2 + (int) ( max * (rand()/(RAND_MAX+1.0))); + } + + // fill blob + for( k = 0; k < blob_num_ ; k ++ ) + { + if( (blobs_[k].x > 0) && + (blobs_[k].x < (width - blob_dradius_)) && + (blobs_[k].y > 0) && + (blobs_[k].y < (height - blob_dradius_)) ) + { + s = blobs_[k].x + blobs_[k].y * width; + f(s,width); + } + else + { + blob_init_( blobs_ + k,width ,height ); + } + } + + // project blob onto video frame + for(i = 0; i < len ; i ++ ) + { + if( blob_image_[i] == 0x0 ) + { + srcY[i] = 16; + srcCb[i] = 128; + srcCr[i] = 128; + } + blob_image_[i] = 0x0; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/blob.h b/branches/V-1.5.3/veejay-server/libvje/effects/blob.h new file mode 100644 index 00000000..881029f3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/blob.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BLOB_H +#define BLOB_H +#include +#include +#include + +vj_effect *blob_init(int w, int h); +void blob_apply( VJFrame *frame, int width, int height, int p0,int p1, int p2, int p3); +int blob_malloc( int w, int h ); +void blob_free(void); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/boids.c b/branches/V-1.5.3/veejay-server/libvje/effects/boids.c new file mode 100644 index 00000000..120f4f33 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/boids.c @@ -0,0 +1,423 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* Copyright (C) 2002-2003 W.P. van Paassen - peter@paassen.tmfweb.nl + + 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; see the file COPYING. If not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + + blob , originally from the demo effect collection + extended to video boids. the boids are an implementation of + Craig Reynolds's BOIDS behavioral algorithm + (http://www.vergenet.net/~conrad/boids/pseudocode.html) + + p0: radius + p1: number of blobs + p2: shape (rect,circle) + p3: influence boids trying to fly towards centre of mass of neighbouring boids + p4: influence boids trying to keep a small distance away from other boids + p5: influence boids trying to match velocity with near boids + p6: speed limiter + p7: home position distance to center point + + added optional flock rules: + + limiting speed + +*/ + +#include +#include +#include +#include +#include +#include "common.h" +#include "blob.h" + + +typedef struct +{ + short x; // x + short y; // y + double vx; // velocity x + double vy; // velocity y +} blob_t; + +#define DEFAULT_RADIUS 16 +#define DEFAULT_NUM 100 + +#define BLOB_RECT 0 +#define BLOB_CIRCLE 1 + +static blob_t *blobs_; +static uint8_t **blob_; +static uint8_t *blob_image_; + +static int blob_ready_ = 0; +static int blob_radius_ = 16; +static int blob_dradius_ = 0; +static int blob_sradius_ = 0; +static int blob_num_ = 100; +static int blob_type_ = 1; +static int blob_home_radius_= 203; + +vj_effect *boids_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 8; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = w/2; // radius + ve->limits[0][1] = 2; + ve->limits[1][1] = 256; // num blobs + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; // shape + ve->limits[0][3] = 0; + ve->limits[1][3] = 100; // m1 + ve->limits[0][4] = 0; + ve->limits[1][4] = 100; // m2 + ve->limits[0][5] = 0; + ve->limits[1][5] = 100; // m3 + ve->limits[0][6] = 1; + ve->limits[1][6] = 100; + ve->limits[0][7] = 1; + ve->limits[1][7] = 360; + ve->defaults[0] = DEFAULT_RADIUS; + ve->defaults[1] = DEFAULT_NUM; + ve->defaults[2] = 1; + ve->defaults[3] = 1; + ve->defaults[4] = 0; + ve->defaults[5] = 0; + ve->defaults[6] = 199; + ve->defaults[7] = w/4; + + ve->description = "Video Boids"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user =0; + ve->param_description = vje_build_param_list( ve->num_params, "Radius","Blobs","Shape","Cohesion","Seperation","Alignment","Speed","Home Radius"); + return ve; +} + + + + +static void blob_home_position( int blob_id, int w, int h , double v[2] ) +{ + double theta = 360.0 / ( (double) blob_num_ ) * blob_id; + double rad = (theta / 180.0 ) * M_PI; + double ratio = (w/h); + double cx = ( double )( w/ 2); + double cy = ( double )( h/ 2) * ratio; + v[0] = cx + cos(rad) * blob_home_radius_; + v[1] = cy + sin(rad) * blob_home_radius_; +} + +static void blob_init_( blob_t *b , int blob_id, int w , int h) +{ + double v[2]; + + blob_home_position( blob_id,w,h,v ); + + b->x = v[0]; + b->y = v[1]; + b->vx = 0.01; + b->vy = 0.01; +} +// FIXME private +int boids_malloc(int w, int h) +{ + int j,i; + double frac; + int dist_sqrt; + + if(blob_radius_ <= 0) + return 0; + + blob_dradius_ = blob_radius_ * 2; + blob_sradius_ = blob_radius_ * blob_radius_; + + blob_ = (uint8_t**) vj_malloc(sizeof(uint8_t*) * blob_dradius_ ); + for(i = 0; i < blob_dradius_ ; i ++ ) + { + blob_[i] = (uint8_t*) vj_calloc(sizeof(uint8_t) * blob_dradius_ ); + if(!blob_[i]) return 0; + } + + blobs_ = (blob_t*) vj_calloc(sizeof(blob_t) * blob_num_ ); + if(!blobs_ ) return 0; + + blob_image_ = (uint8_t*) vj_calloc(sizeof(uint8_t) * w * h ); + if(!blob_image_) return 0; + + + for( i = -blob_radius_ ; i < blob_radius_ ; ++ i ) + { + for( j = -blob_radius_ ; j < blob_radius_ ; ++ j ) + { + dist_sqrt = i * i + j * j; + if( dist_sqrt < blob_sradius_ ) + { + frac = (double) (sqrt(dist_sqrt)) / (double) blob_sradius_; + blob_[i + blob_radius_][j + blob_radius_] = 0xff; + } + else + { + blob_[i + blob_radius_][j + blob_radius_ ] = 0x0; // was 0 + } + } + } + + for( i = 0; i < blob_num_ ; i ++ ) + { + blob_init_( blobs_ + i ,i, w , h ); + } + + veejay_memset( blob_image_ , 0 , w * h ); + + blob_ready_ = 1; + + return 1; +} + + +void boids_free() +{ + int i; + for (i = 0; i < blob_dradius_ ; i ++ ) + if( blob_[i] ) free( blob_[i] ); + if(blobs_) + free(blobs_); + if(blob_image_) + free(blob_image_); +} + +typedef void (*blob_func)(int s, int width); + +static void blob_render_circle(int s, int width) +{ + int i,j; + for( i = 0; i < blob_dradius_ ; ++ i ) + { + for( j = 0; j < blob_dradius_ ; ++ j) + { + if( blob_image_[ s + j ] + blob_[i][j] > 255 ) + blob_image_[s + j] = 0xff; + else + blob_image_[s + j] += blob_[i][j]; + } + s += width; + } +} + +static void blob_render_rect(int s, int width) +{ + int i,j; + for( i = 0; i < blob_dradius_ ; ++ i ) + { + for( j = 0; j < blob_dradius_ ; ++ j) + { + blob_image_[s + j] = 0xff; + } + s += width; + } +} + +static blob_func blob_render(void) +{ + if( blob_type_ == BLOB_RECT) + return blob_render_rect; + return blob_render_circle; +} + + +// calculate center of mass +static void boid_rule1_( int boid_id, double v1[2] ) +{ + int i; + double v[2] = { 0.0, 0.0 }; + for( i = 0; i < blob_num_ ; i ++ ) + { + if( i != boid_id ) + { + v[0] += (double) blobs_[i].x; + v[1] += (double) blobs_[i].y; + } + } + v[0] = v[0] / ( (double) blob_num_ - 1 ); + v[1] = v[1] / ( (double) blob_num_ - 1 ); + v1[0] = (v[0] - ((double)blobs_[boid_id].x)) / 100.0; + v1[1] = (v[1] - ((double)blobs_[boid_id].y)) / 100.0; +} + + +// try to keep a small distance away from other blobs +static void boid_rule2_( int boid_id, double v1[2] ) +{ + double v[2] = {0.0 , 0.0}; + int i; + for( i = 0; i < blob_num_; i ++ ) + { + if( i != boid_id) + { + // find nearby blob + double d = ( blobs_[boid_id].x - blobs_[i].x ) * ( blobs_[boid_id].x - blobs_[i].x ) + + ( blobs_[boid_id].y - blobs_[i].y ) * ( blobs_[boid_id].y - blobs_[i].y ); + + if( d < blob_sradius_ ) + { + v[0] = v[0] - ((double) ( blobs_[boid_id].x - blobs_[i].x )); + v[1] = v[1] - ((double) ( blobs_[boid_id].y - blobs_[i].y )); + } + } + } + v1[0] = v[0]; + v1[1] = v[1]; +} + +// try to match velocity with near blobs +static void boid_rule3_( int boid_id, double v1[2] ) +{ + double v[2] = { 0.0, 0.0 }; + int i; + for( i = 0; i < blob_num_; i ++ ) + { + if( boid_id != i ) + { + v[0] = v[0] + blobs_[i].vx; + v[1] = v[1] + blobs_[i].vy; + } + } + v1[0] = v[0] /( (double)( blob_num_ -1 )); + v1[0] = ( v[0] - blobs_[boid_id].vx ) / 8; + v1[1] = v[1] /( (double)( blob_num_ -1 )); + v1[1] = ( v[1] - blobs_[boid_id].vy ) / 8; +} + +static void boid_rule4_( int boid_id, int vlim ) +{ + // speed limiter + if( blobs_[boid_id].vx > vlim ) + blobs_[boid_id].vx = ( blobs_[boid_id].vx / fabs( blobs_[boid_id].vx) ) * vlim; + if( blobs_[boid_id].vy > vlim ) + blobs_[boid_id].vy = ( blobs_[boid_id].vy / fabs( blobs_[boid_id].vy) ) * vlim; +} + +void boids_apply(VJFrame *frame, + int width, int height, int radius, int num, int shape, int m1, int m2, int m3, int speed, int home_radius ) +{ + const int len = frame->len; + uint8_t *srcY = frame->data[0]; + uint8_t *srcCb= frame->data[1]; + uint8_t *srcCr= frame->data[2]; + int s,i,j,k; + const double M1 = ( (m1==0? 0.0 : m1/100.0) ); + const double M2 = ( (m2==0? 0.0 : m2/100.0) ); + const double M3 = ( (m3==0? 0.0 : m3/100.0) ); + + blob_func f = blob_render(); + + blob_type_ = shape; + + if( radius != blob_radius_ || num != blob_num_ ) + { // reinitialize + blob_radius_ = radius; + blob_num_ = num; + boids_free(); + boids_malloc(width,height); + } + + if( home_radius != blob_home_radius_ ) + { + blob_home_radius_ = home_radius; + for( i = 0; i < blob_num_ ; i ++ ) + blob_init_(blobs_ + i , i, width, height); + } + + // move boid to new positions + for( i = 0; i < blob_num_; i ++) + { + double v1[2],v2[2],v3[2]; + + boid_rule1_( i, v1 ); + boid_rule2_( i, v2 ); + boid_rule3_( i, v3 ); + + v1[0] *= M1; + v1[1] *= M1; + v2[0] *= M2; + v2[1] *= M2; + v3[0] *= M3; + v3[1] *= M3; + + blobs_[i].vx = blobs_[i].vx + v1[0] + v2[0] + v3[0]; + blobs_[i].vy = blobs_[i].vy + v1[1] + v2[1] + v3[1]; + + boid_rule4_( i, speed * speed ); + + blobs_[i].x = blobs_[i].x + (short) blobs_[i].vx; + blobs_[i].y = blobs_[i].y + (short) blobs_[i].vy; + + } + + // fill blob + for( k = 0; k < blob_num_ ; k ++ ) + { + if( (blobs_[k].x > 0) && + (blobs_[k].x < (width - blob_dradius_)) && + (blobs_[k].y > 0) && + (blobs_[k].y < (height - blob_dradius_)) ) + { + s = blobs_[k].x + blobs_[k].y * width; + f(s,width); + } + else + { + blob_init_( blobs_ + k,k,width ,height ); + } + } + + // project blob onto video frame + for(i = 0; i < len ; i ++ ) + { + if( blob_image_[i] == 0x0 ) + { + srcY[i] = 16; + srcCb[i] = 128; + srcCr[i] = 128; + } + blob_image_[i] = 0x0; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/boids.h b/branches/V-1.5.3/veejay-server/libvje/effects/boids.h new file mode 100644 index 00000000..0c0ebfb7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/boids.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BOIDS_H +#define BOIDS_H +#include +#include +#include + +vj_effect *boids_init(int w, int h); +void boids_apply( VJFrame *frame, int width, int height, int p0,int p1, int p2, int p3, int p4, int p5, int p6, int p7); +int boids_malloc( int w, int h ); +void boids_free(void); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/borders.c b/branches/V-1.5.3/veejay-server/libvje/effects/borders.c new file mode 100644 index 00000000..12ad0673 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/borders.c @@ -0,0 +1,57 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "borders.h" +#include "common.h" + +vj_effect *borders_init(int width,int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + + ve->defaults[0] = 41; + ve->defaults[1] = 0; + ve->limits[0][0] = 1; + ve->limits[1][0] = (height / 2); + ve->limits[0][1] = 0; + ve->limits[1][1] = 7; + ve->description = "Colored Border Translation"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Size", "Color"); + return ve; +} + +void borders_apply( VJFrame *frame, int width, int height, int size, + int color) +{ + blackborder_yuvdata(frame->data[0], frame->data[1], frame->data[2], + width, height, (size), (size), (size), (size), + frame->shift_h, frame->shift_v,color); + +} +void borders_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/borders.h b/branches/V-1.5.3/veejay-server/libvje/effects/borders.h new file mode 100644 index 00000000..6149dcff --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/borders.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BORDERS_H +#define BORDERS_H +#include +#include +#include + +vj_effect *borders_init(int width,int height); +void borders_apply(VJFrame *frame, int width, int height, int size, + int color); +void borders_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/bwselect.c b/branches/V-1.5.3/veejay-server/libvje/effects/bwselect.c new file mode 100644 index 00000000..695bb99e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/bwselect.c @@ -0,0 +1,76 @@ + +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "bwselect.h" +#include "common.h" +vj_effect *bwselect_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 16; + ve->defaults[1] = 235; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->description = "Black and White by Threshold"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user =0 ; + ve->param_description = vje_build_param_list( ve->num_params, "Min threshold", "Max threshold" ); + return ve; +} + +void bwselect_apply(VJFrame *frame, int width, int height, int min_threshold, int max_threshold) { + int r,c; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + for(r=0; r < len; r+=width) { + for(c=0; c < width; c++) { + uint8_t p = Y[r+c]; + if( p > min_threshold && p < max_threshold) { + Y[r+c] = 235; + } + else { + Y[r+c] = 16; + } + } + } +#ifdef HAVE_ASM_MMX + memset_ycbcr( Cb, Cb, 128, frame->uv_width, frame->uv_height); + memset_ycbcr( Cr, Cr, 128, frame->uv_width, frame->uv_height); +#else + memset(Cb, 128, frame->uv_len); + memset(Cr, 128, frame->uv_len); +#endif +} + +void bwselect_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/bwselect.h b/branches/V-1.5.3/veejay-server/libvje/effects/bwselect.h new file mode 100644 index 00000000..39255289 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/bwselect.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BWSELECT_H +#define BWSELECT_H +#include +#include +#include + +vj_effect *bwselect_init(); +void bwselect_apply(VJFrame *frame, int width, int height, int min_threshold, + int max_threshold); +void bwselect_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/cali.c b/branches/V-1.5.3/veejay-server/libvje/effects/cali.c new file mode 100644 index 00000000..49bd7a24 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/cali.c @@ -0,0 +1,239 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2010 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "diff.h" +#include "common.h" +#include +#include +#include +#include +#include +#include "softblur.h" + +#ifdef STRICT_CHECKING +#include +#endif + +typedef struct +{ + uint8_t *b[3]; + uint8_t *l[3]; + uint8_t *m[3]; + double mean[3]; +} cali_data; + +vj_effect *cali_init(int width, int height) +{ + //int i,j; + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 3; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->defaults[0] = 0; + ve->defaults[1] = 1; + + ve->description = "Image calibration"; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 1; + ve->user_data = NULL; + + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Subtract Dark Current Only" ); + + return ve; +} + + + +void cali_destroy(void) +{ + +} + + +#define ru8(num)(((num)+8)&~8) + +int cali_prepare( void *ed, double meanY, double meanU, double meanV, uint8_t *data, int len, int uv_len ) +{ + int fl = len + (2*uv_len); + cali_data *c = (cali_data*) ed; + c->b[0] = data; + c->b[1] = c->b[0] + len; + c->b[2] = c->b[1] + uv_len; + c->l[0] = data + fl; + c->l[1] = c->l[0] + len; + c->l[2] = c->l[1] + uv_len; + c->m[0] = c->l[0] + fl; + c->m[1] = c->m[0] + len; + c->m[2] = c->m[1] + uv_len; + c->mean[0] = meanY; + c->mean[1] = meanU; + c->mean[2] = meanV; +#ifdef STRICT_CHECKING + assert ( data != NULL ); + assert ( meanY > 0 ); + assert( meanU > 0 ); + assert( meanV > 0 ); +#endif + +} + + +int cali_malloc(void **d, int width, int height) +{ + cali_data *my; + *d = (void*) vj_calloc(sizeof(cali_data)); + my = (cali_data*) *d; + + return 1; +} + +void cali_free(void *d) +{ + if(d) + { + free(d); + } + d = NULL; +} + + +static int flood =0; + +void cali_apply(void *ed, VJFrame *frame, int w, int h,int mode, int full) +{ + cali_data *c = (cali_data*) ed; + + if( c->b[0] == NULL || c->l[0] == NULL || + c->mean[0] <= 0.0 || c->mean[1] <= 0.0 || + c->mean[2] <= 0.0 ) { + if( flood == 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, + "Please select a calibration source (use source/channel list)"); + } + flood = (flood + 1) % 25; + return; + } + + uint8_t *Y = frame->data[0]; + uint8_t *U = frame->data[1]; + uint8_t *V = frame->data[2]; + const int min_Y = get_pixel_range_min_Y(); + const int chroma = 127; + const int uv_len = frame->uv_len; + int p,i; + const int len = w*h; + if( mode == 1 ) { + //@ just show dark frame + veejay_memcpy(Y, c->b[0], (w*h)); + veejay_memcpy(U, c->b[1], uv_len); + veejay_memcpy(V, c->b[2], uv_len); + return; + } else if ( mode == 2 ) { + //@ just show light frame + veejay_memcpy(Y, c->l[0], (w*h)); + veejay_memcpy(U, c->l[1], uv_len); + veejay_memcpy(V, c->l[2], uv_len); + return; + } else if ( mode == 3 ) { + veejay_memcpy(Y, c->m[0], (w*h)); + veejay_memcpy(U, c->m[1], uv_len); + veejay_memcpy(V, c->m[2], uv_len); + return; + } + + uint8_t *by = c->b[0]; + uint8_t *bu = c->b[1]; + uint8_t *bv = c->b[2]; + + uint8_t *wy = c->m[0]; + uint8_t *wu = c->m[1]; + uint8_t *wv = c->m[2]; + + //@ process master flat image + if( full ) { + + for( i = 0; i < len; i ++ ) { + p = ( Y[i] - by[i] ); + if( p < 0 ) + p = 0; + if( wy[i] != 0 ) + Y[i] = c->mean[0] * p / wy[i]; + else + Y[i] = 0; + } + + for( i = 0; i < uv_len; i ++ ) { + p = chroma + ((U[i]-chroma)-(bu[i]-chroma)); + if( p<0) + p = 0; + + if( wu[i]==0 ) + U[i] = chroma; + else + U[i] = (uint8_t) ( c->mean[1] * p / wu[i]); + + p = chroma + ((V[i]-chroma)-(bv[i]-chroma)); + if( p < 0 ) + p = 0; + + if( wv[i] == 0 ) + V[i] = chroma; + else + V[i] = (uint8_t) ( c->mean[2] * p / wv[i] ); + } + + } else { + //@ just show result of frame - dark current + for( i = 0; i <(w*h); i ++ ) { + p = ( Y[i] - by[i] ); + if( p < 0 ) + Y[i] = 0; + else + Y[i] = p; + } + for( i = 0; i < uv_len; i ++ ) { + p = chroma + ( (U[i]-chroma) - (bu[i]-chroma)); + if( p < 0 ) + U[i] = chroma; + else + U[i] = p; + + p = chroma + ( (V[i]-chroma) - (bv[i]-chroma)); + if( p < 0 ) + V[i] = chroma; + else + V[i] = p; + } + } + +} + + + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/cali.h b/branches/V-1.5.3/veejay-server/libvje/effects/cali.h new file mode 100644 index 00000000..568761f0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/cali.h @@ -0,0 +1,35 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2010 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CALIEFFECT_H +#define CALIEFFECT_H +#include +#include +#include + +vj_effect *cali_init(int width, int height); +void cali_free(void *d); +int cali_malloc(void **c, int w, int h); +int cali_prepare(void *userd, double *a, double *b, double *c, uint8_t *d, int e , int f); +void cali_apply(void *d , VJFrame *frame, + int width, int height, + int mode, int full); +void cali_destroy(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/cartonize.c b/branches/V-1.5.3/veejay-server/libvje/effects/cartonize.c new file mode 100644 index 00000000..02b1026d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/cartonize.c @@ -0,0 +1,95 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "cartonize.h" + +vj_effect *cartonize_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->defaults[0] = 64; + ve->defaults[1] = 0; + ve->defaults[2] = 0; + + ve->description = "Cartoon"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Damp Y", "Damp U", "Damp V" ); + return ve; +} + +void cartonize_apply( VJFrame *frame, int width, int height, int b1, int b2, int b3) +{ + unsigned int i; + int len = (width * height); + int uv_len = frame->uv_len; + uint8_t tmp; + int p; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + const int base = (const int) b1; + int ubase= (const int) b2 - 128; + int vbase= (const int) b3 - 128; + // ubase/vbase cannot be 0 + if(ubase==0) ubase=1; + if(vbase==0) vbase=1; + for( i = 0 ; i < len ; i ++ ) + { + tmp = Y[i]; + // if(tmp < 16 ) tmp = 16; else if(tmp > 235 ) tmp = 235; + Y[i] = (tmp / base) * base; // loose fractional part + } + + if(b2 > 0) + for( i = 0; i < uv_len; i ++ ) + { + p = Cb[i] - 128; + //if( p < -127 ) p = -127; + // if( p > 127 ) p = 127; + Cb[i] = (p / ubase) * ubase + 128; + } + + if(b3> 0 ) + for( i = 0; i < uv_len; i ++ ) + { + p = Cr[i] - 128; + //if( p < -127 ) p = -127; + // if( p > 127 ) p = 127; + Cr[i] = (p / vbase) * vbase + 128; + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/cartonize.h b/branches/V-1.5.3/veejay-server/libvje/effects/cartonize.h new file mode 100644 index 00000000..b93ced41 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/cartonize.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CARTONIZE_H +#define CARTONIZE_H +#include +#include +#include + +vj_effect *cartonize_init(int w, int h); +void cartonize_apply( VJFrame *frame, int width, int height, int b1, int b2, int b3); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chameleon.c b/branches/V-1.5.3/veejay-server/libvje/effects/chameleon.c new file mode 100644 index 00000000..0987388b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chameleon.c @@ -0,0 +1,290 @@ +/* + * Linux VeeJay + * EffecTV - Realtime Digital Video Effector + * Copyright (C) 2001-2006 FUKUCHI Kentaro + * + * ChameleonTV - Vanishing into the wall!! + * Copyright (C) 2003 FUKUCHI Kentaro + * + * Ported to veejay by Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "chameleon.h" +#include "common.h" + +vj_effect *chameleon_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->defaults[0] = 0; + ve->description = "ChameleonTV (EffectTV)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Appearing/Dissapearing"); + return ve; +} + +static int last_mode_ = -1; +static int N__ = 0; +static int n__ = 0; + +static int has_bg = 0; +static int32_t *sum = NULL; +static uint8_t *timebuffer = NULL; +static uint8_t *tmpimage[3] = { NULL,NULL,NULL}; +static int plane = 0; +static uint8_t *bgimage[3] = { NULL,NULL,NULL}; + +#define PLANES_DEPTH 6 +#define PLANES (1<< PLANES_DEPTH) + +int chameleon_prepare( uint8_t *map[3], int width, int height ) +{ + if(!bgimage[0]) + return 0; + + //@ copy the iamge + veejay_memcpy( bgimage[0], map[0], (width*height)); + veejay_memcpy( bgimage[1], map[1], (width*height)); + veejay_memcpy( bgimage[2], map[2], (width*height)); + + VJFrame tmp; + veejay_memset( &tmp, 0, sizeof(VJFrame)); + tmp.data[0] = bgimage[0]; + tmp.width = width; + tmp.height = height; + + //@ 3x3 blur + softblur_apply( &tmp, width,height,0); + + veejay_msg(2, "ChameleonTV: Snapped background frame"); + return 1; +} + +int chameleon_malloc(int w, int h) +{ + if( bgimage[0] ) + free(bgimage[0]); + bgimage[0] = (uint8_t*)vj_yuvalloc(w,h); + if(!bgimage[0]) + return 0; + bgimage[1] = bgimage[0] + (w*h); + bgimage[2] = bgimage[1] + (w*h); + if(tmpimage[0]) + free(tmpimage[0]); + tmpimage[0] = (uint8_t*)vj_yuvalloc(w,h); + if(!tmpimage[0]) + return 0; + tmpimage[1] = tmpimage[0] + (w*h); + tmpimage[2] = tmpimage[1] + (w*h); + + if( sum ) + free(sum); + sum = (int32_t*) vj_calloc( w * h * sizeof(int32_t)); + if( timebuffer ) + free(timebuffer); + timebuffer = (uint8_t*) vj_calloc( w* h * PLANES ); + + has_bg = 0; + plane = 0; + N__ = 0; + n__ = 0; + last_mode_ = -1; + + return 1; +} + +void chameleon_free() +{ + if( bgimage[0]) free(bgimage[0]); + if( tmpimage[0]) free(tmpimage[0]); + if( timebuffer ) free(timebuffer); + if( sum ) free(sum); + bgimage[0] = NULL; + tmpimage[0] = NULL; + timebuffer = NULL; + sum = NULL; + has_bg = 0; + plane = 0; +} + +static void drawAppearing(VJFrame *src, VJFrame *dest) +{ + int i; + unsigned int Y; + uint8_t *p, *qy, *qu, *qv; + int32_t *s; + const int video_area = src->len; + + p = timebuffer + plane * video_area; + qy = bgimage[0]; + qu = bgimage[1]; + qv = bgimage[2]; + + uint8_t *lum = src->data[0]; + uint8_t *u0 = src->data[1]; + uint8_t *v0 = src->data[2]; + + uint8_t *Y1 = dest->data[0]; + uint8_t *U1 = dest->data[1]; + uint8_t *V1 = dest->data[2]; + + s = sum; + uint8_t a,b,c; + for(i=0; i>PLANES_DEPTH; + if(Y>255) Y = 255; + a = lum[i]; + b = u0[i]; + c = v0[i]; + a += (( qy[i] - a ) * Y )>>8; + Y1[i] = a; + b += (( qu[i] - b ) * Y )>>8; + U1[i] = b; + c += (( qv[i] - c ) * Y )>>8; + V1[i] = c; + p++; + s++; + } + plane++; + plane = plane & (PLANES-1); +} + + +static void drawDisappearing(VJFrame *src, VJFrame *dest) +{ + int i; + unsigned int Y; + uint8_t *p, *qu, *qv, *qy; + int32_t *s; + const int video_area = src->len; + + uint8_t *Y1 = dest->data[0]; + uint8_t *U1 = dest->data[1]; + uint8_t *V1 = dest->data[2]; + uint8_t *lum = src->data[0]; + uint8_t *u0 = src->data[1]; + uint8_t *v0 = src->data[2]; + + p = timebuffer + (plane * video_area); + qy = bgimage[0]; + qu= bgimage[1]; + qv= bgimage[2]; + s = sum; + + uint8_t a,b,c,A,B,C; + + for(i=0; i < video_area; i++) { + + Y = a = lum[i]; + b = u0[i]; + c = v0[i]; + + A = qy[i]; + B = qu[i]; + C = qv[i]; + + *s -= *p; + *s += Y; + *p = Y; + + Y = (abs(((int)Y<>PLANES_DEPTH; + if(Y>255) Y = 255; + + A += (( a - A ) * Y )>> 8; + Y1[i] = A; + B += (( b - B ) * Y ) >> 8; + U1[i] = B; + C += (( c - C ) * Y ) >> 8; + V1[i] = C; + + p++; + s++; + } + + plane++; + plane = plane & (PLANES-1); +} + +void chameleon_apply( VJFrame *frame, int width, int height, int mode) +{ + unsigned int i; + const int len = (width * height); + VJFrame source; + veejay_memcpy( tmpimage[0], frame->data[0], len ); + veejay_memcpy( tmpimage[1], frame->data[1], len ); + veejay_memcpy( tmpimage[2], frame->data[2], len ); + veejay_memcpy( &source, frame, sizeof(VJFrame)); + source.data[0] = tmpimage[0]; + source.data[1] = tmpimage[1]; + source.data[2] = tmpimage[2]; + + int interpolate = 0; + uint32_t activity = 0; + int auto_switch = 0; + int tmp1,tmp2; + if( motionmap_active() ) + { + motionmap_scale_to( 32,32,1,1, &tmp1,&tmp2, &n__, &N__ ); + auto_switch = 1; + activity = motionmap_activity(); + } + else + { + N__ = 0; + n__ = 0; + } + + if( n__ == N__ || n__ == 0 ) + auto_switch = 0; + + + if(auto_switch) + { + if( activity <= 40 ) + { + // into the wall + drawDisappearing( &source, frame ); + } + else + { + // out of the wall + drawAppearing( &source, frame ); + } + } + + if( mode == 0 ) + drawDisappearing( &source, frame ); + else + drawAppearing( &source, frame ); + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chameleon.h b/branches/V-1.5.3/veejay-server/libvje/effects/chameleon.h new file mode 100644 index 00000000..7ed7b957 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chameleon.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CHAMELEON_H +#define CHAMELEON_H +#include +#include +#include + +vj_effect *chameleon_init(int w, int h); +void chameleon_apply( VJFrame *frame, int width, int height, int mode); +int chameleon_malloc(int w, int h ); +void chameleon_free(); +int chameleon_prepare( uint8_t *bg[3], int w, int h ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chameleonblend.c b/branches/V-1.5.3/veejay-server/libvje/effects/chameleonblend.c new file mode 100644 index 00000000..707f1fb9 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chameleonblend.c @@ -0,0 +1,282 @@ +/* + * Linux VeeJay + * EffecTV - Realtime Digital Video Effector + * Copyright (C) 2001-2006 FUKUCHI Kentaro + * + * ChameleonTV - Vanishing into the wall!! + * Copyright (C) 2003 FUKUCHI Kentaro + * + * Ported to veejay by Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "chameleon.h" +#include "common.h" + +vj_effect *chameleonblend_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->defaults[0] = 0; + ve->description = "Chameleon BlendTV"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode (Appear,Dissapear)" ); + return ve; +} + +static int last_mode_ = -1; +static int N__ = 0; +static int n__ = 0; + +static int has_bg = 0; +static int32_t *sum = NULL; +static uint8_t *timebuffer = NULL; +static uint8_t *tmpimage[3] = { NULL,NULL,NULL}; +static int plane = 0; +static uint8_t *bgimage[3] = { NULL,NULL,NULL}; + +#define PLANES_DEPTH 6 +#define PLANES (1<< PLANES_DEPTH) + +int chameleonblend_prepare( uint8_t *map[3], int width, int height ) +{ + if(!bgimage[0]) + return 0; + + //@ copy the iamge + veejay_memcpy( bgimage[0], map[0], (width*height)); + veejay_memcpy( bgimage[1], map[1], (width*height)); + veejay_memcpy( bgimage[2], map[2], (width*height)); + + VJFrame tmp; + veejay_memset( &tmp, 0, sizeof(VJFrame)); + tmp.data[0] = bgimage[0]; + tmp.width = width; + tmp.height = height; + + //@ 3x3 blur + softblur_apply( &tmp, width,height,0); + + veejay_msg(2, "Chameleon BlendTV: Snapped background mask"); + return 1; +} + +int chameleonblend_malloc(int w, int h) +{ + if( bgimage[0] ) + free(bgimage[0]); + bgimage[0] = (uint8_t*)vj_yuvalloc(w,h); + if(!bgimage[0]) + return 0; + bgimage[1] = bgimage[0] + (w*h); + bgimage[2] = bgimage[1] + (w*h); + if(tmpimage[0]) + free(tmpimage[0]); + tmpimage[0] = (uint8_t*)vj_yuvalloc(w,h); + if(!tmpimage[0]) + return 0; + tmpimage[1] = tmpimage[0] + (w*h); + tmpimage[2] = tmpimage[1] + (w*h); + + if( sum ) + free(sum); + sum = (int32_t*) vj_calloc( w * h * sizeof(int32_t)); + if( timebuffer ) + free(timebuffer); + timebuffer = (uint8_t*) vj_calloc( w* h * PLANES ); + + has_bg = 0; + plane = 0; + N__ = 0; + n__ = 0; + last_mode_ = -1; + + return 1; +} + +void chameleonblend_free() +{ + if( bgimage[0]) free(bgimage[0]); + if( tmpimage[0]) free(tmpimage[0]); + if( timebuffer ) free(timebuffer); + if( sum ) free(sum); + bgimage[0] = NULL; + tmpimage[0] = NULL; + timebuffer = NULL; + sum = NULL; + has_bg = 0; + plane = 0; +} + +static void drawAppearing(VJFrame *src, VJFrame *dest) +{ + int i; + unsigned int Y; + uint8_t *p, *qy, *qu, *qv; + int32_t *s; + const int video_area = src->len; + + p = timebuffer + plane * video_area; + qy = bgimage[0]; + qu = bgimage[1]; + qv = bgimage[2]; + + uint8_t *lum = src->data[0]; + uint8_t *u0 = src->data[1]; + uint8_t *v0 = src->data[2]; + + uint8_t *Y1 = dest->data[0]; + uint8_t *U1 = dest->data[1]; + uint8_t *V1 = dest->data[2]; + + s = sum; + uint8_t a,b,c; + for(i=0; i>PLANES_DEPTH; + if(Y>255) Y = 255; + a = lum[i]; + b = u0[i]; + c = v0[i]; + a += (( qy[i] - a ) * Y )>>8; + Y1[i] = a; + b += (( qu[i] - b ) * Y )>>8; + U1[i] = b; + c += (( qv[i] - c ) * Y )>>8; + V1[i] = c; + p++; + s++; + } + plane++; + plane = plane & (PLANES-1); +} + + +static void drawDisappearing(VJFrame *src, VJFrame *dest) +{ + int i; + unsigned int Y; + uint8_t *p, *qu, *qv, *qy; + int32_t *s; + const int video_area = src->len; + + uint8_t *Y1 = dest->data[0]; + uint8_t *U1 = dest->data[1]; + uint8_t *V1 = dest->data[2]; + uint8_t *lum = src->data[0]; + uint8_t *u0 = src->data[1]; + uint8_t *v0 = src->data[2]; + + p = timebuffer + (plane * video_area); + qy = bgimage[0]; + qu= bgimage[1]; + qv= bgimage[2]; + s = sum; + + uint8_t a,b,c,A,B,C; + + for(i=0; i < video_area; i++) { + + Y = a = lum[i]; + b = u0[i]; + c = v0[i]; + + A = qy[i]; + B = qu[i]; + C = qv[i]; + + *s -= *p; + *s += Y; + *p = Y; + + Y = (abs(((int)Y<>PLANES_DEPTH; + if(Y>255) Y = 255; + + A += (( a - A ) * Y )>> 8; + Y1[i] = A; + B += (( b - B ) * Y ) >> 8; + U1[i] = B; + C += (( c - C ) * Y ) >> 8; + V1[i] = C; + + p++; + s++; + } + + plane++; + plane = plane & (PLANES-1); +} + +void chameleonblend_apply( VJFrame *frame, VJFrame *source, int width, int height, int mode ) +{ + unsigned int i; + const int len = (width * height); + int interpolate = 0; + uint32_t activity = 0; + int auto_switch = 0; + int tmp1,tmp2; + + if( motionmap_active() ) + { + motionmap_scale_to( 32,32,1,1, &tmp1,&tmp2, &n__, &N__ ); + auto_switch = 1; + activity = motionmap_activity(); + } + else + { + N__ = 0; + n__ = 0; + } + + if( n__ == N__ || n__ == 0 ) + auto_switch = 0; + + + if(auto_switch) + { + if( activity <= 40 ) + { + // into the wall + drawDisappearing( source, frame ); + } + else + { + // out of the wall + drawAppearing( source, frame ); + } + } + + if( mode == 0 ) + drawDisappearing( source, frame ); + else + drawAppearing( source, frame ); + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chameleonblend.h b/branches/V-1.5.3/veejay-server/libvje/effects/chameleonblend.h new file mode 100644 index 00000000..1ccbd385 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chameleonblend.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CHAMELEONBLEND_H +#define CHAMELEONBLEND_H +#include +#include +#include + +vj_effect *chameleonblend_init(int w, int h); +void chameleonblend_apply( VJFrame *frame, VJFrame *source, int width, int height, int mode); +int chameleonblend_malloc(int w, int h ); +int chameleonblend_prepare( uint8_t *bg[3],int w, int h ); +void chameleonblend_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/checker.c b/branches/V-1.5.3/veejay-server/libvje/effects/checker.c new file mode 100644 index 00000000..ddd0e3f9 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/checker.c @@ -0,0 +1,259 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + + */ +#include +#include +#include +#include +#include "motionmap.h" +#include "common.h" +#include "softblur.h" +#include "opacity.h" + +#define HIS_DEFAULT 2 +#define HIS_LEN (8*25) +#define ACT_TOP 4000 +#define MAXCAPBUF 55 + +typedef struct { + int p; + int t; +} boxes_t; + +vj_effect *motionmap_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; // motionmap + ve->limits[1][0] = 255; + ve->limits[0][1] = 50; // reverse + ve->limits[1][1] = 10000; + ve->limits[0][2] = 0; + ve->limits[1][2] = 60*25; + /* ve->limits[0][4] = 0; // buffer + ve->limits[1][4] = 255; + ve->limits[0][3] = HIS_DEFAULT; + ve->limits[1][3] = HIS_LEN; */ + ve->defaults[0] = 40; + ve->defaults[1] = ACT_TOP; + ve->defaults[2] = 1; + /* ve->defaults[3] = HIS_DEFAULT; + ve->defaults[4] = 0; */ + ve->description = "Motion Mapping"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->n_out = 2; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Min weight", "Decay" ); + return ve; +} + +static uint8_t *binary_img = NULL; +static uint8_t *original_img = NULL; +static uint8_t *previous_img = NULL; +static uint8_t *large_buf = NULL; +static uint32_t key1_ = 0, key2_ = 0, keyv_ = 0, keyp_ = 0; +static int have_bg = 0; +static int running = 0; +static boxes_t *boxes = NULL; + +#define RUP8(num)(((num)+8)&~8) +int motionmap_prepare( uint8_t *map[3], int w, int h ) +{ + if(!previous_img) + return 0; + + veejay_memcpy( previous_img, map[0], w * h ); + have_bg = 1; + nframe_ = 0; + running = 0; + veejay_msg(2, "Motion Mapping: Snapped background frame"); + return 1; +} + +int motionmap_malloc(int w, int h ) +{ + binary_img = (uint8_t*) vj_malloc(sizeof(uint8_t) * RUP8(w * h * 3) ); + original_img = binary_img + RUP8(w*h); + previous_img = original_img + RUP8(w*h); + large_buf = vj_malloc(sizeof(uint8_t) * RUP8(w*h*3) * (MAXCAPBUF+1)); + if(!large_buf) + { + veejay_msg(0, "Memory allocation error for Motion Mapping. Too large: %ld bytes",(long) ((RUP8(w*h*3)*(MAXCAPBUF+1)))); + return 0; + } + nframe_ = 0; + boxes = (boxes_t*) vj_malloc(sizeof(boxes_t) * 64 * 64 ); + int i ; + for ( i = 0;i < 64*64; i ++ ) { + boxes[i].p = 0; + boxes[i].t = 0; + } + return 1; +} + +void motionmap_free(void) +{ + if(binary_img) + free(binary_img); + if(large_buf) + free(large_buf); + have_bg = 0; + nframe_ = 0; + running = 0; + binary_img = NULL; +} + +#ifndef MIN +#define MIN(a,b) ( (a)>(b) ? (b) : (a) ) +#endif +#ifndef MAX +#define MAX(a,b) ( (a)>(b) ? (a) : (b) ) +#endif + +static void update_bgmask( uint8_t *dst,uint8_t *in, uint8_t *src, int len, int threshold ) +{ + int i; + unsigned int op0,op1; + for( i =0; i < len ; i ++ ) + { + if( abs(in[i] - src[i]) > threshold ) + { + dst[i] = 1; + in[i] = (in[i] + src[i])>>1; + } + else + { + dst[i] = 0; + } + } +} + + +static void put_photo( uint8_t *dst_plane, uint8_t *src_plane, int dst_w, int dst_h, int index , matrix_t matrix, + int box_w, int box_h) +{ + int x,y; + uint8_t *P = dst_plane + (matrix.h*dst_w); + uint8_t *Q = src_plane + (matrix.h*dst_w); + int offset = matrix.w; + + for( y = 0; y < box_h; y ++ ) + { + for( x = 0; x < box_w; x ++ ) + { + *(P+offset+x) = *(Q+offset+x); + } + P += dst_w; + Q += dst_w; + } +} + +void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int param1, int param2 ) +{ + unsigned int i,x,y; + int len = (width * height); + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + int w = frame->width; + int h = frame->height; + + veejay_memcpy( original_img, frame->data[0], len ); + +// softblur_apply( frame, width,height,0 ); + if(!have_bg) + { + veejay_memcpy( previous_img, frame->data[0], len ); + have_bg = 1; + nframe_ = 0; + running = 0; + return; + } + else + { + update_bgmask( binary_img, previous_img, frame->data[0], len , threshold); + } + + int x,y,dx,dy; + int sum; + int dst_x, dst_y; + int step_y; + int step_x; + int box_width = photo_list[index]->w; + int box_height = photo_list[index]->h; + int it = 0; + uint8_t *plane = binary_img; + + matrix_f matrix_placement = get_matrix_func(mode); + + + step_x = w / box_width; + step_y = h / box_height; + + for( y = 0 ; y < h ; y += step_y ) + { + for( x = 0; x < w ; x+= step_x ) + { + sum = 0; + for( dy = 0; dy < step_y; dy ++ ) + { + for( dx = 0; dx < step_x; dx++) + { + sum += plane[ ((y+dy)*w+(dx+x)) ]; + } + } + } + + boxes[ it ].p = sum; + it ++; + sum = 0; + } + + + for( y = 0 ; y < it ; y ++ ) + { + if(boxes[it].p > param1) //@ sufficient motion + { + if( boxes[it].t < 5 ) //@ update timer + boxes[it].t = param2; //@ Time stop + + } + if( boxes[it].t > 0 ) + boxes[it].t --; + if( boxes[it].t == 0 ) { + boxes[it].p = 0; + } + } + for ( i = 0; i < num_photos; i ++ ) + { + matrix_t m = matrix_placement(i, size,width,height ); + put_photo( dstY, photo_list[i]->data[0],width,height,i, m); + put_photo( dstU, photo_list[i]->data[1],width,height,i, m); + put_photo( dstV, photo_list[i]->data[2],width,height,i, m); + } + + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromamagick.c b/branches/V-1.5.3/veejay-server/libvje/effects/chromamagick.c new file mode 100644 index 00000000..dd90aaea --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromamagick.c @@ -0,0 +1,1038 @@ +/* + * VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +/* Note that the 'opacity' parameter is sometimes used as a + threshold value or substraction value depending on the mode + of this effect */ + +#include +#include +#include +#include "chromamagick.h" +#include +#include "common.h" +// fixme: mode 8 and 9 corrupt (green/purple cbcr) + +vj_effect *chromamagick_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 7; + ve->defaults[1] = 150; + ve->description = "Chroma Magic"; + ve->limits[0][0] = 0; + ve->limits[1][0] = 25; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Value" ); + return ve; +} + +void chromamagic_selectmin(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a, b; + const int op_b = 255 - op_a; + for (i = 0; i < len; i++) { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + if (b < a) { + Y[i] = b; + Cb[i] = Cb2[i]; + Cr[i] = Cr2[i]; + } + } +} + +void chromamagic_addsubselectlum(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a) +{ + unsigned int i; + int c, a, b; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + const int op_b = 255 - op_a; + for (i = 0; i < len; i++) { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + if (b < a) { + c = (a + b) >> 1; + Y[i] = c; + + a = Cb[i]; + b = Cb2[i]; + c = (a + b) >> 1; + Cb[i] = c; + + a = Cr[i]; + b = Cr2[i]; + c = (a + b) >> 1; + Cr[i] = c; + } + } +} + + +void chromamagic_selectmax(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a, b; + const int op_b = 255 - op_a; + for (i = 0; i < len; i++) { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + if (b > a) { + Y[i] = (3 * b + a)>>2; + Cb[i] = Cb2[i]; + Cr[i] = Cr2[i]; + } + } +} +void chromamagic_selectdiff(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a, b; + int op_b = 255 - op_a; + for (i = 0; i < len; i++) { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + if (a > b) { + Y[i] = abs(Y[i] - Y2[i]); + Cb[i] = (Cb[i] + Cb2[i]) >> 1; + Cr[i] = (Cr[i] + Cr2[i]) >> 1; + } + } +} + +void chromamagic_diffreplace(VJFrame *frame, VJFrame *frame2, int width, int height, int threshold) +{ + /* op_a = threshold */ + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + unsigned int i ; + int op_b ; + int op_a ; + int a,b; + unsigned long sum = 0; + for(i=0; i < len; i++) + { + sum += Y[i]; + } + op_b = (sum & 0xff); + op_a = 255 - op_b; + for(i=0; i < len; i++) + { + if( abs(Y[i] - Y2[i]) >= threshold ) + { + a = ( Y[i] * op_a ); + b = ( Y2[i] * op_b ); + Y[i] = (a + b) >> 8; + a = ( Cb[i] * op_a ); + b = ( Cb2[i] * op_b ); + + Cb[i] = (a + b) >> 8; + a = ( Cr[i] * op_a ); + b = ( Cr2[i] * op_b ); + + Cr[i] = (a + b) >> 8; + } + } +} + +void chromamagic_selectdiffneg(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a, b,c; + const int op_b = 255 - op_a; + for (i = 0; i < len; i++) { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + if (a > b) { + Y[i] = 255 - abs(255 - a - b); + Cb[i] = ((Cb[i] * op_a) + (Cb2[i]*op_b) )>>8; + Cr[i] = ((Cr[i] * op_a) + (Cr2[i]*op_b) )>>8; + } + } +} + +void chromamagic_selectunfreeze(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int c, a, b; + const int op_b = 255 - op_a; + for (i = 0; i < len; i++) { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + if (a > b) { + if (a > pixel_Y_lo_) + Y[i] = 255 - ((256 - b) * (256 - b)) / a; + Cb[i] = (Cb[i] + Cb2[i]) >> 1; + Cr[i] = (Cr[i] + Cr2[i]) >> 1; + } + } +} + +void chromamagic_addlum(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int c, a, b; + const int op_b = 255 - op_a; + + for (i = 0; i < len; i++) { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + Y[i] = (a * a) / (256- b); + Cb[i] = (Cb[i] + Cb2[i]) >> 1; + Cr[i] = (Cr[i] + Cr2[i]) >> 1; + } +} + +void chromamagic_exclusive(VJFrame *frame, VJFrame *frame2, int width, int height, int op_a) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a=0, b=0, c=0; + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - a; + + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + + a *= o1; + b *= o2; + a = a >> 8; + b = b >> 8; + + Y[i] = (a+b) - ((a * b) >> 8); + + a = Cb[i]-128; + b = Cb2[i]-128; + c = (a + b) - (( a * b) >> 8); + c += 128; + Cb[i] = CLAMP_UV(c); + + + a = Cr[i]-128; + b = Cr2[i]-128; + c = (a + b) - ((a*b) >> 8); + c += 128; + Cr[i] = CLAMP_UV(c); + } +} + +void chromamagic_diffnegate(VJFrame *frame, VJFrame *frame2, int width, int height, int op_a) { + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c,d; + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - o1; +#define MAGIC_THRESHOLD 40 + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + d = abs( a - b ); + if ( d > MAGIC_THRESHOLD ) + { + a = Y[i] * o1; + b = Cb2[i] * o2; + Y[i] = 255 - ( (a + b) >>8 ); + + a = (Cb[i]-128) * o1; + b = (Cb2[i]-128) * o2; + Cb[i] = 255 - ( 128 + (( a + b ) >> 8 )); + + + a = (Cr[i]-128) * o1; + b = (Cr2[i]-128) * o2; + Cr[i] = 255 - ( 128 + (( a + b ) >> 8 )); + + } + } +} + +void chromamagic_additive(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a) { + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + for(i=0; i < len; i++) { + a = (Y[i]*o1) >> 7; + b = (Y2[i]*o2) >> 7; + Y[i] = a + (( 2 * b ) - 255); + + a = Cb[i]; + b = Cb2[i]; + + Cb[i] = a + ( ( 2 * b ) - 255 ); + + a = Cr[i] ; + b = Cr2[i] ; + + Cr[i] = a + ( ( 2 * b ) - 255 ); + } + +} + +void chromamagic_basecolor(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a, b, c, d; + const unsigned int o1 = op_a; + for (i = 0; i < len; i++) { + a = o1 - Y[i]; + b = o1 - Y2[i]; + c = a * b >> 8; + Y[i] = c + a * ((255 - (((255 - a) * (255 - b)) >> 8) - c) >> 8); //8 + + + a = Cb[i]-128; + b = Cb2[i]-128; + c = a * b >> 8; + d = c + a * ((255 - (((255-a) * (255-b)) >> 8) -c) >> 8); + d += 128; + Cb[i] = CLAMP_UV(d); + + a = Cr[i]-128; + b = Cr2[i]-128; + c = a * b >> 8; + d = c + a * ((255 - (((255-a) * (255-b)) >> 8) -c ) >> 8); + d += 128; + Cr[i] = CLAMP_UV(d); + + } +} + + +void chromamagic_freeze(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) { + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + unsigned int i; + + int a,b,c; + + if(op_a==0) op_a = 255; + + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if( b > 0 ) + c = 255 - ((op_a -a ) * (op_a - a)) / b; + else + c = 255 - a; + + Y[i] = CLAMP_Y(c); + + a = Cb[i]; + b = Cb2[i]; + + if(b > 0) + c = 255 - ((256-a) * (256 - a)) / b; + else + c = 255 - a; + + Cb[i] = CLAMP_UV(c); + + a = Cr[i]; + b = Cr2[i]; + + if(b > 0) + c = 255 - (( 256 - a ) * ( 256 - a )) / b; + else + c= 255 -a; + Cr[i] = CLAMP_UV(c); + } + +} + +void chromamagic_unfreeze( VJFrame *frame, VJFrame *frame2, int w, int h, int op_a ) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if( a > pixel_Y_lo_ ) + Y[i] = 255 - (( op_a - b) * (op_a - b)) / a; + + a = Cb[i]; + b = Cb2[i]; + + if( a > pixel_U_lo_ ) + Cb[i] = 255 - (( 256 - b) * ( 256 - b )) / a; + + a = Cr[i]; + b = Cr2[i]; + + if( a > pixel_U_lo_ ) + Cr[i] = 255 - ((256 -b ) * (256 - b)) /a ; + } +} + + +void chromamagic_hardlight( VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if ( b < 128 ) { + c = ( a * b ) >> 8; + } + else { + c = 255 - (( op_a - b) * ( op_a - a ) >> 8); + } + Y[i] =CLAMP_Y( c); + + a = Cb[i]-128; + b = Cb2[i]-128; + if ( b < 128 ) c = ( a * b ) >> 8; + else c = 255 - (( 256 - b) * ( 256 - a) >> 8); + c += 128; + Cb[i] = CLAMP_UV(c); + + a = Cr[i]-128; + b = Cr2[i]-128; + if ( b < 128) c = ( a * b ) >> 8; + else c = 255 - (( 256 - b) * ( 256 - a) >> 8 ); + c += 128; + Cr[i] = CLAMP_UV(c); + + } +} + + +void chromamagic_multiply( VJFrame *frame, VJFrame *frame2, int w, int h,int op_a ) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + for( i=0; i < len; i++) { + a = (Y[i] * o1) >> 8; + b = (Y2[i] * o2) >> 8; + Y[i] = (a * b) >> 8; + + a = Cb[i]-128; + b = Cb2[i]-128; + c = ( a * b ) >> 8; + c += 128; + Cb[i] = CLAMP_UV(c); + + a = Cr[i] - 128; + b = Cr2[i] - 128; + c = ( a * b ) >> 8; + c += 128; + Cr[i] = CLAMP_UV(c); + + } +} + + +void chromamagic_divide(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a ) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + const unsigned int o1 = op_a; + + for(i=0; i < len; i++) { + a = Y[i] * Y[i]; + b = o1 - Y2[i]; + if ( b > pixel_Y_lo_ ) + Y[i] = a / b; + + a = Cb[i] * Cb2[i]; + b = 255 - Cb2[i]; + if( b > pixel_U_lo_ ) + Cb[i] = a / b; + + a = Cr[i] * Cr[i];; + b = 255 - Cr2[i]; + if( b > pixel_U_lo_ ) + Cr[i] = ( a / b ); + } +} + +void chromamagic_substract(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a ,b; + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + + for( i=0; i < len; i++ ) + { + a = Y[i]; + b = Y2[i]; + + Y[i] = a - ((b * o1) >> 8); + + a = Cb[i]; + b = Cb2[i]; + Cb[i] = (((a * o2) + (b * o1))>>8); + + a = Cr[i]; + b = Cr2[i]; + Cr[i] = (((a * o2) + (b * o1)) >> 8); + } + +} + + +void chromamagic_add(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a) { + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + Y[i] = a + (( 2 * b ) - op_a); + + a = Cb[i]-128; + b = Cb2[i]-128; + c = a + ( 2 * b ); + c += 128; + Cb[i] = CLAMP_UV(c); + + a = Cr[i]-128; + b = Cr2[i]-128; + c = a + ( 2 * b ); + c += 128; + Cr[i] = CLAMP_UV(c); + } +} + +void chromamagic_screen(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + Y[i] = 255 - ( (op_a-a) * (op_a-b) >> 8); + a = Cb[i]-128; + b = Cb2[i]-128; + c = 255 - ( ( 256-a) * (256 - b) >> 8); + c += 128; + Cb[i] = CLAMP_UV(c); + a = Cr[i]-128; + b = Cr2[i]-128; + c = 255 - ( ( 256 -a) * (256 - b)>>8); + c += 128; + Cr[i] = CLAMP_UV(c); + } +} + +void chromamagic_difference(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + int a,b,c; + for(i=0; i < len; i++) { + a = (Y[i] * o1)>>7; + b = (Y2[i] * o2)>>7; + Y[i] = abs ( a - b ); + + a = (Cb[i]-128); + b = (Cb2[i]-128); + c = abs ( a - b ); + c += 128; + Cb[i] = CLAMP_UV(c); + + a = (Cr[i]-128); + b = (Cr2[i]-128); + c = abs( a - b ); + c += 128; + Cr[i] = CLAMP_UV(c); + } +} + +/* not really softlight but still cool */ +void chromamagic_softlightmode(VJFrame *frame,VJFrame *frame2, + int width,int height, int op_a) { + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c,d; + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if ( a < op_a ) { + c = (a * b) >> 8; + Y[i] = (c + a * ( 255 - ( (255-a)*(255-b) >> 8) - c)) >> 8; + + a = abs(Cb[i]-128); + b = abs(Cb2[i]-128); + c = (a * b); + d = (c + a * ( 255 - ( (a * b) >> 7) - c)) >> 7; + d += 128; + Cb[i] = CLAMP_UV(d); + + a = abs(Cr[i]-128); + b = abs(Cr2[i]-128); + c = (a * b) >> 7; + d = (c + a * ( 255 - ( (a * b) >> 7) -c)) >> 7; + d += 128; + Cr[i] = CLAMP_UV(d); + } + } +} + +void chromamagic_dodge(VJFrame *frame, VJFrame *frame2, int w, int h, + int op_a) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + for(i=0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if( a >= op_a) c = a; + else { + Y[i] = (a << 8) / ( 256 - b ); + + a = Cb[i] - 128; + b = Cb2[i] - 128; + if ( b > 127 ) b = 127; + c = ( a << 7 ) / ( 128 - b ); + c += 128; + Cb[i] = CLAMP_UV(c); + + a = Cr[i] - 128; + b = Cr2[i] - 128; + if ( b > 127 ) b = 127; + c = ( a << 7 ) / ( 128 - b); + c += 128; + Cr[i] = CLAMP_UV(c); + } + } +} + + +void chromamagic_darken(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) +{ + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + + for(i=0; i < len; i++) + { + if(Y[i] > Y2[i]) + { + Y[i] = ((Y[i] * o1) + (Y2[i] * o2)) >> 8; + Cb[i] = ((Cb[i] * o1) + (Cb2[i] * o2)) >> 8; + Cr[i] = ((Cr[i] * o1) + (Cr2[i] * o2)) >> 8; + } + } +} + +void chromamagic_lighten(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) +{ + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + + for(i=0; i < len; i++) + { + if(Y[i] < Y2[i]) + { + Y[i] = ((Y[i] * o1) + (Y2[i] * o2)) >> 8; + Cb[i] = ((Cb[i] * o1) + (Cb2[i] * o2)) >> 8; + Cr[i] = ((Cr[i] * o1) + (Cr2[i] * o2)) >> 8; + } + } +} + + +void chromamagic_reflect(VJFrame *frame, VJFrame *frame2, + int width,int height, int op_a) { + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b,c; + + for(i=0; i < len ; i++) { + a = Y[i]; + b = Y2[i]; + + if ( b > op_a ) c = b; + else { + Y[i] = (a * a) / ( 256 - b ); + + a = Cb[i]; + b = Cb2[i]; + a -= 128; + b -= 128; + if ( b == 128 ) b = 127; + c = ( a * a ) / ( 128 - b); + c += 128; + Cb[i] = CLAMP_UV(c); + + a = Cr[i]; + b = Cr2[i]; + a -= 128; + b -= 128; + if ( b == 128) b = 127; + c = ( a * a ) / ( 128 - b); + c += 128; + Cr[i] = CLAMP_UV(c); + + } + } +} + + +void chromamagic_modadd(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a, b; + const int op_b = 255 - op_a; + + for (i = 0; i < len; i++) + { + a = (Y[i] * op_a) >> 8; + b = (Y2[i] * op_b) >> 8; + Y[i] = (a + ( 2 * b - 128)) & 255; + + a = (Cb[i] * op_a) >> 8; + b = (Cb2[i] * op_b ) >> 8; + + Cb[i] = (a + ( 2 * b )) & 255; + + a = (Cr[i] * op_a ) >> 8; + b = (Cr2[i] * op_b ) >> 8; + + Cr[i] = (a + ( 2 * b ) ) & 255; + + } +} + + +void chromamagick_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int type, int op_a) +{ + + switch (type) { + case 0: + chromamagic_addsubselectlum(frame, frame2, width, height, op_a); + break; + case 1: + chromamagic_selectmin(frame, frame2, width, height, op_a); + break; + case 2: + chromamagic_selectmax(frame, frame2, width, height, op_a); + break; + case 3: + chromamagic_selectdiff(frame, frame2, width, height, op_a); + break; + case 4: + chromamagic_selectdiffneg(frame, frame2, width, height, op_a); + break; + case 5: + chromamagic_addlum(frame, frame2, width, height, op_a); + break; + case 6: + chromamagic_selectunfreeze(frame, frame2, width, height, op_a); + break; + case 7: + chromamagic_exclusive(frame,frame2,width,height,op_a); + break; + case 8: + chromamagic_diffnegate(frame,frame2,width,height,op_a); + break; + case 9: + chromamagic_additive( frame,frame2,width,height,op_a); + break; + case 10: + chromamagic_basecolor(frame,frame2,width,height,op_a); + break; + case 11: + chromamagic_freeze(frame,frame2,width,height,op_a); + break; + case 12: + chromamagic_unfreeze(frame,frame2,width,height,op_a); + break; + case 13: + chromamagic_hardlight(frame,frame2,width,height,op_a); + break; + case 14: + chromamagic_multiply(frame,frame2,width,height,op_a); + break; + case 15: + chromamagic_divide(frame,frame2,width,height,op_a); + break; + case 16: + chromamagic_substract(frame,frame2,width,height,op_a); + break; + case 17: + chromamagic_add(frame,frame2,width,height,op_a); + break; + case 18: + chromamagic_screen(frame,frame2,width,height,op_a); + break; + case 19: + chromamagic_difference(frame,frame2,width,height,op_a); + break; + case 20: + chromamagic_softlightmode(frame,frame2,width,height,op_a); + break; + case 21: + chromamagic_dodge(frame,frame2,width,height,op_a); + break; + case 22: + chromamagic_reflect(frame,frame2,width,height,op_a); + break; + case 23: + chromamagic_diffreplace(frame,frame2,width,height,op_a); + break; + case 24: + chromamagic_darken( frame,frame2,width,height,op_a); + break; + case 25: + chromamagic_lighten( frame,frame2,width,height,op_a); + break; + case 26: + chromamagic_modadd( frame,frame2,width,height,op_a); + break; + } +} + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromamagick.h b/branches/V-1.5.3/veejay-server/libvje/effects/chromamagick.h new file mode 100644 index 00000000..650f1174 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromamagick.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CHROMAMAGICK_H +#define CHROMAMAGICK_H +#include +#include +#include + +vj_effect *chromamagick_init(); +void chromamagick_apply(VJFrame *frame, VJFrame *frame2 , int width, + int height, int type, int op0); + +void chromamagick_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromapalette.c b/branches/V-1.5.3/veejay-server/libvje/effects/chromapalette.c new file mode 100644 index 00000000..b9140ac3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromapalette.c @@ -0,0 +1,191 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "chromapalette.h" +#include "common.h" +#include + +vj_effect *chromapalette_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 6; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + //angle,r,g,b,cbc,crc + + ve->limits[0][0] = 1; + ve->limits[1][0] = 900; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 255; + + ve->limits[0][5] = 0; + ve->limits[1][5] = 255; + + ve->defaults[0] = 319;//angle + ve->defaults[1] = 255; //r + ve->defaults[2] = 0; //g + ve->defaults[3] = 0; //b + ve->defaults[4] = 200; //cb default + ve->defaults[5] = 20; //cr default + ve->description = "Chrominance Palette (rgb key) "; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_help = 1; + ve->has_user = 0; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( ve->num_params, "Angle", "Red","Green","Blue", "Chroma Blue","Chroma Red" ); + return ve; +} + +void chromapalette_help() +{ +/* veejay_msg(1, "Chrominance Palette"); + veejay_msg(1, "Select a color and set a new chroma value for the entire selection"); + veejay_msg(1, "one or both of the parameters p4 and p5"); + veejay_msg(1, "p0 = Accept angle"); + veejay_msg(1, "p1 = Red"); + veejay_msg(1, "p2 = Green"); + veejay_msg(1, "p3 = Blue"); + veejay_msg(1, "p4 = New chroma Blue value"); + veejay_msg(1, "p5 = New chroma Red value"); +*/ +} + +static inline int _chroma_key( uint8_t fg_cb, uint8_t fg_cr, uint8_t cb, uint8_t cr, int angle) +{ + // see rgbkey.c + short xx = ((fg_cb * cb) + (fg_cr * cr)) >> 7; + short yy = ((fg_cr * cb) - (fg_cb * cr)) >> 7; + int val; + + if (xx < -128) { + xx = -128; + } + else + if (xx > 127) { + xx = 127; + } + + if (yy < -128) { + yy = -128; + } + else + if (yy > 127) { + yy = 127; + } + + val = (xx * angle) >> 4; + + if( abs(yy) < val ) return 1; + return 0; +} + + + +void chromapalette_apply(VJFrame *frame, int width, int height, int angle, int r, int g, int b, int color_cb, int color_cr ) +{ + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t U; + uint8_t V; + int y,u,v; + const float cb_mul = 0.492; + const float cr_mul = 0.877; + + _rgb2yuv( r,g,b,y,u,v ); + + const float aa = (const float) u; + const float bb = (const float) v; + + float tmp = sqrt(((aa * aa) + (bb * bb))); + const int colorKeycb = 127 * (aa / tmp); + const int colorKeycr = 127 * (bb / tmp); + float angle_f = (angle*0.1); + const int accept_angle = 0xf * tan(M_PI * angle_f / 180.0); + + /* + + chrominance is defined as the difference between a color and a reference value luminance + + U = blue - Y + V = red - Y + + this effect does (on key selection) + + U = color_cb - Y + V = color_cr - Y + + 4:2:0 is supersampled to 4:4:4 so there is a chroma value for every Y + + */ + + if(color_cb != 0 && color_cr != 0) //both cb and cr + { + for( i = 0 ; i < len ; i ++ ) + { + if( _chroma_key( Cb[i] , Cr[i], colorKeycb,colorKeycr, accept_angle)) + { + U = 128+(int)( (float) (color_cb - Y[i]) * cb_mul ); + Cb[i] = CLAMP_UV( U ); + V = 128+(int)( (float) (color_cr - Y[i]) * cr_mul ); + Cr[i] = CLAMP_UV( V ); + } + } + } + if(color_cr == 0 ) //only cr + { + for( i = 0 ; i < len ; i ++ ) + { + if( _chroma_key( Cb[i], Cr[i], colorKeycb, colorKeycr, accept_angle)) + { + V = 128+(int)( (float) (color_cr - Y[i]) * cr_mul ); + Cr[i] = CLAMP_UV( V ); + } + } + } + if(color_cb == 0 ) // only cb + { + for( i = 0 ; i < len ; i ++ ) + { + if( _chroma_key( Cb[i] , Cr[i], colorKeycb,colorKeycr, accept_angle)) + { + U = 128 + (int)( (float) (color_cb - Y[i]) * cb_mul ); + Cb[i] = CLAMP_UV(U); + } + } + } + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromapalette.h b/branches/V-1.5.3/veejay-server/libvje/effects/chromapalette.h new file mode 100644 index 00000000..48ec411b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromapalette.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CHROMAPAL_H +#define CHROMAPAL_H +#include +#include +#include +#include + +vj_effect *chromapalette_init(int w, int h); +void chromapalette_apply(VJFrame *frame, int width, int height, int a,int r,int g, int b,int c1,int c2); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromascratcher.c b/branches/V-1.5.3/veejay-server/libvje/effects/chromascratcher.c new file mode 100644 index 00000000..1b4d2882 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromascratcher.c @@ -0,0 +1,209 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "common.h" +#include "chromascratcher.h" +#include "chromamagick.h" +static uint8_t *cframe[3]; +static int cnframe = 0; +static int cnreverse = 0; +static int chroma_restart = 0; + +static VJFrame *_tmp; + +vj_effect *chromascratcher_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 25; /* uses the chromamagick effect for scratchign */ + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 25; + ve->limits[0][3] = 0; + ve->limits[1][3] = 1; + + ve->defaults[0] = 1; + ve->defaults[1] = 150; + ve->defaults[2] = 8; + ve->defaults[3] = 1; + ve->description = "Matte Scratcher"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user =0; + ve->param_description = vje_build_param_list(ve->num_params, "Mode", "Value", "Length", "Pingpong" ); + + return ve; +} +// FIXME private +int chromascratcher_malloc(int w, int h) +{ + cframe[0] = + (uint8_t *) vj_malloc(w * h * sizeof(uint8_t) * 25 * 3 ); + if(!cframe[0]) return 0; + _tmp = (VJFrame*) vj_calloc(sizeof(VJFrame)); + + cframe[1] = cframe[0] + ( w * h * 25 ); + cframe[2] = cframe[1] + ( w * h * 25 ); + + veejay_memset( cframe[0], 0, (w*h*25)); + veejay_memset( cframe[1], 128,(w*h*25)); + veejay_memset( cframe[2], 128,(w*h*25)); + + return 1; +} + +void chromascratcher_free() { + if(cframe[0]) + free(cframe[0]); + if(_tmp) free(_tmp); + cframe[0] = NULL; + cframe[1] = NULL; + cframe[2] = NULL; + _tmp = NULL; +} + +void chromastore_frame(uint8_t * yuv1[3], int w, int h, int n, + int no_reverse) +{ + if (cnreverse) + cnframe--; + else + cnframe++; + + + + if (cnframe >= n) { + if (no_reverse == 0) { + cnreverse = 1; + cnframe = n - 1; + } else { + cnframe = 0; + } + } + if (cnframe == 0) + cnreverse = 0; + + if (!cnreverse) { + veejay_memcpy(cframe[0] + (w * h * cnframe), yuv1[0], (w * h)); + veejay_memcpy(cframe[1] + (w * h * cnframe), yuv1[1], (w * h)); + veejay_memcpy(cframe[2] + (w * h * cnframe), yuv1[2], (w * h)); + } else { + veejay_memcpy(yuv1[0], cframe[0] + (w * h * cnframe), (w * h)); + veejay_memcpy(yuv1[1], cframe[1] + (w * h * cnframe), (w * h)); + veejay_memcpy(yuv1[2], cframe[2] + (w * h * cnframe), (w * h)); + } + +} + +void chromascratcher_apply(VJFrame *frame, + int width, int height, int mode, int opacity, + int n, int no_reverse) +{ + int i; + const int len = frame->len; + const unsigned int op_a = (opacity > 255) ? 255 : opacity; + const unsigned int op_b = 255 - op_a; + const int offset = len * cnframe; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + veejay_memcpy( _tmp, frame, (sizeof(VJFrame))); + _tmp->data[0] = cframe[0]; + _tmp->data[1] = cframe[1]; + _tmp->data[2] = cframe[2]; + + if(no_reverse != chroma_restart) + { + chroma_restart = no_reverse; + cnframe = n; + } + + if (cnframe == 0) + { + veejay_memcpy(cframe[0] + (len * cnframe), Y, len); + veejay_memcpy(cframe[1] + (len * cnframe), Cb, len); + veejay_memcpy(cframe[2] + (len * cnframe), Cr, len); + } + + if(mode>3) { + mode-=3; + chromamagick_apply( frame,_tmp,width, height,mode,opacity); + } + else { + + + switch (mode) { /* scratching with a sequence of frames (no scene changes) */ + + + case 0: + /* moving parts will dissapear over time */ + for (i = 0; i < len; i++) { + if (cframe[0][offset + i] < Y[i]) { + Y[i] = cframe[0][offset + i]; + Cb[i] = cframe[1][offset + i]; + Cr[i] = cframe[2][offset + i]; + } + } + break; + case 1: + for (i = 0; i < len; i++) { + /* moving parts will remain visible */ + if (cframe[0][offset + i] > Y[i]) { + Y[i] = cframe[0][offset + i]; + Cb[i] = cframe[1][offset + i]; + Cr[i] = cframe[2][offset + i]; + } + } + break; + case 2: + for (i = 0; i < len; i++) { + if ((cframe[0][offset + i] * op_a) < (Y[i] * op_b)) { + Y[i] = cframe[0][offset + i]; + Cb[i] = cframe[1][offset + i]; + Cr[i] = cframe[2][offset + i]; + } + } + break; + case 3: + for (i = 0; i < len; i++) { + /* moving parts will remain visible */ + if ((cframe[0][offset + i] * op_a) > (Y[i] * op_b)) { + Y[i] = cframe[0][offset + i]; + Cb[i] = cframe[1][offset + i]; + Cr[i] = cframe[2][offset + i]; + } + } + break; + + } + + } // else + + + chromastore_frame(frame->data, width, height, n, no_reverse); +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromascratcher.h b/branches/V-1.5.3/veejay-server/libvje/effects/chromascratcher.h new file mode 100644 index 00000000..ef3143c8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromascratcher.h @@ -0,0 +1,34 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CHROMASCRATCHER_H +#define CHROMASCRATCHER_H +#include +#include +#include +#include + +vj_effect *chromascratcher_init(int w, int h); +int chromascratcher_malloc(int w, int h); +void chromascratcher_free(); +void chromascratcher_apply(VJFrame *frame, + int width, int height, int mode, int opacity, + int nframes, int no_reverse); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromium.c b/branches/V-1.5.3/veejay-server/libvje/effects/chromium.c new file mode 100644 index 00000000..e6272d09 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromium.c @@ -0,0 +1,99 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "chromium.h" +#include "common.h" + + +vj_effect *chromium_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 3; + ve->defaults[0] = 0; + ve->description = "Chromium"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode" ); + return ve; +} + +void chromium_apply(VJFrame *frame, int width, int height, int m ) +{ + const int len = frame->uv_len; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + unsigned int i; + double tmp; + switch(m) + { + case 0: + for( i = 0; i < len ; i++) + { + Cb[i] = 0xff - Cb[i]; + } + break; + case 1: + for( i = 0; i < len ; i++ ) + { + Cr[i] = 0xff - Cr[i]; + } + break; + case 2: + for( i = 0; i < len; i++) + { + Cb[i] = 0xff - Cb[i]; + Cr[i] = 0xff - Cr[i]; + } + break; + case 3: + // swap cb/cr + for (i = 0; i < len ; i ++ ) + { + tmp = Cb[i]; + Cb[i] = Cr[i]; + Cr[i] = tmp; + } + break; +/* + case 4: + // U - blue - Y , V = Red - Y + // U = 0.492 * ( B - Y ) + for( i = 0; i < len; i++) + { + tmp = 0.492 * (VJ_EFFECT_CB_YELLOW - yuv[0][i * 2]); + t = 128 + (uint8_t) tmp; + Cb[i] = t; + } + break; +*/ + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/chromium.h b/branches/V-1.5.3/veejay-server/libvje/effects/chromium.h new file mode 100644 index 00000000..b997d986 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/chromium.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CHROMIUM_H +#define CHROMIUM_H +#include +#include +#include + +vj_effect *chromium_init(int w, int h); +void chromium_apply(VJFrame *frame, int width, int height, int n); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colflash.c b/branches/V-1.5.3/veejay-server/libvje/effects/colflash.c new file mode 100644 index 00000000..860b1ba3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colflash.c @@ -0,0 +1,103 @@ +/* + * Linux VeeJay + * + * Copyright(C)2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "colflash.h" +#include "common.h" + +// very simple color flashing fx + +vj_effect *colflash_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 50; //tempo in frames + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + ve->limits[0][4] = 1; + ve->limits[1][4] = 10; + ve->defaults[0] = 5; + ve->defaults[1] = 0; + ve->defaults[2] = 0; + ve->defaults[3] = 0; + ve->defaults[4] = 3; //delay + ve->description = "Color Flash"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( ve->num_params, "Frametime" , "Red", "Green", "Blue", "Delay" ); + return ve; +} + + +static int color_flash_ = 0; +static int color_delay_ = 0; +static int delay_ = 0; +void colflash_apply( VJFrame *frame, int width, int height, int f,int r, int g, int b, int d) +{ + unsigned int i, op0, op1; + unsigned int len = frame->len; + unsigned int uv_len = frame->uv_len; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + uint8_t y,u,v; + + _rgb2yuv( r,g,b,y,u,v ); + + if( d != delay_ ) + { + delay_ = d; + color_delay_ = d; + } + + if( color_delay_ ) + { + veejay_memset( Y, y, len ); + veejay_memset( Cb, u, uv_len ); + veejay_memset( Cr, v, uv_len ); + color_delay_ -- ; + } + else + { + color_flash_ ++ ; + if( color_flash_ >= f ) + { + color_delay_ = delay_; + color_flash_ = 0; + } + + } + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colflash.h b/branches/V-1.5.3/veejay-server/libvje/effects/colflash.h new file mode 100644 index 00000000..4623ff0c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colflash.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COLFLASH_H +#define COLFLASH_H +#include +#include +#include + +vj_effect *colflash_init(); +void colflash_apply( VJFrame *frame, int width, int height, int f,int r, int g, int b, int d); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colmorphology.c b/branches/V-1.5.3/veejay-server/libvje/effects/colmorphology.c new file mode 100644 index 00000000..98d91be4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colmorphology.c @@ -0,0 +1,148 @@ +/* + * Linux VeeJay + * + * Copyright(C)2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "colmorphology.h" +#include "common.h" +typedef uint8_t (*morph_func)(uint8_t *kernel, uint8_t mt[9] ); + +vj_effect *colmorphology_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; // threshold + ve->limits[1][0] = 255; + + ve->limits[0][1] = 0; // morpology operator (dilate,erode, ... ) + ve->limits[1][1] = 8; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; // passes + + ve->defaults[0] = 140; + ve->defaults[1] = 0; + ve->defaults[2] = 0; + + ve->description = "Colored Morphology"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold","Operator mode","Repeat"); + return ve; +} + + +static uint8_t *binary_img; + +int colmorphology_malloc(int w, int h ) +{ + binary_img = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!binary_img) return 0; + return 1; +} + +void colmorphology_free(void) +{ + if(binary_img) + free(binary_img); + binary_img = NULL; +} + +static uint8_t _dilate_kernel3x3( uint8_t *kernel, uint8_t img[9]) +{ + register int x; + /* consider all background pixels (0) in input image */ + for(x = 0; x < 9; x ++ ) + if((kernel[x] * img[x]) > 0 ) + return 235; + return 16; +} + + +static uint8_t _erode_kernel3x3( uint8_t *kernel, uint8_t img[9]) +{ + register int x; + /* consider all background pixels (0) in input image */ + for(x = 0; x < 9; x ++ ) + if(kernel[x] && img[x] == 0 ) + return 16; + return 235; +} + +static morph_func _morphology_function(int i) +{ + if( i == 0 ) + return _dilate_kernel3x3; + return _erode_kernel3x3; +} + + +void colmorphology_apply( VJFrame *frame, int width, int height, int threshold, int type, int passes ) +{ + unsigned int i,x,y; + int len = (width * height); + int c = 0,t=0,k=0; + uint8_t pixel; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t kernels[8][9] ={ + { 1,1,1, 1,1,1 ,1,1,1 },//0 + { 0,1,0, 1,1,1, 0,1,0 },//1 + { 0,0,0, 1,1,1, 0,0,0 },//2 + { 0,1,0, 0,1,0, 0,1,0 },//3 + { 0,0,1, 0,1,0, 1,0,0 },//4 + { 1,0,0, 0,1,0, 0,0,1 }, + { 1,1,1, 0,0,0, 0,0,0 }, + { 0,0,0, 0,0,0, 1,1,1 } + }; + + morph_func p = _morphology_function(passes); + + for( i = 0; i < len; i ++ ) + { + binary_img[i] = ( Y[i] < threshold ? 0: 0xff ); + t++; + } + + len -= width; + + /* compute dilation of binary image with kernel */ + for(y = width; y < len; y += width ) + { + for(x = 1; x < width-1; x ++) + { + if(binary_img[x+y] == 0) + { + uint8_t mt[9] = { + binary_img[x-1+y-width], binary_img[x+y-width], binary_img[x+1+y-width], + binary_img[x-1+y], binary_img[x+y] , binary_img[x+1+y], + binary_img[x-1+y+width], binary_img[x+y+width], binary_img[x+1+y+width] + }; + Y[x+y] = p( kernels[type], mt ); + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colmorphology.h b/branches/V-1.5.3/veejay-server/libvje/effects/colmorphology.h new file mode 100644 index 00000000..c8d9c4ca --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colmorphology.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COLMORPHOLOGY_H +#define COLMORPHOLOGY_H +#include +#include +#include + +vj_effect *colmorphology_init(int w, int h); +void colmorphology_apply( VJFrame *frame, int width, int height, int t, int val, int n); +int colmorphology_malloc(int w, int h); +void colmorphology_free(void); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/color.c b/branches/V-1.5.3/veejay-server/libvje/effects/color.c new file mode 100644 index 00000000..e2df57bf --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/color.c @@ -0,0 +1,98 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "color.h" +vj_effect *color_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 150; + ve->defaults[1] = 150; + ve->defaults[2] = 150; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->sub_format = 0; + ve->description = "Color Enhance"; + ve->param_description = vje_build_param_list( ve->num_params, "Intensity Y", "Intensity U", "Intensity V" ); + ve->has_user = 0; + ve->extra_frame = 0; + return ve; +} + + +void color_apply(VJFrame *frame, int width, int height, + int opacity_a, int opacity_b, + int opacity_c) +{ + unsigned int i; + const unsigned int op_a0 = 255 - opacity_a; + const unsigned int op_b0 = 255 - opacity_b; + const unsigned int op_c0 = 255- opacity_c; + + const unsigned int cb_a = opacity_a * 100; + const unsigned int cb_c = opacity_c * 212; + const unsigned int cb_b = opacity_b * 72; + + const unsigned int cr_a = opacity_a * 212; + const unsigned int cr_b = opacity_b * 58; + const unsigned int cr_c = opacity_c * 114; + + int p1,p2,q1,q2; + + const int uv_len = frame->uv_len; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + for (i = 0; i < uv_len; i++) { + p1 = Cb[i]; + p2 = Cr[i]; + + q1 = ( + ((op_a0 * p1 + cb_a)>>8) + + ((op_b0 * p1 + cb_b)>>8) + + ((op_c0 * p1 + cb_c)>>8)) ; + q2 = ( + ((op_a0 * p2 + cr_a)>>8) + + ((op_b0 * p2 + cr_b)>>8) + + ((op_c0 * p2 + cr_c)>>8)) ; + + if( q1 > 512) q1 = q1 / 3; + else if( q1 > 255) q1 = q1 >> 1; + + if( q2 > 512) q2 = q2 / 3; + else if (q2 > 255) q1 = q2 >> 1; + + Cb[i] = q1; + Cr[i] = q2; + + } + +} +void color_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/color.h b/branches/V-1.5.3/veejay-server/libvje/effects/color.h new file mode 100644 index 00000000..38724277 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/color.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COLORVAL_H +#define COLORVAL_H +#include +#include +#include + +vj_effect *color_init(); +void color_apply( VJFrame *frame , int width, int height, int a, int b, int c); + +void color_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/coloradjust.c b/branches/V-1.5.3/veejay-server/libvje/effects/coloradjust.c new file mode 100644 index 00000000..d9ff2b8f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/coloradjust.c @@ -0,0 +1,134 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "coloradjust.h" +#include +#include "common.h" +vj_effect *coloradjust_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + /* ve->limits[0][0] = -235; + ve->limits[1][0] = 235; + ve->limits[0][1] = 0; + ve->limits[1][1] = 36000; + ve->defaults[0] = 116; + ve->defaults[1] = 4500;*/ + ve->limits[0][0] = 0; + ve->limits[1][0] = 360; + ve->limits[0][1] = 0; + ve->limits[1][1] = 256; + ve->defaults[0] = 50; + ve->defaults[1] = 50; + ve->param_description = vje_build_param_list( ve->num_params, "Degrees", "Intensity" ); + ve->description = "Hue and Saturation"; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 0; + return ve; +} + +/* these methods were derived from yuv-subtitler */ +inline uint8_t ccolor_adjust_u(double dcolor, double dsaturation) +{ + return (sin(dcolor) * dsaturation) + 128; +} +inline uint8_t ccolor_adjust_v(double dcolor, double dsaturation) +{ + return (cos(dcolor) * dsaturation) + 128; +} + + +inline double ccolor_sqrt(double u, double v) +{ +// return sqrt((u * u) + (v * v)); + double r; + fast_sqrt( r,(u*u)+(v*v)); + return r; +} +inline double ccolor_sine(int u, double dsaturation) +{ + return asin((u / dsaturation)); +} + + +void coloradjust_apply(VJFrame *frame, int width, int height, int val, + int _degrees) +{ + unsigned int i; + const int len = frame->uv_len; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; +//@ Hue, Saturation, copied from AVIDEMUX! +//@ the commented out version is the same as the optimized version (?) +// + + float hue = (float) ( (val/180.0) * M_PI); + float sat = (float) ( _degrees * 0.01 ); + + const int s = (int) rint( sin(hue) * (1<<16) * sat ); + const int c = (int) rint( cos(hue) * (1<<16) * sat ); + + for( i = 0 ; i < len ;i ++ ) + { + const int u = Cb[i] - 128; + const int v = Cr[i] - 128; + int new_u = (c * u - s * v + (1<<15) + (128<<16)) >> 16; + int new_v = (s * u + c * v + (1<<15) + (128<<16)) >> 16; + if( new_u & 768 ) new_u = (-new_u) >> 31; + if( new_v & 768 ) new_v = (-new_v) >> 31; + + Cb[i] = new_u; + Cr[i] = new_v; + } + + + /* int cb, cr; + double dsaturation, dcolor; + const double degrees = (_degrees / 100.0); + double co, si; + const double dsat = val / 100.0; + + for (i = 0; i < len; i++) + { + cb = Cb[i] - 128; + cr = Cr[i] - 128; + if (cb != 0 && cr != 0) + { + dsaturation = ccolor_sqrt((double) cb, (double) cr); + dcolor = ccolor_sine(cb, dsaturation); + if (cr < 0) + dcolor = M_PI - dcolor; + + dcolor += (degrees * M_PI) / 180.0; + dsaturation *= dsat; + sin_cos(co,si, dcolor ); + Cb[i] = si * dsaturation + 128; + Cr[i] = co * dsaturation + 128; + } + } +*/ +} +void coloradjust_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/coloradjust.h b/branches/V-1.5.3/veejay-server/libvje/effects/coloradjust.h new file mode 100644 index 00000000..5c0f148f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/coloradjust.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COLORADJUST_H +#define COLORADJUST_H +#include +#include +#include + +vj_effect *coloradjust_init(); + +void coloradjust_apply(VJFrame *frame, int width, int height, int val, + int degrees); +void coloradjust_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colorhis.c b/branches/V-1.5.3/veejay-server/libvje/effects/colorhis.c new file mode 100644 index 00000000..a2023136 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colorhis.c @@ -0,0 +1,128 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "colorhis.h" +#include +#include +#include +#include "common.h" +vj_effect *colorhis_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 3; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->defaults[0] = 0; // r only, g only, b only, rgb + ve->defaults[1] = 0; // draw + ve->defaults[2] = 200; // intensity + ve->defaults[3] = 132; // strength + ve->param_description = vje_build_param_list ( ve->num_params, "Mode (R,G,B,All)", "Draw","Intensity", "Strength" ); + ve->description = "Color Histogram"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + return ve; +} + +static void *histogram_ = NULL; +static VJFrame *rgb_frame_ = NULL; +static uint8_t *rgb_ = NULL; +static void *convert_yuv = NULL; +static void *convert_rgb = NULL; + +int colorhis_malloc(int w, int h) +{ + if( histogram_ ) + veejay_histogram_del(histogram_); + if( rgb_ ) + free(rgb_); + histogram_ = veejay_histogram_new(); + rgb_ = vj_malloc(sizeof(uint8_t) * w * h * 3 ); + rgb_frame_ = yuv_rgb_template( rgb_, w, h, PIX_FMT_RGB24 ); + + + return 1; +} + +void colorhis_free() +{ + if( histogram_ ) + veejay_histogram_del(histogram_); + if( rgb_ ) + free(rgb_); + if( rgb_frame_) + free(rgb_frame_); + rgb_ = NULL; + rgb_frame_ = NULL; + histogram_ = NULL; + + if( convert_yuv ) + yuv_fx_context_destroy( convert_yuv ); + if( convert_rgb ) + yuv_fx_context_destroy( convert_rgb ); + + convert_rgb = NULL; + convert_yuv = NULL; + +} + + +void colorhis_apply( VJFrame *frame, int width, int height,int mode, int val, int intensity, int strength) +{ + int src_fmt = (frame->uv_height == height ? PIX_FMT_YUV422P : PIX_FMT_YUV420P); + + if(!convert_yuv) + convert_yuv = yuv_fx_context_create( frame, rgb_frame_, src_fmt, PIX_FMT_RGB24 ); + + yuv_fx_context_process( convert_yuv, frame, rgb_frame_ ); + + //yuv_convert_any_ac( frame, rgb_frame_, src_fmt, PIX_FMT_RGB24 ); + + if( val == 0 ) + { + veejay_histogram_draw_rgb( histogram_, frame, rgb_, intensity, strength, mode ); + } + else + { + veejay_histogram_analyze_rgb( histogram_,rgb_, frame ); + veejay_histogram_equalize_rgb( histogram_, frame, rgb_, intensity, strength, mode ); + + if(!convert_rgb ) + convert_rgb = yuv_fx_context_create( rgb_frame_, frame, PIX_FMT_RGB24, src_fmt ); + yuv_fx_context_process( convert_rgb, rgb_frame_, frame ); + +// yuv_convert_any_ac( rgb_frame_, frame, PIX_FMT_RGB24, src_fmt ); + } +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colorhis.h b/branches/V-1.5.3/veejay-server/libvje/effects/colorhis.h new file mode 100644 index 00000000..554ea63d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colorhis.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COLORHIS_H +#define COLORHIS_H +#include +#include +#include + +vj_effect *colorhis_init(int w, int h); +int colorhis_malloc(int w , int h ); +void colorhis_free( ); +void colorhis_apply( VJFrame *frame, int width, int height, int mode,int val, int intensity, int strength); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colormap.c b/branches/V-1.5.3/veejay-server/libvje/effects/colormap.c new file mode 100644 index 00000000..8a4a9744 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colormap.c @@ -0,0 +1,88 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include +#include "colormap.h" + +vj_effect *colormap_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->defaults[0] = 46; + ve->defaults[1] = 109; + ve->defaults[2] = 92; + + ve->description = "Color mapping"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Red","Green","Blue" ); + return ve; +} + +static uint8_t u_[256]; +static uint8_t v_[256]; + +void colormap_apply( VJFrame *frame, int width, int height, int r, int g, int b) +{ + int i; + int len = (width * height); + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t dummy = 0; + for(i = 1; i < 256; i ++ ) + { + COLOR_rgb2yuv( (r % i),(g % i),(b % i), dummy, u_[i-1],v_[i-1]); + + } + + +/* for (i = 0; i < len; i++) { + *(Y) = val - *(Y); + *(Y)++; + }*/ + + for (i = 0; i < len; i++) { +// *(Cb) = val - *(Cb); + // *(Cb)++; + // *(Cr) = val - *(Cr); +// *(Cr)++; + *(Cb) = u_[ (*Y) ]; + *(Cr) = v_[ (*Y) ]; + *(Cb)++; + *(Cr)++; + *(Y)++; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colormap.h b/branches/V-1.5.3/veejay-server/libvje/effects/colormap.h new file mode 100644 index 00000000..0b95b1cd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colormap.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COLORMAP_H +#define COLORMAP_H +#include +#include +#include + +vj_effect *colormap_init(int w, int h); +void colormap_apply( VJFrame *frame, int width, int height, int vala , int valb, int valc); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colorshift.c b/branches/V-1.5.3/veejay-server/libvje/effects/colorshift.c new file mode 100644 index 00000000..dd4b8881 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colorshift.c @@ -0,0 +1,220 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "colorshift.h" + +vj_effect *colorshift_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 5; + ve->defaults[1] = 235; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 9; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->description = "Shift pixel values YCbCr"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Value" ); + return ve; +} + + +/* bitwise and test */ + +void softmask2_apply(VJFrame *frame, int width, int height, int paramt) +{ + const unsigned int len = frame->len; + unsigned int x; + uint8_t *Y = frame->data[0]; + for (x = 0; x < len; x++) + Y[x] &= paramt; +} + +void softmask2_applycb(VJFrame *frame, int width, int height, + int paramt) +{ + const unsigned int len = frame->uv_len; + uint8_t *Cb = frame->data[1]; + unsigned int x; + for (x = 0; x < len; x++) + Cb[x] &= paramt; +} + +void softmask2_applycr(VJFrame *frame, int width, int height, + int paramt) +{ + uint8_t *Cr = frame->data[2]; + const unsigned int len = frame->uv_len; + unsigned int x; + for (x = 0; x < len; x++) + Cr[x] &= paramt; +} + +void softmask2_applycbcr(VJFrame *frame, int width, int height, + int paramt) +{ + const unsigned int len = frame->uv_len; + unsigned int x; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + for (x = 0; x < len; x++) { + Cb[x] &= paramt; + Cr[x] &= paramt; + } +} + +void softmask2_applyycbcr(VJFrame *frame, int width, int height, + int paramt) +{ + const unsigned int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + unsigned int x; + + for (x = 0; x < len; x++) + Y[x] &= paramt; + + for (x = 0; x < uv_len; x++) { + Cb[x] &= paramt; + Cr[x] &= paramt; + } +} + +void softmask_apply(VJFrame *frame, int width, int height, int paramt) +{ + const unsigned int len = frame->len; + unsigned int x; + uint8_t *Y = frame->data[0]; + + + for (x = 0; x < len; x++) + Y[x] |= paramt; +} + + +void softmask_applycb(VJFrame *frame, int width, int height, int paramt) +{ + const unsigned int len = frame->uv_len; + uint8_t *Cb = frame->data[1]; + + + unsigned int x; + for (x = 0; x < len; x++) + Cb[x] |= paramt; +} + + +void softmask_applycr(VJFrame *frame, int width, int height, int paramt) +{ + const unsigned int len = frame->uv_len; + uint8_t *Cr = frame->data[2]; + + + unsigned int x; + for (x = 0; x < len; x++) + Cr[x] |= paramt; +} + + +void softmask_applycbcr(VJFrame *frame, int width, int height, + int paramt) +{ + const unsigned int len = frame->uv_len; + unsigned int x; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + for (x = 0; x < len; x++) + { + Cb[x] |= paramt; + Cr[x] |= paramt; + } +} + +void softmask_applyycbcr(VJFrame *frame, int width, int height, + int paramt) +{ + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + const int uv_len = frame->uv_len; + + unsigned int x; + for (x = 0; x < len; x++) + Y[x] |= paramt; + + for (x = 0; x < uv_len; x++) { + Cb[x] |= paramt; + Cr[x] |= paramt; + } +} + + +void colorshift_apply(VJFrame *frame, int width, int height, int type, + int n) +{ + switch (type) { + case 0: + softmask_apply(frame, width, height, n); + break; + case 1: + softmask_applycb(frame, width, height, n); + break; + case 2: + softmask_applycr(frame, width, height, n); + break; + case 3: + softmask_applycbcr(frame, width, height, n); + break; + case 4: + softmask_applyycbcr(frame, width, height, n); + break; + case 5: + softmask2_apply(frame, width, height, n); + break; + case 6: + softmask2_applycb(frame, width, height, n); + break; + case 7: + softmask2_applycr(frame, width, height, n); + break; + case 8: + softmask2_applycbcr(frame, width, height, n); + break; + case 9: + softmask2_applyycbcr(frame, width, height, n); + break; + } +} +void colorshift_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/colorshift.h b/branches/V-1.5.3/veejay-server/libvje/effects/colorshift.h new file mode 100644 index 00000000..f48ec689 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/colorshift.h @@ -0,0 +1,34 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COLORSHIFT_H +#define COLORSHIFT_H +#include +#include +#include + +/* this effect uses bit masking to increase/decrease the luma cq chroma values + in a frame. with this you can create distorted colours. */ + +vj_effect *colorshift_init(); +void colorshift_apply( VJFrame *frame, int width, int height, int n, + int type); +void colorshift_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/common.c b/branches/V-1.5.3/veejay-server/libvje/effects/common.c new file mode 100644 index 00000000..ef1db5e6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/common.c @@ -0,0 +1,2017 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include +#include +#include +#include +#include +#include +#include "common.h" +#ifdef STRICT_CHECKING +#include +#endif +char **vje_build_param_list( int num, ... ) +{ + va_list args; + char buf[1024]; + char **list; + char *tmp = NULL; + list = (char**) vj_malloc(sizeof(char*) * (num+1) ); + + va_start( args, num ); + + int i; + for( i = 0; i >2; + src[stride ] = (src[stride ] + 2*src[stride*2] + src[stride*3])>>2; + src[stride*2] = (src[stride*2] + 2*src[stride*3] + src[stride*4])>>2; + src[stride*3] = (src[stride*3] + 2*src[stride*4] + src[stride*5])>>2; + src[stride*4] = (src[stride*4] + 2*src[stride*5] + src[stride*6])>>2; + src[stride*5] = (src[stride*5] + 2*src[stride*6] + src[stride*7])>>2; + src[stride*6] = (src[stride*6] + 2*src[stride*7] + src[stride*8])>>2; + src[stride*7] = (src[stride*7] + 2*src[stride*8] + src[stride*9])>>2; + + src++; + } +//#endif +} + + +matrix_t matrix_placementA(int photoindex, int size, int w , int h) +{ + matrix_t m; + m.w = (photoindex % size) * (w/size); + m.h = (photoindex / size) * (h/size); + return m; +} + +matrix_t matrix_placementB(int photoindex, int size, int w , int h) +{ + matrix_t m; + m.w = (photoindex/size) * (w/size); + m.h = (photoindex % size) * (h/size); + return m; +} + +matrix_t matrix_placementC(int photoindex, int size, int w , int h) +{ + matrix_t m; + int n = size*size-1; + m.w = ((n-photoindex) % size) * (w/size); + m.h = ((n-photoindex) / size) * (h/size); + return m; +} + +matrix_t matrix_placementD(int photoindex, int size, int w , int h) +{ + matrix_t m; + int n = size*size-1; + m.w = ((n-photoindex) / size) * (w/size); + m.h = ((n-photoindex) % size) * (h/size); + return m; +} + +matrix_f get_matrix_func(int type) +{ + if(type==0) + return &matrix_placementA; + if(type==1) + return &matrix_placementB; + if(type==2) + return &matrix_placementC; + return &matrix_placementD; +} + + +int power_of(int size) +{ + int power = 1; + while( size-- ) + power *= 2; + + return power; +} + +int max_power(int w) +{ + int i=1; + while(power_of(i) < w) + i++; + return i; +} +/* some parts (linearBlend() and deinterlace() from : + * + * Simple xawtv deinterlacing plugin - linear blend + * + * CAVEATS: Still some interlacing effects in high motion perhaps + * Some ghosting in instant transitions, slightly noticeable + * + * BENEFITS: NO DROP IN FRAMERATE =] + * Looks absolutely beautiful + * Doesn't lower framerate + * Oh and did I mention it doesn't lower framerate? + * Plus, its MMX'itized now, so it really doesn't lower framerate. + * + * AUTHORS: + * Conrad Kreyling + * Patrick Barrett + * + * This is licenced under the GNU GPL until someone tells me I'm stealing code + * and can't do that ;) www.gnu.org for any version of the license. + * + * Based on xawtv-3.72/libng/plugins/flt-nop.c (also GPL) + * Linear blend deinterlacing algorithm adapted from mplayer's libpostproc + */ + + + +void deinterlace(uint8_t *data, int w, int h, int v) +{ + int x,y; + uint8_t *src; + for(y=1; y < h-8; y+=8) + { + for(x=0; x < w; x+=8) + { + src = data + x + y * w; + linearBlend(src, w); + } + } +} + + +void frameborder_yuvdata(uint8_t * input_y, uint8_t * input_u, + uint8_t * input_v, uint8_t * putin_y, + uint8_t * putin_u, uint8_t * putin_v, int width, + int height, int top, int bottom, int left, + int right, int shift_h, int shift_v) +{ + + int line, x; + int input_active_width; + int input_active_height; + uint8_t *rightvector; + shift_h = 0; + shift_v = 0; + input_active_height = height - top - bottom; + input_active_width = width - left - right; + + /* Y component TOP */ + for (line = 0; line < top; line++) { + for (x = 0; x < width; x++) { + *(input_y + x) = *(putin_y + x); + } + //memcpy (input_y, putin_y, width); + input_y += width; + putin_y += width; + } + rightvector = input_y + left + input_active_width; + /* Y component LEFT AND RIGHT */ + for (line = 0; line < input_active_height; line++) { + for (x = 0; x < left; x++) { + *(input_y + x) = *(putin_y + x); + } + //memcpy (input_y, putin_y, left); + for (x = 0; x < right; x++) { + *(rightvector + x) = + *(putin_y + left + input_active_width + x); + } + //memcpy (rightvector, putin_y + left + input_active_width, right); + input_y += width; + rightvector += width; + putin_y += width; + } + /* Y component BOTTOM */ + for (line = 0; line < bottom; line++) { + for (x = 0; x < width; x++) + *(input_y + x) = *(putin_y + x); + + //memcpy (input_y, putin_y, width); + input_y += width; + putin_y += width; + } + + + /* U component TOP */ + for (line = 0; line < (top >> shift_v); line++) { + for (x = 0; x < (width >> shift_h); x++) { + *(input_u + x) = *(putin_u + x); + } + //memcpy (input_u, putin_u, width >> 1); + input_u += width >> shift_h; + putin_u += width >> shift_h; + } + + rightvector = input_u + ((left + input_active_width) >> shift_h); + for (line = 0; line < (input_active_height >> shift_v); line++) { + //memcpy (input_u, putin_u, left >> 1); + for (x = 0; x < (left >> shift_h); x++) { + *(input_u + x) = *(putin_u + x); + } + //memcpy (rightvector, putin_u + ((left + input_active_width)>>1) , right >> 1); + for (x = 0; x < (right >> shift_h); x++) { + *(rightvector + x) = *(putin_u + + ((left + input_active_width + x) >> shift_h)); + + } + input_u += width >> shift_h; + rightvector += width >> shift_h; + putin_u += width >> shift_h; + } + + for (line = 0; line < (bottom >> shift_v); line++) { + for (x = 0; x < (width >> shift_h); x++) + *(input_u + x) = *(putin_u + x); + //memcpy (input_u, putin_u, width >> 1); + input_u += width >> shift_h; + putin_u += width >> shift_h; + } + + /* V component Top */ + for (line = 0; line < (top >> shift_v); line++) { + //memcpy (input_v, putin_v, width >> 1); + for (x = 0; x < (width >> shift_h); x++) { + *(input_v + x) = *(putin_v + x); + } + input_v += width >> shift_h; + putin_v += width >> shift_h; + } + /* Left and Right */ + rightvector = input_v + ((left + input_active_width) >> shift_h); + for (line = 0; line < (input_active_height >> shift_v); line++) { + for (x = 0; x < (left >> shift_h); x++) + *(input_v + x) = *(putin_v + x); + + //memcpy (input_v, putin_v, left >> 1); + //memcpy (rightvector, putin_v + ((left+input_active_width)>>1), right >> 1); + for (x = 0; x < (right >> shift_h); x++) + *(rightvector + x) = + *(putin_v + ((left + input_active_width + x) >> shift_h)); + + input_v += width >> shift_h; + rightvector += width >> shift_h; + putin_v += width >> shift_h; + } + /* Bottom */ + for (line = 0; line < (bottom >> shift_v); line++) { + //memcpy (input_v, putin_v, width >> 1); + for (x = 0; x < (width >> shift_h); x++) + *(input_v + x) = *(putin_v + x); + input_v += width >> shift_h; + putin_v += width >> shift_h; + } + + +} + + + +/********************************************************************************************** + * + * frameborder_yuvdata, based upon blackborder_yuvdata. + * instead of making the borders black, fill it with pixels coming from the second YUV420 frame. + **********************************************************************************************/ +void ffframeborder_yuvdata(uint8_t * input_y, uint8_t * input_u, + uint8_t * input_v, uint8_t * putin_y, + uint8_t * putin_u, uint8_t * putin_v, int width, + int height, int top, int bottom, int left, + int right, int wshift, int hshift) +{ + + int line, x; + int input_active_width = (height - top - bottom); + int input_active_height = (width - left -right); + uint8_t *rightvector; + int uv_top = top >> hshift; + int uv_bottom = bottom >> hshift; + int uv_left = left >> wshift; + int uv_right = right >> wshift; + int uv_width = width >> wshift; + int uv_height = height >> hshift; + int uv_input_active_height = uv_height - uv_top - uv_bottom; + int uv_input_active_width = uv_width - uv_left - uv_right; + + /* Y component TOP */ + + if(top) + { + for (line = 0; line < top; line++) { + for (x = 0; x < width; x++) { + *(input_y + x) = *(putin_y + x); + } + //memcpy (input_y, putin_y, width); + input_y += width; + putin_y += width; + } + } + + if(left && right) + { + rightvector = input_y + left + input_active_width; + /* Y component LEFT AND RIGHT */ + for (line = 0; line < input_active_height; line++) { + for (x = 0; x < left; x++) { + *(input_y + x) = *(putin_y + x); + } + //memcpy (input_y, putin_y, left); + for (x = 0; x < right; x++) { + *(rightvector + x) = + *(putin_y + left + input_active_width + x); + } + //memcpy (rightvector, putin_y + left + input_active_width, right); + input_y += width; + rightvector += width; + putin_y += width; + } + } + + + /* Y component BOTTOM */ + if(bottom) + { + for (line = 0; line < bottom; line++) { + for (x = 0; x < width; x++) + *(input_y + x) = *(putin_y + x); + + //memcpy (input_y, putin_y, width); + input_y += width; + putin_y += width; + } + } + + + /* U V components */ + /* U component TOP */ + + if(uv_top) + { + for (line = 0; line < uv_top; line++) + { + for (x = 0; x < uv_width; x++) + { + *(input_u + x) = *(putin_u + x); + } + input_u += uv_width; + putin_u += uv_width; + } + } + + + if(left && right) + { + rightvector = input_u + uv_left + uv_input_active_width; + for (line = 0; line < uv_input_active_height; line++) + { + //memcpy (input_u, putin_u, left >> 1); + for (x = 0; x < uv_left; x++) + { + *(input_u + x) = *(putin_u + x); + } + //memcpy (rightvector, putin_u + ((left + input_active_width)>>1) , right >> 1); + for (x = 0; x < uv_right; x++) + { + *(rightvector + x) = *(putin_u + + uv_left + uv_input_active_width + x ); + + } + input_u += uv_width; + rightvector += uv_width; + putin_u += uv_width; + } + } + + if(uv_bottom) + { + for (line = 0; line < uv_bottom; line++) + { + for (x = 0; x < uv_width; x++) + *(input_u + x) = *(putin_u + x); + input_u += uv_width; + putin_u += uv_width; + } + } + + /* V component Top */ + if(uv_top) + { + for (line = 0; line < uv_top; line++) + { + for (x = 0; x < uv_width; x++) + *(input_v + x) = *(putin_v + x); + input_v += uv_width; + putin_v += uv_width; + } + } + + if(uv_left && uv_right) + { + /* Left and Right */ + rightvector = input_v + uv_left + uv_input_active_width; + for (line = 0; line < uv_input_active_height; line++) + { + for (x = 0; x < uv_left; x++) + *(input_v + x) = *(putin_v + x); + + for (x = 0; x < uv_right; x++) + *(rightvector + x) = + *(putin_v + uv_left + uv_input_active_width + x); + + input_v += uv_width; + rightvector += uv_width; + putin_v += uv_width; + + } + } + + if(uv_bottom) + { + /* Bottom */ + for (line = 0; line < uv_bottom; line++) { + for (x = 0; x < uv_width; x++) + *(input_v + x) = *(putin_v + x); + input_v += uv_width; + putin_v += uv_width; + } + } +} + + + +void blackborder_yuvdata(uint8_t * input_y, uint8_t * input_u, + uint8_t * input_v, int width, int height, int top, + int bottom, int left, int right, int wshift, int hshift, int color) +{ + int line, x; + int input_active_width; + int input_active_height; + uint8_t *rightvector; + uint8_t colorY = bl_pix_get_color_y(color); + uint8_t colorCb= bl_pix_get_color_cb(color); + uint8_t colorCr= bl_pix_get_color_cr(color); + input_active_height = height - top - bottom; + input_active_width = width - left - right; + + /* Y component TOP */ + for (line = 0; line < top; line++) { + for (x = 0; x < width; x++) { + *(input_y + x) = colorY; + } + //memcpy (input_y, putin_y, width); + input_y += width; + } + rightvector = input_y + left + input_active_width; + /* Y component LEFT AND RIGHT */ + for (line = 0; line < input_active_height; line++) { + for (x = 0; x < left; x++) { + *(input_y + x) = colorY; + } + //memcpy (input_y, putin_y, left); + for (x = 0; x < right; x++) { + *(rightvector + x) = colorY; + } + //memcpy (rightvector, putin_y + left + input_active_width, right); + input_y += width; + rightvector += width; + } + /* Y component BOTTOM */ + for (line = 0; line < bottom; line++) { + for (x = 0; x < width; x++) + *(input_y + x) = colorY; + + //memcpy (input_y, putin_y, width); + input_y += width; + } + + + /* U component TOP */ + for (line = 0; line < (top >> hshift); line++) { + for (x = 0; x < (width >> wshift); x++) { + *(input_u + x) = colorCb; + } + //memcpy (input_u, putin_u, width >> 1); + input_u += width >> wshift; + } + + rightvector = input_u + ((left + input_active_width) >> wshift); + for (line = 0; line < (input_active_height >> hshift); line++) { + //memcpy (input_u, putin_u, left >> 1); + for (x = 0; x < (left >> wshift); x++) { + *(input_u + x) = colorCb; + } + //memcpy (rightvector, putin_u + ((left + input_active_width)>>1) , right >> 1); + for (x = 0; x < (right >> wshift); x++) { + *(rightvector + x) = colorCb; + } + input_u += width >> wshift; + rightvector += width >> wshift; + } + + for (line = 0; line < (bottom >> hshift); line++) { + for (x = 0; x < (width >> wshift); x++) + *(input_u + x) = colorCb; + //memcpy (input_u, putin_u, width >> 1); + input_u += width >> wshift; + } + + /* V component Top */ + for (line = 0; line < (top >> hshift); line++) { + //memcpy (input_v, putin_v, width >> 1); + for (x = 0; x < (width >> wshift); x++) { + *(input_v + x) = colorCr; + } + input_v += width >> wshift; + } + /* Left and Right */ + rightvector = input_v + ((left + input_active_width) >> wshift); + for (line = 0; line < (input_active_height >> hshift); line++) { + for (x = 0; x < (left >> wshift); x++) + *(input_v + x) = colorCr; + + //memcpy (input_v, putin_v, left >> 1); + //memcpy (rightvector, putin_v + ((left+input_active_width)>>1), right >> 1); + for (x = 0; x < (right >> wshift); x++) + *(rightvector + x) =colorCr; + + input_v += width >> wshift; + rightvector += width >> wshift; + } + /* Bottom */ + for (line = 0; line < (bottom >> hshift); line++) { + //memcpy (input_v, putin_v, width >> 1); + for (x = 0; x < (width >> wshift); x++) + *(input_v + x) = colorCr; + input_v += width >> wshift; + } +} + + +// fastrand (C) FUKUCHI, Kentaro (EffectTV) +unsigned int fastrand(int val) +{ + return (val = val * 1103516245 + 12345); +} + + +/* function to blend luminance pixel */ +pix_func_Y get_pix_func_Y(const int pix_type) +{ + if (pix_type == 0) + return &bl_pix_swap_Y; + if (pix_type == VJ_EFFECT_BLEND_ADDDISTORT) + return &bl_pix_add_distorted_Y; + if (pix_type == VJ_EFFECT_BLEND_SUBDISTORT) + return &bl_pix_sub_distorted_Y; + if (pix_type == VJ_EFFECT_BLEND_MULTIPLY) + return &bl_pix_multiply_Y; + if (pix_type == VJ_EFFECT_BLEND_DIVIDE) + return &bl_pix_divide_Y; + if (pix_type == VJ_EFFECT_BLEND_ADDITIVE) + return &bl_pix_additive_Y; + if (pix_type == VJ_EFFECT_BLEND_SUBSTRACTIVE) + return &bl_pix_substract_Y; + if (pix_type == VJ_EFFECT_BLEND_SOFTBURN) + return &bl_pix_softburn_Y; + if (pix_type == VJ_EFFECT_BLEND_INVERSEBURN) + return &bl_pix_inverseburn_Y; + if (pix_type == VJ_EFFECT_BLEND_COLORDODGE) + return &bl_pix_colordodge_Y; + if (pix_type == VJ_EFFECT_BLEND_MULSUB) + return &bl_pix_mulsub_Y; + if (pix_type == VJ_EFFECT_BLEND_LIGHTEN) + return &bl_pix_lighten_Y; + if (pix_type == VJ_EFFECT_BLEND_DIFFERENCE) + return &bl_pix_difference_Y; + if (pix_type == VJ_EFFECT_BLEND_DIFFNEGATE) + return &bl_pix_diffnegate_Y; + if (pix_type == VJ_EFFECT_BLEND_EXCLUSIVE) + return &bl_pix_exclusive_Y; + if (pix_type == VJ_EFFECT_BLEND_BASECOLOR) + return &bl_pix_basecolor_Y; + if (pix_type == VJ_EFFECT_BLEND_FREEZE) + return &bl_pix_freeze_Y; + if (pix_type == VJ_EFFECT_BLEND_UNFREEZE) + return &bl_pix_unfreeze_Y; + if (pix_type == VJ_EFFECT_BLEND_HARDLIGHT) + return &bl_pix_hardlight_Y; + if (pix_type == VJ_EFFECT_BLEND_RELADD) + return &bl_pix_relativeadd_Y; + if (pix_type == VJ_EFFECT_BLEND_RELSUB) + return &bl_pix_relativesub_Y; + if (pix_type == VJ_EFFECT_BLEND_MAXSEL) + return &bl_pix_maxsel_Y; + if (pix_type == VJ_EFFECT_BLEND_MINSEL) + return &bl_pix_minsel_Y; + if (pix_type == VJ_EFFECT_BLEND_RELADDLUM) + return &bl_pix_relativeadd_Y; + if (pix_type == VJ_EFFECT_BLEND_RELSUBLUM) + return &bl_pix_relativesub_Y; + if (pix_type == VJ_EFFECT_BLEND_MINSUBSEL) + return &bl_pix_minsubsel_Y; + if (pix_type == VJ_EFFECT_BLEND_MAXSUBSEL) + return &bl_pix_maxsubsel_Y; + if (pix_type == VJ_EFFECT_BLEND_ADDSUBSEL) + return &bl_pix_addsubsel_Y; + if (pix_type == VJ_EFFECT_BLEND_ADDAVG) + return &bl_pix_dblbneg_Y; + if (pix_type == VJ_EFFECT_BLEND_ADDTEST2) + return &bl_pix_dblbneg_Y; + if (pix_type == VJ_EFFECT_BLEND_ADDTEST3) + return &bl_pix_relneg_Y; + if (pix_type == VJ_EFFECT_BLEND_ADDTEST4) + return &bl_pix_test3_Y; + /* + if(pix_type == VJ_EFFECT_BLEND_SELECTMIN) return &bl_pix_minsel_Y; + if(pix_type == VJ_EFFECT_BLEND_SELECTMAX) return &bl_pix_maxsel_Y; + if(pix_type == VJ_EFFECT_BLEND_SELECTDIFF) return &bl_pix_seldiff_Y; + if(pix_type == VJ_EFFECT_BLEND_SELECTDIFFNEG) return &bl_pix_seldiffneg_Y; + if(pix_type == VJ_EFFECT_BLEND_ADDLUM) return &bl_pix_relativeadd_Y; + if(pix_type == VJ_EFFECT_BLEND_SELECTFREEZE) return &bl_pix_selfreeze_Y; + if(pix_type == VJ_EFFECT_BLEND_SELECTUNFREEZE) return &bl_pix_selunfreeze_Y; + */ + return &bl_pix_noswap_Y; +} + +/* function to blend chrominance pixel */ +pix_func_C get_pix_func_C(const int pix_type) +{ + if (pix_type == 0) + return &bl_pix_swap_C; + if (pix_type == VJ_EFFECT_BLEND_ADDDISTORT) + return &bl_pix_add_distorted_C; + if (pix_type == VJ_EFFECT_BLEND_SUBDISTORT) + return &bl_pix_sub_distorted_C; + if (pix_type == VJ_EFFECT_BLEND_RELADD) + return &bl_pix_relativeadd_C; + if (pix_type == VJ_EFFECT_BLEND_ADDTEST2) + return &bl_pix_dblbneg_C; + if (pix_type == VJ_EFFECT_BLEND_ADDTEST3) + return &bl_pix_relneg_C; + if (pix_type == VJ_EFFECT_BLEND_ADDTEST4) + return &bl_pix_test3_C; + /* + if(pix_type == VJ_EFFECT_BLEND_SELECTMAX) return &bl_pix_swap_C; + if(pix_type == VJ_EFFECT_BLEND_SELECTDIFF) return &bl_pix_swap_C; + if(pix_type == VJ_EFFECT_BLEND_SELECTDIFFNEG) return &bl_pix_swap_C; + if(pix_type == VJ_EFFECT_BLEND_SELECTFREEZE) return &bl_pix_swap_C; + if(pix_type == VJ_EFFECT_BLEND_SELECTUNFREEZE) return &bl_pix_swap_C; + */ + return &bl_pix_noswap_C; +} + + +/* point arithemetic , these are blending functions. */ + +/* multiply pixel a with pixel b */ +uint8_t bl_pix_multiply_Y(uint8_t y1, uint8_t y2) +{ + return ( (y1 * y2) >> 8); +} +/* divide pixel a with pixel b */ +uint8_t bl_pix_divide_Y(uint8_t y1, uint8_t y2) +{ + int c = y1 * y2; + int b = 0xff - y2; + if( b <= pixel_Y_lo_ || c <= pixel_Y_lo_ ) + return pixel_Y_lo_; + return ( c / b ); +} + +uint8_t bl_pix_additive_Y(uint8_t y1, uint8_t y2) +{ + return (y1 + ((2 * y2) - 0xff) ); +} + + +uint8_t bl_pix_substract_Y(uint8_t y1, uint8_t y2) +{ + return ( y1 + (y2 - 0xff ) ); +} + +uint8_t bl_pix_softburn_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (a + b < 0xff) { + if (a > pixel_Y_hi_) { + new_Y = pixel_Y_hi_; + } else { + new_Y = (b >> 7) / (256 - a); + if (new_Y > pixel_Y_hi_) + new_Y = pixel_Y_hi_; + } + } else { + new_Y = 0xff - (((0xff - a) >> 7) / b); + } + return new_Y; +} + +uint8_t bl_pix_inverseburn_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (a <= pixel_Y_lo_) { + new_Y = pixel_Y_lo_; + } else { + new_Y = 0xff - (((0xff - b) >> 8) / a); + } + return new_Y; +} + + +uint8_t bl_pix_colordodge_Y(uint8_t y1, uint8_t y2) +{ + if(y1 > pixel_Y_hi_ ) + y1 = pixel_Y_hi_; + return ((y2 >> 8) / (256 - y1)); +} + +uint8_t bl_pix_mulsub_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b; + a = y1; + b = (0xff - y2); + if( a < 16 ) + a = 16; + if (b < 16) + b = 16; + return ( a / b ); +} + +uint8_t bl_pix_lighten_Y(uint8_t y1, uint8_t y2) +{ + if (y1 > y2) + return y1; + return y2; +} + +uint8_t bl_pix_difference_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + new_Y = abs(a - b); + return new_Y; +} + +uint8_t bl_pix_diffnegate_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = 0xff - y1; + b = y2; + return ( 0xff - abs(a - b) ); +} + +uint8_t bl_pix_exclusive_Y(uint8_t y1, uint8_t y2) +{ + return ( y1 + y2 - ((y1 * y2) >> 8) ); +} + + +uint8_t bl_pix_basecolor_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, c, new_Y; + a = y1; + b = y2; + if (a < 16) + a = 16; + if (b < 16) + b = 16; + c = a * b >> 7; + new_Y = c + a * ((0xff - (((0xff - a) * (0xff - b)) >> 7) - c) >> 7); + return new_Y; +} + +uint8_t bl_pix_freeze_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (b < 16) { + new_Y = 16; + } else { + new_Y = 0xff - ((0xff - a) * (0xff - a)) / b; + } + return new_Y; +} + +uint8_t bl_pix_unfreeze_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (a < 16) { + new_Y = 16; + } else { + if(b > 235) b = 235; + new_Y = 0xff - ((0xff - b) * (0xff - b)) / a; + } + return new_Y; +} + +uint8_t bl_pix_hardlight_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (b < 128) { + new_Y = (a * b) >> 7; + } else { + new_Y = 0xff - ((0xff - b) * (0xff - a) >> 7); + } + return new_Y; +} + +uint8_t bl_pix_relativeadd_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, c, d, new_Y; + a = y1; + b = y2; + c = a >> 1; + d = b >> 1; + new_Y = c + d; + return new_Y; +} + +uint8_t bl_pix_relativeadd_C(uint8_t y1, uint8_t y2) +{ + uint8_t new_C; + new_C = (y1 - y2 + 0xff) >> 1; + return new_C; +} + +uint8_t bl_pix_relativesub_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + new_Y = (a - b + 0xff) >> 1; + return new_Y; +} + +uint8_t bl_pix_maxsubsel_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (b > a) { + new_Y = (b - a + 0xff) >> 1; + } else { + new_Y = (a - b + 0xff) >> 1; + } + return new_Y; +} + +uint8_t bl_pix_minsubsel_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (b < a) { + new_Y = (b - a + 0xff) >> 1; + } else { + new_Y = (a - b + 0xff) >> 1; + } + return new_Y; +} + +uint8_t bl_pix_addsubsel_Y(uint8_t y1, uint8_t y2) +{ + return ( (y1 + y2) >> 1 ); +} + +uint8_t bl_pix_maxsel_Y(uint8_t y1, uint8_t y2) +{ + return ( (y2>y1 ? y2 : y1 ) ); +} + +uint8_t bl_pix_minsel_Y(uint8_t y1, uint8_t y2) +{ + return ( (y2 < y1 ? y2: y1 )); +} + + +uint8_t bl_pix_dblbneg_Y(uint8_t y1, uint8_t y2) +{ + return ( (y1 + (y2 << 1 ) - 0xff ) ); +} + +uint8_t bl_pix_dblbneg_C(uint8_t y1, uint8_t y2) +{ + return ( (y1 + (y2 << 1 ) - 0xff )); +} + +uint8_t bl_pix_muldiv_Y(uint8_t y1, uint8_t y2) +{ + if( y2 > 235 ) y2 = 235; + if( y1 < 16 ) y1 = 16; + return ( (y1*y1) / (0xff - y2 ) ); +} + +uint8_t bl_pix_add_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (b < 16) + b = 16; + if (a < 16) + a = 16; + if ((0xff - b) <= 0) { + new_Y = (a * a) >> 8; + } else { + if( b > 235) + b= 235; + new_Y = (a * a) / (0xff - b); + } + return new_Y; +} + +uint8_t bl_pix_relneg_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = 0xff - y2; + if (a < 16) + a = 16; + if (b < 16) + b = y1; + if (b < 16) + b = 16; + new_Y = (a * a) / b; + return new_Y; +} + +uint8_t bl_pix_relneg_C(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_C; + a = y1; + b = 0xff - y2; + if (b < 16) + b = y2; + if (b < 16) + b = 16; + if (a < 16) + a = 16; + new_C = (a >> 1) + (b >> 1); + if (new_C < 16) + new_C = 16; + return new_C; +} + +uint8_t bl_pix_selfreeze_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + + a = y1; + b = y2; + if (a > b) { + if (a < 16) { + new_Y = 16; + } else { + new_Y = 0xff - ((0xff - b) * (0xff - b)) / a; + } + return new_Y; + } + return 0; +} + +uint8_t bl_pix_selunfreeze_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + + a = y1; + b = y2; + if (a > b) { + if (b < 16) { + new_Y = 16; + } else { + if( a > 235 ) a = 235; + new_Y = 0xff - ((0xff - a) * (0xff - a)) / b; + if (new_Y < 16) + new_Y = 16; + } + return new_Y; + } + return 0; +} + +uint8_t bl_pix_seldiff_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b; + a = y1; + b = y2; + if (a > b) { + return (uint8_t) abs(y1 - y2); + } + return y1; +} + + +uint8_t bl_pix_seldiffneg_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + + a = y1; + b = y2; + if (a > b) { + new_Y = 0xff - abs(0xff - a - b); + return new_Y; + } + return 0; +} + +uint8_t bl_pix_swap_Y(uint8_t y1, uint8_t y2) +{ + return y2; +} + +uint8_t bl_pix_swap_C(uint8_t y1, uint8_t y2) +{ + return y2; +} + +uint8_t bl_pix_noswap_C(uint8_t y1, uint8_t y2) +{ + return y1; +} + +uint8_t bl_pix_noswap_Y(uint8_t y1, uint8_t y2) +{ + return y1; +} + +uint8_t bl_pix_add_distorted_Y(uint8_t y1, uint8_t y2) +{ + return ( y1 + y2 ); +} + +uint8_t bl_pix_add_distorted_C(uint8_t y1, uint8_t y2) +{ + return ( y1 + y2 ); +} + +uint8_t bl_pix_sub_distorted_Y(uint8_t y1, uint8_t y2) +{ + uint8_t new_Y, a, b; + a = y1; + b = y2; + new_Y = y1 - y2; + new_Y -= y2; + return new_Y; +} + +uint8_t bl_pix_sub_distorted_C(uint8_t y1, uint8_t y2) +{ + uint8_t new_C; + new_C = y1 - y2; + new_C -= y2; + return new_C; +} + + +uint8_t bl_pix_test3_Y(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_Y; + a = y1; + b = y2; + if (b < 16) + b = 16; + if (a < 16) + a = 16; + new_Y = (a >> 1) + (b >> 1); + return new_Y; +} + +uint8_t bl_pix_test3_C(uint8_t y1, uint8_t y2) +{ + uint8_t a, b, new_C; + a = y1; + b = 0xff - y2; + if (b < 16) + b = y2; + if (a < 16) + a = 16; + new_C = (a >> 1) + (b >> 1); + return new_C; +} + +void _4byte_copy( uint8_t *src, uint8_t *dst, int width,int height, int x_start, int y_start) +{ + unsigned int x = 0, y = 0; + int *in,*out; + + width = width >> 2; + + for(y = y_start; y < height; y++ ) + { + out = (int*) &dst[y*width]; + in = (int*) &src[y*width]; + for(x=x_start;x < width; x++) + { + out[x] =(((in[x] >> 24) & 0xff)) + (((in[x] >> 16) & 0xff) << 8) + (((in[x] >> 8) & 0xff) << 16) + (((in[x]) & 0xff) << 24); + } + } + +} + +int bl_pix_get_color_y(int color_num) +{ + switch (color_num) { + case VJ_EFFECT_COLOR_RED: + return VJ_EFFECT_LUM_RED; + case VJ_EFFECT_COLOR_BLUE: + return VJ_EFFECT_LUM_BLUE; + case VJ_EFFECT_COLOR_GREEN: + return VJ_EFFECT_LUM_GREEN; + case VJ_EFFECT_COLOR_CYAN: + return VJ_EFFECT_LUM_CYAN; + case VJ_EFFECT_COLOR_MAGNETA: + return VJ_EFFECT_LUM_MAGNETA; + case VJ_EFFECT_COLOR_YELLOW: + return VJ_EFFECT_LUM_YELLOW; + case VJ_EFFECT_COLOR_BLACK: + return VJ_EFFECT_LUM_BLACK; + case VJ_EFFECT_COLOR_WHITE: + return VJ_EFFECT_LUM_WHITE; + } + return VJ_EFFECT_LUM_BLACK; +} +int bl_pix_get_color_cb(int color_num) +{ + switch (color_num) { + case VJ_EFFECT_COLOR_RED: + return VJ_EFFECT_CB_RED; + case VJ_EFFECT_COLOR_BLUE: + return VJ_EFFECT_CB_BLUE; + case VJ_EFFECT_COLOR_GREEN: + return VJ_EFFECT_CB_GREEN; + case VJ_EFFECT_COLOR_CYAN: + return VJ_EFFECT_CB_CYAN; + case VJ_EFFECT_COLOR_MAGNETA: + return VJ_EFFECT_CB_MAGNETA; + case VJ_EFFECT_COLOR_YELLOW: + return VJ_EFFECT_CB_YELLOW; + case VJ_EFFECT_COLOR_BLACK: + return VJ_EFFECT_CB_BLACK; + case VJ_EFFECT_COLOR_WHITE: + return VJ_EFFECT_CB_WHITE; + } + return VJ_EFFECT_CB_BLACK; +} + +int bl_pix_get_color_cr(int color_num) +{ + switch (color_num) { + case VJ_EFFECT_COLOR_RED: + return VJ_EFFECT_CR_RED; + case VJ_EFFECT_COLOR_BLUE: + return VJ_EFFECT_CR_BLUE; + case VJ_EFFECT_COLOR_GREEN: + return VJ_EFFECT_CR_GREEN; + case VJ_EFFECT_COLOR_CYAN: + return VJ_EFFECT_CR_CYAN; + case VJ_EFFECT_COLOR_MAGNETA: + return VJ_EFFECT_CR_MAGNETA; + case VJ_EFFECT_COLOR_YELLOW: + return VJ_EFFECT_CR_YELLOW; + case VJ_EFFECT_COLOR_BLACK: + return VJ_EFFECT_CR_BLACK; + case VJ_EFFECT_COLOR_WHITE: + return VJ_EFFECT_CR_WHITE; + } + return VJ_EFFECT_CR_BLACK; +} + + +uint8_t _pf_dneg(uint8_t a, uint8_t b) +{ + uint8_t t = + 255 - ( abs ( (255 - abs((255-a)-a)) - (255-abs((255-b)-b))) ); + return ( abs( abs(t-b) - b )); +} + +uint8_t _pf_lghtn(uint8_t a, uint8_t b) +{ + if( a > b ) return a; + return b; +} + +uint8_t _pf_dneg2(uint8_t a,uint8_t b) +{ + return ( 255 - abs ( (255-a)- b ) ); +} + +uint8_t _pf_min(uint8_t a, uint8_t b) +{ + uint8_t p = ( (b < a) ? b : a); + return ( 255 - abs( (255-p) - b ) ); +} + +uint8_t _pf_max(uint8_t a,uint8_t b) +{ + uint8_t p = ( (b > a) ? b : a); + if( p<=16) p = 16; + return ( 255 - ((255 - b) * (255 - b)) / p); + +} + +uint8_t _pf_pq(uint8_t a,uint8_t b) +{ + if( a <= 16) a = 16; + if( b <= 16) b = 16; + int p = 255 - ((255-a) * (255-a)) / a; + int q = 255 - ((255-b) * (255-b)) / b; + + return ( 255 - ((255-p) * (255 - a)) / q); +} + +uint8_t _pf_none(uint8_t a, uint8_t b) +{ + return a; +} + +_pf _get_pf(int type) +{ + + switch(type) + { + + case 0: return &_pf_dneg; + case 3: return &_pf_lghtn; + case 1: return &_pf_min; + case 2: return &_pf_max; + case 5: return &_pf_pq; + case 6: return &_pf_dneg2; + + } + return &_pf_none; +} + +int calculate_luma_value(uint8_t *Y, int w , int h) { + unsigned int len = (w * h); + unsigned int sum = 0; + unsigned int i = len; + while( i ) { + sum += *(Y++); + i--; + } + return (sum/len); +} + +int calculate_cbcr_value(uint8_t *Cb,uint8_t *Cr, int w, int h) { + unsigned int len = (w * h) >> 1; + unsigned int sum = 0; + unsigned int i = len; + while( i ) { + sum += ( Cb[i] + Cr[i] ) >> 1; + i--; + } + return (sum/len); + +} + +#ifdef HAVE_ASM_MMX + +#define MMX_load8byte_mm7(data)__asm__("\n\t movq %0,%%mm7\n" : "=m" (data):) + +#endif + +void memset_ycbcr( uint8_t *in, + uint8_t *out, + uint8_t val, + unsigned int width, + unsigned int height) +{ + veejay_memset( in, val, (width*height) ); +} + +double m_get_radius( int x, int y ) +{ + return (sqrt( (x*x) + (y*y) )); +} +double m_get_angle( int x, int y ) +{ + return (atan2( (float)y,x)); +} + +double m_get_polar_x( double r, double a) +{ + return ( r * cos(a) ); +} +double m_get_polar_y( double r, double a) +{ + return ( r * sin(a) ); +} + +//copied from xine +inline void blur(uint8_t *dst, uint8_t *src, int w, int radius, int dstStep, int srcStep){ + int x; + const int length= radius*2 + 1; + const int inv= ((1<<16) + length/2)/length; + + int sum= 0; + + for(x=0; x>16; + } + + for(; x>16; + } + + for(; x>16; + } +} + +//copied from xine +inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int power, int dstStep, int srcStep){ + uint8_t temp[2][4096]; + uint8_t *a= temp[0], *b=temp[1]; + + if(radius){ + blur(a, src, w, radius, 1, srcStep); + for(; power>2; power--){ + uint8_t *c; + blur(b, a, w, radius, 1, 1); + c=a; a=b; b=c; + } + if(power>1) + blur(dst, a, w, radius, dstStep, 1); + else{ + int i; + for(i=0; ihR; + Hg = h->hG; + Hb = h->hB; + + int W = f->width; + int H = f->height; + int r = W * 3; + + veejay_memset( Hr, 0,sizeof(uint32_t) * 256 ); + veejay_memset( Hg, 0,sizeof(uint32_t) * 256 ); + veejay_memset( Hb, 0,sizeof(uint32_t) * 256 ); + + for( i = 0; i < H; i ++ ) + { + for( j = 0; j < r; j += 3 ) + { + Hr[ (rgb[i*r+j] ) ] ++; + Hg[ (rgb[i*r+j+1]) ] ++; + Hb[ (rgb[i*r+j+2]) ] ++; + } + } +} + +static void build_histogram( histogram_t *h, VJFrame *f ) +{ + unsigned int i, len; + uint32_t *H; + uint8_t *p; + + // intensity histogram + H = h->hY; + p = f->data[0]; + len = f->len; + veejay_memset( H, 0, sizeof(uint32_t) * 256 ); + for( i = 0; i < len; i ++ ) + H[ p[i] ] ++; + +} + +static void veejay_lut_calc( uint32_t *h, uint32_t *lut, int intensity, int strength, int len ) +{ + unsigned int i; + unsigned int op0 = 255 - strength; + unsigned int op1 = strength; + lut[0] = h[0]; + for( i = 1; i < 256; i ++ ) + lut[i] = lut[i-1] + h[i]; + for( i = 0; i < 256; i ++ ) + lut[i] = (lut[i] * intensity ) / len; + for( i = 0; i < 256; i ++ ) + lut[i] = (op1 * lut[i] + op0 * i ) >> 8; +} + +static void veejay_blit_histogram( uint8_t *D, uint32_t *h, int len ) +{ + unsigned int i; + for( i = 0; i < 256; i ++ ) + D[i] = (h[i] > 0 ? (len / h[i]) : 0 ); +} + + +static inline void veejay_histogram_qdraw( uint32_t *histi, histogram_t *h, VJFrame *f, uint8_t *plane, int left, int down) +{ + uint8_t lut[256]; + unsigned int i,j,len; + + len = f->len; + veejay_blit_histogram( lut, histi, len ); + + int his_height = f->height/5; + int his_width = f->width/5; + + float sx = his_width/256.0f; + float sy = his_height/256.0f; + +//@ slow! + for ( i = 0; i < 256; i ++ ) + { + for( j = 0; j < 256 ; j ++ ) + { + int dx = j * sx; + int dy = i * sy; + + int pos = (f->height - dy - 1 - down) * f->width + dx + left; + if( plane[pos] != 0xff) + plane[pos] = (lut[j] >= i ? 0xff: 0); + } + } +} + +void veejay_histogram_draw( void *his, VJFrame *org, VJFrame *f, int intensity, int strength ) +{ + histogram_t *h = (histogram_t*) his; + + veejay_histogram_analyze( his, org, 0 ); + veejay_histogram_qdraw( h->hY, h, f, f->data[0],0,0 ); + + + veejay_histogram_equalize( his, org, intensity, strength ); + veejay_histogram_analyze( his, org, 0 ); + veejay_histogram_qdraw( h->hY, h, f, f->data[0],f->width/4 + 10,0 ); +} + +void veejay_histogram_draw_rgb( void *his, VJFrame *f, uint8_t *rgb, int in, int st, int mode ) +{ + histogram_t *h = (histogram_t*) his; + + veejay_histogram_analyze_rgb(his,rgb,f ); + switch(mode) + { + case 0: + veejay_histogram_qdraw( h->hR, h, f, f->data[0], 0,f->height/4 ); + break; + case 1: + veejay_histogram_qdraw( h->hG, h, f, f->data[0], 0,f->height/4 ); + break; + case 2: + veejay_histogram_qdraw( h->hB, h, f, f->data[0], 0,f->height/4 ); + break; + case 3: + veejay_histogram_qdraw( h->hR, h , f, f->data[0], 0, f->height/4 ); + veejay_histogram_qdraw( h->hG, h , f, f->data[0], (f->width/4+10), f->height/4 ); + veejay_histogram_qdraw( h->hB, h, f, f->data[0], (f->width/4+10)*2, f->height/4 ); + break; + } + + veejay_histogram_equalize_rgb( his, f, rgb, in,st, mode ); + veejay_histogram_analyze_rgb(his,rgb,f ); + + switch(mode) + { + case 0: + veejay_histogram_qdraw( h->hR, h,f,f->data[0], 0,0 ); + break; + case 1: + veejay_histogram_qdraw( h->hG, h,f,f->data[0], 0,0); + break; + case 2: + veejay_histogram_qdraw( h->hB, h,f, f->data[0],0,0); + break; + case 3: + veejay_histogram_qdraw( h->hR, h,f,f->data[0], 0, 0 ); + veejay_histogram_qdraw( h->hG, h,f,f->data[0], (f->width/4 + 10),0 ); + veejay_histogram_qdraw( h->hB, h,f,f->data[0], (f->width/4 + 10)*2,0 ); + break; + } +} + +void veejay_histogram_equalize_rgb( void *his, VJFrame *f, uint8_t *rgb, int intensity, int strength, int mode ) +{ + histogram_t *h = (histogram_t*) his; + uint32_t LUTr[256]; + uint32_t LUTg[256]; + uint32_t LUTb[256]; + unsigned int i,j; + unsigned int len = f->len; + + uint32_t r = f->width * 3; + uint32_t H = f->height; + + switch(mode) + { + case 0: + veejay_lut_calc( h->hR, LUTr, intensity , strength , len ); + for( i = 0; i < H; i ++ ) + { + for( j = 0; j < r ; j +=3 ) + rgb[i*r+j] = LUTr[ rgb[i*r+j] ]; + } + break; + case 1: + veejay_lut_calc( h->hG, LUTg, intensity , strength , len ); + for( i = 0; i < H; i ++ ) + { + for( j = 0; j < r; j += 3 ) + rgb[ i*r+j+1 ] = LUTg[rgb[i*r+j+1]]; + } + break; + case 2: + veejay_lut_calc( h->hB, LUTb, intensity , strength , len ); + for( i = 0; i < H; i ++ ) + { + for( j = 0; j < r; j += 3 ) + rgb[i*r+j+2] = LUTb[ rgb[i*r+j+2]]; + } + break; + case 3: + veejay_lut_calc( h->hR, LUTr, intensity , strength , len ); + veejay_lut_calc( h->hG, LUTg, intensity , strength , len ); + veejay_lut_calc( h->hB, LUTb, intensity , strength , len ); + + for( i = 0; i < H; i ++ ) + { + for( j = 0; j < r ; j +=3 ) + { + rgb[i*r+j] = LUTr[ rgb[i*r+j] ]; + rgb[i*r+j+1] = LUTg[rgb[i*r+j+1]]; + rgb[i*r+j+2] = LUTb[ rgb[i*r+j+2]]; + } + } + break; + } +} + +void veejay_histogram_equalize( void *his, VJFrame *f , int intensity, int strength) +{ + histogram_t *h = (histogram_t*) his; + uint32_t LUT[256]; + unsigned int i; + uint8_t *u,*v,*y; + unsigned int len; + + len = f->len; + veejay_lut_calc( h->hY, LUT, intensity, strength, len ); + y = f->data[0]; + for( i = 0; i < len ; i ++ ) + y[i] = LUT[ y[i] ]; +} + +void veejay_histogram_analyze_rgb( void *his, uint8_t *rgb, VJFrame *f ) +{ + histogram_t *h = (histogram_t*) his; + build_histogram_rgb( rgb,h,f ); +} + +void veejay_histogram_analyze( void *his, VJFrame *f, int type ) +{ + histogram_t *h = (histogram_t*) his; + + build_histogram( h, f ); +} + +#ifndef MIN +#define MIN(a,b) ( (a)>(b) ? (b) : (a) ) +#endif +#define min4(a,b,c,d) MIN(MIN(MIN(a,b),c),d) +#define min5(a,b,c,d,e) MIN(MIN(MIN(MIN(a,b),c),d),e) + +#ifndef MAX +#define MAX(a,b) ( (a)>(b) ? (a) : (b) ) +#endif + +#define max4(a,b,c,d) MAX(MAX(MAX(a,b),c),d) + +void veejay_distance_transform8( uint8_t *plane, int w, int h, uint32_t *output) +{ + register unsigned int x,y; + const uint8_t *I = plane; + uint32_t *Id = output; + const uint32_t wid = w - 1; + const uint32_t hei = h - 2; + + for( y = 1; y < hei; y ++ ) + { + for( x = 1; x < wid; x ++ ) + { + if( I[ y * w + x ] ) + Id[ y * w + x ] = min4( + (Id[ (y-1) * w + (x-1) ]) + 1, + (Id[ (y-1) * w + x ]) + 1, + (Id[ (y-1) * w + (x+1) ]) + 1, + (Id[ y * w + (x-1) ]) + 1 ); + } + } + + for( y = hei; y > 1; y -- ) + { + for( x = wid; x > 1; x -- ) + { + if( I[ y * w + x ] ) + Id[ y * w + x ] = min5( + (Id[ (y+1) * w + (x-1) ]) + 1, + Id[ y * w + x ], + (Id[ (y+1) * w + x ]) + 1, + (Id[ y * w + (x + 1) ]) + 1, + (Id[ (y+1) * w + (x+1) ]) + 1 + ); + } + } +} + + + +void veejay_distance_transform( uint32_t *plane, int w, int h, uint32_t *output) +{ + register unsigned int x,y; + const uint32_t *I = plane; + uint32_t *Id = output; + const uint32_t wid = w - 1; + const uint32_t hei = h - 2; + + for( y = 1; y < hei; y ++ ) + { + for( x = 1; x < wid; x ++ ) + { + if( I[ y * w + x ] ) + Id[ y * w + x ] = min4( + (Id[ (y-1) * w + (x-1) ]) + 1, + (Id[ (y-1) * w + x ]) + 1, + (Id[ (y-1) * w + (x+1) ]) + 1, + (Id[ y * w + (x-1) ]) + 1 ); + } + } + + for( y = hei; y > 1; y -- ) + { + for( x = wid; x > 1; x -- ) + { + if( I[ y * w + x ] ) + Id[ y * w + x ] = min5( + (Id[ (y+1) * w + (x-1) ]) + 1, + Id[ y * w + x ], + (Id[ (y+1) * w + x ]) + 1, + (Id[ y * w + (x + 1) ]) + 1, + (Id[ (y+1) * w + (x+1) ]) + 1 + ); + } + } +} + +uint32_t veejay_component_labeling(int w, int h, uint32_t *I , uint32_t *M) +{ + uint32_t label = 0; + uint32_t x,y,i; + uint32_t p1,p2; + uint32_t Mi=0,Ma=0; + uint32_t Eq[5000]; + + uint32_t n_labels = 0; + + for( y = 1; y < (h-1); y ++ ) + { + for ( x = 1; x < (w-1); x ++ ) + { + if( I[ y * w + x] ) + { + p1 = I[ (y-1) * w + x ]; + p2 = I[ y * w + (x-1) ]; + + if( p1 == 0 && p2 == 0 ) + { + label++; + if( label > 5000 ) + return 0; + + I[ y * w + x ] = Eq[ label ] = label; + } else if ( p1 == 0 ) { + I[ y * w + x ] = p2; + } else if ( p2 == 0 ) { + I[ y * w + x ] = p1; + } else if ( p1 == p2 ) { + I[ y * w + x ] = p1; + } else { + + // Mi = min4(p1,p2,p3,p4); + // Ma = max4(p1,p2,p3,p4); + //Mi = MIN( p1,p2 ); + //Ma = MAX( p1,p2 ); + + I[ y * w + x ] = Mi; + + while( Eq[ Ma ] != Ma ) + Ma = Eq[ Ma ]; + while( Eq[ Mi ] != Mi ) + Mi = Eq[ Mi ]; + + if( Ma >= Mi ) + Eq[ Ma ] = Mi; + else + Eq[ Mi ] = Ma; + } + } + } + } + n_labels = 0; + for( i = 1; i <= label; i ++ ) + { + if( Eq[ i ] == i ) { + n_labels ++; + Eq[i] = n_labels; + } + else { + Eq[i] = Eq[ Eq[i] ]; + } + } + + if( n_labels > 5000 ) + return 0; + + for( i = 1; i < n_labels ; i ++ ) + M[ i ] = 0; + + for( y = 0; y < h ; y ++ ) + { + for( x = 0; x < w ; x ++ ) + { + if( I[y * w + x ] ) + { + I[y * w + x ] = Eq[ I[y * w + x] ]; + M[ I[y * w +x ] ]++; + } + } + } + + return n_labels; +} + +static inline int center_of_blob( + uint8_t *img, + int width, + int height, + uint8_t label, + uint32_t *dx, uint32_t *dy, uint32_t *xsize, uint32_t *ysize) +{ + unsigned int i,j; + uint32_t product_row = 0; + uint32_t pixels_row = 0; + uint32_t product_col = 0; + uint32_t pixels_col = 0; + uint32_t pixels_row_c = 0; + uint32_t product_col_c = 0; + + for( i = 0; i < height; i ++ ) + { + pixels_row = 0; + for( j = 0; j < width; j ++ ) + { + if ( img[i * width + j] == label ) + pixels_row++; + } + if( pixels_row > *(xsize) ) + *xsize = pixels_row; + product_row += (i * pixels_row); + pixels_row_c += pixels_row; + } + + for( j = 0; j < width; j ++ ) + { + pixels_col = 0; + for( i = 0; i < height; i ++ ) + { + if( img[i * width + j ] == label ) + pixels_col ++; + } + if( pixels_col > *(ysize) ) + *ysize = pixels_col; + product_col += (j * pixels_col); + product_col_c += pixels_col; + } + + + if( pixels_row_c == 0 || product_col_c == 0 ) + return 0; + + *dy = ( product_row / pixels_row_c ); + *dx = ( product_col / product_col_c ); + + return 1; +} + +int compare_l8( const void *a, const void *b ) +{ + return ( *(int*)a - *(int*)b ); +} + +uint8_t veejay_component_labeling_8(int w, int h, uint8_t *I , uint32_t *M, + uint32_t *XX, + uint32_t *YY, + uint32_t *xsize, + uint32_t *ysize, + int min_blob_weight) +{ + uint8_t label = 0; + uint32_t x,y,i; + uint8_t p1,p2; + uint32_t Mi=0,Ma=0; + uint8_t Eq[256]; + + uint8_t n_labels = 0; + + veejay_memset( Eq, 0, sizeof(Eq) ); + + for( y = 1; y < (h-1); y ++ ) + { + for ( x = 1; x < (w-1); x ++ ) + { + if( I[ y * w + x] ) + { + p1 = I[ (y-1) * w + x ]; + p2 = I[ y * w + (x-1) ]; + + if( p1 == 0 && p2 == 0 ) + { + label++; + if( label > 254 ) + { + veejay_msg(0, "available labels exceeded"); + return 0; + } + I[ y * w + x ] = Eq[ label ] = label; + } else if ( p1 == 0) { + I[ y * w + x ] = p2; + } else if ( p2 == 0 ) { + I[ y * w + x ] = p1; + } else if ( p1 == p2 ) { + I[ y * w + x ] = p1; + } else { + + Mi = MIN( p1,p2 ); + Ma = MAX( p1,p2 ); + + I[ y * w + x ] = Mi; + + while( Eq[ Ma ] != Ma ) + Ma = Eq[ Ma ]; + while( Eq[ Mi ] != Mi ) + Mi = Eq[ Mi ]; + + if( Ma >= Mi ) + Eq[ Ma ] = Mi; + else + Eq[ Mi ] = Ma; + } + } + } + } + n_labels = 0; + for( i = 1; i <= label; i ++ ) + { + if( Eq[ i ] == i ) { + n_labels ++; + Eq[i] = n_labels; + } + else { + Eq[i] = Eq[ Eq[i] ]; + } + } + + if( n_labels > 254 ) + { + veejay_msg(0, "Too many blobs"); + return 0; + } + for( i = 0; i <= n_labels ; i ++ ) + M[ i ] = 0; + + for( y = 0; y < h ; y ++ ) + { + for( x = 0; x < w ; x ++ ) + { + if( I[y * w + x ] ) + { + I[y * w + x ] = Eq[ I[y * w + x] ]; + M[ I[y * w +x ] ]++; + } + } + } + + if( n_labels <= 0 ) + return 0; + + for( i = 1; i <= n_labels; i ++ ) + { + if( (M[i] * 8) >= min_blob_weight ) + { + if(! center_of_blob( I,w,h, i, &(XX[i]), &(YY[i]), &(xsize[i]), &(ysize[i]) ) ) + { + M[i] = 0; + } + } + else + { + M[i] = 0; + } + } + + return n_labels; +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/common.h b/branches/V-1.5.3/veejay-server/libvje/effects/common.h new file mode 100644 index 00000000..88dd4468 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/common.h @@ -0,0 +1,328 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2007 Niels Elburg + * + * some portion by: (referenced) + * Copyright (C) 2001 Matthew J. Marjanovic + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#define MAX_SCRATCH_FRAMES 25 +#define func_opacity(a,b,p,q) ( ((a * p) + (b * q)) >> 8 ) +#define limit_luma(c) ( c < 16 ? 16 : ( c > 235 ? 235 : c) ) +#define limit_chroma(c) ( c < 16 ? 16 : ( c > 240 ? 240 : c) ) +#define func_multiply(a,b) ( (a * b) >> 8 ) +#define func_additive(a,b) ( a + (2 * b) - 235 ) +#define func_substractive(a,b) ( a + (b - 235) ) + + +extern int pixel_Y_hi_; +extern int pixel_U_hi_; +extern int pixel_Y_lo_; +extern int pixel_U_lo_; +#define CLAMP_Y( a ) ( a < pixel_Y_lo_ ? pixel_Y_lo_ : (a > pixel_Y_hi_ ? pixel_Y_hi_ : a ) ) +#define CLAMP_UV( a )( a < pixel_U_lo_ ? pixel_U_lo_ : (a > pixel_U_hi_ ? pixel_U_hi_ : a ) ) + +extern void set_pixel_range(uint8_t Yhi,uint8_t Uhi, uint8_t Ylo, uint8_t Ulo); + +#ifndef ARCH_X86 +# define sin_cos(si, co, x) si = sin(x); co = cos(x) +# define fast_sqrt( res,x ) res = sqrt(x) +# define fast_sin(res,x ) res = sin(x) +# define fast_cos(res,x ) res = cos(x) +# define fast_abs(res,x ) res = abs(x) +# define fast_exp(res,x ) res = exp(x) +#else +# define sin_cos(si, co, x) asm ("fsincos" : "=t" (co), "=u" (si) : "0" (x)) +# define fast_sqrt(res,x) asm ("fsqrt" : "=t" (res) : "0" (x)) +# define fast_sin(res,x) asm ("fsin" : "=t" (res) : "0" (x)) +# define fast_cos(res,x) asm ("fcos" : "=t" (res) : "0" (x)) +# define fast_abs(res,x) asm ("fabs" : "=t" (res) : "0" (x)) +# define fast_exp(res,x) asm ("fexp" : "=t" (res) : "0" (x)) +#endif + + + +#define Y_Red ( 0.29900) +#define Y_Green ( 0.58700) +#define Y_Blue ( 0.11400) + +#define U_Red (-0.16874) +#define U_Green (-0.33126) +#define U_Blue ( 0.50000) + +#define V_Red ( 0.50000) +#define V_Green (-0.41869) +#define V_Blue (-0.08131) + +/* RGB to YUV conversion, www.fourcc.org */ + +#define Y_Redco ( 0.257f ) +#define Y_Greenco ( 0.504f ) +#define Y_Blueco ( 0.098f ) + +#define U_Redco ( 0.439f ) +#define U_Greenco ( 0.368f ) +#define U_Blueco ( 0.071f ) + +#define V_Redco ( 0.148f ) +#define V_Greenco (0.291f ) +#define V_Blueco (0.439f ) + + +#define JPEGJFIF_RGB( r,g,b,y,u,v) \ + {\ + r = y + 1.40200 * ( u - 128 );\ + g = y - 0.34414 * ( v - 128 ) - 0.71414 * ( u - 128 );\ + b = y + 1.77200 * ( v - 128 );\ + } + +#define COLOR_rgb2yuv(r,g,b, y,u,v ) \ + {\ + y = (int) ( (Y_Redco * (float) r) + (Y_Greenco * (float)g) + (Y_Blueco * (float)b) + 16.0);\ + u = (int) ( (U_Redco * (float) r) - (U_Greenco * (float)g) + (U_Blueco * (float)b) + 128.0);\ + v = (int) ( -(V_Redco * (float) r) - (V_Greenco * (float)g) + (V_Blueco * (float)b) + 128.0);\ + } + +#define CCIR601_rgb2yuv(r,g,b,y,u,v) \ + {\ + float Ey = (0.299f * (float)r) + (0.587f * (float) g) + (0.114f * (float)b );\ + float Eu = (0.713f * ( ((float)r) - Ey ) );\ + float Ev = (0.564f * ( ((float)b) - Ey ) );\ + y = (int) ( 255.0 * Ey );\ + u = (int) (( 255.0 * Eu ) + 128);\ + v = (int) (( 255.0 * Ev ) + 128);\ +} + +/* + http://www.w3.org/Graphics/JPEG/jfif.txt + YCbCr (256 levels) can be computed directly from 8-bit RGB as follows: + IEC 601 + */ + +/* MJPEGtools lavtools/colorspace.c by matthew */ +#define YCBCR_to_IEC601 ( y, u, v ) \ + {\ + y = y * 219.0 / 256.0 + 16 ;\ + u = (u - 128 ) * 224.0 / 256.0 + 128;\ + v = (v - 128 ) * 224.0 / 256.0 + 128;\ + } + +#define IEC601_to_YCBCR( y, u, v ) \ + {\ + y = ( y - 16 ) / 219.0 * 256.0;\ + u = ( u - 128 ) / 224.0 * 256.0 + 128;\ + v = ( v - 128 ) / 224.0 * 256.0 + 128;\ + } + + + +static inline int myround(float n) +{ + if (n >= 0) + return (int)(n + 0.5); + else + return (int)(n - 0.5); +} +/* End colorspace.c */ + + +#define GIMP_rgb2yuv(r,g,b,y,u,v)\ + {\ + float Ey = (0.299 * (float)r) + (0.587 * (float)g) + (0.114 * (float) b);\ + float Eu = (-0.168736 * (float)r) - (0.331264 * (float)g) + (0.500 * (float)b) + 128.0;\ + float Ev = (0.500 * (float)r) - (0.418688 * (float)g) - (0.081312 * (float)b)+ 128.0;\ + y = CLAMP_Y(myround(Ey));\ + u = CLAMP_UV(myround(Eu));\ + v = CLAMP_UV(myround(Ev));\ + } + +#define CCYUV_red( r,y,u,v )\ + r = (int)( (float) y + 1.14f * (float) v) + +#define CCYUV_green( g,y,u,v )\ + g = (int)( (float)y - 0.396f * (float)u - 0.581f * (float)v) + +#define CCYUV_blue( b,y,u,v )\ + b = (int)( (float) y + 2.029f * (float) u ) + +enum +{ + GIMP_RGB=0, + CCIR601_RGB=1, + OLD_RGB=2, + JFIF_RGB=3, +}; + +#define _rgb2yuv(r,g,b,y,u,v)\ +{\ + if( rgb_parameter_conversion_type_ == GIMP_RGB )\ + GIMP_rgb2yuv(r,g,b,y,u,v)\ + if( rgb_parameter_conversion_type_ == CCIR601_RGB )\ + CCIR601_rgb2yuv(r,g,b,y,u,v)\ + if( rgb_parameter_conversion_type_ == OLD_RGB )\ + COLOR_rgb2yuv(r,g,b,y,u,v)\ +} + +typedef uint8_t (*pix_func_Y) (uint8_t y1, uint8_t y2); +typedef uint8_t (*pix_func_C) (uint8_t y1, uint8_t y2); +typedef uint8_t (*_pf) (uint8_t a, uint8_t b); + + +pix_func_Y get_pix_func_Y(const int pix_type); /* get blend function for luminance values */ +pix_func_C get_pix_func_C(const int pix_type); /* get blend function for chrominance values */ + +typedef struct +{ + uint8_t *data[3]; + int w; + int h; +} picture_t; + +typedef struct +{ + int w; + int h; +} matrix_t; + +typedef matrix_t (*matrix_f)(int i, int s, int w, int h); +matrix_t matrix_placementA(int photoindex, int size, int w , int h); +matrix_t matrix_placementB(int photoindex, int size, int w , int h); +matrix_f get_matrix_func(int type); + + + +int power_of(int size); +int max_power(int w); + +void frameborder_yuvdata(uint8_t * input_y, uint8_t * input_u, + uint8_t * input_v, uint8_t * putin_y, + uint8_t * putin_u, uint8_t * putin_v, int width, + int height, int top, int bottom, int left, + int right, int shiftw, int shifth); + +void blackborder_yuvdata(uint8_t * input_y, uint8_t * input_u, + uint8_t * input_v, int width, int height, int top, + int bottom, int left, int right, int shiftw, int shifth, int color); + +void +deinterlace(uint8_t *data, int width, int height, int noise); + + +_pf _get_pf(int type); + + +uint8_t bl_pix_additive_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_divide_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_multiply_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_substract_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_softburn_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_inverseburn_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_colordodge_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_mulsub_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_lighten_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_difference_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_diffnegate_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_exclusive_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_basecolor_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_freeze_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_unfreeze_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_hardlight_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_relativeadd_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_relativeadd_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_relativesub_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_maxsubsel_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_minsubsel_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_addsubsel_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_maxsel_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_minsel_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_dblbneg_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_dblbneg_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_muldiv_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_add_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_relneg_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_relneg_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_selfreeze_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_selunfreeze_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_seldiffneg_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_swap_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_swap_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_test3_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_test3_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_sub_distorted_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_sub_distorted_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_add_distorted_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_add_distorted_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_noswap_Y(uint8_t y1, uint8_t y2); +uint8_t bl_pix_noswap_C(uint8_t y1, uint8_t y2); +uint8_t bl_pix_seldiff_Y(uint8_t y1, uint8_t y2); +void _4byte_copy( uint8_t *src, uint8_t *dst, int width,int height, int x_start, int y_start); +unsigned int fastrand(int val); +int bl_pix_get_color_y(int color_num); +int bl_pix_get_color_cb(int color_num); +int bl_pix_get_color_cr(int color_num); + + +void memset_ycbcr( uint8_t *in, + uint8_t *out, + uint8_t val, + unsigned int width, + unsigned int height); + +double m_get_radius(int x, int y); +double m_get_angle(int x, int y); +double m_get_polar_x(double r, double a); +double m_get_polar_y(double r, double a); + +inline void blur(uint8_t *dst, uint8_t *src, int w, int radius, int dstStep, int srcStep); +inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int power, int dstStep, int srcStep); + + +extern int motionmap_active(); +extern void motionmap_scale_to( int p1max, int p2max,int p1min,int p2min, int *p1val, int *p2val, int *pos, int *len ); +extern void motionmap_lerp_frame( VJFrame *cur, VJFrame *prev, int N, int n ); +extern void motionmap_store_frame(VJFrame *fx); +extern void motionmap_interpolate_frame(VJFrame *fx, int N, int n); +extern uint8_t *motionmap_bgmap(); +extern uint32_t motionmap_activity(); + +void veejay_histogram_analyze( void *his, VJFrame *f , int t); +void veejay_histogram_del(void *his); +void *veejay_histogram_new(); +void veejay_histogram_draw( void *his, VJFrame *src, VJFrame *dst , int intensity, int strength ); +void veejay_histogram_equalize( void *his, VJFrame *f, int intensity, int strength ); + +void veejay_histogram_analyze_rgb( void *his, uint8_t *rgb, VJFrame *f ); +void veejay_histogram_equalize_rgb( void *his, VJFrame *f, uint8_t *rgb, int in, int st, int mode ); +void veejay_histogram_draw_rgb( void *his, VJFrame *f, uint8_t *rgb, int in, int st, int mode ); + +void veejay_distance_transform( uint32_t *plane, int w, int h, uint32_t *output); +void veejay_distance_transform8( uint8_t *plane, int w, int h, uint32_t *output); + + +uint8_t veejay_component_labeling_8(int w, int h, uint8_t *I , uint32_t *M, uint32_t *XX, uint32_t *YY, + uint32_t *xsize, uint32_t *ysize, int blob); + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexinvert.c b/branches/V-1.5.3/veejay-server/libvje/effects/complexinvert.c new file mode 100644 index 00000000..6edd3059 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexinvert.c @@ -0,0 +1,182 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rgbkey.h" +#include +#include "common.h" +#include "complexinvert.h" + + +vj_effect *complexinvert_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 2400; /* noise suppression*/ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 3500; + ve->has_user = 0; + ve->description = "Complex Invert"; + ve->extra_frame = 0; + ve->sub_format = 1; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( + ve->num_params, "Angle", "Red", "Green", "Blue", "Noise suppression" ); + return ve; +} + +void complexinvert_apply(VJFrame *frame, int width, + int height, int i_angle, int r, int g, int b, int i_noise) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + int kbg, x1, y1; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise / 100.0); + unsigned int pos; + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + int iy=pixel_Y_lo_,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = frame->data[0]; + fg_cb = frame->data[1]; + fg_cr = frame->data[2]; + + bg_y = frame->data[0]; + bg_cb = frame->data[1]; + bg_cr = frame->data[2]; + + for (pos = 0; pos < frame->len; pos++) + { + short xx, yy; + + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) + xx = -128; + + if (xx > 127) + xx = 127; + + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) + yy = -128; + + if (yy > 127) + yy = 127; + + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + + if (abs(yy) < val ) + { + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + Y[pos] = val; + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cb[pos] = val; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + Cr[pos] = val; + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + + + val = 255 - ((Y[pos] + (kbg * bg_y[pos])) >> 8); + Y[pos] = CLAMP_Y(val); + + val = 255 - ((Cb[pos] + (kbg * bg_cb[pos])) >> 8); + Cb[pos] = CLAMP_UV(val); + + val = 255 - ( (Cr[pos] + (kbg * bg_cr[pos])) >> 8); + Cr[pos] = CLAMP_UV(val); + } + } +} +void complexinvert_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexinvert.h b/branches/V-1.5.3/veejay-server/libvje/effects/complexinvert.h new file mode 100644 index 00000000..e1f629d2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexinvert.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COMPLEXINVERT_H +#define COMPLEXINVERT_H +#include +#include +#include + +vj_effect *complexinvert_init(); +void complexinvert_apply(VJFrame *frame, int width, + int height, int i_angle, + int red, int green, int blue, int i_noise); +void complexinvert_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexopacity.c b/branches/V-1.5.3/veejay-server/libvje/effects/complexopacity.c new file mode 100644 index 00000000..42f8a517 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexopacity.c @@ -0,0 +1,223 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include "rgbkey.h" +#include +#include +#include +#include +#include +#include "common.h" +#include "complexopacity.h" + + +vj_effect *complexopacity_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 80; /* angle */ + ve->defaults[1] = 0; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 255; /* b */ + ve->defaults[4] = 150; /* opacity */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 255; + ve->has_user = 0; + ve->description = "Complex Overlay"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( ve->num_params, "Angle", "Red", "Green", "Blue", "Opacity" ); + return ve; +} + +/* this method decides whether or not a pixel from the fg will be accepted for keying */ +int accept_ipixel(uint8_t fg_cb, uint8_t fg_cr, int cb, int cr, + int accept_angle_tg) +{ + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + uint8_t val; + + xx = ((fg_cb * cb) + (fg_cr * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = ((fg_cr * cb) - (fg_cb * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + if (abs(yy) < val) { + return 1; + } + return 0; +} + +void complexopacity_apply(VJFrame *frame, int width, + int height, int i_angle, int r, int g, int b, + int level ) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + + int cb, cr; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle / 10.0; + //float noise_level = 350.0; + unsigned int pos; + int matrix[5]; + uint8_t val; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + int iy,iu,iv; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = frame->data[0]; + fg_cb = frame->data[1]; + fg_cr = frame->data[2]; + + bg_y = frame->data[0]; + bg_cb = frame->data[1]; + bg_cr = frame->data[2]; + + for (pos = width + 1; pos < (len) - width - 1; pos++) { + int i = 0; + int smooth = 0; + /* setup matrix + [ - 0 - ] = do not accept. [ - 1 - ] = level 5 , accept only when all n = 1 + [ 0 0 0 ] [ 1 1 1 ] + [ - 0 - ] [ - 1 - ] + + [ - 0 - ] sum of all n is acceptance value for level + [ 1 0 1 ] + [ 0 1 0 ] + */ + matrix[0] = accept_ipixel(fg_cb[pos], fg_cr[pos], cb, cr, accept_angle_tg); /* center pixel */ + matrix[1] = accept_ipixel(fg_cb[pos - 1], fg_cr[pos - 1], cb, cr, accept_angle_tg); /* left pixel */ + matrix[2] = accept_ipixel(fg_cb[pos + 1], fg_cr[pos + 1], cb, cr, accept_angle_tg); /* right pixel */ + matrix[3] = accept_ipixel(fg_cb[pos + width], fg_cr[pos + width], cb, cr, accept_angle_tg); /* top pixel */ + matrix[4] = accept_ipixel(fg_cb[pos - width], fg_cr[pos - width], cb, cr, accept_angle_tg); /* bottom pixel */ + for (i = 0; i < 5; i++) { + if (matrix[i] == 1) + smooth++; + } + if (smooth >= level) { + short xx, yy; + /* get bg/fg pixels */ + uint8_t p1 = (matrix[0] == 0 ? fg_y[pos] : bg_y[pos]); + uint8_t p2 = (matrix[1] == 0 ? fg_y[pos - 1] : bg_y[pos - 1]); + uint8_t p3 = (matrix[2] == 0 ? fg_y[pos + 1] : bg_y[pos + 1]); + uint8_t p4 = + (matrix[3] == 0 ? fg_y[pos + width] : bg_y[pos + width]); + uint8_t p5 = + (matrix[4] == 0 ? fg_y[pos - width] : bg_y[pos - width]); + /* and blur the pixel */ + fg_y[pos] = (p1 + p2 + p3 + p4 + p5) / 5; + + /* convert foreground to xz coordinates where x direction is + defined by key color */ + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + /* see if pixel is within range of color and opacity it */ + if (abs(yy) < val ) { + Y[pos] = 255 - Y[pos]; + Cb[pos] = 255 - Cb[pos]; + Cr[pos] = 255 - Cr[pos]; + } + } + } +} +void complexopacity_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexsaturate.c b/branches/V-1.5.3/veejay-server/libvje/effects/complexsaturate.c new file mode 100644 index 00000000..9641e383 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexsaturate.c @@ -0,0 +1,227 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "complexsaturate.h" +#include "common.h" + +vj_effect *complexsaturation_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 7; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 50; /* v_adjust */ + ve->defaults[5] = 50; /* degrees */ + ve->defaults[6] = 2400; /* noise suppression */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 360; + + ve->limits[0][5] = 0; + ve->limits[1][5] = 256; + + ve->limits[0][6] = 0; + ve->limits[1][6] = 3500; + ve->has_user = 0; + ve->description = "Complex Saturation"; + ve->extra_frame = 0; + ve->sub_format = 1; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( ve->num_params, "Angle", "Red", "Green", "Blue", "Intensity", "Degrees", "Noise suppression" ); + return ve; +} + +void complexsaturation_apply(VJFrame *frame, int width, + int height, int i_angle, int r, int g, + int b, int adjust_v, int adjust_degrees, int i_noise) +{ +// double degrees = adjust_degrees * 0.01; +// double dsat = adjust_v * 0.01; + + + float hue = (adjust_degrees/180.0)*M_PI; + float sat = (adjust_v * 0.01); + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + int kbg, x1, y1; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise * 0.01f); + unsigned int pos; + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + int iy=pixel_Y_lo_,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = frame->data[0]; + fg_cb = frame->data[1]; + fg_cr = frame->data[2]; + + bg_y = frame->data[0]; + bg_cb = frame->data[1]; + bg_cr = frame->data[2]; + const int s = (int) rint( sin(hue) * (1<<16) * sat ); + const int c = (int) rint( cos(hue) * (1<<16) * sat ); + for (pos = 0; pos < frame->len; pos++) + { + short xx, yy; + + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) + xx = -128; + + if (xx > 127) + xx = 127; + + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) + yy = -128; + + if (yy > 127) + yy = 127; + + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + + if (abs(yy) > val) { /* pixel is within selected color range, saturate */ + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + Y[pos] = val; + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cb[pos] = val; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + Cr[pos] = val; + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + + val = (Y[pos] + (kbg * bg_y[pos])) >> 8; + Y[pos] = CLAMP_Y(val); + + val = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; + Cb[pos] = CLAMP_UV(val); + + val = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; + Cr[pos] = CLAMP_UV(val); + + int _cb = Cb[pos] - 128; + int _cr = Cr[pos] - 128; + if( _cb != 0 && _cr != 0) + { + /* double co=0.0,si=0.0; + //fast_sqrt( dsaturation, (double) (_cb * cr + _cr * _cr) ); + dsaturation = ccolor_sqrt( (double) _cb, (double) _cr); + dcolor = ccolor_sine( _cb, dsaturation); + if( _cr < 0) { + dcolor = M_PI - dcolor; + } + dcolor += (degrees * M_PI) / 180.0; + dsaturation *= dsat; + sin_cos( co, si , dcolor ); + Cb[pos] = si * dsaturation + 128; + const int u = Cb[i] - 128; + const int v = Cr[i] - 128; + int new_u = (c * u - s * v + (1<<15) + (128<<16)) >> 16; + int new_v = (s * u + c * v + (1<<15) + (128<<16)) >> 16; + if( new_u & 768 ) new_u = (-new_u) >> 31; + if( new_v & 768 ) new_v = (-new_v) >> 31; +Cr[pos] = co * dsaturation + 128;*/ + const int u = Cb[pos] - 128; + const int v = Cr[pos] - 128; + int new_u = (c * u - s * v + (1<<15) + (128<<16)) >> 16; + int new_v = (s * u + c * v + (1<<15) + (128<<16)) >> 16; + if( new_u & 768 ) new_u = (-new_u) >> 31; + if( new_v & 768 ) new_v = (-new_v) >> 31; + Cb[pos] = new_u; + Cr[pos] = new_v; + } + } + + } +} + +void complexsaturate_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexsaturate.h b/branches/V-1.5.3/veejay-server/libvje/effects/complexsaturate.h new file mode 100644 index 00000000..c85de617 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexsaturate.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COMPLEXSATURATE_H +#define COMPLEXSATURATE_H +#include +#include +#include + +vj_effect *complexsaturation_init(); +void complexsaturation_apply(VJFrame *frame, int width, + int height, int i_angle, + int red, int green, int blue, int adjust_degrees, int adjust_v, int i_noise ); +void complexsaturate_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexsync.c b/branches/V-1.5.3/veejay-server/libvje/effects/complexsync.c new file mode 100644 index 00000000..00b5211c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexsync.c @@ -0,0 +1,95 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include "complexsync.h" +#include + +static uint8_t *c_outofsync_buffer[3]; + +vj_effect *complexsync_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = height-1; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->limits[0][2] = 1; + ve->limits[1][2] = (25 * 10); + ve->defaults[0] = 36; + ve->defaults[1] = 1; + ve->defaults[2] = 1; + ve->description = "Out of Sync -Replace selection-"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Vertical size", "Mode", "Framespeed" ); + return ve; +} + +int complexsync_malloc(int width, int height) +{ + c_outofsync_buffer[0] = (uint8_t*)vj_yuvalloc(width ,height ); + c_outofsync_buffer[1] = c_outofsync_buffer[0] + (width * height ); + c_outofsync_buffer[2] = c_outofsync_buffer[1] + ( width * height ); + return 1; + +} + +void complexsync_free() { + if(c_outofsync_buffer[0]) + free(c_outofsync_buffer[0]); + c_outofsync_buffer[0] = NULL; + c_outofsync_buffer[1] = NULL; + c_outofsync_buffer[2] = NULL; +} +void complexsync_apply(VJFrame *frame, VJFrame *frame2, int width, int height, int val) +{ + + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + const unsigned int region = width * val; + + veejay_memcpy( c_outofsync_buffer[0], Y, region ); + veejay_memcpy( c_outofsync_buffer[1], Cb, region ); + veejay_memcpy( c_outofsync_buffer[2], Cr, region ); + + veejay_memcpy( Y, Y2, region ); + veejay_memcpy( Cb, Cb2, region ); + veejay_memcpy( Cr, Cr2, region ); + + if( (len - region) > 0) + { + veejay_memcpy( Y + region, c_outofsync_buffer[0], (len-region) ); + veejay_memcpy( Cb + region, c_outofsync_buffer[1], (len - region) ); + veejay_memcpy( Cr + region, c_outofsync_buffer[2], (len - region) ); + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexsync.h b/branches/V-1.5.3/veejay-server/libvje/effects/complexsync.h new file mode 100644 index 00000000..c9e426a0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexsync.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COMPLEXSYNC_H +#define COMPLEXSYNC_H +#include +#include +#include +#include + +vj_effect *complexsync_init(int width, int height); +int complexsync_malloc(int w, int h); +void complexsync_free(); +void complexsync_apply(VJFrame *frame, VJFrame *frame2, int width, int height, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexthreshold.c b/branches/V-1.5.3/veejay-server/libvje/effects/complexthreshold.c new file mode 100644 index 00000000..5da2914e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexthreshold.c @@ -0,0 +1,267 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rgbkey.h" +#include +#include +#include "common.h" +#include "complexthreshold.h" + + +vj_effect *complexthreshold_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 6; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 80; /* angle */ + ve->defaults[1] = 0; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 255; /* b */ + ve->defaults[4] = 1; /* smoothen level */ + ve->defaults[5] = 255; /* threshold */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][5] = 0; + ve->limits[1][5] = 255; + ve->limits[0][4] = 0; + ve->limits[1][4] = 4; + ve->description = "Complex Threshold (fixme)"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->has_user = 0; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( ve->num_params,"Angle", "Red", "Green", "Blue", "Smoothen", "Threshold" ); + return ve; +} + +/* this method decides whether or not a pixel from the fg will be accepted for keying */ +int accept_tpixel(uint8_t fg_cb, uint8_t fg_cr, int cb, int cr, + int accept_angle_tg) +{ + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + int val; + + xx = ((fg_cb * cb) + (fg_cr * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = ((fg_cr * cb) - (fg_cb * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + if (abs(yy) < val) { + return 1; + } + return 0; +} + +void complexthreshold_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int r, int g, int b, + int level, int threshold) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + + int cb, cr; + int kbg, x1, y1; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle / 10.0; + //float noise_level = 350.0; + unsigned int pos; + int matrix[5]; + int val, tmp1; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + int iy,iv,iu; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float)iy; + aa = (float)iu; + bb = (float)iv; + + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = Y2; + fg_cb = Cb2; + fg_cr = Cr2; + + bg_y = Y; + bg_cb = Cb; + bg_cr = Cr; + + for (pos = width + 1; pos < (len) - width - 1; pos++) { + int i = 0; + int smooth = 0; + /* setup matrix + [ - 0 - ] = do not accept. [ - 1 - ] = level 5 , accept only when all n = 1 + [ 0 0 0 ] [ 1 1 1 ] + [ - 0 - ] [ - 1 - ] + + [ - 0 - ] sum of all n is acceptance value for level + [ 1 0 1 ] + [ 0 1 0 ] + */ + matrix[0] = accept_tpixel(fg_cb[pos], fg_cr[pos], cb, cr, accept_angle_tg); /* center pixel */ + matrix[1] = accept_tpixel(fg_cb[pos - 1], fg_cr[pos - 1], cb, cr, accept_angle_tg); /* left pixel */ + matrix[2] = accept_tpixel(fg_cb[pos + 1], fg_cr[pos + 1], cb, cr, accept_angle_tg); /* right pixel */ + matrix[3] = accept_tpixel(fg_cb[pos + width], fg_cr[pos + width], cb, cr, accept_angle_tg); /* top pixel */ + matrix[4] = accept_tpixel(fg_cb[pos - width], fg_cr[pos - width], cb, cr, accept_angle_tg); /* bottom pixel */ + for (i = 0; i < 5; i++) { + if (matrix[i] == 1) + smooth++; + } + if (smooth >= level) { + short xx, yy; + /* get bg/fg pixels */ + uint8_t p1 = (matrix[0] == 0 ? fg_y[pos] : bg_y[pos]); + uint8_t p2 = (matrix[1] == 0 ? fg_y[pos - 1] : bg_y[pos - 1]); + uint8_t p3 = (matrix[2] == 0 ? fg_y[pos + 1] : bg_y[pos + 1]); + uint8_t p4 = + (matrix[3] == 0 ? fg_y[pos + width] : bg_y[pos + width]); + uint8_t p5 = + (matrix[4] == 0 ? fg_y[pos - width] : bg_y[pos - width]); + /* and blur the pixel */ + fg_y[pos] = (p1 + p2 + p3 + p4 + p5 + p1) / 6; + + /* convert foreground to xz coordinates where x direction is + defined by key color */ + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + /* see if pixel is within range of color and threshold */ + if (abs(yy) < val && fg_y[pos] > threshold) { + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + if (val > 0xff) + val = 0xff; + + Y[pos] = fg_y[pos] - val; + /* convert suppressed fg back to cbcr */ + Cb[pos] = ((x1 * cb) - (y1 * cr)) >> 7; + Cr[pos] = ((x1 * cr) - (y1 * cb)) >> 7; + + val = (yy * yy) + (kg * kg); + if (val > 0xff) + val = 0xff; + if (val < (35 * 35)) { + kbg = 255; + } + + Y[pos] = (Y[pos] + (kbg * bg_y[pos])) >> 8; + // Y[pos] = CLAMP_Y(val); + + Cb[pos] = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; + // Cb[pos] = CLAMP_UV(val); + + Cr[pos] = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; + // Cr[pos] = CLAMP_UV(val); + } + } + } +} +void complexthreshold_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/complexthreshold.h b/branches/V-1.5.3/veejay-server/libvje/effects/complexthreshold.h new file mode 100644 index 00000000..ebfc3db3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/complexthreshold.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef COMPLEXTHRESHOLD_H +#define COMPLEXTHRESHOLD_H +#include +#include +#include + +vj_effect *complexthreshold_init(); +void complexthreshold_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int red, int green, + int blue, int level, int threshold); +void complexthreshold_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/constantblend.c b/branches/V-1.5.3/veejay-server/libvje/effects/constantblend.c new file mode 100644 index 00000000..9e26fcfc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/constantblend.c @@ -0,0 +1,77 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* Blend + (add, substract,mult, divide) between source image and constant value + cat libvje/internal.h |grep BLEND + Most of the blending parameters ignore p3 and p4 (default values 128) + + */ + +#include +#include +#include +#include +#include "constantblend.h" +#include "common.h" +vj_effect *constantblend_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 31; + ve->limits[0][1] = 0; // scale from 0.0 to 5.0 (only luma) + ve->limits[1][1] = 500; + ve->limits[0][2] = pixel_Y_lo_; + ve->limits[1][2] = pixel_Y_hi_; + ve->defaults[0] = 1; // blend type (additive) + ve->defaults[1] = 110; // scale before blend + ve->defaults[2] = 16; // constant Y + ve->description = "Constant Luminance Blend"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Threshold", "Constant" ); + return ve; +} + +void constantblend_apply( VJFrame *frame, int width, int height, + int type, int scale, int valY ) +{ + unsigned int i; + const int len = (width * height); + const uint8_t y = (uint8_t) valY; + const float s = ((float) scale / 100.0 ); + + pix_func_Y blend_y = get_pix_func_Y( type ); + + uint8_t *Y = frame->data[0]; + + for (i = 0; i < len; i++) + { + int tmp_val =(int)( ((float) *(Y)) * s); + *(Y)++ = blend_y( (uint8_t) ( (uint8_t) tmp_val ) , y ); + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/constantblend.h b/branches/V-1.5.3/veejay-server/libvje/effects/constantblend.h new file mode 100644 index 00000000..2a2b675f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/constantblend.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef constantblend_H +#define constantblend_H +#include +#include +#include + +vj_effect *constantblend_init(int w, int h); +void constantblend_apply( VJFrame *frame, int width, int height, int a, + int b, int c ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/contourextract.c b/branches/V-1.5.3/veejay-server/libvje/effects/contourextract.c new file mode 100644 index 00000000..ee55f6ff --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/contourextract.c @@ -0,0 +1,388 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "diff.h" +#include "common.h" +#include +#include +#include +#include +#include +#include +#include + +#include "softblur.h" +static uint8_t *static_bg = NULL; +static int take_bg_ = 0; +static uint32_t *dt_map = NULL; +static void *shrink_ = NULL; +static sws_template template_; +static VJFrame to_shrink_; +static VJFrame shrinked_; +static int dw_, dh_; +static int x_[255]; +static int y_[255]; +static void *proj_[255]; + +typedef struct +{ + uint32_t *data; + uint8_t *bitmap; + uint8_t *current; +} contourextract_data; + +typedef struct +{ + int x; + int y; +} point_t; + +static point_t **points = NULL; + + +vj_effect *contourextract_init(int width, int height) +{ + //int i,j; + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; /* reverse */ + ve->limits[1][1] = 1; + ve->limits[0][2] = 0; /* show thresholded image / contour */ + ve->limits[1][2] = 2; + ve->limits[0][3] = 1; /* thinning */ + ve->limits[1][3] = 100; + ve->limits[0][4] = 1; /* minimum blob weight */ + ve->limits[1][4] = 5000; + + ve->defaults[0] = 30; + ve->defaults[1] = 0; + ve->defaults[2] = 0; + ve->defaults[3] = 3; + ve->defaults[4] = 200; + + ve->description = "Contour extraction"; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 1; + ve->user_data = NULL; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Mode", "Show image/contour", "Thinning", "Min weight" ); + return ve; +} + +void contourextract_destroy(void) +{ + if(static_bg) + free(static_bg); + if(dt_map) + free(dt_map); + static_bg = NULL; + dt_map = NULL; + +} + +#define ru8(num)(((num)+8)&~8) +static int nearest_div(int val ) +{ + int r = val % 8; + while(r--) + val--; + return val; +} +int contourextract_malloc(void **d, int width, int height) +{ + contourextract_data *my; + *d = (void*) vj_calloc(sizeof(contourextract_data)); + my = (contourextract_data*) *d; + + dw_ = nearest_div( width / 8 ); + dh_ = nearest_div( height / 8 ); + + my->current = (uint8_t*) vj_calloc( ru8( sizeof(uint8_t) * dw_ * dh_ * 3 ) ); + my->data = (uint32_t*) vj_calloc( ru8(sizeof(uint32_t) * width * height) ); + my->bitmap = (uint8_t*) vj_calloc( ru8(sizeof(uint8_t) * width * height )); + + if(static_bg == NULL) + static_bg = (uint8_t*) vj_calloc( ru8( width + width * height * sizeof(uint8_t)) ); + if(dt_map == NULL ) + dt_map = (uint32_t*) vj_calloc( ru8(width * height * sizeof(uint32_t) + width ) ); + + veejay_memset( &template_, 0, sizeof(sws_template) ); + veejay_memset( proj_, 0, sizeof(proj_) ); + + template_.flags = 1; + + vj_get_yuvgrey_template( &to_shrink_, width, height ); + vj_get_yuvgrey_template( &shrinked_ , dw_, dh_ ); + + shrink_ = yuv_init_swscaler( + &(to_shrink_), + &(shrinked_), + &template_ , + yuv_sws_get_cpu_flags() ); + + points = (point_t**) vj_calloc( sizeof(point_t*) * 12000 ); + int i; + for( i = 0; i < 12000; i ++ ) + { + points[i] = (point_t*) vj_calloc( sizeof(point_t) ); + } + + veejay_memset( x_, 0, sizeof(x_) ); + veejay_memset( y_, 0, sizeof(y_) ); + + return 1; +} + +void contourextract_free(void *d) +{ + if(d) + { + contourextract_data *my = (contourextract_data*) d; + if(my->data) free(my->data); + if(my->current) free(my->current); + if(my->bitmap) free(my->bitmap); + free(d); + } + + if( shrink_ ) + { + yuv_free_swscaler( shrink_ ); + shrink_ = NULL; + } + + int i; + for( i = 0; i < 255; i++ ) + if( proj_[i] ) + viewport_destroy( proj_[i] ); + for( i = 0; i < 12000; i ++ ) + { + if(points[i]) + free(points[i]); + } + free(points); + + d = NULL; +} + +int contourextract_prepare(uint8_t *map[3], int width, int height) +{ + if(!static_bg ) + { + return 0; + } + + veejay_memcpy( static_bg, map[0], (width*height)); + + VJFrame tmp; + veejay_memset( &tmp, 0, sizeof(VJFrame)); + tmp.data[0] = static_bg; + tmp.width = width; + tmp.height = height; + softblur_apply( &tmp, width,height,0); + + veejay_msg(2, "Contour extraction: Snapped background frame"); + return 1; +} + +static void binarify( uint8_t *bm, uint32_t *dst, uint8_t *bg, uint8_t *src,int threshold,int reverse, const int len ) +{ + int i; + if(!reverse) + { + for( i = 0; i < len; i ++ ) + { + if ( abs(bg[i] - src[i]) <= threshold ) + { dst[i] = 0; bm[i] = 0; } + else + { dst[i] = 1; bm[i] = 0xff; } + } + + } + else + { + for( i = 0; i < len; i ++ ) + { + if ( abs(bg[i] - src[i]) >= threshold ) + { dst[i] = 0; bm[i] = 0; } + else + { dst[i] = 1; bm[i] = 0xff; } + + } + } +} + +static void contourextract_centroid() +{ + +} + +static int bg_frame_ = 0; + +void contourextract_apply(void *ed, VJFrame *frame,int width, int height, + int threshold, int reverse,int mode, int take_bg, int feather, int min_blob_weight) +{ + + unsigned int i,j,k; + const uint32_t len = frame->len; + const uint32_t uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + uint32_t cx[256]; + uint32_t cy[256]; + uint32_t xsize[256]; + uint32_t ysize[256]; + + float sx = (float) width / (float) dw_; + float sy = (float) height / (float) dh_; + float sw = (float) sqrt( sx * sy ); + + veejay_memset( cx,0,sizeof(cx)); + veejay_memset( cy,0,sizeof(cy)); + + veejay_memset( xsize,0,sizeof(xsize)); + veejay_memset( ysize,0,sizeof(ysize)); + + contourextract_data *ud = (contourextract_data*) ed; + + if( take_bg != take_bg_ ) + { + veejay_memcpy( static_bg, frame->data[0], frame->len ); + take_bg_ = take_bg; + bg_frame_ ++; + return; + } + if( bg_frame_ > 0 && bg_frame_ < 4 ) + { + for( i = 0 ; i < len ; i ++ ) + { + static_bg[i] = (static_bg[i] + Y[i] ) >> 1; + } + bg_frame_ ++; + return; + } + + int packets = 0; + + //@ clear distance transform map + veejay_memset( dt_map, 0 , len * sizeof(uint32_t) ); + + //@ todo: optimize with mmx + binarify( ud->bitmap, ud->data, static_bg, frame->data[0], threshold, reverse,len ); + + if(mode==1) + { + //@ show difference image in grayscale + veejay_memcpy( Y, ud->bitmap, len ); + veejay_memset( Cb, 128, uv_len ); + veejay_memset( Cr, 128, uv_len ); + return; + } + + //@ calculate distance map + veejay_distance_transform( ud->data, width, height, dt_map ); + + to_shrink_.data[0] = ud->bitmap; + shrinked_.data[0] = ud->current; + + uint32_t blobs[255]; + + veejay_memset( blobs, 0, sizeof(blobs) ); + + yuv_convert_and_scale_grey( shrink_, &to_shrink_, &shrinked_ ); + + uint32_t labels = veejay_component_labeling_8(dw_,dh_, shrinked_.data[0], blobs, cx,cy,xsize,ysize, + min_blob_weight); + + veejay_memset( Y, 0, len ); + veejay_memset( Cb , 128, uv_len); + veejay_memset( Cr , 128, uv_len ); + + int num_objects = 0; + for( i = 1 ; i <= labels; i ++ ) + if( blobs[i] ) + num_objects ++; + + + //@ Iterate over blob's bounding boxes and extract contours + for( i = 1; i <= labels; i ++ ) + { + if( blobs[i] > 0 ) + { + int nx = cx[i] * sx; + int ny = cy[i] * sy; + int size_x = xsize[i] * sx; + int size_y = ysize[i] * sy * 0.5; + int x1 = nx - size_x; + int y1 = ny - size_y; + int x2 = nx + size_y; + int y2 = ny + size_y; + int n_points = 0; + int center = 0; + int dx1 = 0,dy1=0; + + + if( x1 < 0 ) x1 = 0; else if ( x1 > width ) x1 = width; + if( x2 < 0 ) x2 = 0; else if ( x2 > width ) x2 = width; + if( y1 < 0 ) y1 = 0; else if ( y1 >= height ) y1 = height -1; + if( y2 < 0 ) y2 = 0; else if ( y2 >= height ) y2 = height -1; + + + for( k = y1; k < y2; k ++ ) + { + for( j = x1; j < x2; j ++ ) + { + //@ use distance transform map to find centroid (fuzzy) + if( dt_map[ (k * width + j) ] > center ) + { + center = dt_map[ (k* width +j) ]; + dx1 = j; + dy1 = k; + } + if( dt_map[ (k * width + j) ] == feather ) + { + Y[ (k * width +j)] = 0xff; + points[ n_points ]->x = j; + points[ n_points ]->y = k; + n_points++; + if( n_points >= 11999 ) + { + veejay_msg(0, "Too many points in contour"); + return; + } + } + } + } + } + } + +} + + + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/contourextract.h b/branches/V-1.5.3/veejay-server/libvje/effects/contourextract.h new file mode 100644 index 00000000..4243a42e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/contourextract.h @@ -0,0 +1,34 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CONTEFFECT_H +#define CONTEFFECT_H +#include +#include +#include + +vj_effect *contourextract_init(int width, int height); +void contourextract_free(void *d); +int contourextract_malloc(void **c, int w, int h); +int contourextract_prepare(uint8_t *map[3], int w, int h); +void contourextract_apply(void *d , VJFrame *frame,int width, int height, + int th, int reverse, int show, int feather, int blob); +void contourextract_destroy(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/contrast.c b/branches/V-1.5.3/veejay-server/libvje/effects/contrast.c new file mode 100644 index 00000000..2fec1312 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/contrast.c @@ -0,0 +1,110 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "contrast.h" +#include "common.h" +vj_effect *contrast_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 2; /* type */ + ve->defaults[1] = 125; + ve->defaults[2] = 200; + ve->limits[0][0] = 0; + ve->limits[1][0] = 2; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->description = "Contrast"; + ve->has_user = 0; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Intensity 1", "Intensity 2" ); + return ve; +} + +/* also from yuvdenoise */ +void contrast_cb_apply(VJFrame *frame, int width,int height, int *s) { + unsigned int r; + register int cb; + register int cr; + const int uv_len = frame->uv_len; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + for(r=0; r < uv_len; r++) { + cb = Cb[r]; + cb -= 128; + cb *= s[2]; + cb = (cb + 50)/100; + cb += 128; + + cr = Cr[r]; + cr -= 128; + cr *= s[2]; + cr = (cr + 50)/100; + cr += 128; + + Cb[r] = CLAMP_UV(cb); + Cr[r] = CLAMP_UV(cr); + } +} + +void contrast_y_apply(VJFrame *frame, int width, int height, int *s) { + unsigned int r; + register int m; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + + for(r=0; r < len; r++) { + m = Y[r]; + m -= 128; + m *= s[1]; + m = (m + 50)/100; + m += 128; + Y[r] = CLAMP_Y(m); + } + +} + +void contrast_apply(VJFrame *frame, int width, int height, int *s ) { + + switch(s[0]) { + case 0: + contrast_y_apply(frame, width,height, s); + break; + case 1: + contrast_cb_apply(frame,width,height,s); + break; + case 2: + contrast_y_apply(frame,width,height,s); + contrast_cb_apply(frame,width,height,s); + break; + } +} + +void contrast_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/contrast.h b/branches/V-1.5.3/veejay-server/libvje/effects/contrast.h new file mode 100644 index 00000000..89be1eb6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/contrast.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CONTRAST_H +#define CONTRAST_H +#include +#include +#include + +vj_effect *contrast_init(); + + +void contrast_apply(VJFrame *frame, int w, int h, int *t); + +void contrast_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/crosspixel.c b/branches/V-1.5.3/veejay-server/libvje/effects/crosspixel.c new file mode 100644 index 00000000..40491633 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/crosspixel.c @@ -0,0 +1,148 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "crosspixel.h" +#include "common.h" +#include + +static uint8_t *cross_pixels[3]; + +vj_effect *crosspixel_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->limits[0][1] = 1; + ve->limits[1][1] = 40; + ve->defaults[0] = 0; + ve->defaults[1] = 2; + ve->description = "Pixel Raster"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Size" ); + return ve; +} +// FIXME private + +int crosspixel_malloc(int w, int h) +{ + cross_pixels[0] = (uint8_t*)vj_yuvalloc(w,h ); + cross_pixels[1] = cross_pixels[0] + (w * h ); + cross_pixels[2] = cross_pixels[1] + (w * h); + return 1; +} + +void crosspixel_free() { + if(cross_pixels[0]) + free(cross_pixels[0]); + cross_pixels[0] = NULL; + cross_pixels[1] = NULL; + cross_pixels[2] = NULL; +} + +void crosspixel_apply(VJFrame *frame, int w, int h, int t,int v) { + unsigned int x,y,pos; + const unsigned int vv = v * 2; // only even numbers + const unsigned int u_vv = vv >> frame->shift_h; // sfhit = / 2, shift_v = 2 + + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + const int uv_width = frame->uv_width; + const int uv_height = frame->uv_height; + + unsigned int p = 0; + + veejay_memcpy( cross_pixels[0], Y, len); + veejay_memcpy( cross_pixels[1], Cb, uv_len); + veejay_memcpy( cross_pixels[2], Cr, uv_len); + + if(t==0) { + veejay_memset(Y, pixel_Y_lo_, len); + veejay_memset(Cb, 128, uv_len); + veejay_memset(Cr, 128, uv_len); + } + else + { + veejay_memset(Y, 235, len); + veejay_memset(Cb, 128, uv_len); + veejay_memset(Cr, 128, uv_len); + } + + for(y=0; y < (h>>1); y++) { + if( (y%vv)==1) { + for(x=0; x < w; x+=vv) { + for(p=0; p < vv; p++) { + pos = (x+p) + ( y * w ); + Y[(x+(y*w))] = cross_pixels[0][pos]; + } + } + } + } + + for(y=0; y < (uv_height >> frame->shift_v); y++) { + if( (y%u_vv)==1) { + for(x=0; x < uv_width; x+=u_vv) { + for(p=0; p < u_vv; p++) { + pos = (x+p) + ( y * uv_width ); + Cb[(x+(y*uv_width))] = cross_pixels[1][pos]; + Cr[(x+(y*uv_width))] = cross_pixels[2][pos]; + } + } + } + } + + + for(y=(h>>1); y < h; y++) { + if( (y%vv)==1) { + for(x=0; x < w; x+=vv) { + for(p=0; p < vv; p++) { + pos = (x+p) + ( y * w ); + Y[(x+(y*w))] = cross_pixels[0][pos]; + } + } + } + } + for(y=(uv_height >> frame->shift_v); y < uv_height; y++) { + if( (y%u_vv)==1) { + for(x=0; x < uv_width; x+=u_vv) { + for(p=0; p < u_vv; p++) { + pos = (x+p) + ( y * uv_width ); + Cb[(x+(y*uv_width))] = cross_pixels[1][pos]; + Cr[(x+(y*uv_width))] = cross_pixels[2][pos]; + } + } + } + } + + +} + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/crosspixel.h b/branches/V-1.5.3/veejay-server/libvje/effects/crosspixel.h new file mode 100644 index 00000000..07fc3b94 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/crosspixel.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CROSSPIXEL_H +#define CROSSPIXEL_H +#include +#include +#include +#include + +vj_effect *crosspixel_init(int w, int h); +int crosspixel_malloc(int w, int h); +void crosspixel_free(); +void crosspixel_apply(VJFrame *frame, int width, int height, int type, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/cutstop.c b/branches/V-1.5.3/veejay-server/libvje/effects/cutstop.c new file mode 100644 index 00000000..6d0b4f61 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/cutstop.c @@ -0,0 +1,140 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * vvCutStop - ported from vvFFPP_basic + * Copyright(C)2005 Maciek Szczesniak + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. +*/ +#include +#include +#include "common.h" +#include "split.h" +#include +#include + +static uint8_t *vvcutstop_buffer[3]; +static unsigned int frq_cnt; + +vj_effect *cutstop_init(int width , int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 40; // treshold + ve->defaults[1] = 50; // hold frame freq + ve->defaults[2] = 0; // cut mode + ve->defaults[3] = 0; // hold front/back + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 1; + + ve->description = "vvCutStop"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Frame freq", "Cut mode", "Hold front/back" ); + frq_cnt = 256; + + return ve; +} + +int cutstop_malloc(int width, int height) +{ + vvcutstop_buffer[0] = (uint8_t*)vj_yuvalloc(width,height); + vvcutstop_buffer[1] = vvcutstop_buffer[0] + (width * height ); + vvcutstop_buffer[2] = vvcutstop_buffer[1] + (width * height ); + veejay_memset( vvcutstop_buffer[1],128,(width*height)); + veejay_memset( vvcutstop_buffer[2],128,(width*height)); + return 1; +} + +void cutstop_free() { + if(vvcutstop_buffer[0]) + free(vvcutstop_buffer[0]); + vvcutstop_buffer[0] = NULL; + vvcutstop_buffer[1] = NULL; + vvcutstop_buffer[2] = NULL; +} + + +void cutstop_apply( VJFrame *frame, int width, int height, int threshold, int freq, int cutmode, int holdmode) { + int i=0; + const unsigned int len = frame->len; + + uint8_t *Yb = vvcutstop_buffer[0]; + uint8_t *Ub = vvcutstop_buffer[1]; + uint8_t *Vb = vvcutstop_buffer[2]; + uint8_t *Yd = frame->data[0]; + uint8_t *Ud = frame->data[1]; + uint8_t *Vd = frame->data[2]; + + frq_cnt = frq_cnt + freq; + + if (freq == 255 || frq_cnt > 255) { + veejay_memcpy(Yb, Yd, len); + veejay_memcpy(Ub, Ud, len); + veejay_memcpy(Vb, Vd, len); + frq_cnt = 0; + } + // moved cutmode & holdmode outside loop + if(cutmode && !holdmode) + { + for( i = 0; i < len; i ++ ) + if( threshold > Yb[i] ) + { + Yd[i] = Yb[i]; Ud[i] = Ub[i]; Vd[i] = Vb[i]; + } + } + if(cutmode && holdmode) + { + for( i = 0; i < len; i ++ ) + if( threshold > Yd[i] ) + { + Yd[i] = Yb[i]; Ud[i] = Ub[i]; Vd[i] = Vb[i]; + } + } + if(!cutmode && holdmode) + { + for( i =0 ; i < len; i ++ ) + if( threshold < Yd[i]) + { + Yd[i] = Yb[i]; Ud[i] = Ub[i]; Vd[i] = Vb[i]; + } + } + if(!cutmode && !holdmode) + { + for( i = 0; i < len; i ++ ) + if(threshold < Yb[i]) + { + Yd[i] = Yb[i]; Ud[i] = Ub[i]; Vd[i] = Vb[i]; + } + } + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/cutstop.h b/branches/V-1.5.3/veejay-server/libvje/effects/cutstop.h new file mode 100644 index 00000000..bbacf957 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/cutstop.h @@ -0,0 +1,14 @@ +#ifndef CUTSTOP_H +#define CUTSTOP_H +#include +void cutstop_free() ; + +vj_effect *cutstop_init(int width , int height); + +int cutstop_malloc(int width, int height); + +void cutstop_apply( VJFrame *frame, + int width, int height, int treshold, + int freq, int cutmode, int holdmode); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/deinterlace.c b/branches/V-1.5.3/veejay-server/libvje/effects/deinterlace.c new file mode 100644 index 00000000..14c496e4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/deinterlace.c @@ -0,0 +1,58 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "common.h" +#include "deinterlace.h" + +vj_effect *deinterlace_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->defaults[0] = 0; + + ve->description = "Deinterlace (yuvkineco)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value" ); + return ve; +} + +void deinterlace_apply(VJFrame *frame, int width, int height, int val) +{ + const unsigned int uv_width = frame->uv_width; + const unsigned int uv_height = frame->uv_height; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + deinterlace( Y, width,height,val); + deinterlace( Cb, uv_width,uv_height,val); + deinterlace( Cr, uv_width,uv_height,val); +} + +void deinterlace_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/deinterlace.h b/branches/V-1.5.3/veejay-server/libvje/effects/deinterlace.h new file mode 100644 index 00000000..eee7de8c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/deinterlace.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DEINTERLACE_H +#define DEINTERLACE_H +#include +#include +#include + +vj_effect *deinterlace_init(); +void deinterlace_apply(VJFrame *frame, int width, int height, int val); +void deinterlace_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dices.c b/branches/V-1.5.3/veejay-server/libvje/effects/dices.c new file mode 100644 index 00000000..1a3cb5a6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dices.c @@ -0,0 +1,184 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + * + * This Effect was ported from: + * EffecTV - Realtime Digital Video Effector + * Copyright (C) 2001-2002 FUKUCHI Kentaro + * + * dice.c: a 'dicing' effect + * copyright (c) 2001 Sam Mertens. This code is subject to the provisions of + * the GNU Public License. + * + */ +#include +#include +#include +#include +#include "dices.h" + +static int g_map_width = 0; +static int g_map_height = 0; +static int g_cube_size = 0; +static int g_cube_bits = 0; +static uint8_t *g_dicemap=NULL; + +void dice_create_map(int w, int h); + +typedef enum _dice_dir { + Up = 0, + Right = 1, + Down = 2, + Left = 3, +} DiceDir; + +vj_effect *dices_init(int width, int height) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 4; + ve->limits[0][0] = 0; + ve->limits[1][0] = 5; + ve->description = "Dices (EffectTV)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Dice size" ); + return ve; +} +// FIXME: private +int dices_malloc(int width, int height) +{ + g_dicemap = (uint8_t *) vj_malloc(sizeof(uint8_t) * width * height); + if(!g_dicemap) return 0; + dice_create_map(width, height); + return 1; +} + +void dices_free() { + if(g_dicemap) + free(g_dicemap); + g_dicemap = NULL; +} + +unsigned int dices_fastrand_val; +/* effectv's rand val */ +unsigned int dices_fastrand() +{ + return (dices_fastrand_val = dices_fastrand_val * 1103515245 + 12345); +} + +void dice_create_map(int w, int h) +{ + int k,x, y, i = 0; + int maplen = (w * h); + g_map_height = h >> g_cube_bits; + g_map_width = w >> g_cube_bits; + g_cube_size = 1 << g_cube_bits; + maplen = maplen / (g_map_height * g_map_width); + for( k = 0; k < maplen;k++) { + for (y = 0; y < g_map_height; y++) { + for (x = 0; x < g_map_width; x++) { + //g_dicemap[i] = j++; + //if(j==3) j=0; + g_dicemap[i] = ((1 + (rand() * (i + y))) & 0x03); + i++; + } + } + } +// fprintf(stderr, "created map of %d, %d did %d in dicemap, total is %d\n", +// w,h,i,(w*h)); +} + +void dices_apply( void* data, VJFrame *frame, int width, int height, + int cube_bits) +{ + + int i = 0, map_x, map_y, map_i = 0, base, dx, dy, di; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + if (cube_bits != g_cube_bits) { + g_cube_bits = cube_bits; + dice_create_map(width, height); + } + //printf("g_cube_bits = %d, g_cube_size= %d range = %d, %d\n", g_cube_bits, g_cube_size, g_map_width,g_map_height); + + + for (map_y = 0; map_y < g_map_height; map_y++) { + for (map_x = 0; map_x < g_map_width; map_x++) { + base = (map_y << g_cube_bits) * width + (map_x << g_cube_bits); + switch (g_dicemap[map_i]) { + case Left: + for (dy = 0; dy < g_cube_size; dy++) { + i = base + dy * width; + for (dx = 0; dx < g_cube_size; dx++) { + di = base + (dx * width) + (g_cube_size - dy - 1); + Y[di] = Y[i]; + Cb[di] = Cb[i]; + Cr[di] = Cr[i]; + i++; + } + } + break; + case Down: + for (dy = 0; dy < g_cube_size; dy++) { + di = base + dy * width; + i = base + (g_cube_size - dy - 1) * width + + g_cube_size; + for (dx = 0; dx < g_cube_size; dx++) { + i--; + Y[di] = Y[i]; + Cb[di] = Cb[i]; + Cr[di] = Cr[i]; + di++; + } + } + break; + case Right: + for (dy = 0; dy < g_cube_size; dy++) { + i = base + (dy * width); + for (dx = 0; dx < g_cube_size; dx++) { + di = base + dy + (g_cube_size - dx - 1) * width; + Y[di] = Y[i]; + Cb[di] = Cb[i]; + Cr[di] = Cr[i]; + i++; + } + } + break; + case Up: + for( dy = 0; dy < g_cube_size ; dy ++ ) + { + i = base + dy * width; + for( dx = 0; dx < g_cube_size ; dx ++ ) + { + Y[di] = Y[i]; Cb[di] = Cb[i]; Cr[di] = Cr[i]; i ++; + } + } + break; + } + map_i++; + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dices.h b/branches/V-1.5.3/veejay-server/libvje/effects/dices.h new file mode 100644 index 00000000..efc2a61e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dices.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DICES_H +#define DICES_H +#include +#include +#include + +vj_effect *dices_init(int width, int height); +int dices_malloc(int w, int h); +void dices_free(); +void dices_apply( void * data, VJFrame *frame, int width, int height, + int cube_bits); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/diff.c b/branches/V-1.5.3/veejay-server/libvje/effects/diff.c new file mode 100644 index 00000000..de278108 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/diff.c @@ -0,0 +1,246 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include "diff.h" +#include "common.h" +#include +#include +#include +#include +#include +#include +#include +#include "softblur.h" +static uint8_t *static_bg = NULL; +static int *dt_map = NULL; + +typedef struct +{ + uint8_t *data; + uint8_t *current; +} diff_data; + +vj_effect *diff_init(int width, int height) +{ + //int i,j; + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; /* reverse */ + ve->limits[1][1] = 1; + ve->limits[0][2] = 0; /* show mask */ + ve->limits[1][2] = 2; + ve->limits[0][3] = 1; /* thinning */ + ve->limits[1][3] = 100; + + ve->defaults[0] = 30; + ve->defaults[1] = 0; + ve->defaults[2] = 2; + ve->defaults[3] = 5; + + ve->description = "Map B to A (substract background mask)"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->has_user = 1; + ve->user_data = NULL; + + + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Mode", "Show mask/image", "Thinning" ); + + return ve; +} + + + +void diff_destroy(void) +{ + if(static_bg) + free(static_bg); + if(dt_map) + free(dt_map); + static_bg = NULL; + dt_map = NULL; + +} + +#define ru8(num)(((num)+8)&~8) + +int diff_malloc(void **d, int width, int height) +{ + diff_data *my; + *d = (void*) vj_calloc(sizeof(diff_data)); + my = (diff_data*) *d; + my->data = (uint8_t*) vj_calloc( ru8(sizeof(uint8_t) * width * height) ); +// my->current = my->data + (width*height); + + if(static_bg == NULL) + static_bg = (uint8_t*) vj_calloc( ru8( width + width * height * sizeof(uint8_t)) ); + if(dt_map == NULL ) + dt_map = (uint32_t*) vj_calloc( ru8(width * height * sizeof(uint32_t) + width ) ); + return 1; +} + +void diff_free(void *d) +{ + if(d) + { + diff_data *my = (diff_data*) d; + if(my->data) free(my->data); + free(d); + } + d = NULL; +} + +int diff_prepare(void *user, uint8_t *map[3], int width, int height) +{ + if(!static_bg ) + { + return 0; + } + + veejay_memcpy( static_bg, map[0], (width*height)); + + VJFrame tmp; + veejay_memset( &tmp, 0, sizeof(VJFrame)); + tmp.data[0] = static_bg; + tmp.width = width; + tmp.height = height; + softblur_apply( &tmp, width,height,0); + veejay_msg(2 , "Map B to A: Snapped background frame"); + + return 1; +} + +static void binarify( uint8_t *dst, uint8_t *bg, uint8_t *src,int threshold,int reverse, const int len ) +{ + int i; + + if(!reverse) + { + for( i = 0; i < len; i ++ ) + { + if ( abs(bg[i] - src[i]) <= threshold ) + dst[i] = 0; + else + dst[i] = 0xff; + } + + } + else + { + for( i = 0; i < len; i ++ ) + { + if ( abs(bg[i] - src[i]) >= threshold ) + dst[i] = 0; + else + dst[i] = 0xff; + + } + } +} + + +void diff_apply(void *ed, VJFrame *frame, + VJFrame *frame2, int width, int height, + int threshold, int reverse,int mode, int feather) +{ + + unsigned int i; + const uint32_t len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + diff_data *ud = (diff_data*) ed; + + +/* VJFrame *tmp = yuv_yuv_template( ud->current, NULL,NULL, width,height, + PIX_FMT_YUV444P ); + veejay_memcpy( ud->current, frame->data[0], len ); + softblur_apply(tmp,width,height,0); + free(tmp); +*/ + //@ clear distance transform map + veejay_memset( dt_map, 0 , len * sizeof(uint32_t) ); + + //@ todo: optimize with mmx + binarify( ud->data, static_bg, frame->data[0], threshold, reverse,len ); + + //@ calculate distance map + veejay_distance_transform8( ud->data, width, height, dt_map ); + + if(mode==1) + { + //@ show difference image in grayscale + veejay_memcpy( Y, ud->data, len ); + veejay_memset( Cb, 128, len ); + veejay_memset( Cr, 128, len ); + + return; + } else if (mode == 2 ) + { + //@ show dt map as grayscale image, intensity starts at 128 + for( i = 0; i < len ; i ++ ) + { + + if( dt_map[i] == feather ) + Y[i] = 0xff; //@ border white + else if( dt_map[i] > feather ) { + Y[i] = 128 + (dt_map[i] % 128); //grayscale value + } else if ( dt_map[i] == 1 ) { + Y[i] = 0xff; + } else { + Y[i] = 0; //@ black (background) + } + Cb[i] = 128; + Cr[i] = 128; + } + return; + } + + //@ process dt map + uint8_t *bin = ud->data; + for( i = 0; i < len ;i ++ ) + { + if( dt_map[ i ] >= feather ) + { + Y[i] = Y2[i]; + Cb[i] = Cb2[i]; + Cr[i] = Cr2[i]; + } + else + { + Y[i] = 0; + Cb[i] = 128; + Cr[i] = 128; + } + } +} + + + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/diff.h b/branches/V-1.5.3/veejay-server/libvje/effects/diff.h new file mode 100644 index 00000000..114dc8c0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/diff.h @@ -0,0 +1,35 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DIFFEFFECT_H +#define DIFFEFFECT_H +#include +#include +#include + +vj_effect *diff_init(int width, int height); +void diff_free(void *d); +int diff_malloc(void **c, int w, int h); +int diff_prepare(void *d, uint8_t *map[3], int w, int h); +void diff_apply(void *d , VJFrame *frame, + VJFrame *frame2, int width, int height, + int th, int reverse, int show, int feather); +void diff_destroy(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/diffimg.c b/branches/V-1.5.3/veejay-server/libvje/effects/diffimg.c new file mode 100644 index 00000000..a334f79b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/diffimg.c @@ -0,0 +1,90 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "diffimg.h" +#include "common.h" + +vj_effect *diffimg_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 6;/* type */ + ve->defaults[1] = 15; /* min */ + ve->defaults[2] = 235; /* max */ + + ve->limits[0][0] = 0; + ve->limits[1][0] = 7; + /* 0,179,0253,0127 */ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; + + ve->limits[1][2] = 255; + ve->limits[0][2] = 1; + ve->param_description = vje_build_param_list( ve->num_params,"Mode", "Min threshold", "Max threshold" ); + ve->description = "Enhanced Magic Blend"; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 0; + return ve; +} + + + +void diffimg_apply( + VJFrame *frame, + int width, + int height, + int type, + int threshold_min, + int threshold_max + ) +{ + unsigned int i; + const int len = frame->len - width - 2; + int d,m; + uint8_t y,yb; + uint8_t *Y = frame->data[0]; + + _pf _pff = _get_pf(type); + + for(i=0; i < len; i++) + { + y = Y[i]; + if( y < 16 ) y = 16; else if (y > 235) y = 235; + yb = y; + if(y >= threshold_min && y <= threshold_max) + { + m = (Y[i+1] + Y[i+width] + Y[i+width+1]+2) >> 2; + d = Y[i] - m; + d *= 500; + d /= 100; + m = m + d; + y = ((((y << 1) - (255 - m))>>1) + Y[i])>>1; + if(y < 16) y = 16; else if (y>235) y = 235; + Y[i] = _pff(y,yb); + } + } +} +void diffimg_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/diffimg.h b/branches/V-1.5.3/veejay-server/libvje/effects/diffimg.h new file mode 100644 index 00000000..addab2ca --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/diffimg.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DIFFIMGEFFECT_H +#define DIFFIMGEFFECT_H +#include +#include +#include + +vj_effect *diffimg_init(); +void diffimg_apply(VJFrame *frame, int w, int h, int type, int threshold, int opacity); + +void diffimg_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/diffmap.c b/branches/V-1.5.3/veejay-server/libvje/effects/diffmap.c new file mode 100644 index 00000000..49f51765 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/diffmap.c @@ -0,0 +1,365 @@ +/* + * Linux VeeJay + * + * Copyright(C)2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "diffmap.h" +#include "common.h" +#include "softblur.h" + +typedef int (*morph_func)(uint8_t *kernel, uint8_t mt[9] ); + +vj_effect *differencemap_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; // threshold + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; // reverse + ve->limits[1][1] = 1; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; // show map + ve->defaults[0] = 40; + ve->defaults[1] = 0; + ve->defaults[2] = 1; + ve->description = "Map B to A (bitmask)"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Reverse", "Show"); + return ve; +} + + +static uint8_t *binary_img = NULL; +static uint8_t *previous_img = NULL; +static int nframe = 0; +#define RUP8(num)(((num)+8)&~8) + +int differencemap_malloc(int w, int h ) +{ + if(binary_img || previous_img) + differencemap_free(); + + binary_img = (uint8_t*) vj_malloc(sizeof(uint8_t) * RUP8(w*h*2) ); + previous_img = binary_img + RUP8(w*h); + nframe = 0; + if(!binary_img) return 0; + return 1; +} + +void differencemap_free(void) +{ + if(binary_img) + free(binary_img); + binary_img = NULL; + previous_img = NULL; +} + +#ifndef MIN +#define MIN(a,b) ( (a)>(b) ? (b) : (a) ) +#endif +#ifndef MAX +#define MAX(a,b) ( (a)>(b) ? (a) : (b) ) +#endif + +static int _dilate_kernel3x3( uint8_t *kernel, uint8_t img[9]) +{ + register int x; + /* consider all background pixels (0) in input image */ + for(x = 0; x < 9; x ++ ) + if((kernel[x] * img[x]) > 0 ) + return 1; + return 0; +} +/* +#ifdef HAVE_ASM_MMX +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW ) +#define HAVE_K6_2PLUS +#endif + +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif + +static inline void load_binary_map( uint8_t *mask ) +{ + __asm __volatile( + "movq (%0), %%mm0\n\t" + :: "r" (mask) + ); +} + +static inline void map_luma( uint8_t *dst, uint8_t *B ) +//static inline void map_luma( uint8_t *dst, uint8_t *B, uint8_t *mask ) +{ + __asm __volatile( + // "movq (%0), %%mm0\n\t" + "movq (%0), %%mm1\n\t" + "pand %%mm0, %%mm1\n\t" + "movq %%mm1, (%1)\n\t" + // :: "r" (mask), "r" (B), "r" (dst) + :: "r" (B) , "r" (dst) + ); +} + +static inline void load_chroma( uint8_t val ) +{ + uint8_t mask[8] = { val,val,val,val, val,val,val,val }; + uint8_t *m = &mask[0]; + + __asm __volatile( + "movq (%0), %%mm3\n\t # mm3: 128,128,128,128, ..." + :: "r" (m) + ); +} + +static inline void map_chroma( uint8_t *dst, uint8_t *B ) +{ + __asm __volatile( + "movq (%0), %%mm1\n\t" + "pand %%mm0, %%mm1\n\t" + "pxor %%mm5, %%mm5\n\t" + "pcmpeqb %%mm1,%%mm5\n\t" + "pand %%mm3,%%mm5\n\t" + "paddb %%mm5,%%mm1\n\t" + "movq %%mm1, (%1) \n\t" + :: "r" (B), "r" (dst) + ); + +} + +static void load_differencemapmm7(uint8_t v) +{ + uint8_t mm[8] = { v,v,v,v, v,v,v,v }; + uint8_t *m = (uint8_t*) &(mm[0]); + __asm __volatile( + "movq (%0), %%mm7\n\t" + :: "r" (m) ); +} +#endif + + + +static void binarify( uint8_t *dst, uint8_t *src, uint8_t *prev, uint8_t threshold, int reverse,int w, int h ) +{ + int len = (w * h)>>3; + int i; + uint8_t *s = src; + uint8_t *d = dst; + load_differencemapmm7( threshold ); + + + uint8_t *p = dst; + + for( i = 0; i < len ; i ++ ) + { + __asm __volatile( + "movq (%0),%%mm0\n\t" + "pcmpgtb %%mm7,%%mm0\n\t" + "movq %%mm0,(%1)\n\t" + :: "r" (s), "r" (d) + ); + s += 8; + d += 8; + } + + if( reverse ) + { + __asm __volatile( + "pxor %%mm4,%%mm4" :: + ); + for( i = 0; i < len ; i ++ ) + { + __asm __volatile( + "movq (%0), %%mm0\n\t" + "pcmpeqb %%mm4, %%mm0\n\t" + "movq %%mm0, (%1)\n\t" + :: "r" (p), "r" (p) + ); + p += 8; + } + } +} + + +#else*/ +static void binarify( uint8_t *dst, uint8_t *src,int threshold,int reverse, int w, int h ) +{ + const int len = w*h; + int i; + if(!reverse) + { + for( i = 0; i < len; i ++ ) + dst[i] = ( src[i] <= threshold ? 0: 0xff ); + } + else + { + for( i = 0; i < len; i ++ ) + dst[i] = ( src[i] >= threshold ? 0: 0xff ); + } +} + +void differencemap_apply( VJFrame *frame, VJFrame *frame2,int width, int height, int threshold, int reverse, + int show ) +{ + unsigned int i,x,y; + int len = (width * height); + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2=frame2->data[1]; + uint8_t *Cr2=frame2->data[2]; + + const uint8_t kernel[9] = { 1,1,1, 1,1,1, 1,1,1 }; + uint8_t *bmap = binary_img; + +// morph_func p = _dilate_kernel3x3; + +//@ take copy of image + VJFrame *tmp = vj_malloc(sizeof(VJFrame)); + veejay_memcpy(tmp, frame, sizeof(VJFrame)); + tmp->data[0] = previous_img; + veejay_memcpy( previous_img, Y, len ); + softblur_apply( tmp, width,height,0 ); + free(tmp); + + binarify( binary_img,previous_img,threshold,reverse, width,height); +/* + +#ifdef HAVE_ASM_MMX + int work = (width*height)>>3; + load_chroma( 128 ); + for( y = 0 ; y < work; y ++ ) + { + load_binary_map( bmap ); + map_luma(Y , Y2 ); + map_chroma( Cb, Cb2 ); + map_chroma( Cr, Cr2 ); + //@ we could mmx-ify dilation + Y += 8; + Y2 += 8; + Cb += 8; + Cb2 += 8; + Cr += 8; + Cr2 +=8; + bmap += 8; + } + + __asm__ __volatile__ ( _EMMS:::"memory"); +#else +*/ + + //@ clear image + + if(show) + { + veejay_memcpy(frame->data[0], binary_img, len ); + veejay_memset(frame->data[1],128, len); + veejay_memset(frame->data[2],128, len); + return; + } + + veejay_memset( Y, 0, width ); + veejay_memset( Cb, 128, width ); + veejay_memset( Cr, 128, width ); + + len -= width; + +// if(!reverse) +// { + for(y = width; y < len; y += width ) + { + for(x = 1; x < width-1; x ++) + { + if(binary_img[x+y]) //@ found white pixel + { + /* uint8_t mt[9] = { + binary_img[x-1+y-width], binary_img[x+y-width], binary_img[x+1+y-width], + binary_img[x-1+y], binary_img[x+y] , binary_img[x+1+y], + binary_img[x-1+y+width], binary_img[x+y+width], binary_img[x+1+y+width] + }; + if( p( kernel, mt ) ) //@ replace pixel for B + { + Y[x + y] = Y2[x+y]; + Cb[x + y] = Cb2[1][x+y]; + Cr[x + y] = Cr[2][x+y]; + } + else //@ black + { + Y[x + y] = 0; + Cb[x + y] = 128; + Cr[x+ y] = 128; + }*/ + Y[x+y] = Y2[x+y]; + Cb[x+y] = Cb2[x+y]; + Cr[x+y] = Cr2[x+y]; + } + else + { + Y[x+y] = 0; + Cb[x+y] = 128; + Cr[x+y] = 128; + } + } + } +// } +/* else + { + for(y = width; y < len; y += width ) + { + for(x = 1; x < width-1; x ++) + { + if(!binary_img[x+y]) //@ found black pixel + { + uint8_t mt[9] = { + 0xff-binary_img[x-1+y-width], 0xff-binary_img[x+y-width], 0xff-binary_img[x+1+y-width], + 0xff-binary_img[x-1+y], 0xff-binary_img[x+y] , 0xff-binary_img[x+1+y], + 0xff-binary_img[x-1+y+width], 0xff-binary_img[x+y+width], 0xff-binary_img[x+1+y+width] + }; + if( p( kernel, mt ) ) + { + Y[x + y] = frame2->data[0][x+y]; + Cb[x + y] = frame2->data[1][x+y]; + Cr[x + y] = frame2->data[2][x+y]; + } + else + { + Y[x + y] = 0; + Cb[x + y] = 128; + Cr[x + y] = 128; + } + } + } + } +//#endif +*/ +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/diffmap.h b/branches/V-1.5.3/veejay-server/libvje/effects/diffmap.h new file mode 100644 index 00000000..91964d94 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/diffmap.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DIFFERENCEMAP_H +#define DIFFERENCEMAP_H +#include +#include +#include + +vj_effect *differencemap_init(int w, int h); +void differencemap_apply( VJFrame *frame,VJFrame *frame2, int width, int height, int t, int n, int show); +int differencemap_malloc(int w, int h); +void differencemap_free(void); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dissolve.c b/branches/V-1.5.3/veejay-server/libvje/effects/dissolve.c new file mode 100644 index 00000000..e87ca6af --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dissolve.c @@ -0,0 +1,82 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "dissolve.h" +#include + +vj_effect *dissolve_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->defaults[0] = 150; + ve->description = "Dissolve Overlay"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Opacity" ); + return ve; +} + + + +void dissolve_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int opacity) +{ + unsigned int i; + unsigned int len = frame->len; + const int op1 = (opacity > 255) ? 255 : opacity; + const int op0 = 255 - op1; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + for (i = 0; i < len; i++) + { + // set pixel as completely transparent or completely solid + + if(Y[i] > opacity) // completely transparent + { + Y[i] = (op0 * Y[i] + op1 * Y2[i]) >> 8; + Cb[i] = (op0 * Cb[i] + op1 * Cb2[i]) >> 8; + Cr[i] = (op0 * Cr[i] + op1 * Cr2[i]) >> 8; + } + else // pixel is solid + { + Y[i] = Y2[i]; + Cb[i] = Cb2[i]; + Cr[i] = Cr2[i]; + } + + } +} + +void dissolve_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dissolve.h b/branches/V-1.5.3/veejay-server/libvje/effects/dissolve.h new file mode 100644 index 00000000..3c0a6851 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dissolve.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DISSOLVE_H +#define DISSOLVE_H +#include +#include +#include + +vj_effect *dissolve_init(int w, int h); +void dissolve_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int dissolve); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/distort.c b/branches/V-1.5.3/veejay-server/libvje/effects/distort.c new file mode 100644 index 00000000..1b0ad947 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/distort.c @@ -0,0 +1,166 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* distortion effects */ +#include +#include +#include +#include +#include "distort.h" +#include "widthmirror.h" + +static int *plasma_table = NULL; +static int plasma_pos1 = 0; +static int plasma_pos2 = 0; + +vj_effect *distortion_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + int i; + float rad; + plasma_table = (int *) vj_calloc(sizeof(int) * 512); + for (i = 0; i < 512; i++) { + rad = ((float) i * 0.703125) * 0.0174532; + plasma_table[i] = sin(rad) * (1024); + } + + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 5; + ve->defaults[1] = 3; + ve->limits[0][0] = 0; + ve->limits[1][0] = 8; + ve->limits[0][1] = 0; + ve->limits[1][1] = 8; + ve->description = "Distortion"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Inc 1" , "Inc2" ); + return ve; +} +// FIXME private + +void distortion_free() { + if(plasma_table) free(plasma_table); +} + +void distortion_destroy() +{ + if(plasma_table) + free( plasma_table ); +} + +/* the distortion effect comes originally from the demo effects collection, + it is the plasma effect */ + +void distortion_apply(VJFrame *frame, int width, int height, + int inc_val1, int inc_val2) +{ + + unsigned int x, y, i, j; + uint8_t index; + int tpos1 = 0, tpos2 = 0, tpos3 = 0, tpos4 = 0; + int z = 511; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + const int uv_width = frame->uv_width; + const int uv_height = frame->uv_height; + unsigned int yi; + + uint8_t p, cb, cr; + + for (i = 0; i < height; ++i) { + tpos1 = plasma_pos1 + inc_val1; + tpos2 = plasma_pos2 + inc_val2; + + tpos3 &= z; + tpos4 &= z; + + for (j = 0; j < width; ++j) { + tpos1 &= z; + tpos2 &= z; + x = plasma_table[tpos1] + plasma_table[tpos2] + + plasma_table[tpos3] + plasma_table[tpos4]; + + index = 128 + (x >> 4); + + /* image = index */ + Y[(i * width) + j] = Y[index]; + + tpos1 += inc_val1; + tpos2 += inc_val2; + } + tpos4 += 3; + tpos3 += 1; + } + + + + for (i = 0; i < uv_height; ++i) { + tpos1 = plasma_pos1 + inc_val1; + tpos2 = plasma_pos2 + inc_val2; + + tpos3 &= z; + tpos4 &= z; + + for (j = 0; j < uv_width; ++j) { + tpos1 &= z; + tpos2 &= z; + x = plasma_table[tpos1] + plasma_table[tpos2] + + plasma_table[tpos3] + plasma_table[tpos4]; + + index = 128 + (x >> 4); + + /* image = index */ + Cb[(j * uv_width) + i] = Cb[index]; + Cr[(j * uv_width) + i] = Cr[index]; + tpos1 += inc_val1; + tpos2 += inc_val2; + } + tpos4 += 3; + tpos3 += 1; + } + + plasma_pos1 += 9; + plasma_pos2 += 8; + + for (y = 0; y < height; y++) { + yi = y * width; + for (x = 0; x < width; x++) { + p =Y[yi + x]; + Y[yi + (width - x - 1)] = p; + } + } + for (y = 0; y < uv_height; y++) { + yi = y * uv_width; + for (x = 0; x < uv_width; x++) { + cb = Cb[yi + x]; + cr = Cr[yi + x]; + Cb[yi + uv_width - x - 1] = cb; + Cr[yi + uv_width - x - 1] = cr; + } + } + +} +void distort_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/distort.h b/branches/V-1.5.3/veejay-server/libvje/effects/distort.h new file mode 100644 index 00000000..4278366a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/distort.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DISTORT_H +#define DISTORT_H +#include +#include +#include + +vj_effect *distortion_init(int w, int h); +void distortion_apply( VJFrame *frame, int width, int height, int n, + int type); +void distort_free(); +void distortion_destroy(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dither.c b/branches/V-1.5.3/veejay-server/libvje/effects/dither.c new file mode 100644 index 00000000..ef0dddfe --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dither.c @@ -0,0 +1,77 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "dither.h" +vj_effect *dither_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 2; + ve->defaults[1] = 0; + + ve->limits[0][0] = 2; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + + ve->description = "Matrix Dithering"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Value" ); + + return ve; +} + +void dither_apply(VJFrame *frame, int width, int height, int size, + int random_on) +{ + long int w_, h_; + long int dith[size][size]; + long int i, j, d, v, l, m; + uint8_t *Y = frame->data[0]; + + for (l = 0; l < size; l++) { + for (m = 0; m < size; m++) { + dith[l][m] = + 1 + (int) ((double) size * rand() / (RAND_MAX + 1.0)); + } + } + + for (h_ = 0; h_ < height; h_++) { + j = h_ % size; + for (w_ = 0; w_ < width; w_++) { + i = w_ % size; + d = dith[i][j] << 4; + /* Luminance , dither image. Do + this for U and V too, see what happens hehe */ + v = ((long) Y[((h_ * width) + w_)] + d); + Y[(h_ * width) + w_] = (uint8_t) ((v >> 7) << 7); + } + } +} +void dither_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dither.h b/branches/V-1.5.3/veejay-server/libvje/effects/dither.h new file mode 100644 index 00000000..91968fba --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dither.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DITHER_H +#define DITHER_H +#include +#include +#include + +vj_effect *dither_init(); +void dither_apply( VJFrame *frame, int width, int height, int size, + int n); +void dither_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dummy.c b/branches/V-1.5.3/veejay-server/libvje/effects/dummy.c new file mode 100644 index 00000000..d60b476b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dummy.c @@ -0,0 +1,83 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2010 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include +#include +#include + +vj_effect *dummy_init(int w, int h) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 3; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 7; + + ve->description = "Dummy Frame"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user= 0; + ve->param_description = vje_build_param_list(ve->num_params, "Color"); + return ve; +} +void dummy_apply( VJFrame *frame, int width, int height, int color) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + char colorCb, colorCr, colorY; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + colorY = bl_pix_get_color_y(color); + colorCb = bl_pix_get_color_cb(color); + colorCr = bl_pix_get_color_cr(color); + + veejay_memset( Y, colorY, len); + veejay_memset( Cb,colorCb,uv_len); + veejay_memset( Cr,colorCr,uv_len); +} + +void dummy_rgb_apply( VJFrame *frame, int width, int height, int r,int g, int b) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + int colorCb, colorCr, colorY; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + _rgb2yuv(r,g,b,colorY,colorCb,colorCr); + + veejay_memset( Y, colorY, len); + veejay_memset( Cb,colorCb,uv_len); + veejay_memset( Cr,colorCr,uv_len); +} +void dummy_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dummy.h b/branches/V-1.5.3/veejay-server/libvje/effects/dummy.h new file mode 100644 index 00000000..f202d504 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dummy.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DUMMY_H +#define DUMMY_H +#include +#include +#include + +vj_effect *dummy_init(); +void dummy_apply(VJFrame *frame, int width, int height, int n); +void dummy_rgb_apply(VJFrame *frame, int width, int height, int r, int g, int b); +void dummy_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dupmagic.c b/branches/V-1.5.3/veejay-server/libvje/effects/dupmagic.c new file mode 100644 index 00000000..6460266d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dupmagic.c @@ -0,0 +1,115 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "dupmagic.h" +#include "magicoverlays.h" + +vj_effect *dupmagic_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 5; + ve->description = "Strong Luma Overlay"; + ve->limits[0][0] = 1; + ve->limits[1][0] = 13; + ve->extra_frame = 1; + ve->sub_format = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode" ); + return ve; +} + +void dupmagic_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n) +{ + switch (n) { + case 1: + _overlaymagic_additive(frame, frame, width, height); + _overlaymagic_additive(frame2, frame2, width, height); + _overlaymagic_additive(frame, frame2, width, height); + break; + case 2: + _overlaymagic_multiply(frame, frame, width, height); + _overlaymagic_multiply(frame2, frame2, width, height); + _overlaymagic_multiply(frame, frame2, width, height); + break; + case 3: + _overlaymagic_divide(frame, frame, width, height); + _overlaymagic_divide(frame2, frame2, width, height); + _overlaymagic_divide(frame, frame2, width, height); + break; + case 4: + _overlaymagic_lighten(frame, frame, width, height); + _overlaymagic_lighten(frame2, frame2, width, height); + _overlaymagic_lighten(frame, frame2, width, height); + break; + case 5: + _overlaymagic_diffnegate(frame, frame, width, height); + _overlaymagic_diffnegate(frame2, frame2, width, height); + _overlaymagic_diffnegate(frame, frame2, width, height); + break; + case 6: + _overlaymagic_freeze(frame, frame, width, height); + _overlaymagic_freeze(frame2, frame2, width, height); + _overlaymagic_freeze(frame, frame2, width, height); + break; + case 7: + _overlaymagic_unfreeze(frame, frame, width, height); + _overlaymagic_unfreeze(frame2, frame2, width, height); + _overlaymagic_unfreeze(frame, frame2, width, height); + break; + case 8: + _overlaymagic_relativeadd(frame, frame2, width, height); + _overlaymagic_relativeadd(frame2, frame2, width, height); + _overlaymagic_relativeadd(frame, frame2, width, height); + break; + case 9: + _overlaymagic_relativeaddlum(frame, frame, width, height); + _overlaymagic_relativeaddlum(frame2, frame2, width, height); + _overlaymagic_relativeaddlum(frame, frame2, width, height); + break; + case 10: + _overlaymagic_maxselect(frame, frame, width, height); + _overlaymagic_maxselect(frame2, frame2, width, height); + _overlaymagic_maxselect(frame, frame2, width, height); + break; + case 11: + _overlaymagic_minselect(frame, frame, width, height); + _overlaymagic_minselect(frame2, frame2, width, height); + _overlaymagic_minselect(frame, frame2, width, height); + break; + case 12: + _overlaymagic_addtest2(frame, frame, width, height); + _overlaymagic_addtest2(frame2, frame2, width, height); + _overlaymagic_addtest2(frame, frame2, width, height); + break; + case 13: + _overlaymagic_softburn(frame, frame, width, height); + _overlaymagic_softburn(frame2, frame2, width, height); + _overlaymagic_softburn(frame, frame2, width, height); + break; + } +} +void dupmagic_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/dupmagic.h b/branches/V-1.5.3/veejay-server/libvje/effects/dupmagic.h new file mode 100644 index 00000000..7a0f8192 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/dupmagic.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef DUPMAGIC_H +#define DUPMAGIC_H +#include +#include +#include + +vj_effect *dupmagic_init(); + +void dupmagic_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int n); + +void dupmagic_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/emboss.c b/branches/V-1.5.3/veejay-server/libvje/effects/emboss.c new file mode 100644 index 00000000..6f9f37a2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/emboss.c @@ -0,0 +1,352 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "emboss.h" +#include +#include +#include "common.h" +vj_effect *emboss_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 10; + ve->limits[0][0] = 0; + ve->limits[1][0] = 10; + ve->description = "Various Weird Effects"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params,"Mode" ); + return ve; +} + + +void simpleedge_framedata(VJFrame *frame, int width, int height) +{ + unsigned int x, y; + uint8_t a1, a2, a3, b1, b2, b3, c1, c2, c3; + uint8_t *Y = frame->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + a1 = Y[(y - 1) * width + (x - 1)]; + a2 = Y[(y - 1) * width + x]; + a3 = Y[(y - 1) * width + (x + 1)]; + b1 = Y[y * width + (x - 1)]; + b2 = Y[y * width + x]; /* center */ + b3 = Y[y * width + (x + 1)]; + c1 = Y[(y + 1) * width + (x - 1)]; + c2 = Y[(y + 1) * width + x]; + c3 = Y[(y + 1) * width + (x + 1)]; + if (b2 > a1 && b2 > a2 && b2 > a3 && + b2 > b1 && b2 > b3 && b3 > c1 && b2 > c2 && b2 > c2) + Y[y * width + x] = pixel_Y_hi_; + else + Y[y * width + x] = pixel_Y_lo_; + } + } +} + +/********************************************************************************************** + * + * xtreme_emboss: looks a bit like emboss, but with dark colours and distorted edges + * + **********************************************************************************************/ +void xtreme_emboss_framedata(VJFrame *frame, int width, int height) +{ + unsigned int r, c; + uint8_t *Y = frame->data[0]; + for (r = 0; r < (width * height); r += width) { + for (c = 0; c < width; c++) { + Y[c + r] = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] + + Y[r + c - 1] - + Y[r + c] + + Y[r + c + 1] + + Y[r + 1 + c - 1] + + Y[r + 1 + c] - Y[r + 1 + c + 1] + ) / 9; + } + } +} + +void another_try_edge(VJFrame *frame, int w, int h) { + uint8_t p; + const unsigned int len=(w*h)-w; + unsigned int r,c; + uint8_t *Y = frame->data[0]; + for(r=w; r < len; r+= w) { + for(c=1; c < w-1; c++) { + p = ((Y[r+c-w] * -1) + (Y[r+c-w-1] * -1) + + (Y[r+c-w+1] * -1) + (Y[r+c-1] * -1) + + (Y[r+c] * -8) + (Y[r+c+1] * -1) + + (Y[r+c+w] * -1) + (Y[r+c+w-1] * -1) + + (Y[r+c+w+1] * -1))/9; + Y[r+c] = CLAMP_Y(p); + } + } +} + + +/********************************************************************************************** + * + * lines_white_balanced_framedata: it looks cool, just try it. + * + **********************************************************************************************/ +void lines_white_balance_framedata(VJFrame *frame, int width, int height) +{ + unsigned int r, c; + const unsigned int len = (width * height); + uint8_t val; + uint8_t *Y = frame->data[0]; + for (r = 0; r < len; r += width) { + for (c = 0; c < width; c++) { + val = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] + + Y[r + c - 1] - + Y[r + c] + + Y[r + c + 1] + + Y[r + 1 + c - 1] - + Y[r + 1 + c] - Y[r + 1 + c + 1] + ) / 9; + Y[c + r] = CLAMP_Y(val); + } + } +} + +/********************************************************************************************** + * + * white_emboss_framedata: again, i cannot explain what it looks like. + * + **********************************************************************************************/ +void white_emboss_framedata(VJFrame *frame, int width, int height) +{ + unsigned int r, c; + int val; + uint8_t *Y = frame->data[0]; + for (r = 0; r < (width * height); r += width) { + for (c = 0; c < width; c++) { + val = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] + + Y[r + c - 1] + + Y[r + c] - + Y[r + c + 1] - + Y[r + 1 + c - 1] - + Y[r + 1 + c] - Y[r + 1 + c + 1] + ) / 9; + Y[c + r] = CLAMP_Y(val); + + } + } +} + +void emboss_test_framedata(VJFrame *frame, int width, int height) +{ + int a, b, c; + int i; + const int len = width * height; + uint8_t *Y = frame->data[0]; + for (i = 0; i < len; i++) { + a = Y[i]; + b = (a + 235) >> 1; + c = (b + 235) >> 1; + Y[i] = c; + } +} + +/********************************************************************************************** + * + * gray_emboss_framedata: similar as white_emboss_framedata, but image is more grayish + * + **********************************************************************************************/ +void gray_emboss_framedata(VJFrame *frame, int width, int height) +{ + int r, c; + uint8_t val; + uint8_t *Y = frame->data[0]; + for (r = 0; r < (width * height); r += width) { + for (c = 0; c < width; c++) { + val = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] + + Y[r + c - 1] - + Y[r + c] - + Y[r + c + 1] - + Y[r + 1 + c - 1] - + Y[r + 1 + c] - Y[r + 1 + c + 1] + ) / 9; + Y[r + c] = CLAMP_Y(val); + } + } + +} + +/********************************************************************************************** + * + * aggressive_emboss_framedata: much like the above two, but more aggressive. + * + **********************************************************************************************/ +void aggressive_emboss_framedata(VJFrame *frame, int width, int height) +{ + int r, c; + uint8_t val; + uint8_t *Y = frame->data[0]; + const int len = width * height; + for (r = 0; r < len; r += width) { + for (c = 0; c < width; c++) { + val = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] + + Y[r + c - 1] - + Y[r + c] - + Y[r + c + 1] - + Y[r + 1 + c - 1] + + Y[r + 1 + c] + Y[r + 1 + c + 1] + ) / 9; + Y[c + r] = CLAMP_Y(val); + } + } + +} + +/********************************************************************************************** + * + * dark_emboss_framedata: like the above, but much less light. + * + **********************************************************************************************/ +void dark_emboss_framedata(VJFrame *frame, int width, int height) +{ + int r, c; + uint8_t *Y = frame->data[0]; + for (r = 0; r < (width * height); r += width) { + for (c = 0; c < width; c++) { + Y[c + r] = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] + + Y[r + c - 1] + + Y[r + c] - + Y[r + c + 1] - + Y[r + 1 + c - 1] + + Y[r + 1 + c] + Y[r + 1 + c + 1] + ) / 9; + } + } + +} + +/********************************************************************************************** + * + * grayish_mood_framedata: less light, more gray, only overal colour changes. + * Name probably does not reflect resulting effects. + **********************************************************************************************/ +void grayish_mood_framedata(VJFrame *frame, int width, int height) +{ + int r, c; + uint8_t *Y = frame->data[0]; + for (r = 0; r < (width * height); r += width) { + for (c = 0; c < width; c++) { + Y[c + r] = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] - + Y[r + c - 1] - + Y[r + c] - + Y[r + c + 1] - + Y[r + 1 + c - 1] - + Y[r + 1 + c] - Y[r + 1 + c + 1] + ) / 9; + } + } + + +} + +/********************************************************************************************** + * + * blur_dark_framedata: blurs the image a little and decreases luminance + * + **********************************************************************************************/ + +void blur_dark_framedata(VJFrame *frame, int width, int height) +{ + int r, c; + int len = (width*height) - width; + /* incomplete */ + uint8_t *Y = frame->data[0]; + for (r = width; r < len; r += width) { + for (c = 1; c < width-1; c++) { + Y[c + r] = (Y[r - 1 + c - 1] - + Y[r - 1 + c] - + Y[r - 1 + c + 1] + + Y[r + c - 1] + + Y[r + c] + + Y[r + c + 1] + + Y[r + 1 + c - 1] - + Y[r + 1 + c] + Y[r + 1 + c + 1] + ) / 9; + } + } +} + +void emboss_apply(VJFrame *frame, int width, int height, int n) +{ + switch (n) { + case 1: + xtreme_emboss_framedata(frame, width, height); + break; + case 2: + lines_white_balance_framedata(frame, width, height); + break; + case 3: + white_emboss_framedata(frame, width, height); + break; + case 4: + gray_emboss_framedata(frame, width, height); + break; + case 5: + aggressive_emboss_framedata(frame, width, height); + break; + case 6: + dark_emboss_framedata(frame, width, height); + break; + case 7: + grayish_mood_framedata(frame, width, height); + break; + case 8: + simpleedge_framedata(frame, width, height); + break; + case 9: + emboss_test_framedata(frame, width, height); + break; + case 10: + another_try_edge(frame,width,height); + break; + default: + blur_dark_framedata(frame, width, height); + break; + } +} +void emboss_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/emboss.h b/branches/V-1.5.3/veejay-server/libvje/effects/emboss.h new file mode 100644 index 00000000..2caf4fae --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/emboss.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef EMBOSS_H +#define EMBOSS_H +#include +#include +#include + +vj_effect *emboss_init(); +void emboss_apply( VJFrame *frame, int width, int height, int n); +void emboss_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/enhancemask.c b/branches/V-1.5.3/veejay-server/libvje/effects/enhancemask.c new file mode 100644 index 00000000..cb213829 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/enhancemask.c @@ -0,0 +1,104 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include + +#include "enhancemask.h" +#include "common.h" +vj_effect *enhancemask_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 125; /* type */ + // ve->defaults[1] = 255; /* yuvdenoise's default sharpen parameter */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 2048; + // ve->limits[0][1] = 0; + // ve->limits[1][1] = 255; + ve->description = "Sharpen"; + + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value" ); + return ve; +} + +void enhancemask_apply(VJFrame *frame, int width, int height, int *s ) { + + //int s[9]= { 1, 0, -1, 2, 0, -2, 1 , 0 , -1}; + unsigned int r; + const unsigned int len = (width*height)-width-1; + uint8_t *Y = frame->data[0]; + /* + int sum=0; + for(r=0; r < 9; r++) sum+=s[r]; + + for(r=width; r < len; r+=width) { + for(c=1; c < width-1; c++) { + int p1 = ( + (Y[r - width + c - 1] * s[0]) + + (Y[r - width + c ] * s[1]) + + (Y[r - width + c + 1] * s[2]) + + (Y[r + c - 1] * s[3]) + + (Y[r + c] * s[4]) + + (Y[r + c + 1] * s[5]) + + (Y[r + width + c - 1] * s[6]) + + (Y[r + width + c ] * s[7]) + + (Y[r + width + c + 1] * s[8]) ); + Y[r+c] = (p1/sum); + } + } + */ + + /* The sharpen comes from yuvdenoiser, we like grainy video so 512 is allowed. */ + + + register int d,m; +// unsigned int op0,op1; + // op0 = (s[1] > 255) ? 255 : s[1]; + // op1 = 255 - op1; + for(r=0; r < len; r++) { + m = ( Y[r] + Y[r+1] + Y[r+width] + Y[r+width+1] + 2) >> 2; + d = Y[r] - m; + d *= s[0]; + d /= 100; + m = m + d; +// a = Y[r]; +// Y[r] = (m * op0 + a * op1) / 255; + Y[r] = m; + } + for(r=len; r < (width*height); r++) { + m = (Y[r] + Y[r+1] + Y[r-width] + Y[r-width+1] + 2) >> 2; + d = Y[r]-m; + d *= s[0]; + d /= 100; + m = m + d; + Y[r] = m; + } + +} + +void enhancemask_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/enhancemask.h b/branches/V-1.5.3/veejay-server/libvje/effects/enhancemask.h new file mode 100644 index 00000000..f092bf11 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/enhancemask.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef ENHANCEMASK_H +#define ENHANCEMASK_H +#include +#include +#include + +vj_effect *enhancemask_init(int w, int h); + + +void enhancemask_apply(VJFrame *frame, int w, int h, int *t); + +void enhancemask_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/fibdownscale.c b/branches/V-1.5.3/veejay-server/libvje/effects/fibdownscale.c new file mode 100644 index 00000000..85fa94d2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/fibdownscale.c @@ -0,0 +1,133 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "fibdownscale.h" + +vj_effect *fibdownscale_init(int w, int h) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->description = "Fibonacci Downscaler"; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + ve->defaults[1] = 1; + ve->limits[0][0] = 0; + ve->limits[0][1] = 1; + ve->limits[1][0] = 1; + ve->limits[1][1] = 8; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Fib" ); + ve->has_user =0; + return ve; +} + +void fibdownscale_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n) +{ + if (n == 0) + _fibdownscale_apply(frame, frame2, width, height); + if (n == 1) + _fibrectangle_apply(frame, frame2, width, height); +} + +void _fibdownscale_apply(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + + unsigned i, f1; + unsigned int len = frame->len / 2; + unsigned int uv_len = frame->uv_len / 2; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + + + + /* do fib over half of image. (now we have 2 squares in upper half) */ + for (i = 2; i < len; i++) { + f1 = (i + 1) + (i - 1); + Y[i] = Y2[f1]; + } + + /* copy over first half (we could use veejay_memcpy) */ +// for (i = len; i < (width * height); i++) { +// Y[i] = Y[i - len]; + // } + veejay_memcpy( Y + len, Y, len ); + + /* do the same thing for UV to get correct image */ + + for (i = 2; i < uv_len; i++) { + f1 = (i + 1) + (i - 1); + Cb[i] = Cb2[f1]; + Cr[i] = Cr2[f1]; + } + + veejay_memcpy( Cb + uv_len, Cb , uv_len ); + veejay_memcpy( Cr + uv_len, Cr , uv_len ); +} + +void _fibrectangle_apply(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i, f1; + const uint32_t len = frame->len /2; + const uint32_t uv_len = frame->uv_len/2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + for (i = 2; i < len; i++) { + f1 = (i - 1) + (i - 2); +// if (f1 < len) + Y[i] = Y2[f1]; +// else +// Y[i] = Y[(f1 - len)]; + } + + for (i = 2; i < uv_len; i++) { + + f1 = (i - 1) + (i - 2); +// if (f1 < len) { + Cb[i] = Cb2[f1]; + Cr[i] = Cr2[f1]; +// } else { +// Cb[i] = Cb2[f1 - len]; +// Cr[i] = Cr2[f1 - len]; +// } + } +} +void fibdownscale_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/fibdownscale.h b/branches/V-1.5.3/veejay-server/libvje/effects/fibdownscale.h new file mode 100644 index 00000000..f02213c9 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/fibdownscale.h @@ -0,0 +1,35 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FIBDOWNSCALE_H +#define FIBDOWNSCALE_H +#include +#include +#include +vj_effect *fibdownscale_init(); + +void fibdownscale_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n); +void _fibdownscale_apply(VJFrame *frame, VJFrame *frame2, int width, + int height); +void _fibrectangle_apply(VJFrame *frame, VJFrame *frame2, int width, + int height); +void fibdownscale_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.c b/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.c new file mode 100644 index 00000000..05f35f18 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.c @@ -0,0 +1,197 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "fisheye.h" +#include +#include "common.h" +#include +vj_effect *fisheye_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = -1000; + ve->limits[1][0] = 1000; + ve->defaults[0] = 1; + ve->description = "Fish Eye"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value" ); + return ve; +} + +//FIXME private +static int _v = 0; + +static double *polar_map; +static double *fish_angle; +static int *cached_coords; +static uint8_t *buf[3]; + +int fisheye_malloc(int w, int h) +{ + int x,y; + int h2=h/2; + int w2=w/2; + int p =0; + + buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h * 3 ); + if(!buf[0]) return 0; + buf[1] = buf[0] + (w*h); + buf[2] = buf[1] + (w*h); + + polar_map = (double*) vj_calloc(sizeof(double) * w* h ); + if(!polar_map) return 0; + fish_angle = (double*) vj_calloc(sizeof(double) * w* h ); + if(!fish_angle) return 0; + + cached_coords = (int*) vj_calloc(sizeof(int) * w * h); + if(!cached_coords) return 0; + + for(y=(-1 *h2); y < (h-h2); y++) + { + for(x= (-1 * w2); x < (w-w2); x++) + { + double res; + fast_sqrt( res,(double) (y*y+x*x)); + p = (h2+y)*w+(w2+x); + polar_map[p] = res; + //polar_map[p] = sqrt( y*y + x*x ); + fish_angle[p] = atan2( (float) y, x); + } + } + _v = 0; + return 1; +} + +void fisheye_free() +{ + if(buf[0]) + free(buf[0]); + buf[0] = NULL; + buf[1] = NULL; + buf[2] = NULL; + + if(polar_map) free(polar_map); + if(fish_angle) free(fish_angle); + if(cached_coords) free(cached_coords); + +} + +static double __fisheye(double r,double v, double e) +{ + return (exp( r / v )-1) / e; +} + +static double __fisheye_i(double r, double v, double e) +{ + return v * log(1 + e * r); +} + + + +void fisheye_apply(VJFrame *frame, int w, int h, int v ) +{ + int i; + double (*pf)(double a, double b, double c); + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + if( v==0) v =1; + + if( v < 0 ) { + pf = &__fisheye_i; + v = v * -1; + } + else { + pf = &__fisheye; + } + + if( v != _v ) + { + const double curve = 0.001 * v; + const unsigned int R = h/2; + const double coeef = R / log(curve * R + 1); + /* pre calculate */ + unsigned int i; + int px,py; + double r,a,co,si; + const int w2 = w/2; + const int h2 = h/2; + + for(i=0; i < len; i++) + { + r = polar_map[i]; + a = fish_angle[i]; + if(r <= R) + { + r = pf( r, coeef, curve ); + sin_cos( si,co, a); + px =(int) ( r * co); + py =(int) ( r * si); + + px += w2; + py += h2; + + if(px < 0) px =0; + if(px > w) px = w; + if(py < 0) py = 0; + if(py >= (h-1)) py = h-1; + + cached_coords[i] = (py * w)+px; + } + else + { + cached_coords[i] = -1; + + } + } + _v = v; + } + + veejay_memcpy(buf[0], Y,(w*h)); + veejay_memcpy(buf[1], Cb,(w*h)); + veejay_memcpy(buf[2], Cr,(w*h)); + + for(i=0; i < len; i++) + { + if(cached_coords[i] == -1) + { + Y[i] = pixel_Y_lo_; + Cb[i] = 128; + Cr[i] = 128; + } + else + { + + Y[i] = buf[0][ cached_coords[i] ]; + Cb[i] = buf[1][ cached_coords[i] ]; + Cr[i] = buf[2][ cached_coords[i] ]; + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.c_wip b/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.c_wip new file mode 100644 index 00000000..2c958921 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.c_wip @@ -0,0 +1,240 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include "fisheye.h" +#include +#include "common.h" +#include +vj_effect *fisheye_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) malloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) malloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) malloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) malloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = -1000; + ve->limits[1][0] = 1000; + ve->defaults[0] = 1; + ve->description = "Fish Eye"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_internal_data= 1; + + return ve; +} + + +static double *polar_map; +static double *fish_angle; +static int *cached_coords; +static uint8_t *buf[3]; + +int fisheye_malloc(int w, int h) +{ + int x,y; + int h2=h/2; + int w2=w/2; + int p =0; + + buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!buf[0]) return -1; + buf[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!buf[1]) return -1; + + buf[2] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!buf[2]) return -1; + + polar_map = (double*) vj_malloc(sizeof(double) * w* h ); + if(!polar_map) return -1; + fish_angle = (double*) vj_malloc(sizeof(double) * w* h ); + if(!fish_angle) return -1; + + cached_coords = (int*) vj_malloc(sizeof(int) * w * h); + if(!cached_coords) return -1; + for(y=(-1 *h2); y < (h-h2); y++) + { + for(x= (-1 * w2); x < (w-w2); x++) + { + double res; + fast_sqrt( res,(double) (y*y+x*x)); + p = (h2+y)*w+(w2+x); + polar_map[p] = res; + //polar_map[p] = sqrt( y*y + x*x ); + fish_angle[p] = atan2( (float) y, x); + } + } + + + + return 1; +} + +void fisheye_free() +{ + if(buf[0]) free(buf[0]); + if(buf[1]) free(buf[1]); + if(buf[2]) free(buf[2]); + + if(polar_map) free(polar_map); + if(fish_angle) free(fish_angle); + if(cached_coords) free(cached_coords); + +} + +static double __fisheye(double r,double v, double e) +{ + return (exp( r / v )-1) / e; +} + +static double __fisheye_i(double r, double v, double e) +{ + return v * log(1 + e * r); +} + + +extern void *(* veejay_memcpy)(void *to, const void *from, size_t len) ; + + +static int _v = 0; +void fisheye_apply(uint8_t *yuv[3], int w, int h, int v ) +{ + int i; + const int len = w * h; + double (*pf)(double a, double b, double c); + + if( v==0) v =1; + + if( v < 0 ) { + pf = &__fisheye_i; + v = v * -1; + } + else { + pf = &__fisheye; + } + + if( v != _v ) + { + const double curve = 0.001 * v; + const unsigned int R = h/2; + const double coeef = R / log(curve * R + 1); + /* pre calculate */ + int i; + int px,py,x,y; + double r,a,co,si; + const int w2 = w/2; + const int h2 = h/2; + int j=0; + int c = (h2 * w + w2); + int count = 0; + for (i=1; i w2) px = w2; + if(py > h2) py = h2; + + cached_coords[c+i+((i-1)*w)] = ((py-1) * w) + px; + cached_coords[c-i+((i-1)*w)+1] = ((py-1) * w) - px; + cached_coords[c+i-((i-1)*w)-w] = -((py-1) * w) + px; + cached_coords[c-i-((i-1)*w)-w+1] = -((py-1) * w) - px; + + for (j=1; j w2) px = w2; + if(py > h2) py = h2; + + cached_coords[c+i+((j-1)*w)] = ((py-1) * w) + px; + cached_coords[c-i+((j-1)*w)+1] = ((py-1) * w) - px; + cached_coords[c+i-((j-1)*w)-w] = -((py-1) * w) + px; + cached_coords[c-i-((j-1)*w)-w+1] = -((py-1) * w) - px; + + cached_coords[c+j+((i-1)*w)] = ((px-1) * w) + py; + cached_coords[c-j+((i-1)*w)+1] = ((px-1) * w) - py; + cached_coords[c+j-((i-1)*w)-w] = -((px-1) * w) + py; + cached_coords[c-j-((i-1)*w)-w+1] = -((px-1) * w) - py; + } + } + /* for(i=0; i < len; i++) + { + r = polar_map[i]; + a = fish_angle[i]; + if(r <= R) + { + r = pf( r, coeef, curve ); + sin_cos( si,co, a); + px =(int) ( r * co); + py =(int) ( r * si); + + px += w2; + py += h2; + + if(px < 0) px =0; + if(px > w) px = w; + if(py < 0) py = 0; + if(py >= (h-1)) py = h-1; + + cached_coords[i] = (py * w)+px; + } + else + { + cached_coords[i] = -1; + + } + } + */ + + + _v = v; + } + + veejay_memcpy(buf[0], yuv[0],(w*h)); + veejay_memcpy(buf[1], yuv[1],(w*h)); + veejay_memcpy(buf[2], yuv[2],(w*h)); + + for(i=0; i < len; i++) + { + if(cached_coords[i] == -1) + { + yuv[0][i] = 16; + yuv[1][i] = 128; + yuv[2][i] = 128; + } + else + { + + yuv[0][i] = buf[0][ cached_coords[i] ]; + yuv[1][i] = buf[1][ cached_coords[i] ]; + yuv[2][i] = buf[2][ cached_coords[i] ]; + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.h b/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.h new file mode 100644 index 00000000..b0f02387 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/fisheye.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FISHEYE_H +#define FISHEYE_H +#include +#include +#include +#include + +vj_effect *fisheye_init(int w, int h); +int fisheye_malloc(int w, int h); +void fisheye_free(); +void fisheye_apply(VJFrame *frame, int width, int height, int val ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/flare.c b/branches/V-1.5.3/veejay-server/libvje/effects/flare.c new file mode 100644 index 00000000..adcf2b84 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/flare.c @@ -0,0 +1,328 @@ +/* + * VeeJay + * + * Copyright(C)2002-2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +#include +#include +#include +#include +#include +#include "flare.h" +#include "common.h" + +/* blend by blurred mask. + derived from radial blur and chromamagick effect. + + */ + +vj_effect *flare_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 3; + ve->defaults[1] = 25; + ve->defaults[2] = 100; + ve->description = "Flare (Glow)"; + ve->limits[0][0] = 0; /* p0 = type, p2 = opacity, p3 = radius */ + ve->limits[1][0] = 5; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 100; + ve->extra_frame = 0; + ve->sub_format = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params , "Mode", "Opacity", "Radius" ); + return ve; +} + +static uint8_t *flare_buf[3]; + +int flare_malloc(int w, int h) +{ + flare_buf[0] = (uint8_t*)vj_yuvalloc(w,h); + if(!flare_buf[0]) + return 0; + flare_buf[1] = flare_buf[0] + (w*h); + flare_buf[2] = flare_buf[1] + (w*h); + return 1; +} + +void flare_free(void) +{ + if(flare_buf[0]) free(flare_buf[0]); + flare_buf[0] = NULL; + flare_buf[1] = NULL; + flare_buf[2] = NULL; +} + +void flare_exclusive(VJFrame *frame, VJFrame *frame2, int width, int height, int op_a) { + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a=0, b=0, c=0; + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - a; + + + for (i = 0; i < len; i++) + { + a = Y[i]; + b = Y2[i]; + + a *= o1; + b *= o2; + a = a >> 8; + b = b >> 8; + Y[i] = (a+b) - ((a * b) >> 8); + // CLAMP_Y(c); + + a = Cb[i]-128; + b = Cb2[i]-128; + c = (a + b) - (( a * b) >> 8); + c += 128; + Cb[i] = CLAMP_UV(c); + + a = Cr[i]-128; + b = Cr2[i]-128; + c = (a + b) - ((a*b) >> 8); + c += 128; + Cr[i] = CLAMP_UV(c); + } +} + +void flare_additive(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a) { + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b; + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + + for(i=0; i < len; i++) + { + a = (Y[i]*o1) >> 7; + b = (Y2[i]*o2) >> 7; + Y[i] = a + (( 2 * b ) - 255); + + a = Cb[i]; + b = Cb2[i]; + + Cb[i] = a + ( ( 2 * b ) - 255 ); + + a = Cr[i] ; + b = Cr2[i] ; + + Cr[i] = a + ( ( 2 * b ) - 255 ); + } +} + +void flare_unfreeze( VJFrame *frame, VJFrame *frame2, int w, int h, int op_a ) { + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + int a,b; + + for(i=0; i < len; i++) + { + a = Y[i]; + b = Y2[i]; + if ( a < 1 ) a = 1; + Y[i] = 255 - (( op_a - b) * (op_a - b)) / a; + //Y[i] = CLAMP_Y(c); + + a = Cb[i]; + b = Cb2[i]; + if ( a < 1) a = 1; + Cb[i] = 255 - (( 255 - b) * ( 255 - b )) / a; + //Cb[i] = CLAMP_UV(c); + + a = Cr[i]; + b = Cr2[i]; + if ( a < 1 ) a = 1; + Cr[i] = 255 - ((255 -b ) * (255 - b)) /a ; + //Cr[i] = CLAMP_UV(c); + } +} + + +void flare_darken(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) +{ + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + + for(i=0; i < len; i++) + { + if(Y[i] > Y2[i]) + { + Y[i] = ((Y[i] * o1) + (Y2[i] * o2)) >> 8; + Cb[i] = ((Cb[i] * o1) + (Cb2[i] * o2)) >> 8; + Cr[i] = ((Cr[i] * o1) + (Cr2[i] * o2)) >> 8; + } + } +} + +void flare_simple( VJFrame *frame, VJFrame *frame2, int w, int h, int op_a ) +{ + unsigned int i; + unsigned int len = w* h; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + const uint8_t solid = 255 - op_a; + uint8_t premul; + for (i = 0; i < len; i++) + { + premul = ((Y2[i] * op_a) + (solid * 0xff )) >> 8; + Y[i] = ( (Y[i] >> 1) + (premul >> 1 ) ); + } + +} + +void flare_lighten(VJFrame *frame, VJFrame *frame2, int w, int h, int op_a) +{ + + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + const unsigned int o1 = op_a; + const unsigned int o2 = 255 - op_a; + + for(i=0; i < len; i++) + { + if(Y[i] < Y2[i]) + { + Y[i] = ((Y[i] * o1) + (Y2[i] * o2)) >> 8; + Cb[i] = ((Cb[i] * o1) + (Cb2[i] * o2)) >> 8; + Cr[i] = ((Cr[i] * o1) + (Cr2[i] * o2)) >> 8; + } + } +} + + +void flare_apply(VJFrame *A, + int width, int height, int type, int op_a, int radius) +{ + int y,x; + int plane = 0; + /* clone A */ + VJFrame B; + veejay_memcpy( &B, A, sizeof(VJFrame)); + /* data is local */ + B.data[0] = flare_buf[0]; + B.data[1] = flare_buf[1]; + B.data[2] = flare_buf[2]; + + /* copy image data */ + veejay_memcpy( B.data[0], A->data[0], A->len ); + veejay_memcpy( B.data[1], A->data[1], A->len ); + veejay_memcpy( B.data[2], A->data[2], A->len ); + + /* apply blur on Image, horizontal and vertical + (blur2 is from xine, see radial blur */ + + for( plane = 0; plane < 2; plane ++ ) + { + for( y = 0; y < height; y ++ ) + blur2( A->data[plane] + (y * width), + B.data[plane] + (y * width), + width, + radius, + 2, + 1, + 1 ); + + for( x = 0; x < width; x ++ ) + blur2( A->data[plane] + x , + B.data[plane] + x, + height, + radius, + 2, + width, + width ); + + } + /* overlay original on top of blurred image */ + switch( type ) + { + case 1: + flare_exclusive(A,&B,width,height,op_a); + break; + case 2: + flare_additive(A,&B,width,height,op_a); + break; + case 3: + flare_unfreeze(A,&B,width,height,op_a); + break; + case 4: + flare_darken(A,&B,width,height,op_a); + break; + case 5: + flare_lighten( A, &B, width, height, op_a ); + break; + + default: + flare_simple( A, &B, width,height, op_a ); + break; + + } +} + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/flare.h b/branches/V-1.5.3/veejay-server/libvje/effects/flare.h new file mode 100644 index 00000000..6b2b33cb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/flare.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FLARE_H +#define FLARE_H +#include +#include +#include + +vj_effect *flare_init(int w, int h); +int flare_malloc(int w, int h); +void flare_apply(VJFrame *A, int width, int height, int type, int theshold,int radius ); +void flare_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/flip.c b/branches/V-1.5.3/veejay-server/libvje/effects/flip.c new file mode 100644 index 00000000..deaf89f3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/flip.c @@ -0,0 +1,153 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "flip.h" +#include +vj_effect *flip_init(int w, int h) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + + ve->description = "Flip Frane"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "H or V"); + return ve; +} + +void flip_apply(VJFrame *frame, int width, int height, int n) +{ + if (n == 0) + _flip_y_yuvdata(frame, width, height); + if (n == 1) + _flip_x_yuvdata(frame, width, height); +} + + +void _flip_x_yuvdata(VJFrame *frame, int width, int height) +{ + unsigned int y = height, x; + unsigned int pos = 0; + int w2 = width >> 1; + uint8_t temp; + const unsigned int uv_width = frame->uv_width; + unsigned int uy = frame->uv_height; + unsigned int uw2 = w2 >> frame->shift_h; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + /* Luminance */ + do { + x = w2; + do { + temp = Y[pos + x]; + Y[pos + x] = Y[pos + width - x]; + Y[pos + width - x] = temp; + } while (--x); + pos += width; + + } while (--y); + + pos = 0; + + do { + x = uw2; + do { + temp = Cb[pos + x]; + Cb[pos + x] = Cb[pos + uv_width - x]; + Cb[pos + uv_width - x] = temp; + temp = Cr[pos + x]; + Cr[pos + x] = Cr[pos + uv_width - x]; + Cr[pos + uv_width - x] = temp; + + } while (--x); + pos += uv_width; + + } while (--uy); + +} + +/********************************************************************************************** + * flip_y_yuvdata + * flips the image horizontal, derived from SDLcam-0.7.0 (flip_y.c) + * added uv routine to cope with Cb and Cr data + **********************************************************************************************/ +/* fixme: put all chroma supersample subsample routines elsewhere to be smart */ +void _flip_y_yuvdata(VJFrame *frame, int width, int height) +{ + unsigned int x, pos_a = 0, pos_b; + uint8_t temp; + unsigned int w1 = width - 1; + unsigned int y = height >> 1; + unsigned int uy = y >> frame->shift_v; + const unsigned int uv_height = frame->uv_height; + const unsigned int uv_width = frame->uv_width; + const unsigned int uw1 = width >> frame->shift_h; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + /* Luminance */ + pos_b = (height - 1) * width; + do { + x = w1; + do { + temp = Y[pos_a + x]; + Y[pos_a + x] = Y[pos_b + x]; + Y[pos_b + x] = temp; + } while (--x); + pos_a += width; + pos_b -= width; + } while (--y); + + /* Chrominance */ + pos_a = 0; + pos_b = (uv_height - 1) * uv_width; + do { + x = uw1; + do { + temp = Cb[pos_a + x]; + Cb[pos_a + x] = Cb[pos_b + x]; + Cb[pos_b + x] = temp; + + temp = Cr[pos_a + x]; + Cr[pos_a + x] = Cr[pos_b + x]; + Cr[pos_b + x] = temp; + + } while (--x); + pos_a += uv_width; + pos_b -= uv_width; + } while (--uy); + + +} +void flip_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/flip.h b/branches/V-1.5.3/veejay-server/libvje/effects/flip.h new file mode 100644 index 00000000..dbe5b283 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/flip.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FLIP_H +#define FLIP_H +#include +#include +#include + +vj_effect *flip_init(); +void flip_apply(VJFrame *frame, int width, int height, int n); +void _flip_y_yuvdata(VJFrame *frame, int width, int height); +void _flip_x_yuvdata(VJFrame *frame, int width, int height); +void flip_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/frameborder.c b/branches/V-1.5.3/veejay-server/libvje/effects/frameborder.c new file mode 100644 index 00000000..34ef00b5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/frameborder.c @@ -0,0 +1,55 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "frameborder.h" +#include "common.h" + +vj_effect *frameborder_init(int width, int height) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = width/8; + ve->limits[0][0] = 1; + ve->limits[1][0] = height / 2; + ve->has_user = 0; + ve->description = "Frame Border Translation"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->param_description = vje_build_param_list( ve->num_params, "Size"); + return ve; +} + + +void frameborder_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int size) +{ + frameborder_yuvdata(frame->data[0], frame->data[1], frame->data[2], frame2->data[0], frame2->data[1], + frame2->data[2], width, height, (size), (size), (size), + (size),frame->shift_h,frame->shift_v); + +} +void frameborder_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/frameborder.h b/branches/V-1.5.3/veejay-server/libvje/effects/frameborder.h new file mode 100644 index 00000000..cbd69c4a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/frameborder.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FRAMEBORDER_H +#define FRAMEBORDER_H +#include +#include +#include + +vj_effect *frameborder_init(int width, int height); +void frameborder_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int size); +void frameborder_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/gamma.c b/branches/V-1.5.3/veejay-server/libvje/effects/gamma.c new file mode 100644 index 00000000..cc03e9ac --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/gamma.c @@ -0,0 +1,75 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "gamma.h" +#include +static int gamma_flag = 0; + +static uint8_t table[256]; + +vj_effect *gamma_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 124; + ve->limits[0][0] = 0; + ve->limits[1][0] = 500; + ve->description = "Gamma Correction"; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Gamma"); + return ve; +} +// FIXME private + +inline void gamma_setup(int width, int height, + double gamma_value) +{ + int i; + double val; + + for (i = 0; i < 256; i++) { + val = i / 256.0; + val = pow(val, gamma_value); + val = 256.0 * val; + table[i] = val; + } +} + +void gamma_apply(VJFrame *frame, int width, + int height, int gamma_value) +{ + unsigned int i, len = frame->len; + uint8_t *Y = frame->data[0]; + /* gamma correction YCbCr, only on luminance not on chroma */ + if (gamma_value != gamma_flag) + gamma_setup(width, height, (double) (gamma_value / 100.0)); + + for (i = 0; i < len; i++) { + Y[i] = (uint8_t) table[Y[i]]; + } +} +void gamma_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/gamma.h b/branches/V-1.5.3/veejay-server/libvje/effects/gamma.h new file mode 100644 index 00000000..8250ee76 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/gamma.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef GAMMA_H +#define GAMMA_H +#include +#include +#include + +vj_effect *gamma_init(); +void gamma_apply(VJFrame *frame, int width, + int height, int gamma_val); +void gamma_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/ghost.c b/branches/V-1.5.3/veejay-server/libvje/effects/ghost.c new file mode 100644 index 00000000..25c56388 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/ghost.c @@ -0,0 +1,151 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include +#include +#include +#include +#include "common.h" +#include "ghost.h" + +static uint8_t *ghost_buf[3]; +static uint8_t *diff_map; +static int diff_period; + +vj_effect *ghost_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 16; + ve->limits[1][0] = 255; // opacity + ve->defaults[0] = 134; + ve->description = "Motion Ghost"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user =0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity" ); + return ve; +} + +// FIXME private +int ghost_malloc(int w, int h) +{ + const int len = (w * h ); + int i; + + for( i = 0; i < 3 ; i ++ ) + { + ghost_buf[i] = (uint8_t*) vj_calloc( sizeof(uint8_t) * len); + if(!ghost_buf[i]) + return 0; + } + diff_map = (uint8_t*) vj_calloc( sizeof(uint8_t) * len); + diff_period = 0; + + return 1; +} + +void ghost_free() +{ + int i; + for(i = 0 ; i < 3; i ++ ) + { + if(ghost_buf[i]) + free(ghost_buf[i]); + ghost_buf[i] = NULL; + } + if( diff_map ) + free(diff_map); +} + +void ghost_apply(VJFrame *frame, + int width, int height, int opacity) +{ + register int q,z=0; + int x,y,i,tmp; + const int len = frame->len; + const unsigned int op_a = opacity; + const unsigned int op_b = 255 - op_a; + uint8_t *srcY = frame->data[0]; + uint8_t *srcCb= frame->data[1]; + uint8_t *srcCr= frame->data[2]; + uint8_t *dY = ghost_buf[0]; + uint8_t *dCb = ghost_buf[1]; + uint8_t *dCr = ghost_buf[2]; + uint8_t *bm = diff_map; + + const uint8_t kernel[9] = + { + 1,1,1,1,1,1,1,1,1 + }; + // first time running + if(diff_period == 0) + { + veejay_memcpy( dY, srcY, len ); + veejay_memcpy( dCb,srcCb, len ); + veejay_memcpy( dCr,srcCr, len ); + diff_period = 1; + return; + } + + + // absolute difference on threshold + + for(i = 0; i < len; i ++ ) + bm[i] = ( abs(srcY[i] - dY[i]) > 1 ? 0xff: 0x0); + + + + for( y = width; y < (len-width); y += width ) + { + for( x = 1; x < width - 1; x ++ ) + { + // input matrix + uint8_t mt[9] = { + bm[ x-1+y-width], bm[ x+y-width], bm[x+1+y-width], + bm[ x-1+y ], bm[ x+y ], bm[x+1+y], + bm[ x-1+y+width], bm[ x+y+width ], bm[x+1+y+width] + }; + + for( q = 0; q < 9; q ++ ) + { + if( kernel[q] && mt[q] ) // dilation + { z ++; break; } + } + + if( z > 0 ) // accept + { + // new pixel value back in ghost buf (feedback) + dY[x+y] = ( (op_a * srcY[x+y] ) + (op_b * dY[x+y]) ) >> 8; + dCb[x+y] = ((op_a * srcCb[x+y] ) + (op_b * dCb[x+y])) >> 8; + dCr[x+y] = ((op_a * srcCr[x+y] ) + (op_b * dCr[x+y])) >> 8; + // put result to screen + srcY[x+y] = dY[x+y]; + srcCb[x+y]= dCb[x+y]; + srcCr[x+y] = dCr[x+y]; + } + + z = 0; + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/ghost.h b/branches/V-1.5.3/veejay-server/libvje/effects/ghost.h new file mode 100644 index 00000000..3a0cb954 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/ghost.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef GHOST_H +#define GHOST_H +#include +#include +#include + +vj_effect *ghost_init(int w, int h); +void ghost_apply( VJFrame *frame, int width, int height, int op); +int ghost_malloc( int w, int h ); +void ghost_free(void); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/greyselect.c b/branches/V-1.5.3/veejay-server/libvje/effects/greyselect.c new file mode 100644 index 00000000..b464627a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/greyselect.c @@ -0,0 +1,132 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rgbkey.h" +#include +#include "common.h" + +vj_effect *greyselect_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 0; /* b */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + ve->has_user = 0; + ve->description = "Grayscale by Color Key"; + ve->extra_frame = 0; + ve->sub_format = 1; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list(ve->num_params,"Angle","Red","Green","Blue"); + + return ve; +} + +void greyselect_apply( VJFrame *frame, int width, + int height, int i_angle, int r, int g, + int b) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle / 10.0; + unsigned int pos; + uint8_t val; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + int iy,iu,iv; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = Y; + fg_cb = Cb; + fg_cr = Cr; + + bg_y = Y; + bg_cb = Cb; + bg_cr = Cr; + + for (pos = (width * height); pos != 0; pos--) { + short xx, yy; + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + + if (abs(yy) > val) { + Cb[pos]=128; + Cr[pos]=128; + } + } +} + +void greyselect_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/greyselect.h b/branches/V-1.5.3/veejay-server/libvje/effects/greyselect.h new file mode 100644 index 00000000..5635b331 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/greyselect.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef GREYSELECT_H +#define GREYSELECT_H +#include +#include +#include + +vj_effect *greyselect_init(); +void greyselect_apply( VJFrame *frame, int width, + int height, int i_angle, + int red, int green, int blue); +void greyselect_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/iris.c b/branches/V-1.5.3/veejay-server/libvje/effects/iris.c new file mode 100644 index 00000000..ef18d194 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/iris.c @@ -0,0 +1,112 @@ +/* + * Linux VeeJay + * + * Cvalyright(C) 2009 Niels Elburg + * + * 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 valtion) any later version. + * + * This program is distributed in the hvale 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 cvaly of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* "weed"-plugin partially ported from LiVES (C) G. Finch (Salsaman) 2009 + * + * weed-plugins/multi_transitions.c?revision=286 + * + */ +#include +#include +#include +#include +#include "iris.h" +#include "common.h" + +vj_effect *iris_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 100; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->defaults[0] = 1; + ve->defaults[1] = 0; + ve->description = "Iris Transition (Circle,Rect)"; + ve->sub_format = 1; //@todo: write this for native + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value", "Shape" ); + return ve; +} + + +void iris_apply( VJFrame *frame, VJFrame *frame2, int width, int height, int val, int shape) +{ + int i,j,k=0; + int len = (width * height); + int uv_len = frame->uv_len; + + uint8_t *Y0 = frame->data[0]; + uint8_t *Cb0 = frame->data[1]; + uint8_t *Cr0 = frame->data[2]; + + uint8_t *Y1 = frame2->data[0]; + uint8_t *Cb1 = frame2->data[1]; + uint8_t *Cr1 = frame2->data[2]; + + int half_wid = width >> 1; + int half_hei = height >> 1; + + float val0 = (val * 0.01f ); + float val1 = 1.0f - val0; + if( shape == 0 ) { + float x1,y1; + double rad = (double) ( (half_hei * half_hei) + (half_wid * half_wid ) ); + double sval=0; + + for( i = 0; i < len; i += width ) { + for( j = 0; j < width; j ++ ) { + //@ todo: extend this with feather for smoothness + x1 = (float)( k - half_hei ); + y1 = (float)( j - half_wid ); + fast_sqrt( sval, (x1*x1+y1*y1)/rad); + if( sval > val0 ) { + // if( sqrt( (x1 * x1 + y1 * y1 )/ rad) > val0 ) { + Y0[ i + j] = Y1[ i + j ]; + Cb0[i + j] = Cb1[ i + j ]; + Cr0[i + j] = Cr1[ i + j ]; + } + } + k ++; + } + } else if( shape == 1 ) { + float x1,y1; + for( i = 0; i < len; i += width ) { + for( j = 0; j < width; j ++ ){ + //@ todo: extend this with feather for smoothness + x1 = (float)half_wid * val1 + 0.5f; + y1 = (float)half_hei * val1 + 0.5f; + + if( j < x1 || j>=(width-x1) || k < y1 || k >= ( height-y1 )) { + Y0[ i + j] = Y1[ i + j ]; + Cb0[i + j] = Cb1[ i + j ]; + Cr0[i + j] = Cr1[ i + j ]; + } + } + k++; + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/iris.h b/branches/V-1.5.3/veejay-server/libvje/effects/iris.h new file mode 100644 index 00000000..95375307 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/iris.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2009 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef IRIS_H +#define IRIS_H +#include +#include +#include + +vj_effect *iris_init(); +void iris_apply( VJFrame *frame, VJFrame *frame2, int width, int height, int value, int shape); +void iris_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/isolate.c b/branches/V-1.5.3/veejay-server/libvje/effects/isolate.c new file mode 100644 index 00000000..87c437d7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/isolate.c @@ -0,0 +1,145 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "common.h" +#include "isolate.h" + +vj_effect *isolate_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 150; /* white transparency */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 255; + ve->has_user = 0; + ve->description = "Isolate Color"; + ve->extra_frame = 0; + ve->sub_format = 1; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( ve->num_params, "Angle","Red", "Green","Blue", "White"); + return ve; +} + +/* another key derivate */ + +void isolate_apply( VJFrame *frame, int width, + int height, int i_angle, int r, int g, + int b, int opacity) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle / 10.0; + unsigned int pos; + uint8_t val; + unsigned int op1 = (opacity > 255) ? 255: opacity; + unsigned int op0 = 255 - op1; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + int iy,iu,iv; + _rgb2yuv(r,g,b,iy,iu,iv); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = Y; + fg_cb = Cb; + fg_cr = Cr; + + bg_y = Y; + bg_cb = Cb; + bg_cr = Cr; + + for (pos = (width * height); pos != 0; pos--) { + short xx, yy; + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + + if (abs(yy) > val) { + Y[pos]=235; + Cb[pos]=128; + Cr[pos]=128; + } + else { + Y[pos] = (op0 * Y[pos] + (op1 * 235)) / 255; + Cb[pos] = (op0 * Cb[pos] + (op1 * 128)) / 255; + Cr[pos] = (op0 * Cr[pos] + (op1 * 128)) / 255; + } + } +} + +void isolate_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/isolate.h b/branches/V-1.5.3/veejay-server/libvje/effects/isolate.h new file mode 100644 index 00000000..dfd47e02 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/isolate.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef ISOLATE_H +#define ISOLATE_H +#include +#include +#include + +vj_effect *isolate_init(); +void isolate_apply( VJFrame *frame, int width, + int height, int i_angle, + int red, int green, int blue, int opacity); +void isolate_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/keyselect.c b/branches/V-1.5.3/veejay-server/libvje/effects/keyselect.c new file mode 100644 index 00000000..86329dcd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/keyselect.c @@ -0,0 +1,259 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rgbkey.h" +#include +#include "common.h" + +vj_effect *keyselect_init(int w, int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 6; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 300; /* angle */ + ve->defaults[1] = 255; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 3; /* blend type */ + ve->defaults[5] = 2400; /* noise suppression */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 256; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 256; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 256; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 7; + + ve->limits[0][5] = 0; + ve->limits[1][5] = 3500; + ve->has_user = 0; + ve->description = "Blend by Color Key"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list(ve->num_params, "Angle","Red","Green","Blue","Blend mode","Noise suppression" ); + return ve; +} + +typedef uint8_t(*blend_func)(uint8_t y1, uint8_t y2); +blend_func get_blend_func(const int mode); + +uint8_t blend_func1(uint8_t a, uint8_t b) { + return (uint8_t) 255 - (abs(255-a-b)); +} + +uint8_t blend_func2(uint8_t a, uint8_t b) { + uint8_t val; + if( a == 0 ) + a = 0xff; + val = 255 - ((255-b) * (255-b))/a; + return CLAMP_Y(val); +} + +uint8_t blend_func3(uint8_t a , uint8_t b) { + return (uint8_t) (a * b)>>8; +} + + +uint8_t blend_func4(uint8_t a, uint8_t b) { + uint8_t val; + val = (a * a) / ( 256 - b ); + return CLAMP_Y(val); +} + +uint8_t blend_func5(uint8_t a, uint8_t b) { + uint8_t val; + int c = 256 - b; + val = b / c; + return CLAMP_Y(val); +} + +uint8_t blend_func6(uint8_t a, uint8_t b) { + uint8_t val = a + (2 * (b)) - 255; + return CLAMP_Y(val); +} + +uint8_t blend_func7(uint8_t a, uint8_t b) { + return (uint8_t) ( a + ( b - 255) ); +} + +uint8_t blend_func8(uint8_t a, uint8_t b) { + int c; + if(b < 128) c = (a * b) >> 7; + else c = 255 - ((255-b)*(255-a)>>7); + return CLAMP_Y(c); +} + + + +blend_func get_blend_func(const int mode) { + switch(mode) { + case 0: return &blend_func1; + case 1: return &blend_func2; + case 2: return &blend_func3; + case 3: return &blend_func4; + case 4: return &blend_func5; + case 5: return &blend_func6; + case 6: return &blend_func7; + case 7: return &blend_func8; + } + return &blend_func1; +} + +/* +http://www.cs.utah.edu/~michael/chroma/ +*/ +void keyselect_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int r, int g, + int b, int mode, int i_noise) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + int kbg, x1, y1; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise * 0.01f); + unsigned int pos; + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + int iy=pixel_Y_lo_,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + blend_func blend_pixel = get_blend_func(mode); + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = Y; + fg_cb = Cb; + fg_cr = Cr; + /* 2005: swap these !! */ + bg_y = Y2; + bg_cb = Cb2; + bg_cr = Cr2; + + for (pos = (width * height); pos != 0; pos--) { + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + if (abs(yy) < val) { + /* compute fg, suppress fg in xz according to kfg + */ + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + + Y[pos] = val; + + // convert suppressed fg back to cbcr + // cb,cr are signed, go back to unsigned ! + val = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cb[pos] = val; + val = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + Cr[pos] = val; + // deal with noise + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + val = (Y[pos] + (kbg * bg_y[pos])) >> 8; + Y[pos] = blend_pixel( val, fg_y[pos] ); + + } + } + + +} + +void keyselect_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/keyselect.h b/branches/V-1.5.3/veejay-server/libvje/effects/keyselect.h new file mode 100644 index 00000000..8837aa15 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/keyselect.h @@ -0,0 +1,32 @@ +/* +* Linux VeeJay +* +* Copyright(C)2004 Niels Elburg +* +* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. +*/ + +#ifndef KEYSELECT_H +#define KEYSELECT_H +#include +#include +#include + +vj_effect *keyselect_init(); +void keyselect_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, + int red, int green, int blue, int mode, int noise); +void keyselect_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/killchroma.c b/branches/V-1.5.3/veejay-server/libvje/effects/killchroma.c new file mode 100644 index 00000000..d650d628 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/killchroma.c @@ -0,0 +1,71 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include "killchroma.h" +#include "common.h" +#include +#include +#include +#include + +vj_effect *killchroma_init(int w, int h) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->sub_format = 0; + ve->limits[0][0] = 0; + ve->limits[1][0] = 2; + ve->defaults[0] = 0; + ve->has_user = 0; + ve->description = "Filter out chroma channels"; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Mode" ); + + return ve; +} + + +void killchroma_apply(VJFrame *frame, int width, int height, int n) +{ + if(n==0) + { +#ifdef HAVE_ASM_MMX + memset_ycbcr( frame->data[1], frame->data[1], 128, frame->uv_width,frame->uv_height ); + memset_ycbcr( frame->data[2], frame->data[2], 128, frame->uv_width,frame->uv_height ); +#else + memset( frame->data[1], 128, frame->uv_len); + memset( frame->data[2], 128, frame->uv_len); +#endif + } + else + { +#ifdef HAVE_ASM_MMX + memset_ycbcr( frame->data[n], frame->data[n], 128,frame->uv_width, frame->uv_height ); +#else + memset( frame->data[n], 128, frame->uv_len ); +#endif + } +} +void killchroma_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/killchroma.h b/branches/V-1.5.3/veejay-server/libvje/effects/killchroma.h new file mode 100644 index 00000000..daef44b0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/killchroma.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef KILLCHROMA_H +#define KILLCHROMA_H +#include +#include +#include + +vj_effect *killchroma_init(); + +void killchroma_apply( VJFrame *v, int width, int height, int n); + +void killchroma_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumablend.c b/branches/V-1.5.3/veejay-server/libvje/effects/lumablend.c new file mode 100644 index 00000000..6f4840cd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumablend.c @@ -0,0 +1,179 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include +#include +#include +#include "lumablend.h" + +vj_effect *lumablend_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; /* type */ + ve->limits[1][0] = 2; + ve->limits[0][1] = 0; /* threshold 1 */ + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; /* threshold 2 */ + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; /*opacity */ + ve->limits[1][3] = 255; + ve->defaults[0] = 2; + ve->defaults[1] = 0; + ve->defaults[2] = 35; + ve->defaults[3] = 150; + ve->description = "Opacity by Threshold"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Mode", "Threshold A", "Threshold B", "Opacity" ); + + return ve; +} + + +void opacity_by_threshold(uint8_t * yuv1[3], uint8_t * yuv2[3], int width, + int height, int threshold, int threshold2, + int opacity) +{ + + unsigned int x, y, len = width * height; + uint8_t a1, a2; + unsigned int op0, op1; + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + + for (y = 0; y < len; y += width) { + for (x = 0; x < width; x++) { + a1 = yuv1[0][x + y]; + a2 = yuv2[0][x + y]; + if (a1 >= threshold && a1 <= threshold2) { + yuv1[0][x + y] = (op0 * a1 + op1 * a2) >> 8; + yuv1[1][x + y] = + (op0 * yuv1[1][x + y] + op1 * yuv2[1][x + y]) >> 8; + yuv1[2][x + y] = + (op0 * yuv1[2][x + y] + op1 * yuv2[2][x + y]) >> 8; + } + } + } + +} + + +void opacity_by_threshold_(uint8_t * yuv1[3], uint8_t * yuv2[3], int width, + int height, int threshold, int threshold2, + int opacity) +{ + + unsigned int x, y, len = width * height; + uint8_t a1, a2; + unsigned int op0, op1; + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + for (y = 0; y < len; y += width) { + for (x = 0; x < width; x++) { + a1 = yuv1[0][x + y]; + a2 = yuv2[0][x + y]; + if (a2 > threshold && a2 < threshold2) { + yuv1[0][x + y] = (op0 * a1 + op1 * a2) >> 8; + yuv1[1][x + y] = + (op0 * yuv1[1][x + y] + op1 * yuv2[1][x + y]) >> 8; + yuv1[2][x + y] = + (op0 * yuv1[2][x + y] + op1 * yuv2[2][x + y]) >> 8; + } + } + } +} + + + +void opacity_by_threshold_blur(uint8_t * yuv1[3], uint8_t * yuv2[3], + int width, int height, int threshold, + int threshold2, int opacity) +{ + + unsigned int x, y, len = width * height - width; + uint8_t a1, a2; + unsigned int op0, op1; + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + /* incomplete */ + for (y = width; y < len; y += width) { + for (x = 1; x < width-1; x++) { + a1 = yuv1[0][x + y]; + a2 = yuv2[0][x + y]; + if (a1 >= threshold && a1 <= threshold2) { + a1 = (yuv1[0][y - width + x - 1] + + yuv1[0][y - width + x + 1] + + yuv1[0][y - width + x] + + yuv1[0][y + x] + + yuv1[0][y + x - 1] + + yuv1[0][y + x + 1] + + yuv1[0][y + width + x] + + yuv1[0][y + width + x + 1] + + yuv1[0][y + width + x - 1] + ) / 9; + + a2 = (yuv2[0][y - width + x - 1] + + yuv2[0][y - width + x + 1] + + yuv2[0][y - width + x] + + yuv2[0][y + x] + + yuv2[0][y + x - 1] + + yuv2[0][y + x + 1] + + yuv2[0][y + width + x] + + yuv2[0][y + width + x + 1] + + yuv2[0][y + width + x - 1] + ) / 9; + + yuv1[0][x + y] = (op0 * a1 + op1 * a2) >> 8; + yuv1[1][x + y] = + (op0 * yuv1[1][x + y] + op1 * yuv2[1][x + y]) >> 8; + yuv1[2][x + y] = + (op0 * yuv1[2][x + y] + op1 * yuv2[2][x + y]) >> 8; + } + } + } +} + +void lumablend_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int type, int t1, int t2, int opacity) +{ + + switch (type) { + case 0: + opacity_by_threshold(frame->data, frame2->data, width, height, t1, t2, opacity); + break; + case 1: + opacity_by_threshold_(frame->data, frame2->data, width, height, t1, t2, opacity); + break; + case 2: + opacity_by_threshold_blur(frame->data, frame2->data, width, height, t1, t2, + opacity); + break; + + } + +} +void lumablend_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumablend.h b/branches/V-1.5.3/veejay-server/libvje/effects/lumablend.h new file mode 100644 index 00000000..004bb4ba --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumablend.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef LUMABLEND_H +#define LUMABLEND_H +#include +#include +#include + +vj_effect *lumablend_init(); +void lumablend_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int threhold1, int threshold2, + int opacity, int type); + +void lumablend_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumakey.c b/branches/V-1.5.3/veejay-server/libvje/effects/lumakey.c new file mode 100644 index 00000000..4d687795 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumakey.c @@ -0,0 +1,328 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "lumakey.h" + +vj_effect *lumakey_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; /* feather */ + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; /* threshold min */ + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; /* threshold max */ + ve->limits[1][2] = 255; + ve->limits[0][3] = 1; /* distance */ + ve->limits[1][3] = width; + ve->limits[0][4] = 0; /* type */ + ve->limits[1][4] = 2; + ve->defaults[0] = 255; + ve->defaults[1] = 150; + ve->defaults[2] = 200; + ve->defaults[3] = 1; + ve->defaults[4] = 1; + ve->description = "Luma Key"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Feather", "Min Threshold","Max Threshold","Distance", "Mode" ); + + return ve; +} + + + +void lumakey_simple(uint8_t * yuv1[3], uint8_t * yuv2[3], int width, + int height, int threshold, int threshold2, int opacity) +{ + + unsigned int x, y, len = width * height; + uint8_t a1, a2; + unsigned int op0, op1; + uint8_t Y, Cb, Cr; + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + for (y = 0; y < len; y += width) { + for (x = 0; x < width; x++) { + a1 = yuv1[0][x + y]; + a2 = yuv2[0][x + y]; + /* + if ( a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2 )/255; + Cb = (op0 * yuv1[1][x+y] + op1 * yuv2[1][x+y])/255; + Cr =(op0 * yuv1[2][x+y] + op1 * yuv2[2][x+y])/255; + + } + */ + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][x + y] + op1 * yuv2[1][x + y]) >> 1; + Cr = (op0 * yuv1[2][x + y] + op1 * yuv2[2][x + y]) >> 1; + yuv1[0][x + y] = Y; // < 16 ? 16 : Y > 235 ? 235 : Y; + yuv1[1][x + y] = Cb; // < 16 ? 16 : Cb > 240 ? 240 : Cb; + yuv1[2][x + y] = Cr; // < 16 ? 16 : Cr > 240 ? 240 : Cr; + } + + } + } +} + + +void lumakey_smooth(uint8_t * yuv1[3], uint8_t * yuv2[3], int width, + int height, int threshold, int threshold2, int opacity, + int distance) +{ + + unsigned int x, y = 0, len = width * height; + uint8_t a1, a2; + unsigned int op0, op1; + uint8_t Y, Cb, Cr; + unsigned int soft0, soft1; + unsigned int t2, t3; + uint8_t p1, p2; + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + soft0 = 255 / distance; + soft1 = 255 - soft0; + + t2 = threshold - distance; // 0 - 4 + t3 = threshold2 + distance; // 3 + 4 + + /* first row */ + + if (t2 < 0) + t2 = 0; + if (t3 > 255) + t3 = 255; + + for (x = 0; x < width; x++) { + a1 = yuv1[0][x]; + a2 = yuv2[0][x]; + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][x] + op1 * yuv2[1][x]) >> 8; + Cr = (op0 * yuv1[2][x] + op1 * yuv2[2][x]) >> 8; + + yuv1[0][x] = Y; //< 16 ? 16 : Y > 235 ? 235 : Y; + yuv1[1][x] = Cb; // < 16 ? 16 : Cb > 240 ? 240 : Cb; + yuv1[2][x] = Cr; // < 16 ? 16 : Cr > 240 ? 240 : Cr; + } + } + + for (y = width; y < len - width; y += width) { + /* first pixel in column */ + a1 = yuv1[0][y]; + a2 = yuv2[0][y]; + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][y] + op1 * yuv2[1][y]) >> 8; + Cr = (op0 * yuv1[2][y] + op1 * yuv2[2][y]) >> 8; + } + /* rest of pixels in column */ + for (x = 1; x < width - 1; x++) { + a1 = yuv1[0][x + y]; + a2 = yuv2[0][x + y]; + + if ((a1 >= t2 && a1 < threshold) + || (a1 > threshold2 && a1 <= t3)) { + /* special case */ + p1 = ( /* calculate mean of a1 */ + yuv1[0][y - width + x - 1] + + yuv1[0][y - width + x + 1] + + yuv1[0][y - width + x] + + yuv1[0][y + x] + + yuv1[0][y + x - 1] + + yuv1[0][y + x + 1] + + yuv1[0][y + width + x] + + yuv1[0][y + width + x + 1] + + yuv1[0][y + width + x - 1] + ) / 9; + p2 = ( /* calculate mean of a1 */ + yuv2[0][y - width + x - 1] + + yuv2[0][y - width + x + 1] + + yuv2[0][y - width + x] + + yuv2[0][y + x] + + yuv2[0][y + x - 1] + + yuv2[0][y + x + 1] + + yuv2[0][y + width + x] + + yuv2[0][y + width + x + 1] + + yuv2[0][y + width + x - 1] + ) / 9; + + yuv1[0][x + y] = (op0 * p1 + op1 * p2) >> 8; + yuv1[1][x + y] = + (op0 * yuv1[1][x + y] + op1 * yuv2[1][x + y]) >> 8; + yuv1[2][x + y] = + (op0 * yuv1[2][x + y] + op1 * yuv2[2][x + y]) >> 8; + + } else { + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][x + y] + + op1 * yuv2[1][x + y]) >> 8; + Cr = (op0 * yuv1[2][x + y] + + op1 * yuv2[2][x + y]) >> 8; + + yuv1[0][x + y] = Y; // < 16 ? 16 : Y > 235 ? 235 : Y; + yuv1[1][x + y] = Cb; // < 16 ? 16 : Cb > 240 ? 240 : Cb; + yuv1[2][x + y] = Cr; // < 16 ? 16 : Cr > 240 ? 240 : Cr; + } + } + } + } + /* last row */ + for (x = len - width; x < len; x++) { + a1 = yuv1[0][x]; + a2 = yuv2[0][x]; + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][x] + op1 * yuv2[1][x]) >> 8; + Cr = (op0 * yuv1[2][x] + op1 * yuv2[2][x]) >> 8; + + yuv1[0][x] = Y; // < 16 ? 16 : Y > 235 ? 235 : Y; + yuv1[1][x] = Cb; // < 16 ? 16 : Cb > 240 ? 240 : Cb; + yuv1[2][x] = Cr; // < 16 ? 16 : Cr > 240 ? 240 : Cr; + } + } + +} + +void lumakey_smooth_white(uint8_t * yuv1[3], uint8_t * yuv2[3], int width, + int height, int threshold, int threshold2, + int opacity, int distance) +{ + + unsigned int x, y = 0, len = width * height; + uint8_t a1, a2; + unsigned int op0, op1; + uint8_t Y, Cb, Cr; + unsigned int soft0, soft1; + unsigned int t2, t3; + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + soft0 = 255 / distance; + soft1 = 255 - soft0; + + t2 = threshold - distance; + t3 = threshold2 + distance; + + /* first row */ + + for (x = 0; x < width; x++) { + a1 = yuv1[0][x]; + a2 = yuv2[0][x]; + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][x] + op1 * yuv2[1][x]) >> 8; + Cr = (op0 * yuv1[2][x] + op1 * yuv2[2][x]) >> 8; + + yuv1[0][x] = Y; // < 16 ? 16 : Y > 235 ? 235 : Y; + yuv1[1][x] = Cb; // < 16 ? 16 : Cb > 240 ? 240 : Cb; + yuv1[2][x] = Cr; // < 16 ? 16 : Cr > 240 ? 240 : Cr; + } + } + + for (y = width; y < len - width; y += width) { + /* first pixel in column */ + a1 = yuv1[0][y]; + a2 = yuv2[0][y]; + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][y] + op1 * yuv2[1][y]) >> 8; + Cr = (op0 * yuv1[2][y] + op1 * yuv2[2][y]) >> 8; + } + /* rest of pixels in column */ + /* rest of pixels in column */ + for (x = 1; x < width - 1; x++) { + a1 = yuv1[0][x + y]; + a2 = yuv2[0][x + y]; + + if ((a1 >= t2 && a1 < threshold) + || (a1 > threshold2 && a1 <= t3)) { + /* special case */ + yuv1[0][x + y] = 235; + yuv1[1][x + y] = 128; + yuv1[2][x + y] = 128; + } else { + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][x + y] + + op1 * yuv2[1][x + y]) >> 8; + Cr = (op0 * yuv1[2][x + y] + + op1 * yuv2[2][x + y]) >> 8; + + yuv1[0][x + y] = Y; // < 16 ? 16 : Y > 235 ? 235 : Y; + yuv1[1][x + y] = Cb; // < 16 ? 16 : Cb > 240 ? 240 : Cb; + yuv1[2][x + y] = Cr; // < 16 ? 16 : Cr > 240 ? 240 : Cr; + } + } + } + } + /* last row */ + for (x = len - width; x < len; x++) { + a1 = yuv1[0][x]; + a2 = yuv2[0][x]; + if (a1 >= threshold && a1 <= threshold2) { + Y = (op0 * a1 + op1 * a2) >> 8; + Cb = (op0 * yuv1[1][x] + op1 * yuv2[1][x]) >> 8; + Cr = (op0 * yuv1[2][x] + op1 * yuv2[2][x]) >> 8; + + yuv1[0][x] = Y; // < 16 ? 16 : Y > 235 ? 235 : Y; + yuv1[1][x] = Cb; // < 16 ? 16 : Cb > 240 ? 240 : Cb; + yuv1[2][x] = Cr; // < 16 ? 16 : Cr > 240 ? 240 : Cr; + } + } +} + + + +void lumakey_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int type, int threshold, int threshold2, + int feather, int d) +{ + + switch (type) { + case 0: + /* normal overlay */ + lumakey_simple(frame->data, frame2->data, width, height, threshold, threshold2, + feather); + break; + case 1: + /* threshold */ + lumakey_smooth_white(frame->data, frame2->data, width, height, threshold, + threshold2, feather, d); + break; + case 2: + lumakey_smooth(frame->data, frame2->data, width, height, threshold, threshold2, + feather, d); + break; + } + +} +void lumakey_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumakey.h b/branches/V-1.5.3/veejay-server/libvje/effects/lumakey.h new file mode 100644 index 00000000..85e7d5cf --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumakey.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef LUMAKEY_H +#define LUMAKEY_H +#include +#include +#include + +vj_effect *lumakey_init(); +void lumakey_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int type, int threshold, int threshold2, + int feather, int d); + +void lumakey_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumamagick.c b/branches/V-1.5.3/veejay-server/libvje/effects/lumamagick.c new file mode 100644 index 00000000..09db84f3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumamagick.c @@ -0,0 +1,1054 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* 7 ,14, 24, 25, 26 */ +#include +#include +#include +#include +#include +#include "magicoverlays.h" +#include "common.h" +/* 04/01/03: added transparency parameters for frame a and frame b in each function */ + +vj_effect *lumamagick_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + //ve->param_description = (char**)vj_calloc(sizeof(char)* ve->num_params); + ve->defaults[0] = 1; + ve->defaults[1] = 100; + ve->defaults[2] = 100; + ve->description = "Luma Magick"; + ve->limits[0][0] = 1; + ve->limits[1][0] = 39; + ve->limits[0][1] = 0; + ve->limits[1][1] = 200; + ve->limits[0][2] = 0; + ve->limits[1][2] = 200; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Opacity A", "Opacity B" ); + return ve; +} + +/* 33 = illumination . it increases or decreases light intensity and associate color pixel*/ + + +void _lumamagick_adddistorted(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + int a, b, c; + const double opacity_a = op_a * 0.01; + const int opacity_b = op_b * 0.01; + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + c = a + b; + Y[i] = CLAMP_Y(c); + } + for (i = 0; i < uv_len; i++) { + a = Cb[i]; + b = Cb2[i]; + c = a + b; + Cb[i] = CLAMP_UV(c); + + a = Cr[i]; + b = Cr2[i]; + c = a + b; + Cr[i] = CLAMP_UV(c); + } +} + +/*FIXME : overlay magic add distorted */ +void _lumamagick_add_distorted(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + + unsigned int i; + uint8_t y1, y2, y3, cb, cr, cs; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + y1 = Y[i] * opacity_a; + y2 = Y2[i] * opacity_b; + y3 = y1 + y2; + y3 *= opacity_a; + y3 += y2; + Y[i] = y3; + } + for (i = 0; i < uv_len; i++) { + cb = Cb[i] * opacity_a; + cr = Cb2[i] * opacity_b; + cs = cb + cr; + cs += cr; + Cb[i] = cs; + + cb = Cr[i]; + cr = Cr2[i]; + + cs = cb + cr; + cs += cr; + Cr[i] = cs; + } + +} + +void _lumamagick_subdistorted(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + uint8_t y1, y2, cb, cr; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + y1 = Y[i] * opacity_a; + y2 = Y2[i] * opacity_b; + y1 -= y2; + Y[i] = y1; + } + for (i = 0; i < uv_len; i++) { + cb = Cb[i]; + cr = Cb2[i]; + cb -= cr; + Cb[i] = cb; + cb = Cr[i]; + cr = Cr2[i]; + cb -= cr; + Cr[i] = cb; + } +} + +void _lumamagick_sub_distorted(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + + unsigned int i; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + uint8_t y1, y2, cb, cr, y3, cs; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + y1 = Y[i] * opacity_a; + y2 = Y2[i] * opacity_b; + y3 = y1 - y2; + y3 *= opacity_a; + y3 -= y2; + Y[i] = y3; + } + for (i = 0; i < uv_len; i++) { + cb = Cb[i]; + cr = Cb2[i]; + cs = cb - cr; + cs -= cr; + Cb[i] = cs; + + cb = Cr[i]; + cr = Cr2[i]; + + cs = cb - cr; + cs -= cr; + Cr[i] = cs; + + } +} + +void _lumamagick_multiply(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + uint8_t y1, y2; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + y1 = Y[i] * opacity_a; + y2 = Y2[i] * opacity_b; + y1 = (y1 * y2) >> 8; + Y[i] = y1; + } +} + +void _lumamagick_divide(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + const unsigned int len = width * height; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + b = (Y[i] * opacity_a) * (Y[i] * opacity_a); + c = 255 - (Y2[i] * opacity_b); + if (c > pixel_Y_lo_) + Y[i] = b/c; + } +} + +void _lumamagick_additive(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a=0; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = (Y[i] * opacity_a) + ((2 * (Y2[i] * opacity_b)) - 255); + Y[i] = CLAMP_Y(a); + } +} + +void _lumamagick_substractive(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = (Y[i] * opacity_a) + ((Y2[i] - 255) * opacity_b); + Y[i] = CLAMP_Y(a); + } +} + +void _lumamagick_softburn(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + + if (a + b < 255) { + if (a > pixel_Y_hi_) + c = a; + else + c = (b >> 7) / (256 - a); + } else { + if (b <= pixel_Y_lo_) + b = 0xff; + c = 255 - (((255 - a) >> 7) / b); + } + Y[i] = c; + } +} + +void _lumamagick_inverseburn(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (a <= pixel_Y_lo_) + c = pixel_Y_lo_; + else + c = 255 - (((255 - b) >> 8) / a); + Y[i] = c; + } +} + + +void _lumamagick_colordodge(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c,d; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (a >= pixel_Y_hi_) + c = pixel_Y_hi_; + else { + d = pixel_Y_hi_ - a; + if( d <= pixel_Y_lo_ ) + d = 1; + c = (b >> 8) / d; + } + Y[i] = c; + } +} + +void _lumamagick_mulsub(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = (pixel_Y_hi_ - Y2[i]) * opacity_b; + if (b <= pixel_Y_lo_) + b = 1; + c = a / b; + Y[i] = c; + } +} + +void _lumamagick_lighten(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (a > b) + c = a; + else + c = b; + Y[i] = c; + } +} + +void _lumamagick_difference(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + Y[i] = abs(a - b); + } +} + +void _lumamagick_diffnegate(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = (255 - Y[i]) * opacity_a; + b = Y2[i] * opacity_b; + Y[i] = 255 - abs(a - b); + } +} + +void _lumamagick_exclusive(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + c = a + b - ((a * b) >> 8); + // Y[i] = Y[i] + Y2[i] - + // ((Y[i]*Y2[i])>>8); //or try 7 + Y[i] = c; + } +} + +void _lumamagick_basecolor(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c, d; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + c = a * b >> 7; + d = c + a * ((255 - (((255 - a) * (255 - b)) >> 8) - c) >> 8); //8 + Y[i] = d; + } +} + +void _lumamagick_freeze(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + + if (b <= pixel_Y_lo_) + c = pixel_Y_lo_; + else + c = 255 - ((255 - a) * (255 - a)) / b; + + Y[i] = c; + } +} + +void _lumamagick_unfreeze(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + + if (a <= pixel_Y_lo_) + c = pixel_Y_lo_; + else + c = 255 - ((256 - b) * (256 - b)) / a; + + Y[i] = c; + } +} + +void _lumamagick_hardlight(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + + if (b < 128) + c = (a * b) >> 7; + else + c = 255 - ((256 - b) * (256 - a) >> 7); + + Y[i] = c; + } +} +void _lumamagick_relativeaddlum(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + int a, b, c, d; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + c = a >> 1; + b = Y2[i] * opacity_b; + d = b >> 1; + Y[i] = c + d; + } +} + +void _lumamagick_relativesublum(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + Y[i] = (a - b + 255) >> 1; + } +} + +void _lumamagick_relativeadd(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b, c, d; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + c = a >> 1; + b = Y2[i] * opacity_b; + d = b >> 1; + Y[i] = c + d; + } + for (i = 0; i < uv_len; i++) { + a = Cb[i]; + c = a >> 1; + b = Cb2[i]; + d = b >> 1; + Cb[i] = c + d; + + a = Cr[i]; + c = a >> 1; + b = Cr2[i]; + d = b >> 1; + Cr[i] = c + d; + } +} + +void _lumamagick_relativesub(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + Y[i] = (a - b + 255) >> 1; + } + for (i = 0; i < uv_len; i++) { + a = Cb[i]; + b = Cb2[i]; + Cb[i] = (a - b + 255) >> 1; + a = Cr[i]; + b = Cr2[i]; + Cr[i] = (a - b + 255) >> 1; + } + +} +void _lumamagick_minsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (b < a) + Y[i] = (b - a + 255) >> 1; + else + Y[i] = (a - b + 255) >> 1; + } +} + +void _lumamagick_maxsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (b > a) + Y[i] = (b - a + 255) >> 1; + else + Y[i] = (a - b + 255) >> 1; + } +} + + + +void _lumamagick_addsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b) +{ + unsigned int i; + int c, a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + + if (b < a) { + c = (a + b) >> 1; + Y[i] = c; + } + } +} + + +void _lumamagick_maxselect(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (b > a) + Y[i] = b; + } +} + +void _lumamagick_minselect(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (b < a) + Y[i] = b; + } +} + +void _lumamagick_addtest(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int c, a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + c = a + ((2 * b) - 255); + Y[i] = CLAMP_Y(c); + } +} +void _lumamagick_addtest2(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int c, a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + c = a + ((2 * b) - 255); + Y[i] = CLAMP_Y(c); + } + for (i = 0; i < uv_len; i++) { + a = Cb[i]; + b = Cb2[i]; + c = a + (2 * b) - 255; + Cb[i] = CLAMP_UV(c); + + a = Cr[i]; + b = Cr2[i]; + c = a + (2 * b) - 255; + Cr[i] = CLAMP_UV(c); + + } + +} +void _lumamagick_addtest4(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int c, a, b; + double opacity_a = op_a * 0.01; + double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + b = b - 255; + if (b <= pixel_Y_lo_) + b = 0xff; + c = (a * a) / b; + + Y[i] = CLAMP_Y(c); + } + +} + +void _lumamagick_selectmin(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + a = Y[(i<<2)] * opacity_a; + b = Y2[(i<<2)] * opacity_b; + if (a > b) { + Cb[i] = Cb2[i]; + Cr[i] = Cr2[i]; + } + } + + + for (i = 0; i < uv_len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (b < a) { + Y[i] = b; + } + } +} + +void _lumamagick_addtest3(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int c, a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = (255 - Y2[i]) * opacity_b; + if (b <= pixel_Y_lo_) + b = 1; + c = (a * a) / b; + + Y[i] = c; + } + for (i = 0; i < uv_len; i++) { + //a = Cb[i] * opacity_a; + //b = (pixel_Y_hi_ - Cb2[i]) * opacity_b; + //if (b < pixel_Y_lo_) b = Cb2[i] * opacity_b; + a = Cb[i]; + b = 255 - Cb2[i]; + if (b < pixel_U_lo_) + b = Cb2[i]; + + c = (a >> 1) + (b >> 1); + + Cb[i] = c; + + //a = Cr[i] * opacity_a; + //b = (pixel_Y_hi_ - Cr2[i]) * opacity_b; + //if (b < pixel_Y_lo_) b = Cr2[i] * opacity_b; + + a = Cr[i]; + b = 255 - Cr2[i]; + if (b < pixel_U_lo_) + b = Cr2[i]; + + + c = (a >> 1) + (b >> 1); + + Cr[i] = c; + + } + +} + + +void _lumamagick_addlum(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b) +{ + unsigned int i; + int c, a, b; + const double opacity_a = op_a * 0.01; + const double opacity_b = op_b * 0.01; + const unsigned int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i] * opacity_a; + b = Y2[i] * opacity_b; + if (b > pixel_Y_hi_) + b = pixel_Y_hi_; + if ((255 - b) > 0) { + c = (a * a) / 255; + } else { + c = (a * a) / (256 - b); + } + Y[i] = c; + + } +} + + +void lumamagic_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n, int op_a, int op_b) +{ + switch (n) { + case VJ_EFFECT_BLEND_ADDDISTORT: + _lumamagick_add_distorted(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_SUBDISTORT: + _lumamagick_sub_distorted(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_MULTIPLY: + _lumamagick_multiply(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_DIVIDE: + _lumamagick_divide(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_ADDITIVE: + _lumamagick_additive(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_SUBSTRACTIVE: + _lumamagick_substractive(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_SOFTBURN: + _lumamagick_softburn(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_INVERSEBURN: + _lumamagick_inverseburn(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_COLORDODGE: + _lumamagick_colordodge(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_MULSUB: + _lumamagick_mulsub(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_LIGHTEN: + _lumamagick_lighten(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_DIFFERENCE: + _lumamagick_difference(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_DIFFNEGATE: + _lumamagick_diffnegate(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_EXCLUSIVE: + _lumamagick_exclusive(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_BASECOLOR: + _lumamagick_basecolor(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_HARDLIGHT: + _lumamagick_hardlight(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_RELADD: + _lumamagick_relativeadd(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_RELSUB: + _lumamagick_relativesub(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_MAXSEL: + _lumamagick_maxselect(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_MINSEL: + _lumamagick_minselect(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_RELADDLUM: + _lumamagick_relativeaddlum(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_RELSUBLUM: + _lumamagick_relativesublum(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_MINSUBSEL: + _lumamagick_minsubselect(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_MAXSUBSEL: + _lumamagick_maxsubselect(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_ADDSUBSEL: + _lumamagick_addsubselect(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_ADDAVG: + _lumamagick_addtest(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_ADDTEST2: + _lumamagick_addtest2(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_ADDTEST4: + _lumamagick_addtest3(frame, frame2, width, height, op_a, op_b); + break; + case VJ_EFFECT_BLEND_ADDTEST3: + _lumamagick_addtest4(frame, frame2, width, height, op_a, op_b); + break; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumamagick.h b/branches/V-1.5.3/veejay-server/libvje/effects/lumamagick.h new file mode 100644 index 00000000..82764088 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumamagick.h @@ -0,0 +1,149 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef LUMAMAGIC_H +#define LUMAMAGIC_H +#include +#include +#include + +vj_effect *lumamagick_init(); + +void lumamagic_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n, int op_a, int op_b); + +void _lumamagick_add_distorted(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_sub_distorted(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_multiply(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_divide(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_additive(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_substractive(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_softburn(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_inverseburn(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_colordodge(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_mulsub(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_lighten(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_difference(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_diffnegate(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_exclusive(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_basecolor(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_freeze(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_unfreeze(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_hardlight(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + + +void _lumamagick_relativesublum(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + + +void _lumamagick_relativeaddlum(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + + +void _lumamagick_relativesub(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_relativeadd(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + + +void _lumamagick_maxselect(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + + +void _lumamagick_minselect(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + + +void _lumamagick_minsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); +void _lumamagick_maxsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); +void _lumamagick_addsubselectlum(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, + int op_b); + +void _lumamagick_addsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); +void _lumamagick_addtest(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); +void _lumamagick_addtest2(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); +void _lumamagick_addtest3(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); +void _lumamagick_addtest4(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_selectmin(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_selectmax(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +void _lumamagick_selectfreeze(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_selectunfreeze(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_selectdiff(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); + +void _lumamagick_selectdiffneg(VJFrame *frame, VJFrame *frame2, + int width, int height, int op_a, int op_b); +void _lumamagick_addlum(VJFrame *frame, VJFrame *frame2, int width, + int height, int op_a, int op_b); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumamask.c b/branches/V-1.5.3/veejay-server/libvje/effects/lumamask.c new file mode 100644 index 00000000..50381352 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumamask.c @@ -0,0 +1,190 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* + this effect takes lumaninance information of frame B (0=no displacement,255=max displacement) + to extract distortion offsets for frame A. + h_scale and v_scale can be used to limit the scaling factor. + if the value is < 128, the pixels will be shifted to the left + otherwise to the right. + + + +*/ +#include +#include +#include +#include +#include "lumamask.h" +#include "common.h" +static uint8_t *buf[3] = { NULL,NULL,NULL }; + +vj_effect *lumamask_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = width; + ve->limits[0][1] = 1; + ve->limits[1][1] = height; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + ve->defaults[0] = width/20; + ve->defaults[1] = height/10; + ve->defaults[2] = 0; // border + ve->description = "Displacement Map"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "X displacement", "Y displcement", "Mode" ); + return ve; +} + +// FIXME: private + +static int n__ = 0; +static int N__ = 0; + + +int lumamask_malloc(int width, int height) +{ + buf[0] = (uint8_t*)vj_yuvalloc(width,height); + if(!buf[0]) return 0; + buf[1] = buf[0] + (width *height); + buf[2] = buf[1] + (width *height); + + n__ = 0; + N__ = 0; + return 1; +} + +void lumamask_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int v_scale, int h_scale, int border ) +{ + unsigned int x,y; + int dx,dy,nx,ny; + int tmp; + int interpolate = 1; + int tmp1 = v_scale; + int tmp2 = h_scale; + int motion = 0; + + if( motionmap_active() ) + { + motionmap_scale_to(width,height,1,1,&tmp1,&tmp2,&n__,&N__ ); + motion = 1; + } + else + { + n__ = 0; + N__ = 0; + } + if( n__ == N__ || n__ == 0 ) + interpolate = 0; + + double w_ratio = (double) tmp1 / 128.0; + double h_ratio = (double) tmp2 / 128.0; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + // keep copy of original frame + veejay_memcpy(buf[0], Y, width * height ); + veejay_memcpy(buf[1], Cb, (width * height) ); + veejay_memcpy(buf[2], Cr, (width * height) ); + + + if( border ) + { + for(y=0; y < height; y++) + { + for(x=0; x < width ; x++) + { + // calculate new location of pixel + tmp = Y2[(y*width+x)] - 128; + // new x offset + dx = w_ratio * tmp; + // new y offset + dy = h_ratio * tmp; + // new pixel coordinates + nx = x + dx; + ny = y + dy; + + + if( nx < 0 || ny < 0 || nx >= width || ny >= height ) + { + Y[y*width+x] = 16; + Cb[y*width+x] = 128; + Cr[y*width+x] = 128; + } + else + { + Y[y*width+x] = Y2[ny * width + nx]; + Cb[y*width+x] = Cb2[ny * width + nx]; + Cr[y*width+x] = Cr2[ny * width + nx]; + } + } + } + } + else + { + for(y=0; y < height; y++) + { + for(x=0; x < width ; x++) + { + tmp = Y2[(y*width+x)] - 128; + dx = w_ratio * tmp; + dy = h_ratio * tmp; + nx = x + dx; + ny = y + dy; + while( nx < 0 ) + nx += width; + while( ny < 0 ) + ny += height; + if( ny >= height ) ny = height - 1; + if( nx > width ) nx = width; + + Y[y*width+x] = Y2[ny * width + nx]; + Cb[y*width+x] = Cb2[ny * width + nx]; + Cr[y*width+x] = Cr2[ny * width + nx]; + } + } + } + + if( interpolate ) + motionmap_interpolate_frame( frame, N__, n__ ); + + if( motion ) + motionmap_store_frame( frame ); + +} +void lumamask_free() +{ + if(buf[0]) free(buf[0]); + buf[0] = NULL; + buf[1] = NULL; + buf[2] = NULL; +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/lumamask.h b/branches/V-1.5.3/veejay-server/libvje/effects/lumamask.h new file mode 100644 index 00000000..c36eafcc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/lumamask.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef LUMAMASK_H +#define LUMAMASK_H +#include +#include +#include + +void lumamask_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int mode, int h_scale, int border); +vj_effect *lumamask_init(int w, int h); +int lumamask_malloc(int w, int h); +void lumamask_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/magicmirror.c b/branches/V-1.5.3/veejay-server/libvje/effects/magicmirror.c new file mode 100644 index 00000000..96371c0b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/magicmirror.c @@ -0,0 +1,235 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "magicmirror.h" +#include "common.h" +// if d or n changes, tables need to be calculated +static uint8_t *magicmirrorbuf[3]; +static double *funhouse_x = NULL; +static double *funhouse_y = NULL; +static unsigned int *cache_x = NULL; +static unsigned int *cache_y = NULL; +static unsigned int last[2] = {0,0}; +//static uint8_t *p0_frame_ = NULL; + +vj_effect *magicmirror_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + + ve->defaults[0] = w/4; + ve->defaults[1] = h/4; + ve->defaults[2] = 20; + ve->defaults[3] = 20; + + ve->limits[0][0] = 0; + ve->limits[1][0] = w/2; + ve->limits[0][1] = 0; + ve->limits[1][1] = h/2; + ve->limits[0][2] = 0; + ve->limits[1][2] = 100; + ve->limits[0][3] = 0; + ve->limits[1][3] = 100; + + ve->sub_format = 1; + ve->description = "Magic Mirror Surface"; + ve->has_user =0; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list(ve->num_params, "X", "Y", "X","Y" ); + return ve; +} +// FIXME private +#define RUP8(num)(((num)+8)&~8) + +static int n__ = 0; +static int N__ = 0; +int magicmirror_malloc(int w, int h) +{ + magicmirrorbuf[0] = (uint8_t*)vj_yuvalloc(w,h); + if(!magicmirrorbuf[0]) return 0; + magicmirrorbuf[1] = magicmirrorbuf[0] + (w*h); + magicmirrorbuf[2] = magicmirrorbuf[1] + (w*h); + + funhouse_x = (double*)vj_calloc(sizeof(double) * w ); + if(!funhouse_x) return 0; + + cache_x = (unsigned int *)vj_calloc(sizeof(unsigned int)*w); + if(!cache_x) return 0; + + funhouse_y = (double*)vj_calloc(sizeof(double) * h ); + if(!funhouse_y) return 0; + + cache_y = (unsigned int*)vj_calloc(sizeof(unsigned int)*h); + if(!cache_y) return 0; + veejay_memset(cache_x,0,w); + veejay_memset(cache_y,0,h); + + n__ =0; + N__ =0; + //p0_frame_ = (uint8_t*) vj_malloc( sizeof(uint8_t) * RUP8( w * h * 3) ); + + return 1; +} + +void magicmirror_free() +{ + if(magicmirrorbuf[0]) free(magicmirrorbuf[0]); + if(funhouse_x) free(funhouse_x); + if(funhouse_y) free(funhouse_y); + if(cache_x) free(cache_x); + if(cache_y) free(cache_y); +// if(p0_frame_) free(p0_frame_); +// p0_frame_=0; + magicmirrorbuf[0] = NULL; + magicmirrorbuf[1] = NULL; + magicmirrorbuf[2] = NULL; + cache_x = NULL; + cache_y = NULL; + funhouse_x = NULL; + funhouse_y = NULL; +} + +void magicmirror_apply( VJFrame *frame, int w, int h, int vx, int vy, int d, int n ) +{ + double c1 = (double)vx; + double c2 = (double)vy; + int motion = 0; + if( motionmap_active()) + { + motionmap_scale_to( 100,100,0,0, &d, &n, &n__, &N__ ); + motion = 1; + } + else + { + n__ = 0; + N__ = 0; + } + + double c3 = (double)d * 0.001; + unsigned int dx,dy,x,y,p,q,len=w*h; + double c4 = (double)n * 0.001; + int changed = 0; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + int interpolate = 1; + + if( n__ == N__ || n__ == 0) + interpolate = 0; + + if( d != last[1] ) + { + changed = 1; last[1] =d; + } + if( n != last[0] ) + { + changed = 1; last[0] = n; + } + + if(changed==1) + { // degrees x or y changed, need new sin + for(x=0; x < w ; x++) + { + double res; + fast_sin(res,(double)(c3*x)); + funhouse_x[x] = res; + //funhouse_x[x] = sin(c3 * x); + } + for(y=0; y < h; y++) + { + double res; + fast_sin(res,(double)(c4*y)); + funhouse_y[y] = res; + //funhouse_y[y] = sin(c4 * y); + } + } + + veejay_memcpy( magicmirrorbuf[0], Y, len ); + veejay_memcpy( magicmirrorbuf[1], Cb, len ); + veejay_memcpy( magicmirrorbuf[2], Cr, len ); + + + for(x=0; x < w; x++) + { + dx = x + funhouse_x[x] * c1; + if(dx < 0) dx += w; + if(dx < 0) dx = 0; else if (dx >= w) dx = w-1; + cache_x[x] = dx; + } + for(y=0; y < h; y++) + { + dy = y + funhouse_y[y] * c2; + if(dy < 0) dy += h; + if(dy < 0) dy = 0; else if (dy >= h) dy = h-1; + cache_y[y] = dy; + } + + for(y=1; y < h-1; y++) + { + for(x=1; x < w-1; x++) + { + p = cache_y[y] * w + cache_x[x]; + q = y * w + x; + Y[q] = magicmirrorbuf[0][p]; + Cb[q] = magicmirrorbuf[1][p]; + Cr[q] = magicmirrorbuf[2][p]; + } + } +/* + uint8_t *p0[3] = { + p0_frame_ + 0, + p0_frame_ + (w*h), + p0_frame_ + (2*w*h) }; + + if(interpolate) + { + VJFrame prev; + veejay_memcpy(&prev, frame, sizeof(VJFrame)); + prev->data[0] = p0_frame_; + prev->data[1] = p0_frame_ + (w*h); + prev->data[2] = p0_frame_ + (2*w*h); + + motionmap_lerp_frame( frame, &prev, N__, n__ ); + } + + if( motionmap_active()) + { + veejay_memcpy( prev->data[0], Y, w*h); + veejay_memcpy( prev->data[1], Cb, w*h); + veejay_memcpY( prev->data[2], Cr,w*h); + }*/ + + if( interpolate ) + { + motionmap_interpolate_frame( frame, N__, n__ ); + } + + if( motion ) + { + motionmap_store_frame(frame); + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/magicmirror.h b/branches/V-1.5.3/veejay-server/libvje/effects/magicmirror.h new file mode 100644 index 00000000..dde65fba --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/magicmirror.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MAGICMIRROR_H +#define MAGICMIRROR_H +#include +#include +#include +#include + +vj_effect *magicmirror_init(int w, int h); +int magicmirror_malloc(int w, int h); +void magicmirror_apply( VJFrame *frame, int width, int height, int a, int b, + int na, int nb); +void magicmirror_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/magicoverlays.c b/branches/V-1.5.3/veejay-server/libvje/effects/magicoverlays.c new file mode 100644 index 00000000..241bd1ee --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/magicoverlays.c @@ -0,0 +1,794 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "magicoverlays.h" +#include + +#include "common.h" +vj_effect *overlaymagic_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 7; + ve->defaults[0] = 0; + ve->description = "Overlay Magic"; + ve->limits[0][0] = 1; + ve->limits[1][0] = 33; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; // clear chroma or keep + ve->extra_frame = 1; + ve->sub_format = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Keep or clear color" ); + return ve; +} + +/* rename methods in lumamagick and chromamagick */ + + +void _overlaymagic_adddistorted(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + c = a + b; + Y[i] = CLAMP_Y(c); + } + +} + +void _overlaymagic_add_distorted(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + + unsigned int i; + uint8_t y1, y2, cb, cr; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + y1 = Y[i]; + y2 = Y2[i]; + Y[i] = CLAMP_Y(y1 + y2); + } + +} + +void _overlaymagic_subdistorted(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + uint8_t y1, y2, cb, cr; + for (i = 0; i < len; i++) { + y1 = Y[i]; + y2 = Y2[i]; + y1 -= y2; + Y[i] = CLAMP_Y(y1); + } +} + +void _overlaymagic_sub_distorted(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + + unsigned int i ; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + uint8_t y1, y2, cb, cr; + for (i = 0; i < len; i++) { + y1 = Y[i]; + y2 = Y2[i]; + Y[i] = y1 - y2; + } +} + +void _overlaymagic_multiply(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + for (i = 0; i < len; i++) + Y[i] = (Y[i] * Y2[i]) >> 8; + +} +void _overlaymagic_simpledivide(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + for (i = 0; i < len; i++) { + if(Y2[i] > pixel_Y_lo_ ) + Y[i] = Y[i] / Y2[i]; + } +} + +void _overlaymagic_divide(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i; + int a, b, c; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + for (i = 0; i < len; i++) { + b = Y[i] * Y[i]; + c = 255 - Y2[i]; + if (c == 0) + c = 1; + a = b / c; + Y[i] = a; + } +} + +void _overlaymagic_additive(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a; + while(len--) { + a = Y[len] + (2 * Y2[len]) - 255; + Y[len] = CLAMP_Y(a); + } +} + + +void _overlaymagic_substractive(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + + unsigned int i; + int a; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) + Y[i] = CLAMP_Y( Y[i] - Y2[i] ); +} + +void _overlaymagic_softburn(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + + if ( (a + b) <= pixel_Y_hi_) { + if (a == pixel_Y_hi_) + c = a; + else + c = (b >> 7) / (256 - a); + } else { + if (b <= pixel_Y_lo_) { + b = 255; + } + c = 255 - (((255 - a) >> 7) / b); + } + Y[i] = c; + } +} + +void _overlaymagic_inverseburn(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if (a <= pixel_Y_lo_) + c = pixel_Y_lo_; + else + c = 255 - (((255 - b) >> 8) / a); + Y[i] = CLAMP_Y(c); + } +} + + +void _overlaymagic_colordodge(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if (a >= pixel_Y_hi_) + + c = pixel_Y_hi_; + else + c = (b >> 8) / (256 - a); + + if (c >= pixel_Y_hi_) + c = pixel_Y_hi_; + Y[i] = c; + } +} + +void _overlaymagic_mulsub(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = 255 - Y2[i]; + if (b > pixel_Y_lo_) + Y[i] = a / b; + } +} + +void _overlaymagic_lighten(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if (a > b) + c = a; + else + c = b; + Y[i] = c; + } +} + +void _overlaymagic_difference(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + Y[i] = abs(a - b); + } +} + +void _overlaymagic_diffnegate(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + int a, b; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = (255 - Y[i]); + b = Y2[i]; + Y[i] = 255 - abs(a - b); + } +} + +void _overlaymagic_exclusive(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a,b,c; + for (i = 0; i < len; i++) { + c = Y[i] + (2 * Y2[i]) - 255; + Y[i] = CLAMP_Y(c - (( Y[i] * Y2[i] ) >> 8 )); + } +} + +void _overlaymagic_basecolor(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + int a, b, c, d; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + c = a * b >> 8; + d = c + a * ((255 - (((255 - a) * (255 - b)) >> 8) - c) >> 8); //8 + Y[i] = CLAMP_Y(d); + } +} + +void _overlaymagic_freeze(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if ( b > pixel_Y_lo_ ) + Y[i] = CLAMP_Y(255 - ((( 255 - a) * ( 255 - a )) / b)); + } +} + +void _overlaymagic_unfreeze(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if( a > pixel_Y_lo_ ) + Y[i] = CLAMP_Y( 255 - ((( 255 - b ) * ( 255 - b )) / a)); + } +} + +void _overlaymagic_hardlight(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + + if (b < 128) + c = (a * b) >> 7; + else + c = 255 - ((255 - b) * (255 - a) >> 7); + Y[i] = c; + } +} +void _overlaymagic_relativeaddlum(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + int a, b, c, d; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + a = Y[i]; + c = a >> 1; + b = Y2[i]; + d = b >> 1; + Y[i] = CLAMP_Y(c + d); + } +} + +void _overlaymagic_relativesublum(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + Y[i] = (a - b + 255) >> 1; + } +} + +void _overlaymagic_relativeadd(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b, c, d; + for (i = 0; i < len; i++) { + a = Y[i]; + c = a >> 1; + b = Y2[i]; + d = b >> 1; + Y[i] = c + d; + } +} + +void _overlaymagic_relativesub(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + Y[i] = (a - b + 255) >> 1; + } + +} +void _overlaymagic_minsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if (b < a) + Y[i] = (b - a + 255) >> 1; + else + Y[i] = (a - b + 255) >> 1; + } +} + +void _overlaymagic_maxsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if (b > a) + Y[i] = (b - a + 255) >> 1; + else + Y[i] = (a - b + 255) >> 1; + } +} + + + +void _overlaymagic_addsubselect(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + int c, a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + + if (b < a) { + c = (a + b) >> 1; + Y[i] = c; + } + } +} + + +void _overlaymagic_maxselect(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if (b > a) + Y[i] = b; + } +} + +void _overlaymagic_minselect(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + if (b < a) + Y[i] = b; + } +} + +void _overlaymagic_addtest(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int c, a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + c = a + ((2 * b) - 255)>>1; + Y[i] = CLAMP_Y(c); + } +} +void _overlaymagic_addtest2(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + int c, a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + c = a + (2 * b) - 255; + Y[i] = CLAMP_Y(c); + } + + +} +void _overlaymagic_addtest4(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int i; + unsigned int len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + int c, a, b; + for (i = 0; i < len; i++) { + a = Y[i]; + b = Y2[i]; + b = b - 255; + if (b <= pixel_Y_lo_) + Y[i] = a; + else + Y[i] = (a * a) / b; + } + +} + +void _overlaymagic_try + (VJFrame *frame, VJFrame *frame2, int width, int height) { + unsigned int i; + unsigned int len = width * height; + int a, b, p, q; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + + for (i = 0; i < len; i++) { + /* calc p */ + a = Y[i]; + b = Y[i]; + + if (b <= pixel_Y_lo_) + p = pixel_Y_lo_; + else + p = 255 - ((256 - a) * (256 - a)) / b; + if (p <= pixel_Y_lo_) + p = pixel_Y_lo_; + + /* calc q */ + a = Y2[i]; + b = Y2[i]; + if (b <= pixel_Y_lo_) + q = pixel_Y_lo_; + else + q = 255 - ((256 - a) * (256 - a)) / b; + if (b <= pixel_Y_lo_) + q = pixel_Y_lo_; + + /* calc pixel */ + if (q <= pixel_Y_lo_) + q = pixel_Y_lo_; + else + q = 255 - ((256 - p) * (256 - a)) / q; + + Y[i] = q; + } +} + +void overlaymagic_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n, int clearchroma) +{ + switch (n) { + case VJ_EFFECT_BLEND_ADDITIVE: + _overlaymagic_additive(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_SUBSTRACTIVE: + _overlaymagic_substractive(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_MULTIPLY: + _overlaymagic_multiply(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_DIVIDE: + _overlaymagic_simpledivide(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_LIGHTEN: + _overlaymagic_lighten(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_DIFFERENCE: + _overlaymagic_difference(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_DIFFNEGATE: + _overlaymagic_diffnegate(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_EXCLUSIVE: + _overlaymagic_exclusive(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_BASECOLOR: + _overlaymagic_basecolor(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_FREEZE: + _overlaymagic_freeze(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_UNFREEZE: + _overlaymagic_unfreeze(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_RELADD: + _overlaymagic_relativeadd(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_RELSUB: + _overlaymagic_relativesub(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_RELADDLUM: + _overlaymagic_relativeaddlum(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_RELSUBLUM: + _overlaymagic_relativesublum(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_MAXSEL: + _overlaymagic_maxselect(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_MINSEL: + _overlaymagic_minselect(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_MINSUBSEL: + _overlaymagic_minsubselect(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_MAXSUBSEL: + _overlaymagic_maxsubselect(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_ADDSUBSEL: + _overlaymagic_addsubselect(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_ADDAVG: + _overlaymagic_add_distorted(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_ADDTEST2: + _overlaymagic_addtest(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_ADDTEST3: + _overlaymagic_addtest2(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_ADDTEST4: + _overlaymagic_addtest4(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_MULSUB: + _overlaymagic_mulsub(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_SOFTBURN: + _overlaymagic_softburn(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_INVERSEBURN: + _overlaymagic_inverseburn(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_COLORDODGE: + _overlaymagic_colordodge(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_ADDDISTORT: + _overlaymagic_adddistorted(frame, frame2, width, height); + break; + case VJ_EFFECT_BLEND_SUBDISTORT: + _overlaymagic_subdistorted(frame, frame2, width, height); + break; + case 32: + _overlaymagic_try(frame, frame2, width, height); + break; + case 33: + _overlaymagic_divide(frame,frame2,width,height); + break; + + } + if(clearchroma) { + veejay_memset( frame->data[1], 128, frame->uv_len ); + veejay_memset( frame->data[2], 128, frame->uv_len ); + } +} +void overlaymagic_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/magicoverlays.h b/branches/V-1.5.3/veejay-server/libvje/effects/magicoverlays.h new file mode 100644 index 00000000..3d201f2a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/magicoverlays.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MAGICOVERLAYS_H +#define MAGICOVERLAYS_H +#include +#include +#include + +vj_effect *overlaymagic_init(int w, int h); + +void overlaymagic_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int n, int mode); + +void magicoverlays_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/magicphotos.c b/branches/V-1.5.3/veejay-server/libvje/effects/magicphotos.c new file mode 100644 index 00000000..3199a7ca --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/magicphotos.c @@ -0,0 +1,228 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include "photoplay.h" +#include +#include "common.h" + +vj_effect *photoplay_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; // divider + ve->limits[1][0] = max_power(w); + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; // waterfall + ve->limits[0][2] = 0; + ve->limits[1][2] = 3; // mode + ve->defaults[0] = 2; + ve->defaults[1] = 0; + ve->defaults[2] = 1; + ve->description = "Photoplay (timestretched mosaic)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Photos", "Waterfall", "Mode" ); + return ve; +} + +static picture_t **photo_list = NULL; +static int num_photos = 0; +static int frame_counter = 0; + + +static int prepare_filmstrip(int film_length, int w, int h) +{ + int i,j; + int picture_width = w / sqrt(film_length); + int picture_height = h / sqrt(film_length); + + photo_list = (picture_t**) vj_malloc(sizeof(picture_t*) * (film_length + 1) ); + if(!photo_list) + return 0; + + num_photos = film_length; + + uint8_t val = 0; + int inc = num_photos % 255; + + for ( i = 0; i < num_photos; i ++ ) + { + photo_list[i] = vj_malloc(sizeof(picture_t)); + if(!photo_list[i]) + return 0; + photo_list[i]->w = picture_width; + photo_list[i]->h = picture_height; + for( j = 0; j < 3; j ++ ) + { + photo_list[i]->data[j] = vj_malloc(sizeof(uint8_t) * picture_width * picture_height ); + if(!photo_list[i]->data[j]) + return 0; + memset(photo_list[i]->data[j], (j==0 ? val : 128), picture_width *picture_height ); + } + val+= inc; + } + frame_counter = 0; + + return 1; +} + +static void destroy_filmstrip(void) +{ + if(photo_list) + { + int i = 0; + while(i < num_photos) + { + if( photo_list[i] ) + { + int j; + for( j = 0; j < 3; j ++ ) + if(photo_list[i]->data[j]) + free(photo_list[i]->data[j]); + free(photo_list[i]); + } + i++; + } + free(photo_list); + } + photo_list = NULL; + num_photos = 0; + frame_counter = 0; +} + + + +int photoplay_malloc(int w, int h ) +{ + num_photos = 0; + return 1; +} + + +void photoplay_free(void) +{ + destroy_filmstrip(); +} + +static void take_photo( uint8_t *plane, uint8_t *dst_plane, int w, int h, int index ) +{ + + int x,y,dx,dy; + int sum; + int dst_x, dst_y; + int step_y; + int step_x; + int box_width = photo_list[index]->w; + int box_height = photo_list[index]->h; + + step_x = w / box_width; + step_y = h / box_height; + + for( y = 0 ,dst_y = 0; y < h && dst_y < box_height; y += step_y ) + { + for( x = 0, dst_x = 0; x < w && dst_x < box_width; x+= step_x ) + { + sum = 0; + for( dy = 0; dy < step_y; dy ++ ) + { + for( dx = 0; dx < step_x; dx++) + { + sum += plane[ ((y+dy)*w+(dx+x)) ]; + } + } + // still problem here! + if(sum > 0) + dst_plane[(dst_y*box_width)+dst_x] = sum / (step_y*step_x); + else + dst_plane[(dst_y*box_width)+dst_x] = 16; + + dst_x++; + } + dst_y++; + } +} + +static void put_photo( uint8_t *dst_plane, uint8_t *photo, int dst_w, int dst_h, int index , matrix_t matrix) +{ + int box_w = photo_list[index]->w; + int box_h = photo_list[index]->h; + int x,y; + + uint8_t *P = dst_plane + (matrix.h*dst_w); + int offset = matrix.w; + + for( y = 0; y < box_h; y ++ ) + { + for( x = 0; x < box_w; x ++ ) + { + *(P+offset+x) = photo[(y*box_w)+x]; + } + P += dst_w; + } +} + +void photoplay_apply( VJFrame *frame, int width, int height, int size, int delay, int mode ) +{ + unsigned int i; + uint8_t *dstY = frame->data[0]; + uint8_t *dstU = frame->data[1]; + uint8_t *dstV = frame->data[2]; + + matrix_f matrix_placement = get_matrix_func(mode); + + if( (size*size) != num_photos || num_photos == 0 ) + { + destroy_filmstrip(); + if(!prepare_filmstrip(size*size, width,height)) + { + return; + } + } + + + if(frame_counter < num_photos) + { + for( i = 0; i < 3 ; i ++ ) + memset( frame->data[i], (i==0?16:128), (width*height)); + frame_counter ++; + return; + } + + for( i = 0; i < 3; i ++ ) + { + take_photo( frame->data[i], photo_list[(frame_counter%num_photos)]->data[i], width, height , frame_counter % num_photos); + } + + for ( i = 0; i < num_photos; i ++ ) + { + matrix_t m = matrix_placement(i, size,width,height ); + put_photo( dstY, photo_list[i]->data[0],width,height,i, m); + put_photo( dstU, photo_list[i]->data[1],width,height,i, m); + put_photo( dstV, photo_list[i]->data[2],width,height,i, m); + } + + + frame_counter ++; +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/magicscratcher.c b/branches/V-1.5.3/veejay-server/libvje/effects/magicscratcher.c new file mode 100644 index 00000000..b636eca5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/magicscratcher.c @@ -0,0 +1,182 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "magicscratcher.h" +#include "common.h" + +static uint8_t *mframe; +static int m_frame = 0; +static int m_reverse = 0; +static int m_rerun = 0; + +vj_effect *magicscratcher_init(int w, int h) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 9; + ve->limits[0][1] = 1; + ve->limits[1][1] = MAX_SCRATCH_FRAMES - 1; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + ve->defaults[0] = 1; + ve->defaults[1] = 7; + ve->defaults[2] = 1; + ve->description = "Magic Overlay Scratcher"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Scratch frames", "PingPong"); + return ve; +} +//FIXME: private +int magicscratcher_malloc(int w, int h) +{ + mframe = + (uint8_t *) vj_calloc(w * h * sizeof(uint8_t) * MAX_SCRATCH_FRAMES); + if(!mframe) return 0; + return 1; + +} +void magicscratcher_free() { + if(mframe) free(mframe); + m_rerun = 0; +} + +void store_mframe(uint8_t * yuv1[3], int w, int h, int n, int no_reverse) +{ + if (!m_reverse) { + veejay_memcpy(mframe + (w * h * m_frame), yuv1[0], (w * h)); + } else { + veejay_memcpy(yuv1[0], mframe + (w * h * m_frame), (w * h)); + } + if (m_reverse) + m_frame--; + else + m_frame++; + + if (m_frame >= n ) { + if (no_reverse == 0) { + m_reverse = 1; + m_frame = n - 1; + } else { + m_frame = 0; + } + } + + if (m_frame == 0) + m_reverse = 0; + + m_rerun = m_frame; +} + + +void magicscratcher_apply(VJFrame *frame, + int width, int height, int mode, int n, + int no_reverse) +{ + + unsigned int x, len = width * height; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + int uv_width = frame->uv_width; + int uv_height = frame->uv_height; + /* param 6 is cool ,8,7,10,13,15, ,9,11,12,14, + + 16 voor default ?, 17 (!),18,19, 20(!), 21, 24,,25,30 */ + int offset = len * m_frame; + + pix_func_Y func_y; + + switch (mode) { + //case 0: mode = 5; break; + case 1: + mode = 22; + break; + case 2: + mode = 25; + break; + //case 3: mode = 30; break; + case 3: + mode = 24; + break; + //case 5: mode = 21; break; + //case 6: mode = 20; break; + //case 7: mode = 19; break; + //case 8: mode = 18; break; + case 4: + mode = 17; + break; + case 5: + mode = 16; + break; + //case 11: mode = 14; break; + //case 12: mode = 12; break; + //case 13: mode = 11; break; + case 6: + mode = 9; + break; + case 7: + mode = 8; + break; + case 8: + mode = 7; + break; + case 9: + mode = 6; + break; + } + + func_y = get_pix_func_Y((const int) mode); + + /* kill chroma in channel */ + veejay_memset( Cb, 128, frame->uv_len); + veejay_memset( Cr, 128, frame->uv_len); + + if (m_frame == 0) { + if( m_rerun > 0 ) { + veejay_memcpy( mframe + (len * m_rerun) , Y , len ); + m_rerun = m_frame; + } + else { + veejay_memcpy(mframe + (len * m_frame), Y, len); + } + m_frame ++; + } + + for (x = 0; x < len; x++) { + Y[x] = func_y( mframe[offset + x], Y[x]); + } + if (m_frame > 0) { + veejay_memset(mframe + (len * (m_frame - 1)), 16, len); + } + + store_mframe(frame->data, width, height, n, no_reverse); + + //printf( "[%d] , reverse = %d, offset = %d, n = %d\n",m_frame,m_reverse,offset,n); +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/magicscratcher.h b/branches/V-1.5.3/veejay-server/libvje/effects/magicscratcher.h new file mode 100644 index 00000000..9dc872eb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/magicscratcher.h @@ -0,0 +1,34 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MAGICSCRATCHER_H +#define MAGICSCRATCHER_H +#include +#include +#include +#include + +vj_effect *magicscratcher_init(int w, int h); +int magicscratcher_malloc(int w, int h); +void magicscratcher_free(); +void magicscratcher_apply( VJFrame *frame, + int width, int height, int type, int nframes, + int no_reverse); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mask.c b/branches/V-1.5.3/veejay-server/libvje/effects/mask.c new file mode 100644 index 00000000..c26c64eb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mask.c @@ -0,0 +1,87 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "mask.h" + + +vj_effect *simplemask_init(int w, int h ) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->defaults[0] = 128; + ve->defaults[1] = 0; + ve->description = "Simple Mask (black and white)"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user =0; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Mode" ); + return ve; +} + + +void mask_replace_black(uint8_t *yuv1[3], uint8_t *yuv2[3], int w, int h, int threshold) { + unsigned int len = w * h; + unsigned int i=0; + for(i=0; i < len; i++) { + if (yuv1[0][i] > threshold) { + yuv1[0][i] = yuv2[0][i]; + yuv1[1][i] = yuv2[1][i]; + yuv1[2][i] = yuv2[2][i]; + } + } +} +void mask_replace_black_fill(uint8_t *yuv1[3], uint8_t *yuv2[3], int w, int h, int threshold) { + unsigned int len = w * h; + unsigned int i=0; + for(i=0; i < len; i++) { + if (yuv1[0][i] > threshold) { + yuv1[0][i] = yuv2[0][i]; + yuv1[1][i] = yuv2[1][i]; + yuv1[2][i] = yuv2[2][i]; + } + else { + yuv1[0][i] = 16; + yuv1[1][i] = 128; + yuv1[2][i] = 128; + } + } +} + +void simplemask_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int threshold, int invert) +{ + + switch(invert) { + case 0 : mask_replace_black(frame->data,frame2->data,width,height,threshold); break; + case 1 : mask_replace_black_fill(frame->data,frame2->data,width,height,threshold); break; + } + +} +void mask_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mask.h b/branches/V-1.5.3/veejay-server/libvje/effects/mask.h new file mode 100644 index 00000000..b79f6675 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mask.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SIMPLEMASK_H +#define SIMPLEMASK_H +#include +#include +#include + +vj_effect *simplemask_init(); +void simplemask_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int threshold, int invert); +void mask_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/maskstop.c b/branches/V-1.5.3/veejay-server/libvje/effects/maskstop.c new file mode 100644 index 00000000..afd97e44 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/maskstop.c @@ -0,0 +1,200 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * vvMaskStop - ported from vvFFPP_basic + * Copyright(C)2005 Maciek Szczesniak + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include "common.h" +#include "split.h" +#include +#include + +static uint8_t *vvmaskstop_buffer[6]; +static unsigned int frq_frame; +static unsigned int frq_mask; + +vj_effect *maskstop_init(int width , int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; // negate mask + ve->defaults[1] = 0; // swap mask/frame + ve->defaults[2] = 80; // hold frame freq + ve->defaults[3] = 20; // hold mask freq + + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->param_description = vje_build_param_list( ve->num_params, "Negate Mask", "Swap Mask/Frame", "Hold Frame Frequency", "Hold Mask Frequency"); + + ve->description = "vvMaskStop"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + + frq_frame = 256; + frq_mask = 256; + + return ve; +} + +int maskstop_malloc(int width, int height) +{ + int i; + vvmaskstop_buffer[0] = (uint8_t*) vj_malloc( sizeof(uint8_t) * width * height * 6 ); + for( i = 1; i < 6; i ++ ) + vvmaskstop_buffer[i] = vvmaskstop_buffer[(i-1)] + (width * height); + veejay_memset( vvmaskstop_buffer[1], 128, (width*height)*2); + veejay_memset( vvmaskstop_buffer[2], 128, (width*height)*2); + + return 1; +} + +void maskstop_free() { + if(vvmaskstop_buffer[0]) + free(vvmaskstop_buffer[0]); + int i; + for(i = 0 ;i < 6 ; i++) + vvmaskstop_buffer[i] = NULL; +} + + +void maskstop_apply( VJFrame *frame, int width, int height, int negmask, int swapmask, int framefreq, int maskfreq) { + int i=0; + const unsigned int len = frame->len; + + uint8_t *Yframe = vvmaskstop_buffer[0]; + uint8_t *Uframe = vvmaskstop_buffer[1]; + uint8_t *Vframe = vvmaskstop_buffer[2]; + uint8_t *Ymask = vvmaskstop_buffer[3]; + uint8_t *Umask = vvmaskstop_buffer[4]; + uint8_t *Vmask = vvmaskstop_buffer[5]; + uint8_t *Ydest = frame->data[0]; + uint8_t *Udest = frame->data[1]; + uint8_t *Vdest = frame->data[2]; + + float val, valN; + + frq_frame = frq_frame + framefreq; + frq_mask = frq_mask + maskfreq; + + if (frq_frame > 255) { + veejay_memcpy(Yframe, Ydest, len); + veejay_memcpy(Uframe, Udest, len); + veejay_memcpy(Vframe, Vdest, len); + frq_frame = 0; + } + + if (frq_mask > 255) { + veejay_memcpy(Ymask, Ydest, len); + veejay_memcpy(Umask, Udest, len); + veejay_memcpy(Vmask, Vdest, len); + frq_mask = 0; + } + + // negmask acts like transparency mask: new p = ((p0 * a) + (p1 * (255-a))) / 255 + if(swapmask && negmask) + { + for( i = 0; i < len; i ++ ) + { + Ydest[i] = ((Yframe[i] * Ymask[i]) + ((0xff-Ydest[i]) * (0xff-Ymask[i])))>>8; + Udest[i] = ((Uframe[i] * Umask[i]) + ((0xff-Udest[i]) * (0xff-Umask[i])))>>8; + Vdest[i] = ((Vframe[i] * Vmask[i]) + ((0xff-Vdest[i]) * (0xff-Vmask[i])))>>8; + } + } + if(swapmask && !negmask) + { + for( i = 0; i < len ; i ++ ) + { + Ydest[i] = ((Yframe[i] * (0xff-Ymask[i]) + (Ydest[i] * Ymask[i])))>>8; + Udest[i] = ((Uframe[i] * (0xff-Umask[i]) + (Udest[i] * Umask[i])))>>8; + Vdest[i] = ((Vframe[i] * (0xff-Vmask[i]) + (Vdest[i] * Vmask[i])))>>8; + } + } + if(!swapmask && negmask) + { + for( i = 0; i < len; i ++ ) + { + Ydest[i] = ((Ymask[i] * Yframe[i]) + ( (0xff-Ydest[i]) * (0xff-Yframe[i])) ) >> 8; + Udest[i] = ((Umask[i] * Uframe[i]) + ( (0xff-Udest[i]) * (0xff-Uframe[i])) ) >> 8; + Vdest[i] = ((Vmask[i] * Vframe[i]) + ( (0xff-Vdest[i]) * (0xff-Vframe[i])) ) >> 8; + } + } + if(!swapmask && !negmask) + { + for( i = 0; i < len; i ++ ) + { + Ydest[i] = ((Ymask[i] * (0xff-Yframe[i])) + ( Ydest[i] * Yframe[i]) ) >> 8; + Udest[i] = ((Umask[i] * (0xff-Uframe[i])) + ( Udest[i] * Uframe[i]) ) >> 8; + Vdest[i] = ((Vmask[i] * (0xff-Vframe[i])) + ( Vdest[i] * Vframe[i]) ) >> 8; + } + + } + + +/* + for (i = 0; i < len; i++) { + if (swapmask) { + + if (negmask) { + val = (float)Ymask[i]/255; + valN = (float)1 - val; + } else { + valN = (float)Ymask[i]/255; + val = (float)1 - valN; + } + + Ydest[i] = (uint8_t) Yframe[i] * val + Ydest[i] * valN; + Udest[i] = (uint8_t) Uframe[i] * val + Udest[i] * valN; + Vdest[i] = (uint8_t) Vframe[i] * val + Vdest[i] * valN; + + } else { + + if (negmask) { + val = (float)Yframe[i]/255; + valN = (float)1 - val; + } else { + valN = (float)Yframe[i]/255; + val = (float)1 - valN; + } + + Ydest[i] = (uint8_t) Ymask[i] * val + Ydest[i] * valN; + Udest[i] = (uint8_t) Umask[i] * val + Udest[i] * valN; + Vdest[i] = (uint8_t) Vmask[i] * val + Vdest[i] * valN; + + } + + } + */ +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/maskstop.h b/branches/V-1.5.3/veejay-server/libvje/effects/maskstop.h new file mode 100644 index 00000000..48c24798 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/maskstop.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MASKSTOP_H +#define MASKSTOP_H +#include +#include +#include + +vj_effect *maskstop_init(int width, int height); +int maskstop_malloc(int w, int h); +void maskstop_free(); +void maskstop_apply( VJFrame *frame, int width, int height, int negmask, int swapmask, int framefreq, int maskfreq); +#endif + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/median.c b/branches/V-1.5.3/veejay-server/libvje/effects/median.c new file mode 100644 index 00000000..d7e374cb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/median.c @@ -0,0 +1,70 @@ +/* + * Linux VeeJay + * + * Copyright(C)2010 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "median.h" +#include +vj_effect *medianfilter_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 127; + ve->defaults[0] = 3;// 255; + ve->description = "Constant Time Median Filter"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value" ); + return ve; +} + +void medianfilter_apply( VJFrame *frame, int width, int height, int val) +{ + int i; + int len = (width * height); + int uv_len = frame->uv_len; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + if( val == 0 ) + return; + + uint8_t *buffer = (uint8_t*) vj_malloc(sizeof(uint8_t)*width*height*3); + veejay_memset( buffer,0, width*height*3); + ctmf( Y, buffer, width,height,width,width,val,1,1024*1024*8); + ctmf( Cb,buffer + (width*height), width,height/2,width,width,val,1,512*1024); + ctmf( Cr,buffer + (width*height*2),width,height/2,width,width,val,1,512*1024); + + veejay_memcpy( Y, buffer, width*height); + veejay_memcpy( Cb,buffer + (width*height), width*height); + veejay_memcpy( Cr,buffer + (width*height*2), width*height); + + free(buffer); + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/median.h b/branches/V-1.5.3/veejay-server/libvje/effects/median.h new file mode 100644 index 00000000..772c6a9c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/median.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2010 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MEDIANFILT_H +#define MEDIANFILT_H +#include +#include +#include + +vj_effect *medianfilter_init(int w, int h); +void medianfilter_apply( VJFrame *frame, int width, int height, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mirrors.c b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors.c new file mode 100644 index 00000000..34cfee5d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors.c @@ -0,0 +1,177 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "mirrors.h" +#include "common.h" + +vj_effect *mirrors_init(int width,int height) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + ve->defaults[1] = 1; + ve->limits[0][0] = 0; /* horizontal or vertical mirror */ + ve->limits[1][0] = 3; + ve->limits[0][1] = 0; + ve->limits[1][1] = (int)((float)(width * 0.33)); + ve->sub_format = 1; + ve->description = "Multi Mirrors"; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "H or V", "Number" ); + return ve; +} + +void _mirrors_v( uint8_t *yuv[3], int width, int height, int factor, int swap) +{ + const int len = width * height; + int r,c; + const int line_width = width / ( factor + 1); + int i=0; + + if(swap) + { + for(r = 0; r < len; r += width ) + { + for( c = 0 ; c < width; c+= line_width) + { + for(i = 0; i < line_width; i++) + { + yuv[0][r + c + (line_width-i)] = yuv[0][r + c + i]; + yuv[1][r + c + (line_width-i)] = yuv[1][r + c + i]; + yuv[2][r + c + (line_width-i)] = yuv[2][r + c + i]; + } + } + + } + } + else + { + for(r = 0; r < len; r += width ) + { + for( c = 0 ; c < width; c+= line_width) + { + for(i = 0; i < line_width; i++) + { + yuv[0][r + c + i] = yuv[0][r + c + (line_width-i)]; + yuv[1][r + c + i] = yuv[1][r + c + (line_width-i)]; + yuv[2][r + c + i] = yuv[2][r + c + (line_width-i)]; + } + } + + } + } +} +void _mirrors_h( uint8_t *yuv[3], int width, int height, int factor, int swap) +{ + int line_height = height / ( factor + 1); + + int nr = height / line_height; + int x,y,i; + int slice = 0; + int slice_end = 0; + if(swap) + { + for(i=0; i < nr; i++) + { + slice = i * line_height; + slice_end = slice + line_height; + for(y=slice; y < slice_end; y++) + { + for(x=0; x < width; x++) + { + yuv[0][(y*width)+x] = yuv[0][(slice_end-y)*width+x]; + yuv[1][y*width+x] = yuv[1][(slice_end-y)*width+x]; + yuv[2][y*width+x] = yuv[2][(slice_end-y)*width+x]; + } + } + } + } + else + { + for(i=0; i < nr; i++) + { + slice = i * line_height; + slice_end = slice + line_height; + for(y=slice_end; y > 0; y--) + { + for(x=0; x < width; x++) + { + yuv[0][y*width+x] = yuv[0][(slice_end-y)*width+x]; + yuv[1][y*width+x] = yuv[1][(slice_end-y)*width+x]; + yuv[2][y*width+x] = yuv[2][(slice_end-y)*width+x]; + } + } + } + } +} + +static int n__ = 0; +static int N__ = 0; + +void mirrors_apply(VJFrame *frame, int width, int height, int type, + int factor ) +{ + int interpolate = 1; + int motion = 0; + int tmp1 = 0; + int tmp2 = factor; + if( motionmap_active() ) + { + int hi = (int)((float)(width * 0.33)); + + motionmap_scale_to( hi,hi,0,0,&tmp1,&tmp2,&n__,&N__); + motion = 1; + } + else + { + n__ = 0; + N__ = 0; + interpolate=0; + } + + switch (type) { + case 0: + _mirrors_v(frame->data, width, height, tmp2, 0); + break; + case 1: + _mirrors_v(frame->data,width,height,tmp2,1); + break; + case 2: + _mirrors_h(frame->data,width,height,tmp2,0); + break; + case 3: + _mirrors_h(frame->data,width,height,tmp2,1); + break; + } + + if( interpolate ) + motionmap_interpolate_frame( frame, N__,n__ ); + if( motion ) + motionmap_store_frame( frame ); +} +void mirrors_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mirrors.h b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors.h new file mode 100644 index 00000000..b1654e3e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MIRRORS_H +#define MIRRORS_H +#include +#include +#include + +vj_effect *mirrors_init(int width,int height); + +void mirrors_apply( VJFrame *frame, int width, int height, int type, + int factor); + +void mirrors_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mirrors2.c b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors2.c new file mode 100644 index 00000000..beee2c32 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors2.c @@ -0,0 +1,214 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "mirrors2.h" + +vj_effect *mirrors2_init(int w, int h) +{ + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 4; + ve->limits[0][0] = 0; /* horizontal or vertical mirror */ + ve->limits[1][0] = 5; + ve->sub_format = 1; + ve->description = "Mirror"; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "H or V mode"); + return ve; +} + + + +void mirror_multi_dr(uint8_t * yuv[3], int width, int height) +{ + + unsigned int x, y; + unsigned int hlen = height / 2; + unsigned int vlen = width / 2; + unsigned int yi1, yi2; + uint8_t p, cr, cb; + + for (y = hlen; y < height; y++) { + yi1 = y * width; + yi2 = (height - y - 1) * width; + for (x = vlen; x < width; x++) { + p = yuv[0][yi1 + x]; + yuv[0][yi1 + x + (width - x - 1)] = p; + yuv[0][yi2 + x] = p; + yuv[0][yi2 + (width - x - 1)] = p; + cb = yuv[1][yi1 + x]; + cr = yuv[2][yi1 + x]; + yuv[1][yi1 + x + (width - x - 1)] = cb; + yuv[1][yi2 + x] = cb; + yuv[1][yi2 + (width - x - 1)] = cb; + yuv[2][yi1 + x + (width - x - 1)] = cr; + yuv[2][yi2 + x] = cr; + yuv[2][yi2 + (width - x - 1)] = cr; + } + } +} + +void mirror_multi_u(uint8_t * yuv[3], int width, int height) +{ + unsigned int x, y; + + unsigned int yi1, yi2; + unsigned int hlen = height / 2; + + uint8_t p, cb, cr; + + for (y = 0; y < hlen; y++) { + yi1 = y * width; + yi2 = (height - y - 1) * width; + for (x = 0; x < width; x++) { + p = yuv[0][yi1 + x]; + yuv[0][yi2 + x] = p; + cb = yuv[1][yi1 + x]; + cr = yuv[2][yi1 + x]; + yuv[1][yi2 + x] = cb; + yuv[2][yi2 + x] = cr; + } + } +} + +void mirror_multi_d(uint8_t * yuv[3], int width, int height) +{ + unsigned int x, y; + unsigned int yi1 = 0; + unsigned int yi2 = 0; + unsigned int hlen = height / 2; + uint8_t p, cb, cr; + + for (y = hlen; y < height; y++) { + yi1 = y * width; + yi2 = (height - y - 1) * width; + + for (x = 0; x < width; x++) { + p = yuv[0][yi1 + x]; + yuv[0][yi2 + x] = p; + cb = yuv[1][yi1 + x]; + cr = yuv[2][yi1 + x]; + yuv[1][yi2 + x] = cb; + yuv[2][yi2 + x] = cr; + } + } +} + +void mirror_multi_l(uint8_t * yuv[3], int width, int height) +{ + unsigned int x, y; + + unsigned int yi; + unsigned int vlen = width / 2; + uint8_t p, cb, cr; + for (y = 0; y < height; y++) { + yi = y * width; + for (x = vlen; x < width; x++) { + p = yuv[0][yi + x]; + yuv[0][yi + (width - x - 1)] = p; + cb = yuv[1][yi + x]; + yuv[1][yi + (width - x - 1)] = cb; + cr = yuv[2][yi + x]; + yuv[2][yi + (width - x - 1)] = cr; + } + } +} + +void mirror_multi_r(uint8_t * yuv[3], int width, int height) +{ + unsigned int x, y; + + unsigned int yi; + + uint8_t p, cb, cr; + + for (y = 0; y < height; y++) { + yi = y * width; + for (x = 0; x < width; x++) { + p = yuv[0][yi + x]; + yuv[0][yi + (width - x - 1)] = p; + cb = yuv[1][yi + x]; + cr = yuv[2][yi + x]; + yuv[1][yi + (width - x - 1)] = cb; + yuv[2][yi + (width - x - 1)] = cr; + } + } +} + +void mirror_multi_ur(uint8_t * yuv[3], int width, int height) +{ + unsigned int x, y; + + unsigned int yi, yi2; + unsigned int vlen = width / 2; + unsigned int hlen = width / 2; + uint8_t p, cb, cr; + + for (y = hlen; y < height; y++) { + yi = y * width; + yi2 = (height - y - 1) * width; + for (x = 0; x < vlen; x++) { + p = yuv[0][yi + x]; + yuv[0][yi + (width - x - 1)] = p; + yuv[0][yi2 + x] = p; + yuv[0][yi2 + x + (width - x - 1)] = p; + cb = yuv[1][yi + x]; + cr = yuv[2][yi + x]; + yuv[1][yi + (width - x - 1)] = cb; + yuv[1][yi2 + x] = cb; + yuv[1][yi2 + x + (width - x - 1)] = cb; + yuv[2][yi + (width - x - 1)] = cr; + yuv[2][yi2 + x] = cr; + yuv[2][yi2 + x + (width - x - 1)] = cr; + } + } +} + +void mirrors2_apply( VJFrame *frame, int width, int height, int type) +{ + switch (type) { + case 0: + mirror_multi_dr(frame->data, width, height); + break; + case 1: + mirror_multi_ur(frame->data, width, height); + break; + case 2: + mirror_multi_u(frame->data, width, height); + break; + case 3: + mirror_multi_d(frame->data, width, height); + break; + case 4: + mirror_multi_l(frame->data, width, height); + break; + case 5: + mirror_multi_r(frame->data, width, height); + break; + } +} +void mirrors2_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mirrors2.h b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors2.h new file mode 100644 index 00000000..9660afe1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mirrors2.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MIRRORS2_H +#define MIRRORS2_H +#include +#include +#include + +vj_effect *mirrors2_init(); + +void mirrors2_apply( VJFrame *frame, int width, int height, int type); + +void mirrors2_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/morphology.c b/branches/V-1.5.3/veejay-server/libvje/effects/morphology.c new file mode 100644 index 00000000..6911c0ed --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/morphology.c @@ -0,0 +1,153 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "morphology.h" + +typedef uint8_t (*morph_func)(uint8_t *kernel, uint8_t mt[9] ); + +vj_effect *morphology_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; // threshold + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; // morpology operator (dilate,erode, ... ) + ve->limits[1][1] = 8; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; // passes + ve->defaults[0] = 140; + ve->defaults[1] = 0; + ve->defaults[2] = 0; + ve->description = "Morphology (experimental)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params,"Threshold", "Operator", "Repeat"); + return ve; +} + + +static uint8_t *binary_img; + +int morphology_malloc(int w, int h ) +{ + binary_img = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h ); + if(!binary_img) return 0; + return 1; +} + +void morphology_free(void) +{ + if(binary_img) + free(binary_img); + binary_img = NULL; +} + +static uint8_t _dilate_kernel3x3( uint8_t *kernel, uint8_t img[9]) +{ + register int x; + /* consider all background pixels (0) in input image */ + for(x = 0; x < 9; x ++ ) + if((kernel[x] * img[x]) > 0 ) + return 235; + return 16; +} + + +static uint8_t _erode_kernel3x3( uint8_t *kernel, uint8_t img[9]) +{ + register int x; + /* consider all background pixels (0) in input image */ + for(x = 0; x < 9; x ++ ) + if(kernel[x] && img[x] == 0 ) + return 16; + return 235; +} + +morph_func _morphology_function(int i) +{ + if( i == 0 ) + return _dilate_kernel3x3; + return _erode_kernel3x3; +} + + +void morphology_apply( VJFrame *frame, int width, int height, int threshold, int type, int passes ) +{ + unsigned int i,x,y; + int len = (width * height); + int c = 0,t=0,k=0; + int uv_len = frame->uv_len; + uint8_t pixel; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t kernels[8][9] ={ + { 1,1,1, 1,1,1 ,1,1,1 },//0 + { 0,1,0, 1,1,1, 0,1,0 },//1 + { 0,0,0, 1,1,1, 0,0,0 },//2 + { 0,1,0, 0,1,0, 0,1,0 },//3 + { 0,0,1, 0,1,0, 1,0,0 },//4 + { 1,0,0, 0,1,0, 0,0,1 }, + { 1,1,1, 0,0,0, 0,0,0 }, + { 0,0,0, 0,0,0, 1,1,1 } + }; + + morph_func p = _morphology_function(passes); + + /* threshold image --> binary img + 0 = bg + 255 = fg + */ + for( i = 0; i < len; i ++ ) + { + binary_img[i] = ( Y[i] < threshold ? 0: 0xff ); + t++; + } + + veejay_memset( Cb, 128, uv_len ); + veejay_memset( Cr, 128, uv_len ); + + len -= width; + + /* compute dilation of binary image with kernel */ + for(y = width; y < len; y += width ) + { + for(x = 1; x < width-1; x ++) + { + if(binary_img[x+y] == 0) + { + uint8_t mt[9] = { + binary_img[x-1+y-width], binary_img[x+y-width], binary_img[x+1+y-width], + binary_img[x-1+y], binary_img[x+y] , binary_img[x+1+y], + binary_img[x-1+y+width], binary_img[x+y+width], binary_img[x+1+y+width] + }; + Y[x+y] = p( kernels[type], mt ); + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/morphology.h b/branches/V-1.5.3/veejay-server/libvje/effects/morphology.h new file mode 100644 index 00000000..46d00fb7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/morphology.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MORPHOLOGY_H +#define MORPHOLOGY_H +#include +#include +#include + +vj_effect *morphology_init(int w, int h); +void morphology_apply( VJFrame *frame, int width, int height, int t, int val, int n); +int morphology_malloc(int w, int h); +void morphology_free(void); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/motionblur.c b/branches/V-1.5.3/veejay-server/libvje/effects/motionblur.c new file mode 100644 index 00000000..3e039d66 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/motionblur.c @@ -0,0 +1,111 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "motionblur.h" +#include + +static uint8_t *previous_frame[3]; +vj_effect *motionblur_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 15; + ve->limits[0][0] = 0; + ve->limits[1][0] = 1000; /* time in frames */ + ve->description = "Motion blur"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Frames" ); + return ve; +} + +int motionblur_malloc(int width, int height) +{ + previous_frame[0] = (uint8_t*) vj_yuvalloc( width , height ); + if(!previous_frame[0]) return 0; + previous_frame[1] = previous_frame[0] + (width * height); + previous_frame[2] = previous_frame[1] + (width * height); + return 1; +} + +void motionblur_free() { + if(previous_frame[0]) + free(previous_frame[0]); + previous_frame[0] = NULL; + previous_frame[1] = NULL; + previous_frame[2] = NULL; +} + + +static int n_motion_frames = 0; +void motionblur_apply( VJFrame *frame, int width, int height, int n) { + const int len = width * height; + const int uv_len = frame->uv_len; + + unsigned int i; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + + if(n_motion_frames > 0) { + + for(i=0; i < len; i++) { + Y[i] = (Y[i] + previous_frame[0][i])>>1; + previous_frame[0][i] = Y[i]; + } + + + for(i=0; i < uv_len; i++) { + Cb[i] = (Cb[i] + previous_frame[1][i])>>1; + Cr[i] = (Cr[i] + previous_frame[2][i])>>1; + previous_frame[1][i] = Cb[i]; + previous_frame[2][i] = Cr[i]; + } + + } + else + { + /* just copy to previous */ + veejay_memcpy( previous_frame[0], Y, len ); + veejay_memcpy( previous_frame[1], Cb, uv_len); + veejay_memcpy( previous_frame[2], Cr, uv_len); + + } + + n_motion_frames ++; + + if(n_motion_frames >= n ) { + n_motion_frames = 0; + + veejay_memset( previous_frame[0], 0, (width*height)); + veejay_memset( previous_frame[1], 0, uv_len); + veejay_memset( previous_frame[2], 0, uv_len); + + } + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/motionblur.h b/branches/V-1.5.3/veejay-server/libvje/effects/motionblur.h new file mode 100644 index 00000000..b2f9b37c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/motionblur.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MOTIONBLUR_H +#define MOTIONBLUR_H +#include +#include +#include +#include + +vj_effect *motionblur_init(int w, int h); +int motionblur_malloc(int w, int h); +void motionblur_free(); +void motionblur_apply( VJFrame *frame, int width, int height, int n); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/motiondetect.c b/branches/V-1.5.3/veejay-server/libvje/effects/motiondetect.c new file mode 100644 index 00000000..6c3f7f05 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/motiondetect.c @@ -0,0 +1,25 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include "transop.h" +#include +#include + +void motiondetect_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/motionmap.c b/branches/V-1.5.3/veejay-server/libvje/effects/motionmap.c new file mode 100644 index 00000000..89d92721 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/motionmap.c @@ -0,0 +1,423 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + + This is a quite simple motion detection filter + + There are 5 parameters: + p0 = Threshold + p1 = Acitivity Maximum Level + p2 = Draw difference frame (no processing) + p3 = Ringbuffer length N + p4 = Opacity level + + This filter detects the amount of motion in a frame. It keeps an internal + buffer to average (smoothen) the acitivity levels over N frames + At each step in N , a new value is linearly interpolated which is later + pulled by other FX to override their parameter values. + To compensate for jumpy video, the frames n+1 to N are linearly interpolated + from frame n+0 to frame N automatically. + + + */ +#include +#include +#include +#include +#include +#include "motionmap.h" +#include "common.h" +#include "softblur.h" +#include "opacity.h" + +typedef int (*morph_func)(uint8_t *kernel, uint8_t mt[9] ); +#define HIS_DEFAULT 2 +#define HIS_LEN (8*25) +#define ACT_TOP 4000 +#define MAXCAPBUF 55 +vj_effect *motionmap_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; // motionmap + ve->limits[1][0] = 255; + ve->limits[0][1] = 50; // reverse + ve->limits[1][1] = 10000; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + ve->limits[0][4] = 0; // buffer + ve->limits[1][4] = 255; + ve->limits[0][3] = HIS_DEFAULT; + ve->limits[1][3] = HIS_LEN; + ve->defaults[0] = 40; + ve->defaults[1] = ACT_TOP; + ve->defaults[2] = 1; + ve->defaults[3] = HIS_DEFAULT; + ve->defaults[4] = 0; + ve->description = "Motion Mapping"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->n_out = 2; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Reverse","Draw","History" ,"Capture length"); + return ve; +} + +static uint8_t *binary_img = NULL; +static uint8_t *original_img = NULL; +static uint8_t *previous_img = NULL; +static uint32_t histogram_[HIS_LEN]; +static uint8_t *large_buf = NULL; +static uint32_t nframe_ =0; +static uint32_t activity_total_ = 0; +static uint32_t max_d = ACT_TOP; +static int current_his_len = HIS_DEFAULT; +static uint32_t key1_ = 0, key2_ = 0, keyv_ = 0, keyp_ = 0; +static int have_bg = 0; +static int n_captured = 0; +static int n_played = 0; +static int capturing = 0; +static int playing = 0; +static uint8_t *interpolate_buf = NULL; +static int running = 0; + +#define RUP8(num)(((num)+8)&~8) + +int motionmap_malloc(int w, int h ) +{ + binary_img = (uint8_t*) vj_malloc(sizeof(uint8_t) * RUP8(w * h * 3) ); + original_img = binary_img + RUP8(w*h); + previous_img = original_img + RUP8(w*h); + large_buf = vj_malloc(sizeof(uint8_t) * RUP8(w*h*3) * (MAXCAPBUF+1)); + if(!large_buf) + { + veejay_msg(0, "Memory allocation error for Motion Mapping. Too large: %ld bytes",(long) ((RUP8(w*h*3)*(MAXCAPBUF+1)))); + return 0; + } + interpolate_buf = vj_malloc( sizeof(uint8_t) * RUP8(w*h*3)); + veejay_msg(2, "This is 'Motion Mapping'"); + veejay_msg(2, "Add any of the following to the FX chain (if not already present)"); + veejay_msg(2, "\tBathroom Window, Displacement Mapping, Multi Mirrors, Magic Mirror, Sinoids"); + veejay_msg(2, "\tSlice Window , Smear, ChameleonTV and TimeDistort TV"); + veejay_msg(2, "Using %2.2fMb for large buffer", (RUP8(w*h*3)*(MAXCAPBUF+1))/1048576.0f); + veejay_memset( histogram_, 0, sizeof(uint32_t) * HIS_LEN ); + nframe_ = 0; + running = 0; + return 1; +} + +void motionmap_free(void) +{ + if(binary_img) + free(binary_img); + if(large_buf) + free(large_buf); + if( interpolate_buf ) + free(interpolate_buf); + have_bg = 0; + interpolate_buf = NULL; + nframe_ = 0; + running = 0; + keyv_ = 0; + keyp_ = 0; + binary_img = NULL; +} + +#ifndef MIN +#define MIN(a,b) ( (a)>(b) ? (b) : (a) ) +#endif +#ifndef MAX +#define MAX(a,b) ( (a)>(b) ? (a) : (b) ) +#endif + +static void update_bgmask( uint8_t *dst,uint8_t *in, uint8_t *src, int len, int threshold ) +{ + int i; + unsigned int op0,op1; + for( i =0; i < len ; i ++ ) + { + if( abs(in[i] - src[i]) > threshold ) + { + dst[i] = 0xff; + //in[i] = (in[i] + src[i])>>1; + } + else + { + dst[i] = 0; + } + } +} + +uint8_t *motionmap_interpolate_buffer() +{ + return interpolate_buf; +} + +uint8_t *motionmap_bgmap() +{ + return binary_img; +} + +int motionmap_active() +{ + return running; +} + +uint32_t motionmap_activity() +{ + return keyv_; +} + +void motionmap_scale_to( int p1max, int p2max, int p1min, int p2min, int *p1val, int *p2val, int *pos, int *len ) +{ + if(nframe_ <= 1) + return; + + if( keyv_ > max_d ) + { + veejay_msg(0, "Motion rollover = %d", keyv_ % max_d ); + keyv_ = max_d; + } + + int n = ((nframe_-1) % current_his_len)+1; + + float q = 1.0f / (float) current_his_len * n; + float diff = (float) keyv_ - (float) keyp_ ; + float pu = keyp_ + (q * diff); + + float m = (float) max_d; + + if( pu > m ) + pu = m; + + + float w = 1.0 / max_d; + float pw = w * pu; + + *p1val = p1min + (int) ((p1max-p1min) * pw); + *p2val = p2min + (int) ((p2max-p2min) * pw); + *len = current_his_len; + *pos = n; +// veejay_msg(0, "%s:%s p1=%d,p2=%d, len=%d,pos=%d", +// __FILE__,__FUNCTION__,*p1val,*p2val, *len, *pos ); + +} + +void motionmap_lerp_frame( VJFrame *cur, VJFrame *prev, int N, int n ) +{ + unsigned int i; + int n1 = (( n-1) % N ) + 1; + float frac = 1.0f / (float) N * n1; + + const int len = cur->len; + uint8_t *Y0 = cur->data[0]; + uint8_t *Y1 = prev->data[0]; + uint8_t *U0 = cur->data[1]; + uint8_t *U1 = prev->data[1]; + uint8_t *V0 = cur->data[2]; + uint8_t *V1 = prev->data[2]; + + for ( i = 0; i < len ; i ++ ) + { + Y0[i] = Y1[i] + ( frac * (Y0[i] - Y1[i])); + U0[i] = U1[i] + ( frac * (U0[i] - U1[i])); + V0[i] = V1[i] + ( frac * (V0[i] - V1[i])); + } +} + + +void motionmap_store_frame( VJFrame *fx ) +{ + veejay_memcpy( interpolate_buf, fx->data[0], fx->len ); + veejay_memcpy( interpolate_buf+fx->len,fx->data[1],fx->len); + veejay_memcpy( interpolate_buf+fx->len+fx->len,fx->data[2],fx->len); +} + +void motionmap_interpolate_frame( VJFrame *fx, int N, int n ) +{ + if( n == 0 || N == 0 ) + return; + + VJFrame prev; + veejay_memcpy(&prev, fx, sizeof(VJFrame)); + prev.data[0] = interpolate_buf; + prev.data[1] = interpolate_buf + (fx->len); + prev.data[2] = interpolate_buf + (2*fx->len); + + motionmap_lerp_frame( fx, &prev, N, n ); +} + +int motionmap_prepare( uint8_t *map[3], int width, int height ) +{ + if(!previous_img) + return 0; + + veejay_memcpy( previous_img ,map[0], width *height ); + have_bg = 1; + nframe_ = 0; + running = 0; + veejay_msg(2, "Motion Mapping: Snapped background frame"); + return 1; +} + +static int stop_capture_ = 0; +static int reaction_ready_ = 0; +void motionmap_apply( VJFrame *frame, int width, int height, int threshold, int reverse, int draw, int history, int capbuf ) +{ + unsigned int i,x,y; + int len = (width * height); + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + if(!have_bg) { + veejay_msg(VEEJAY_MSG_ERROR,"Take a background snapshot first!"); + return; + } + + veejay_memcpy( original_img, frame->data[0], len ); + + softblur_apply( frame, width,height,0 ); + update_bgmask( binary_img, previous_img, frame->data[0], len , threshold); + + uint32_t sum = 0,min=0xffff,max=0; + uint64_t activity_level1 = 0; + uint64_t activity_level2 = 0; + uint64_t activity_level3 = 0; + uint64_t activity_level4 = 0; + for( i = 0; i < len; i += 4 ) + { + + activity_level1 += binary_img[i]; + activity_level2 += binary_img[i+1]; + activity_level3 += binary_img[i+2]; + activity_level4 += binary_img[i+3]; + } + uint32_t activity_level = ( (activity_level1>>8) + (activity_level2>>8) + (activity_level3>>8) + (activity_level4>>8)); + + max_d = reverse; + + current_his_len = history; + + histogram_[ (nframe_%current_his_len) ] = activity_level; + + for( i = 0; i < current_his_len; i ++ ) + { + sum += histogram_[i]; + if(histogram_[i] > max ) max = histogram_[i]; + if(histogram_[i] < min ) min = histogram_[i]; + } + if( (nframe_ % current_his_len)==0 ) + { + key1_ = min; + key2_ = max; + keyp_ = keyv_; + keyv_ = (sum > 0 ? (sum/current_his_len):0 ); + } + + if( draw ) + { + veejay_memset( Cb, 128, len ); + veejay_memset( Cr, 128, len ); + veejay_memcpy( frame->data[0], binary_img, len ); + nframe_++; + return; + } + + + if( capbuf ) + { + if(!capturing) + { + if( keyv_ > max_d ) + { + if( !reaction_ready_ ) + { + stop_capture_ = keyv_ / 5; + capturing = 1; + } + else + { + playing = 1; + } + } + } + + if( stop_capture_ && !reaction_ready_) + { + if( keyv_ < stop_capture_ || n_captured >= MAXCAPBUF ) + { + capturing = 0; + stop_capture_= 0; + reaction_ready_ =1; + } + } + } + else + { + capturing = 0; playing = 0; stop_capture_ = 0; reaction_ready_ = 0; n_captured = 0; + } + + if( capturing ) + { + uint8_t *dst[3]; + dst[0] = large_buf + ( n_captured * (len*3) ); + dst[1] = dst[0] + len; + dst[2] = dst[1] + len; + veejay_memcpy( dst[0], frame->data[0], len ); + veejay_memcpy( dst[1], frame->data[1], len ); + veejay_memcpy( dst[2], frame->data[2], len ); + n_captured ++; + if( n_captured >= MAXCAPBUF ) + { + capturing = 0; + stop_capture_ = 0; + } + } + else if (playing ) + { + uint8_t *src[3]; + src[0] = large_buf + ( n_played * (len*3)); + src[1] = src[0]+ len; + src[2] = src[1]+ len; + /* veejay_memcpy( frame->data[0], src[0], len ); + veejay_memcpy( frame->data[1], src[1], len ); + veejay_memcpy( frame->data[2], src[2], len );*/ + + VJFrame b; + veejay_memcpy(&b, frame, sizeof(VJFrame)); + b.data[0] = src[0]; b.data[1] = src[1]; b.data[2] = src[2]; + opacity_apply( frame, &b, frame->width,frame->height, capbuf ); + + + n_played ++; + if( n_played >= n_captured) + { + n_played = 0; n_captured = 0; playing = 0; capturing = 0; + reaction_ready_ = 0; + } + nframe_++; + return; + } + veejay_memcpy( frame->data[0], original_img, len ); + nframe_ ++; + running = 1; +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/motionmap.h b/branches/V-1.5.3/veejay-server/libvje/effects/motionmap.h new file mode 100644 index 00000000..b1960f7c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/motionmap.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MOTIONMAP_H +#define MOTIONMAP_H +#include +#include +#include + +vj_effect *motionmap_init(int w, int h); +void motionmap_apply( VJFrame *frame, int width, int height, int t, int n, int draw, int histo, int op); +int motionmap_malloc(int w,int h); +void motionmap_free(void); +int motionmap_prepare( uint8_t *map[3], int w, int h ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mtracer.c b/branches/V-1.5.3/veejay-server/libvje/effects/mtracer.c new file mode 100644 index 00000000..0fcc5971 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mtracer.c @@ -0,0 +1,95 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "scratcher.h" +#include "common.h" +#include "magicoverlays.h" + + +uint8_t *mtrace_buffer[3]; +static int mtrace_counter = 0; + +vj_effect *mtracer_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 30; + ve->limits[0][1] = 1; + ve->limits[1][1] = 25; + ve->defaults[0] = 150; + ve->defaults[1] = 8; + ve->description = "Magic Tracer"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Length"); + return ve; +} +// FIXME private +void mtracer_free() { + if(mtrace_buffer[0]) free(mtrace_buffer[0]); + mtrace_buffer[0] = NULL; + mtrace_buffer[1] = NULL; +} + +int mtracer_malloc(int w, int h) +{ + mtrace_buffer[0] = (uint8_t *) vj_yuvalloc(w,h ); + if(!mtrace_buffer[0]) return 0; + mtrace_buffer[1] = mtrace_buffer[0] + (w*h); + mtrace_buffer[2] = mtrace_buffer[1] + (w*h); + return 1; +} + +void mtracer_apply( VJFrame *frame, VJFrame *frame2, + int width, int height, int mode, int n) +{ + + unsigned int len = frame->len; + unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + if (mtrace_counter == 0) { + overlaymagic_apply(frame, frame2, width, height, mode,0); + veejay_memcpy(mtrace_buffer[0], Y, len); + veejay_memcpy(mtrace_buffer[1], Cb, uv_len); + veejay_memcpy(mtrace_buffer[2], Cr, uv_len); + } else { + overlaymagic_apply(frame, frame2, width, height, mode,0); + veejay_memcpy(mtrace_buffer[0], Y, len); + veejay_memcpy(mtrace_buffer[1], Cb, uv_len); + veejay_memcpy(mtrace_buffer[2], Cr, uv_len); + + } + + mtrace_counter++; + if (mtrace_counter >= n) + mtrace_counter = 0; + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/mtracer.h b/branches/V-1.5.3/veejay-server/libvje/effects/mtracer.h new file mode 100644 index 00000000..24e81f38 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/mtracer.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef MTRACER_H +#define MTRACER_H +#include +#include +#include +#include + +vj_effect *mtracer_init(int w, int h); +int mtracer_malloc(int w, int h); +void mtracer_free(); +void mtracer_apply( VJFrame *frame, VJFrame *frame2, + int width, int height, int mode, int nframes); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/negatechannel.c b/branches/V-1.5.3/veejay-server/libvje/effects/negatechannel.c new file mode 100644 index 00000000..bb056e50 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/negatechannel.c @@ -0,0 +1,185 @@ +/* + * Linux VeeJay + * + * Copyright(C)2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "negatechannel.h" + +vj_effect *negatechannel_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 2; + ve->limits[0][1] = 0; + ve->limits[1][1] = 0xff; + ve->defaults[0] = 0; + ve->defaults[1] = 0xff; + ve->description = "Negate a channel"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Y=0, Cb=1, Cr=2", "Value" ); + return ve; +} + +#ifdef HAVE_ASM_MMX +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW ) +#define HAVE_K6_2PLUS +#endif + +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif +static inline void negate_mask(uint8_t val) +{ + uint8_t mask[8] = { val,val,val,val, val,val,val,val }; +// uint64_t mask = 0xffffffffffffffffLL; + uint8_t *m = (uint8_t*)&mask; + + __asm __volatile( + "movq (%0), %%mm4\n\t" + :: "r" (m) ); +} + +static inline void mmx_negate( uint8_t *dst, uint8_t *in ) +{ + __asm __volatile( + "movq (%0), %%mm0\n\t" + "movq %%mm4, %%mm1\n\t" + "psubb %%mm0, %%mm1\n\t" + "movq %%mm1, (%1)\n\t" + :: "r" (in) , "r" (dst) + ); +} + +#endif + +void negatechannel_apply( VJFrame *frame, int width, int height, int chan, int val) +{ + int i; + int len = (width * height); + int uv_len = frame->uv_len; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + +#ifndef HAVE_ASM_MMX + switch( chan ) { + case 0: + for (i = 0; i < len; i++) { + *(Y) = val - *(Y); + *(Y)++; + } + break; + case 1: + + for (i = 0; i < uv_len; i++) { + *(Cb) = val - *(Cb); + *(Cb)++; + } + break; + case 2: + for (i = 0; i < uv_len; i++) { + *(Cr) = val - *(Cr); + *(Cr)++; + } + break; + } + +#else + + int left = len % 8; + int work= len >> 3; + + negate_mask(val); + + switch( chan ) { + case 0: + for( i = 0; i < work ; i ++ ) + { + mmx_negate( Y, Y ); + Y += 8; + } + + if (left ) + { + for( i = 0; i < left; i ++ ) + { + *(Y) = val - *(Y); + *(Y)++; + } + } + break; + case 1: + + work = uv_len >> 3; + left = uv_len % 8; + for( i = 0; i < work ; i ++ ) + { + mmx_negate( Cb, Cb ); + Cr += 8; + } + + if(left ) + { + for( i = 0; i < left; i ++ ) + { + *(Cb) = val - *(Cb); + *(Cb)++; + } + } + break; + case 2: + work = uv_len >> 3; + left = uv_len % 8; + for( i = 0; i < work ; i ++ ) + { + mmx_negate( Cr, Cr ); + Cr += 8; + } + + if(left ) + { + for( i = 0; i < left; i ++ ) + { + *(Cr) = val - *(Cr); + *(Cr)++; + } + } + break; + } + + __asm__ __volatile__ ( _EMMS:::"memory"); + +#endif +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/negatechannel.h b/branches/V-1.5.3/veejay-server/libvje/effects/negatechannel.h new file mode 100644 index 00000000..d0446dd9 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/negatechannel.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef CHANNELNEGATION_H +#define CHANNELNEGATION_H +#include +#include +#include + +vj_effect *negatechannel_init(int w, int h); +void negatechannel_apply( VJFrame *frame, int width, int height,int chan, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/negation.c b/branches/V-1.5.3/veejay-server/libvje/effects/negation.c new file mode 100644 index 00000000..7a34a325 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/negation.c @@ -0,0 +1,151 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "negation.h" +#include +vj_effect *negation_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->defaults[0] = 3;// 255; + ve->description = "Negation"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value" ); + return ve; +} + +#ifdef HAVE_ASM_MMX +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW ) +#define HAVE_K6_2PLUS +#endif + +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif +static inline void negate_mask(uint8_t val) +{ + uint8_t mask[8] = { val,val,val,val, val,val,val,val }; +// uint64_t mask = 0xffffffffffffffffLL; + uint8_t *m = (uint8_t*)&mask; + + __asm __volatile( + "movq (%0), %%mm4\n\t" + :: "r" (m) ); +} + +static inline void mmx_negate( uint8_t *dst, uint8_t *in ) +{ + __asm __volatile( + "movq (%0), %%mm0\n\t" + "movq %%mm4, %%mm1\n\t" + "psubb %%mm0, %%mm1\n\t" + "movq %%mm1, (%1)\n\t" + :: "r" (in) , "r" (dst) + ); +} + +#endif + +void negation_apply( VJFrame *frame, int width, int height, int val) +{ + int i; + int len = (width * height); + int uv_len = frame->uv_len; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + +#ifndef HAVE_ASM_MMX + for (i = 0; i < len; i++) { + *(Y) = val - *(Y); + *(Y)++; + } + + for (i = 0; i < uv_len; i++) { + *(Cb) = val - *(Cb); + *(Cb)++; + *(Cr) = val - *(Cr); + *(Cr)++; + } +#else + + int left = len % 8; + int work= len >> 3; + + negate_mask(val); + + for( i = 0; i < work ; i ++ ) + { + mmx_negate( Y, Y ); + Y += 8; + } + + if (left ) + { + for( i = 0; i < left; i ++ ) + { + *(Y) = val - *(Y); + *(Y)++; + } + } + + work = uv_len >> 3; + left = uv_len % 8; + for( i = 0; i < work ; i ++ ) + { + mmx_negate( Cb, Cb ); + mmx_negate( Cr, Cr ); + Cb += 8; + Cr += 8; + } + + if(left ) + { + for( i = 0; i < left; i ++ ) + { + *(Cb) = val - *(Cb); + *(Cb)++; + *(Cr) = val - *(Cr); + *(Cr)++; + } + } + + __asm__ __volatile__ ( _EMMS:::"memory"); + +#endif +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/negation.h b/branches/V-1.5.3/veejay-server/libvje/effects/negation.h new file mode 100644 index 00000000..431699e3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/negation.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NEGATION_H +#define NEGATION_H +#include +#include +#include + +vj_effect *negation_init(int w, int h); +void negation_apply( VJFrame *frame, int width, int height, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours.c b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours.c new file mode 100644 index 00000000..e1e5d697 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours.c @@ -0,0 +1,284 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "neighbours.h" + +vj_effect *neighbours_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 16; /* brush size (shape is rectangle)*/ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; /* smoothness */ + ve->limits[0][2] = 0; /* luma only / include chroma */ + ve->limits[1][2] = 1; + ve->defaults[0] = 4; + ve->defaults[1] = 4; + ve->defaults[2] = 0; + ve->description = "ZArtistic Filter (Oilpainting, acc. add )"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Brush size", "Smoothness", "Mode (Luma/Chroma)" ); + + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; + + +int neighbours_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h * 2); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = tmp_buf[0] + (w*h); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h *2); + if(!chromacity[0]) return 0; + chromacity[1] = chromacity[0] + (w*h); + return 1; +} + +void neighbours_free(void) +{ + if(tmp_buf[0]) + free(tmp_buf[0]); + if(chromacity[0]) + free(chromacity[0]); + tmp_buf[0] = NULL; + tmp_buf[1] = NULL; + chromacity[0] = NULL; + chromacity[1] = NULL; +} + +static inline uint8_t evaluate_pixel( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image /* image data */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h-1; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + for( i = y0; i < y1; i ++ ) + { + for( j = x0; j < x1; j ++ ) + { + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ i * w + j]; + } + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[ y * w + x]; + + return( (uint8_t) ( y_map[ peak_index] / peak_value )); +} + +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + + +static inline pixel_t evaluate_pixel_c( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h-1; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size * brush_size and counts + many loads and stores. */ + for( i = y0; i < y1; i ++ ) + { + for( j = x0; j < x1; j ++ ) + { + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ i * w + j]; + cb_map[ brightness ] += image_cb[ i * w + j ]; + cr_map[ brightness ] += image_cr[ i * w + j ]; + } + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + + return val; + +} + + +void neighbours_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2 + ); + } + } + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_c( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1] + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours.h b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours.h new file mode 100644 index 00000000..3c1e1ff7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NEIGHBOURS_H +#define NEIGHBOURS_H +#include +#include +#include + +vj_effect *neighbours_init(int w, int h); +int neighbours_malloc(int w, int h); +void neighbours_free(void); +void neighbours_apply( VJFrame *frame, int width, int height, int brush_size, int level,int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours2.c b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours2.c new file mode 100644 index 00000000..ce9061ff --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours2.c @@ -0,0 +1,285 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "neighbours2.h" + +vj_effect *neighbours2_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 16; /* brush size (shape is rectangle)*/ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; /* smoothness */ + ve->limits[0][2] = 0; /* luma only / include chroma */ + ve->limits[1][2] = 1; + ve->defaults[0] = 4; + ve->defaults[1] = 15; + ve->defaults[2] = 0; + ve->description = "ZArtistic Filter (Oilpaint, acc. avg)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Brush size", "Smoothness", "Mode (Luma/Chroma)" ); + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; + + +int neighbours2_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h * 2); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = tmp_buf[0] + (w*h); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h *2); + if(!chromacity[0]) return 0; + chromacity[1] = chromacity[0] + (w*h); + return 1; +} + +void neighbours2_free(void) +{ + if(tmp_buf[0]) + free(tmp_buf[0]); + if(chromacity[0]) + free(chromacity[0]); + tmp_buf[0] = NULL; + tmp_buf[1] = NULL; + chromacity[0] = NULL; + chromacity[1] = NULL; +} + +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h-1; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size * brush_size and counts + many loads and stores. */ + for( i = y0; i < y1; i ++ ) + { + for( j = x0; j < x1; j ++ ) + { + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] = (image[ i * w + j] + y_map[brightness])>>1; + cb_map[ brightness ] = (cb_map[brightness] + image_cb[ i * w + j ])>>1; + cr_map[ brightness ] = (cr_map[brightness] + image_cr[ i * w + j ])>>1; + } + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + val.y = y_map[peak_index]; + val.u = cb_map[peak_index]; + val.v = cr_map[peak_index]; + + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image /* image data */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 > h ) y1 = h; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + for( i = y0; i < y1; i ++ ) + { + for( j = x0; j < x1; j ++ ) + { + // average while adding + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] = (y_map[brightness] + image[ i * w + j]) / 2; + + } + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[y*w+x]; + + return( (uint8_t) ( y_map[ peak_index] )); +} + +void neighbours2_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2 + ); + } + } + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1] + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours2.h b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours2.h new file mode 100644 index 00000000..04b49426 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours2.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NEIGHBOURS2_H +#define NEIGHBOURS2_H +#include +#include +#include + +vj_effect *neighbours2_init(int w, int h); +int neighbours2_malloc(int w, int h); +void neighbours2_free(void); +void neighbours2_apply( VJFrame *frame, int width, int height, int brush_size, int level,int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours3.c b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours3.c new file mode 100644 index 00000000..ba294acd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours3.c @@ -0,0 +1,290 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include +#include +#include +#include +#include "neighbours3.h" + +vj_effect *neighbours3_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 32; /* line size */ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; /* smoothness */ + ve->limits[0][2] = 0; /* luma only / include chroma */ + ve->limits[1][2] = 1; + ve->defaults[0] = 9; + ve->defaults[1] = 7; + ve->defaults[2] = 1; + ve->description = "ZArtistic Filter (Horizontal strokes)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Line size", "Smoothness", "Mode (Luma/Chroma)" ); + + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; + + +int neighbours3_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h * 2); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = tmp_buf[0] + (w*h); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h *2); + if(!chromacity[0]) return 0; + chromacity[1] = chromacity[0] + (w*h); + return 1; +} + +void neighbours3_free(void) +{ + if(tmp_buf[0]) + free(tmp_buf[0]); + if(chromacity[0]) + free(chromacity[0]); + tmp_buf[0] = NULL; + tmp_buf[1] = NULL; + chromacity[0] = NULL; + chromacity[1] = NULL; +} +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h-1; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size and counts + many loads and stores. */ + i = y; + for( j = x0; j < x1; j ++ ) + { + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ i * w + j]; + cb_map[ brightness ] += image_cb[ i * w + j ]; + cr_map[ brightness ] += image_cr[ i * w + j ]; + } + + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + if( peak_value > 0 ) + { + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + } + else + { + val.y = image[y * w + x]; + val.u = image_cb[y * w + x]; + val.v = image_cr[y * w + x]; + } + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image /* image data */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h-1; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + i = y; + for( j = x0; j < x1; j ++ ) + { + // average while adding + brightness = premul[ i * w + j]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ i * w + j]; + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[ y * w + x]; + + return( (uint8_t) ( y_map[ peak_index] / peak_value )); +} + +void neighbours3_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2 + ); + } + } + veejay_memset( frame->data[1], 128, frame->len ); + veejay_memset( frame->data[2], 128, frame->len ); + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1] + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours3.h b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours3.h new file mode 100644 index 00000000..ae36db72 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours3.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NEIGHBOURS3_H +#define NEIGHBOURS3_H +#include +#include +#include + +vj_effect *neighbours3_init(int w, int h); +int neighbours3_malloc(int w, int h); +void neighbours3_free(void); +void neighbours3_apply( VJFrame *frame, int width, int height, int brush_size, int level,int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours4.c b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours4.c new file mode 100644 index 00000000..edbbcf41 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours4.c @@ -0,0 +1,337 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "neighbours4.h" + +vj_effect *neighbours4_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 32; /* radius */ + ve->limits[0][1] = 1; + ve->limits[1][1] = 200; /* distance from center */ + ve->limits[0][2] = 1; + ve->limits[1][2] = 255; /* smoothness */ + ve->limits[0][3] = 0; /* luma only / include chroma */ + ve->limits[1][3] = 1; + ve->defaults[0] = 4; + ve->defaults[1] = 24; + ve->defaults[2] = 8; + ve->defaults[3] = 1; + ve->description = "ZArtistic Filter (Round Brush)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Radius", "Distance from center","Smoothness", "Mode (Luma/Chroma)" ); + + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + +typedef struct +{ + double x; + double y; +} relpoint_t; + +static relpoint_t points[2048]; + + + +int neighbours4_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h * 2); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = tmp_buf[0] + (w*h); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h *2); + if(!chromacity[0]) return 0; + chromacity[1] = chromacity[0] + (w*h); + int i; + for(i = 0; i < w; i ++ ) + { + points[i].x = 0.0; + points[i].y = 0.0; + } + return 1; +} + +void neighbours4_free(void) +{ + if(tmp_buf[0]) + free(tmp_buf[0]); + if(chromacity[0]) + free(chromacity[0]); + tmp_buf[0] = NULL; + tmp_buf[1] = NULL; + chromacity[0] = NULL; + chromacity[1] = NULL; +} + +static void create_circle( double radius, int depth, int w ) +{ + double t = 0.0; + int index = 0; + double theta = ((double)w/depth); + while( index <= depth) + { + double r = (t / 180.0) * M_PI; + points[index].x = cos(r) * radius; + points[index].y = sin(r) * radius; + t += theta; + index++; + } +} + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr, + const relpoint_t *points /* relative coordinate map */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + const int max_ = (int) ( 0xff * intensity ); + int dx,dy; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size and counts + many loads and stores. */ + i = y; + + /* loop over perimter of circle (!) */ + for( i = 0; i < brush_size; i ++) + { + dx = points[i].x + x; + dy = points[i].y + y; + if(dx < 0) dx = 0; else if (dx >= w) dx = w-1; + if(dy < 0) dy = 0; else if (dy >= h) dy = h-1; + + brightness = premul[ dy * w + dx]; + pixel_histogram[ brightness ] ++; + + y_map[ brightness ] += image[ dy * w + dx]; + cb_map[ brightness ] += image_cb[ dy * w + dx ]; + cr_map[ brightness ] += image_cr[ dy * w + dx ]; + } + + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + if(peak_value > 0) + { + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + } + else + { + val.y = image[y * w + x]; + val.u = image_cb[y * w + x]; + val.v = image_cr[y * w + x]; + } + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const relpoint_t *points /* relative coordinate map*/ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + int dx,dy; + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h-1; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + // points in circle + for( i = 0; i < brush_size; i ++) + { + dx = points[i].x + x; + dy = points[i].y + y; + if(dx < 0) dx = 0; else if (dx > w) dx = w; + if(dy < 0) dy = 0; else if (dy >= h) dy = h-1; + + brightness = premul[ dy * w + dx]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ dy * w + dx]; + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[ y * w + x]; + + return( (uint8_t) ( y_map[ peak_index] / peak_value )); +} + +void neighbours4_apply( VJFrame *frame, int width, int height, int radius, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + double r = (double)radius; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + create_circle( r, brush_size,width ); + + relpoint_t *p_points = &points[0]; + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + p_points + ); + } + } + veejay_memset( frame->data[1], 128, frame->len ); + veejay_memset( frame->data[2], 128, frame->len ); + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1], + p_points + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours4.h b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours4.h new file mode 100644 index 00000000..3c28115e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours4.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NEIGHBOURS4_H +#define NEIGHBOURS4_H +#include +#include +#include + +vj_effect *neighbours4_init(int w, int h); +int neighbours4_malloc(int w, int h); +void neighbours4_free(void); +void neighbours4_apply( VJFrame *frame, int width, int height, int radius,int brush_size, int level,int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours5.c b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours5.c new file mode 100644 index 00000000..da708550 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours5.c @@ -0,0 +1,290 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "neighbours5.h" + +vj_effect *neighbours5_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 32; /* line size */ + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; /* smoothness */ + ve->limits[0][2] = 0; /* luma only / include chroma */ + ve->limits[1][2] = 1; + ve->defaults[0] = 6; + ve->defaults[1] = 5; + ve->defaults[2] = 1; + ve->description = "ZArtistic Filter (Vertical strokes)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Stroke size", "Smoothness", "Mode (Luma/Chroma)" ); + + return ve; +} + +static int pixel_histogram[256]; +static int y_map[256]; +static int cb_map[256]; +static int cr_map[256]; +static uint8_t *tmp_buf[2]; +static uint8_t *chromacity[2]; + + +int neighbours5_malloc(int w, int h ) +{ + tmp_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h * 2); + if(!tmp_buf[0] ) return 0; + tmp_buf[1] = tmp_buf[0] + (w*h); + chromacity[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h *2); + if(!chromacity[0]) return 0; + chromacity[1] = chromacity[0] + (w*h); + return 1; +} + +void neighbours5_free(void) +{ + if(tmp_buf[0]) + free(tmp_buf[0]); + if(chromacity[0]) + free(chromacity[0]); + tmp_buf[0] = NULL; + tmp_buf[1] = NULL; + chromacity[0] = NULL; + chromacity[1] = NULL; +} + +typedef struct +{ + uint8_t y; + uint8_t u; + uint8_t v; +} pixel_t; + +static inline pixel_t evaluate_pixel_bc( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image, /* image data */ + const uint8_t *image_cb, + const uint8_t *image_cr +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h-1; + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + cb_map[i] = 0; + cr_map[i] = 0; + } + + /* fill histogram, cummulative add of luma values */ + /* this innerloop is executed w * h * brush_size and counts + many loads and stores. + vertical passing + */ + for( j = y0; j < y1; j ++ ) + { + brightness = premul[ j * w + x]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += (image[ j * w + x]); + cb_map[ brightness ] += (image_cb[ j * w + x ]); + cr_map[ brightness ] += (image_cr[ j * w + x ]); + } + + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + pixel_t val; + + if(peak_value > 0) + { + val.y = y_map[peak_index] / peak_value; + val.u = cb_map[peak_index] / peak_value; + val.v = cr_map[peak_index] / peak_value; + } + else + { + val.y = image[ y * w + x]; + val.u = image_cb[ y * w + x]; + val.v = image_cr[ y * w + x]; + } + return val; + +} + + +static inline uint8_t evaluate_pixel_b( + int x, int y, /* center pixel */ + const int brush_size, /* brush size (works like equal sized rectangle) */ + const double intensity, /* Luma value * scaling factor */ + const int w, /* width of image */ + const int h, /* height of image */ + const uint8_t *premul, /* map data */ + const uint8_t *image /* image data */ +) +{ + unsigned int brightness; /* scaled brightnes */ + int peak_value = 0; + int peak_index = 0; + int i,j; + int x0 = x - brush_size; + int x1 = x + brush_size; + int y0 = y - brush_size; + int y1 = y + brush_size; + const int max_ = (int) ( 0xff * intensity ); + + if( y0 < 0 ) y0 = 0; + if( y1 >= h ) y1 = h - 1; + if( x0 < 0 ) x0 = 0; + if( x1 > w ) x1 = w; + + /* clear histogram and y_map */ + for( i =0 ; i < max_; i ++ ) + { + pixel_histogram[i] = 0; + y_map[i] = 0; + } + + for( j = y0; j < y1; j ++ ) + { + // average while adding + brightness = premul[ j * w + x]; + pixel_histogram[ brightness ] ++; + y_map[ brightness ] += image[ j * w + x]; + } + + /* find most occuring value */ + for( i = 0; i < max_ ; i ++ ) + { + if( pixel_histogram[i] >= peak_value ) + { + peak_value = pixel_histogram[i]; + peak_index = i; + } + } + if( peak_value < 16) + return image[ y * w + x]; + + return( (uint8_t) ( y_map[ peak_index] / peak_value )); +} + +void neighbours5_apply( VJFrame *frame, int width, int height, int brush_size, int intensity_level, int mode ) +{ + int x,y; + const double intensity = intensity_level / 255.0; + uint8_t *Y = tmp_buf[0]; + uint8_t *Y2 = tmp_buf[1]; + uint8_t *dstY = frame->data[0]; + uint8_t *dstCb = frame->data[1]; + uint8_t *dstCr = frame->data[2]; + // keep luma + veejay_memcpy( Y2, frame->data[0], frame->len ); + + if(mode) + { + veejay_memcpy( chromacity[0], frame->data[1], frame->len ); + veejay_memcpy( chromacity[1], frame->data[2], frame->len ); + } + + // premultiply intensity map + for( y = 0 ; y < frame->len ; y ++ ) + Y[y] = (uint8_t) ( (double)Y2[y] * intensity ); + + if(!mode) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + *(dstY)++ = evaluate_pixel_b( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2 + ); + } + } + veejay_memset( frame->data[1], 128, frame->len ); + veejay_memset( frame->data[2], 128, frame->len ); + } + else + { + pixel_t tmp; + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < width; x ++ ) + { + tmp = evaluate_pixel_bc( + x,y, + brush_size, + intensity, + width, + height, + Y, + Y2, + chromacity[0], + chromacity[1] + ); + *(dstY++) = tmp.y; + *(dstCb++) = tmp.u; + *(dstCr++) = tmp.v; + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/neighbours5.h b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours5.h new file mode 100644 index 00000000..bf3f92c6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/neighbours5.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NEIGHBOURS5_H +#define NEIGHBOURS5_H +#include +#include +#include + +vj_effect *neighbours5_init(int w, int h); +int neighbours5_malloc(int w, int h); +void neighbours5_free(void); +void neighbours5_apply( VJFrame *frame, int width, int height, int radius,int brush_size, int level); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/nervous.c b/branches/V-1.5.3/veejay-server/libvje/effects/nervous.c new file mode 100644 index 00000000..41596775 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/nervous.c @@ -0,0 +1,120 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +/* + Nervous is loosly based on Kentaro's Nervous effect, found + in EffecTV ( http://effectv.sf.net ). + +*/ +#include +#include +#include +#include +#include +#include "nervous.h" + +#define N_MAX 25 + +static uint8_t *nervous_buf[3]; // huge buffer +static int frames_elapsed; + +vj_effect *nervous_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = N_MAX; + ve->defaults[0] = N_MAX; + ve->description = "Nervous"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Buffer length"); + return ve; +} + +int nervous_malloc(int w, int h ) +{ + nervous_buf[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * w * h * N_MAX * 3); + + if(!nervous_buf[0]) return 0; + nervous_buf[1] = nervous_buf[0] + (w*h*N_MAX); + nervous_buf[2] = nervous_buf[1] + (w*h*N_MAX); + frames_elapsed = 0; + + veejay_memset( nervous_buf[0], 0, (w*h) * N_MAX ); + veejay_memset( nervous_buf[1], 128, (w*h) * N_MAX ); + veejay_memset( nervous_buf[2], 128, (w*h) * N_MAX ); + + return 1; +} + +void nervous_free(void) +{ + if( nervous_buf[0] ) free(nervous_buf[0]); + nervous_buf[0] = NULL; + nervous_buf[1] = NULL; + nervous_buf[2] = NULL; +} + + +void nervous_apply( VJFrame *frame, int width, int height, int delay) +{ + unsigned int i; + int len = (width * height); + int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *NY = nervous_buf[0] + (len * frames_elapsed ); + uint8_t *NCb= nervous_buf[1] + (uv_len * frames_elapsed ); + uint8_t *NCr= nervous_buf[2] + (uv_len * frames_elapsed ); + + // copy original into nervous buf + veejay_memcpy( NY, Y, len ); + veejay_memcpy( NCb, Cb, uv_len ); + veejay_memcpy( NCr, Cr, uv_len ); + + if(frames_elapsed > 0) + { + // take a random frame + unsigned int index = (unsigned int) ((double)frames_elapsed * + rand() / (RAND_MAX+1.0) ); + // setup pointers + uint8_t *sY = nervous_buf[0] + (len * index); + uint8_t *sCb = nervous_buf[1] + (uv_len * index); + uint8_t *sCr = nervous_buf[2] + (uv_len * index); + // copy it to dst + veejay_memcpy( Y, sY, len ); + veejay_memcpy( Cb, sCb, uv_len ); + veejay_memcpy( Cr, sCr, uv_len ); + } + + frames_elapsed ++; + + if( frames_elapsed == N_MAX ) + frames_elapsed = 0; + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/nervous.h b/branches/V-1.5.3/veejay-server/libvje/effects/nervous.h new file mode 100644 index 00000000..e1e741cc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/nervous.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NERVOUS_H +#define NERVOUS_H +#include +#include +#include + +vj_effect *nervous_init(int w, int h); +int nervous_malloc(int w, int h); +void nervous_free(void); +void nervous_apply(VJFrame *Frame, int width, int height,int delay); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/noiseadd.c b/branches/V-1.5.3/veejay-server/libvje/effects/noiseadd.c new file mode 100644 index 00000000..0b0bc0fd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/noiseadd.c @@ -0,0 +1,199 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "noiseadd.h" + +static uint8_t *Yb_frame; + +vj_effect *noiseadd_init(int width , int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 0; /* type */ + ve->defaults[1] = 1000; + ve->limits[0][0] = 0; + ve->limits[1][0] = 2; + ve->limits[0][1] = 1; + ve->limits[1][1] = 5000; + ve->description = "Amplify low noise"; + + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Amplification"); + return ve; +} +// FIXME private + +int noiseadd_malloc(int width, int height) +{ + + Yb_frame = (uint8_t *) vj_calloc( sizeof(uint8_t) * width * height); + if(!Yb_frame) return 0; + return 1; +} + +void noiseadd_free() { + if(Yb_frame) free(Yb_frame); + Yb_frame = NULL; +} + +void noiseblur1x3_maskapply(uint8_t *src[3], int width, int height, int coeef ) { + + int r, c; + double k = (coeef/100.0); + uint8_t d; + + const int len = (width*height); + + for (r = 0; r < len; r += width) { + for (c = 1; c < width-1; c++) { + Yb_frame[c + r] = (src[0][r + c - 1] + + src[0][r + c] + + src[0][r + c + 1] + ) / 3; + } + } + + for(c=0; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + d = (Yb_frame[c] - src[0][c]) * k; + src[0][c] = d; + } + +} +void noiseblur3x3_maskapply(uint8_t *src[3], int width, int height, int coeef ) { + + int r, c; + const double k = (coeef/1000.0); + uint8_t d; + + const int len = (width*height)-width; + + + for (r = width; r < len; r += width) { + for (c = 1; c < width-1; c++) { + Yb_frame[c + r] = (src[0][r - width + c - 1] + + src[0][r - width + c] + + src[0][r - width + c + 1] + + src[0][r + width + c - 1] + + src[0][r + width + c] + + src[0][r + width + c + 1] + + src[0][r + c] + + src[0][r + c + 1] + + src[0][r + c - 1] + ) / 9; + } + } + + for(c=width; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + d = (Yb_frame[c] - src[0][c]) * k; + src[0][c] = d; + } + +} + +void noiseneg3x3_maskapply(uint8_t *src[3], int width, int height, int coeef ) { + + int r, c; + const double k = (coeef/1000.0); + uint8_t d; + + int len = (width*height)-width; + + + for (r = width; r < len; r += width) { + for (c = 1; c < width-1; c++) { + Yb_frame[c + r] = 255 - ((src[0][r - width + c - 1] + + src[0][r - width + c] + + src[0][r - width + c + 1] + + src[0][r + width + c - 1] + + src[0][r + width + c] + + src[0][r + width + c + 1] + + src[0][r + c] + + src[0][r + c + 1] + + src[0][r + c - 1] + )) / 9; + } + } + + for(c=width; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + d = (src[0][c] - Yb_frame[c]) * k; + src[0][c] = d; + } + +} + +void noiseadd3x3_maskapply(uint8_t *src[3], int width, int height, int coeef ) { + + int r, c; + const double k = (coeef/1000.0); + uint8_t d; + + const int len = (width*height)-width; + + + for (r = width; r < len; r += width) { + for (c = 1; c < width-1; c++) { + Yb_frame[c + r] = (src[0][r - width + c - 1] + + src[0][r - width + c] + + src[0][r - width + c + 1] + + src[0][r + width + c - 1] + + src[0][r + width + c] + + src[0][r + width + c + 1] + + src[0][r + c] + + src[0][r + c + 1] + + src[0][r + c - 1] + ) / 9; + } + } + + for(c=width; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + d = (src[0][c] - Yb_frame[c]) * k; + src[0][c] = d; + } + +} + + +void noiseadd_apply( VJFrame *frame, int width, int height, int type, int coeef) { + + switch(type) { + case 0: + noiseblur1x3_maskapply(frame->data,width,height,coeef); break; + case 1: + noiseblur3x3_maskapply(frame->data,width,height,coeef); break; + case 2: + noiseneg3x3_maskapply(frame->data,width,height,coeef); break; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/noiseadd.h b/branches/V-1.5.3/veejay-server/libvje/effects/noiseadd.h new file mode 100644 index 00000000..f5554017 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/noiseadd.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NOISEADD_H +#define NOISEADD_H +#include +#include +#include + +vj_effect *noiseadd_init(int w, int h); +void noiseadd_free(); +int noiseadd_malloc(int w, int h); +void noiseadd_apply( VJFrame *frame, int w, int h, int t, int n); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/noisepencil.c b/branches/V-1.5.3/veejay-server/libvje/effects/noisepencil.c new file mode 100644 index 00000000..4a9997bc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/noisepencil.c @@ -0,0 +1,270 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include +#include +#include +#include "noisepencil.h" + +static uint8_t *Yb_frame; + +vj_effect *noisepencil_init(int width , int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 0; /* type */ + ve->defaults[1] = 1000; + ve->defaults[2] = 68; + ve->defaults[3] = 110; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 3; + ve->limits[0][1] = 1; + ve->limits[1][1] = 10000; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + ve->param_description = vje_build_param_list(ve->num_params, "Mode", "Amplification", "Min Threshold", "Max Threshold"); + ve->description = "Noise Pencil"; + + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 0; + return ve; +} + +//FIXME private +int noisepencil_malloc(int width,int height) +{ + Yb_frame = (uint8_t *) vj_calloc( sizeof(uint8_t) * width * height); + if(!Yb_frame) return 0; + return 1; +} + +void noisepencil_free() { + if(Yb_frame) free(Yb_frame); + Yb_frame = NULL; +} + +void noisepencil_1_apply(uint8_t *src[3], int width, int height, int coeef, int min_t, int max_t ) { + + int r, c; + double k = (coeef/100.0); + int len = (width*height); + uint8_t tmp; + + for( r = 0; r < width ; r ++ ) + { + Yb_frame[ r ] = (src[0][r] + src[0][r+width])>>1; + if(Yb_frame[r] < min_t || Yb_frame[r] > max_t) + { + Yb_frame[r] = 0; + } + } + + for (r = 0; r < len; r += width) { + for (c = 1; c < width-1; c++) { + tmp = (src[0][r + c - 1] + + src[0][r + c] + + src[0][r + c + 1] + ) / 3; + + if( tmp >= min_t && tmp <= max_t ) + { + Yb_frame[r + c ] = tmp; + } + else + { + Yb_frame[r + c ] = 0; + } + } + } + + for(c=0; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + if( Yb_frame[c] != 0) src[0][c] = (Yb_frame[c] - src[0][c]) * k; + } + +} +void noisepencil_2_apply(uint8_t *src[3], int width, int height, int coeef , int min_t, int max_t) { + + int r, c; + double k = (coeef/1000.0); + int len = (width*height)-width; + uint8_t tmp; + + for( r = 0; r < width; r++) + { + Yb_frame[ r ] = (src[0][r + width] + src[0][r]) >> 1; + if(Yb_frame[r] < min_t || Yb_frame[r] > max_t) + { + Yb_frame[r] = 0; + } + } + + for (r = width; r < len; r += width) { + for (c = 1; c < width-1; c++) { + tmp = (src[0][r - width + c - 1] + + src[0][r - width + c] + + src[0][r - width + c + 1] + + src[0][r + width + c - 1] + + src[0][r + width + c] + + src[0][r + width + c + 1] + + src[0][r + c] + + src[0][r + c + 1] + + src[0][r + c - 1] + ) / 9; + + if( tmp >= min_t && tmp <= max_t) + { + Yb_frame[c + r ] = tmp; + } + else + { + Yb_frame[c + r ] = 0; + } + } + } + + for(c=0; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + if(Yb_frame[c] != 0) src[0][c] = (Yb_frame[c] - src[0][c]) * k; + } + +} + +void noisepencil_3_apply(uint8_t *src[3], int width, int height, int coeef, int min_t , int max_t ) { + + int r, c; + double k = (coeef/1000.0); + int len = (width*height)-width; + uint8_t tmp; + for ( r = 0 ; r < width ; r++) + { + Yb_frame[r] = ( src[0][r + width] + src[0][r] ) >> 1; + if( Yb_frame[r] max_t) { + Yb_frame[r] = 0; + } + } + + for (r = width; r < len; r += width) { + for (c = 1; c < width-1; c++) { + tmp = (src[0][r - width + c - 1] + + src[0][r - width + c] + + src[0][r - width + c + 1] + + src[0][r + width + c - 1] + + src[0][r + width + c] + + src[0][r + width + c + 1] + + src[0][r + c] + + src[0][r + c + 1] + + src[0][r + c - 1] + ) / 9; + + if( min_t >= tmp && tmp <= max_t) + { + Yb_frame[c + r] = tmp; + } + else + { + Yb_frame[c + r] = 0; + } + + } + } + + for(c=0; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + if(Yb_frame[c] > 0 ) src[0][c] = (src[0][c] - Yb_frame[c]) * k; + } + +} + +void noisepencil_4_apply(uint8_t *src[3], int width, int height, int coeef, int min_t, int max_t ) { + + int r, c; + double k = (coeef/1000.0); + int len = (width*height)-width; + uint8_t tmp; + + for ( r = 0; r < width ; r++ ) + { + Yb_frame[r] = (src[0][ r + width ] + src[0][ r ] ) >> 1; + if(Yb_frame[r] < min_t || Yb_frame[r] > max_t ) + { + Yb_frame[r] = 0; + } + } + + for (r = width; r < len; r += width) { + for (c = 1; c < width-1; c++) { + tmp = (src[0][r - width + c - 1] + + src[0][r - width + c] + + src[0][r - width + c + 1] + + src[0][r + width + c - 1] + + src[0][r + width + c] + + src[0][r + width + c + 1] + + src[0][r + c] + + src[0][r + c + 1] + + src[0][r + c - 1] + ) / 9; + + if( tmp >= min_t && tmp <= max_t ) + { + Yb_frame[r] = tmp; + } + else + { + Yb_frame[r] = 16; + } + } + } + + + + for(c=0; c < len; c++) { + /* get higher signal frequencies and*/ + /* multiply result with coeffcient to get d*/ + if(Yb_frame[c] > 0) src[0][c] = (src[0][c] - Yb_frame[c]) * k; + } + +} + +/* with min_t -> max_t select the threshold to 'noise ' */ +void noisepencil_apply(VJFrame *frame, int width, int height, int type, int coeef, int min_t, + int max_t) { + + switch(type) { + case 0: + noisepencil_1_apply(frame->data,width,height,coeef,min_t,max_t); break; + case 1: + noisepencil_2_apply(frame->data,width,height,coeef,min_t,max_t); break; + case 2: + noisepencil_3_apply(frame->data,width,height,coeef,min_t,max_t); break; + case 3: + noisepencil_4_apply(frame->data,width,height,coeef,min_t,max_t); break; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/noisepencil.h b/branches/V-1.5.3/veejay-server/libvje/effects/noisepencil.h new file mode 100644 index 00000000..f003278d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/noisepencil.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef NOISEPENCIL_H +#define NOISEPENCIL_H +#include +#include +#include + +vj_effect *noisepencil_init (int w, int h); +void noisepencil_free(); +int noisepencil_malloc(int w, int h); +void noisepencil_apply( VJFrame *frame, int w, int h, int t, int n, int a, int b); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/opacity.c b/branches/V-1.5.3/veejay-server/libvje/effects/opacity.c new file mode 100644 index 00000000..71b62aa0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/opacity.c @@ -0,0 +1,172 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +/* Alpha blending with MMX, shamelessy ripped from libvisual + * + * + * Libvisual-plugins - Standard plugins for libvisual + * + * Copyright (C) 2004, 2005, 2006 Dennis Smit + * + * Authors: Dennis Smit + * + * $Id: morph_alphablend.c,v 1.19 2006/01/27 20:19:18 synap Exp $ + * + * + * + */ + +#include +#include +#include +#include +#include "opacity.h" +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif + +#define do_emms __asm__ __volatile__ ( _EMMS:::"memory") + +vj_effect *opacity_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->defaults[0] = 150; + ve->description = "Normal Overlay"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Opacity"); + return ve; +} + +#ifdef HAVE_ASM_MMX +static inline int blend_plane(uint8_t *dst, uint8_t *A, uint8_t *B, int size, int alpha) +{ + uint32_t ialpha = alpha; + int i; + + ialpha |= ialpha << 16; + + __asm __volatile + ("\n\t pxor %%mm6, %%mm6" + ::); + + for (i = size; i > 4; i -= 4) { + __asm __volatile + ("\n\t movd %[alpha], %%mm3" + "\n\t movd %[src2], %%mm0" + "\n\t psllq $32, %%mm3" + "\n\t movd %[alpha], %%mm2" + "\n\t movd %[src1], %%mm1" + "\n\t por %%mm3, %%mm2" + "\n\t punpcklbw %%mm6, %%mm0" /* interleaving dest */ + "\n\t punpcklbw %%mm6, %%mm1" /* interleaving source */ + "\n\t psubsw %%mm1, %%mm0" /* (src - dest) part */ + "\n\t pmullw %%mm2, %%mm0" /* alpha * (src - dest) */ + "\n\t psrlw $8, %%mm0" /* / 256 */ + "\n\t paddb %%mm1, %%mm0" /* + dest */ + "\n\t packuswb %%mm0, %%mm0" + "\n\t movd %%mm0, %[dest]" + : [dest] "=m" (*(dst + i)) + : [src1] "m" (*(A + i)) + , [src2] "m" (*(B + i)) + , [alpha] "m" (ialpha)); + } + return i; +} +#else +static inline int blend_plane( uint8_t *dst, uint8_t *A, uint8_t *B, int size, int opacity ) +{ + unsigned int i, op0, op1; + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + for( i = 0; i < size; i ++ ) + dst[i] = (op0 * A[i] + op1 * B[i] ) >> 8; + + + return 0; +} +#endif + + +void opacity_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int opacity) +{ + int y = blend_plane( frame->data[0], frame->data[0], frame2->data[0], frame->len, opacity ); + int u = blend_plane( frame->data[1], frame->data[1], frame2->data[1], frame->uv_len, opacity ); + int v = blend_plane( frame->data[2], frame->data[2], frame2->data[2], frame->uv_len, opacity ); +#ifdef HAVE_ASM_MMX + do_emms; +#endif + if( y>0) while (y--) + frame->data[0][y] = ((opacity * (frame->data[0][y] - frame2->data[0][y])) >> 8 ) + frame->data[0][y]; + + if( u>0) while( u-- ) + frame->data[1][u] = ((opacity * (frame->data[1][u] - frame2->data[1][u])) >> 8 ) + frame->data[1][u]; + + if(v>0) while( v-- ) + frame->data[2][v] = ((opacity * (frame->data[2][v] - frame2->data[2][v])) >> 8 ) + frame->data[2][v]; + +} + +void opacity_blend_apply( uint8_t *src1[3], uint8_t *src2[3], int len, int uv_len, int opacity ) +{ + int y = blend_plane( src1[0], src1[0], src2[0], len, opacity ); + int u = blend_plane( src1[1], src1[1], src2[1], uv_len,opacity); + int v = blend_plane( src1[2], src1[2], src2[2], uv_len, opacity); +#ifdef HAVE_ASM_MMX + do_emms; +#endif + + while (y--) + src1[0][y] = ((opacity * (src1[0][y] - src2[0][y])) >> 8) + src1[0][y]; + while( u-- ) + src1[1][u] = ((opacity * (src1[1][u] - src2[1][u])) >> 8) + src1[1][u]; + while( v-- ) + src1[2][v] = ((opacity * (src1[2][v] - src2[2][v])) >> 8) + src1[2][v]; + + +} + + +void opacity_blend_luma_apply( uint8_t *A, uint8_t *B, int len,int opacity ) +{ + int y = blend_plane( A,A,B, len, opacity ); +#ifdef HAVE_ASM_MMX + do_emms; +#endif + while (y--) + A[y] = ((opacity * (A[y] - B[y])) >> 8 ) + A[y]; +} + +void opacity_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/opacity.h b/branches/V-1.5.3/veejay-server/libvje/effects/opacity.h new file mode 100644 index 00000000..82ea0d65 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/opacity.h @@ -0,0 +1,35 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef OPACITY_H +#define OPACITY_H +#include +#include +#include + +vj_effect *opacity_init(); +void opacity_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int opacity); + +void opacity_blend_luma_apply( uint8_t *src, uint8_t *dst, int len, int opacity ); +void opacity_blend_apply( uint8_t *src[3], uint8_t *dst[3], int len, int uv_len, int opacity ); + +void opacity_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/opacityadv.c b/branches/V-1.5.3/veejay-server/libvje/effects/opacityadv.c new file mode 100644 index 00000000..b847ee8c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/opacityadv.c @@ -0,0 +1,92 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "opacityadv.h" + +vj_effect *opacityadv_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->defaults[0] = 150; + ve->defaults[1] = 40; + ve->defaults[2] = 176; + ve->description = "Overlay by Threshold Range"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user =0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Min Threshold", "Max Threshold"); + return ve; +} + +void opacityadv_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int opacity, int threshold, + int threshold2) +{ + + unsigned int x, y, len = width * height; + uint8_t a1, a2; + unsigned int op0, op1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + for (y = 0; y < len; y += width) { + for (x = 0; x < width; x++) { + a1 = Y[x + y]; + a2 = Y2[x + y]; + /* + if(a2 > a1) { + d = abs(a2-a1); + if (d > threshold && d < threshold2) { + Y[x+y] = (op0 * a1 + op1 * a2 )/255; + Cb[x+y] = (op0 * Cb[x+y] + op1 * Cb2[x+y])/255; + Cr[x+y] = (op0 * Cr[x+y] + op1 * Cr2[x+y])/255; + } + } */ + if (a1 >= threshold && a1 <= threshold2) { + Y[x + y] = (op0 * a1 + op1 * a2) >> 8; + + Cb[x + y] = + (op0 * Cb[x + y] + op1 * Cb2[x + y]) >> 8; + Cr[x + y] = + (op0 * Cr[x + y] + op1 * Cr2[x + y]) >> 8; + } + } + } +} +void opacityadv_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/opacityadv.h b/branches/V-1.5.3/veejay-server/libvje/effects/opacityadv.h new file mode 100644 index 00000000..26a84f9f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/opacityadv.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef OPACITYADV_H +#define OPACITYADV_H +#include +#include +#include + +vj_effect *opacityadv_init(); +void opacityadv_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int opacity, int threshold, + int threshold2); +void opacityadv_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/opacitythreshold.c b/branches/V-1.5.3/veejay-server/libvje/effects/opacitythreshold.c new file mode 100644 index 00000000..3c11f2b3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/opacitythreshold.c @@ -0,0 +1,108 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "opacitythreshold.h" + +vj_effect *opacitythreshold_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->defaults[0] = 180; + ve->defaults[1] = 50; + ve->defaults[2] = 255; + ve->description = "Threshold blur with overlay"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Min Threshold", "Max Threshold"); + return ve; +} + + + +void opacitythreshold_apply( VJFrame *frame, VJFrame *frame2, + int width, int height, int opacity, + int threshold, int t2) +{ + + unsigned int x, y, len = width * height-width; + uint8_t a1, a2; + unsigned int op0, op1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + for (y = width; y < len; y += width) { + for (x = 1; x < width-1; x++) { + a1 = Y[x + y]; + a2 = Y2[x + y]; + if (a1 < threshold || a1 > t2) { + a1 = (Y[y - width + x - 1] + + Y[y - width + x + 1] + + Y[y - width + x] + + Y[y + x] + + Y[y + x - 1] + + Y[y + x + 1] + + Y[y + width + x] + + Y[y + width + x + 1] + + Y[y + width + x - 1] + ) / 9; + + a2 = (Y2[y - width + x - 1] + + Y2[y - width + x + 1] + + Y2[y - width + x] + + Y2[y + x] + + Y2[y + x - 1] + + Y2[y + x + 1] + + Y2[y + width + x] + + Y2[y + width + x + 1] + + Y2[y + width + x - 1] + ) / 9; + + Y[x + y] = (op0 * a1 + op1 * a2) >> 8; + Cb[x + y] = + (op0 * Cb[x + y] + + op1 * Cb2[x + y]) >> 8; + Cr[x + y] = + (op0 * Cr[x + y] + + op1 * Cr2[x + y]) >> 8; + } + } + } +} +void opacitythreshold_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/opacitythreshold.h b/branches/V-1.5.3/veejay-server/libvje/effects/opacitythreshold.h new file mode 100644 index 00000000..95829603 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/opacitythreshold.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef OPACITYTHRESHOLD_H +#define OPACITYTHRESHOLD_H +#include +#include +#include + +vj_effect *opacitythreshold_init(); +void opacitythreshold_apply( VJFrame *frame, VJFrame *frame2, + int width, int height, int opacity, + int threshold, int t2); +void opacitythreshold_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/overclock.c b/branches/V-1.5.3/veejay-server/libvje/effects/overclock.c new file mode 100644 index 00000000..faefcc43 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/overclock.c @@ -0,0 +1,156 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "overclock.h" + +vj_effect *overclock_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = (h/8); + ve->limits[0][1] = 1; + ve->limits[1][1] = 90; + ve->defaults[0] = 5; + ve->defaults[1] = 2; + ve->description = "Radial cubics"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Radius", "Value"); + return ve; +} + +static uint8_t *oc_buf[3]; + +//copied from xine +static inline void blur(uint8_t *dst, uint8_t *src, int w, int radius, int dstStep, int srcStep){ + int x; + const int length= radius*2 + 1; + const int inv= ((1<<16) + length/2)/length; + + int sum= 0; + + for(x=0; x>16; + } + + for(; x>16; + } + + for(; x>16; + } +} + +//copied from xine +static inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int power, int dstStep, int srcStep){ + uint8_t temp[2][4096]; + uint8_t *a= temp[0], *b=temp[1]; + + if(radius){ + blur(a, src, w, radius, 1, srcStep); + for(; power>2; power--){ + uint8_t *c; + blur(b, a, w, radius, 1, 1); + c=a; a=b; b=c; + } + if(power>1) + blur(dst, a, w, radius, dstStep, 1); + else{ + int i; + for(i=0; idata[0]; + + for ( y = 0 ; y < height ; y ++) + { + blur2( oc_buf[0] + (y*width),Y + (y*width) ,width, radius,1,1,1); + } + + for( y = N ; y < (height-N); y += (1+rand()%N) ) + { + int r = 1 + rand() % N; + for( x = 0; x < width; x+= r ) + { + s = 0; + for(dy = 0; dy < N; dy++ ) + { + for(dx = 0; dx < N; dx ++ ) + { + s += oc_buf[0][(y+dy)*width+x+dx]; + } + } + t = (uint8_t) (s / (N*N)); + for(dy = 0; dy < N; dy++ ) + { + for(dx = 0; dx < N; dx ++ ) + { + i = (y+dy)*width+x+dx; + Y[i] = ( oc_buf[0][i] > Y[i] ? ((Y[i]+t)>>1) : t ); + } + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/overclock.h b/branches/V-1.5.3/veejay-server/libvje/effects/overclock.h new file mode 100644 index 00000000..892ff307 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/overclock.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef OVERCLOCK_H +#define OVERCLOCK_H +#include +#include +#include +vj_effect *overclock_init(int w, int h); +int overclock_malloc(int w, int h ); +void overclock_free(); +void overclock_apply(VJFrame *frame, int width, int height, int val, int r); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/pencilsketch.c b/branches/V-1.5.3/veejay-server/libvje/effects/pencilsketch.c new file mode 100644 index 00000000..31ae7efd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/pencilsketch.c @@ -0,0 +1,211 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "pencilsketch.h" +#include "common.h" + +vj_effect *pencilsketch_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 0;/* type */ + ve->defaults[1] = pixel_Y_lo_; /* min */ + ve->defaults[2] = pixel_Y_hi_; /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 8; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[1][2] = 255; + ve->limits[0][2] = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Mode", "Min Threshold", "Max Treshold" ); + ve->description = "Pencil Sketch (8)"; + ve->extra_frame = 0; + ve->sub_format = 0; + ve->has_user = 0; + return ve; +} + +/* PenCil sketch pixel Function + applies some artithematic on pixel a and b, + if the resulting pixel is within some range, + it will be made black otherwise white +*/ +typedef uint8_t (*_pcf) (uint8_t a, uint8_t b, int t_max); +typedef uint8_t (*_pcbcr) (uint8_t a, uint8_t b); + + static uint8_t _pcf_dneg(uint8_t a, uint8_t b, int t_max) + { + uint8_t p = + 255 - ( abs ( (255 - abs((255-a)-a)) - (255-abs((255-b)-b))) ); + p = (abs(abs(p-b) - b)); + return p; + } + + static uint8_t _pcf_lghtn(uint8_t a, uint8_t b, int t_max) + { + return (a > b ? a : b ); + } + + static uint8_t _pcf_dneg2(uint8_t a,uint8_t b, int t_max) + { + uint8_t p = ( 255 - abs ( (255-a)- b ) ); + return p; + } + + static uint8_t _pcf_min(uint8_t a, uint8_t b, int t_max) + { + uint8_t p = ( (b < a) ? b : a); + p = ( 255 - abs( (255-p) - b ) ); + return p; + } + + static uint8_t _pcf_max(uint8_t a,uint8_t b, int t_max) + { + int p = ( (b > a) ? b : a); + p = CLAMP_Y(p); + if( p == 0 ) p = 1; + p = ( 255 - ((256 - b) * (256 - b)) / p); + return (uint8_t)p; + } + + static uint8_t _pcf_pq(uint8_t a,uint8_t b, int t_max) + { + a = CLAMP_Y(a); + b = CLAMP_Y(b); + if( a == 0 ) a = 1; else if ( b == 0 ) b = 1; + int p = 255 - ((256-a) * (256-a)) / a; + int q = 255 - ((256-b) * (256-b)) / b; + p = ( 255 - ((256-p) * (256 - a)) / q); + return (uint8_t)p; + } + + static uint8_t _pcf_color(uint8_t a, uint8_t b, int t_max) + { + uint8_t p = + 255 - ( abs ( (255 - abs((255-a)-a)) - (255-abs((255-b)-b))) ); + p = (abs(abs(p-b) - b)); + p = p + b - (( p * b ) >> 8); + return p; + } + static uint8_t _pcbcr_color(uint8_t a,uint8_t b) + { + int p = a - 128; + int q = b - 128; + return ( p + q - (( p * q ) >> 8) ) + 128 ; + } + + static uint8_t _pcf_none(uint8_t a, uint8_t b, int t_max) + { + if( a >= pixel_Y_lo_ || a <= t_max) a = pixel_Y_lo_ ; else a = pixel_Y_hi_; + return a; + } + + /* get a pointer to a pixel function */ + _pcf _get_pcf(int type) + { + + switch(type) + { + + case 0: return &_pcf_dneg; + case 3: return &_pcf_lghtn; + case 1: return &_pcf_min; + case 2: return &_pcf_max; + case 5: return &_pcf_pq; + case 6: return &_pcf_dneg2; + case 7: return &_pcf_color; + } + + return &_pcf_none; + } + + +void pencilsketch_apply( + VJFrame *frame, + int width, + int height, + int type, + int threshold_min, + int threshold_max + ) +{ + unsigned int i; + int len = frame->len; + int uv_len = frame->uv_len; + int m,d; + uint8_t y,yb; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + + /* get a pointer to a pixel blend function */ + _pcf _pff = (_pcf) _get_pf(type); + _pcbcr _pcbcrff = &_pcbcr_color; + + len = len - width - 1 ; + + for(i=0; i < len; i++) + { + y = Y[i]; + yb = y; + + /* substract user defined mask from image */ + if(y >= threshold_min && y <= threshold_max) + { + /* sharpen the pixels */ + m = (Y[i+1] + Y[i+width] + Y[i+width+1]+2) >> 2; + d = Y[i] - m; + d *= 500; + d /= 100; + m = m + d; + /* a magical forumula to combine the pixel with the original*/ + y = ((((y << 1) - (255 - m))>>1) + Y[i])>>1; + /* apply blend operation on masked pixel */ + Y[i] = _pff(y,yb,threshold_max); + } + else + { + Y[i] = pixel_Y_hi_; + } + } + + /* data in I420 or YV12 */ + + if(type != 7) /* all b/w sketches */ + { + veejay_memset( Cb, 128, uv_len ); + veejay_memset( Cr, 128, uv_len ); + } + else /* all colour sketches */ + { + for(i=0; i < uv_len; i++) + { + Cb[i] = _pcbcrff(128, Cb[i]); + Cr[i] = _pcbcrff(128, Cr[i]); + } + } +} +void pencilsketch_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/pencilsketch.h b/branches/V-1.5.3/veejay-server/libvje/effects/pencilsketch.h new file mode 100644 index 00000000..6fdbf54b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/pencilsketch.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef PENCILSKETCH_EFFECT_H +#define PENCILSKETCH_EFFECT_H +#include +#include +#include + +vj_effect *pencilsketch_init(); +void pencilsketch_apply(VJFrame *frame, int w, int h, int type, int threshold, int opacity); + +void pencilsketch_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/photoplay.c b/branches/V-1.5.3/veejay-server/libvje/effects/photoplay.c new file mode 100644 index 00000000..a617fe82 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/photoplay.c @@ -0,0 +1,232 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "photoplay.h" +#include "common.h" + +vj_effect *photoplay_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; // divider + ve->limits[1][0] = max_power(w); + ve->limits[0][1] = 1; + ve->limits[1][1] = 250; // waterfall + ve->limits[0][2] = 0; + ve->limits[1][2] = 3; // mode + ve->defaults[0] = 2; + ve->defaults[1] = 1; + ve->defaults[2] = 1; + ve->description = "Photoplay (timestretched mosaic)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Photos", "Waterfall", "Mode"); + return ve; +} + +static picture_t **photo_list = NULL; +static int num_photos = 0; +static int frame_counter = 0; +static int frame_delay = 0; + +static int prepare_filmstrip(int film_length, int w, int h) +{ + int i,j; + int picture_width = w / sqrt(film_length); + int picture_height = h / sqrt(film_length); + + photo_list = (picture_t**) vj_calloc(sizeof(picture_t*) * (film_length + 1) ); + if(!photo_list) + return 0; + + num_photos = film_length; + + uint8_t val = 0; +// int inc = num_photos % 255; + + for ( i = 0; i < num_photos; i ++ ) + { + photo_list[i] = vj_malloc(sizeof(picture_t)); + if(!photo_list[i]) + return 0; + photo_list[i]->w = picture_width; + photo_list[i]->h = picture_height; + for( j = 0; j < 3; j ++ ) + { + photo_list[i]->data[j] = vj_malloc(sizeof(uint8_t) * picture_width * picture_height ); + if(!photo_list[i]->data[j]) + return 0; + veejay_memset(photo_list[i]->data[j], (j==0 ? pixel_Y_lo_ : 128), picture_width *picture_height ); + } + // val+= inc; + } + frame_counter = 0; + + return 1; +} + +static void destroy_filmstrip(void) +{ + if(photo_list) + { + int i = 0; + while(i < num_photos) + { + if( photo_list[i] ) + { + int j; + for( j = 0; j < 3; j ++ ) + if(photo_list[i]->data[j]) + free(photo_list[i]->data[j]); + free(photo_list[i]); + } + i++; + } + free(photo_list); + } + photo_list = NULL; + num_photos = 0; + frame_counter = 0; +} + + + +int photoplay_malloc(int w, int h ) +{ + num_photos = 0; + return 1; +} + + +void photoplay_free(void) +{ + destroy_filmstrip(); +} + +static void take_photo( uint8_t *plane, uint8_t *dst_plane, int w, int h, int index ) +{ + + int x,y,dx,dy; + int sum; + int dst_x, dst_y; + int step_y; + int step_x; + int box_width = photo_list[index]->w; + int box_height = photo_list[index]->h; + + step_x = w / box_width; + step_y = h / box_height; + + for( y = 0 ,dst_y = 0; y < h && dst_y < box_height; y += step_y ) + { + for( x = 0, dst_x = 0; x < w && dst_x < box_width; x+= step_x ) + { + sum = 0; + for( dy = 0; dy < step_y; dy ++ ) + { + for( dx = 0; dx < step_x; dx++) + { + sum += plane[ ((y+dy)*w+(dx+x)) ]; + } + } + // still problem here! + if(sum > 0) + dst_plane[(dst_y*box_width)+dst_x] = sum / (step_y*step_x); + else + dst_plane[(dst_y*box_width)+dst_x] = pixel_Y_lo_; + + dst_x++; + } + dst_y++; + } +} + +static void put_photo( uint8_t *dst_plane, uint8_t *photo, int dst_w, int dst_h, int index , matrix_t matrix) +{ + int box_w = photo_list[index]->w; + int box_h = photo_list[index]->h; + int x,y; + + uint8_t *P = dst_plane + (matrix.h*dst_w); + int offset = matrix.w; + + for( y = 0; y < box_h; y ++ ) + { + for( x = 0; x < box_w; x ++ ) + { + *(P+offset+x) = photo[(y*box_w)+x]; + } + P += dst_w; + } +} + +void photoplay_apply( VJFrame *frame, int width, int height, int size, int delay, int mode ) +{ + unsigned int i; + uint8_t *dstY = frame->data[0]; + uint8_t *dstU = frame->data[1]; + uint8_t *dstV = frame->data[2]; + + matrix_f matrix_placement = get_matrix_func(mode); + + if( (size*size) != num_photos || num_photos == 0 ) + { + destroy_filmstrip(); + if(!prepare_filmstrip(size*size, width,height)) + { + return; + } + frame_delay = 0; + } + + if( frame_delay ) + frame_delay --; + + if( frame_delay == 0) + { + for( i = 0; i < 3; i ++ ) + { + take_photo( frame->data[i], photo_list[(frame_counter%num_photos)]->data[i], width, height , frame_counter % num_photos); + } + frame_delay = delay; + } + + + + for ( i = 0; i < num_photos; i ++ ) + { + matrix_t m = matrix_placement(i, size,width,height ); + put_photo( dstY, photo_list[i]->data[0],width,height,i, m); + put_photo( dstU, photo_list[i]->data[1],width,height,i, m); + put_photo( dstV, photo_list[i]->data[2],width,height,i, m); + } + + + if(frame_delay == delay) + frame_counter ++; +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/photoplay.h b/branches/V-1.5.3/veejay-server/libvje/effects/photoplay.h new file mode 100644 index 00000000..52ff0859 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/photoplay.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef PHOTOPLAY_H +#define PHOTOPLAY_H +#include +#include +#include + +vj_effect *photoplay_init(int w, int h); +int photoplay_malloc(int w, int h); +void photoplay_free(void); +void photoplay_apply( VJFrame *frame, int width, int height, int size, int behaviour, int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/picinpic.c b/branches/V-1.5.3/veejay-server/libvje/effects/picinpic.c new file mode 100644 index 00000000..93395c4e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/picinpic.c @@ -0,0 +1,196 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* + This effect uses libpostproc , it should be enabled at compile time + (--with-swscaler) if you want to use this Effect. + */ +#include +#include +#include +#include +#include "picinpic.h" +#include + +extern void vj_get_yuv444_template(VJFrame *src, int w, int h); +typedef struct +{ + void *scaler; + VJFrame frame; + sws_template template; + void *sampler; + int cached; + int w; + int h; +} pic_t; + +static int nearest_div(int val); + +vj_effect *picinpic_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 64; /* width of view port */ + ve->defaults[1] = 64; /* height of viewport */ + ve->defaults[2] = 64; /* x1 */ + ve->defaults[3] = 64; /* y1 */ + + ve->limits[0][0] = 8; + ve->limits[1][0] = nearest_div(width); + ve->limits[0][1] = 8; + ve->limits[1][1] = nearest_div(height); + ve->limits[0][2] = 8; + ve->limits[1][2] = nearest_div(width); + ve->limits[0][3] = 8; + ve->limits[1][3] = nearest_div(height); + + ve->description = "Picture in picture"; + ve->sub_format = 1; + ve->extra_frame = 1; + + ve->has_user = 1; + ve->user_data = NULL; + + ve->param_description = vje_build_param_list( ve->num_params, "Width", "Height", "X offset", "Y offset" ); + return ve; +} + +int picinpic_malloc(void **d, int w, int h) +{ + int i; + pic_t *my; + *d = (void*) vj_calloc(sizeof(pic_t)); + my = (pic_t*) *d; + + my->scaler = NULL; + my->template.flags = 1; + my->w = 0; + my->h = 0; + + return 1; +} + +static int nearest_div(int val ) +{ + int r = val % 8; + while(r--) + val--; + return val; +} + +void picinpic_apply( void *user_data, VJFrame *frame, VJFrame *frame2, int width, int height, + int twidth, int theight, int x1, int y1 ) +{ + int x, y; + uint8_t *dY = frame->data[0]; + uint8_t *dCb = frame->data[1]; + uint8_t *dCr = frame->data[2]; + uint8_t *sY = frame2->data[0]; + uint8_t *sCb = frame2->data[1]; + uint8_t *sCr = frame2->data[2]; + pic_t *picture = (pic_t*) user_data; + int view_width = nearest_div(twidth); + int view_height = nearest_div(theight); + int dy = nearest_div(y1); + int dx = nearest_div(x1); + + //@ round view_width to nearest multiple of 2,4,8 + + + if ( (dx + view_width ) > width ) + view_width = width - dx; + if ( (dy + view_height ) > height ) + view_height = height - dy; + + if(view_width < 8 || view_height < 1 ) + return; // nothing to do + + /* pic in pic, using 444p */ + VJFrame scale_src; + vj_get_yuv444_template( &(scale_src), width,height ); + + scale_src.data[0] = frame2->data[0]; + scale_src.data[1] = frame2->data[1]; + scale_src.data[2] = frame2->data[2]; + + /* Setup preview scaler */ + if( picture->w != view_width || picture->h != view_height || picture->w == 0 || picture->h == 0) + { + int len = (view_width * view_height); + + if(picture->scaler) + yuv_free_swscaler( picture->scaler ); + if(picture->frame.data[0]) + free( picture->frame.data[0] ); + if(picture->frame.data[1]) + free( picture->frame.data[1] ); + if(picture->frame.data[2]) + free( picture->frame.data[2] ); + /* Allocate in picture */ + vj_get_yuv444_template( &(picture->frame), view_width,view_height ); + + picture->scaler = yuv_init_swscaler( + &(scale_src), + &(picture->frame), + &(picture->template), + yuv_sws_get_cpu_flags() + ); + picture->frame.data[0] = (uint8_t*) vj_calloc(sizeof(uint8_t) * len ); + picture->frame.data[1] = (uint8_t*) vj_malloc(sizeof(uint8_t) * len ); + picture->frame.data[2] = (uint8_t*) vj_malloc(sizeof(uint8_t) * len ); + veejay_memset( picture->frame.data[1],128, len ); + veejay_memset( picture->frame.data[2],128, len ); + picture->w = view_width; + picture->h = view_height; + + } + + yuv_convert_and_scale( picture->scaler, &(scale_src), &(picture->frame) ); + + /* Copy the scaled image to output */ + for( y = 0 ; y < picture->h-1; y ++ ) + { + for( x = 0 ; x < picture->w-1; x ++ ) + { + dY[ (dy + y ) * width + dx + x ] = + picture->frame.data[0][ y * picture->w + x]; + dCb[(dy + y ) * width + dx + x ] = + picture->frame.data[1][ y * picture->w + x]; + dCr[ (dy + y ) * width + dx + x ] = + picture->frame.data[2][ y * picture->w + x]; + } + } + +} + +void picinpic_free(void *d) +{ + if(d) + { + pic_t *my = (pic_t*) d; + if(my->scaler) + yuv_free_swscaler( my->scaler ); + free( my ); + } + d=NULL; +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/picinpic.h b/branches/V-1.5.3/veejay-server/libvje/effects/picinpic.h new file mode 100644 index 00000000..3c8bc3af --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/picinpic.h @@ -0,0 +1,37 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef PICINPIC_H +#define PICINPIC_H + +#include +#include +#include +vj_effect *picinpic_init( int w, int h ); + +void picinpic_free(void *d); + +int picinpic_malloc( void **c, int w , int h ); + + +void picinpic_apply( void *user_data, VJFrame *frame, VJFrame *frame2, + int w, int h, int twidth, int theight, int x1, int y1 ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/pixelate.c b/branches/V-1.5.3/veejay-server/libvje/effects/pixelate.c new file mode 100644 index 00000000..4e42798e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/pixelate.c @@ -0,0 +1,84 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "pixelate.h" + +static uint8_t values[2048]; + +vj_effect *pixelate_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + int i; + int nvalues=0; + for(i=1; i < width; i++) + { + if( (width%i)== 0) + { + values[nvalues] = i; + nvalues++; + } + } + + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = nvalues-2; + ve->defaults[0] = 8; + ve->description = "Pixelate"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user =0; + ve->param_description = vje_build_param_list( ve->num_params, "Pixels"); + return ve; +} + +void pixelate_apply( VJFrame *frame, int w, int h , int vv ) +{ + unsigned int i,j ; + unsigned int len = frame->len; + const unsigned int v = values[vv]; + const unsigned int uv_len = frame->uv_len; + const unsigned int u_v = v >> frame->shift_h; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + for (i = 0; i < len; i+=v) { + for(j=0; j < v; j++) + { + Y[i+j] = Y[i]; + } + } + + for (i = 0; i < uv_len; i+=u_v) { + for(j=0; j < u_v; j++) + { + Cb[i+j] = Cb[i]; + Cr[i+j] = Cr[i]; + } + } +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/pixelate.h b/branches/V-1.5.3/veejay-server/libvje/effects/pixelate.h new file mode 100644 index 00000000..0c2de417 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/pixelate.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef PIXELATE_H +#define PIXELATE_H +#include +#include +#include + +vj_effect *pixelate_init(int w, int h); +void pixelate_apply( VJFrame *frame, int width, int height, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/posterize.c b/branches/V-1.5.3/veejay-server/libvje/effects/posterize.c new file mode 100644 index 00000000..5d9836a1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/posterize.c @@ -0,0 +1,79 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "posterize.h" +vj_effect *posterize_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 4; + ve->defaults[1] = 16; + ve->defaults[2] = 235; + + ve->limits[0][0] = 1; + ve->limits[1][0] = 256; + ve->limits[0][1] = 0; + ve->limits[1][1] = 256; + ve->limits[0][2] = 0; + ve->limits[1][2] = 256; + + ve->description = "Posterize (Threshold Range)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Posterize", "Min Threshold", "Max Threshold"); + return ve; +} + + + +static void _posterize_y_simple(uint8_t *src[3], int len, int value, int threshold_min,int threshold_max) +{ + int i; + uint8_t Y; + uint8_t *y = src[0]; + const unsigned int factor = (256 / value); + for( i = 0; i < len ; i++ ) + { + Y = y[i]; + Y = Y - ( Y % factor ); + + if( Y >= threshold_min && Y <= threshold_max) + { + y[i] = Y; + + } + else + { + if( Y < threshold_min) Y = 16; else Y = 235; + } + } +} + +void posterize_apply(VJFrame *frame, int width, int height, int factor, int t1,int t2) +{ + _posterize_y_simple( frame->data, (width*height), factor, t1,t2); +} +void posterize_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/posterize.h b/branches/V-1.5.3/veejay-server/libvje/effects/posterize.h new file mode 100644 index 00000000..1b13ad0f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/posterize.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef POSTERIZE_H +#define POSTERIZE_H +#include +#include +#include + +vj_effect *posterize_init(); +void posterize_apply(VJFrame *frame, int width, int height, int factor,int t1,int t2); +void posterize_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/radcor.c b/branches/V-1.5.3/veejay-server/libvje/effects/radcor.c new file mode 100644 index 00000000..415d6599 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/radcor.c @@ -0,0 +1,175 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* Radial Distortion Correction + * http://local.wasp.uwa.edu.au/~pbourke/projection/lenscorrection/ + * + */ +#include +#include +#include +#include +#include "radcor.h" + +vj_effect *radcor_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 1000; + ve->limits[0][1] = 1; + ve->limits[1][1] = 1000; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + ve->defaults[0] = 10; + ve->defaults[1] = 40; + ve->defaults[2] = 0; + ve->description = "Lens correction"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Alpha X", "Alpha Y", "Direction"); + return ve; +} + +static uint8_t *badbuf = NULL; +static uint32_t *Map = NULL; +static int map_upd[3] = {0,0,0}; + +int radcor_malloc( int width, int height ) +{ + badbuf = (uint8_t*) vj_malloc( width * height * 3 * sizeof(uint8_t)); + if(!badbuf) + return 0; + Map = (uint32_t*) vj_malloc( width * height * sizeof(uint32_t)); + if(!Map) + return 0; + return 1; +} + +void radcor_free() +{ + free(badbuf); + free(Map); + badbuf = NULL; + Map = NULL; +} + +typedef struct +{ + uint32_t y; + uint32_t v; + uint32_t u; +} pixel_t; + + +void radcor_apply( VJFrame *frame, int width, int height, int alpaX, int alpaY, int dir) +{ + int i,j; + int len = (width * height); + int i2,j2,ii,jj,aacount; + double x,y,x2,x3,y2,y3,r; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + pixel_t csum,c; + int aa = 1; + int nx = width; + int ny = height; + int nxout = nx; + int nyout = ny; + + //@ copy source image to internal buffer + veejay_memcpy( badbuf, Y, width * height ); + veejay_memcpy( badbuf + len, Cb, len ); + veejay_memcpy( badbuf + len + len, Cr, len ); + + uint8_t *Yi = badbuf; + uint8_t *Cbi = badbuf + len; + uint8_t *Cri = badbuf + len + len; + + double alphax = alpaX / (double) 1000.0; + double alphay = alpaY / (double) 1000.0; + + if(!dir) + { + alphax *= -1.0; // inward, outward, change sign + alphay *= -1.0; + } + + veejay_memset( Y, 0, len ); + veejay_memset( Cb, 128, len ); + veejay_memset( Cr, 128, len ); + + int update_map = 0; + + if( map_upd[0] != alpaX || map_upd[1] != alpaY || map_upd[2] != dir ) + { + map_upd[0] = alpaX; + map_upd[1] = alpaY; + map_upd[2] = dir; + update_map = 1; + } + + if( update_map ) + { + for( i = 0; i < nyout; i ++ ) + { + for( j = 0; j < nxout; j ++ ) + { + x = ( 2 * j - nxout ) / (double) nxout; + y = ( 2 * i - nyout ) / (double) nyout; + + r = x*x + y*y; + x3 = x / (1 - alphax * r); + y3 = y / (1 - alphay * r); + x2 = x / (1 - alphax * (x3*x3+y3*y3)); + y2 = y / (1 - alphay * (x3*x3+y3*y3)); + i2 = (y2 + 1) * ny / 2; + j2 = (x2 + 1) * nx / 2; + + if( i2 >= 0 && i2 < ny && j2 >= 0 && j2 < nx ) + Map[ i * nxout + j ] = i2 * nx + j2; + else + Map[ i * nxout + j ] = 0; + + } + } + + } + + + // process + + for( i = 0; i < height; i ++ ) + { + for( j = 0; j < width ; j ++ ) + { + Y[ i * width + j ] = Yi[ Map[i * width + j] ]; + Cb[ i * width + j ] = Cbi[ Map[i * width + j] ]; + Cr[ i * width + j ] = Cri[ Map[i * width + j] ]; + } + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/radcor.h b/branches/V-1.5.3/veejay-server/libvje/effects/radcor.h new file mode 100644 index 00000000..3e2f4cb7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/radcor.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef LENSCOR_H +#define LENSCOR_H +#include +#include +#include + +vj_effect *radcor_init(int w, int h); +int radcor_malloc(int w, int h); +void radcor_free(); +void radcor_apply( VJFrame *frame, int width, int height, int a, int b, int c); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/radialblur.c b/branches/V-1.5.3/veejay-server/libvje/effects/radialblur.c new file mode 100644 index 00000000..e818959a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/radialblur.c @@ -0,0 +1,153 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +/* + * Copyright (C) 2000-2004 the xine project + * + * This file is part of xine, a free video player. + * + * xine 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. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: radialblur.c,v 1.1.1.1 2004/10/27 23:49:01 niels Exp $ + * + * mplayer's boxblur + * Copyright (C) 2002 Michael Niedermayer + */ +#include +#include +#include +#include "radialblur.h" +#include "common.h" +//FIXME: private +static uint8_t *radial_src[3]; + +vj_effect *radialblur_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 15; + ve->defaults[1] = 0; + ve->defaults[2] = 2; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 90; // radius + ve->limits[0][1] = 0; // power + ve->limits[1][1] = 100; + ve->limits[0][2] = 0; // direction + ve->limits[1][2] = 2; // 2 = both + ve->description = "Radial Blur"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Radius", "Power", "Direction"); + return ve; +} + +int radialblur_malloc(int w, int h) +{ + radial_src[0] = (uint8_t*) vj_yuvalloc(w,h); + if(!radial_src[0]) return 0; + radial_src[1] = radial_src[0] + (w * h); + radial_src[2] = radial_src[1] + (w * h); + return 1; +} + + +static void rhblur_apply( uint8_t *dst , uint8_t *src, int w, int h, int r , int p) +{ + int y; + for(y = 0; y < h ; y ++ ) + { + blur2( dst + y * w, src + y *w , w, r,p, 1, 1); + } + +} +static void rvblur_apply( uint8_t *dst, uint8_t *src, int w, int h, int r , int p) +{ + int x; + for(x=0; x < w; x++) + { + blur2( dst + x, src + x , h, r, p, w, w ); + } +} + + +void radialblur_apply(VJFrame *frame, int width, int height, int radius, int power, int direction) +{ + const int len = frame->len; + const int uv_len = frame->uv_len; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + if(radius == 0) return; + // inplace + + veejay_memcpy( radial_src[0] , Y, len); + veejay_memcpy( radial_src[1] , Cb, uv_len); + veejay_memcpy( radial_src[2] , Cr, uv_len); + + switch(direction) + { + case 0: rhblur_apply( Y, radial_src[0],width, height, radius, power ); + rhblur_apply( Cb, radial_src[1],frame->uv_width, frame->uv_height, radius, power ); + rhblur_apply( Cr, radial_src[2],frame->uv_width, frame->uv_height, radius, power ); + break; + case 1: rvblur_apply( Y, radial_src[0],width, height, radius, power ); + rvblur_apply( Cb, radial_src[1],frame->uv_width, frame->uv_height, radius, power ); + rvblur_apply( Cr, radial_src[2],frame->uv_width, frame->uv_height, radius, power ); + break; + case 2: + rhblur_apply( Y, radial_src[0],width, height, radius, power ); + rhblur_apply( Cb, radial_src[1],frame->uv_width, frame->uv_height, radius, power ); + rhblur_apply( Cr, radial_src[2],frame->uv_width, frame->uv_height, radius, power ); + rvblur_apply( Y, radial_src[0],width, height, radius, power ); + rvblur_apply( Cb, radial_src[1],frame->uv_width, frame->uv_height, radius, power ); + rvblur_apply( Cr, radial_src[2],frame->uv_width, frame->uv_height, radius, power ); + break; + + } + +} + + +void radialblur_free() +{ + if( radial_src[0] ) + free(radial_src[0]); + radial_src[0] = NULL; + radial_src[1] = NULL; + radial_src[2] = NULL; +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/radialblur.h b/branches/V-1.5.3/veejay-server/libvje/effects/radialblur.h new file mode 100644 index 00000000..f09e4d7f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/radialblur.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RADIALBLUR_H +#define RADIALBLUR_H +#include +#include +#include + +vj_effect *radialblur_init(int w, int h); +int radialblur_malloc(int w, int h); +void radialblur_apply(VJFrame *frame, int width, int height, int r, + int p, int n); +void radialblur_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/radioactive.c b/branches/V-1.5.3/veejay-server/libvje/effects/radioactive.c new file mode 100644 index 00000000..15ffbda7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/radioactive.c @@ -0,0 +1,379 @@ +/* + * EffecTV - Realtime Digital Video Effector + * RadioacTV - motion-enlightment effect. + * I referred to "DUNE!" by QuoVadis for this effect. + * Copyright (C) 2001-2006 FUKUCHI Kentaro + * + * Veejay FX 'RadioActiveVJ' + * (C) 2007 Niels Elburg + * This effect was ported from EffecTV. + * Differences: + * - difference frame over 2 frame interval intsead of bg substraction + * - several mask methods + * - more parameters + * - no palette (but mixing source) + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "radioactive.h" +#include "softblur.h" +#include +#include +#include "common.h" +#include + +vj_effect *radioactivetv_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; /* methods */ + ve->limits[1][0] = 6; + ve->limits[0][1] = 50;// zoom ratio + ve->limits[1][1] = 100; + ve->limits[0][2] = 0; // strength + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; //diff threhsold + ve->limits[1][3] = 255; + ve->defaults[0] = 0; + ve->defaults[1] = 95; + ve->defaults[2] = 200; + ve->defaults[3] = 30; + ve->description = "RadioActive EffecTV"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Mode", "Zoom ratio", "Strength", "Difference Threshold" ); + return ve; +} +#define RUP8(num)(((num)+8)&~8) + + +static uint8_t *diffbuf = NULL; +static uint8_t *blurzoombuf = NULL; +static int *blurzoomx = NULL; +static int *blurzoomy = NULL; +static int buf_width_blocks = 0; +static int buf_width = 0; +static int buf_height = 0; +static int buf_area = 0; +static int buf_margin_left = 0; +static int buf_margin_right = 0; +static void *convert_rgb = NULL; +static int first_frame=0; +static int last_mode=0; +static float ratio_ = 0.95; + +#define VIDEO_HWIDTH (buf_width/2) +#define VIDEO_HHEIGHT (buf_height/2) + + +/* this table assumes that video_width is times of 32 */ +static void setTable(void) +{ + unsigned int bits; + int x, y, tx, ty, xx; + int ptr, prevptr; + + prevptr = (int)(0.5+ratio_*(-VIDEO_HWIDTH)+VIDEO_HWIDTH); + for(xx=0; xx<(buf_width_blocks); xx++){ + bits = 0; + for(x=0; x<32; x++){ + ptr= (int)(0.5+ratio_*(xx*32+x-VIDEO_HWIDTH)+VIDEO_HWIDTH); + bits = bits>>1; + if(ptr != prevptr) + bits |= 0x80000000; + prevptr = ptr; + } + blurzoomx[xx] = bits; + } + + ty = (int)(0.5+ratio_*(-VIDEO_HHEIGHT)+VIDEO_HHEIGHT); + tx = (int)(0.5+ratio_*(-VIDEO_HWIDTH)+VIDEO_HWIDTH); + xx=(int)(0.5+ratio_*(buf_width-1-VIDEO_HWIDTH)+VIDEO_HWIDTH); + blurzoomy[0] = ty * buf_width + tx; + prevptr = ty * buf_width + xx; + for(y=1; y0; y--) { + for(x=width-2; x>0; x--) { + v = (*(p-width) + *(p-1) + *(p+1) + *(p+width))/4 - 1; + if(v == 255) v = 0; + *q = v; + p++; + q++; + } + p += 2; + q += 2; + } +} +static void zoom(void) +{ + int b, x, y; + unsigned char *p, *q; + int blocks, height; + int dx; + + p = blurzoombuf + buf_area; + q = blurzoombuf; + height = buf_height; + blocks = buf_width_blocks; + + for(y=0; y>1; + } + } + } +} +void blurzoomcore(void) +{ + kentaro_blur(); + zoom(); +} + +int radioactivetv_malloc(int w, int h) +{ + buf_width_blocks = (w / 32 ); + if( buf_width_blocks > 255 ) + { + return 0; + } + buf_width = buf_width_blocks * 32; + buf_height = h; + + buf_area = buf_width * buf_height; + buf_margin_left = (w - buf_width ) >> 1; + buf_margin_right = (w - buf_width - buf_margin_left); + + blurzoombuf = (uint8_t*) vj_calloc( RUP8(buf_area * 2 )); + if(!blurzoombuf) + return 0; + + blurzoomx = (int*) vj_calloc( RUP8(buf_width * sizeof(int))); + blurzoomy = (int*) vj_calloc( RUP8(buf_width * sizeof(int))); + + if( blurzoomx == NULL || blurzoomy == NULL ) + { + if(blurzoombuf) free(blurzoombuf); + return 0; + } + + diffbuf = (uint8_t*) vj_malloc( RUP8((4*w) + 2 * w * h * sizeof(uint8_t))); + + setTable(); + + first_frame = 0; + last_mode = 0; + ratio_ = 0.95; + return 1; +} + +void radioactivetv_free() +{ + if(blurzoombuf) + free(blurzoombuf); + blurzoombuf = NULL; + if(blurzoomx ) free(blurzoomx); + blurzoomx = NULL; + if(blurzoomy ) free(blurzoomy); + blurzoomy = NULL; + + if(diffbuf) free(diffbuf); + diffbuf = NULL; + +} +void radioactivetv_apply( VJFrame *frame, VJFrame *blue, int width, int height, + int mode, int snapRatio, int snapInterval, int threshold) +{ + unsigned int x, y; + uint8_t *diff = diffbuf; + uint8_t *prev = diff + frame->len; + const int len = frame->len; + uint8_t *lum = frame->data[0]; + uint8_t *dstY = lum; + uint8_t *dstU = frame->data[1]; + uint8_t *dstV = frame->data[2]; + uint8_t *p, *src = lum; + uint8_t *blueY = blue->data[0]; + uint8_t *blueU = blue->data[1]; + uint8_t *blueV = blue->data[2]; + float new_ratio = ratio_; + VJFrame smooth; + veejay_memcpy( &smooth, frame, sizeof(VJFrame)); + smooth.data[0] = prev; + + //@ set new zoom ratio + new_ratio = (snapRatio * 0.01); + if ( ratio_ != new_ratio ) + { + ratio_ = new_ratio; + setTable(); + } + + if( !first_frame ) + { //@ take current + veejay_memcpy( prev, lum , len ); + softblur_apply( &smooth, width,height,0); + first_frame++; + return; + } + if( last_mode != mode ) + { +//@ mode changed, reset + veejay_memset( blurzoombuf, 0, 2*buf_area); + veejay_memset( diff, 0, len ); + last_mode = mode; + } + + uint8_t *d = diff; + +//@ varying diff methods (strobe, normal, average, etc) + switch( mode ) + { + case 0: + for( y = 0; y < len; y ++ ){ + diff[y] = abs(lum[y] - prev[y]); + if(diff[y] < threshold ) + diff[y] = 0; + prev[y] = (prev[y] + lum[y])>>1; + } + break; + case 1: + for( y = 0; y < len; y ++ ) { + diff[y] = abs(lum[y] - prev[y]); + if(diff[y] < threshold ) + diff[y] = 0; + prev[y] = lum[y]; + } + break; + case 2: + for( y = 0; y < len; y ++ ){ + diff[y] = ( prev[y] >> 1 ) + lum[y] >> 1; + if( diff[y] < threshold ) + diff[y] = 0; + prev[y] = lum[y]; + } + break; + case 3: + for( y = 0; y < len; y ++ ) { + diff[y] = abs( lum[y] - prev[y] ); + diff[y] = (prev[y] + lum[y] + lum[y] + lum[y])>>2; + if( diff[y] < threshold ) + diff[y] = 0; + prev[y] = diff[y]; + } + break; + case 4: + for( y = 0; y < len; y ++ ) { + diff[y] = abs( lum[y] - prev[y] ); + diff[y] = (lum[y] - prev[y])>>1; + if( diff[y] < threshold ) + { + if(diff[y]) diff[y]--; + } + prev[y] = lum[y]; + } + break; + case 5: + for( y = 0; y < len; y ++ ) { + diff[y] = abs(lum[y] - prev[y]); + if(diff[y] < threshold ) + diff[y] = 0; + prev[y] = lum[y]; + } + break; + case 6: + for( y = 0; y < len; y ++ ){ + if( abs( lum[y] - prev[y]) > threshold ) + diff[y] = lum[y]>>2; + else + diff[y] = 0; + prev[y] = lum[y]; + } + + break; + } +//@ end of diff + + + p = blurzoombuf; + d += buf_margin_left; + for( y = 0; y < buf_height; y++ ) { + for( x = 0; x< buf_width; x ++ ) { + p[x] |= ( (d[x] * snapInterval)>>7); + } + d += width; + p += buf_width; + } + //@ prepare frame for next difference take + softblur_apply( &smooth, width,height,0); + + blurzoomcore(); + p = blurzoombuf; + + if(mode >= 3 ) + { + veejay_memset( dstU,128,len); + veejay_memset( dstV,128,len); + veejay_memcpy( dstY, blurzoombuf, len ); + return; + } + + + uint32_t k =0; + for( y = 0; y < height; y ++ ) + { + k += buf_margin_left; + for( x = 0; x < buf_width; x ++ ) + { + uint8_t op0 = (*p ++); + uint8_t op1 = 0xff - op0; + + dstY[k] = (op0 * blueY[k] + op1 * dstY[k])>>8; + dstU[k] = (op0 * blueU[k] + op1 * dstU[k])>>8; + dstV[k] = (op0 * blueV[k] + op1 * dstV[k])>>8; + + k ++; + } + k += buf_margin_right; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/radioactive.h b/branches/V-1.5.3/veejay-server/libvje/effects/radioactive.h new file mode 100644 index 00000000..0538b8c2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/radioactive.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RADIOACTIVE_TVH +#define RADIOACTIVE_TVH +#include +#include +#include + +vj_effect *radioactivetv_init(int w, int h); +void radioactivetv_apply( VJFrame *frame, VJFrame *blue,int width, int height, int bla,int stride, int mode, int thres); +int radioactivetv_malloc(int w, int h ); +void radioactivetv_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/raster.c b/branches/V-1.5.3/veejay-server/libvje/effects/raster.c new file mode 100644 index 00000000..d0195617 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/raster.c @@ -0,0 +1,168 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "raster.h" +#include "common.h" +#include + +vj_effect *raster_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 4; + ve->limits[1][0] = h/4; + ve->defaults[0] = 4; + ve->description = "Grid"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Grid size"); + return ve; +} + +void raster_apply(VJFrame *frame, int w, int h, int v ) +{ + int x,y; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + if(v == 0 ) + return; + + for(y=0; y < h; y++) + { + for(x=0; x < w; x++) + { + Y[y*w+x] = ((x%v>1)? ((y%v>1) ? Y[y*w+x]: 235):235); + } + } + w= frame->uv_width; + h= frame->uv_height; + + for(y=0; y < h; y++) + { + for(x=0; x < w; x++) + { + Cb[y*w+x] = ((x%v>1)? ((y%v>1) ? Cb[y*w+x]:128):128); + Cr[y*w+x] = ((x%v>1)? ((y%v>1) ? Cr[y*w+x]:128):128); + } + } +/* + int x,y; + int px,py; + int i,j; + double r,a; + unsigned int R = h/2; + double curve; //curve + double coeef; + int w2 = w/2; + int h2 = h/2; + int n1=0,n2=0,n3=0; + int k,l,m,o1=0,o2=0; + + double (*pf)(double a, double b, double c); + + if( v==0) v =1; + if( v < 0 ) { + pf = &__fisheye_i; + v = v * -1; + } + else { + pf = &__fisheye; + } + + curve = 0.001 * v; //curve + coeef = R / log(curve * R + 1); + + if(!buf) + { + buf = (uint8_t*)vj_calloc(sizeof(uint8_t) * w * h ); + if(!buf)return; + } + memcpy(buf, Y,(w*h)); + + for(y= (-1*h2); y < (h-h2); y++) +// for(y=0; y < h; y++) + //for(y=0; y < h; y++) + { + for(x = (-1*w2); x < (w-w2); x++) + // for(x=0 ;x < w; x++) + { + //if(x > 0 && y > 0) + // + if(x==0 && y==0) r = 0; + else r = sqrt( y*y+x*x); + if(x==0 && y==0) + a= 1; + else + a = atan2( (float)y,x); + + //if(x > 0 && y < 0) a += 240; + + //if(x < 0 && y > 0) a+= 180; + + //if(x < 0 && y < 0) a+= 180; + + i = (y+h2)*w+(w2+x); + if( r <= R) + { + //r = coeef * log(1 + curve * r); + r = pf( r, coeef, curve); + //px en py ook zonder + + px = (int) ( r * cos(a) ); + py = (int) ( r * sin(a) ); + px += w2; + py += h2; + if(px < 0) px =0; + if(px > w) px = w; + if(py < 0) py = 0; + if(py > (h-1)) py = h-1; + j = px + py * w; + //k = py * w + (w - px); + Y[i] = buf[j]; + } + else + { + Y[i] = 16; + } + + + + } + + } + + + printf(" n1 = %d n2 = %d n3 = %d \n",n1,n2,n3); + + + memset(Cb,128,(w*h)/4); + memset(Cr,128,(w*h)/4); + */ + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/raster.h b/branches/V-1.5.3/veejay-server/libvje/effects/raster.h new file mode 100644 index 00000000..648f98fc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/raster.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RASTER_H +#define RASTER_H +#include +#include +#include + +vj_effect *raster_init(int w, int h); +void raster_apply( VJFrame *frame, int width, int height, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rawman.c b/branches/V-1.5.3/veejay-server/libvje/effects/rawman.c new file mode 100644 index 00000000..b4717fa0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rawman.c @@ -0,0 +1,103 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rawman.h" +#include +vj_effect *rawman_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + ve->defaults[1] = 15; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 4; + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; + ve->sub_format = 0; + ve->description = "Raw Data Manipulation"; + ve->has_user = 0; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Value"); + return ve; +} + +void rawman_apply(VJFrame *frame, unsigned int width, + unsigned int height, unsigned int mode, unsigned int YY) +{ + unsigned int len = width * height; + unsigned int i; + uint8_t *Y = frame->data[0]; + + /* playing with data. experimentation gives the greatest results. + maybe these routine don't seem usefull, but combine them with + other effects. + */ + switch (mode) { + + case 1: /* 1 in reverse, if Y == 0 this darkens the image */ + for (i = 0; i < len; i++) { + if ((Y[i] < YY)) { + Y[i] *= 2; + } else { + Y[i] /= 2; + } + } + break; + case 2: + + for (i = 0; i < len; i++) { + Y[i] -= YY; + } + break; + case 3: /* divide action */ + for (i = 0; i < len; i++) { + if ((Y[i] < YY)) { + Y[i] /= 2; + } else { + /* divide by 2 */ + Y[i] *= 2; + } + } + break; + case 4: /* addition */ + for (i = 0; i < len; i++) { + if ((Y[i] < YY)) { + Y[i] += YY; + } else { + Y[i] -= YY; + } + } + break; + default: + /* brightness */ + for (i = 0; i < len; i++) { + Y[i] += YY; + } + break; + + } +} +void rawman_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rawman.h b/branches/V-1.5.3/veejay-server/libvje/effects/rawman.h new file mode 100644 index 00000000..35d64ed2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rawman.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RAWMAN_H +#define RAWMAN_H +#include +#include +#include + +vj_effect *rawman_init(); + +void rawman_apply(VJFrame *frame, unsigned int width, + unsigned int height, unsigned int mode, unsigned int Y); +void rawman_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rawval.c b/branches/V-1.5.3/veejay-server/libvje/effects/rawval.c new file mode 100644 index 00000000..f000fd69 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rawval.c @@ -0,0 +1,73 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rawval.h" +#include +#include +vj_effect *rawval_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 232; + ve->defaults[1] = 16; + ve->defaults[2] = 16; + ve->defaults[3] = 16; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->sub_format = 0; + ve->description = "Raw Chroma Pixel Replacement"; + ve->has_user = 0; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Old Cb", "Old Cr", "New Cb", "New Cr" ); + return ve; +} + + + +void rawval_apply( VJFrame *frame, int width, int height, + const int color_cb, const int color_cr, + const int new_color_cb, const int new_color_cr) +{ + unsigned int i; + const int uv_len = frame->uv_len; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + for (i = 0; i < uv_len; i++) { + if (Cb[i] >= new_color_cb) + Cb[i] = color_cb; + if (Cr[i] >= new_color_cr) + Cr[i] = color_cr; + } +} +void rawval_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rawval.h b/branches/V-1.5.3/veejay-server/libvje/effects/rawval.h new file mode 100644 index 00000000..274ca11a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rawval.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RAWVAL_H +#define RAWVAL_H +#include +#include +#include + +vj_effect *rawval_init(); +void rawval_apply( VJFrame *frame, int width, int height, int a, int b, + int na, int nb); +void rawval_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/reflection.c b/branches/V-1.5.3/veejay-server/libvje/effects/reflection.c new file mode 100644 index 00000000..77304382 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/reflection.c @@ -0,0 +1,208 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* Copyright (C) 2002 W.P. van Paassen - peter@paassen.tmfweb.nl + + 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; see the file COPYING. If not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This effect was inspired by an article by Sqrt(-1) */ +/* 08-22-02 Optimized by WP */ +/* note that the code has not been fully optimized */ + +/* orignal code for RGB, define INTENSITY( r + b + g / 3 ), + this effect works in YCbCr space now. */ + +#include +#include +#include +#include "reflection.h" +#include + +static short reflect_aSin[2048]; +static int reflection_map[2048][256]; +static int sin_index = 0; +static int sin_index2 = 20; +static uint8_t *reflection_buffer; + +vj_effect *reflection_init(int width,int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 2; + ve->defaults[1] = 5; + ve->defaults[2] = 1; + ve->limits[0][0] = 1; + ve->limits[1][0] = 256; + ve->limits[0][1] = 1; + ve->limits[1][1] = 256; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + ve->description = "Bump 2D"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Value 1", "Value 2", "Mode"); + return ve; +} +// FIXME private +int reflection_malloc(int width, int height) +{ + int i, x, y; + float rad; + + for (i = 0; i < width; i++) { + rad = (float) i * 0.0174532 * 0.703125; + reflect_aSin[i] = (short) ((sin(rad) * 100.0) + 256.0); + } + for (x = 0; x < width; ++x) { + for (y = 0; y < 256; ++y) { + float xx = (x - 128) / 128.0; + float yy = (y - 128) / 128.0; + float zz = 1.0 - sqrt(xx * xx + yy * yy); + zz *= 255.0; + if (zz < 0.0) + zz = 0.0; + reflection_map[x][y] = (int) zz; + } + } + reflection_buffer = (uint8_t *) vj_malloc(sizeof(uint8_t) * width + 1); /* fixme */ + if(!reflection_buffer) return 0; + + return 1; + + +} + + + +void reflection_free() { + if(reflection_buffer) free(reflection_buffer); + reflection_buffer = NULL; +} + + +void reflection_apply(VJFrame *frame, int width, int height, int index1, + int index2, int move) +{ + unsigned int normalx, normaly, x, y; + unsigned int lightx, lighty, temp; + int uv_height = frame->uv_height; + int uv_width = frame->uv_width; + uint8_t *row = frame->data[0] + width + 1; + uint8_t *cbrow = frame->data[1] + uv_width + 1; + uint8_t *crrow = frame->data[2] + uv_width + 1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + lightx = reflect_aSin[sin_index]; + lighty = reflect_aSin[sin_index2]; + + + if (!move) { + sin_index = index1; + sin_index2 = index2; + } else { + sin_index += index1; + sin_index2 += index2; + } + sin_index &= 511; + sin_index2 &= 511; + + for (x = 0; x < width; x++) { + reflection_buffer[x]= Y[x]; + } + + + for (y = 1; y < height - 1; y++) { + uint8_t p; + temp = lighty - y; + p = Y[x + (y * width)]; + + for (x = 0; x < width; x++) { + int i1 = (int) p; + int i2 = Y[x + 1 + (y * width)]; /* deviate */ + int i3 = (int) reflection_buffer[x]; + normalx = i2 - i1 + lightx - x; + normaly = i1 - i3 + temp; + if (normalx < 0) + normalx = 0; + else if (normalx > 255) + normalx = 255; + if (normaly < 0) + normaly = 0; + else if (normaly > 255) + normaly = 255; + *row++ = reflection_map[normalx][normaly]; + p = i2; + reflection_buffer[x] = i2; + } + *row += 2; + } + + for (y = 1; y < uv_height - 1; y++) { + uint8_t p; + temp = lighty - y; + p = Y[(x<shift_h) + (y << frame->shift_v) * width]; + + for (x = 0; x < uv_width; x++) { + int i1 = (int) p; + int i2 = Y[(x<shift_h) + 1 + ((y<shift_v) * width)]; + int i3 = (int) reflection_buffer[(x<shift_h)]; + normalx = i2 - i1 + lightx - x; + normaly = i1 - i3 + temp; + if (normalx < 0) + normalx = 0; + else if (normalx > 255) + normalx = 255; + if (normaly < 0) + normaly = 0; + else if (normaly > 255) + normaly = 255; + *cbrow++ = ((reflection_map[normalx][normaly] * (Cb[x + 1 + (y * uv_width)]-128)) >> 8) +128; + *crrow++ = ((reflection_map[normalx][normaly] * (Cr[x + 1 + (y * uv_width)]-128)) >> 8) +128; + p = i2; + reflection_buffer[x] = i2; + } + *row += 2; + } + + + //sin_index+=n; + //sin_index &= 511; + //sin_index2 +=n-2; + //sin_index2 &= 511; + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/reflection.h b/branches/V-1.5.3/veejay-server/libvje/effects/reflection.h new file mode 100644 index 00000000..c3b01e68 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/reflection.h @@ -0,0 +1,54 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +/* Copyright (C) 2002 W.P. van Paassen - peter@paassen.tmfweb.nl + + 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; see the file COPYING. If not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This effect was inspired by an article by Sqrt(-1) */ +/* 08-22-02 Optimized by WP */ +/* note that the code has not been fully optimized */ + + +#ifndef REFLECTION_H +#define REFLECTION_H +#include +#include +#include + +vj_effect *reflection_init(int width,int hei); +int reflection_malloc(int width, int height); +void reflection_free(); +void reflection_apply(VJFrame *frame, int width, int height, int n1, + int n2, int move); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/revtv.c b/branches/V-1.5.3/veejay-server/libvje/effects/revtv.c new file mode 100644 index 00000000..6f3e5266 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/revtv.c @@ -0,0 +1,109 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "revtv.h" +#include "common.h" + +#include +vj_effect *revtv_init(int max_width, int max_height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 2; + ve->defaults[1] = 42; + ve->defaults[2] = 201; + ve->defaults[3] = 6; + ve->limits[0][0] = 1; /* line spacing */ + ve->limits[1][0] = max_height; + ve->limits[0][1] = 1; /* vscale */ + ve->limits[1][1] = max_width; + ve->limits[0][2] = 0; /* luminance intensity */ + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; /* color range */ + ve->limits[1][3] = 7; + ve->description = "RevTV (EffectTV)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Line spacing", "Vertical scale", "Luminance intensity","Color range"); + return ve; +} + +/********************************************************************************************** + * + * revTV: taken from effectv-0.3.5. linespace = 1 gives a nice result. + * added the variable 'color' , so the user is free to choose replacement result. Default was 0xff. + * + **********************************************************************************************/ +void revtv_apply(VJFrame *frame, int width, int height, int linespace, + int vscale, int color, int color_num) +{ + int x, y; + uint8_t *nsrc; + int X1, X2, X3; + int yval; + int uv_width = frame->uv_width; + int uv_height = frame->uv_height; + + + int colorCb = bl_pix_get_color_cb(color); + int colorCr = bl_pix_get_color_cr(color_num); + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + for (y = 0; y < height; y += linespace) { + for (x = 0; x <= width; x++) { + nsrc = Y + (y * width) + x; + X1 = ((*nsrc) & 0xff0000) >> (16 - 1); + X2 = ((*nsrc) & 0xff00) >> (8 - 2); + X3 = (*nsrc) & 0xff; + yval = y - ((short) (X1 + X2 + X3) / vscale); + if (yval > 0) + Y[x + (yval * width)] = color; + } + } + if (color_num > 0) { + for (y = 0; y < uv_height; y += linespace) { + for (x = 0; x <= uv_width; x++) { + nsrc = Cb + (y * uv_width) + x; + X1 = ((*nsrc) & 0xff0000) >> (8 - 1); + X2 = ((*nsrc) & 0xff00) >> (4 - 2); + X3 = ((*nsrc) & 0xff) >> 1; + yval = y - ((short) (X1 + X2 + X3) / vscale); + if (yval > 0) + Cb[x + (yval * uv_width)] = colorCr; + nsrc = Cr + (y * uv_width) + x; + X1 = ((*nsrc) & 0xff0000) >> (8 - 1); + X2 = ((*nsrc) & 0xff00) >> (4 - 2); + X3 = ((*nsrc) & 0xff) >> 1; + yval = y - ((short) (X1 + X2 + X3) / vscale); + if (yval > 0) + Cr[x + (yval * uv_width)] = colorCb; + } + } + } +} +void revtv_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/revtv.h b/branches/V-1.5.3/veejay-server/libvje/effects/revtv.h new file mode 100644 index 00000000..c2871171 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/revtv.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef REVTV_H +#define REVTV_H +#include +#include +#include + +vj_effect *revtv_init(int max_width, int max_height); +void revtv_apply(VJFrame *frame, int width, int height, int space, + int vscale, int c, int cn); +void revtv_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rgbchannel.c b/branches/V-1.5.3/veejay-server/libvje/effects/rgbchannel.c new file mode 100644 index 00000000..507e2072 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rgbchannel.c @@ -0,0 +1,144 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include "rgbchannel.h" + +vj_effect *rgbchannel_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + + ve->defaults[0] = 0; + ve->defaults[0] = 0; + ve->defaults[0] = 0; + ve->description = "RGB Channel"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Red", "Green", "Blue"); + return ve; +} + +static uint8_t *rgb_ = NULL; +static VJFrame *rgb_frame_ = NULL; +static void *convert_yuv = NULL; +static void *convert_rgb = NULL; +int rgbchannel_malloc( int w, int h ) +{ + if(!rgb_) + rgb_ = vj_malloc( sizeof(uint8_t) * w * h * 3 ); + if(!rgb_) + return 0; + if(!rgb_frame_) + rgb_frame_ = yuv_rgb_template( rgb_, w, h , PIX_FMT_RGB24 ); + return 1; +} + +void rgbchannel_free( ) +{ + if(rgb_) + free(rgb_); + if(rgb_frame_) + free(rgb_frame_); + rgb_frame_ = NULL; + rgb_ = NULL; + + if(convert_rgb) + yuv_fx_context_destroy( convert_rgb ); + if(convert_yuv) + yuv_fx_context_destroy( convert_yuv ); + convert_rgb = NULL; + convert_yuv = NULL; +} + +void rgbchannel_apply( VJFrame *frame, int width, int height, int chr, int chg , int chb) +{ + unsigned int x,y,i; + + VJFrame *tmp = yuv_yuv_template( frame->data[0], + frame->data[1], + frame->data[2], + width, height, PIX_FMT_YUV444P ); + +// yuv_convert_any_ac( tmp, rgb_frame_, PIX_FMT_YUV444P, PIX_FMT_RGB24 ); + + if(!convert_yuv ) + convert_yuv = yuv_fx_context_create( tmp, rgb_frame_, PIX_FMT_YUV444P, PIX_FMT_RGB24 ); + if(!convert_rgb ) + convert_rgb = yuv_fx_context_create( rgb_frame_,tmp, PIX_FMT_RGB24, PIX_FMT_YUV444P ); + + yuv_fx_context_process( convert_yuv, tmp, rgb_frame_ ); + + int row_stride = width * 3; + + if(chr) + { + for( y = 0; y < height; y ++ ) + { + for( x = 0; x < row_stride; x += 3 ) + { + rgb_[ y * row_stride + x ] = 0; + } + } + } + if(chg) + { + for( y = 0; y < height; y ++ ) + { + for( x = 1; x < row_stride-1; x += 3 ) + { + rgb_[ y * row_stride + x ] = 0; + } + } + } + if(chb) + { + for( y = 0; y < height; y ++ ) + { + for( x = 2; x < row_stride-2; x += 3 ) + { + rgb_[ y * row_stride + x ] = 0; + } + } + } + +// yuv_convert_any_ac( rgb_frame_, tmp, PIX_FMT_RGB24, PIX_FMT_YUV444P ); + + yuv_fx_context_process( convert_rgb, rgb_frame_, tmp ); + + free(tmp); + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rgbchannel.h b/branches/V-1.5.3/veejay-server/libvje/effects/rgbchannel.h new file mode 100644 index 00000000..4cb9a0ea --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rgbchannel.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2007 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RGBCHANNEL_H +#define RGBCHANNEL_H +#include +#include +#include + +vj_effect *rgbchannel_init(int w, int h); +void rgbchannel_apply( VJFrame *frame, int width, int height, int r, int g, int b); +int rgbchannel_malloc(int w, int h ); +void rgbchannel_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rgbkey.c b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkey.c new file mode 100644 index 00000000..c4c96f5a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkey.c @@ -0,0 +1,362 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rgbkey.h" +#include +#include +#include "common.h" + +/* + + This effect is based on this small project: + + http://www.cs.utah.edu/~michael/chroma/ + + The algorithm decides which pixels belong to resp. foreground + or background. Other effects that make use of this same algorithm are + + Complex Invert, Complex Negation, Complex Saturation, Smooth RGB Key + Isolate by Color , Complex Threshold and Blend by Color Key, +*/ + +/* + (march,2005) fixed flaw (signed vs. unsigned) in algorithm + use selectable rgb -> yuv formula, + */ + +vj_effect *rgbkey_init(int w,int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 6; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 319; /* angle , 45 degrees*/ + ve->defaults[1] = 0; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 255; /* b */ + ve->defaults[4] = 1; /* type */ + ve->defaults[5] = 3500; /* noise */ + + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 1; /* total noise suppression off */ + + ve->limits[0][5] = 1; + ve->limits[1][5] = 6300; + + ve->param_description = vje_build_param_list(ve->num_params, "Angle", "Red", "Green", "Blue", "Mode", "Noise suppression"); + ve->has_user = 0; + ve->description = "Chroma Key (RGB)"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->rgb_conv = 1; + return ve; +} +/* +void rgbkey_scan_fg(uint8_t * src2[3], int *r, int *g, int *b) +{ + *r = (int) (+(1.0 * Y2[0]) + (0 * Cb2[0]) + + (1.402 * Cr2[0])); + *g = (int) (+(1.0 * Y2[0]) - (0.344136 * Cb2[0]) + + (-0.714136 * Cr2[0])); + *b = (int) (+(1.0 * Y2[0]) + (1.772 * Cb2[0]) + + (0 * Cr2[0])); +} +*/ +void rgbkey_apply1(VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int r, int g, + int b, int i_noise) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + int kbg, x1, y1; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise / 100.0); + unsigned int pos; + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + int iy=16,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = Y; + fg_cb = Cb; + fg_cr = Cr; + /* 2005: swap these !! */ + bg_y = Y2; + bg_cb = Cb2; + bg_cr = Cr2; + + for (pos = (width * height); pos != 0; pos--) { + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + // if (abs(yy) > val) { + if (abs(yy) < val) { + /* compute fg, suppress fg in xz according to kfg + */ + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + + Y[pos] = val; + + // convert suppressed fg back to cbcr + // cb,cr are signed, go back to unsigned ! + Cb[pos] = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cr[pos] = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + + // deal with noise + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + + Y[pos] = (Y[pos] + (kbg * bg_y[pos])) >> 8; + Cb[pos] = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; + Cr[pos] = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; + } + } +} + +void rgbkey_apply2(VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle,int r, int g, + int b, int i_noise) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + int kbg, x1, y1; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise / 100.0); + unsigned int pos; + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + int iy=16,iu=128,iv=128; + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = Y; + fg_cb = Cb; + fg_cr = Cr; + + bg_y = Y2; + bg_cb = Cb2; + bg_cr = Cr2; + + int len = frame->len; + + for (pos = 0; pos < len; pos++) { + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + // if (abs(yy) > val) { + if (abs(yy) < val) { + /* compute fg, suppress fg in xz according to kfg */ + + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + + Y[pos] = val; + + /* convert suppressed fg back to cbcr */ + + Cb[pos] = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cr[pos] = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + + /* deal with noise */ + + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + Y[pos] = Cb[pos] = Cr[pos] = 0; + kbg = 255; + } + + Y[pos] = (Y[pos] + (kbg * bg_y[pos])) >> 8; + Cb[pos] = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; + Cr[pos] = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; + } + } +} + + /* this is the same as rgbkey_apply1, but here we have total noise suppression + */ + +void rgbkey_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int red, int green, + int blue, int type, int i_noise) +{ + + switch (type) { + case 0: + rgbkey_apply1(frame, frame2, width, height, i_angle, red, + green, blue, i_noise); + break; + case 1: + rgbkey_apply2(frame, frame2, width, height, i_angle, red, + green, blue, i_noise); + break; + } + +} +void rgbkey_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rgbkey.h b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkey.h new file mode 100644 index 00000000..0544f27f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkey.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RGBKEY_H +#define RGBKEY_H +#include +#include +#include +vj_effect *rgbkey_init(); +void rgbkey_scan_fg(uint8_t * src2[3], int *r, int *g, int *b); +void rgbkey_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int i_noise, + int red, int green, int blue, int type ); +void rgbkey_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rgbkeysmooth.c b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkeysmooth.c new file mode 100644 index 00000000..f564d4c1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkeysmooth.c @@ -0,0 +1,198 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "rgbkey.h" +#include +#include +#include "common.h" +#include "rgbkey.h" + + +vj_effect *rgbkeysmooth_init(int w,int h) +{ + vj_effect *ve; + ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 6; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 290; /* angle */ + ve->defaults[1] = 255; /* r */ + ve->defaults[2] = 0; /* g */ + ve->defaults[3] = 0; /* b */ + ve->defaults[4] = 150; /* opacity */ + ve->defaults[5] = 1500; /* noise level */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 900; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 255; + + ve->limits[0][5] = 0; + ve->limits[1][5] = 3500; + + ve->has_user = 0; + ve->description = "Transparent Chroma Key (RGB)"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->rgb_conv = 1; + ve->param_description = vje_build_param_list( ve->num_params,"Angle","Red","Green","Blue","Opacity","Noise level"); + return ve; +} + + +void rgbkeysmooth_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int r, int g, int b, + int opacity, int i_noise) +{ + + uint8_t *fg_y, *fg_cb, *fg_cr; + uint8_t *bg_y, *bg_cb, *bg_cr; + int accept_angle_tg, accept_angle_ctg, one_over_kc; + int kfgy_scale, kg; + int cb, cr; + int kbg, x1, y1; + float kg1, tmp, aa = 128, bb = 128, _y = 0; + float angle = (float) i_angle * 0.1f; + float noise_level = (i_noise / 100.0); + unsigned int pos; + uint8_t val, tmp1; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + int iy=16,iu=128,iv=128; + unsigned int op0 = opacity > 255 ? 255 : opacity; + unsigned int op1 = 255 - op0; + + _rgb2yuv( r,g,b, iy,iu,iv ); + _y = (float) iy; + aa = (float) iu; + bb = (float) iv; + tmp = sqrt(((aa * aa) + (bb * bb))); + cb = 127 * (aa / tmp); + cr = 127 * (bb / tmp); + kg1 = tmp; + + /* obtain coordinate system for cb / cr */ + accept_angle_tg = 0xf * tan(M_PI * angle / 180.0); + accept_angle_ctg = 0xf / tan(M_PI * angle / 180.0); + + tmp = 1 / kg1; + one_over_kc = 0xff * 2 * tmp - 0xff; + kfgy_scale = 0xf * (float) (_y) / kg1; + kg = kg1; + + /* intialize pointers */ + fg_y = Y; + fg_cb = Cb; + fg_cr = Cr; + /* 2005: swap these !! */ + bg_y = Y2; + bg_cb = Cb2; + bg_cr = Cr2; + + for (pos = (width * height); pos != 0; pos--) { + short xx, yy; + /* convert foreground to xz coordinates where x direction is + defined by key color */ + + xx = (((fg_cb[pos]) * cb) + ((fg_cr[pos]) * cr)) >> 7; + + if (xx < -128) { + xx = -128; + } + if (xx > 127) { + xx = 127; + } + + yy = (((fg_cr[pos]) * cb) - ((fg_cb[pos]) * cr)) >> 7; + + if (yy < -128) { + yy = -128; + } + if (yy > 127) { + yy = 127; + } + + + /* accept angle should not be > 90 degrees + reasonable results between 10 and 80 degrees. + */ + + val = (xx * accept_angle_tg) >> 4; + if (val > 127) + val = 127; + // if (abs(yy) > val) { + if (abs(yy) < val) { + /* compute fg, suppress fg in xz according to kfg + */ + val = (yy * accept_angle_ctg) >> 4; + + x1 = abs(val); + y1 = yy; + tmp1 = xx - x1; + + kbg = (tmp1 * one_over_kc) >> 1; + if (kbg < 0) + kbg = 0; + if (kbg > 255) + kbg = 255; + + val = (tmp1 * kfgy_scale) >> 4; + val = fg_y[pos] - val; + + Y[pos] = val; + + // convert suppressed fg back to cbcr + // cb,cr are signed, go back to unsigned ! + Cb[pos] = ((x1 * (cb-128)) - (y1 * (cr-128))) >> 7; + Cr[pos] = ((x1 * (cr-128)) - (y1 * (cb-128))) >> 7; + + // deal with noise + val = (yy * yy) + (kg * kg); + if (val < (noise_level * noise_level)) { + kbg = 255; + } + + Y[pos] = ( Y[pos] + (kbg * bg_y[pos])) >> 8; + Y[pos] = ( Y[pos] * op0 + bg_y[pos] * op1 ) >> 8; + Cb[pos] = (Cb[pos] + (kbg * bg_cb[pos])) >> 8; + Cb[pos] = (Cb[pos] * op0 + bg_cb[pos] * op1) >> 8; + Cr[pos] = (Cr[pos] + (kbg * bg_cr[pos])) >> 8; + Cr[pos] = (Cr[pos] * op0 + bg_cr[pos] * op1 ) >> 8; + + } + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rgbkeysmooth.h b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkeysmooth.h new file mode 100644 index 00000000..84b2064e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rgbkeysmooth.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RGBKEYSMOOTH_H +#define RGBKEYSMOOTH_H +#include +#include +#include + +vj_effect *rgbkeysmooth_init(); +void rgbkeysmooth_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int red, int green, + int blue, int op, int noise); +void rgbkeysmooth_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/ripple.c b/branches/V-1.5.3/veejay-server/libvje/effects/ripple.c new file mode 100644 index 00000000..fc0652e6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/ripple.c @@ -0,0 +1,191 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +/* This effect recalculates a pretty large table if 'waves' or 'amplitude' + is changed. Results will be placed in ripple_table, a copy of the + frame is kept in ripple_data. So is the calculation of the first frame slow, + the following frames will use the cached coordinates until the user changes + the number of waves or the amplitude. + + +*/ + +#include +#include +#include +#include +#include +#include "ripple.h" + +#define RIPPLE_DEGREES 360.0 +#define RIPPLE_VAL 180.0 + +static double *ripple_table; +static uint8_t *ripple_data[3]; +static double *ripple_sin; +static double *ripple_cos; + +static int ripple_waves = 0; +static int ripple_ampli = 0; +static int ripple_attn = 0; +// FIXME private +vj_effect *ripple_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 3600; + ve->limits[0][1] = 1; + ve->limits[1][1] = 80; + ve->limits[0][2] = 1; + ve->limits[1][2] = 360; + ve->defaults[0] = 132; + ve->defaults[1] = 47; + ve->defaults[2] = 7; + ve->description = "Ripple"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Waves", "Amplitude", "Attenuation"); + return ve; +} + +int ripple_malloc(int width, int height) +{ + int i; + ripple_table = (double*) vj_malloc(sizeof(double) * width * height + 16); + if(!ripple_table) return 0; + ripple_data[0] = (uint8_t*)vj_yuvalloc(width,height ); + if(!ripple_data[0]) return 0; + ripple_data[1] = ripple_data[0] + (width * height); + ripple_data[2] = ripple_data[1] + (width * height); + + ripple_sin = (double*) vj_malloc(sizeof(double) * RIPPLE_DEGREES); + if(!ripple_sin) return 0; + ripple_cos = (double*) vj_malloc(sizeof(double) * RIPPLE_DEGREES); + if(!ripple_cos) return 0; + + for(i=0; i < RIPPLE_DEGREES; i++) { + ripple_sin[i] = sin ((M_PI * i) / RIPPLE_VAL); + ripple_cos[i] = sin ((M_PI * i) / RIPPLE_VAL); + } + + return 1; + +} + +void ripple_free() { + if(ripple_table) free(ripple_table); + if(ripple_sin) free(ripple_sin); + if(ripple_cos) free(ripple_cos); + if(ripple_data[0]) + free(ripple_data[0]); + ripple_data[0] = NULL; + ripple_data[1] = NULL; + ripple_data[2] = NULL; + ripple_sin = NULL; + ripple_cos = NULL; + ripple_table = NULL; +} + + +void ripple_apply(VJFrame *frame, int width, int height, int _w, int _a , int _att ) { + + double wp2 = width * 0.5; + double hp2 = height * 0.5; + int x,y,dx,dy,a=0,sx=0,sy=0,angle=0; + double r,z; + double maxradius,frequency,amplitude; + double waves = (_w/10.0); + double ampli = (double) (_a/10.0); + double attenuation = (_att/10.0); + int have_calc_data = 1; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + maxradius = sqrt(wp2 * wp2 + hp2 * hp2); + frequency = 360.0 * waves / maxradius; + amplitude = maxradius / ampli; + + + if(ripple_waves != _w) { + ripple_waves = _w; + have_calc_data=0; + } + if(ripple_ampli != _a) { + ripple_ampli = _a; + have_calc_data=0; + } + if(ripple_attn != _att) { + ripple_attn = _att; + have_calc_data = 0; + } + veejay_memcpy( ripple_data[0], Y, (width*height)); + veejay_memcpy( ripple_data[1], Cb, (width*height)); + veejay_memcpy( ripple_data[2], Cr, (width*height)); + + if (have_calc_data==0) { + for(y=0; y < height-1;y++) { + for (x=0; x < width; x++) { + dx = x - wp2; + dy = y - hp2; + + angle = 180.0 * (atan2(dx,dy)/M_PI); + + if (angle < 0) angle+=360.0; + + r = sqrt( dx * dx + dy * dy); + + z = amplitude/ pow(r,attenuation) * ripple_sin[ ((int)(frequency * r)) % 360 ]; + + a = ((int) (angle)) % 360; + sx = (int) (x+z * ripple_cos[a]); + sy = (int) (y+z * ripple_sin[a]); + + if(sy > (height-1)) sy = height-1; + if(sx > width) sx = width; + if(sx < 0) sx =0; + if(sy < 0) sy =0; + + ripple_table[(y*width)+x] = (sx + (sy * width)); + + Y[((y * width) +x)] = ripple_data[0][(sx +( sy * width)) ]; + Cb[((y * width) +x)] = ripple_data[1][(sx +( sy * width)) ]; + Cr[((y * width) +x)] = ripple_data[2][(sx +( sy * width)) ]; + } + } + } + else { + for(y=0; y < height-1;y++) { + for (x=0; x < width; x++) { + sx = ripple_table[(y*width)+x]; + Y[(y * width) +x] = ripple_data[0][sx]; + Cb[(y * width) +x] = ripple_data[1][sx]; + Cr[(y * width) +x] = ripple_data[2][sx]; + } + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/ripple.h b/branches/V-1.5.3/veejay-server/libvje/effects/ripple.h new file mode 100644 index 00000000..a5afbef0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/ripple.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RIPPLE_H +#define RIPPLE_H +#include +#include +#include +#include + +vj_effect *ripple_init(int w, int h); +void ripple_free(); +int ripple_malloc(int w, int h); +void ripple_apply(VJFrame *frame, int width, int height, int waves, int ampli,int atten); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rippletv.h b/branches/V-1.5.3/veejay-server/libvje/effects/rippletv.h new file mode 100644 index 00000000..4cf6bc5f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rippletv.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef RIPPLETV_H +#define RIPPLETV_H +#include +#include +#include +#include + +vj_effect* water_init(int width, int height); +int water_malloc(void **d,int w, int h); +void water_free(void *d); +void water_apply(void *user_data, VJFrame *frame, VJFrame *frame2, int width, int height,int fresh, int loopnum, int decay, int mode, int threshold ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rotozoom.c b/branches/V-1.5.3/veejay-server/libvje/effects/rotozoom.c new file mode 100644 index 00000000..d0f683e7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rotozoom.c @@ -0,0 +1,242 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +/* distortion effects */ +#include +#include +#include "rotozoom.h" +#include +#include + + +static int *test_roto[9]; +static int *test_roto2[9]; +static int new_zpath = 0; +static int new_path = 0; +static int roto_old_p = 0; +static int roto_old_z = 0; +static uint8_t *rotobuffer[3]; +// FIXME private +vj_effect *rotozoom_init(int width, int height) +{ + int i, j; + + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + ve->defaults[1] = 1; + ve->defaults[2] = 1; + ve->defaults[3] = 1; + ve->limits[0][0] = 0; + ve->limits[1][0] = 8; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 3; + ve->description = "Rotozoom"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Mode", "Rotate", "Zoom" , "Automatic"); + ve->has_user = 0; + for (j = 0; j < 9; j++) { + test_roto[j] = (int *) vj_malloc(sizeof(int) * 256); + test_roto2[j] = (int *) vj_malloc(sizeof(int) * 256); + } + + for (i = 0; i < 256; i++) { + float rad = (float) i * 1.41176 * 0.0174532; + float c = sin(rad); + test_roto[0][i] = (c + 0.8) * 4096.0; + test_roto2[0][i] = (2.0 * c) * 4096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 2.41176 * 0.0174532; + float c = sin(rad); + test_roto[1][i] = (c + 0.8) * 4096.0; + test_roto2[1][i] = (2.0 * c) * 4096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 3.41576 * 0.0174532; + float c = sin(rad); + test_roto[2][i] = (c + 0.8) * 4096.0; + test_roto2[2][i] = (2.0 * c) * 4096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 4.74176 * 0.0174532; + float c = sin(rad); + test_roto[3][i] = (c + 0.8) * 4096.0; + test_roto2[3][i] = (2.0 * c) * 4096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 5.91176 * 0.0174532; + float c = sin(rad); + test_roto[4][i] = (c + 0.8) * 4096.0; + test_roto2[4][i] = (2.0 * c) * 4096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 9.12345 * 0.0174532; + float c = sin(rad); + test_roto[5][i] = (c + 0.8) * 4096.0; + test_roto2[5][i] = (2.0 * c) * 4096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 9.12345 * 0.0174532; + float c = sin(rad); + test_roto[6][i] = (c + 0.8) * 8096.0; + test_roto2[6][i] = (2.0 * c) * 8096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 1.41176 * 0.0174532; + float c = sin(rad); + test_roto[7][i] = c * 4096.0; + test_roto2[7][i] = c * 4096.0; + } + for (i = 0; i < 256; i++) { + float rad = (float) i * 1.0 * 0.0174532; + float c = sin(rad); + test_roto[8][i] = c * 4096.0; + test_roto2[8][i] = c * 4096.0; + } + + return ve; +} + +void rotozoom_destroy() +{ + int j; + for (j = 0; j < 9; j++) { + if( test_roto[j] ) + free(test_roto[j]); + if( test_roto2[j]); + free(test_roto2[j]); + } +} + +int rotozoom_malloc(int width, int height) +{ + + + rotobuffer[0] = (uint8_t *) vj_calloc(sizeof(uint8_t) * width * height * 3); + if(!rotobuffer[0]) + return 0; + rotobuffer[1] = rotobuffer[0] + (width * height); + rotobuffer[2] = rotobuffer[1] + (width * height); + return 1; + +} + +void rotozoom_free() { + if(rotobuffer[0]) + free(rotobuffer[0]); + rotobuffer[0] = NULL; + rotobuffer[1] = NULL; + rotobuffer[2] = NULL; +} + +/* rotozoomer, from the demo effects collection, works in supersampled YCbCr space. + printf("Retro Rotozoom Effect - B. Ellacott, W.P. van Paassen - 2002\n"); + */ +void draw_tile(int stepx, int stepy, int zoom, int w, int h, + uint8_t * src1[3], uint8_t * src2[3]) +{ + + int x, y, i, j, xd, yd, a, b, sx, sy; + + sx = sy = 0; + xd = (stepx * zoom) >> 12; + yd = (stepy * zoom) >> 12; + + for (j = 0; j < h; j++) { + x = sx; + y = sy; + for (i = 0; i < w; i++) { + a = (x >> 12) & 255; + b = (y >> 12) & 255; + src1[0][(j * w) + i] = src2[0][b * w + a]; + src1[1][(j * w) + i] = src2[1][b * w + a]; + src1[2][(j * w) + i] = src2[2][b * w + a]; + x += xd; + y += yd; + } + sx -= yd; + sy += xd; + } +} + +void rotozoom2_apply(VJFrame *frame, uint8_t *data[3], int width, + int height, int n, int p, int z) +{ + + + draw_tile(test_roto[n][p], + test_roto[n][(p + 128) & 0xFF], + test_roto2[n][z], width, height, frame->data, data); +} + +void rotozoom1_apply(VJFrame *frame, uint8_t *data[3], int w, int h, + int n, int p, int z) +{ + + if (roto_old_p != p) { + roto_old_p = p; + new_path = p & 255; + } + if (roto_old_z != z) { + roto_old_z = z; + new_zpath = z & 255; + } + + draw_tile(test_roto[n][new_path], + test_roto[n][(new_path + 128) & 0xff], + test_roto2[n][new_zpath], w, h, frame->data, data); + + new_path = (new_path - 1) & 255; + new_zpath = (new_zpath + 1) & 255; + +} + + +void rotozoom_apply( VJFrame *frame, int width, int height, int mode, + int rotate, int zoom, int autom) +{ + switch (autom) { /* alas must do memcpy */ + case 0: + veejay_memcpy(rotobuffer[0], frame->data[0], (width * height)); + veejay_memcpy(rotobuffer[1], frame->data[1], (width * height)); + veejay_memcpy(rotobuffer[2], frame->data[2], (width * height)); + rotozoom2_apply(frame, rotobuffer, width, height, mode, rotate, + zoom); + break; + case 1: + veejay_memcpy(rotobuffer[0], frame->data[0], (width * height)); + veejay_memcpy(rotobuffer[1], frame->data[1], (width * height)); + veejay_memcpy(rotobuffer[2], frame->data[2], (width * height)); + rotozoom1_apply(frame, rotobuffer, width, height, mode, rotate, + zoom); + break; + } + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/rotozoom.h b/branches/V-1.5.3/veejay-server/libvje/effects/rotozoom.h new file mode 100644 index 00000000..58de653d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/rotozoom.h @@ -0,0 +1,34 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef ROTOZOOM_H +#define ROTOZOOM_H +#include +#include +#include +#include + +vj_effect *rotozoom_init(int width, int height); +int rotozoom_malloc(int w, int h); +void rotozoom_destroy(); +void rotozoom_free(); +void rotozoom_apply( VJFrame *frame, int width, int height, int mode, + int rot, int zoom, int autom); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/scratcher.c b/branches/V-1.5.3/veejay-server/libvje/effects/scratcher.c new file mode 100644 index 00000000..4433bfc5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/scratcher.c @@ -0,0 +1,172 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include +#include +#include +#include "scratcher.h" +#include "common.h" +#include + +static uint8_t *frame[3]; +static int nframe = 0; +static int nreverse = 0; + +vj_effect *scratcher_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 1; + ve->limits[1][1] = (MAX_SCRATCH_FRAMES-1); + ve->limits[0][2] = 0; + ve->limits[1][2] = 1; + ve->defaults[0] = 150; + ve->defaults[1] = 8; + ve->defaults[2] = 1; + ve->description = "Overlay Scratcher"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Scratch buffer", "PingPong"); + return ve; + +} + +//FIXME private + +void scratcher_free() { + if(frame[0]) + free(frame[0]); + frame[0] = NULL; + frame[1] = NULL; + frame[2] = NULL; +} + +int scratcher_malloc(int w, int h) +{ + /* need memory for bounce mode ... */ + frame[0] = + (uint8_t *) vj_malloc(w * h * 2 * sizeof(uint8_t) * MAX_SCRATCH_FRAMES); + if(!frame[0]) return 0; + + veejay_memset( frame[0], pixel_Y_lo_, w * h * MAX_SCRATCH_FRAMES ); + + frame[1] = + frame[0] + ( w * h * MAX_SCRATCH_FRAMES ); + frame[2] = + frame[1] + ( ((w*h)/4) * MAX_SCRATCH_FRAMES ); + + veejay_memset( frame[1], 128, ((w * h)/4 ) * MAX_SCRATCH_FRAMES); + veejay_memset( frame[2], 128, ((w * h)/4) * MAX_SCRATCH_FRAMES); + return 1; +} + + +void store_frame(VJFrame *src, int w, int h, int n, int no_reverse) +{ + int uv_len = src->uv_len; + uint8_t *Y = src->data[0]; + uint8_t *Cb= src->data[1]; + uint8_t *Cr= src->data[2]; + + + if (!nreverse) { + //printf("copy from buffer at pos %d to display", (w*h*nframe)); + veejay_memcpy(frame[0] + (w * h * nframe), Y, (w * h)); + veejay_memcpy(frame[1] + (uv_len * nframe), Cb, uv_len); + veejay_memcpy(frame[2] + (uv_len * nframe), Cr, uv_len); + } else { + //printf("copy frame to buffer at pos %d", (w*h*nframe)); + veejay_memcpy(Y, frame[0] + (w * h * nframe), (w * h)); + veejay_memcpy(Cb, frame[1] + (uv_len * nframe), uv_len); + veejay_memcpy(Cr, frame[2] + (uv_len * nframe), uv_len); + } + + if (nreverse) + nframe--; + else + nframe++; + + + + if (nframe >= n) { + if (no_reverse == 0) { + nreverse = 1; + nframe = n - 1; + } else { + nframe = 0; + } + } + + if (nframe == 0) + nreverse = 0; + + // printf("nframe=%d, n=%d, nreverse=%d. no_reverse=%d\n", nframe,n,nreverse,no_reverse); +} + + +void scratcher_apply(VJFrame *src, + int width, int height, int opacity, int n, + int no_reverse) +{ + + unsigned int x,len = src->len; + unsigned int op1 = (opacity > 255) ? 255 : opacity; + unsigned int op0 = 255 - op1; + int offset = len * nframe; + int uv_len = src->uv_len; + int uv_offset = uv_len * nframe; + uint8_t *Y = src->data[0]; + uint8_t *Cb = src->data[1]; + uint8_t *Cr = src->data[2]; + VJFrame copy; + + if (nframe== 0) { + veejay_memcpy(frame[0] + (len * nframe), Y, len); + veejay_memcpy(frame[1] + (uv_len * nframe), Cb, uv_len); + veejay_memcpy(frame[2] + (uv_len * nframe), Cr, uv_len); + return; + } + + for (x = 0; x < len; x++) { + Y[x] = + ((op0 * Y[x]) + (op1 * frame[0][offset + x])) >> 8; + } + + for(x=0; x < uv_len; x++) { + Cr[x] = + ((op0 * Cr[x]) + (op1 * frame[2][uv_offset + x])) >> 8; + + Cb[x] = + ((op0 * Cb[x]) + (op1 * frame[1][uv_offset + x])) >> 8; + } + + copy.uv_len = src->uv_len; + copy.data[0] = frame[0]; + copy.data[1] = frame[1]; + copy.data[2] = frame[2]; + store_frame( ©, width, height, n, no_reverse); + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/scratcher.h b/branches/V-1.5.3/veejay-server/libvje/effects/scratcher.h new file mode 100644 index 00000000..7402aeed --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/scratcher.h @@ -0,0 +1,34 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SCRATCHER_H +#define SCRATCHER_H +#include +#include +#include +#include + +vj_effect *scratcher_init(int w, int h); +int scratcher_malloc(int w, int h); +void scratcher_free(); +void scratcher_apply(VJFrame *frame, + int width, int height, int opacity, int nframes, + int no_reverse); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/sinoids.c b/branches/V-1.5.3/veejay-server/libvje/effects/sinoids.c new file mode 100644 index 00000000..3f4f77d1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/sinoids.c @@ -0,0 +1,162 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +#include +#include +#include +#include +#include +#include "sinoids.h" +#include "common.h" + +static int *sinoids_X; +static uint8_t *sinoid_frame[3]; + +vj_effect *sinoids_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 1; + ve->defaults[1] = 70; + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1000; /* sinoids */ + ve->description = "Sinoids"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Sinoids"); + return ve; +} + +static int n__ = 0; +static int N__= 0; +//FIXME private +int sinoids_malloc(int width, int height) +{ + int i = 0; + sinoids_X = (int*) vj_calloc(sizeof(int) * width); + if(!sinoids_X) return 0; + + sinoid_frame[0] = (uint8_t*)vj_yuvalloc(width,height); + if(!sinoid_frame[0]) return 0; + sinoid_frame[1] = sinoid_frame[0] + (width * height); + sinoid_frame[2] = sinoid_frame[1] + (width * height); + + n__ = 0; + N__ = 0; + for(i=0; i < width; i++ ) { + sinoids_X[i] = (int) ( sin( ((double)i/(double)width) * 2 * 3.1415926) * 1); + sinoids_X[i] *= 4; + } + + return 1; + +} + +void sinoids_free() { + if(sinoids_X) free(sinoids_X); + if(sinoid_frame[0]) + free(sinoid_frame[0]); + sinoid_frame[0] = NULL; + sinoid_frame[1] = NULL; + sinoid_frame[2] = NULL; +} + +void sinoids_recalc(int width, int z) { + int i=0; + double zoom = ( (double)z / 10.0); + for(i=0; i < width; i++ ) { + //fast_sin(si, ( ((double)i/(double)width)*2*3.1415926));// + //sinoids_X[i] = (int) si; + sinoids_X[i] = (int) ( sin( ((double)i/(double)width) * 2 * 3.1415926) * zoom); + sinoids_X[i] *= 4; + } +} + +static int current_sinoids = 100; +void sinoids_apply(VJFrame *frame, int width, int height, int m, int s) { + unsigned int len = width * height; + unsigned int r,c; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + int interpolate = 1; + int tmp1 = m; + int tmp2 = s; + int motion = 0; + if( motionmap_active()) + { + motionmap_scale_to( 1,1000,0, 0, &tmp1, &tmp2, &n__, &N__ ); + motion = 1; + } + else + { + n__ = 0; + N__ = 0; + } + if( n__ == N__ || n__ == 0 ) + interpolate = 0; + + + + if(tmp2 != current_sinoids) { + sinoids_recalc( width, tmp2); + current_sinoids = tmp2; + } + + if(m==0) { + for( r=width ; r < len-width; r+=width) { + for( c = 0; c < width; c++) { + Y[r+c] = Y[(r+c+sinoids_X[c])]; + Cb[r+c] = Cb[(r+c+sinoids_X[c])]; + Cr[r+c] = Cr[(r+c+sinoids_X[c])]; + } + } + } + else { + /* on copy */ + for(r=0; r < len ;r++) { + sinoid_frame[0][r] = Y[r]; + sinoid_frame[1][r] = Cb[r]; + sinoid_frame[2][r] = Cr[r]; + } + for(r=width; r < len-width; r+= width) { + for(c=0; c < width; c++) { + Y[r+c] = sinoid_frame[0][(r+c+sinoids_X[c])]; + Cb[r+c] = sinoid_frame[1][(r+c+sinoids_X[c])]; + Cr[r+c] = sinoid_frame[2][(r+c+sinoids_X[c])]; + } + } + } + + if( interpolate ) + motionmap_interpolate_frame( frame, N__, n__ ); + + if (motion) + motionmap_store_frame( frame ); + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/sinoids.h b/branches/V-1.5.3/veejay-server/libvje/effects/sinoids.h new file mode 100644 index 00000000..810765e6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/sinoids.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SINOIDS_H +#define SINOIDS_H +#include +#include +#include + +vj_effect *sinoids_init(int w, int h); +void sinoids_free(); +int sinoids_malloc(int w, int h); +void sinoids_apply(VJFrame *frame, int width, int height, int a,int b); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/slice.c b/branches/V-1.5.3/veejay-server/libvje/effects/slice.c new file mode 100644 index 00000000..688f14b0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/slice.c @@ -0,0 +1,174 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "slice.h" +#include +#include "common.h" + +static uint8_t *slice_frame[3]; +static int *slice_xshift; +static int *slice_yshift; +static int n__ = 0; +static int N__ = 0; +void slice_recalc(int width, int height, int val); + + + +vj_effect *slice_init(int width,int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 128; + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->defaults[0] = 63; + ve->defaults[1] = 0; + ve->description = "Slice Window"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user =0; + ve->param_description = vje_build_param_list( ve->num_params, "Slices", "Mode"); + return ve; +} +//FIXME private + +int slice_malloc(int width, int height) +{ + slice_frame[0] = (uint8_t*)vj_yuvalloc(width,height); + if(!slice_frame[0]) + return 0; + slice_frame[1] = slice_frame[0] + (width * height); + slice_frame[2] = slice_frame[1] + (width * height); + slice_xshift = (int*) vj_malloc(sizeof(int) * height); + if(!slice_xshift) return 0; + slice_yshift = (int*) vj_malloc(sizeof(int) * width); + if(!slice_yshift) return 0; + slice_recalc(width,height, 63); + n__ = 0; + N__ = 0; + return 1; +} + + +void slice_free() { + if(slice_frame[0]) + free(slice_frame[0]); + slice_frame[0] = NULL; + slice_frame[1] = NULL; + slice_frame[2] = NULL; + if(slice_xshift) + free(slice_xshift); + if(slice_yshift) + free(slice_yshift); + slice_yshift = NULL; + slice_xshift = NULL; +} + +/* much like the bathroom window, width height indicate block size within frame */ +void slice_recalc(int width, int height, int val) { + unsigned int x,y,dx,dy,r; + for(x = dx = 0; x < width; x++) + { + if(dx==0) + { + r = ((rand() & val))-((val>>1)+1); + dx = 8 + (rand() & ((val>>1))-1); + } + else + { + dx--; + } + slice_yshift[x] = r; + } + + for(y=dy=0; y < height; y++) { + if(dy==0) { r = (rand() & val)-((val>>1)+1); dy = 8 + rand() & ((val>>1)-1); } else dy--; + slice_xshift[y] = r; + } +} + + +void slice_apply(VJFrame *frame, int width, int height, int val, int re_init) { + unsigned int x,y,dx,dy; + unsigned int len = (width*height); + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + + int interpolate = 1; + int tmp1 = val; + int tmp2 = re_init; + int motion = 0; + if( motionmap_active()) + { + motionmap_scale_to( 128,1, 2, 0, &tmp1, &tmp2, &n__ , &N__ ); + if( val >= 64 ) + { + if( (rand() % 25 )== 0) + tmp2 = 1; + } + else + { + tmp2 = 1; + } + motion = 1; + } + else + { + n__ = 0; + N__ = 0; + } + + if( n__ == N__ || n__ == 0 ) + interpolate = 0; + + if(tmp2==1) slice_recalc(width,height,tmp1); + + veejay_memcpy( slice_frame[0], Y, len); + veejay_memcpy( slice_frame[1], Cb, len); + veejay_memcpy( slice_frame[2], Cr, len); + + for(y=0; y < height; y++){ + for(x=0; x < width; x++) { + dx = x + slice_xshift[y] ; dy = y + slice_yshift[x]; + if(dx < width && dy < height && dx >= 0 && dy >= 0) { + Y[(y*width)+x] = slice_frame[0][(dy*width)+dx]; + Cb[(y*width)+x] = slice_frame[1][(dy*width)+dx]; + Cr[(y*width)+x] = slice_frame[2][(dy*width)+dx]; + } + } + } + + if( interpolate ) + motionmap_interpolate_frame( frame, N__, n__ ); + + if( motion ) + motionmap_store_frame( frame ); + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/slice.h b/branches/V-1.5.3/veejay-server/libvje/effects/slice.h new file mode 100644 index 00000000..99c14388 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/slice.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SLICE_H +#define SLICE_H +#include +#include +#include +#include + +vj_effect *slice_init(int width, int height); +int slice_malloc(int width, int height); +void slice_free(); +void slice_apply(VJFrame *frame, int width, int height,int val, int re_init); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/slicer.c b/branches/V-1.5.3/veejay-server/libvje/effects/slicer.c new file mode 100644 index 00000000..6b1aa726 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/slicer.c @@ -0,0 +1,142 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include +#include +#include +#include +#include +#include "slicer.h" +static int *slice_xshift; +static int *slice_yshift; + +static recalc(int w, int h , uint8_t *Yin, int v1, int v2 ) +{ + unsigned int x,y,dx,dy,r,p; + unsigned int l = w * h; + unsigned int valx = (w / 100.0) * v1; + unsigned int valy = (h / 100.0) * v1; + unsigned int modx = (w / 100.0) * v2; + unsigned int mody = (h / 100.0) * v2; + for(x = dx = 0; x < w; x++) + { + p = 0 + (int)( l * (rand()/RAND_MAX + 0.0) ); + + if(dx==0) + { + r = ((Yin[p] & valx))-((valx>>1)+1); + dx = 8 + ( (Yin[p] & ((valx>>1))-1) ); + + } + else + { + dx--; + } + slice_yshift[x] = r; + } + + for(y=dy=0; y < h; y++) + { + p = 0 + (int)( l * rand()/RAND_MAX + 0.0 ); + if(dy==0) + { + r = (Yin[p] & valy)-((valy>>1)+1); + dy = ( 8 + Yin[p] & ((valy>>1)-1) ); + + } + else + { + dy--; + } + slice_xshift[y] = r; + } + +} + + + +int slicer_malloc(int width, int height) +{ + slice_xshift = (int*) vj_malloc(sizeof(int) * height); + if(!slice_xshift) return 0; + slice_yshift = (int*) vj_malloc(sizeof(int) * width); + if(!slice_yshift) return 0; + return 1; +} + +vj_effect *slicer_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; + ve->limits[1][0] = 100; + ve->limits[0][1] = 2; + ve->limits[1][1] = 100; + ve->defaults[0] = 16; + ve->defaults[1] = 16; + ve->description = "Slicer"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "A", "b"); + return ve; +} + + +void slicer_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int val1, int val2) +{ + unsigned int x,y,p; + const unsigned int len = (width * height); + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2= frame2->data[0]; + uint8_t *Cb2=frame2->data[1]; + uint8_t *Cr2=frame2->data[2]; + unsigned int dx,dy; + recalc( width, height, Y2, val1 ,val2 ); + + for(y=0; y < height; y++){ + for(x=0; x < width; x++) { + dx = x + slice_xshift[y]; + dy = y + slice_yshift[x]; + p = dy * width + dx; + if( p >= 0 && p < len ) { + Y[(y*width)+x] = Y2[p]; + Cb[(y*width)+x] = Cb2[p]; + Cr[(y*width)+x] = Cr2[p]; + } + } + } + } + +void slicer_free() +{ + if ( slice_xshift ) + free( slice_xshift ); + if ( slice_yshift ) + free( slice_yshift ); + slice_xshift = NULL; + slice_yshift = NULL; +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/slicer.h b/branches/V-1.5.3/veejay-server/libvje/effects/slicer.h new file mode 100644 index 00000000..5c391e56 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/slicer.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SLICER_H +#define SLICER_H +#include +#include +#include + +vj_effect *slicer_init(); +void slicer_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int slice_width, int slice_direction); +int slicer_malloc (int w, int h ); +void slicer_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/smear.c b/branches/V-1.5.3/veejay-server/libvje/effects/smear.c new file mode 100644 index 00000000..426e4904 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/smear.c @@ -0,0 +1,183 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "smear.h" +#include "common.h" + +vj_effect *smear_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 3; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->defaults[0] = 0; + ve->defaults[1] = 1; + ve->description = "Pixel Smear"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Value" ); + return ve; +} +static void _smear_apply_x(VJFrame *frame, int width, int height, int val) +{ + unsigned int j; + unsigned int x,y; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + for(y=0; y < height-1; y++) + { + for(x=0; x < width; x++) + { + j = Y[y*width+x]; + if(j >= val) + { + Y[y*width+x] = Y[y*width+x+j]; + Cb[y*width+x] = Cb[y*width+x+j]; + Cr[y*width+x] = Cr[y*width+x+j]; + } + } + } +} +static void _smear_apply_x_avg(VJFrame *frame, int width, int height, int val) +{ + unsigned int i,j; + unsigned int x,y; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + for(y=0; y < height-1; y++) + { + for(x=0; x < width; x++) + { + j = Y[y*width+x]; + if(j >= val) + { + Y[y*width+x] = ((Y[y*width+x+j] + Y[y*width+x])) >> 1; + Cb[y*width+x] = (((Cb[y*width+x+j]-128)+(Cb[y*width+x]-128))>>1)+128; + Cr[y*width+x] = (((Cb[y*width+x+j]-128)+(Cr[y*width+x]-128))>>1)+128; + } + } + } +} +static void _smear_apply_y_avg(VJFrame *frame, int width, int height, int val) +{ + unsigned int i,j; + unsigned int x,y; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + for(y=1; y < height; y++) + { + for(x=0; x < width; x++) + { + j = Y[y*width+x]; + if(j >= val) + { + if(j >= height) j = height-1; + i = j * width + x; + Y[y*width+x] = (Y[i]+Y[y*width+x])>>1; + Cb[y*width+x] = (((Cb[i]-128)+(Cb[y*width+x]-128))>>1)+128; + Cr[y*width+x] = (((Cr[i]-128)+(Cr[y*width+x]-128))>>1)+128; + } + } + } +} +static void _smear_apply_y(VJFrame *frame, int width, int height, int val) +{ + unsigned int i,j; + unsigned int x,y; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + for(y=1; y < height; y++) + { + for(x=0; x < width; x++) + { + j = Y[y*width+x]; + if(j >= val) + { + if(j >= height) j = height-1; + i = j * width + x; + Y[y*width+x] = Y[i]; + Cb[y*width+x] = Cb[i]; + Cr[y*width+x] = Cr[i]; + } + } + } +} + + +static int n__ = 0; +static int N__ = 0; + +void smear_apply( VJFrame *frame, int width, int height,int mode, int val) +{ + int interpolate = 1; + int tmp1 = mode; + int tmp2 = val; + int motion = 0; + if(motionmap_active()) + { + motionmap_scale_to( 255, 3, 0, 0, &tmp2, &tmp1, &n__, &N__ ); + motion = 1; + } + else + { + N__ = 0; + n__ = 0; + } + + if( n__ == N__ || n__ == 0 ) + interpolate = 0; + + switch(mode) + { + case 0: _smear_apply_x(frame,width,height,tmp2); break; + case 1: _smear_apply_x_avg(frame,width,height,tmp2); break; + case 2: _smear_apply_y(frame,width,height,tmp2); break; + case 3: _smear_apply_y_avg(frame,width,height,tmp2); break; + default: break; + } + + if( interpolate ) + { + motionmap_interpolate_frame( frame, N__,n__ ); + } + + if(motion) + { + motionmap_store_frame( frame ); + } + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/smear.h b/branches/V-1.5.3/veejay-server/libvje/effects/smear.h new file mode 100644 index 00000000..2bddf94f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/smear.h @@ -0,0 +1,29 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SMEAR_H +#define SMEAR_H +#include +#include +#include + +vj_effect *smear_init(int w, int h); +void smear_apply(VJFrame *frame, int width, int height,int mode, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/smuck.c b/branches/V-1.5.3/veejay-server/libvje/effects/smuck.c new file mode 100644 index 00000000..e2c7f987 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/smuck.c @@ -0,0 +1,79 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "smuck.h" +#include "common.h" +#include +#include + +static int smuck_rand_val; + +vj_effect *smuck_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 1; + ve->limits[0][0] = 0; + ve->limits[1][0] = 14; + + ve->description = "SmuckTV (EffectTV)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode"); + return ve; +} + +static inline unsigned int smuck_fastrand() +{ + return (smuck_rand_val = smuck_rand_val * 1103516245 + 12345); +} + +/* this effect comes from Effect TV as well; the code for this one is in Transform + different is the smuck table containing some values. + This effect was originally created by Buddy Smith, one of EffecTV's developers from the USA +*/ +void smuck_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int n) +{ + unsigned int yd, xd, x, y; + // different table ... + const unsigned int smuck[15] = + { 30, 60, 58, 59, 57, 56, 55, 54, 53, 89, 90, 88, 87, 86, 85 }; + uint8_t *Y = frame->data[0]; + uint8_t *Y2 = frame2->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + yd = y + (smuck_fastrand() >> smuck[n]) - 2; + xd = x + (smuck_fastrand() >> smuck[n]) - 2; + if (xd > width) + xd = width-1; + if (yd > height) + yd = height; + Y[x + y * width] = Y2[xd + yd * width]; + } + } +} +void smuck_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/smuck.h b/branches/V-1.5.3/veejay-server/libvje/effects/smuck.h new file mode 100644 index 00000000..e6bd6ff7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/smuck.h @@ -0,0 +1,34 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SMUCK_H +#define SMUCK_H + + + +#include +#include +#include + +vj_effect *smuck_init(); +void smuck_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int level); +void smuck_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/softblur.c b/branches/V-1.5.3/veejay-server/libvje/effects/softblur.c new file mode 100644 index 00000000..03ebb5d4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/softblur.c @@ -0,0 +1,210 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "softblur.h" +#include +#include + +vj_effect *softblur_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 0; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 1; /* 3*/ + ve->description = "Soft Blur (1x3) and (3x3)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Kernel size"); + return ve; +} + +void softblur1_apply( VJFrame *frame, int width, int height) +{ + int r, c; + int len = (width * height); + uint8_t *Y = frame->data[0]; + for (r = 0; r < len; r += width) { + for (c = 1; c < width-1; c++) { + Y[c + r] = (Y[r + c - 1] + + Y[r + c] + + Y[r + c + 1] + ) / 3; + + } + } + +} + +void softblur3_apply(VJFrame *frame, int width, int height ) { + int r,c; + uint8_t *Y = frame->data[0]; + const int len = frame->len; + + for(c = 1; c < width - 1; c ++ ) + Y[c ] = (Y[c - 1] + + Y[c ] + + Y[c + 1] + ) / 3; + + + + + for(r=width; r < (len-width); r+=width) { + for(c=1; c < (width-1); c++) { + Y[r+c] = ( Y[r - width + c - 1] + + Y[r - width + c ] + + Y[r + c + 1] + + Y[r - width + c] + + Y[r + c] + + Y[r + c + 1] + + Y[r + width + c - 1] + + Y[r + width + c] + + Y[r + width + c + 1] ) / 9; + + } + } + + for( c = (len-width) ; c < len; c ++ ) + Y[c ] = (Y[c - 1] + + Y[c] + + Y[c + 1] + ) / 3; + + +} +#ifdef HAVE_ASM_MMX + +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW ) +#define HAVE_K6_2PLUS +#endif + +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif + + +/* mmx_blur() taken from libvisual plugins + * + * Libvisual-plugins - Standard plugins for libvisual + * + * Copyright (C) 2002, 2003, 2004, 2005 Dennis Smit + * + * Authors: Dennis Smit + */ + +static void mmx_blur(uint8_t *buffer, int width, int height) +{ + __asm __volatile + ("\n\t pxor %%mm6, %%mm6" + ::); + + int scrsh = (width * height) >> 1; + int i; + + int len = (width * height); + + uint8_t *buf = buffer; + /* Prepare substraction register */ + for (i = 0; i < scrsh; i += 4) { + __asm __volatile + ("\n\t movd %[buf], %%mm0" + "\n\t movd %[add1], %%mm1" + "\n\t punpcklbw %%mm6, %%mm0" + "\n\t movd %[add2], %%mm2" + "\n\t punpcklbw %%mm6, %%mm1" + "\n\t movd %[add3], %%mm3" + "\n\t punpcklbw %%mm6, %%mm2" + "\n\t paddw %%mm1, %%mm0" + "\n\t punpcklbw %%mm6, %%mm3" + "\n\t paddw %%mm2, %%mm0" + "\n\t paddw %%mm3, %%mm0" + "\n\t psrlw $2, %%mm0" + "\n\t packuswb %%mm6, %%mm0" + "\n\t movd %%mm0, %[buf]" + :: [buf] "m" (*(buf + i)) + , [add1] "m" (*(buf + i + width)) + , [add2] "m" (*(buf + i + width + 1)) + , [add3] "m" (*(buf + i + width - 1)) + ); + // : "mm0", "mm1", "mm2", "mm3", "mm6"); + } + + len = (width*height)-1; + + for (i = len; i > scrsh; i -= 4) { + __asm __volatile + ("\n\t movd %[buf], %%mm0" + "\n\t movd %[add1], %%mm1" + "\n\t punpcklbw %%mm6, %%mm0" + "\n\t movd %[add2], %%mm2" + "\n\t punpcklbw %%mm6, %%mm1" + "\n\t movd %[add3], %%mm3" + "\n\t punpcklbw %%mm6, %%mm2" + "\n\t paddw %%mm1, %%mm0" + "\n\t punpcklbw %%mm6, %%mm3" + "\n\t paddw %%mm2, %%mm0" + "\n\t paddw %%mm3, %%mm0" + "\n\t psrlw $2, %%mm0" + "\n\t packuswb %%mm6, %%mm0" + "\n\t movd %%mm0, %[buf]" + :: [buf] "m" (*(buf + i)) + , [add1] "m" (*(buf + i - width)) + , [add2] "m" (*(buf + i - width + 1)) + , [add3] "m" (*(buf + i - width - 1)) + );// : "mm0", "mm1", "mm2", "mm3", "mm6"); + } + + __asm__ __volatile__ ( _EMMS:::"memory"); + +} + +#endif + +void softblur_apply(VJFrame *frame, int width, int height, int type) +{ + switch (type) { + case 0: +#ifdef HAVE_ASM_MMX + mmx_blur( frame->data[0],width,height ); +#else + softblur1_apply(frame, width, height); +#endif + break; + break; + case 1: + softblur3_apply(frame, width, height); + break; + } +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/softblur.h b/branches/V-1.5.3/veejay-server/libvje/effects/softblur.h new file mode 100644 index 00000000..994b5309 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/softblur.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SOFTBLUR_H +#define SOFTBLUR_H +#include +#include +#include + +vj_effect *softblur_init(int w, int h); +void softblur_apply(VJFrame *frame, int width, int height, int n); +void softblur_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/solarize.c b/branches/V-1.5.3/veejay-server/libvje/effects/solarize.c new file mode 100644 index 00000000..67bc1ddb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/solarize.c @@ -0,0 +1,63 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "solarize.h" +#include +vj_effect *solarize_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 16; + + ve->limits[0][0] = 1; /* threshold */ + ve->limits[1][0] = 255; + // negation by threshold + ve->description = "Solarize"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold"); + return ve; +} + +void solarize_apply( VJFrame *frame, int width, int height, int threshold) +{ + int i, len; + uint8_t val; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + len = frame->len; + for (i = 0; i < len; i++) { + val = Y[i]; + if (val > threshold) + { + Y[i] = 255 - val; + Cb[i] = 255 - Cb[i]; + Cr[i] = 255 - Cr[i]; + } + } +} +void solarize_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/solarize.h b/branches/V-1.5.3/veejay-server/libvje/effects/solarize.h new file mode 100644 index 00000000..b974d8cc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/solarize.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SOLARIZE_H +#define SOLARIZE_H +#include +#include +#include + +vj_effect *solarize_init(); +void solarize_apply(VJFrame *frame, int width, int height, + int threshold); +void solarize_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/split.c b/branches/V-1.5.3/veejay-server/libvje/effects/split.c new file mode 100644 index 00000000..9d9c60c4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/split.c @@ -0,0 +1,776 @@ + /* Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include + +#include "split.h" +static uint8_t *split_fixme[3]; +vj_effect *split_init(int width,int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 8; + ve->defaults[1] = 1; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 13; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + + ve->description = "Splitted Screens"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Mode", "Switch"); + return ve; +} +int split_malloc(int width, int height) +{ + split_fixme[0] = (uint8_t *) vj_calloc(sizeof(uint8_t) * width * height + 1); + if(!split_fixme[0]) return 0; + split_fixme[1] = (uint8_t *) vj_calloc(sizeof(uint8_t) * width * height ); + if(!split_fixme[1]) return 0; + split_fixme[2] = (uint8_t *) vj_calloc(sizeof(uint8_t) * width * height); + if(!split_fixme[2]) return 0; + return 1; + +} + +void split_free() { + if(split_fixme[0]) free(split_fixme[0]); + if(split_fixme[1]) free(split_fixme[1]); + if(split_fixme[2]) free(split_fixme[2]); +} + +void split_fib_downscale(VJFrame *frame, int width, int height) +{ + unsigned int i, len = frame->len/2; + unsigned int f; + unsigned int x, y; + int uv_width; + const int ilen = frame->len; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + i = 0; + for (y = 0; y < len; y += width) + { + for (x = 0; x < width; x++) + { + i++; + f = (i + 1) + (i - 1); + if( f >= ilen ) break; + Y[y + x] = Y[f]; + } + } + + i = 0; + uv_width = frame->uv_width; + + for (y = 0; y < uv_len; y += uv_width) + { + for (x = 0; x < uv_width; x++) { + i++; + f = (i + 1) + (i - 1); + if( f >= uv_len ) break; + Cb[y + x] = Cb[f]; + Cr[y + x] = Cr[f]; + } + } + +} +void split_fib_downscaleb(VJFrame *frame, int width, int height) +{ + unsigned int len = frame->len / 2; + unsigned int uv_len = frame->uv_len /2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + split_fib_downscale(frame, width, height); + veejay_memcpy( Y+len, Y , len ); + veejay_memcpy( Cb+uv_len, Cb, uv_len); + veejay_memcpy( Cr+uv_len, Cr, uv_len); +} + +void dosquarefib(VJFrame *frame, int width, int height) +{ + unsigned int i, len = frame->len / 2; + unsigned int f; + unsigned int x, y, y1, y2; + unsigned int uv_len = frame->uv_len; + unsigned int uv_width = frame->uv_width; + const unsigned int uv_height = frame->uv_height; + unsigned int w3 = width >> 2; + const unsigned int u_w3 = w3 >> frame->shift_h; + const unsigned int muv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + i = 0; + + for (y = 0; y < len; y += width) + { + for (x = 0; x < width; x++) { + i++; + f = (i + 1) + (i - 1); + split_fixme[0][y + x] = Y[f]; + } + } + i = 0; + for (y = 0; y < uv_len; y += uv_width) { + for (x = 0; x < uv_width; x++) { + i++; + f = (i + 1) + (i - 1); + if(f > muv_len) break; + // split_fixme[0][y + x] = Y[f]; + split_fixme[1][y + x] = Cb[f]; + split_fixme[2][y + x] = Cr[f]; + } + } + + len = len >> 1; + width = width >> 1; + for (y = 0; y < len; y += width) { + for (x = 0; x < width; x++) { + i++; + f = (i + 1) + (i - 1); + split_fixme[0][y + x] = split_fixme[0][f]; + // split_fixme[0][y + x] = split_fixme[1][f]; + // split_fixme[0][y + x] = split_fixme[2][f]; + } + } + uv_len = uv_len >> 1; + uv_width = uv_width >> 1; + for (y = 0; y < uv_len; y += uv_width) { + for (x = 0; x < uv_width; x++) { + i++; + f = (i + 1) + (i - 1); + if(f > muv_len) break; + split_fixme[1][y + x] = split_fixme[1][f]; + split_fixme[2][y + x] = split_fixme[2][f]; + } + } + + + for (y = 0; y < height; y++) { + y1 = (y * width) >> 1; + y2 = y * width; + for (i = 0; i < 4; i++) + for (x = 0; x < w3; x++) { + Y[y2 + x + (i * w3)] = split_fixme[0][y1 + x]; + } + } + for (y = 0; y < uv_height; y++) { + y1 = (y * uv_width) >> 1; + y2 = y * uv_width; + for (i = 0; i < 4; i++) + for (x = 0; x < u_w3; x++) { + Y[y2 + x + (i * u_w3)] = split_fixme[0][y1 + x]; + } + } + +} + +void split_push_downscale_uh(VJFrame *frame, int width, int height) +{ + + unsigned int len = frame->len/2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + veejay_memcpy( split_fixme[0], Y, len); + veejay_memcpy( split_fixme[1], Cb, len); + veejay_memcpy( split_fixme[2], Cr, len); + +} +void split_push_downscale_lh(VJFrame *frame, int width, int height) +{ + + unsigned int x, y, y1, y2, j = 0; + + int hlen = height / 2; + const int uv_width = frame->uv_width; + const int uv_height = frame->uv_height; + const int uv_hlen = frame->uv_len / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + for (y = 0; y < height; y+=2) + { + j++; + y2 = j * width; + y1 = y * width; + for (x = 0; x < width; x++) { + split_fixme[0][y2 + x] = Y[y1 + x]; + } + } + + j = 0; + for (y = 0; y < uv_height; y+=2) { + j++; + y2 = j * uv_width; + y1 = y * uv_width; + for (x = 0; x < uv_width; x++) { + split_fixme[1][y2 + x] = Cb[y1 + x]; + split_fixme[2][y2 + x] = Cr[y1 + x]; + } + } + + veejay_memcpy( Y+hlen, split_fixme[0] , hlen ); + veejay_memcpy( Cb+uv_hlen, split_fixme[1], uv_hlen); + veejay_memcpy( Cr+uv_hlen, split_fixme[2], uv_hlen); +} + +void split_push_vscale_left(VJFrame *frame, int width, int height) +{ + unsigned int x, y, y1; + + unsigned int wlen = width >> 1; //half + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_wlen = frame->uv_width >> frame->shift_h; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + for (y = 0; y < height; y++) + { + y1 = y * width; + for (x = 0; x < wlen; x++) + { + split_fixme[0][y1 + x] = Y[y1 + (x << 1)]; + } + } + + for (y = 0; y < uv_height; y++) + { + y1 = y * uv_width; + for (x = 0; x < uv_wlen; x++) + { + split_fixme[1][y1 + x] = Cb[y1 + (x << 1)]; + split_fixme[2][y1 + x] = Cr[y1 + (x << 1)]; + } + } + + + for (y = 0; y < height; y++) + { + y1 = y * width; + for (x = 0; x < wlen; x++) + { + Y[y1 + x] = split_fixme[0][y1 + x]; + } + } + + for (y = 0; y < uv_height; y++) { + y1 = y * uv_width; + for (x = 0; x < uv_wlen; x++) { + Cb[y1 + x] = split_fixme[1][y1 + x]; + Cr[y1 + x] = split_fixme[2][y1 + x]; + } + } + + +} +void split_push_vscale_right(VJFrame *frame, int width, int height) +{ + unsigned int x, y, y1; + unsigned int wlen = width >> 1; + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_wlen = frame->uv_width / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + + for (y = 0; y < height; y++) { + y1 = y * width; + for (x = 0; x < wlen; x++) { + split_fixme[0][y1 + x] = Y[y1 + (x * 2)]; +// split_fixme[1][y1 + x] = Cb[y1 + (x * 2)]; +// split_fixme[2][y1 + x] = Cr[y1 + (x * 2)]; + } + } + for (y = 0; y < uv_height; y++) { + y1 = y * uv_width; + for (x = 0; x < uv_wlen; x++) { +// split_fixme[0][y1 + x] = Y[y1 + (x * 2)]; + split_fixme[1][y1 + x] = Cb[y1 + (x * 2)]; + split_fixme[2][y1 + x] = Cr[y1 + (x * 2)]; + } + } + + for (y = 0; y < height; y++) { + y1 = y * width; + for (x = 0; x < wlen; x++) { + Y[y1 + x + wlen] = split_fixme[0][y1 + x]; +// Cb[y1 + x + wlen] = split_fixme[1][y1 + x]; +// Cr[y1 + x + wlen] = split_fixme[2][y1 + x]; + } + } + for (y = 0; y < uv_height; y++) { + y1 = y * uv_width; + for (x = 0; x < uv_wlen; x++) { +// Y[y1 + x + wlen] = split_fixme[0][y1 + x]; + Cb[y1 + x + uv_wlen] = split_fixme[1][y1 + x]; + Cr[y1 + x + uv_wlen] = split_fixme[2][y1 + x]; + } + } + +} + + + +void split_corner_framedata_ul(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int w_len = width / 2; + unsigned int h_len = height / 2; + unsigned int x, y; + unsigned int y1; + const int uv_width = frame->uv_width; + const int uv_wlen = frame->uv_width / 2; + const int uv_hlen = frame->uv_height / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (y = 0; y < h_len; y++) { + y1 = width * y; + for (x = 0; x < w_len; x++) { + Y[y1 + x] = Y2[y1 + x]; + } + } + for (y = 0; y < uv_hlen; y++) { + y1 = uv_width * y; + for (x = 0; x < uv_wlen; x++) { + Cb[y1 + x] = Cb2[y1 + x]; + Cr[y1 + x] = Cr2[y1 + x]; + } + } + + +} +void split_corner_framedata_ur(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int w_len = width / 2; + unsigned int h_len = height / 2; + unsigned int x, y; + unsigned int y1; + const int uv_width = frame->uv_width; + const int uv_wlen = frame->uv_width / 2; + const int uv_hlen = frame->uv_height / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + for (y = 0; y < h_len; y++) { + y1 = width * y; + for (x = w_len; x < width; x++) { + Y[y1 + x] = Y2[y1 + x]; + // Cb[y1 + x] = Cb2[y1 + x]; + // Cr[y1 + x] = Cr2[y1 + x]; + + } + } + for (y = 0; y < uv_hlen; y++) { + y1 = uv_width * y; + for (x = uv_wlen; x < uv_width; x++) { + // Y[y1 + x] = Y2[y1 + x]; + Cb[y1 + x] = Cb2[y1 + x]; + Cr[y1 + x] = Cr2[y1 + x]; + + } + } + +} +void split_corner_framedata_dl(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int w_len = width / 2; + unsigned int h_len = height / 2; + unsigned int x, y; + unsigned int y1; + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_wlen = frame->uv_width / 2; + const int uv_hlen = frame->uv_height / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + + for (y = h_len; y < height; y++) { + y1 = width * y; + for (x = 0; x < w_len; x++) { + Y[y1 + x] = Y2[y1 + x]; + // Cb[y1 + x] = Cb2[y1 + x]; + // Cr[y1 + x] = Cr2[y1 + x]; + } + } + for (y = uv_hlen; y < uv_height; y++) { + y1 = uv_width * y; + for (x = 0; x < uv_wlen; x++) { + Cb[y1 + x] = Cb2[y1 + x]; + Cr[y1 + x] = Cr2[y1 + x]; + } + } + +} + + +void split_corner_framedata_dr(VJFrame *frame, VJFrame *frame2, + int width, int height) +{ + unsigned int w_len = width / 2; + unsigned int h_len = height / 2; + unsigned int x, y; + unsigned int y1; + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_wlen = frame->uv_width / 2; + const int uv_hlen = frame->uv_height / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + + for (y = h_len; y < height; y++) { + y1 = width * y; + for (x = w_len; x < width; x++) { + Y[y1 + x] = Y2[y1 + x]; +// Cb[y1 + x] = Cb2[y1 + x]; +// Cr[y1 + x] = Cr2[y1 + x]; + } + } + for (y = uv_hlen; y < uv_height; y++) { + y1 = uv_width * y; + for (x = uv_wlen; x < uv_width; x++) { + Cb[y1 + x] = Cb2[y1 + x]; + Cr[y1 + x] = Cr2[y1 + x]; + } + } + +} + + +void split_v_first_halfs(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + + unsigned int r, c; + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_len = uv_height * uv_width; + + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + + for (r = 0; r < (width * height); r += width) { + for (c = width / 2; c < width; c++) { + Y[c + r] = Y2[(width - c) + r]; + // Cb[c + r] = Cb2[(width - c) + r]; + // Cr[c + r] = Cr2[(width - c) + r]; + } + } + for (r = 0; r < uv_len; r += uv_width) { + for (c = uv_width/2; c < uv_width; c++) { + Cb[c + r] = Cb2[(uv_width - c) + r]; + Cr[c + r] = Cr2[(uv_width - c) + r]; + } + } + +} +void split_v_second_half(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int r, c; + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_len = uv_height * uv_width; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + + for (r = 0; r < (width * height); r += width) { + for (c = width / 2; c < width; c++) { + Y[c + r] = Y2[c + r]; +// Cb[c + r] = Cb2[c + r]; +// Cr[c + r] = Cr2[c + r]; + } + } + + + for (r = 0; r < uv_len; r += uv_width) { + for (c = uv_width / 2; c < uv_width; c++) { + // Y[c + r] = Y2[c + r]; + Cb[c + r] = Cb2[c + r]; + Cr[c + r] = Cr2[c + r]; + } + } +} + +void split_v_first_half(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int r, c; + + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_len = uv_height * uv_width; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + + for (r = 0; r < (width * height); r += width) { + for (c = 0; c < width / 2; c++) { + Y[c + r] = Y2[c + r]; + // Cb[c + r] = Cb2[c + r]; + // Cr[c + r] = Cr2[c + r]; + } + } + + for (r = 0; r < uv_len; r += uv_width) { + for (c = 0; c < uv_width / 2; c++) { +// Y[c + r] = Y2[c + r]; + Cb[c + r] = Cb2[c + r]; + Cr[c + r] = Cr2[c + r]; + } + } + +} + +void split_v_second_halfs(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int r, c; + const int lw = width / 2; + const int len = frame->len; + const int uv_height = frame->uv_height; + const int uv_width = frame->uv_width; + const int uv_len = uv_height * uv_width; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + + for (r = 0; r < len; r += width) { + for (c = 0; c < lw; c++) { + Y[c + r] = Y2[(width - c) + r]; +// Cb[c + r] = Cb2[(width - c) + r]; +// Cr[c + r] = Cr2[(width - c) + r]; + } + } + + for (r = 0; r < uv_len; r += uv_width) { + for (c = 0; c < (uv_width/2); c++) { +// Y[c + r] = Y2[(width - c) + r]; + Cb[c + r] = Cb2[(width - c) + r]; + Cr[c + r] = Cr2[(width - c) + r]; + } + } + + + + + +} + +void split_h_first_half(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + const int len = frame->len / 2; + const int uv_len = frame->uv_len / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + veejay_memcpy(Y, Y2, len); + veejay_memcpy(Cb, Cb2, uv_len); + veejay_memcpy(Cr, Cr2, uv_len); + +} +void split_h_second_half(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + const unsigned int len = frame->len / 2; + const unsigned int uv_len = frame->uv_len / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + veejay_memcpy( Y, Y2+len, len ); + veejay_memcpy( Cb, Cb2+uv_len, uv_len ); + veejay_memcpy( Cr, Cr2+uv_len, uv_len ); +} +void split_h_first_halfs(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + const unsigned int len = frame->len / 2; + const unsigned int uv_len = frame->uv_len / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + veejay_memcpy( Y, Y2, len ); + veejay_memcpy( Cb, Cb2, uv_len); + veejay_memcpy( Cr, Cr2, uv_len); +} +void split_h_second_halfs(VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + const unsigned int len = frame->len / 2; + const unsigned int uv_len = frame->uv_len / 2; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + veejay_memcpy( Y+len, Y2, len ); + veejay_memcpy( Cb+uv_len, Cb2, uv_len); + veejay_memcpy( Cr+uv_len, Cr2, uv_len); +} + +void split_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n, int swap) +{ + switch (n) { + case 0: + if (swap) + split_push_downscale_uh(frame2, width, height); + split_h_first_half(frame, frame2, width, height); + break; + case 1: + //if (swap) + // split_push_downscale_lh(frame2, width, height); + split_h_second_half(frame, frame2, width, height); + break; + case 2: + //if (swap) + // split_push_downscale_lh(frame2, width, height); + /**/ split_h_first_halfs(frame, frame2, width, height); + break; + case 3: + if (swap) + split_push_downscale_uh(frame2, width, height); + /**/ split_h_second_halfs(frame, frame2, width, height); + break; + case 4: + if (swap) + split_push_vscale_left(frame2, width, height); + /**/ split_v_first_half(frame, frame2, width, height); + break; + case 5: + if (swap) + split_push_vscale_right(frame2, width, height); + /**/ split_v_second_half(frame, frame2, width, height); + break; + case 6: + if (swap) + split_push_vscale_left(frame2, width, height); + /**/ split_v_first_halfs(frame, frame2, width, height); + break; + + case 7: + //if (swap) + split_push_vscale_right(frame2, width, height); + // split_v_second_halfs(frame, frame2, width, height); + break; + case 8: + if (swap) + split_fib_downscale(frame2, width, height); + split_corner_framedata_ul(frame, frame2, width, height); + break; + case 9: + if (swap) + split_fib_downscale(frame2, width, height); + split_corner_framedata_ur(frame, frame2, width, height); + break; + case 10: + if (swap) + split_fib_downscaleb(frame2, width, height); + split_corner_framedata_dr(frame, frame2, width, height); + break; + case 11: + if (swap) + split_fib_downscaleb(frame2, width, height); + /**/ split_corner_framedata_dl(frame, frame2, width, height); + break; + case 12: + split_push_vscale_left(frame2, width, height); + /**/ split_push_vscale_right(frame, width, height); + split_v_first_half(frame, frame2, width, height); + break; + case 13: + split_push_downscale_uh(frame2, width, height); + // split_push_downscale_lh(frame, width, height); + split_h_first_half(frame, frame2, width, height); + break; + } + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/split.h b/branches/V-1.5.3/veejay-server/libvje/effects/split.h new file mode 100644 index 00000000..c3febc8f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/split.h @@ -0,0 +1,34 @@ + +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SPLIT_H +#define SPLIT_H +#include +#include +#include +#include + +vj_effect *split_init(int width, int height); +int split_malloc(int w, int h); +void split_free(); +void split_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int n, int swap); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/swirl.c b/branches/V-1.5.3/veejay-server/libvje/effects/swirl.c new file mode 100644 index 00000000..d20392eb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/swirl.c @@ -0,0 +1,183 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "swirl.h" +#include +#include "common.h" +#include + +vj_effect *swirl_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 360; + ve->defaults[0] = 250; + ve->description = "Swirl"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Degrees" ); + return ve; +} +// FIXME private +static double *polar_map; +static double *fish_angle; +static int *cached_coords; +static uint8_t *buf[3]; + + +int swirl_malloc(int w, int h) +{ + int x,y; + int h2=h/2; + int w2=w/2; + int p = 0; + + buf[0] = (uint8_t*) vj_yuvalloc( w , h ); + if(!buf[0]) return 0; + buf[1] = buf[0] + (w * h); + buf[2] = buf[1] + (w * h); + + polar_map = (double*) vj_calloc(sizeof(double) * w* h ); + if(!polar_map) return 0; + fish_angle = (double*) vj_calloc(sizeof(double) * w* h ); + if(!fish_angle) return 0; + + cached_coords = (int*) vj_calloc(sizeof(int) * w * h ); + if(!cached_coords) return 0; + + for(y=(-1 *h2); y < (h-h2); y++) + { + for(x=(-1 * w2); x < (w-w2); x++) + { + p = (h2+y) * w + (w2+x); + polar_map[p] = sqrt( y*y + x*x ); + fish_angle[p] = atan2( (float) y, x); + } + } + + return 1; +} + +void swirl_free() +{ + if(buf[0]) + free(buf[0]); + buf[1] = NULL; + buf[2] = NULL; + + if(polar_map) + free(polar_map); + if(fish_angle) + free(fish_angle); +} + + +static int _v = 0; +void swirl_apply(VJFrame *frame, int w, int h, int v) +{ + int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + + if( v != _v ) + { + //const double curve = (double) v; + const unsigned int R = w; + const double coeef = v; + //const double coeef = R / log(curve * R + 1); + //const double coeef = R / log( curve * R + 2); + /* pre calculate */ + unsigned int i; + int px,py; + double r,a; + double si,co; + const int w2 = w/2; + const int h2 = h/2; + + for(i=0; i < len; i++) + { + r = polar_map[i]; + a = fish_angle[i]; + if(r <= R) + { + //uncomment for simple fisheye + //p_y = a; + //p_r = (r*r)/R; + //sin_cos( co, si, p_y ); + sin_cos( co,si, (a+r/coeef)); + px = (int) ( r * co ); + py = (int) ( r * si ); + //sin_cos( co, si, (double)v ); + //px = (int) (r * co); + //py = (int) (r * si); + //px = (int) ( p_r * co); + //py = (int) ( p_r * si); + px += w2; + py += h2; + + if(px < 0) px =0; + if(px > w) px = w; + if(py < 0) py = 0; + if(py >= (h-1)) py = h-1; + + cached_coords[i] = (py * w)+px; + + } + else + { + cached_coords[i] = -1; + + } + } + _v = v; + + } + veejay_memcpy(buf[0], Y,len); + veejay_memcpy(buf[1], Cb,len); + veejay_memcpy(buf[2], Cr,len); + + for(i=0; i < len; i++) + { + if(cached_coords[i] == -1) + { + Y[i] = pixel_Y_lo_; + Cb[i] = 128; + Cr[i] = 128; + } + else + { + + Y[i] = Y[ cached_coords[i] ]; + Cb[i] = Cb[ cached_coords[i] ]; + Cr[i] = Cr[ cached_coords[i] ]; + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/swirl.h b/branches/V-1.5.3/veejay-server/libvje/effects/swirl.h new file mode 100644 index 00000000..9ad054bf --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/swirl.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SWIRL_H +#define SWIRL_H +#include +#include +#include + +vj_effect *swirl_init(int w, int h); +int swirl_malloc(int w, int h); +void swirl_free(); +void swirl_apply(VJFrame *frame, int width, int height, int val); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/texmap.c b/branches/V-1.5.3/veejay-server/libvje/effects/texmap.c new file mode 100644 index 00000000..589a4e00 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/texmap.c @@ -0,0 +1,493 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "diff.h" +#include "common.h" +#include +#include +#include +#include +#include +#include +#include + +#include "softblur.h" +static uint8_t *static_bg = NULL; +static uint32_t *dt_map = NULL; +static void *shrink_ = NULL; +static sws_template template_; +static VJFrame to_shrink_; +static VJFrame shrinked_; +static int dw_, dh_; +static int x_[255]; +static int y_[255]; +static void *proj_[255]; +static int *coord_x = NULL; +static int *coord_y = NULL; + +typedef struct +{ + uint32_t *data; + uint8_t *bitmap; + uint8_t *current; +} texmap_data; + +typedef struct +{ + int x; + int y; +} point_t; + +static point_t **points = NULL; + +vj_effect *texmap_init(int width, int height) +{ + //int i,j; + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; /* reverse */ + ve->limits[1][1] = 1; + ve->limits[0][2] = 0; /* show mask */ + ve->limits[1][2] = 4; + ve->limits[0][3] = 1; /* thinning */ + ve->limits[1][3] = 100; + ve->limits[0][4] = 1; /* minimum blob weight */ + ve->limits[1][4] = 5000; + + ve->defaults[0] = 30; + ve->defaults[1] = 0; + ve->defaults[2] = 2; + ve->defaults[3] = 5; + ve->defaults[4] = 200; + + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Reverse", "Show mask", "Thinning", "Min blob weight"); + + ve->description = "Map B to A (sub bg, texture map))"; + ve->extra_frame = 1; + ve->sub_format = 1; + ve->has_user = 1; + ve->user_data = NULL; + return ve; +} + +void texmap_destroy(void) +{ + if(static_bg) + free(static_bg); + if(dt_map) + free(dt_map); + static_bg = NULL; + dt_map = NULL; + +} + +#define ru8(num)(((num)+8)&~8) +static int nearest_div(int val ) +{ + int r = val % 8; + while(r--) + val--; + return val; +} +int texmap_malloc(void **d, int width, int height) +{ + texmap_data *my; + *d = (void*) vj_calloc(sizeof(texmap_data)); + my = (texmap_data*) *d; + + dw_ = nearest_div( width / 8 ); + dh_ = nearest_div( height / 8 ); + + my->current = (uint8_t*) vj_calloc( ru8( sizeof(uint8_t) * dw_ * dh_ * 4 ) ); + my->data = (uint32_t*) vj_calloc( ru8(sizeof(uint32_t) * width * height * 2) ); + my->bitmap = (uint8_t*) vj_calloc( ru8(sizeof(uint8_t) * width * height * 2)); + + if(static_bg == NULL) + static_bg = (uint8_t*) vj_calloc( ru8( width + width * height * sizeof(uint8_t)) ); + if(dt_map == NULL ) + dt_map = (uint32_t*) vj_calloc( ru8(width * height * sizeof(uint32_t) + width ) ); + + veejay_memset( &template_, 0, sizeof(sws_template) ); + veejay_memset( proj_, 0, sizeof(proj_) ); + + template_.flags = 1; + + vj_get_yuvgrey_template( &to_shrink_, width, height ); + vj_get_yuvgrey_template( &shrinked_ , dw_, dh_ ); + + shrink_ = yuv_init_swscaler( + &(to_shrink_), + &(shrinked_), + &template_ , + yuv_sws_get_cpu_flags() ); + + points = (point_t**) vj_calloc( sizeof(point_t) * 12000 ); + int i; + for( i = 0; i < 12000;i ++ ) + points[i] = (point_t*) vj_calloc(sizeof(point_t)); + + + veejay_memset( x_, 0, sizeof(x_) ); + veejay_memset( y_, 0, sizeof(y_) ); + + return 1; +} + +void texmap_free(void *d) +{ + if(d) + { + texmap_data *my = (texmap_data*) d; + if(my->data) free(my->data); + if(my->current) free(my->current); + if(my->bitmap) free(my->bitmap); + free(d); + } + + if( shrink_ ) + { + yuv_free_swscaler( shrink_ ); + shrink_ = NULL; + } + + int i; + for( i = 0; i < 255; i++ ) + if( proj_[i] ) + viewport_destroy( (void*)proj_[i] ); + + if( points ) + { + for( i = 0; i < 12000; i ++ ) + if( points[i]) free(points[i]); + free(points); + } + + d = NULL; +} + +int texmap_prepare(uint8_t *map[3], int width, int height) +{ + if(!static_bg ) + { + return 0; + } + + veejay_memcpy( static_bg, map[0], (width*height)); + + VJFrame tmp; + veejay_memset( &tmp, 0, sizeof(VJFrame)); + tmp.data[0] = static_bg; + tmp.width = width; + tmp.height = height; + softblur_apply( &tmp, width,height,0); + + veejay_msg(2, "Map B to A: Snapped background frame"); + return 1; +} + +static void binarify( uint8_t *bm, uint32_t *dst, uint8_t *bg, uint8_t *src,int threshold,int reverse, const int len ) +{ + int i; + if(!reverse) + { + for( i = 0; i < len; i ++ ) + { + if ( abs(bg[i] - src[i]) <= threshold ) + { dst[i] = 0; bm[i] = 0; } + else + { dst[i] = 1; bm[i] = 0xff; } + } + + } + else + { + for( i = 0; i < len; i ++ ) + { + if ( abs(bg[i] - src[i]) >= threshold ) + { dst[i] = 0; bm[i] = 0; } + else + { dst[i] = 1; bm[i] = 0xff; } + + } + } +} + +static void texmap_centroid() +{ + +} + +static int bg_frame_ = 0; + + + +void texmap_apply(void *ed, VJFrame *frame, + VJFrame *frame2, int width, int height, + int threshold, int reverse,int mode, int feather, int min_blob_weight) +{ + + unsigned int i,j,k; + const uint32_t len = frame->len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + uint32_t cx[256]; + uint32_t cy[256]; + uint32_t xsize[256]; + uint32_t ysize[256]; + + float sx = (float) width / (float) dw_; + float sy = (float) height / (float) dh_; + float sw = (float) sqrt( sx * sy ); + + int packets = 0; + + veejay_memset( cx,0,sizeof(cx)); + veejay_memset( cy,0,sizeof(cy)); + + veejay_memset( xsize,0,sizeof(xsize)); + veejay_memset( ysize,0,sizeof(ysize)); + + texmap_data *ud = (texmap_data*) ed; + + if( bg_frame_ > 0 && bg_frame_ < 4 ) + { + for( i = 0 ; i < len ; i ++ ) + { + static_bg[i] = (static_bg[i] + Y[i] ) >> 1; + } + bg_frame_ ++; + return; + } + + //@ clear distance transform map + veejay_memset( dt_map, 0 , len * sizeof(uint32_t) ); + + //@ todo: optimize with mmx + binarify( ud->bitmap, ud->data, static_bg, frame->data[0], threshold, reverse,len ); + + if(mode==1) + { + //@ show difference image in grayscale + veejay_memcpy( Y, ud->bitmap, len ); + veejay_memset( Cb, 128, len ); + veejay_memset( Cr, 128, len ); + return; + } + + //@ calculate distance map + veejay_distance_transform( ud->data, width, height, dt_map ); + + if( mode ==3 ) + { + //@ process dt map + for( i = 0; i < len ;i ++ ) + { + if( dt_map[ i ] >= feather ) + { + Y[i] = Y2[i]; + Cb[i] = Cb2[i]; + Cr[i] = Cr2[i]; + } + else + { + Y[i] = 0; + Cb[i] = 128; + Cr[i] = 128; + } + } + return; + } + + to_shrink_.data[0] = ud->bitmap; + shrinked_.data[0] = ud->current; + + uint32_t blobs[255]; + + veejay_memset( blobs, 0, sizeof(blobs) ); + + yuv_convert_and_scale_grey( shrink_, &to_shrink_, &shrinked_ ); + + uint32_t labels = veejay_component_labeling_8(dw_,dh_, shrinked_.data[0], blobs, cx,cy,xsize,ysize, + min_blob_weight); + + + + if (mode == 2 ) + { + //@ show dt map as grayscale image, intensity starts at 128 + for( i = 0; i < len ; i ++ ) + { + if( dt_map[i] == feather ) + Y[i] = 0xff; //@ border white + else if( dt_map[i] > feather ) { + Y[i] = 128 + (dt_map[i] % 128); //grayscale value + } else if ( dt_map[i] == 1 ) { + Y[i] = 0xff; + } else { + Y[i] = 0; //@ black (background) + } + Cb[i] = 128; + Cr[i] = 128; + } + } + + int num_objects = 0; + for( i = 1; i <=labels; i ++ ) + if( blobs[i] ) + num_objects ++; + + //@ Iterate over blob's bounding boxes and extract contours + for( i = 1; i <= labels; i ++ ) + { + if( blobs[i] > 0 ) + { + int nx = cx[i] * sx; + int ny = cy[i] * sy; + int size_x = xsize[i] * sx; + int size_y = ysize[i] * sy * 0.5; + + int x1 = nx - size_x; + int y1 = ny - size_y; + int x2 = nx + size_y; + int y2 = ny + size_y; + + int n_points = 0; + int dx1 = 0, dy1=0; + int center = 0; + + if( x1 < 0 ) x1 = 0; else if ( x1 > width ) x1 = width; + if( x2 < 0 ) x2 = 0; else if ( x2 > width ) x2 = width; + if( y1 < 0 ) y1 = 0; else if ( y1 >= height ) y1 = height -1; + if( y2 < 0 ) y2 = 0; else if ( y2 >= height ) y2 = height -1; + + for( k = y1; k < y2; k ++ ) + { + for( j = x1; j < x2; j ++ ) + { + if( dt_map[ (k* width + j) ] > center ) + { + center = dt_map[ (k*width+j) ]; + dx1 = j; + dy1 = k; + } + if( dt_map[ (k * width + j) ] == feather ) + { + points[n_points]->x = j; //@ produces unsorted list of coordinates + points[n_points]->y = k; + n_points++; + if( n_points >= 10000 ) + { + veejay_msg(0, "Too many points in contour"); + return; + } + } + } + } + } + } + + veejay_memset( Y, 0 , len ); + veejay_memset( Cb, 128, len ); + veejay_memset( Cr, 128, len ); + + for( i = 1; i <= labels; i ++ ) + { + if( blobs[i] > 0 ) + { + int radius = (int) ( 0.5 + sqrt( sw * blobs[i]) ); + int nx = cx[i] * sx; + int ny = cy[i] * sy; + int size_x = xsize[i] * sx; + int size_y = ysize[i] * sy * 0.5; // over size in x axis + + if( mode != 4 && ( abs( nx - x_[i] ) > 10 || abs( ny - y_[i] ) > 10 ) ) + //if( mode!=4 && cx[i] != x_[i] || cy[i] != y_[i] || !proj_[i]) + { + x_[i] = nx; + y_[i] = ny; + + int x1 = nx - size_x; + int y1 = ny - size_y; + int x2 = nx + size_x; + int y2 = ny + size_y; + + if( x1 < 0 ) x1 = 0; else if ( x1 > width ) x1 = width; + if( x2 < 0 ) x2 = 0; else if ( x2 > width ) x2 = width; + if( y1 < 0 ) y1 = 0; else if ( y1 >= height ) y1 = height -1; + if( y2 < 0 ) y2 = 0; else if ( y2 >= height ) y2 = height -1; + + if((void*) proj_[i]) + viewport_destroy( (void*)proj_[i] ); + proj_[i] = (void*)viewport_fx_init_map( width,height, + x1, + y1, + x2, + y1, + x2, + y2, + x1, + y2 ); + if(!proj_[i]) + return; + } + + if( mode == 4 ) + { + viewport_line( Y, nx - size_x, ny - size_y , + nx + size_x, ny - size_y , + width, height, 0xff ); + + viewport_line( Y, nx - size_x, ny - size_y , + nx - size_x, ny + size_y , + width, height, 0xff ); + + viewport_line( Y, nx + size_x, ny - size_y , + nx + size_x, ny + size_y , + width, height, 0xff ); + + viewport_line( Y, nx - size_x, ny + size_y, + nx + size_x, ny + size_y , + width, height, 128 ); + } + else + { + viewport_process_dynamic_map( (void*)proj_[i], frame2->data, frame->data, dt_map, feather ); + packets++; + } + } + } + +} + + + + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/texmap.h b/branches/V-1.5.3/veejay-server/libvje/effects/texmap.h new file mode 100644 index 00000000..5c9abe7e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/texmap.h @@ -0,0 +1,35 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TMAPEFFECT_H +#define TMAPEFFECT_H +#include +#include +#include + +vj_effect *texmap_init(int width, int height); +void texmap_free(void *d); +int texmap_malloc(void **c, int w, int h); +int texmap_prepare(uint8_t *map[3], int w, int h); +void texmap_apply(void *d , VJFrame *frame, + VJFrame *frame2, int width, int height, + int th, int reverse, int show, int feather, int blob); +void texmap_destroy(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/threshold.c b/branches/V-1.5.3/veejay-server/libvje/effects/threshold.c new file mode 100644 index 00000000..4c53d88b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/threshold.c @@ -0,0 +1,313 @@ +/* + * Linux VeeJay + * + * Copyright(C)2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "threshold.h" +#include "common.h" +#include "softblur.h" + +typedef int (*morph_func)(uint8_t *kernel, uint8_t mt[9] ); + +vj_effect *threshold_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; // threshold + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; // reverse + ve->limits[1][1] = 1; + + ve->defaults[0] = 40; + ve->defaults[1] = 0; + ve->description = "Map B from threshold mask"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Threshold", "Reverse" ); + return ve; +} + + +static uint8_t *binary_img; +#define RUP8(num)(((num)+8)&~8) + +int threshold_malloc(int w, int h ) +{ + binary_img = (uint8_t*) vj_malloc(sizeof(uint8_t) * RUP8(w * h) ); + if(!binary_img) return 0; + return 1; +} + +void threshold_free(void) +{ + if(binary_img) + free(binary_img); + binary_img = NULL; +} + +#ifndef MIN +#define MIN(a,b) ( (a)>(b) ? (b) : (a) ) +#endif +#ifndef MAX +#define MAX(a,b) ( (a)>(b) ? (a) : (b) ) +#endif + +static int _dilate_kernel3x3( uint8_t *kernel, uint8_t img[9]) +{ + register int x; + /* consider all background pixels (0) in input image */ + for(x = 0; x < 9; x ++ ) + if((kernel[x] * img[x]) > 0 ) + return 1; + return 0; +} + +#ifdef HAVE_ASM_MMX +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW ) +#define HAVE_K6_2PLUS +#endif + +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif + +static inline void load_binary_map( uint8_t *mask ) +{ + __asm __volatile( + "movq (%0), %%mm0\n\t" + :: "r" (mask) + ); +} + +static inline void map_luma( uint8_t *dst, uint8_t *B ) +//static inline void map_luma( uint8_t *dst, uint8_t *B, uint8_t *mask ) +{ + __asm __volatile( + // "movq (%0), %%mm0\n\t" + "movq (%0), %%mm1\n\t" + "pand %%mm0, %%mm1\n\t" + "movq %%mm1, (%1)\n\t" + // :: "r" (mask), "r" (B), "r" (dst) + :: "r" (B) , "r" (dst) + ); +} + +static inline void load_chroma( uint8_t val ) +{ + uint8_t mask[8] = { val,val,val,val, val,val,val,val }; + uint8_t *m = &mask[0]; + + __asm __volatile( + "movq (%0), %%mm3\n\t # mm3: 128,128,128,128, ..." + :: "r" (m) + ); +} + +static inline void map_chroma( uint8_t *dst, uint8_t *B ) +{ + __asm __volatile( + "movq (%0), %%mm1\n\t" + "pand %%mm0, %%mm1\n\t" + "pxor %%mm5, %%mm5\n\t" + "pcmpeqb %%mm1,%%mm5\n\t" + "pand %%mm3,%%mm5\n\t" + "paddb %%mm5,%%mm1\n\t" + "movq %%mm1, (%1) \n\t" + :: "r" (B), "r" (dst) + ); + +} + +static void load_threshold_mm7(uint8_t v) +{ + uint8_t mm[8] = { v,v,v,v, v,v,v,v }; + uint8_t *m = (uint8_t*) &(mm[0]); + __asm __volatile( + "movq (%0), %%mm7\n\t" + :: "r" (m) ); +} + +static void binarify( uint8_t *dst, uint8_t *src, uint8_t threshold, int reverse,int w, int h ) +{ + int len = (w * h)>>3; + int i; + uint8_t *s = src; + uint8_t *d = dst; + load_threshold_mm7( threshold ); + + + uint8_t *p = dst; + + for( i = 0; i < len ; i ++ ) + { + __asm __volatile( + "movq (%0),%%mm0\n\t" + "pcmpgtb %%mm7,%%mm0\n\t" + "movq %%mm0,(%1)\n\t" + :: "r" (s), "r" (d) + ); + s += 8; + d += 8; + } + + if( reverse ) + { + __asm __volatile( + "pxor %%mm4,%%mm4" :: + ); + for( i = 0; i < len ; i ++ ) + { + __asm __volatile( + "movq (%0), %%mm0\n\t" + "pcmpeqb %%mm4, %%mm0\n\t" + "movq %%mm0, (%1)\n\t" + :: "r" (p), "r" (p) + ); + p += 8; + } + } +} + + +#else +static void binarify( uint8_t *dst, uint8_t *src, int threshold,int reverse, int w, int h ) +{ + const int len = w*h; + int i; + if(!reverse) + for( i = 0; i < len; i ++ ) + { + dst[i] = ( src[i] <= threshold ? 0: 0xff ); + } + else + for( i = 0; i < len; i ++ ) + dst[i] = (src[i] > threshold ? 0: 0xff ); +} +#endif + +void threshold_apply( VJFrame *frame, VJFrame *frame2,int width, int height, int threshold, int reverse ) +{ + unsigned int i,x,y; + int len = (width * height); + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2=frame2->data[1]; + uint8_t *Cr2=frame2->data[2]; + + const uint8_t kernel[9] = { 1,1,1, 1,1,1, 1,1,1 }; + uint8_t *bmap = binary_img; + +// morph_func p = _dilate_kernel3x3; + + softblur_apply( frame, width,height,0 ); + + binarify( binary_img,Y,threshold,reverse, width,height); + +#ifdef HAVE_ASM_MMX + int work = (width*height)>>3; + load_chroma( 128 ); + for( y = 0 ; y < work; y ++ ) + { + load_binary_map( bmap ); + map_luma(Y , Y2 ); + map_chroma( Cb, Cb2 ); + map_chroma( Cr, Cr2 ); + //@ we could mmx-ify dilation + Y += 8; + Y2 += 8; + Cb += 8; + Cb2 += 8; + Cr += 8; + Cr2 +=8; + bmap += 8; + } + + __asm__ __volatile__ ( _EMMS:::"memory"); +#else + +// veejay_memset( Y, 0, width ); +// veejay_memset( Cb, 128, width ); +// veejay_memset( Cr, 128, width ); + +// veejay_memset(Y+(len-width),0, width ); +// veejay_memset(Cb+(len-width),128,width); +// veejay_memset(Cr+(len-width),128,width); + +// len -= width; + + if(!reverse) + { + for(y = 0; y < len; y += width ) + { + for(x = 0; x < width; x ++) + { + if(binary_img[x+y]) //@ found white pixel + { + Y[x+y] = Y2[x+y]; + Cb[x+y] = Cb2[x+y]; + Cr[x+y] = Cr2[x+y]; + + } + else //@ black + { + Y[x + y] = 0; + Cb[x + y] = 128; + Cr[x + y] = 128; + } + } + } + } + else + { + for(y = 0; y < len; y += width ) + { + for(x = 0; x < width; x ++) + { + if(binary_img[x+y] == 0x0) //@ found black pixel + { + Y[x+y] = Y2[x+y]; + Cb[x+y]= Cb2[x+y]; + Cr[x+y]= Cr2[x+y]; + } + else + { + Y[x+y] = 0x0; + Cb[x+y] = 128; + Cr[x+y] = 128; + } + } + } + } +#endif +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/threshold.h b/branches/V-1.5.3/veejay-server/libvje/effects/threshold.h new file mode 100644 index 00000000..c05203b3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/threshold.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef THRESHOLD_H +#define THRESHOLD_H +#include +#include +#include + +vj_effect *threshold_init(int w, int h); +void threshold_apply( VJFrame *frame,VJFrame *frame2, int width, int height, int t, int n); +int threshold_malloc(int w, int h); +void threshold_free(void); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/timedistort.c b/branches/V-1.5.3/veejay-server/libvje/effects/timedistort.c new file mode 100644 index 00000000..246f2ef1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/timedistort.c @@ -0,0 +1,238 @@ +/* + * Linux VeeJay + * + * EffecTV - Realtime Digital Video Effector + * Copyright (C) 2001-2006 FUKUCHI Kentaro + * + * TimeDistortionTV - scratch the surface and playback old images. + * Copyright (C) 2005 Ryo-ta + * + * Ported and arranged by Kentaro Fukuchi + + * Ported and modified by Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "timedistort.h" +#include "common.h" +#include "softblur.h" +#ifdef STRICT_CHECKING +#include +#endif +#define PLANES 32 +#define RUP8(num)(((num)+8)&~8) + +vj_effect *timedistort_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 5; + ve->limits[1][0] = 100; + ve->defaults[0] = 40; + ve->description = "TimeDistortionTV (EffectTV)"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Value"); + return ve; +} + +static int n__ = 0; +static int N__ = 0; +static uint8_t *nonmap = NULL; +static uint8_t *planes[3] = { NULL, NULL, NULL }; +static uint8_t *planetableY[PLANES]; +static uint8_t *planetableU[PLANES]; +static uint8_t *planetableV[PLANES]; + +static uint8_t *warptime[2]; +static int state = 0; +static int plane = 0; +static int warptimeFrame = 0; + +static int have_bg =0; +int timedistort_malloc( int w, int h ) +{ + unsigned int i; + if(nonmap) timedistort_free(); + nonmap = vj_malloc( RUP8(w + 2 * w * h) * sizeof(uint8_t)); + if(!nonmap) + return 0; + + planes[0] = vj_malloc( RUP8(PLANES * 3 * w * h) * sizeof(uint8_t)); + planes[1] = planes[0] + RUP8(PLANES * w * h ); + planes[2] = planes[1] + RUP8(PLANES * w * h ); + + veejay_memset( planes[0],0, RUP8(PLANES * w * h )); + veejay_memset( planes[1],128,RUP8(PLANES * w * h )); + veejay_memset( planes[2],128,RUP8(PLANES * w * h )); + + have_bg = 0; + n__ = 0; + N__ = 0; + + for( i = 0; i < PLANES; i ++ ) + { + planetableY[i] = &planes[0][ (w*h) * i ]; + planetableU[i] = &planes[1][ (w*h) * i ]; + planetableV[i] = &planes[2][ (w*h) * i ]; + } + + warptime[0] = (uint8_t*) vj_calloc( sizeof(uint8_t) * RUP8((w * h)+w+1) ); + warptime[1] = (uint8_t*) vj_calloc( sizeof(uint8_t) * RUP8((w * h)+w+1) ); + if( warptime[0] == NULL || warptime[1] == NULL ) + return 0; + + plane = 0; + state = 1; + + + return 1; +} + +void timedistort_free() +{ + if(nonmap) + free(nonmap); + if( planes[0]) + free(planes[0]); + if( warptime[0] ) + free(warptime[0]); + if( warptime[1] ) + free(warptime[1] ); + veejay_memset( planetableY, 0, PLANES); + veejay_memset( planetableU, 0, PLANES); + veejay_memset( planetableV, 0, PLANES); + planes[0] = NULL; + warptime[0] = NULL; + warptime[1] = NULL; + state = 0; + plane = 0; + nonmap = NULL; +} + +void timedistort_apply( VJFrame *frame, int width, int height, int val) +{ + unsigned int i; + const int len = (width * height); + + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + uint8_t *diff = nonmap; + uint8_t *prev = nonmap + len; + int interpolate = 1; + int motion = 0; + int tmp1,tmp2; + int stor_local = 0; + if(motionmap_active()) //@ use motion mapping frame + { + motionmap_scale_to( 255,255,1,1,&tmp1,&tmp2, &n__,&N__ ); + motion = 1; + diff = motionmap_bgmap(); + } + else + { + n__ = 0; + N__ = 0; + + if(!have_bg) + { + veejay_memcpy( prev, Y, len ); + VJFrame smooth; + veejay_memcpy(&smooth,frame, sizeof(VJFrame)); + smooth.data[0] = prev; + softblur_apply(&smooth, width, height, 0 ); + veejay_memset( diff, 0, len ); + have_bg = 1; + return; + } + else + { + for( i = 0; i < len ; i ++ ) + { + diff[i] = (abs(prev[i] - Y[i])> val ? 0xff: 0 ); + } + veejay_memcpy( prev, Y, len ); + VJFrame smooth; + veejay_memcpy(&smooth,frame, sizeof(VJFrame)); + smooth.data[0] = prev; + softblur_apply(&smooth, width, height, 0 ); + } + } + + if( n__ == N__ || n__ == 0 ) + interpolate = 0; + +#ifdef STRICT_CHECKING + assert( plane >= 0 && plane < PLANES ); +#endif + + //@ process + veejay_memcpy( planetableY[plane], Y, len ); + veejay_memcpy( planetableU[plane], Cb, len ); + veejay_memcpy( planetableV[plane], Cr, len ); + + uint8_t *p = warptime[ warptimeFrame ] + width + 1; + uint8_t *q = warptime[ warptimeFrame ^ 1] + width + 1; + + unsigned int x,y; + for( y = height - 2; y > 0 ; y -- ) + { + for( x = width - 2; x > 0; x -- ) + { + i = *(p - width) + *(p-1) + *(p+1) + *(p + width); + if( i > 3 ) i-= 3; + p++; + *q++ = i >> 2; + + } + p += 2; + q += 2; + } + q = warptime[ warptimeFrame ^ 1 ] + width + 1; + int n_plane = 0; + for( i = 0; i < len; i ++ ) + { + if( diff[i] ) { + q[i] = PLANES - 1; + } + + n_plane = ( plane - q[i] + PLANES ) & (PLANES-1); + + Y[i] = planetableY[ n_plane ][i]; + Cb[i] = planetableU[ n_plane ][i]; + Cr[i] = planetableV[ n_plane ][i]; + } + + plane ++; + plane = plane & (PLANES-1); + warptimeFrame ^= 1; + + if(interpolate) + motionmap_interpolate_frame( frame, N__,n__ ); + if(motion) + motionmap_store_frame(frame); + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/timedistort.h b/branches/V-1.5.3/veejay-server/libvje/effects/timedistort.h new file mode 100644 index 00000000..73376524 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/timedistort.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TIMEDISTORT_H +#define TIMEDISTORT_H +#include +#include +#include + +vj_effect *timedistort_init(int w, int h); +void timedistort_apply( VJFrame *frame, int width, int height, int val); +int timedistort_malloc(int w, int h); +void timedistort_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/tracer.c b/branches/V-1.5.3/veejay-server/libvje/effects/tracer.c new file mode 100644 index 00000000..eb605171 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/tracer.c @@ -0,0 +1,128 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "scratcher.h" +#include "common.h" + +static uint8_t *trace_buffer[3]; +static int trace_counter = 0; + +vj_effect *tracer_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 1; + ve->limits[1][1] = 25; + ve->defaults[0] = 150; + ve->defaults[1] = 8; + ve->description = "Tracer"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Opacity", "Buffer length"); + return ve; +} + +int tracer_malloc(int w, int h) +{ + trace_buffer[0] = (uint8_t *) vj_yuvalloc(w , h ); + if(!trace_buffer[0]) return 0; + trace_buffer[1] = trace_buffer[0] + ( w * h ); + trace_buffer[2] = trace_buffer[1] + ( w * h ); + + return 1; +} + +void tracer_free() { + if(trace_buffer[0]) + free(trace_buffer[0]); + trace_buffer[0] = NULL; + trace_buffer[1] = NULL; + trace_buffer[2] = NULL; +} + +void tracer_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int opacity, int n) +{ + + unsigned int x, len = frame->len; + unsigned int op1 = (opacity > 255) ? 255 : opacity; + unsigned int op0 = 255 - op1; + unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + if (trace_counter == 0) + { + for (x = 0; x < len; x++) + { + Y[x] = + limit_luma(func_opacity(Y[x], Y2[x], op0, op1)); + } + for (x = 0; x < uv_len; x++) + { + Cb[x] = + limit_chroma(func_opacity + (Cb[x], Cb2[x], op0, op1)); + Cr[x] = + limit_chroma(func_opacity + (Cr[x], Cr2[x], op0, op1)); + } + veejay_memcpy(trace_buffer[0], Y, len); + veejay_memcpy(trace_buffer[1], Cb, uv_len); + veejay_memcpy(trace_buffer[2], Cr, uv_len); + } + else + { + for (x = 0; x < len; x++) + { + Y[x] = + ((op0 * Y[x]) + (op1 * trace_buffer[0][x])) >> 8; // / 255; + } + for (x = 0; x < uv_len; x++) + { + Cb[x] = + ((op0 * Cb[x]) + (op1 * trace_buffer[1][x])) >> 8 ; // 255; + Cr[x] = + ((op0 * Cr[x]) + (op1 * trace_buffer[2][x])) >> 8 ; // 255; + } + veejay_memcpy(trace_buffer[0], Y, len); + veejay_memcpy(trace_buffer[1], Cb, uv_len); + veejay_memcpy(trace_buffer[2], Cr, uv_len); + + } + + trace_counter++; + if (trace_counter >= n) + trace_counter = 0; + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/tracer.h b/branches/V-1.5.3/veejay-server/libvje/effects/tracer.h new file mode 100644 index 00000000..549001d8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/tracer.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRACER_H +#define TRACER_H +#include +#include +#include +#include + +vj_effect *tracer_init(int w, int h); +int tracer_malloc(int w, int h); +void tracer_free(); +void tracer_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int opacity, int nframes); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/transform.c b/branches/V-1.5.3/veejay-server/libvje/effects/transform.c new file mode 100644 index 00000000..24918e7f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/transform.c @@ -0,0 +1,137 @@ + /* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "transform.h" +#include "common.h" + +vj_effect *transform_init(int width,int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 5; + //ve->defaults[1] = 1; + ve->limits[0][0] = 1; + ve->limits[1][0] = (height / 16); + + //ve->limits[0][1] = 1; + //ve->limits[1][1] = 4096; + + ve->description = "Transform Cubics"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Cubics"); + return ve; +} + +void transform_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, const int size) +{ + unsigned int ty, tx, y, x; + const unsigned int uv_height = frame->uv_height; + const unsigned int uv_width = frame->uv_width; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + + /* Luminance */ + for (y = 1; y < height; y++) + { + ty = y % size - (size >> 1); + if ((y / size) % 2) + { + ty = y - ty; + } + else + { + ty = y + ty; + } + if (ty < 0) + ty = 0; + + if (ty >= height) + ty = height - 1; + + for (x = 1; x < width; x++) + { + tx = x % size - (size >> 1); + if ((x / size) % 2) + { + tx = x - tx; + } + else + { + tx = x + tx; + } + if (tx < 0) + tx = 0; + if (tx >= width) + tx = width - 1; + Y[x + (y * width)] = Y2[(ty * width) + tx]; + } + } + /* Chroma */ + for (y = 1; y < uv_height; y++) + { + ty = y % size - (size >> 1); + if ((y / size) % 2) { + ty = y - ty; + } + else + { + ty = y + ty; + } + if (ty < 0) + ty = 0; + + if (ty >= uv_height) + ty = uv_height - 1; + + for (x = 1; x < uv_width; x++) + { + tx = x % size - (size >> 1); + if ((x / size) % 2) + { + tx = x - tx; + } + else + { + tx = x + tx; + } + if (tx < 0) + tx = 0; + if (tx >= uv_width) + tx = uv_width - 1; + Cb[x + (y * uv_width)] = Cb2[(ty * uv_width) + tx]; + Cr[x + (y * uv_width)] = Cr2[(ty * uv_width) + tx]; + } + } +} +void transform_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/transform.h b/branches/V-1.5.3/veejay-server/libvje/effects/transform.h new file mode 100644 index 00000000..4daf5b44 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/transform.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRANSFORM_H +#define TRANSFORM_H +#include +#include +#include + +vj_effect *transform_init(int w, int height); +void transform_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int size); +void transform_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/tripplicity.c b/branches/V-1.5.3/veejay-server/libvje/effects/tripplicity.c new file mode 100644 index 00000000..86d7246d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/tripplicity.c @@ -0,0 +1,91 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +/* + This effects overlays 2 images , + It allows the user to set the transparency per channel. + Result will vary over different color spaces. + + */ +#include +#include +#include +#include "tripplicity.h" +vj_effect *tripplicity_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; // opacity Y + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; // opacity Cb + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; // opacity Cr + ve->defaults[0] = 150; + ve->defaults[1] = 150; + ve->defaults[2] = 150; + + ve->description = "Normal Overlay (per Channel)"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + + ve->param_description = vje_build_param_list( ve->num_params, "Opacity Y", "Opacity Cb", "Opacity Cr" ); + + return ve; +} + + + +void tripplicity_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int opacityL, int opacityCb, int opacityCr) +{ + unsigned int i; + const unsigned int len = frame->len; + const unsigned int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + const uint8_t *Y2 = frame2->data[0]; + const uint8_t *Cb2= frame2->data[1]; + const uint8_t *Cr2= frame2->data[2]; + const uint8_t op1 = (opacityL > 255) ? 255 : opacityL; + const uint8_t op0 = 255 - op1; + const uint8_t opCb1= (opacityCb > 255) ? 255: opacityCb; + const uint8_t opCb0= 255 - opCb1; + const uint8_t opCr1= (opacityCr > 255) ? 255: opacityCr; + const uint8_t opCr0= 255 - opCr1; + + + for (i = 0; i < len; i++) + { + Y[i] = (op0 * Y[i] + op1 * Y2[i]) >> 8; + } + + for (i = 0; i < uv_len; i++) + { + Cb[i] = (opCb0 * Cb[i] + opCb1 * Cb2[i]) >> 8; + Cr[i] = (opCr0 * Cr[i] + opCr1 * Cr2[i]) >> 8; + } + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/tripplicity.h b/branches/V-1.5.3/veejay-server/libvje/effects/tripplicity.h new file mode 100644 index 00000000..415c7e5a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/tripplicity.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRCITY_H +#define TRCITY_H +#include +#include +#include + +vj_effect *tripplicity_init(); +void tripplicity_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int opacityL, int opacityCb, int opacityCr); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/uvcorrect.c b/branches/V-1.5.3/veejay-server/libvje/effects/uvcorrect.c new file mode 100644 index 00000000..dfb4aab1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/uvcorrect.c @@ -0,0 +1,204 @@ +/* + * Linux VeeJay + * + * Copyright(C)2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +/* + * yuvcorrect_functions.c + * Common functions between yuvcorrect and yuvcorrect_tune + * Copyright (C) 2002 Xavier Biquard + * + * 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 "uvcorrect.h" +#include "common.h" +#include + +static uint8_t *chrominance; + +vj_effect *uvcorrect_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 7; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + //angle,r,g,b,cbc,crc + + ve->limits[0][0] = 1; + ve->limits[1][0] = 360; + ve->limits[0][1] = 0; + ve->limits[1][1] = 255; + ve->limits[0][2] = 0; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 100; + ve->limits[0][4] = 0; + ve->limits[1][4] = 100; + ve->limits[0][5] = 0; + ve->limits[1][5] = 255; + ve->limits[0][6] = 0; + ve->limits[1][6] = 255; + + ve->defaults[0] = 1; + ve->defaults[1] = 128; + ve->defaults[2] = 128; + ve->defaults[3] = 10; + ve->defaults[4] = 10; + ve->defaults[5] = pixel_U_lo_; + ve->defaults[6] = pixel_U_hi_; + ve->description = "U/V Correction"; + ve->param_description = vje_build_param_list( ve->num_params, "Angle" ,"U Rotate Center", "V Rotate Center", + "Intensity U", "Intensity V", "Minimum UV", "Maximum UV"); + + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_help = 1; + ve->has_user = 0; +// FIXME: private + //chrominance = (uint8_t*) vj_calloc (sizeof(uint8_t) * 512 * 256 ); + + return ve; +} + +int uvcorrect_malloc(int w, int h ) +{ + chrominance = (uint8_t*) vj_malloc (sizeof(uint8_t) * 2 * 256 * 256 ); + if(!chrominance) return 0; + return 1; +} + +void uvcorrect_free() +{ + if(chrominance) free(chrominance); + chrominance= NULL; +} + +void uvcorrect_help() +{ + /*veejay_msg(1, "UV Correct (portion of yuvcorrect by Xavier Biquard"); + veejay_msg(1, "Select a color and set a new chroma value for the entire selection"); + veejay_msg(1, "one or both of the parameters p4 and p5"); + veejay_msg(1, "p0 = UV rotation angle"); + veejay_msg(1, "p1 = U rotate center"); + veejay_msg(1, "p2 = V rotate center"); + veejay_msg(1, "p3 = U factor"); + veejay_msg(1, "p4 = V factor"); + veejay_msg(1, "p5 = UV min"); + veejay_msg(1, "p6 = UV max"); */ +} + +static inline void _chrominance_treatment(uint8_t *u,uint8_t *v, const int len) +{ + uint8_t *Uu_c_p, *Vu_c_p; + uint32_t i, base; + + Uu_c_p = u; + Vu_c_p = v; + + // Chroma + for (i = 0; i < len; i++) + { + base = ((((uint32_t) * Uu_c_p) << 8) + (*Vu_c_p)) << 1; // base = ((((uint32_t)*Uu_c_p) * 256) + (*Vu_c_p)) * 2 + *(Uu_c_p++) = chrominance[base++]; + *(Vu_c_p++) = chrominance[base]; + } + +} + +void uvcorrect_apply(VJFrame *frame, int width, int height, int angle, int urot_center, int vrot_center, int iuFactor, int ivFactor, int uv_min, int uv_max ) +{ + float fU,fV,si,co; + uint16_t iU,iV; + + const float f_angle = (float) angle / 180.0 * M_PI; + const uint8_t centerU = urot_center; + const uint8_t centerV = vrot_center; + const float Ufactor = (float)iuFactor * 0.1; + const float Vfactor = (float)ivFactor * 0.1; + const uint32_t uv_len = frame->uv_len; + const uint8_t uvmin = (uint8_t) uv_min; + const uint8_t uvmax = (uint8_t) uv_max; + uint8_t *Uplane = frame->data[1]; + uint8_t *Vplane = frame->data[2]; + // chrominance vector + uint8_t *table = chrominance; + + sin_cos ( si, co, f_angle ); + + + for ( iU = 0; iU <= 255 ; iU ++ ) + { + for( iV = 0; iV <= 255; iV ++ ) + { + //U component + fU = (((float) (iU - centerU ) * Ufactor ) * co - + ((float) (iV - centerV ) * Vfactor ) * si) + + 128.0; + + fU = (float) floor( 0.5 + fU ); + + //clamp U values + if( fU < uvmin ) + { + fU = uvmin; + } + if( fU > uvmax ) + { + fU = uvmax; + } + //V component + + fV = (((float) ( iV - centerV) * Vfactor ) * co + + ((float) ( iU - centerU) * Ufactor ) * si ) + + 128.0; + + fV = (float) floor( 0.5 + fV ); + + //clamp V values + if( fV < uvmin ) + fV = uvmin; + if( fV > uvmax ) + fV = uvmax; + + //store in vector + *(table)++ = (uint8_t) fU; + *(table)++ = (uint8_t) fV; + } + } + + _chrominance_treatment( Uplane,Vplane , uv_len ); + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/uvcorrect.h b/branches/V-1.5.3/veejay-server/libvje/effects/uvcorrect.h new file mode 100644 index 00000000..715474d9 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/uvcorrect.h @@ -0,0 +1,33 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef UVCORRECT_H +#define UVCORRECT_H +#include +#include +#include + +vj_effect *uvcorrect_init(int w, int h); +int uvcorrect_malloc(int w, int h); +void uvcorrect_free(void); +void uvcorrect_apply(VJFrame *frame, int width, int height, + int alpha, int ualpha, int valpha, int uf, + int vf, int min, int max ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/videomask.c b/branches/V-1.5.3/veejay-server/libvje/effects/videomask.c new file mode 100644 index 00000000..9b7081b8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/videomask.c @@ -0,0 +1,100 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#include "videomask.h" +#include "../../config.h" +#include +#include "../subsample.h" +#include "common.h" + +vj_effect *videomask_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->defaults[0] = 150; /* threshold */ + ve->description = "Luminance Map"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Threshold"); + return ve; +} + + + +void videomask_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int videomask) +{ + unsigned int i, op0, op1; + const int len = frame->len; + const int uv_len = frame->uv_len; + const uint8_t pure_white_y = pixel_Y_hi_; + const uint8_t pure_white_c = pixel_U_hi_; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + + for (i = 0; i < len; i++) + { + op1 = Y[i]; + op0 = 255 - op1; + Y[i] = (op0 * Y[i] + op1 * pure_white_y)>>8; + } + + for (i = 0; i < uv_len; i++) + { + op1 = Cb[i]; + op0 = 255 - op1; + Cb[i] = (op0 * Cb[i] + op1 * pure_white_c)>>8; + op1 = Cb[i]; + op0 = 255 - op1; + Cr[i] = (op0 * Cr[i] + op1 * pure_white_c) >> 8; + } +} + + +/* + + 1. load 1st input reference to mm0 + 2. load 2nd input reference to mm1 + 3. Output reference to mm2 + 4. load op0 to mm7 + 5. load op1 to mm6 + 4. unpack byte 1st input to word on mm3 + 5. unpack byte 2nd input to word on mm4 + 6. multiply mm7 with mm3 + 7. multiply mm6 with mm4 + 8. add mm3 + mm4 + 9. shift rotate right with 8 ( / 256) + + + + +*/ +void videomask_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/videoplay.c b/branches/V-1.5.3/veejay-server/libvje/effects/videoplay.c new file mode 100644 index 00000000..66aed73c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/videoplay.c @@ -0,0 +1,260 @@ + +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "videoplay.h" +#include "common.h" + +vj_effect *videoplay_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 2; // divider + ve->limits[1][0] = max_power(w); + ve->limits[0][1] = 1; + ve->limits[1][1] = 250; // waterfall + ve->limits[0][2] = 0; + ve->limits[1][2] = 3; // mode + ve->defaults[0] = 2; + ve->defaults[1] = 1; + ve->defaults[2] = 1; + ve->description = "Videoplay (timestretched mosaic)"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Photos", "Waterfall", "Mode"); + return ve; +} + +static picture_t **video_list = NULL; +static int num_videos = 0; +static int frame_counter = 0; +static int frame_delay = 0; + +static int prepare_filmstrip(int film_length, int w, int h) +{ + int i,j; + int picture_width = w / sqrt(film_length); + int picture_height = h / sqrt(film_length); + + video_list = (picture_t**) vj_calloc(sizeof(picture_t*) * (film_length + 1) ); + if(!video_list) + return 0; + + num_videos = film_length; + + uint8_t val = 0; +// int inc = num_videos % 255; + + for ( i = 0; i < num_videos; i ++ ) + { + video_list[i] = vj_calloc(sizeof(picture_t)); + if(!video_list[i]) + return 0; + video_list[i]->w = picture_width; + video_list[i]->h = picture_height; + for( j = 0; j < 3; j ++ ) + { + video_list[i]->data[j] = vj_malloc(sizeof(uint8_t) * picture_width * picture_height ); + if(!video_list[i]->data[j]) + return 0; + veejay_memset(video_list[i]->data[j], (j==0 ? pixel_Y_lo_ : 128), picture_width *picture_height ); + } + // val+= inc; + } + frame_counter = 0; + + return 1; +} + +static void destroy_filmstrip(void) +{ + if(video_list) + { + int i = 0; + while(i < num_videos) + { + if( video_list[i] ) + { + int j; + for( j = 0; j < 3; j ++ ) + if(video_list[i]->data[j]) + free(video_list[i]->data[j]); + free(video_list[i]); + } + i++; + } + free(video_list); + } + video_list = NULL; + num_videos = 0; + frame_counter = 0; +} + + + +int videoplay_malloc(int w, int h ) +{ + num_videos = 0; + return 1; +} + + +void videoplay_free(void) +{ + destroy_filmstrip(); +} + +static void take_video( uint8_t *plane, uint8_t *dst_plane, int w, int h, int index ) +{ + + int x,y,dx,dy; + int sum; + int dst_x, dst_y; + int step_y; + int step_x; + int box_width = video_list[index]->w; + int box_height = video_list[index]->h; + + step_x = w / box_width; + step_y = h / box_height; + + for( y = 0 ,dst_y = 0; y < h && dst_y < box_height; y += step_y ) + { + for( x = 0, dst_x = 0; x < w && dst_x < box_width; x+= step_x ) + { + sum = 0; + for( dy = 0; dy < step_y; dy ++ ) + { + for( dx = 0; dx < step_x; dx++) + { + sum += plane[ ((y+dy)*w+(dx+x)) ]; + } + } + // still problem here! + if(sum > 0) + dst_plane[(dst_y*box_width)+dst_x] = sum / (step_y*step_x); + else + dst_plane[(dst_y*box_width)+dst_x] = pixel_Y_lo_; + + dst_x++; + } + dst_y++; + } +} + +static void put_video( uint8_t *dst_plane, uint8_t *video, int dst_w, int dst_h, int index , matrix_t matrix) +{ + int box_w = video_list[index]->w; + int box_h = video_list[index]->h; + int x,y; + + uint8_t *P = dst_plane + (matrix.h*dst_w); + int offset = matrix.w; + + for( y = 0; y < box_h; y ++ ) + { + for( x = 0; x < box_w; x ++ ) + { + *(P+offset+x) = video[(y*box_w)+x]; + } + P += dst_w; + } +} + +void videoplay_apply( VJFrame *frame, VJFrame *B, int width, int height, int size, int delay, int mode ) +{ + unsigned int i; + uint8_t *dstY = frame->data[0]; + uint8_t *dstU = frame->data[1]; + uint8_t *dstV = frame->data[2]; + + matrix_f matrix_placement = get_matrix_func(mode); + + if( (size*size) != num_videos || num_videos == 0 ) + { + destroy_filmstrip(); + if(!prepare_filmstrip(size*size, width,height)) + { + return; + } + frame_delay = delay; + } + + if( frame_delay ) + frame_delay --; + + if( frame_delay == 0) + { + frame_delay = delay; + } + + + if(frame_delay == delay) + { + for( i = 0; i < 3; i ++ ) + { + take_video( B->data[i], video_list[(frame_counter%num_videos)]->data[i], + width, height , frame_counter % num_videos); + } + for( i = 0; i < 3; i ++ ) + { + take_video( frame->data[i], video_list[((frame_counter+1)%num_videos)]->data[i], + width, height , (frame_counter+1) % num_videos); + } + } + else + { + int n = frame_counter - 1; + if(n>=0) + { + for( i = 0; i < 3; i ++ ) + { + take_video( frame->data[i], video_list[(n%num_videos)]->data[i], + width, height , frame_counter % num_videos); + } + n++; + for( i = 0; i < 3; i ++ ) + { + take_video( B->data[i], video_list[(n%num_videos)]->data[i], + width, height , (frame_counter+1) % num_videos); + } + } + } + + for ( i = 0; i < num_videos; i ++ ) + { + matrix_t m = matrix_placement(i, size,width,height ); + put_video( dstY, video_list[i]->data[0],width,height,i, m); + put_video( dstU, video_list[i]->data[1],width,height,i, m); + put_video( dstV, video_list[i]->data[2],width,height,i, m); + } + + if( frame_delay == delay) + frame_counter+=2; + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/videoplay.h b/branches/V-1.5.3/veejay-server/libvje/effects/videoplay.h new file mode 100644 index 00000000..773e793e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/videoplay.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef VIDEOPLAY_H +#define VIDEOPLAY_H +#include +#include +#include + +vj_effect *videoplay_init(int w, int h); +int videoplay_malloc(int w, int h); +void videoplay_free(void); +void videoplay_apply( VJFrame *frame, VJFrame *b,int width, int height, int size, int behaviour, int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/videowall.c b/branches/V-1.5.3/veejay-server/libvje/effects/videowall.c new file mode 100644 index 00000000..3e2bb507 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/videowall.c @@ -0,0 +1,255 @@ +/* + * Linux VeeJay + * + * Copyright(C)2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "videowall.h" +#include "common.h" +static inline int gcd(int p, int q ) { if(q==0) return p; else return(gcd(q,p%q)); } + +static inline int n_pics(int w, int h) +{ + return (( w / gcd(w,h)) * 2); +} + +vj_effect *videowall_init(int w, int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 0; // selector + ve->limits[1][0] = n_pics(w,h); + ve->limits[0][1] = 0; + ve->limits[1][1] = w; // displacement x + ve->limits[0][2] = 0; + ve->limits[1][2] = h; // displacement y + ve->limits[0][3] = 0; + ve->limits[1][3] = 1; // lock update of x,y in offset[selector] + ve->defaults[0] = 0; + ve->defaults[1] = 1; + ve->defaults[2] = 1; + ve->defaults[3] = 0; + ve->description = "VideoWall / Tile Placement"; + ve->sub_format = 1; // todo: optimize to work in 4:2:0/4:2:2, see also photo/video play.c + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Photos","X Displacement", "Y displacement", "Lock update"); + return ve; +} + +static picture_t **photo_list = NULL; +static int num_photos = 0; +static int frame_counter = 0; +static int frame_delay = 0; +static int *offset_table_x = NULL; +static int *offset_table_y = NULL; + + + + +static int prepare_filmstrip(int w, int h) +{ + int i,j; + int picture_width = gcd(w,h); + int picture_height = gcd(w,h); + int film_length = n_pics(w,h); + + photo_list = (picture_t**) vj_calloc(sizeof(picture_t*) * film_length ); + if(!photo_list) + return 0; + + num_photos = film_length; + + uint8_t val = 0; + int inc = num_photos % 255; + + for ( i = 0; i < num_photos; i ++ ) + { + photo_list[i] = vj_calloc(sizeof(picture_t)); + if(!photo_list[i]) + return 0; + photo_list[i]->w = picture_width; + photo_list[i]->h = picture_height; + for( j = 0; j < 3; j ++ ) + { + photo_list[i]->data[j] = vj_malloc(sizeof(uint8_t) * picture_width * picture_height ); + if(!photo_list[i]->data[j]) + return 0; + } + veejay_memset( photo_list[i]->data[0], 0, + picture_width * picture_height ); + veejay_memset( photo_list[i]->data[1],128, + picture_width * picture_height ); + veejay_memset( photo_list[i]->data[2],128, + picture_width * picture_height ); + val+= inc; + } + frame_counter = 0; + + offset_table_x = (int*) vj_calloc(sizeof(int) * film_length); + if(!offset_table_x) + return 0; + offset_table_y = (int*) vj_calloc(sizeof(int) * film_length); + if(!offset_table_y) + return 0; + + return 1; +} + +static void destroy_filmstrip(void) +{ + if(photo_list) + { + int i = 0; + while(i < num_photos) + { + if( photo_list[i] ) + { + int j; + for( j = 0; j < 3; j ++ ) + if(photo_list[i]->data[j]) + free(photo_list[i]->data[j]); + free(photo_list[i]); + } + i++; + } + free(photo_list); + } + photo_list = NULL; + num_photos = 0; + frame_counter = 0; + if(offset_table_x) free(offset_table_x); + if(offset_table_y) free(offset_table_y); +} + + + +int videowall_malloc(int w, int h ) +{ + prepare_filmstrip(w,h); + return 1; +} + + +void videowall_free(void) +{ + destroy_filmstrip(); +} + +static void take_photo( uint8_t *plane, uint8_t *dst_plane, int w, int h, int index ) +{ + int x,y,dx,dy; + int sum; + int dst_x, dst_y; + int step_y; + int step_x; + int box_width = photo_list[index]->w; + int box_height = photo_list[index]->h; + + step_x = w / box_width; + step_y = h / box_height; + + for( y = 0 ,dst_y = 0; y < h && dst_y < box_height; y += step_y ) + { + for( x = 0, dst_x = 0; x < w && dst_x < box_width; x+= step_x ) + { + sum = 0; + for( dy = 0; dy < step_y; dy ++ ) + { + for( dx = 0; dx < step_x; dx++) + { + sum += plane[ ((y+dy)*w+(dx+x)) ]; + } + } + // still problem here! + if(sum > 0) + dst_plane[(dst_y*box_width)+dst_x] = sum / (step_y*step_x); + else + dst_plane[(dst_y*box_width)+dst_x] = pixel_Y_lo_; + + dst_x++; + } + dst_y++; + } +} + +static void put_photo( uint8_t *dst_plane, uint8_t *photo, int dst_w, int dst_h, int index) +{ + int n = (num_photos/2); + int box_w = photo_list[index]->w; + int box_h = photo_list[index]->h; + int x,y; + // blits photos left -> right , < n ? :top : bottom + int dy = offset_table_y[index]; + int dx = offset_table_x[index]; + uint8_t *P = (index < n ? dst_plane + ( dy * dst_w ) : dst_plane + ((abs(dst_h-box_h-dy)%dst_h)*dst_w)); + int offset = (box_w * index + dx) % dst_w; + + for( y = 0 ; y < box_h ; y ++ ) + { + for( x = 0; x < box_w; x ++ ) + { + *(P + offset + x ) = photo[(y*box_h)+x]; + } + P += dst_w; + } +} + +static void scale_photo(uint8_t *dst_plane, uint8_t *src_plane, int dst_w, int dst_h) +{ +} + +void videowall_apply( VJFrame *frameA, VJFrame *frameB, int width, int height, int a,int b, int c, int d ) +{ + unsigned int i; + uint8_t *dstY = frameA->data[0]; + uint8_t *dstU = frameA->data[1]; + uint8_t *dstV = frameA->data[2]; + + if(d==0) + { + offset_table_x[a] = b; + offset_table_y[a] = c; + } + + for( i = 0; i < 3; i ++ ) + { + take_photo( frameA->data[i], photo_list[(frame_counter%num_photos)]->data[i], width, height , frame_counter % num_photos); + } + frame_counter++; + + for( i = 0; i < 3; i ++ ) + { + take_photo( frameB->data[i], photo_list[(frame_counter%num_photos)]->data[i], width, height , frame_counter % num_photos); + } + + for ( i = 0; i < num_photos; i ++ ) + { + put_photo( dstY, photo_list[i]->data[0],width,height,i); + put_photo( dstU, photo_list[i]->data[1],width,height,i); + put_photo( dstV, photo_list[i]->data[2],width,height,i); + } + frame_counter++; + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/videowall.h b/branches/V-1.5.3/veejay-server/libvje/effects/videowall.h new file mode 100644 index 00000000..c973a209 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/videowall.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef VIDEOWALL_H +#define VIDEOWALL_H +#include +#include +#include + +vj_effect *videowall_init(int w, int h); +int videowall_malloc(int w, int h); +void videowall_free(void); +void videowall_apply( VJFrame *frameA, VJFrame *frameB,int width, int height, + int a, int b , int c, int d); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/water.c b/branches/V-1.5.3/veejay-server/libvje/effects/water.c new file mode 100644 index 00000000..92ec48b6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/water.c @@ -0,0 +1,644 @@ +/* EffecTV - Realtime Digital Video Effektor + * Copyright (C) 2001-2003 FUKUCHI Kentaro + * + * RippleTV - Water ripple effect + * Copyright (C) 2001 - 2002 FUKUCHI Kentaro + * + * ported to Linux VeeJay by: + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +#include +#include +#include +#include +#include "rippletv.h" +#include "softblur.h" +#include +#include +#include +#include +#include "common.h" +#define RUP8(num)(((num)+8)&~8) + +typedef struct { + uint8_t *ripple_data[3]; + uint8_t *diff_img; + int stat; + signed char *vtable; + int *map; + int *map1; + int *map2; + int *map3; + int map_h; + int map_w; + int have_img; + int sqrtable[256]; + int point; + int impact; + int last_fresh_rate; + int loopnum; + int lastmode; + unsigned int wfastrand_val; +} water_t; + +/*static uint8_t *ripple_data[3]; +static int stat; +static signed char *vtable; +static int *map; +static int *map1, *map2, *map3; +static int map_h, map_w; +static uint8_t *diff_img = NULL; +static int have_img = 0; +static int sqrtable[256]; +static const int point = 16; +static const int impact = 2; +//static const int loopnum = 2; +static int bgIsSet = 0; +*/ + +/* from EffecTV: + * fastrand - fast fake random number generator + * Warning: The low-order bits of numbers generated by fastrand() + * are bad as random numbers. For example, fastrand()%4 + * generates 1,2,3,0,1,2,3,0... + * You should use high-order bits. + */ + +unsigned int wfastrand(water_t *w) +{ + return (w->wfastrand_val=w->wfastrand_val*1103515245+12345); +} + +static void setTable(water_t *w) +{ + int i; + + for(i=0; i<128; i++) { + w->sqrtable[i] = i*i; + } + + for(i=1; i<=128; i++) { + w->sqrtable[256-i] = -i*i; + } +} +//easy/calm: 10,2,32 +//flimmerin: 10,2,3 +//flowing: 10,1,29 +//p2 = wave speed +// + +vj_effect *water_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 3600; + ve->limits[0][1] = 1; + ve->limits[1][1] = 16; + ve->limits[0][2] = 1; + ve->limits[1][2] = 31; //number of waves + ve->limits[0][3] = 0; + ve->limits[1][3] = 6; // mode + ve->limits[0][4] = 0; + ve->limits[1][4] = 255; // threshold + ve->defaults[0] = 10; + ve->defaults[1] = 1; + ve->defaults[2] = 10; + ve->defaults[3] = 1; + ve->defaults[4] = 45; + ve->description = "Water ripples"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 1; + ve->user_data = NULL; + + ve->param_description= vje_build_param_list(ve->num_params, "Refresh Frequency", + "Wavespeed", "Decay", "Mode", "Threshold (motion)"); + + return ve; +} +#define HIS_LEN (8*25) +#define HIS_DEFAULT 2 + +static uint32_t histogram_[HIS_LEN]; +static int n__ = 0; +static uint32_t keyv_ = 0; +static uint32_t keyp_ = 0; +int water_malloc(void **d, int width, int height) +{ + *d = (void*) vj_calloc(sizeof(water_t)); + water_t *w = (water_t*) *d; + + w->ripple_data[0] = (uint8_t*)vj_calloc(sizeof(uint8_t) * RUP8(width * height)); + if(!w->ripple_data[0]) return 0; + + w->diff_img = (uint8_t*)vj_calloc(sizeof(uint8_t) * RUP8(width * height * 2)); + if(!w->diff_img) return 0; + + w->map_h = height / 2 + 1; + w->map_w = width / 2 + 1; + + w->map = (int*) vj_calloc (sizeof(int) * RUP8( w->map_h * w->map_w * 3)); + if(!w->map) return 0; + + w->vtable = (signed char*) vj_calloc( sizeof(signed char) * RUP8(w->map_w * w->map_h * 2)); + if(!w->vtable) return 0; + + w->map3 = w->map + w->map_w * w->map_h * 2; + + setTable(w); + + w->map1 = w->map; + w->map2 = w->map + w->map_h*w->map_w; + w->stat = 1; + w->point = 16; + w->impact = 2; + w->loopnum = 2; + + return 1; +} + +void water_free(void *ud) { + + water_t *w = (water_t*) ud; + if(w) { + if(w->ripple_data[0]) free(w->ripple_data[0]); + if(w->map) free(w->map); + if(w->diff_img) free(w->diff_img); + if(w->vtable) free(w->vtable); + free(w); + } + w = NULL; +} + + +static inline void drop(water_t *w,int power) +{ + int x, y; + int *p, *q; + + x = wfastrand(w)%(w->map_w-4)+2; + y = wfastrand(w)%(w->map_h-4)+2; + p = w->map1 + y*w->map_w + x; + q = w->map2 + y*w->map_w + x; + *p = power; + *q = power; + *(p-w->map_w) = *(p-1) = *(p+1) = *(p+w->map_w) = power/2; + *(p-w->map_w-1) = *(p-w->map_w+1) = *(p+w->map_w-1) = *(p+w->map_w+1) = power/4; + *(q-w->map_w) = *(q-1) = *(q+1) = *(q+w->map_w) = power/2; + *(q-w->map_w-1) = *(q-w->map_w+1) = *(q+w->map_w-1) = *(p+w->map_w+1) = power/4; +} + +static void drawmotionframe( VJFrame *f , water_t *w ) +{ + veejay_memset( f->data[1], 128, f->uv_len ); + veejay_memset( f->data[2], 128, f->uv_len ); + veejay_memcpy( f->data[0], w->diff_img, f->width * f->height ); +} + +static int globalactivity(VJFrame *f2, water_t *w, int in) +{ + int len = (f2->width * f2->height)/4; + uint32_t sum = 0,min=0xffff,max=0; + uint64_t activity_level1 = 0; + uint64_t activity_level2 = 0; + uint64_t activity_level3 = 0; + uint64_t activity_level4 = 0; + uint8_t *binary_img = w->diff_img; + int i = 0; + for( i = 0; i < len; i += 4 ) + { + + activity_level1 += binary_img[i]; + activity_level2 += binary_img[i+1]; + activity_level3 += binary_img[i+2]; + activity_level4 += binary_img[i+3]; + } + uint32_t activity_level = ( (activity_level1>>8) + (activity_level2>>8) + (activity_level3>>8) + (activity_level4>>8)); + + int current_his_len = 8; + + histogram_[ (n__%current_his_len) ] = activity_level; + + for( i = 0; i < current_his_len; i ++ ) + { + sum += histogram_[i]; + if(histogram_[i] > max ) max = histogram_[i]; + if(histogram_[i] < min ) min = histogram_[i]; + } + if( (n__ % current_his_len)==0 ) + { + keyp_ = keyv_; + keyv_ = (sum > 0 ? (sum/current_his_len):0 ); + } + + if( n__ <= 1 ) + return in; + + int tmp = (( n__ - 1) % current_his_len) + 1; + float q = 1.0f/(float) current_his_len * tmp; + float diff = (float) keyv_ - (float) keyp_; + float pu = keyp_ + ( q* diff); + float wu = 1.0f/31; + float pw = wu * pu; + + int res = (30 * pw); + if( res < 1 ) + return 1; + return res; +} + +static void motiondetect(VJFrame *f, VJFrame *f2, int threshold, water_t *w) +{ + uint8_t *bg = w->diff_img + (f->width * f->height); + uint8_t *in = f2->data[0]; + if(!w->have_img) + { + //softblur_apply( f2,f->width,f->height,0); + veejay_memcpy(bg, f2->data[0], f->width * f->height ); + w->have_img = 1; + return; + } + + int i,len= f->width * f->height; + uint8_t pp1; + for(i = 0; i < len ; i ++ ) { + pp1 = abs(bg[i] - in[i]); + if(pp1 > threshold ) { + w->diff_img[i] = pp1; + } else { + w->diff_img[i] = 0; +// (w->diff_img[i] + 0)>>1; + } + } + + int *p = w->map1 + w->map_w + 1; + int *q = w->map2 + w->map_w + 1; + int width = f->width; + int x,y,h; + uint8_t *d = w->diff_img + width + 2; + for( y = w->map_h - 2; y > 0 ; y -- ) { + for( x = w->map_w - 2 ; x > 0 ; x -- ) { + h = (int) *d + (int) *(d+1) + (int) *(d+width) + (int) *(d+width+1); + if(h>0) { + *p = h << ( w->point + w->impact - 8 ); + *q = *p; + } + p ++; q ++; + d += 2; + } + d += width + 2; + p += 2; + q += 2; + } + +} + + +static void motiondetect2(VJFrame *f, VJFrame *f2, int threshold, water_t *w) +{ + uint8_t *bg = w->diff_img + (f->width * f->height); + uint8_t *in = f2->data[0]; + if(!w->have_img) + { + softblur_apply( f2,f->width,f->height,0); + veejay_memcpy(bg, f2->data[0], f->width * f->height ); + w->have_img = 1; + return; + } + + int i,len= f->width * f->height; + uint8_t pp1; + for(i = 0; i < len ; i ++ ) { + pp1 = abs(bg[i] - in[i]); + if(pp1 > threshold ) { + w->diff_img[i] = 0xff-pp1; + } else { + w->diff_img[i] = 0; +// (w->diff_img[i] + 0)>>1; + } + } + + int *p = w->map1 + w->map_w + 1; + int *q = w->map2 + w->map_w + 1; + int width = f->width; + int x,y,h; + uint8_t *d = w->diff_img + width + 2; + for( y = w->map_h - 2; y > 0 ; y -- ) { + for( x = w->map_w - 2 ; x > 0 ; x -- ) { + h = (int) *d + (int) *(d+1) + (int) *(d+width) + (int) *(d+width+1); + if(h>0) { + *p = h << ( w->point + w->impact - 8 ); + *q = *p; + } + p ++; q ++; + d += 2; + } + d += width + 2; + p += 2; + q += 2; + } + +} + + +static void motiondetect3(VJFrame *f, VJFrame *f2, int threshold, water_t *w) +{ + uint8_t *bg = w->diff_img + (f->width * f->height); + uint8_t *in = f2->data[0]; + if(!w->have_img) + { + softblur_apply( f2,f->width,f->height,0); + veejay_memcpy(bg, f2->data[0], f->width * f->height ); + w->have_img = 1; + return; + } + + int i,len= f->width * f->height; + uint8_t pp1; + for(i = 0; i < len ; i ++ ) { + pp1 = abs(bg[i] - in[i]); + if(pp1 < threshold ) { + w->diff_img[i] = pp1; + } else { + w->diff_img[i] = 0; + // (w->diff_img[i] + 0)>>1; + } + } + + int *p = w->map1 + w->map_w + 1; + int *q = w->map2 + w->map_w + 1; + int width = f->width; + int x,y,h; + uint8_t *d = w->diff_img + width + 2; + for( y = w->map_h - 2; y > 0 ; y -- ) { + for( x = w->map_w - 2 ; x > 0 ; x -- ) { + h = (int) *d + (int) *(d+1) + (int) *(d+width) + (int) *(d+width+1); + if(h>0) { + *p = h << ( w->point + w->impact - 8 ); + *q = *p; + } + p ++; q ++; + d += 2; + } + d += width + 2; + p += 2; + q += 2; + } + +} + + +static void raindrop(water_t *w) +{ + static int period = 0; + static int rain_stat = 0; + static unsigned int drop_prob = 0; + static int drop_prob_increment = 0; + static int drops_per_frame_max = 0; + static int drops_per_frame = 0; + static int drop_power = 0; + + int i; + + if(period == 0) { + switch(rain_stat) { + case 0: + period = (wfastrand(w)>>23)+100; + drop_prob = 0; + drop_prob_increment = 0x00ffffff/period; + drop_power = (-(wfastrand(w)>>28)-2)<point; + drops_per_frame_max = 2<<(wfastrand(w)>>30); // 2,4,8 or 16 + rain_stat = 1; + break; + case 1: + drop_prob = 0x00ffffff; + drops_per_frame = 1; + drop_prob_increment = 1; + period = (drops_per_frame_max - 1) * 16; + rain_stat = 2; + break; + case 2: + period = (wfastrand(w)>>22)+1000; + drop_prob_increment = 0; + rain_stat = 3; + break; + case 3: + period = (drops_per_frame_max - 1) * 16; + drop_prob_increment = -1; + rain_stat = 4; + break; + case 4: + period = (wfastrand(w)>>24)+60; + drop_prob_increment = -(drop_prob/period); + rain_stat = 5; + break; + case 5: + default: + period = (wfastrand(w)>>23)+500; + drop_prob = 0; + rain_stat = 0; + break; + } + } + switch(rain_stat) { + default: + case 0: + break; + case 1: + case 5: + if((wfastrand(w)>>8)0; i--) { + drop(w,drop_power); + } + drops_per_frame += drop_prob_increment; + break; + } + period--; +} + +void water_apply(void *user_data, VJFrame *frame, VJFrame *frame2, int width, int height, int fresh_rate, int loopnum, int decay, int mode, int threshold ) +{ + int x, y, i; + int dx, dy; + int h, v; + int wi, hi; + int *p, *q, *r; + signed char *vp; + uint8_t *src,*dest; + const int len = frame->len; + int dummy = 0; + water_t *w = (water_t*) user_data; + + if(w->last_fresh_rate != fresh_rate) + { + w->last_fresh_rate = fresh_rate; + veejay_memset( w->map, 0, (w->map_h*w->map_w*2*sizeof(int))); + } + if(w->lastmode != mode ) + { + veejay_memset( w->map, 0, (w->map_h*w->map_w*2*sizeof(int))); + w->have_img = 0; + w->lastmode = mode; + } + veejay_memcpy ( w->ripple_data[0],frame->data[0],len); + + dest = frame->data[0]; + src = w->ripple_data[0]; + + + w->loopnum = loopnum; + + switch(mode) { + case 0: raindrop(w); w->have_img = 0; break; + case 1: + motiondetect(frame,frame2,threshold,w); + drawmotionframe(frame,w); + return; + case 2: motiondetect(frame,frame2,threshold,w); + break; + case 3: + motiondetect2(frame,frame2,threshold,w); + drawmotionframe(frame,w); + return; + break; + case 4: + motiondetect2(frame,frame2,threshold,w); + break; + case 5: + motiondetect3(frame,frame2,threshold,w); + drawmotionframe(frame,w); + return; + case 6: + motiondetect3(frame,frame2,threshold,w); + break; + default: + break; + } + + /* simulate surface wave */ + wi = w->map_w; + hi = w->map_h; + + /* This function is called only 30 times per second. To increase a speed + * of wave, iterates this loop several times. */ + for(i=w->loopnum; i>0; i--) { + /* wave simulation */ + p = w->map1 + wi + 1; + q = w->map2 + wi + 1; + r = w->map3 + wi + 1; + for(y=hi-2; y>0; y--) { + for(x=wi-2; x>0; x--) { + h = *(p-wi-1) + *(p-wi+1) + *(p+wi-1) + *(p+wi+1) + + *(p-wi) + *(p-1) + *(p+1) + *(p+wi) - (*p)*9; + h = h >> 3; + v = *p - *q; + v += h - (v >> decay); + *r = v + *p; + p++; + q++; + r++; + } + p += 2; + q += 2; + r += 2; + } + + /* low pass filter */ + p = w->map3 + wi + 1; + q = w->map2 + wi + 1; + for(y=hi-2; y>0; y--) { + for(x=wi-2; x>0; x--) { + h = *(p-wi) + *(p-1) + *(p+1) + *(p+wi) + (*p)*60; + *q = h >> 6; + p++; + q++; + } + p+=2; + q+=2; + } + + p = w->map1; + w->map1 = w->map2; + w->map2 = p; + } + + vp = w->vtable; + p = w->map1; + for(y=hi-1; y>0; y--) { + for(x=wi-1; x>0; x--) { + /* difference of the height between two voxel. They are twiced to + * emphasise the wave. */ + vp[0] = w->sqrtable[((p[0] - p[1])>>(w->point-1))&0xff]; + vp[1] = w->sqrtable[((p[0] - p[wi])>>(w->point-1))&0xff]; + p++; + vp+=2; + } + p++; + vp+=2; + } + + hi = height; + wi = width; + vp = w->vtable; + + for(y=0; y=wi) dx=wi-1; + if(dy>=hi) dy=hi-1; + dest[0] = src[dy*wi+dx]; + + i = dx; + + dx = x + 1 + (h+(int)vp[2])/2; + if(dx<0) dx=0; + if(dx>=wi) dx=wi-1; + dest[1] = src[dy*wi+dx]; + + dy = y + 1 + (v+(int)vp[w->map_w*2+1])/2; + if(dy<0) dy=0; + if(dy>=hi) dy=h-1; + dest[wi] = src[dy*wi+i]; + + dest[wi+1] = src[dy*wi+dx]; + dest+=2; + vp+=2; + } + dest += wi; + vp += 2; + } + + +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/waterrippletv.c b/branches/V-1.5.3/veejay-server/libvje/effects/waterrippletv.c new file mode 100644 index 00000000..9a256e5a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/waterrippletv.c @@ -0,0 +1,370 @@ +/* EffecTV - Realtime Digital Video Effektor + * Copyright (C) 2001-2003 FUKUCHI Kentaro + * + * RippleTV - Water ripple effect + * Copyright (C) 2001 - 2002 FUKUCHI Kentaro + * + * ported to Linux VeeJay by: + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + + +#include +#include +#include +#include +#include "rippletv.h" +#include +#include +#include "common.h" +#define RUP8(num)(((num)+8)&~8) + +static uint8_t *ripple_data[3]; + +static int stat; +static signed char *vtable; +static int *map; +static int *map1, *map2, *map3; +static int map_h, map_w; +static int sqrtable[256]; +static const int point = 16; +static const int impact = 2; +//static const int decay = 8; +//static const int loopnum = 2; +static int bgIsSet = 0; +static int tick = 0; + +/* from EffecTV: + * fastrand - fast fake random number generator + * Warning: The low-order bits of numbers generated by fastrand() + * are bad as random numbers. For example, fastrand()%4 + * generates 1,2,3,0,1,2,3,0... + * You should use high-order bits. + */ +static unsigned int wfastrand_val; + +static unsigned int wfastrand() +{ + return (wfastrand_val=wfastrand_val*1103515245+12345); +} + +static void setTable() +{ + int i; + + for(i=0; i<128; i++) { + sqrtable[i] = i*i; + } + for(i=1; i<=128; i++) { + sqrtable[256-i] = -i*i; + } +} + + + +vj_effect *waterrippletv_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 3; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->limits[0][0] = 1; + ve->limits[1][0] = 3600; + ve->limits[0][1] = 1; + ve->limits[1][1] = 16; + ve->limits[0][2] = 1; + ve->limits[1][2] = 32; + ve->defaults[0] = 25*60; + ve->defaults[1] = 1; + ve->defaults[2] = 8; + ve->description = "RippleTV (EffectTV)"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Refresh Frequency", "Wavespeed", "Decay" ); +return ve; +} + +int waterrippletv_malloc(int width, int height) +{ + ripple_data[0] = (uint8_t*)vj_malloc(sizeof(uint8_t) * RUP8(width * height)); + if(!ripple_data[0]) return 0; + veejay_memset( ripple_data[0], pixel_Y_lo_, width*height); + + map_h = height / 2 + 1; + map_w = width / 2 + 1; + map = (int*) vj_calloc (sizeof(int) * RUP8(map_h * map_w * 3)); + if(!map) return 0; + vtable = (signed char*) vj_calloc( sizeof(signed char) * RUP8(map_w * map_h * 2)); + if(!vtable) return 0; + map3 = map + map_w * map_h * 2; + setTable(); + map1 = map; + map2 = map + map_h*map_w; + stat = 1; + + return 1; +} + +void waterrippletv_free() { + if(ripple_data[0]) free(ripple_data[0]); + if(map) free(map); + if(vtable) free(vtable); +} + + +static inline void drop(int power) +{ + int x, y; + int *p, *q; + x = wfastrand()%(map_w-4)+2; + y = wfastrand()%(map_h-4)+2; + p = map1 + y*map_w + x; + q = map2 + y*map_w + x; + *p = power; + *q = power; + *(p-map_w) = *(p-1) = *(p+1) = *(p+map_w) = power/2; + *(p-map_w-1) = *(p-map_w+1) = *(p+map_w-1) = *(p+map_w+1) = power/4; + *(q-map_w) = *(q-1) = *(q+1) = *(q+map_w) = power/2; + *(q-map_w-1) = *(q-map_w+1) = *(q+map_w-1) = *(p+map_w+1) = power/4; +} + +static void raindrop() +{ + static int period = 0; + static int rain_stat = 0; + static unsigned int drop_prob = 0; + static int drop_prob_increment = 0; + static int drops_per_frame_max = 0; + static int drops_per_frame = 0; + static int drop_power = 0; + + int i; + + if(period == 0) { + switch(rain_stat) { + case 0: + period = (wfastrand()>>23)+100; + drop_prob = 0; + drop_prob_increment = 0x00ffffff/period; + drop_power = (-(wfastrand()>>28)-2)<>30); // 2,4,8 or 16 + rain_stat = 1; + break; + case 1: + drop_prob = 0x00ffffff; + drops_per_frame = 1; + drop_prob_increment = 1; + period = (drops_per_frame_max - 1) * 16; + rain_stat = 2; + break; + case 2: + period = (wfastrand()>>22)+1000; + drop_prob_increment = 0; + rain_stat = 3; + break; + case 3: + period = (drops_per_frame_max - 1) * 16; + drop_prob_increment = -1; + rain_stat = 4; + break; + case 4: + period = (wfastrand()>>24)+60; + drop_prob_increment = -(drop_prob/period); + rain_stat = 5; + break; + case 5: + default: + period = (wfastrand()>>23)+500; + drop_prob = 0; + rain_stat = 0; + break; + } + } + switch(rain_stat) { + default: + case 0: + break; + case 1: + case 5: + if((wfastrand()>>8)0; i--) { + drop(drop_power); + } + drops_per_frame += drop_prob_increment; + break; + } + period--; +} + +static int last_fresh_rate = 0; +void waterrippletv_apply(VJFrame *frame, int width, int height, int fresh_rate, int loopnum, int decay) +{ + int x, y, i; + int dx, dy; + int h, v; + int wi, hi; + int *p, *q, *r; + signed char *vp; + uint8_t *src,*dest; + const int len = frame->len; + + if(last_fresh_rate != fresh_rate || tick > fresh_rate) + { + last_fresh_rate = fresh_rate; + veejay_memset( map, 0, (map_h*map_w*2*sizeof(int))); + tick = 0; + } + + tick ++; + veejay_memcpy ( ripple_data[0], frame->data[0],len); + + dest = frame->data[0]; + src = ripple_data[0]; + + /* impact from the motion or rain drop */ + raindrop(); + + /* simulate surface wave */ + wi = map_w; + hi = map_h; + + /* This function is called only 30 times per second. To increase a speed + * of wave, iterates this loop several times. */ + for(i=loopnum; i>0; i--) { + /* wave simulation */ + p = map1 + wi + 1; + q = map2 + wi + 1; + r = map3 + wi + 1; + for(y=hi-2; y>0; y--) { + for(x=wi-2; x>0; x--) { + h = *(p-wi-1) + *(p-wi+1) + *(p+wi-1) + *(p+wi+1) + + *(p-wi) + *(p-1) + *(p+1) + *(p+wi) - (*p)*9; + h = h >> 3; + v = *p - *q; + v += h - (v >> decay); + *r = v + *p; + p++; + q++; + r++; + } + p += 2; + q += 2; + r += 2; + } + + /* low pass filter */ + p = map3 + wi + 1; + q = map2 + wi + 1; + for(y=hi-2; y>0; y--) { + for(x=wi-2; x>0; x--) { + h = *(p-wi) + *(p-1) + *(p+1) + *(p+wi) + (*p)*60; + *q = h >> 6; + p++; + q++; + } + p+=2; + q+=2; + } + + p = map1; + map1 = map2; + map2 = p; + } + + vp = vtable; + p = map1; + for(y=hi-1; y>0; y--) { + for(x=wi-1; x>0; x--) { + /* difference of the height between two voxel. They are twiced to + * emphasise the wave. */ + vp[0] = sqrtable[((p[0] - p[1])>>(point-1))&0xff]; + vp[1] = sqrtable[((p[0] - p[wi])>>(point-1))&0xff]; + p++; + vp+=2; + } + p++; + vp+=2; + } + + hi = height; + wi = width; + vp = vtable; + +/* dest2 = dest; + p = map1; + for(y=0; y>(point-5))+128; + if(h < 0) h = 0; + if(h > 255) h = 255; + dest[0] = h; + dest[1] = h; + dest[wi] = h; + dest[wi+1] = h; + p++; + dest+=2; + vp+=2; + } + dest += width; + vp += 2; + p++; + } + +*/ + + + for(y=0; y=wi) dx=wi-1; + if(dy>=hi) dy=hi-1; + dest[0] = src[dy*wi+dx]; + + i = dx; + + dx = x + 1 + (h+(int)vp[2])/2; + if(dx<0) dx=0; + if(dx>=wi) dx=wi-1; + dest[1] = src[dy*wi+dx]; + + dy = y + 1 + (v+(int)vp[map_w*2+1])/2; + if(dy<0) dy=0; + if(dy>=hi) dy=h-1; + dest[wi] = src[dy*wi+i]; + + dest[wi+1] = src[dy*wi+dx]; + dest+=2; + vp+=2; + } + dest += wi; + vp += 2; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/waterrippletv.h b/branches/V-1.5.3/veejay-server/libvje/effects/waterrippletv.h new file mode 100644 index 00000000..a8d87f08 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/waterrippletv.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef WARIPPLETV_H +#define WARIPPLETV_H +#include +#include +#include +#include + +vj_effect* waterrippletv_init(int width, int height); +int waterrippletv_malloc(int w, int h); +void waterrippletv_free(); +void waterrippletv_apply(VJFrame *frame, int width, int height, int val, int loop, int decay); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/whiteframe.c b/branches/V-1.5.3/veejay-server/libvje/effects/whiteframe.c new file mode 100644 index 00000000..b356ee1f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/whiteframe.c @@ -0,0 +1,74 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "whiteframe.h" + +vj_effect *whiteframe_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 0; + ve->defaults = NULL; /* default values */ + ve->limits[0] = NULL; /* min */ + ve->limits[1] = NULL; /* max */ + ve->description = "Replace Pure White";; + ve->extra_frame = 1; + ve->sub_format = 0; + ve->has_user = 0; + ve->param_description = NULL; + return ve; +} + +/* this method was created for magic motion */ +void whiteframe_apply( VJFrame *frame, VJFrame *frame2, int width, + int height) +{ + unsigned int i; + const int len = frame->len; + const int uv_len = frame->uv_len; + uint8_t p; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + /* look for white pixels in luminance channel and swap with yuv2 */ + for (i = 0; i < len; i++) + { + p = Y[i]; + if (p >= 235) + { + Y[i] = Y2[i]; + } + } + + for (i = 0; i < uv_len; i++) + { + p = Cb[i]; + if (p == 128) + { + Cb[i] = Cb2[i]; + Cr[i] = Cr2[i]; + } + } +} +void whitereplace_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/whiteframe.h b/branches/V-1.5.3/veejay-server/libvje/effects/whiteframe.h new file mode 100644 index 00000000..ec399d8c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/whiteframe.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef WHITEFRAME_H +#define WHITEFRAME_H +#include +#include +#include + +vj_effect *whiteframe_init(); + +void whiteframe_apply(VJFrame *frame, VJFrame *frame2, int width, + int height ); +void whiteframe_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/widthmirror.c b/branches/V-1.5.3/veejay-server/libvje/effects/widthmirror.c new file mode 100644 index 00000000..c3dc0cac --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/widthmirror.c @@ -0,0 +1,98 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "widthmirror.h" +#include +#include +vj_effect *widthmirror_init(int max_width,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 1; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 2; + + ve->limits[0][0] = 2; + ve->limits[1][0] = max_width; + + ve->description = "Width Mirror"; + ve->sub_format = 0; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Widths"); + return ve; +} + +void widthmirror_apply(VJFrame *frame, int width, int height, + int width_div) +{ + unsigned int r, c; + const int len = frame->len; + const int uv_len = frame->uv_len; + const int uv_width = frame->uv_width; + const int uv_width_div = width_div; + int p1; + uint8_t x1, x2, x3; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + if (width_div >= width || width_div < 2) + width_div = 2; + + for (r = width; r < len; r += width) { + unsigned int divisor = width / width_div; + for (c = 0; c < width; c++) { + if (divisor - c < 0) + p1 = c - divisor + r; + else + p1 = divisor - c + r; + x1 = Y[c + r]; + Y[p1] = x1; + Y[width - c + r] = x1; + } + } + for (r = uv_width; r < uv_len; r += uv_width) { + unsigned int divisor = uv_width / uv_width_div; + for (c = 0; c < uv_width; c++) { + if (divisor - c < 0) + p1 = c - divisor + r; + else + p1 = divisor - c + r; + + x2 = Cb[c + r]; + Cb[p1] = x2; + Cb[uv_width - c + r] = x2; + + x3 = Cr[c + r]; + Cr[p1] = x3; + Cr[uv_width - c + r] = x3; + + } + } + + + + + +} +void widthmirror_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/widthmirror.h b/branches/V-1.5.3/veejay-server/libvje/effects/widthmirror.h new file mode 100644 index 00000000..bd2e740d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/widthmirror.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef WIDTHMIRROR_H +#define WIDTHMIRROR_H +#include +#include +#include + +vj_effect *widthmirror_init(int max_width, int h); +void widthmirror_apply(VJFrame *frame, int width, int height, int div); +void widthmirror_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/zoom.c b/branches/V-1.5.3/veejay-server/libvje/effects/zoom.c new file mode 100644 index 00000000..b7c2da66 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/zoom.c @@ -0,0 +1,100 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include +#include + +vj_effect *zoom_init(int width , int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = width/2; + ve->defaults[1] = height/2; + ve->defaults[2] = 50; + ve->defaults[3] = 1; + + ve->limits[0][0] = 0; + ve->limits[1][0] = width; + + ve->limits[0][1] = 0; + ve->limits[1][1] = height; + + ve->limits[0][2] = 10; + ve->limits[1][2] = 100; + + ve->limits[0][3] = 0; + ve->limits[1][3] = 1; + + ve->description = "Zoom"; + ve->sub_format = 1; + ve->extra_frame = 0; + ve->has_user = 0; + ve->param_description = vje_build_param_list( ve->num_params, "Width", "Height", "Factor", "Mode" ); + return ve; +} +static int zoom_[4] = { 0,0,0,0 }; +static void *zoom_vp_ = NULL; + +static uint8_t *zoom_private_[3]; + +int zoom_malloc(int width, int height) +{ + zoom_private_[0] = (uint8_t*) vj_yuvalloc( width,height ); + if(!zoom_private_[0] ) + return 0; + zoom_private_[1] = zoom_private_[0] + (width*height); + zoom_private_[2] = zoom_private_[1] + (width*height); + return 1; +} + +void zoom_free() { + if( zoom_private_[0] ) + free(zoom_private_[0] ); + if( zoom_vp_ ) + viewport_destroy( zoom_vp_ ); + zoom_vp_ = NULL; +} + +void zoom_apply( VJFrame *frame, int width, int height, int x, int y, int factor, int dir) +{ + if( zoom_[0] != x || zoom_[1] != y || zoom_[2] != factor || !zoom_vp_ || dir != zoom_[3]) + { + if( zoom_vp_ ) + viewport_destroy( zoom_vp_ ); + zoom_vp_ = viewport_fx_init( VP_QUADZOOM, width,height,x,y,factor, dir ); + if(!zoom_vp_ ) + return; + zoom_[0] = x; zoom_[1] = y; zoom_[2] = factor; zoom_[3] = dir; + } + + veejay_memcpy( zoom_private_[0], frame->data[0], (width*height)); + veejay_memcpy( zoom_private_[1], frame->data[1], (width*height)); + veejay_memcpy( zoom_private_[2], frame->data[2], (width*height)); + + viewport_process_dynamic( zoom_vp_, zoom_private_, frame->data ); + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/effects/zoom.h b/branches/V-1.5.3/veejay-server/libvje/effects/zoom.h new file mode 100644 index 00000000..fd55ed2d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/effects/zoom.h @@ -0,0 +1,33 @@ + +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef ZOOM_H +#define ZOOM_H +#include +#include +#include + +vj_effect *zoom_init(int width, int height); +int zoom_malloc(int w, int h); +void zoom_free(); +void zoom_apply(VJFrame *frame, int width, + int height, int x_offset, int y_offset, int factor, int dir); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/internal.h b/branches/V-1.5.3/veejay-server/libvje/internal.h new file mode 100644 index 00000000..a4dcc869 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/internal.h @@ -0,0 +1,612 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJE_INTERNAL_H +#define VJE_INTERNAL_H + +#define VJE_MAX_ARGS 10 +#define VJE_INVALID_ARGS -1 +#define VJE_NEED_INIT -2 +#define VJE_NO_FRAMES -3 +#define VJE_SUCCESS 0 +#include + +enum { + VJ_EFFECT_LUM_RED = 65, + VJ_EFFECT_LUM_BLUE = 35, + VJ_EFFECT_LUM_WHITE = 235, + VJ_EFFECT_LUM_BLACK = 16, + VJ_EFFECT_LUM_YELLOW = 162, + VJ_EFFECT_LUM_CYAN = 131, + VJ_EFFECT_LUM_GREEN = 112, + VJ_EFFECT_LUM_MAGNETA = 84, +}; + +enum { + VJ_EFFECT_CB_RED = 100, + VJ_EFFECT_CB_WHITE = 128, + VJ_EFFECT_CB_YELLOW = 44, + VJ_EFFECT_CB_CYAN = 156, + VJ_EFFECT_CB_MAGNETA = 184, + VJ_EFFECT_CB_BLUE = 212, + VJ_EFFECT_CB_GREEN = 72, + VJ_EFFECT_CB_BLACK = 128, +}; + +enum { + VJ_EFFECT_CR_RED = 212, + VJ_EFFECT_CR_WHITE = 128, + VJ_EFFECT_CR_YELLOW = 142, + VJ_EFFECT_CR_CYAN = 44, + VJ_EFFECT_CR_MAGNETA = 198, + VJ_EFFECT_CR_BLUE = 114, + VJ_EFFECT_CR_GREEN = 58, + VJ_EFFECT_CR_BLACK = 128, +}; + +enum { + VJ_EFFECT_COLOR_YELLOW = 7, + VJ_EFFECT_COLOR_RED = 6, + VJ_EFFECT_COLOR_BLUE = 5, + VJ_EFFECT_COLOR_MAGNETA = 4, + VJ_EFFECT_COLOR_CYAN = 3, + VJ_EFFECT_COLOR_GREEN = 2, + VJ_EFFECT_COLOR_BLACK = 1, + VJ_EFFECT_COLOR_WHITE = 0, +}; + +enum { + /* video effects */ + VJ_VIDEO_EFFECT_OVERLAYMAGIC = 201, + VJ_VIDEO_EFFECT_LUMAMAGICK = 202, + VJ_VIDEO_EFFECT_DIFF = 203, + VJ_VIDEO_EFFECT_OPACITY = 204, + VJ_VIDEO_EFFECT_LUMAKEY = 205, + VJ_VIDEO_EFFECT_RGBKEY = 206, + VJ_VIDEO_EFFECT_CHROMAMAGICK = 207, + VJ_VIDEO_EFFECT_LUMABLEND = 208, + VJ_VIDEO_EFFECT_SPLIT = 209, + VJ_VIDEO_EFFECT_BORDERS = 210, + VJ_VIDEO_EFFECT_FRAMEBORDER = 211, + VJ_VIDEO_EFFECT_SLIDINGDOOR = 212, + VJ_VIDEO_EFFECT_TRANSOP = 213, + VJ_VIDEO_EFFECT_CAROT = 214, + VJ_VIDEO_EFFECT_LINE = 215, + VJ_VIDEO_EFFECT_TRANSBLEND = 216, + VJ_VIDEO_EFFECT_FADECOLOR = 217, + VJ_VIDEO_EFFECT_FADECOLORRGB = 218, + VJ_VIDEO_EFFECT_WHITEFRAME = 219, + //VJ_VIDEO_EFFECT_DIFFIMG = 220, + VJ_VIDEO_EFFECT_MASK = 220, + VJ_VIDEO_EFFECT_THRESHOLDSMOOTH = 221, + VJ_VIDEO_EFFECT_THRESHOLD = 222, + VJ_VIDEO_EFFECT_RGBKEYSMOOTH = 223, + VJ_VIDEO_EFFECT_WIPE = 224, + VJ_VIDEO_EFFECT_TRACER = 225, + VJ_VIDEO_EFFECT_MTRACER = 226, + VJ_VIDEO_EFFECT_DUPMAGIC = 227, + VJ_VIDEO_EFFECT_KEYSELECT = 228, + VJ_VIDEO_EFFECT_COMPLEXTHRESHOLD = 229, + VJ_VIDEO_EFFECT_COMPLEXSYNC = 230, + VJ_VIDEO_EFFECT_3BAR = 231, + VJ_VIDEO_EFFECT_VBAR = 232, + VJ_VIDEO_EFFECT_LUMAMASK = 233, + VJ_VIDEO_EFFECT_BINARYOVERLAY = 234, + VJ_VIDEO_EFFECT_DISSOLVE = 235, + VJ_VIDEO_EFFECT_TRIPPLICITY = 236, + VJ_VIDEO_EFFECT_VIDEOPLAY = 237, + VJ_VIDEO_EFFECT_VIDEOWALL = 238, + VJ_VIDEO_EFFECT_EXTTHRESHOLD = 239, + VJ_VIDEO_EFFECT_EXTDIFF = 240, + VJ_VIDEO_EFFECT_PICINPIC = 241, + VJ_VIDEO_EFFECT_CHAMBLEND = 242, + VJ_VIDEO_EFFECT_RADIOACTIVE = 243, + VJ_VIDEO_EFFECT_TEXMAP = 244, + VJ_VIDEO_EFFECT_RIPPLETV = 245, + VJ_VIDEO_EFFECT_SLICER = 246, + VJ_VIDEO_EFFECT_IRIS = 247, +}; + +enum { + /* image effects */ + VJ_IMAGE_EFFECT_MIRROR = 101, + VJ_IMAGE_EFFECT_MIRRORS = 102, + VJ_IMAGE_EFFECT_WIDTHMIRROR = 103, + VJ_IMAGE_EFFECT_FLIP = 104, + VJ_IMAGE_EFFECT_POSTERIZE = 105, + VJ_IMAGE_EFFECT_NEGATION = 106, + VJ_IMAGE_EFFECT_SOLARIZE = 107, + VJ_IMAGE_EFFECT_COLORADJUST = 108, + VJ_IMAGE_EFFECT_GAMMA = 109, + VJ_IMAGE_EFFECT_SOFTBLUR = 110, + VJ_IMAGE_EFFECT_REVTV = 111, + VJ_IMAGE_EFFECT_DICES = 112, + VJ_IMAGE_EFFECT_SMUCK = 113, + VJ_IMAGE_EFFECT_KILLCHROMA = 114, + VJ_IMAGE_EFFECT_EMBOSS = 115, + VJ_IMAGE_EFFECT_DITHER = 116, + VJ_IMAGE_EFFECT_RAWMAN = 117, + VJ_IMAGE_EFFECT_RAWVAL = 118, + VJ_IMAGE_EFFECT_TRANSFORM = 119, + VJ_IMAGE_EFFECT_FIBDOWNSCALE = 120, + VJ_IMAGE_EFFECT_REFLECTION = 121, + VJ_IMAGE_EFFECT_ROTOZOOM = 122, + VJ_IMAGE_EFFECT_COLORSHIFT = 123, + VJ_IMAGE_EFFECT_SCRATCHER = 124, + VJ_IMAGE_EFFECT_MAGICSCRATCHER = 125, + VJ_IMAGE_EFFECT_CHROMASCRATCHER = 126, + VJ_IMAGE_EFFECT_DISTORTION = 127, + VJ_IMAGE_EFFECT_GREYSELECT = 128, + VJ_IMAGE_EFFECT_BWSELECT = 129, + VJ_IMAGE_EFFECT_COMPLEXINVERT = 130, + VJ_IMAGE_EFFECT_COMPLEXSATURATE = 131, + VJ_IMAGE_EFFECT_ISOLATE = 132, + VJ_IMAGE_EFFECT_ENHANCEMASK = 133, + VJ_IMAGE_EFFECT_NOISEADD = 134, + VJ_IMAGE_EFFECT_CONTRAST = 135, + VJ_IMAGE_EFFECT_MOTIONBLUR = 136, + VJ_IMAGE_EFFECT_SINOIDS = 137, + VJ_IMAGE_EFFECT_AVERAGE = 138, + VJ_IMAGE_EFFECT_RIPPLE = 139, + VJ_IMAGE_EFFECT_BATHROOM = 140, + VJ_IMAGE_EFFECT_SLICE = 141, + VJ_IMAGE_EFFECT_ZOOM = 142, + VJ_IMAGE_EFFECT_DEINTERLACE = 144, + VJ_IMAGE_EFFECT_CROSSPIXEL = 145, + VJ_IMAGE_EFFECT_COLORTEST = 146, + VJ_IMAGE_EFFECT_DIFF = 147, + VJ_IMAGE_EFFECT_NOISEPENCIL = 148, + VJ_IMAGE_EFFECT_RIPPLETV = 149, + VJ_IMAGE_EFFECT_PENCILSKETCH = 143, + VJ_IMAGE_EFFECT_BGSUBTRACT = 150, + VJ_IMAGE_EFFECT_MAGICMIRROR = 151, + VJ_IMAGE_EFFECT_PIXELSMEAR = 152, + VJ_IMAGE_EFFECT_RASTER = 153, + VJ_IMAGE_EFFECT_FISHEYE = 154, + VJ_IMAGE_EFFECT_SWIRL = 155, + VJ_IMAGE_EFFECT_RADIALBLUR = 156, + VJ_IMAGE_EFFECT_CHROMIUM = 157, + VJ_IMAGE_EFFECT_CHROMAPALETTE = 158, + VJ_IMAGE_EFFECT_UVCORRECT = 159, + VJ_IMAGE_EFFECT_OVERCLOCK = 160, + VJ_IMAGE_EFFECT_CARTONIZE = 161, + VJ_IMAGE_EFFECT_NERVOUS = 162, + VJ_IMAGE_EFFECT_MORPHOLOGY = 163, + VJ_IMAGE_EFFECT_VIDBLOB = 164, + VJ_IMAGE_EFFECT_VIDBOIDS = 165, + VJ_IMAGE_EFFECT_GHOST = 166, + VJ_IMAGE_EFFECT_NEIGHBOUR = 167, + VJ_IMAGE_EFFECT_NEIGHBOUR2= 168, + VJ_IMAGE_EFFECT_NEIGHBOUR3= 169, + VJ_IMAGE_EFFECT_NEIGHBOUR4= 170, + VJ_IMAGE_EFFECT_NEIGHBOUR5= 171, + VJ_IMAGE_EFFECT_CUTSTOP = 172, + VJ_IMAGE_EFFECT_MASKSTOP = 173, + VJ_IMAGE_EFFECT_PHOTOPLAY = 174, + VJ_IMAGE_EFFECT_FLARE = 175, + VJ_IMAGE_EFFECT_CONSTANTBLEND = 176, + VJ_IMAGE_EFFECT_COLORMAP = 177, + VJ_IMAGE_EFFECT_NEGATECHANNEL = 178, + VJ_IMAGE_EFFECT_COLMORPH = 179, + VJ_IMAGE_EFFECT_COLFLASH = 180, + VJ_IMAGE_EFFECT_RGBCHANNEL = 181, + VJ_IMAGE_EFFECT_AUTOEQ = 182, + VJ_IMAGE_EFFECT_COLORHIS = 183, + VJ_IMAGE_EFFECT_MOTIONMAP = 184, + VJ_IMAGE_EFFECT_TIMEDISTORT = 185, + VJ_IMAGE_EFFECT_CHAMELEON = 186, + VJ_IMAGE_EFFECT_BALTANTV = 187, + VJ_IMAGE_EFFECT_CONTOUR = 188, + VJ_IMAGE_EFFECT_LENSCORRECTION = 189, + VJ_IMAGE_EFFECT_CALI = 190, + VJ_IMAGE_EFFECT_MEDIANFILTER = 191, + VJ_IMAGE_EFFECT_DUMMY=100, +}; + +#define VJ_IMAGE_EFFECT_MIN 100 +#define VJ_IMAGE_EFFECT_MAX 192 + +#define VJ_VIDEO_EFFECT_MIN 200 +#define VJ_VIDEO_EFFECT_MAX 248 + +#define VJ_VIDEO_COUNT (VJ_VIDEO_EFFECT_MAX - VJ_VIDEO_EFFECT_MIN) + +#define VJ_EXT_EFFECT 500 + +/* luma blend types */ +enum { + VJ_EFFECT_BLEND_ADDITIVE = 1, + VJ_EFFECT_BLEND_SUBSTRACTIVE = 2, + VJ_EFFECT_BLEND_MULTIPLY = 3, + VJ_EFFECT_BLEND_DIVIDE = 4, + VJ_EFFECT_BLEND_LIGHTEN = 5, + VJ_EFFECT_BLEND_HARDLIGHT = 6, + VJ_EFFECT_BLEND_DIFFERENCE = 7, + VJ_EFFECT_BLEND_DIFFNEGATE = 8, + VJ_EFFECT_BLEND_EXCLUSIVE = 9, + VJ_EFFECT_BLEND_BASECOLOR = 10, + VJ_EFFECT_BLEND_FREEZE = 11, + VJ_EFFECT_BLEND_UNFREEZE = 12, + VJ_EFFECT_BLEND_RELADD = 13, + VJ_EFFECT_BLEND_RELSUB = 14, + VJ_EFFECT_BLEND_MAXSEL = 15, + VJ_EFFECT_BLEND_MINSEL = 16, + VJ_EFFECT_BLEND_RELADDLUM = 17, + VJ_EFFECT_BLEND_RELSUBLUM = 18, + VJ_EFFECT_BLEND_MINSUBSEL = 19, + VJ_EFFECT_BLEND_MAXSUBSEL = 20, + VJ_EFFECT_BLEND_ADDSUBSEL = 21, + VJ_EFFECT_BLEND_ADDAVG = 22, + VJ_EFFECT_BLEND_ADDTEST2 = 23, + VJ_EFFECT_BLEND_ADDTEST3 = 24, + VJ_EFFECT_BLEND_ADDTEST4 = 25, + VJ_EFFECT_BLEND_MULSUB = 26, + VJ_EFFECT_BLEND_SOFTBURN = 27, + VJ_EFFECT_BLEND_INVERSEBURN = 28, + VJ_EFFECT_BLEND_COLORDODGE = 29, + VJ_EFFECT_BLEND_ADDDISTORT = 30, + VJ_EFFECT_BLEND_SUBDISTORT = 31, + +}; +extern void tripplicity_apply(VJFrame *frame1,VJFrame *frame2, int w, int h, + int a, int b, int c ); + +extern void dices_apply(void * data, VJFrame *frame, int width, + int height, int cube_bits); +extern void dither_apply( VJFrame *frame, int width, int height, int size, + int n); +extern void emboss_apply( VJFrame *frame, int width, int height, int n); +extern void fibdownscale_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int n); +extern void _fibdownscale_apply(VJFrame *frame, VJFrame *frame2, + int width, int height); +extern void _fibrectangle_apply(VJFrame *frame, VJFrame *frame2, + int width, int height); +extern void flip_apply( VJFrame *frame, int width, int height, int n); +extern void killchroma_apply(VJFrame *frame, int width, int height, + int n); +extern void lumamagic_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int n, int op_a, int op_b + ); +extern void overlaymagic_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int n, int m); +extern void mirrors_apply( VJFrame *frame, int width, int height, + int type, int factor); +extern void mirrors2_apply( VJFrame *frame, int width, int height, + int type); +extern void negation_apply( VJFrame *frame, int width, int height, + int val); +extern void medianfilter_apply( VJFrame *frame, int width, int height, + int val); + +extern void negatechannel_apply( VJFrame *frame, int width, int height, + int chan, int val); + +extern void colormap_apply( VJFrame *frame, int width, int height, + int r, int g, int b); +extern void opacity_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int opacity); +extern void opacityadv_apply(VJFrame *frame, VJFrame *frame2, int w, + int h, int o, int t1, int t2); +extern void opacitythreshold_apply(VJFrame *frame, VJFrame *frame2, + int w, int h, int o, int t1, int t2); + + +extern void posterize_apply( VJFrame *frame, int width, int height, + int factor, int t1, int t2); +extern void revtv_apply( VJFrame *frame, int width, int height, int space, + int vscale, int c, int cn); +extern void softblur_apply( VJFrame *frame, int width, int height, int n); +extern void split_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int n, int swap); +extern void widthmirror_apply( VJFrame *frame, int width, int height, + int div); +extern void transblend_apply(VJFrame *frame, VJFrame *frame2, int w, + int h, int mode, int twidth, int theight, + int x1, int y1, int x2, int y2); + +extern void borders_apply(VJFrame *frame, int width, int height, + int size, int color); +extern void frameborder_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int size); +extern void noisepencil_apply(VJFrame *frame, int width, int height, + int a, int b, int c , int d ); + +extern void rawman_apply(VJFrame *frame, unsigned int width, + unsigned int height, unsigned int mode, + unsigned int Y); +extern void rawval_apply(VJFrame *frame, int width, int height, + int color_cb, int color_cr, int new_cb, + int new_cr); +extern void smuck_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int level); +extern void colorfade_apply( VJFrame *frame, int width, int height, + int op, int color); +extern void slidingdoor_apply( VJFrame *frame, VJFrame *frame2, + int width, int height, int size); +extern void transop_apply(VJFrame *frame, VJFrame *frame2, int twidth, + int theight, int x1, int y1, int x2, int y2, + int width, int height, int opacity); + +extern void lumakey_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int a, int b, int c, int d, int e); +extern void pointfade_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int pointsize, + int opacity); +extern void slicer_apply( VJFrame *frame, VJFrame *frame2, int width, int height, int a, int b ); + +extern void transcarot_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int point_size, int dy, + int dye, int row_start, int opacity, + int type); + +extern +void transline_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int distance, int line_width, int opacity, + int type); +extern void transform_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int size); + +extern void coloradjust_apply( VJFrame *frame, int width, int height, + int val, int degrees); + +extern void rgbkey_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int i_angle, int i_noise, + int r, int g, int b, int sup); + +extern void gamma_apply( VJFrame *frame, + int width, int height, int val); + +extern void solarize_apply(VJFrame *frame, int width, int height, + int threshold); +extern void dummy_apply(VJFrame *frame, int width, int height, + int color_num); +extern void rotozoom_apply(VJFrame *frame, int width, int height, int a, + int b, int c, int d); + +extern void whiteframe_apply(VJFrame *frame, VJFrame *frame2, + int width, int height); + +extern void texmap_apply(void *dd, VJFrame *frame, + VJFrame *frame2, int width, int height, + int mode, int threshold, int c , int feather, int blob); +extern void contourextract_apply(void *dd, VJFrame *frame, + int width, int height, + int mode, int threshold, int c , int feather, int blob); + +extern void diff_apply(void *dd, VJFrame *frame, + VJFrame *frame2, int width, int height, + int mode, int threshold, int c ,int feather); + +extern void chromamagick_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int type, int op0); +extern void colorfadergb_apply(VJFrame *frame, int width, int height, + int opacity, int r, int g, int b); + +void lumablend_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int type, int t1, int t2, int op); + +extern void diffimg_apply(VJFrame *frame, + int width, int height, int type, int delta, + int zeta); +extern void rgbkeysmooth_apply(VJFrame *frame, VJFrame *frame2, int w, + int h, int angle, int r, int g, int b, + int level, int noise); +extern void scratcher_apply(VJFrame *frame, int w, int h, int o, int n, + int r); +extern void colorshift_apply(VJFrame *frame, int width, int height, + int type, int param); +extern void reflection_apply(VJFrame *frame, int w, int h, int n1, + int n2, int n3); +extern void distortion_apply(VJFrame *frame, int w, int h, int p1, + int p2); +extern void magicscratcher_apply(VJFrame *frame, int w, int h, int mode, + int nframes, int r); +extern void wipe_apply(VJFrame *frame, VJFrame *frame2, int w, int h, + int inc, int opacity); +/* begin API */ +extern void chromascratcher_apply(VJFrame *frame, + int width, int height, int mode, + int opacity, int nframes, + int no_reverse); + +extern void tracer_apply(VJFrame *frame, VJFrame *frame2, + int w, int h, int opacity, int n); + +extern void mtracer_apply(VJFrame *frame, VJFrame *frame2, int w, + int h, int mode, int n); + +extern void keyselect_apply(VJFrame *frame, VJFrame *frame2,int w,int h, int angle,int r, + int g, int b, int mode, int noise); + +extern void greyselect_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b); +extern void isolate_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, +int opacity); + +extern void bwselect_apply(VJFrame *frame, int w, int h, int a , int b); + +extern void complexinvert_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int i_noise); + +extern void complexsaturation_apply(VJFrame *frame, int w, int h, int angle, int r, int g, int b, int adj, int adjv, int inoise); + +extern void complexthreshold_apply(VJFrame *frame, VJFrame *frame2, int w, int h, int angle, int r, + int g, int b, int level, int threshold); + +extern void complexsync_apply(VJFrame *frame, VJFrame *frame2, int w, int h, int val ); + +extern void enhancemask_apply(VJFrame *frame,int w, int h, int *t); + +extern void contrast_apply(VJFrame *frame, int w, int h, int *t); + +extern void noiseadd_apply(VJFrame *frame, int w , int h , int t, int n); + +extern void motionblur_apply(VJFrame *frame, int w, int h, int n); + +extern void sinoids_apply(VJFrame *frame, int w, int h, int a,int b); + +extern void dupmagic_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int n); + +extern void simplemask_apply(VJFrame *frame, VJFrame *frame2, int width, + int height, int threshold, int invert); + +extern void bar_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int d, int x1, int x2, int t1, int b1); + +extern void vbar_apply(VJFrame *frame, VJFrame *frame2, + int w, int h, int d, int x1, int x2, int t1, int t2); + +extern void average_apply(VJFrame *frame, int w, int h, int val); + +extern void ripple_apply(VJFrame *frame, int width, int height, int waves, int ampli,int atten); + +extern void bathroom_apply(VJFrame *frame, int width, int height, int mode, int val); + +extern void slice_apply(VJFrame *frame, int width, int height, int val, int reinit); + +extern void zoom_apply(VJFrame *frame, int w, int h , int xo, int yo, int f, int dir); + +extern void deinterlace_apply(VJFrame *frame, int w, int h, int val); + +extern void simplematte_apply(VJFrame *frame, int w, int h, int threshold, int invert); + +extern void crosspixel_apply(VJFrame *frame, int w, int h,int type, int val); + +extern void color_apply(VJFrame *frame, int w, int h, int a,int b, int c); + +//extern void water_apply(VJFrame *frame, int w, int h, int val, int l, int d); +extern void water_apply(void *user_data, VJFrame *frame, VJFrame *frame2, int width, int height, int fresh,int loopnum, int decay, int mode, int threshold); + +extern void pencilsketch_apply(VJFrame *frame, int w, int h, int type, int threshold, int opacity); + +extern void pixelate_apply(VJFrame *frame, int w, int h, int v ); + +extern void magicmirror_apply(VJFrame *frame, int w, int h, int x, int y, int d, int n ); + +extern void lumamask_apply(VJFrame *frame,VJFrame *frame2, int w, int h, int n, int m, int border); + +extern void smear_apply(VJFrame *frame, int w, int h, int n, int m); + +extern void raster_apply(VJFrame *frame, int w, int h, int v ); + +extern void fisheye_apply(VJFrame *frame, int w, int h, int v ); + +extern void swirl_apply(VJFrame *frame, int w, int h , int v ); + +extern void radialblur_apply(VJFrame *frame, int w, int h, int r, int p, int n); + +extern void binaryoverlay_apply(VJFrame *frame, VJFrame *frame2,int w, int h, int n); + +extern void chromium_apply( VJFrame *frame, int w, int h, int n); + +extern void chromapalette_apply( VJFrame *frame, int w, int h, int a, int r, int g, int b, int c1, int c2); + + +extern void uvcorrect_apply(VJFrame *frame, int width, int height, int angle, int urot_center, int vrot_center, int iuFactor, int ivFactor, int uvmin, int uvmax ); + +extern void dissolve_apply(VJFrame *frame,VJFrame *frame2, int w, int h, int opacity); + +extern void overclock_apply(VJFrame *frame, int w, int h, int val, int r); + +extern int bgsubstract_prepare(void *user, uint8_t *map[3], int width, int height); + +extern void bgsubstract_apply(VJFrame *frame,int width, int height, int mode, int threshold ); + +extern int diff_prepare(void *data, uint8_t *map[3], int w, int h); + +extern void cartonize_apply( VJFrame *frame, int w, int h, int b1, int b2, int b3 ); + +extern void morphology_apply( VJFrame *frame, int w, int h, int t, int v, int p); + +extern void colmorphology_apply( VJFrame *frame, int w, int h, int t, int v, int p); + +extern void blob_apply( VJFrame *frame, int w, int h, int p0,int p1, int p2, int p3); + +extern void boids_apply( VJFrame *frame, int w, int h, int p0,int p1, int p2, int p3, int p4, int p5, int p6, int p7 +); + + +extern void ghost_apply(VJFrame *frame, int w, int h, int o ); +extern void neighbours_apply( VJFrame *frame, int width, int height, int brush_size, int level, int mode); +extern void neighbours2_apply( VJFrame *frame, int width, int height, int brush_size, int level, int mode); +extern void neighbours3_apply( VJFrame *frame, int width, int height, int brush_size, int level, int mode); +extern void neighbours4_apply( VJFrame *frame, int width, int height, int radius, int brush_size, int level, int mode); +extern void neighbours5_apply( VJFrame *frame, int width, int height, int radius, int brush_size, int level); +extern void cutstop_apply( VJFrame *frame, + int width, int height, int treshold, + int freq, int cutmode, int holdmode); +extern void maskstop_apply( VJFrame *frame, + int width, int height, int treshold, + int freq, int cutmode, int holdmode); +extern void photoplay_apply(VJFrame *frame, int w, int h, int a, int b, int c); + +extern void videoplay_apply(VJFrame *frame,VJFrame *B, int w, int h, int a, int b, int c); + +extern void videowall_apply(VJFrame *frame,VJFrame *B, int w, int h, int a, int b, int c, int d); + +extern void flare_apply(VJFrame *frame, int w, int h, int type, int threshold, int radius ); + +extern void constantblend_apply(VJFrame *frame , int w, int h, int type, int scale, int y ); + +extern void picinpic_apply( void *user_data, VJFrame *frame, VJFrame *frame2, + int twidth, int theight, int x1, int y1, + int width, int height); + +extern void threshold_apply( VJFrame *frame, VJFrame *frame2,int width, int height, int threshold, int reverse ); + +extern void motionmap_apply( VJFrame *frame, int w, int h, int threshold, int reverse, int draw, int his, int op ); + +extern void rgbchannel_apply( VJFrame *frame, int width, int height, int chr, int chg , int chb); + +extern void differencemap_apply( VJFrame *f, VJFrame *f2, int w, int h, int t1, int rev, int show ); + +extern void autoeq_apply( VJFrame *frame, int width, int height, int val, int i, int s); + +extern void colorhis_apply( VJFrame *frame, int w, int h, int v, int m, int i, int s ); + +extern void diff_destroy(); + +extern void texmap_destroy(); + +extern void contourextract_destroy(); + +extern void distortion_destroy(); + +extern void rotozoom_destroy(); + +extern void timedistort_apply( VJFrame *frame, int w, int h, int val ); + +extern void chameleon_apply( VJFrame *frame, int w, int h, int mode ); + +extern void chameleonblend_apply( VJFrame *frame, VJFrame *source, int w, int h, int mode ); + +extern void baltantv_apply (VJFrame *frame, int w, int h , int stride, int mode ); + +extern void radioactivetv_apply( VJFrame *a, VJFrame *b,int w, int h, int mode, int t, int sn, int threhold); + +extern void nervous_apply(VJFrame *Frame, int width, int height,int delay); + +extern void colflash_apply( VJFrame *frame, int width, int height, int f,int r, int g, int b, int d); + +extern void iris_apply( VJFrame *frame,VJFrame *frame2, int width, int height, int value, int shape ); + +extern void cali_apply(void *d , VJFrame *frame, + int width, int height, + int mode, int full); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/plugload.c b/branches/V-1.5.3/veejay-server/libvje/plugload.c new file mode 100644 index 00000000..c811ceed --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/plugload.c @@ -0,0 +1,1013 @@ +/* + * Copyright (C) 2002-2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* + Plugin Loader + * FreeFrame + * frei0r + * Livido (pending) + */ + +/* + inspired by http://onsight.id.gu.se/~gabor/ + http://www.gephex.org/ + + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#define LINUX 1 +#include +#include + +#define V_BITS 24 +#include + +#define livido_port_t vevo_port_t +typedef f0r_instance_t (*f0r_construct_f)(unsigned int width, unsigned int height); +typedef void (*f0r_destruct_f)(f0r_instance_t instance); +typedef void (*f0r_deinit_f)(void); +typedef int (*f0r_init_f)(void); +typedef void (*f0r_get_plugin_info_f)(f0r_plugin_info_t *info); +typedef void (*f0r_get_param_info_f)(f0r_param_info_t *info, int param_index); +typedef void (*f0r_update_f)(f0r_instance_t instance, double time, const uint32_t *inframe, uint32_t *outframe); +typedef void (*f0r_update2_f)(f0r_instance_t instance, double time, const uint32_t *inframe1, const uint32_t *inframe2, const uint32_t *inframe3, uint32_t *outframe); +typedef void (*f0r_set_param_value_f)(f0r_instance_t *instance, f0r_param_t *param, int param_index); + +#define VEVO_FF_PORT 10 // free frame port +#define VEVO_FF_PARAM_PORT 11 // free frame parameter port + +#define VEVO_FR_PORT 20 // frei0r port +#define VEVO_FR_PARAM_PORT 21 // frei0r parameter port + + +//@@ missing specification on http://livido.dyne.org ! livido ignored for now +#define VEVO_LIVIDO_PORT 30 // livido port +#define VEVO_LIVIDO_PARAM_PORT 31 // livido parameter port + +#define VEVO_ILLEGAL 100 + +#if (V_BITS == 32) +#define FF_CAP_V_BITS_VIDEO FF_CAP_32BITVIDEO +#elif (V_BITS == 24) +#define FF_CAP_V_BITS_VIDEO FF_CAP_24BITVIDEO +#else // V_BITS = 16 +#define FF_CAP_V_BITS_VIDEO FF_CAP_16BITVIDEO +#endif + +static void *convert_yuv = NULL; +static void *convert_rgb = NULL; +static vevo_port_t **index_map_ = NULL; +static vevo_port_t *illegal_plugins_ =NULL; +static int index_ = 0; +static void *buffer_ = NULL; +static void *buffer2_ = NULL; +static void *buffer_b_ = NULL; +static int base_width_ =0; +static int base_height_ =0; +static int n_ff_ = 0; +static int n_fr_ = 0; +static int n_lvd_ = 0; + +static int select_f( const struct dirent *d ) +{ + return ( strstr( d->d_name, ".so" ) != NULL ); +} + +static int init_param_livido( void *port, int p, int hint ) +{ + return 0; +} + +static void free_parameters( void *port, int n ) +{ + int i; + + for ( i = 0; i < n ; i ++ ) + { + char key[10]; + void *param = NULL; + sprintf(key, "p%d", i ); + vevo_property_get(port, key,0, param ); + if( param ) + vevo_port_free( param ); + } +} + +static int init_param_fr( void *port, int p, int hint) +{ + void *parameter = vpn( VEVO_FR_PARAM_PORT ); + int min = 0; + int max = 100; + int dv = 50; + int n_values = 0; + + switch(hint) + { + case F0R_PARAM_DOUBLE: + n_values = 1; + break; + case F0R_PARAM_BOOL: + max = 1; + dv = 0; + n_values = 1; + break; + case F0R_PARAM_COLOR: + n_values = 3; + break; + case F0R_PARAM_POSITION: + n_values = 2; + break; + default: + break; + } + + if( n_values > 0 ) + { + int values[n_values]; + int k; + for( k = 0; k < n_values; k ++ ) values[k] = 0; + vevo_property_set( parameter, "value", VEVO_ATOM_TYPE_INT, n_values, &values ); + } + + vevo_property_set( parameter, "value", VEVO_ATOM_TYPE_INT, 0, NULL ); + + vevo_property_set( parameter, "min", VEVO_ATOM_TYPE_INT,1, &min ); + vevo_property_set( parameter, "max", VEVO_ATOM_TYPE_INT,1, &max ); + vevo_property_set( parameter, "default", VEVO_ATOM_TYPE_INT,1, &dv ); + vevo_property_set( parameter, "hint", VEVO_ATOM_TYPE_INT,1, &hint ); + + + char key[20]; + snprintf(key,20, "p%d", p ); + vevo_property_set( port, key, VEVO_ATOM_TYPE_VOIDPTR, 1, ¶meter ); + + return n_values; +} + + +static void* deal_with_livido( void *handle, char *name ) +{ +/* void *port = vevo_port_new( VEVO_LIVIDO_PORT ); + char *plugin_name = NULL; + + livido_setup_f livido_setup = dlsym( handle, "livido_setup" ); + + livido_setup_t setup[] = { + { (void(*)()) vj_malloc }, + { (void(*)()) free }, + { (void(*)())memset }, + { (void(*)())memcpy }, + { (void(*)())vevo_port_new }, + { (void(*)())vevo_port_free }, + { (void(*)())vevo_property_set }, + { (void(*)())vevo_property_get }, + { (void(*)())vevo_property_num_elements }, + { (void(*)())vevo_property_atom_type }, + { (void(*)())vevo_property_element_size }, + { (void(*)())vevo_list_properties } + }; + + void *livido_plugin = livido_setup( setup, 100 ); + if(!livido_plugin) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error setting up '%s'",name ); + vevo_port_free( port ); + return NULL; + } + + vevo_property_set( port, "lvd", LIVIDO_ATOM_TYPE_VOIDPTR, 1,&livido_plugin ); + vevo_property_set( port, "handle", LIVIDO_ATOM_TYPE_VOIDPTR,1,&handle ); + + return port; +*/ + return NULL; +} + +static void* deal_with_fr( void *handle, char *name) +{ + void *port = vpn( VEVO_FR_PORT ); + + f0r_init_f f0r_init = dlsym( handle, "f0r_init" ); + if( f0r_init == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror()); + vevo_port_free( port ); + return NULL; + } + + f0r_deinit_f f0r_deinit = dlsym( handle, "f0r_deinit" ); + if( f0r_deinit == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror()); + vevo_port_free( port ); + return NULL; + } + + f0r_get_plugin_info_f f0r_info = dlsym( handle, "f0r_get_plugin_info"); + if( f0r_info == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror()); + vevo_port_free( port ); + return NULL; + } + + f0r_get_param_info_f f0r_param= dlsym( handle, "f0r_get_param_info" ); + if( f0r_param == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': %s", name, dlerror()); + vevo_port_free( port ); + return NULL; + } +//@ gamble + void *f0r_construct = dlsym( handle, "f0r_construct" ); + void *f0r_destruct = dlsym( handle, "f0r_destruct" ); + void *processf = dlsym( handle, "f0r_update" ); +// void *processm = dlsym( handle, "f0r_update2" ); + void *set_params = dlsym( handle, "f0r_set_param_value" ); + + + vevo_property_set( port, "handle", VEVO_ATOM_TYPE_VOIDPTR,1, &handle ); + vevo_property_set( port, "init", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_init ); + vevo_property_set( port, "deinit", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_deinit ); + vevo_property_set( port, "info", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_info ); + vevo_property_set( port, "parameters", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_param ); + vevo_property_set( port, "construct", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_construct ); + vevo_property_set( port, "destruct", VEVO_ATOM_TYPE_VOIDPTR, 1, &f0r_destruct ); + vevo_property_set( port, "process", VEVO_ATOM_TYPE_VOIDPTR, 1, &processf); +// vevo_property_set( port, "process_mix", VEVO_ATOM_TYPE_VOIDPTR, 1, &processm); + vevo_property_set( port, "set_params", VEVO_ATOM_TYPE_VOIDPTR,1,&set_params); + + f0r_plugin_info_t finfo; + f0r_param_info_t pinfo; + + memset( &finfo,0,sizeof(f0r_plugin_info_t)); + memset( &pinfo,0,sizeof(f0r_param_info_t)); + + + if( (*f0r_init)() == 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tBorked frei0r plugin '%s': ", name); + vevo_port_free( port ); + return NULL; + } + + (*f0r_info)(&finfo); + + if( finfo.frei0r_version != FREI0R_MAJOR_VERSION ) + { + (*f0r_deinit)(); + vevo_port_free(port); + return NULL; + } + int extra = 0; +//@ fixme +// if( finfo.plugin_type == F0R_PLUGIN_TYPE_MIXER2 ) +// extra = 1; + + int n_params = finfo.num_params; + int r_params = 0; + int p = 0; + for ( p = 0; p < n_params; p ++ ) + { + (*f0r_param)(&pinfo,p); + r_params += init_param_fr( port, p, pinfo.type ); + } + + if( r_params > 8 ) + r_params = 8; + + char new_name[512]; + sprintf(new_name, "Frei0r %s", finfo.name ); + char *plug_name = strdup( new_name ); + vevo_property_set( port, "n_params", VEVO_ATOM_TYPE_INT, 1, &r_params ); + vevo_property_set( port, "f0r_p", VEVO_ATOM_TYPE_INT,1, &n_params ); + vevo_property_set( port, "name", VEVO_ATOM_TYPE_STRING,1, &plug_name ); + vevo_property_set( port, "mixer", VEVO_ATOM_TYPE_INT,1, &extra ); + free(plug_name); + return port; +} + +static void* deal_with_ff( void *handle, char *name ) +{ + void *port = vpn( VEVO_FF_PORT ); + char *plugin_name = NULL; + plugMainType *q = (plugMainType*) dlsym( handle, "plugMain" ); + + if( q == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR,"\tBorked FF plugin '%s': %s", name, dlerror()); + vevo_port_free( port ); + return NULL; + } + + PlugInfoStruct *pis = (q(FF_GETINFO, NULL, 0)).PISvalue; + + if ((q(FF_GETPLUGINCAPS, (LPVOID)FF_CAP_V_BITS_VIDEO, 0)).ivalue != FF_TRUE) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to get capabilities for plugin %s",name ); + vevo_port_free(port); + return NULL; + } + + + if (pis->APIMajorVersion < 1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cowardly refusing FF API version < 1.0" ); + vevo_port_free(port); + return NULL; + } + + char new_name[512]; + sprintf(new_name, "FreeFrame %s", pis->pluginName ); + plugin_name = strdup( new_name ); + if ( (q(FF_INITIALISE, NULL, 0 )).ivalue == FF_FAIL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot call init()"); + vevo_port_free(port); + if(plugin_name) free(plugin_name); + return NULL; + } + + int n_params = q( FF_GETNUMPARAMETERS, NULL, 0 ).ivalue; + if( n_params == FF_FAIL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot get number of parameters"); + vevo_port_free(port); + if(plugin_name) free(plugin_name); + return NULL; + } + + void *base = (void*) q; + vevo_property_set( port, "handle", VEVO_ATOM_TYPE_VOIDPTR,1, &handle ); + vevo_property_set( port, "name", VEVO_ATOM_TYPE_STRING,1, &plugin_name ); + vevo_property_set( port, "base", VEVO_ATOM_TYPE_VOIDPTR, 1, &base ); + vevo_property_set( port, "instance", VEVO_ATOM_TYPE_INT, 0, NULL ); + vevo_property_set( port, "n_params", VEVO_ATOM_TYPE_INT, 1,&n_params ); + + int p; + for( p= 0; p < n_params; p ++ ) + { + void *parameter = vpn( VEVO_FF_PARAM_PORT ); +#ifdef STRICT_CHECKING + assert( parameter != NULL ); +#endif + int type = q( FF_GETPARAMETERTYPE, (LPVOID) p, 0 ).ivalue; + // name, kind, flags, description, min,max,default,transition + vevo_property_set( parameter, "type", VEVO_ATOM_TYPE_INT, 1, &type); + + int min = 0; + int max = 100; + + if( type == FF_TYPE_BOOLEAN ) + { + min = 0; + max = 1; + } + else if( type == FF_TYPE_TEXT ) + { + min = 0; + max = 0; + } + + vevo_property_set( parameter, "min", VEVO_ATOM_TYPE_INT,1, &min ); + vevo_property_set( parameter, "max", VEVO_ATOM_TYPE_INT,1, &max ); + + float dvalue = 0.0; + dvalue = q( FF_GETPARAMETERDEFAULT, (LPVOID) p, 0).fvalue; + int ivalue = (int)(dvalue * 100.0); + vevo_property_set( parameter, "default", VEVO_ATOM_TYPE_INT,1 ,&ivalue ); + + char key[20]; + snprintf(key,20, "p%d", p ); + vevo_property_set( port, key, VEVO_ATOM_TYPE_VOIDPTR, 1, ¶meter ); + } + free(plugin_name); + return port; +} + +static int instantiate_plugin( void *plugin, int w , int h ) +{ + + int type = 0; + assert( plugin != NULL ); + vevo_property_get( plugin, "type", 0, &type); + if( type == VEVO_FF_PORT ) + { + VideoInfoStruct v; + v.frameWidth = w; + v.frameHeight = h; + v.orientation = 1; + v.bitDepth = FF_CAP_V_BITS_VIDEO; + + void *base = NULL; + vevo_property_get( plugin, "base", 0, &base); + plugMainType *q = (plugMainType*) base; + void *instance = (void*) q( FF_INSTANTIATE, &v, 0).ivalue; + if( instance == (void*) FF_FAIL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize plugin"); + return 0; + } + vevo_property_set( plugin, "instance", VEVO_ATOM_TYPE_INT, 1, &instance ); + return 1; + } + else if( type == VEVO_FR_PORT ) + { + f0r_construct_f base; + vevo_property_get( plugin, "construct", 0, &base); + f0r_instance_t k = (*base)(w,h); + vevo_property_set(plugin, "instance", VEVO_ATOM_TYPE_VOIDPTR, 1, &k); + if( k == NULL ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize plugin"); + // store instance running status + int state = 1; + vevo_property_set( plugin, "running", VEVO_ATOM_TYPE_INT, 1, &state ); + return state; + } + else if ( type == VEVO_LIVIDO_PORT ) + { + return 0; + } + return 0; +} + +static void deinstantiate_plugin( void *plugin ) +{ + if(plugin == NULL) + return; + + int type = 0; + assert( plugin != NULL); + vevo_property_get( plugin, "type", 0, &type); + + if( type == VEVO_FF_PORT ) + { + void *base = NULL; + vevo_property_get( plugin, "base", 0, &base); + plugMainType *q = (plugMainType*) base; + + void *instance = NULL; + vevo_property_get( plugin, "instance", 0, &instance ); + if( instance ) + q( FF_DEINSTANTIATE, NULL, instance ); + } + else if ( type == VEVO_FR_PORT ) + { + int state = 0; + vevo_property_get( plugin, "state", 0, &state ); + if(!state) + return; + + f0r_destruct_f base; + vevo_property_get( plugin, "destruct", 0, &base); + f0r_instance_t instance; + vevo_property_get( plugin, "instance", 0, &instance ); + (*base)(instance); + } + else if ( type == VEVO_LIVIDO_PORT ) + { + + } +} + +static int is_so( const char *file ) +{ + if( strstr(file, ".so" ) || strstr( file, ".SO" ) ) + return 1; + return 0; +} + +static int is_valid_plugin( const char *file ) +{ + if(!file) + return 0; + struct stat l; + veejay_memset( &l, 0, sizeof( struct stat)); + if ( lstat( file, &l ) < 0 ) + return 0; + + if( S_ISDIR( l.st_mode )) + return 0; + + if( S_ISREG( l.st_mode )) + { + if( is_so(file) ) + return 1; + } + return 0; + +} + +static void add_to_plugin_list( const char *path ) +{ + if(!path) + return; + + int i; + char fullname[PATH_MAX]; + struct dirent **files = NULL; + struct stat sbuf; + int res = 0; + + memset( &sbuf,0 ,sizeof(struct stat)); + res = stat( path, &sbuf ); + + if( res != 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "File or directory '%s' does not exist (skip)", path); + return; + } + + if( S_ISREG( sbuf.st_mode ) ) + { + vevo_property_set( illegal_plugins_, path, VEVO_ATOM_TYPE_STRING, 0, NULL ); + return; + } + + if( !S_ISDIR( sbuf.st_mode ) ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Not a directory : '%s'", path ); + return; + } + int n_files = scandir( path, &files, select_f, alphasort ); + if( n_files <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "No FF plugins found in %s", path ); + return; + } + + for( i = 0 ; i < n_files; i ++ ) + { + char *name = files[i]->d_name; + + if(!name) + continue; + + if( vevo_property_get( illegal_plugins_, name, 0 , NULL ) == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "'%s' marked as bad", name); + continue; + } + + sprintf(fullname, "%s/%s", path,name ); + + //@ check if name is regular file + if( is_valid_plugin( fullname ) == 0 ) + { + continue; + } + + void *handle = dlopen(fullname, RTLD_NOW ); + + if(handle) + { + if(dlsym( handle, "plugMain" )) + { + void *plugin = deal_with_ff( handle, name ); + if( plugin ) + { + index_map_[ index_ ] = plugin; + index_ ++; + n_ff_ ++; + } + else + dlclose( handle ); + } + else if (dlsym( handle, "f0r_construct" )) + { + void *plugin = deal_with_fr( handle, name ); + if( plugin ) + { + index_map_[ index_ ] = plugin; + index_ ++; + n_fr_ ++; + } + else + dlclose( handle ); + } + else + dlclose(handle); + } + } + + for( i = 0; i < n_files; i ++ ) + free( files[i] ); + free(files); +} + +static void free_plugin(void *plugin) +{ + if(plugin == NULL) + return; + + int type = 0; + vevo_property_get( plugin, "type", 0, &type); + + int n = 0; + + if( type == VEVO_FF_PORT ) + { + void *base = NULL; + vevo_property_get( plugin, "base", 0, &base); + plugMainType *q = (plugMainType*) base; + q( FF_DEINITIALISE, NULL, 0 ); + vevo_property_get( plugin, "n_params", 0, &n ); + } + else if ( type == VEVO_FR_PORT ) + { + //@@ clear parameters + f0r_deinit_f base; + vevo_property_get( plugin, "deinit", 0, &base); + (*base)(); + vevo_property_get( plugin, "f0r_p", 0, &n ); + } + else if ( type == VEVO_LIVIDO_PORT ) + { + + } + + free_parameters(plugin,n); + + + void *handle = NULL; + vevo_property_get( plugin, "handle", 0 , &handle ); + if( handle ) dlclose( handle ); + vevo_port_free( plugin ); + +} + +static void free_plugins() +{ + int i; + for( i = 0; i < index_ ; i ++ ) + { + deinstantiate_plugin( index_map_[i] ); + free_plugin( index_map_[i]); + } + free( index_map_ ); + index_ = 0; +} + +#define CONFIG_FILE_LEN 65535 + +static void scan_plugins() +{ + char *home = getenv( "HOME" ); + char path[PATH_MAX]; + char data[CONFIG_FILE_LEN]; + if(!home) + { + veejay_msg(VEEJAY_MSG_ERROR, "Environment variable HOME not set!"); + return; + } + sprintf( path , "%s/.veejay/plugins.cfg" , home ); + + int fd = open( path, O_RDONLY ); + if( fd < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cant open %s", path); + return; + } + + veejay_memset( data, 0, CONFIG_FILE_LEN ); + + if( read( fd, data, CONFIG_FILE_LEN ) > 0 ) + { + int len = strlen(data); + int j; + int k = 0; + char value[PATH_MAX]; + + veejay_memset( value,0, PATH_MAX ); + for( j=0; j < len; j ++ ) + { + if(data[j] == '\0' ) + break; + if( data[j] == '\n' ) + { add_to_plugin_list( value ); veejay_memset(value,0,PATH_MAX); k =0;} + + if( isascii( data[j] ) && data[j] != '\n') + { value[k] = data[j]; if( k < PATH_MAX) k ++; } + + } + } +} + +static void process_plug_plugin( void *plugin, void *buffer , void *out_buffer) +{ + int type = 0; + vevo_property_get( plugin, "type", 0, &type); + if( type == VEVO_FF_PORT ) + { + void *base = NULL; + vevo_property_get( plugin, "base", 0, &base); + plugMainType *q = (plugMainType*) base; + void *instance = NULL; + vevo_property_get( plugin, "instance",0, &instance ); + q( FF_PROCESSFRAME, buffer, instance ); + } + else if (type == VEVO_FR_PORT ) + { + f0r_update_f base; + vevo_property_get( plugin, "process", 0, &base ); + f0r_instance_t instance; + vevo_property_get( plugin, "instance",0, &instance ); + (*base)( instance, rand(), buffer, out_buffer ); + } + else if (type == VEVO_LIVIDO_PORT ) + { + + } +} + +/* public IF */ + +void plug_free(void) +{ + free_plugins(); + + if( convert_rgb ) + yuv_fx_context_destroy( convert_rgb ); + if( convert_yuv ) + yuv_fx_context_destroy( convert_yuv ); + + if( buffer_ ) + free( buffer_ ); + if( buffer2_ ) + free( buffer2_ ); + if( buffer_b_) + free( buffer_b_ ); +} + +void plug_init( int w, int h ) +{ + buffer_ = (void*) vj_calloc( w * h * (V_BITS >> 3)); + buffer2_ = (void*) vj_calloc( w * h * (V_BITS >> 3)); + buffer_b_ = (void*) vj_calloc( w * h * (V_BITS >> 3)); + + base_width_ = w; + base_height_ = h; +} + +int plug_detect_plugins(void) +{ + index_map_ = (vevo_port_t**) vj_calloc(sizeof(vevo_port_t*) * 256 ); + + illegal_plugins_ = vpn( VEVO_ILLEGAL ); + + scan_plugins(); + //@ display copyright notice in binary form + if(n_ff_ > 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "FreeFrame Copyright (c) 2002, Marcus Clements www.freeframe.org. All Rights reserved."); + + veejay_msg(VEEJAY_MSG_INFO, "http://freeframe.sourceforge.net"); + veejay_msg(VEEJAY_MSG_INFO,"Loaded %d FreeFrame %s", + n_ff_ , n_ff_ == 1 ? "plugin" : "plugins" ); + } + if(n_fr_ > 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "frei0r - a minimalistic plugin API for video effects"); + veejay_msg(VEEJAY_MSG_INFO, "http://www.piksel.org/frei0r"); + veejay_msg(VEEJAY_MSG_INFO, "Loaded %d frei0r %s", + n_fr_ , n_fr_ == 1 ? "plugin" : "plugins" ); + } + if(n_lvd_ > 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "Livido - (Linux) Video Objects" ); + veejay_msg(VEEJAY_MSG_INFO, "Loaded %d Livido %s", + n_lvd_, n_lvd_ == 1 ? "plugin" :"plugins" ); + } + + vevo_port_free( illegal_plugins_ ); + + return index_; +} + +vj_effect *plug_get_plugin( int n ) +{ + vj_effect *vje = (vj_effect*) vj_calloc(sizeof(vj_effect)); + vevo_port_t *port = index_map_[n]; + size_t name_len = vevo_property_element_size( port, "name", 0 ); + vje->description = (char*) vj_calloc( name_len ); + vevo_property_get( port, "name", 0, &(vje->description)); + vevo_property_get( port, "n_params", 0, &(vje->num_params)); + vevo_property_get( port, "mixer", 0, &(vje->extra_frame)); + if( vje->num_params > 0 ) + { + if( vje->num_params > 8 ) + { + veejay_msg(VEEJAY_MSG_WARNING, "%s has %d parameters, clip to 8", + vje->description, vje->num_params ); + vje->num_params = 8; + } + + vje->defaults = (int*) vj_calloc(sizeof(int) * vje->num_params ); + vje->limits[0] = (int*) vj_calloc(sizeof(int) * vje->num_params ); + vje->limits[1] = (int*) vj_calloc(sizeof(int) * vje->num_params ); + + int k = 0; + int valid_p = 0; + char **param_descr = NULL; + if( vje->num_params > 0 ) + param_descr = (char**) vj_malloc(sizeof(char*) * vje->num_params ); + + for( k = 0; k < vje->num_params;k++ ) + { + char key[20]; + sprintf(key, "p%d", k ); + void *parameter = NULL; + vevo_property_get( port, key, 0, ¶meter ); + if(parameter) + { + vevo_property_get( parameter, "min", 0, &(vje->limits[0][k])); + vevo_property_get( parameter, "max", 0, &(vje->limits[1][k])); + vevo_property_get( parameter, "default", 0,&(vje->defaults[k])); + param_descr[valid_p] = strdup( "Number" ); + valid_p ++; + } + } + vevo_property_set( port, "n_params",VEVO_ATOM_TYPE_INT, 1,&valid_p); + vje->num_params = valid_p; + vje->param_description = param_descr; + } + + return vje; +} + + +int plug_activate( int fx_id ) +{ + return instantiate_plugin( index_map_[fx_id], base_width_, base_height_ ); +} +void plug_deactivate( int fx_id ) +{ + deinstantiate_plugin( index_map_[fx_id] ); +} + +void plug_control( int fx_id, int *args ) +{ + vevo_port_t *port = index_map_[ fx_id ]; + + int type = 0; + vevo_property_get( port, "type", 0, &type); + if( type == VEVO_FF_PORT ) + { + SetParameterStruct v; + void *base = NULL; + vevo_property_get( port, "base", 0, &base); + plugMainType *q = (plugMainType*) base; + int p,num_params=0; + void *instance = NULL; + vevo_property_get( port, "n_params", 0, &num_params); + vevo_property_get( port, "instance", 0, &instance ); + for( p = 0; p < num_params; p ++ ) + { + v.value = ((float) args[p]) * 0.01; + v.index = p; + q( FF_SETPARAMETER, &v, instance ); + } + } + else if ( type == VEVO_FR_PORT ) + { + int p,num_params=0; + vevo_property_get( port, "n_params", 0, &num_params); + int v_params = 0; + + f0r_set_param_value_f q; + + vevo_property_get( port, "set_params", 0, &q); + for( p = 0; p < num_params; p ++ ) + { + char key[20]; + sprintf(key, "p%d", p ); + void *param = NULL; + vevo_property_get( port, key, 0, ¶m ); + if( param ) continue; + + int n = vevo_property_element_size( param, "value", p ); + + f0r_param_position_t pos; + f0r_param_color_t col; + + double value = 0.0; + //nt instance = 0; + void *instance = NULL; + vevo_property_get( port, "instance", 0, &instance ); + int max = 0; + vevo_property_get( param, "max",0,&max); + + void *fparam = NULL; + switch(n) + { + case 0: + case 1: + value = ( (double) args[v_params] * (max == 100 ? 0.01: 1)); + fparam = &value; + v_params ++; + break; + case 2: + pos.x = ( (double) args[v_params] * 0.01 ); + v_params ++; + pos.y = ( (double) args[v_params] * 0.01 ); + v_params ++; + fparam = &pos; + break; + case 3: + col.r = ( (double) args[v_params] * 0.01 ); + v_params ++; + col.g = ( (double) args[v_params] * 0.01 ); + v_params ++; + col.b = ( (double) args[v_params] * 0.01 ); + v_params ++; + fparam = &col; + break; + default: + break; + } + if( fparam ) + (*q)( instance, fparam, p ); + } + } + else if ( type == VEVO_LIVIDO_PORT ) + { + + } +} + +void plug_process( VJFrame *frame,VJFrame *b, int fx_id, int src_fmt ) +{ + AVPicture p1,p2; + AVPicture o1,o2; + void *plugin = index_map_[fx_id]; + + int is_mix = 0; + vevo_property_get( plugin, "mixer", 0, &is_mix ); + if( is_mix ) + { + veejay_msg(0, "Not supporting mixing plugins yet"); + return; + } + + VJFrame *dst1 = yuv_rgb_template( buffer_, frame->width,frame->height, + PIX_FMT_RGB24 ); + + if(!convert_yuv) + convert_yuv = yuv_fx_context_create( frame,dst1,src_fmt,dst1->format ); + if(!convert_rgb ) + convert_rgb = yuv_fx_context_create( dst1, frame, dst1->format, src_fmt ); + +// yuv_convert_any_ac( frame, dst1, src_fmt, dst1->format ); + + yuv_fx_context_process( convert_yuv, frame,dst1 ); + + process_plug_plugin( plugin, buffer_, buffer2_ ); + + yuv_fx_context_process( convert_rgb, dst1, frame ); + +// yuv_convert_any_ac( dst1, frame, dst1->format, src_fmt ); + + free(dst1); + +} + diff --git a/branches/V-1.5.3/veejay-server/libvje/plugload.h b/branches/V-1.5.3/veejay-server/libvje/plugload.h new file mode 100644 index 00000000..2477cf8b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/plugload.h @@ -0,0 +1,35 @@ +#ifndef PLUGINLOADER_ +#define PLUGINLOADER_ +/* + * Copyright (C) 2002-2006 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "vje.h" + +void plug_free(void); +void plug_init( int w, int h ); +int plug_activate( int fx_id ); +void plug_deactivate( int fx_id ); + +int plug_detect_plugins(void); +vj_effect *plug_get_plugin(int n); + +void plug_process( VJFrame *frame,VJFrame *b, int fx_id, int src_fmt ); +void plug_control( int fx_id, int *args ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/specs/FreeFrame.h b/branches/V-1.5.3/veejay-server/libvje/specs/FreeFrame.h new file mode 100644 index 00000000..b59ec72f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/specs/FreeFrame.h @@ -0,0 +1,207 @@ +#ifndef __FREEFRAME_H__ +#define __FREEFRAME_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// FreeFrame.h +// +// FreeFrame Open Video Plugin Prototype +// C Version + +// www.freeframe.org +// marcus@freeframe.org + +/* + +Copyright (c) 2002, Marcus Clements www.freeframe.org +All rights reserved. + +FreeFrame 1.0 upgrade by Pete Warden +www.petewarden.com + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of FreeFrame nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef LINUX + +typedef unsigned int DWORD; +typedef void * LPVOID; +typedef unsigned char BYTE; + +#elif MACOS + +typedef unsigned int DWORD; +typedef unsigned char BYTE; + +#endif + + +///////////////////////////////////////////////////////////////////////////////////////// +// #defines + +#define FF_EFFECT 0 +#define FF_FAIL 0xFFFFFFFF +#define FF_SUCCESS 0 +#define FF_TRUE 1 +#define FF_FALSE 0 + +#define FF_GETINFO 0 +#define FF_INITIALISE 1 +#define FF_DEINITIALISE 2 +#define FF_PROCESSFRAME 3 +#define FF_GETNUMPARAMETERS 4 +#define FF_GETPARAMETERNAME 5 +#define FF_GETPARAMETERDEFAULT 6 +#define FF_GETPARAMETERDISPLAY 7 +#define FF_SETPARAMETER 8 +#define FF_GETPARAMETER 9 +#define FF_GETPLUGINCAPS 10 +#define FF_INSTANTIATE 11 +#define FF_DEINSTANTIATE 12 +#define FF_GETEXTENDEDINFO 13 +#define FF_PROCESSFRAMECOPY 14 +#define FF_GETPARAMETERTYPE 15 + +#define FF_CAP_16BITVIDEO 0 +#define FF_CAP_24BITVIDEO 1 +#define FF_CAP_32BITVIDEO 2 +#define FF_CAP_PROCESSFRAMECOPY 3 +#define FF_CAP_MINIMUMINPUTFRAMES 10 +#define FF_CAP_MAXIMUMINPUTFRAMES 11 +#define FF_CAP_COPYORINPLACE 15 + +#define FF_CAP_PREFER_NONE 0 +#define FF_CAP_PREFER_INPLACE 1 +#define FF_CAP_PREFER_COPY 2 +#define FF_CAP_PREFER_BOTH 3 + +#define FF_TYPE_BOOLEAN 0 +#define FF_TYPE_EVENT 1 +#define FF_TYPE_RED 2 +#define FF_TYPE_GREEN 3 +#define FF_TYPE_BLUE 4 +#define FF_TYPE_XPOS 5 +#define FF_TYPE_YPOS 6 +#define FF_TYPE_STANDARD 10 +#define FF_TYPE_TEXT 100 + +///////////////////////////////////////////////////////////////////////////////////////// +// +// FreeFrame types + +typedef struct PlugInfoStructTag { + DWORD APIMajorVersion; + DWORD APIMinorVersion; + BYTE uniqueID[4]; // 4 chars uniqueID - not null terminated + BYTE pluginName[16]; // 16 chars plugin friendly name - not null terminated + DWORD pluginType; // Effect or source +} PlugInfoStruct; + +typedef struct PlugExtendedInfoStructTag { + DWORD PluginMajorVersion; + DWORD PluginMinorVersion; + char* Description; + char* About; + DWORD FreeFrameExtendedDataSize; + void* FreeFrameExtendedDataBlock; +} PlugExtendedInfoStruct; + +typedef struct VideoInfoStructTag { + DWORD frameWidth; // width of frame in pixels + DWORD frameHeight; // height of frame in pixels + DWORD bitDepth; // enumerated indicator of bit depth of video + // 0 = 16 bit 5-6-5 1 = 24bit packed 2 = 32bit + DWORD orientation; // video frame orientation meaningful values: + // 1 = origin at top left 2 = origin at bottom left +} VideoInfoStruct; + +typedef struct ProcessFrameCopyStructTag { + DWORD numInputFrames; + void** InputFrames; + void* OutputFrame; +} ProcessFrameCopyStruct; + +typedef struct SetParameterStructTag { + DWORD index; + float value; +} SetParameterStruct; + +typedef union plugMainUnionTag { + DWORD ivalue; + float fvalue; + VideoInfoStruct *VISvalue; + PlugInfoStruct *PISvalue; + char *svalue; +} plugMainUnion; + +typedef plugMainUnion plugMainType(DWORD, LPVOID, DWORD); + +/////////////////////////////////////////////////////////////////////////////////////// +// Function prototypes +// + +/////////////////////////////////////////////////////////////////////////////////////// +// plugMain - The one and only exposed function +// parameters: +// functionCode - tells the plugin which function is being called +// pParam - 32-bit parameter or 32-bit pointer to parameter structure +// instanceID - 32-bit instance identifier. Only used for instance specific functions +// +// PLUGIN DEVELOPERS: you shouldn't need to change this function +// +// All parameters are cast as 32-bit untyped pointers and cast to appropriate +// types here +// +// All return values are cast to 32-bit untyped pointers here before return to +// the host +// + +#ifdef WIN32 + +BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, DWORD instanceID); + +__declspec(dllexport) void* __stdcall plugMain(DWORD functionCode, LPVOID pParam, DWORD instanceID); + +typedef __declspec(dllimport) void* (__stdcall *FF_Main_FuncPtr)(DWORD, LPVOID, DWORD); + +#elif LINUX + +plugMainUnion plugMain(DWORD functionCode, LPVOID pParam, DWORD instanceID); + +#elif MACOS + +typedef void* (*FF_Main_FuncPtr)(DWORD ,void *, DWORD); + +#endif + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/specs/frei0r.h b/branches/V-1.5.3/veejay-server/libvje/specs/frei0r.h new file mode 100644 index 00000000..f6b81d2b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/specs/frei0r.h @@ -0,0 +1,567 @@ +/** @mainpage frei0r - a minimalistic plugin API for video effects + * + * @section sec_intro Introduction + * + * This is frei0r - a minimalistic plugin API for video effects. + * + * The main emphasis is on simplicity - there are many different applications + * that use video effects, and they all have different requirements regarding + * their internal plugin API. And that's why frei0r does not try to be a + * one-in-all general video plugin API, but instead an API for the most + * common video effects: simple filters, sources and mixers that can be + * controlled by parameters. + * + * It's our hope that this way these simple effects can be shared between + * many applications, avoiding their reimplementation by different + * projects. + * + * On the other hand, this is not meant as a competing standard to + * more ambitious efforts that try to satisfy the needs of many different + * applications and more complex effects. + * + * + * @section sec_overview Overview + * + * If you are new to frei0r, the best thing is probably to have + * a look at the frei0r header, + * which is quite simple. + * + * After that, you might want to look at the + * frei0r functions in more detail. + * + * When developing a new frei0r effect, you have to choose + * - which effect type to use (\ref PLUGIN_TYPE), + * - which color model to use (\ref COLOR_MODEL), and + * - which parameter types (\ref PARAM_TYPE) your effect will support. + * + * To round things up, you should decide whether your effect should have + * an associated icon (\ref icons), and where it will be installed + * (\ref pluglocations). + * + * @section sec_changes Changes + * + * @subsection sec_changes_1_0_1_1 From frei0r 1.0 to frei0r 1.1 + * + * - added specifications for plugin locations + * - added specifications for frei0r icons + * - added RGBA8888 color model + * - added packed32 color model + * - added better specification of color models + * - added string type + * - added bounds to resolution (8 <= width, height <= 2048) + * - width and height must be an integer multiple of 8 + * - frame data must be 16 byte aligned + * - improved update specification (must not change parameters, + * must restore fpu state) + * - added note for applications to ignore effects with unknown fields + * - added new plugin types mixer2 and mixer3 + * - added section about \ref concurrency + */ + + +/** + * \addtogroup pluglocations Plugin Locations + * @section sec_pluglocations Plugin Locations + * + * For Unix platforms there are rules for the location of frei0r plugins. + * + * frei0r 1.x plugin files should be located in + * + * - (1) /usr/lib/frei0r-1/\ + * - (2) /usr/local/lib/frei0r-1/\ + * - (3) $HOME/.frei0r-1/lib/\ + * + * Examples: + * + * - /usr/lib/frei0r-1/mob/flippo.so + * - /usr/lib/frei0r-1/drone/flippo.so + * - /usr/local/lib/frei0r-1/gephex/coma/invert0r.so + * - /home/martin/.frei0r-1/lib/martin/test.so + * + * Like in these examples plugins should be placed in "vendor" subdirs + * to reduce name clashes. + * + * @subsection sec_order Plugin Loading Order + * + * The application shall load plugins in the following order: 3, 2, 1. + * If a name clash occurs (two or more frei0r plugins with identical + * effect name), the plugins in directory 3 have precedence over plugins + * in directory 2, and those in directory 2 have precedence over plugins + * in directory 1. + * + * This makes it possible for users to "override" effects that are + * installed in system wide directories by placing plugins in their + * home directory. + * + * The order of loading plugins inside each of the directories + * 1, 2, and 3 is not defined. + */ + +/** + *\addtogroup icons Icons for frei0r effects + * @section sec_icons Icons for frei0r effects + * + * Each frei0r effect can have an associated icon. + * + * @subsection sec_icon_format Icon Format + * + * The format of frei0r icons must be png. + * Recommended resolution is 64x64. + * The icon filename of an effect with effect name "frei0r" + * must be "frei0r.png". + * + * @subsection sec_icon_location Icon location + * + * The exact location where the application should look for the + * plugin is platform dependant. + * + * For Windows platforms, the icon should be at the same place as + * the plugin containing the effect. + * + * For Unix platforms, the following mapping from plugin location + * to icon location must be used: + * + * Let \/\ be a frei0r plugin with name \. + * Then the corresponding icon (if any) shall be located in + * \/\.png. + * \ can be obtained in the following way: + * + * @verbatim + | + ---------------------------------------------------------------------------- + $HOME/.frei0r-1/lib/ | $HOME/.frei0r-1/icons/ + /usr/local/lib/frei0r-1/ | /usr/local/share/frei0r-1/icons/ + /usr/lib/frei0r-1/ | /usr/share/frei0r-1/icons/ + * | + @endverbatim + * + * (The wildcard '*' stands for any other plugin_path) + * + * For other platforms, no location is defined. We recommend to use the + * plugin path where possible. + */ + +/** + * \addtogroup concurrency Concurrency + * @section sec_concurrency Concurrency + * + * - \ref f0r_init + * - \ref f0r_deinit + * + * These methods must not be called more than once. It is obvious that no + * concurrent calls are allowed. + * + * + * - \ref f0r_get_plugin_info + * - \ref f0r_get_param_info + * - \ref f0r_construct + * - \ref f0r_destruct + * + * Concurrent calls of these functions are allowed. + * + * + * - \ref f0r_set_param_value + * - \ref f0r_get_param_value + * - \ref f0r_update + * - \ref f0r_update2 + * + * If a thread is in one of these methods its allowed for another thread to + * enter one of theses methods for a different effect instance. But for one + * effect instance only one thread is allowed to execute any of these methods. + */ + + + +/** \file + * \brief This file defines the frei0r api, version 1.1. + * + * A conforming plugin must implement and export all functions declared in + * this header. + * + * A conforming application must accept only those plugins which use + * allowed values for the described fields. + */ + +#ifndef INCLUDED_FREI0R_H +#define INCLUDED_FREI0R_H + +#include + +/** + * The frei0r API major version + */ +#define FREI0R_MAJOR_VERSION 1 + +/** + * The frei0r API minor version + */ +#define FREI0R_MINOR_VERSION 1 + +//--------------------------------------------------------------------------- + +/** + * f0r_init() is called once when the plugin is loaded by the application. + * \see f0r_deinit + */ +int f0r_init(); + +/** + * f0r_deinit is called once when the plugin is unloaded by the application. + * \see f0r_init + */ +void f0r_deinit(); + +//--------------------------------------------------------------------------- + +/** \addtogroup PLUGIN_TYPE Type of the Plugin + * These defines determine whether the plugin is a + * source, a filter or one of the two mixer types + * @{ + */ + +/** one input and one output */ +#define F0R_PLUGIN_TYPE_FILTER 0 +/** just one output */ +#define F0R_PLUGIN_TYPE_SOURCE 1 +/** two inputs and one output */ +#define F0R_PLUGIN_TYPE_MIXER2 2 +/** three inputs and one output */ +#define F0R_PLUGIN_TYPE_MIXER3 3 + +/** @} */ + +//--------------------------------------------------------------------------- + +/** \addtogroup COLOR_MODEL Color Models + * List of supported color models. + * + * Note: the color models are endian independent, because the + * color components are defined by their positon in memory, not + * by their significance in an uint32_t value. + * + * For effects that work on the color components, + * RGBA8888 is the recommended color model for frei0r-1.1 effects. + * For effects that only work on pixels, PACKED32 is the recommended + * color model since it helps the application to avoid unnecessary + * color conversions. + * + * Effects can choose an appropriate color model, applications must support + * all color models and do conversions if necessary. Source effects + * must not use the PACKED32 color model because the application must know + * in which color model the created framebuffers are represented. + * + * For each color model, a frame consists of width*height pixels which + * are stored row-wise and consecutively in memory. The size of a pixel is + * 4 bytes. There is no extra pitch parameter + * (i.e. the pitch is simply width*4). + * + * The following additional constraints must be honored: + * - The top-most line of a frame is stored first in memory. + * - A frame must be aligned to a 16 byte border in memory. + * - The width and height of a frame must be positive + * - The width and height of a frame must be integer multiples of 8 + * + * These constraints make sure that each line is stored at an address aligned + * to 16 byte. + */ +/*@{*/ +/** + * In BGRA8888, each pixel is represented by 4 consecutive + * unsigned bytes, where the first byte value represents + * the blue, the second the green, and the third the red color + * component of the pixel. The last value represents the + * alpha value. + */ +#define F0R_COLOR_MODEL_BGRA8888 0 + +/** + * In RGBA8888, each pixel is represented by 4 consecutive + * unsigned bytes, where the first byte value represents + * the red, the second the green, and the third the blue color + * component of the pixel. The last value represents the + * alpha value. + */ +#define F0R_COLOR_MODEL_RGBA8888 1 + +/** + * In PACKED32, each pixel is represented by 4 consecutive + * bytes, but it is not defined how the color componets are + * stored. The true color format could be RGBA8888, + * BGRA8888, a packed 32 bit YUV format, or any other + * color format that stores pixels in 32 bit. + * + * This is useful for effects that don't work on color but + * only on pixels (for example a mirror effect). + * + * Note that source effects must not use this color model. + */ +#define F0R_COLOR_MODEL_PACKED32 2 +/*@}*/ + +/** + * The f0r_plugin_info_t structure is filled in by the plugin + * to tell the application about its name, type, number of parameters, + * and version. + * + * An application should ignore (i.e. not use) frei0r effects that + * have unknown values in the plugin_type or color_model field. + * It should also ignore effects with a too high frei0r_version. + * + * This is necessary to be able to extend the frei0r spec (e.g. + * by adding new color models or plugin types) in a way that does not + * result in crashes when loading effects that make use of these + * extensions into an older application. + * + * All strings are unicode, 0-terminated, and the encoding is utf-8. + */ +typedef struct f0r_plugin_info +{ + const char* name; /**< The (short) name of the plugin */ + const char* author; /**< The plugin author */ + /** The plugin type + * \see PLUGIN_TYPE + */ + int plugin_type; + int color_model; /**< The color model used */ + int frei0r_version; /**< The frei0r major version this plugin is built for*/ + int major_version; /**< The major version of the plugin */ + int minor_version; /**< The minor version of the plugin */ + int num_params; /**< The number of parameters of the plugin */ + const char* explanation; /**< An optional explanation string */ +} f0r_plugin_info_t; + + +/** + * Is called once after init. The plugin has to fill in the values in info. + * + * \param info Pointer to an info struct allocated by the application. + */ +void f0r_get_plugin_info(f0r_plugin_info_t* info); + +//--------------------------------------------------------------------------- + +/** \addtogroup PARAM_TYPE Parameter Types + * + * @{ + */ + + +/** + * Parameter type for boolean values + * \see f0r_param_bool + */ +#define F0R_PARAM_BOOL 0 + +/** + * Parameter type for doubles + * \see f0r_param_double + */ +#define F0R_PARAM_DOUBLE 1 + +/** + * Parameter type for color + * \see f0r_param_color + */ +#define F0R_PARAM_COLOR 2 +/** + * Parameter type for position + * \see f0r_param_position + */ +#define F0R_PARAM_POSITION 3 + +/** + * Parameter type for string + * \see f0r_param_string + */ +#define F0R_PARAM_STRING 4 + +/** + * The boolean type. The allowed range of values is [0, 1]. + * [0, 0.5[ is mapped to false and [0.5, 1] is mapped to true. + */ +typedef double f0r_param_bool; + +/** + * The double type. The allowed range of values is [0, 1]. + */ +typedef double f0r_param_double; + +/** + * The color type. All three color components are in the range [0, 1]. + */ +typedef struct f0r_param_color +{ + float r; /**< red color component */ + float g; /**< green color component */ + float b; /**< blue color component */ +} f0r_param_color_t; + +/** + * The position type. Both position coordinates are in the range [0, 1]. + */ +typedef struct f0r_param_position +{ + double x; /**< x coordinate */ + double y; /**< y coordinate */ +} f0r_param_position_t; + + +/** + * The string type. + * Zero terminated array of 8-bit values in utf-8 encoding + */ +typedef char f0r_param_string; + +/** @} */ + + +/** + * Similar to f0r_plugin_info_t, this structure is filled by the plugin + * for every parameter. + * + * All strings are unicode, 0-terminated, and the encoding is utf-8. + */ +typedef struct f0r_param_info +{ + const char* name; /** + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "3bar.h" + +vj_effect *bar_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *)vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 4; + ve->defaults[1] = 1; + ve->defaults[2] = 3; + ve->defaults[3] = 0; + ve->defaults[4] = 0; + ve->limits[0][0] = 1; + ve->limits[1][0] = height; + + ve->sub_format = 1; + ve->limits[0][1] = 0; + ve->limits[1][1] = height; + + ve->limits[0][2] = 0; + ve->limits[1][2] = height; + + ve->limits[0][3] = 0; + ve->limits[1][3] = height; + ve->limits[0][4] = 0; + ve->limits[1][4] = height; + ve->description = "Horizontal Sliding Bars"; + + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Divider", "Top Y", "Bot Y", "Top X", "Bot X"); + return ve; +} + +/* p0 351 , p1 92 : positioneert image 1 bovenaan + p4 beweegt image offset verticaal (frame in frame) + p5 beweegt image offset horizontaal (frame in frame) */ +static int bar_top_auto = 0; +static int bar_bot_auto = 0; +static int bar_top_vert = 0; + +static int bar_bot_vert = 0; +// FIXME private +void bar_apply(VJFrame *frame, VJFrame *frame2, int width, int height,int divider, int top_y, int bot_y, int top_x, int bot_x ) { + + int top_width = width; /* frame in frame destination area */ + int top_height = height/(divider); + + int bottom_width = width; /* frame in frame destionation area */ + int bottom_height = (height - top_height); + int y,x; + int yy=0; + int y2 = bar_top_auto + top_y; /* destination */ + int x2 = bar_top_vert + top_x; + uint8_t *Y = frame->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2= frame2->data[1]; + uint8_t *Cr2= frame2->data[2]; + + if(y2 > width) { y2 = 0; bar_top_auto = 0; } + if(x2 > (height-top_height)) {x2 = 0; bar_top_vert = 0; } + /* start with top frame in a frame */ + for( y = 0; y < top_height; y++ ) { + for ( x = 0; x < top_width; x++ ) { + Y[ (y*width + x)] = Y2[ ( (y+x2) *width + x +y2)]; + Cb[ (y*width + x)] = Cb2[ ( (y+x2) *width + x +y2)]; + Cr[ (y*width + x)] = Cr2[ ( (y+x2) *width + x +y2)]; + } + } + /* do bottom part */ + y2 = bar_bot_auto + bot_y; + x2 = bar_bot_vert + bot_x; + if(y2 > width) { y2 = 0; bar_bot_auto = 0; } + if(x2 > (height-top_height)) { x2 = 0; bar_bot_vert = 0; } + /* start with bottom frame in a frame */ + for ( y = bottom_height; y < height; y++) { + yy++; + for(x=0; x < bottom_width; x++ ) { + Y[ (y*width + x)] = Y2[((yy+x2)*width+x+y2)]; + Cb[ (y*width + x)] = Cb2[((yy+x2)*width+x+y2)]; + Cr[ (y*width + x)] = Cr2[((yy+x2)*width+x+y2)]; + } + } + + bar_top_auto += top_y; + bar_bot_auto += bot_y; + bar_top_vert += top_x; + bar_bot_vert += bot_x; +} +void bar_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/3bar.h b/branches/V-1.5.3/veejay-server/libvje/transitions/3bar.h new file mode 100644 index 00000000..feb2594b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/3bar.h @@ -0,0 +1,61 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BAR_H +#define BAR_H +#include +#include +#include + +vj_effect *bar_init(int width, int height); +void bar_apply(VJFrame *frame, VJFrame *frame2, + int width, int height, int d, int x1, int x2, int t1, int b1); +#endif +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef BAR_H +#define BAR_H +#include "../vj-effect.h" +#include +#include + +vj_effect *bar_init(int width, int height); +void bar_apply(uint8_t * yuv1[3], uint8_t * yuv2[3], + int width, int height, int d, int x1, int x2, int t1, int b1); +void bar_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolor.c b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolor.c new file mode 100644 index 00000000..26125162 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolor.c @@ -0,0 +1,125 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "fadecolor.h" +#include + +vj_effect *fadecolor_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 255; + ve->defaults[1] = VJ_EFFECT_COLOR_BLACK; + ve->defaults[2] = 15; + ve->defaults[3] = 1; + ve->sub_format = 0; + ve->limits[0][0] = 1; + ve->limits[1][0] = 255; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 7; + + ve->limits[0][2] = 1; + ve->limits[1][2] = (120 * 25); + ve->limits[0][3] = 0; + ve->limits[1][3] = 1; + ve->has_user = 0; + ve->description = "Transition Fade to Color"; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Color", "Frame length", "Mode" ); + return ve; +} + +void colorfade_apply(VJFrame *frame, int width, int height, int opacity, + int color) +{ + unsigned int i, op0, op1; + unsigned int len = width * height; + uint8_t colorCb = 128, colorCr = 128; + uint8_t colorY; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + switch (color) { + case VJ_EFFECT_COLOR_RED: + colorCb = VJ_EFFECT_CB_RED; + colorCr = VJ_EFFECT_CR_RED; + colorY = VJ_EFFECT_LUM_RED; + break; + case VJ_EFFECT_COLOR_BLUE: + colorCb = VJ_EFFECT_CB_BLUE; + colorCr = VJ_EFFECT_CR_BLUE; + colorY = VJ_EFFECT_LUM_BLUE; + + break; + case VJ_EFFECT_COLOR_GREEN: + colorCb = VJ_EFFECT_CB_GREEN; + colorCr = VJ_EFFECT_CR_GREEN; + colorY = VJ_EFFECT_LUM_GREEN; + + break; + case VJ_EFFECT_COLOR_CYAN: + colorCb = VJ_EFFECT_CB_CYAN; + colorCr = VJ_EFFECT_CR_CYAN; + colorY = VJ_EFFECT_LUM_CYAN; + + break; + case VJ_EFFECT_COLOR_MAGNETA: + colorCb = VJ_EFFECT_CB_MAGNETA; + colorCr = VJ_EFFECT_CR_MAGNETA; + colorY = VJ_EFFECT_LUM_MAGNETA; + + break; + case VJ_EFFECT_COLOR_YELLOW: + colorCb = VJ_EFFECT_CB_YELLOW; + colorCr = VJ_EFFECT_CR_YELLOW; + colorY = VJ_EFFECT_LUM_YELLOW; + + break; + case VJ_EFFECT_COLOR_BLACK: + colorCb = VJ_EFFECT_CB_BLACK; + colorCr = VJ_EFFECT_CR_BLACK; + colorY = VJ_EFFECT_LUM_BLACK; + + break; + case VJ_EFFECT_COLOR_WHITE: + colorCb = VJ_EFFECT_CB_WHITE; + colorCr = VJ_EFFECT_CR_WHITE; + break; + } + + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + for (i = 0; i < len; i++) + Y[i] = (op0 * Y[i] + op1 * colorY) >> 8; + for (i = 0; i < uv_len; i++) { + Cb[i] = (op0 * Cb[i] + op1 * colorCb) >> 8; + Cr[i] = (op0 * Cr[i] + op1 * colorCr) >> 8; + } +} +void fadecolor_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolor.h b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolor.h new file mode 100644 index 00000000..460d09ec --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolor.h @@ -0,0 +1,63 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FADECOLOR_H +#define FADECOLOR_H +#include +#include +#include + +vj_effect *fadecolor_init(); +void colorfade_apply( VJFrame *frame, int width, int height, int opacity, + int n); + +#endif +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FADECOLOR_H +#define FADECOLOR_H +#include "../vj-effect.h" +#include +#include + +vj_effect *fadecolor_init(int w, int h); +void colorfade_apply(uint8_t * yuv1[3], int width, int height, int opacity, + int n); + +void fadecolor_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolorrgb.c b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolorrgb.c new file mode 100644 index 00000000..85e7b330 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolorrgb.c @@ -0,0 +1,90 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "fadecolorrgb.h" + +vj_effect *fadecolorrgb_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 6; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 150; + ve->defaults[1] = 0; + ve->defaults[2] = 0; + ve->defaults[3] = 0; + ve->defaults[4] = 0; + ve->defaults[5] = 75; + ve->sub_format = 0; + ve->limits[0][0] = 1; + ve->limits[1][0] = 255; + + ve->limits[0][1] = 1; + ve->limits[1][1] = 255; + + ve->limits[0][2] = 1; + ve->limits[1][2] = 255; + ve->limits[0][3] = 0; + ve->limits[1][3] = 255; + + ve->limits[0][4] = 0; + ve->limits[1][4] = 1; + + ve->limits[0][5] = 1; + ve->limits[1][5] = (25 * 120); + ve->description = "Transition Fade to Color by RGB"; + ve->has_user = 0; + ve->extra_frame = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Red","Green", "Blue", "Mode", "Frame length"); + return ve; +} + +void colorfadergb_apply( VJFrame *frame, int width, int height, + int opacity, int r, int g, int b) +{ + unsigned int i, op0, op1; + unsigned int len = width * height; + unsigned int colorCb = 128, colorCr = 128; + unsigned int colorY; + const int uv_len = frame->uv_len; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + + + colorY = ((0.257 * r) + (0.504 * g) + (0.098 * b) + 16); + colorCb = ((0.439 * r) - (0.368 * g) - (0.071 * b) + 128); + colorCr = (-(0.148 * r) - (0.291 * g) + (0.439 * b) + 128); + + + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + for (i = 0; i < len; i++) + Y[i] = (op0 * Y[i] + op1 * colorY) / 255; + for (i = 0; i < uv_len; i++) { + Cb[i] = (op0 * Cb[i] + op1 * colorCb) / 255; + Cr[i] = (op0 * Cr[i] + op1 * colorCr) / 255; + } +} +void fadecolorrgb_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolorrgb.h b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolorrgb.h new file mode 100644 index 00000000..4dcd475e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/fadecolorrgb.h @@ -0,0 +1,63 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FADECOLORRGB_H +#define FADECOLORRGB_H +#include +#include +#include + +vj_effect *fadecolorrgb_init(); +void colorfadergb_apply(VJFrame *frame, int width, int height, + int opacity, int r, int g, int b); + +#endif +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef FADECOLORRGB_H +#define FADECOLORRGB_H +#include "../vj-effect.h" +#include +#include + +vj_effect *fadecolorrgb_init(int w, int h); +void colorfadergb_apply(uint8_t * yuv1[3], int width, int height, + int opacity, int r, int g, int b); + +void fadecolorrgb_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/slidingdoor.c b/branches/V-1.5.3/veejay-server/libvje/transitions/slidingdoor.c new file mode 100644 index 00000000..0537858f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/slidingdoor.c @@ -0,0 +1,94 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "transblend.h" +#include +#include + +vj_effect *slidingdoor_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 0; + ve->defaults = (int *) vj_calloc(sizeof(int) * 1); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * 1); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * 1); /* max */ + /* ve->defaults[0] = 1; + ve->defaults[1] = 1; + + ve->limits[0][0] = 1; + ve->limits[1][0] = height / 16; +*/ + ve->sub_format = 1; + + /* ve->limits[0][1] = 0; + ve->limits[1][1] = 1; +*/ + ve->description = "AlphaLuma Overlay"; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = NULL; + return ve; +} + + + +void slidingdoor_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int size) +{ + + //@ alpha luma + unsigned int i; + const int len = frame->len; + uint8_t *Y = frame->data[0]; + const uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb= frame->data[1]; + uint8_t *Cr= frame->data[2]; + const uint8_t *Cb2= frame2->data[1]; + const uint8_t *Cr2= frame2->data[2]; + + + for( i = 0; i < len ; i ++ ) + { + unsigned int op0 = Y2[i]; + unsigned int op1 = 255 - op0; + Y[i] = (op0 * Y[i] + op1 * Y2[i]) >> 8; + Cb[i] = (op0 * Cb[i] + op1 * Cb2[i]) >> 8; + Cr[i] = (op0 * Cr[i] + op1 * Cr2[i]) >> 8; + } +/* + frameborder_yuvdata( + frame->data[0], + frame->data[1], + frame->data[2], + frame2->data[0], + frame2->data[1], + frame2->data[2], + width,height, + size*16, + size*16, + 0, + 0, + frame->shift_h, + frame->shift_v );*/ + +} +void slidingdoor_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/slidingdoor.h b/branches/V-1.5.3/veejay-server/libvje/transitions/slidingdoor.h new file mode 100644 index 00000000..cdc431a3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/slidingdoor.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef SLIDINGDOOR_H +#define SLIDINGDOOR_H +#include +#include +#include + +vj_effect *slidingdoor_init(int width, int height); +void slidingdoor_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int size); + + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transblend.c b/branches/V-1.5.3/veejay-server/libvje/transitions/transblend.c new file mode 100644 index 00000000..387a5ca0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transblend.c @@ -0,0 +1,112 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "transblend.h" +#include + +vj_effect *transblend_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 7; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 1; + ve->defaults[1] = 50; + ve->defaults[2] = 50; + ve->defaults[3] = 50; + ve->defaults[4] = 50; + ve->defaults[5] = 50; + ve->defaults[6] = 50; + ve->limits[0][0] = 0; + ve->limits[1][0] = 30; + ve->limits[0][1] = 1; + ve->limits[1][1] = width; + ve->limits[0][2] = 1; + ve->limits[1][2] = height; + ve->limits[0][3] = 1; + ve->limits[1][3] = width; + ve->limits[0][4] = 1; + ve->limits[1][4] = height; + ve->limits[0][5] = 1; + ve->limits[1][5] = width; + ve->limits[0][6] = 1; + ve->limits[1][6] = height; + ve->description = "Transition Translate Blend"; + ve->param_description = vje_build_param_list( ve->num_params, "Mode", "Width", "Height", "Ax offset", "Ay offset" , "Bx offset", "By offset"); + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + return ve; +} + + + +void transblend_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int type, int twidth, int theight, + int x1, int y1, int x2, int y2) +{ + + int x, y; + int p, q; + int uv_width = frame->uv_width; + + int uvy1, uvy2, uvx1, uvx2; + uint8_t *Y, *Cb, *Cr, *Y2, *Cb2, *Cr2; + pix_func_Y func_y = get_pix_func_Y((const int) type); + pix_func_C func_c = get_pix_func_C((const int) type); + + uvy1 = y1 >> frame->shift_v; + uvy2 = y2 >> frame->shift_v; + uvx1 = x1 >> frame->shift_h; + uvx2 = x2 >> frame->shift_h; + + Y = frame->data[0]; + Cb = frame->data[1]; + Cr = frame->data[2]; + Y2 = frame2->data[0]; + Cb2 = frame2->data[1]; + Cr2 = frame2->data[2]; + + + + if( (theight + y2) > height ) y2 = (height-theight); + if( (twidth + x2) > width) x2 = (width-twidth); + + for (y = 0; y < theight; y++) { + for (x = 0; x < twidth; x++) { + p = (y2 + y) * width + x2 + x; + q = (y1 + y) * width + x1 + x; + Y[p] = func_y(Y[p], Y2[q]); + } + } + for (y = 0; y < (theight >> frame->shift_v); y++) { + for (x = 0; x < (twidth / frame->shift_h); x++) { + p = (uvy2 + y) * uv_width + uvx2 + x; + q = (uvy1 + y) * uv_width + uvx1 + x; + Cb[p] = func_c( Cb[p], Cb2[q]); + Cr[p] = func_c( Cr[p], Cr2[q]); + } + } + +} +void transblend_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transblend.h b/branches/V-1.5.3/veejay-server/libvje/transitions/transblend.h new file mode 100644 index 00000000..d57d2f44 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transblend.h @@ -0,0 +1,69 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRANSBLEND_H +#define TRANSBLEND_H +#include +#include +#include + +vj_effect *transblend_init(int width, int height); + +void transblend_apply( VJFrame *frame, VJFrame *frame2, int w, int h, + int mode, int twidth, int theight, int x1, int y1, + int x2, int y2); + + +#endif +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRANSBLEND_H +#define TRANSBLEND_H +#include "../vj-effect.h" +#include +#include + +vj_effect *transblend_init(int width, int height); + +void transblend_apply(uint8_t * yuv1[3], uint8_t * yuv2[3], int w, int h, + int mode, int twidth, int theight, int x1, int y1, + int x2, int y2); + + +void transblend_free(); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transcarot.c b/branches/V-1.5.3/veejay-server/libvje/transitions/transcarot.c new file mode 100644 index 00000000..1faa9d72 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transcarot.c @@ -0,0 +1,272 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "transcarot.h" + + +vj_effect *transcarot_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 6; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 180; /* opacity */ + ve->defaults[1] = 0; /* type */ + ve->defaults[2] = 100; /* point sizse */ + ve->defaults[3] = (height / 2); /* dy */ + ve->defaults[4] = 40; /* dye */ + ve->defaults[5] = (width / 2); /* row */ + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + + ve->limits[0][1] = 0; + ve->limits[1][1] = 1; + ve->limits[0][2] = 1; + ve->limits[1][2] = width; + ve->limits[0][3] = 1; + ve->limits[1][3] = height; + ve->limits[0][4] = 1; + ve->limits[1][4] = height; + ve->limits[0][5] = 1; + ve->limits[1][5] = width; + ve->sub_format = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Mode", "Point size", "By start", "By end","Row"); + ve->description = "Transition Translate Carot"; + ve->has_user = 0; + ve->extra_frame = 1; + return ve; +} +void transcarot1_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int point_size, int dy, int dye, + int row_start, int opacity) +{ + + int row_length = 1; + int reverse = 0; + int i; + unsigned int op0, op1; + unsigned int uv_width = frame->uv_width; + int uv_dy, uv_dye, uv_row_start, uv_row_length; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + + + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + uv_dy = dy >> frame->shift_v; + uv_dye = dye >> frame->shift_v; + uv_row_start = row_start; + uv_row_length = 1; + + while (dy >= dye && row_length > 0) + { + for (i = row_start; i < (row_start + row_length); i++) + { + Y[(dy * width + i)] = + (op0 * Y[(dy * width + i)] + + op1 * Y2[(dy * width + i)]) >> 8 ; + + } + if (reverse == 1) + { + row_length -= 2; + row_start++; + } + else + { + row_length += 2; + row_start--; + } + + if (row_length >= point_size) + reverse = 1; + dy--; + } + + reverse = 0; + i = 0; + + while (uv_dy >= uv_dye && uv_row_length > 0) + { + for (i = uv_row_start; i < ((uv_row_start + uv_row_length) >> frame->shift_v); i++) + { + Cb[(uv_dy * uv_width + i)] = + (op0 * Cb[(uv_dy * uv_width + i)] + + op1 * Cb2[(uv_dy * uv_width + i)]) >>8; + Cr[(uv_dy * uv_width + i)] = + (op0 * Cr[(uv_dy * uv_width + i)] + + op1 * Cr2[(uv_dy * uv_width + i)]) >> 8; + } + + if (reverse == 1) { + uv_row_length -= 2; + uv_row_start++; + } + else + { + uv_row_length += 2; + uv_row_start--; + } + if (uv_row_length >= point_size) + reverse = 1; + dy--; + } + +} + +/* carot transistion. like translate, but different form and with mirroring */ +void transcarot2_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int point_size, int dy, int dye, + int row_start, int opacity) +{ + + int row_length = 1; + int reverse = 0; + int i; + unsigned int op0, op1; + unsigned int len = (width * height); + unsigned int uv_width = frame->uv_width; + int uv_dy, uv_dye, uv_row_start, uv_row_length; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + + + + op1 = (opacity > 235) ? 235 : opacity; + op0 = 235 - op1; + + uv_dy = dy >> frame->shift_v; + uv_dye = dye >> frame->shift_v; + uv_row_start = row_start; + uv_row_length = 1; + + while (dy >= dye && row_length > 0) + { + if (reverse == 0) + { + for (i = row_start; i < (row_start + row_length); i++) + { + Y[(dy * width + i)] = + (op0 * Y[(dy * width + i)] + + op1 * Y2[(dy * width + i)]) >> 8; + } + } + else + { + for (i = row_start; i < (row_start + row_length); i++) + { + Y[(dy * width + i)] = + (op0 * Y[(dy * width + i)] + + op1 * Y2[len - (dy * width + i)]) >> 8; + } + } + + if (reverse == 1) + { + row_length -= 2; + row_start++; + } + else + { + row_length += 2; + row_start--; + } + + if (row_length >= point_size) + reverse = 1; + dy--; + } + + reverse = 0; + i = 0; + + while (uv_dy >= uv_dye && uv_row_length > 0) + { + if (reverse == 0) + { + for (i = uv_row_start; + i < ((uv_row_start + uv_row_length) >> frame->shift_v); i++) + { + Cb[(uv_dy * uv_width + i)] = + (op0 * Cb[(uv_dy * uv_width + i)] + + op1 * Cb2[(uv_dy * uv_width + i)]) >> 8; + Cr[(uv_dy * uv_width + i)] = + (op0 * Cr[(uv_dy * uv_width + i)] + + op1 * Cr2[(uv_dy * uv_width + i)]) >> 8; + + } + } + else + { + for (i = uv_row_start; + i < ((uv_row_start + uv_row_length) >> frame->shift_v); i++) + { + Cb[(uv_dy * uv_width + i)] = + (op0 * Cb[(uv_dy * uv_width + i)] + + op1 * Cb2[len - (uv_dy * uv_width + i)]) >> 8; + Cr[(uv_dy * uv_width + i)] = + (op0 * Cr[(uv_dy * uv_width + i)] + + op1 * Cr2[len - (uv_dy * uv_width + i)]) >> 8; + + } + } + if (reverse == 1) + { + uv_row_length -= 2; + uv_row_start++; + } + else + { + uv_row_length += 2; + uv_row_start--; + } + if (uv_row_length >= point_size) + reverse = 1; + dy--; + } + +} + +void transcarot_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int p, int dy, int dye, int row, + int opacity, int type) +{ + if (type == 1) + transcarot1_apply(frame, frame2, width, height, p, dy, dye, row, + opacity); + if (type == 0) + transcarot2_apply(frame, frame2, width, height, p, dy, dye, row, + opacity); +} +void transcarot_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transcarot.h b/branches/V-1.5.3/veejay-server/libvje/transitions/transcarot.h new file mode 100644 index 00000000..5e208ae0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transcarot.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRANSCAROT_H +#define TRANSCAROT_H +#include +#include +#include + +vj_effect *transcarot_init(int width, int height); + +void transcarot_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int p, int dy, int dye, int row, + int opacity, int type); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transline.c b/branches/V-1.5.3/veejay-server/libvje/transitions/transline.c new file mode 100644 index 00000000..5e74be5d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transline.c @@ -0,0 +1,160 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "transline.h" + +vj_effect *transline_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 4; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 150; /* opacity */ + ve->defaults[1] = 10; /* line width */ + ve->defaults[2] = 3; /* distance */ + ve->defaults[3] = 0; /* type */ + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + + ve->limits[0][1] = 1; + ve->limits[1][1] = width; + ve->limits[0][2] = 2; + ve->limits[1][2] = width; + ve->limits[0][3] = 0; + ve->limits[1][3] = 1; + ve->sub_format = 1; + ve->description = "Transition Line"; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Line width", "Distance" , "Mode"); + return ve; +} + +void transline1_apply(uint8_t * yuv1[3], uint8_t * yuv2[3], int width, + int height, int distance, int line_width) +{ + unsigned int uv_width = width >> 1; + unsigned int uv_height = height >> 1; + unsigned int uv_distance = distance >> 1; + int x, y, z; + int step; + + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x += distance) { + step = line_width; + if (distance < step) + step = distance - 1; + for (z = 0; z < step; z++) { + yuv1[0][(y * width + x + z)] = + yuv2[0][(y * width + x + z)]; + } + } + } + uv_width >>= 1; + uv_height >>= 1; + line_width >>= 1; + for (y = 0; y < uv_height; y++) { + for (x = 0; x < uv_width; x += uv_distance) { + step = line_width; + if (uv_distance > step) + step = uv_distance; + for (z = 0; z < step; z++) { + yuv1[1][y * uv_width + x + z] = yuv2[1][y * uv_width + x]; + yuv1[2][y * uv_width + x + z] = + yuv2[2][y * uv_width + x + z]; + } + + } + } + +} + + + +void transline2_apply(uint8_t * yuv1[3], uint8_t * yuv2[3], int width, + int height, int distance, int line_width, + int opacity) +{ + unsigned int op0, op1; + int x, y, z=0; + int step; + + + op1 = (opacity > 235) ? 235 : opacity; + op0 = 235 - op1; + for (y = 0; y < height; y++) { + for (x = 0; (x + z + distance) < width; x += distance) { + step = line_width; + if (distance < step) + step = distance - 1; + for (z = 0; z < step; z++) { + yuv1[0][(y * width + x + z)] = + (op0 * yuv1[0][(y * width + x + z)] + + op1 * yuv2[0][(y * width + x + z)]) / 235; + yuv1[1][(y * width + x + z)] = + (op0 * yuv1[1][(y * width + x + z)] + + op1 * yuv2[1][(y * width + x + z)]) / 235; + yuv1[2][(y * width + x + z)] = + (op0 * yuv1[2][(y * width + x + z)] + + op1 * yuv2[2][(y * width + x + z)]) / 235; + + } + } + } + + /* + uv_width >>= 1; + uv_height >>= 1; + line_width >>= 1; + for (y = 0; y < uv_height; y++) { + for (x = 0; x < uv_width; x += uv_distance) { + step = line_width; + if (uv_distance > step) + step = uv_distance; + for (z = 0; z < step; z++) { + yuv1[1][y * uv_width + x + z] = + (op0 * yuv1[1][y * uv_width + x + z] + + op1 * yuv2[1][y * uv_width + x]) / 235; + yuv1[2][y * uv_width + x + z] = + (op0 * yuv1[2][y * uv_width + x + z] + + op1 * yuv2[2][y * uv_width + x + z]) / 235; + } + + } + } + */ + +} +void transline_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int distance, int line_width, int opacity, + int type) +{ + if (type == 1) + transline1_apply(frame->data, frame2->data, width, height, distance, line_width); + if (type == 0) + transline2_apply(frame->data, frame2->data, width, height, distance, line_width, + opacity); +} +void transline_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transline.h b/branches/V-1.5.3/veejay-server/libvje/transitions/transline.h new file mode 100644 index 00000000..1b0774dd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transline.h @@ -0,0 +1,32 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRANSLINE_H +#define TRANSLINE_H +#include +#include +#include + +vj_effect *transline_init(int width, int height); + +void transline_apply( VJFrame *frame, VJFrame *frame2, int width, + int height, int distance, int line_width, int opacity, + int type); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transop.c b/branches/V-1.5.3/veejay-server/libvje/transitions/transop.c new file mode 100644 index 00000000..63c73361 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transop.c @@ -0,0 +1,121 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2005 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include "transop.h" + +vj_effect *transop_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 7; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 150; /* opacity */ + ve->defaults[1] = 265; /* width of view port */ + ve->defaults[2] = 194; /* height of viewport */ + ve->defaults[3] = 59; /* y1 */ + ve->defaults[4] = 58; /* x1 */ + ve->defaults[5] = 45; /* y2 */ + ve->defaults[6] = 58; /* x2 */ + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + + ve->limits[0][1] = 0; + ve->limits[1][1] = width; + ve->limits[0][2] = 0; + ve->limits[1][2] = height; + ve->limits[0][3] = 0; + ve->limits[1][3] = height; + ve->limits[0][4] = 0; + ve->limits[1][4] = width; + ve->limits[0][5] = 0; + ve->limits[1][5] = height; + ve->limits[0][6] = 0; + ve->limits[1][6] = width; + ve->description = "Transition Translate Opacity"; + ve->sub_format = 1; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Width", "Height", "Ay", "Ax", "By", "Bx"); + return ve; +} + +/* translate, twidth,theight: size of block to transform */ +/* moves block(x2,y2) to (x1,y1), size of block to move is twidth * theight */ +void transop_apply( VJFrame *frame, VJFrame *frame2, + int twidth, int theight, int x1, int y1, int x2, int y2, + int width, int height, int opacity) +{ + int x, y; + unsigned int op0, op1; + + uint8_t *dY = frame->data[0]; + uint8_t *dCb = frame->data[1]; + uint8_t *dCr = frame->data[2]; + uint8_t *sY = frame2->data[0]; + uint8_t *sCb = frame2->data[1]; + uint8_t *sCr = frame2->data[2]; + + op1 = (opacity > 255) ? 255 : opacity; + op0 = 255 - op1; + + int view_width = twidth; + int view_height = theight; + int sy = y1; + int sx = x1; + + int dy = y2; + int dx = x2; + + if ( (dx + view_width ) > width ) + view_width = width - dx; + if ( (dy + view_height ) > height ) + view_height = height - dy; + + + if ( (sy + view_height) > height ) + view_height = height - sy; + if ( (sx + view_width ) > width ) + view_width = width - sx; + + + for( y = 0 ; y < view_height; y ++ ) + { + for( x = 0 ; x < view_width; x ++ ) + { + dY[ (dy + y ) * width + dx + x ] = + sY[ (sy + y) * width + sx + x ]; + + dCb[ (dy + y ) * width + dx + x ] = + sCb[ (sy + y) * width + sx + x ]; + + dCr[ (dy + y ) * width + dx + x ] = + sCr[ (sy + y) * width + sx + x ]; + + } + } + + +} + +void transop_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/transop.h b/branches/V-1.5.3/veejay-server/libvje/transitions/transop.h new file mode 100644 index 00000000..9bca815b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/transop.h @@ -0,0 +1,31 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef TRANSOP_H +#define TRANSOP_H +#include +#include +#include + +vj_effect *transop_init(int width, int height); +void transop_apply( VJFrame *frame, VJFrame *frame2, + int twidth, int theight, int x1, int y1, int x2, int y2, + int width, int height, int opacity); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/vbar.c b/branches/V-1.5.3/veejay-server/libvje/transitions/vbar.c new file mode 100644 index 00000000..9209b34e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/vbar.c @@ -0,0 +1,132 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#include +#include +#include +#include +#include "vbar.h" + +vj_effect *vbar_init(int width, int height) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 5; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); /* default values */ + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* min */ + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); /* max */ + ve->defaults[0] = 4; + ve->defaults[1] = 1; + ve->defaults[2] = 3; + ve->defaults[3] = 0; + ve->defaults[4] = 0; + ve->limits[0][0] = 1; + ve->limits[1][0] = height; + + ve->limits[0][1] = 0; + ve->limits[1][1] = height; + + ve->limits[0][2] = 0; + ve->limits[1][2] = height; + + ve->limits[0][3] = 0; + ve->limits[1][3] = height; + ve->limits[0][4] = 0; + ve->limits[1][4] = height; + + ve->description = "Vertical Sliding Bars"; + ve->sub_format = 1; + + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Divider", "Top Y", "Bot Y", "Top X", "Bot X" ); + return ve; +} + +/* p0 351 , p1 92 : positioneert image 1 bovenaan + p4 beweegt image offset verticaal (frame in frame) + p5 beweegt image offset horizontaal (frame in frame) */ +static int bar_top_auto = 0; +static int bar_bot_auto = 0; +static int bar_top_vert = 0; +static int bar_bot_vert = 0; +void vbar_apply(VJFrame *frame, VJFrame *frame2, int width, int height,int divider, int top_y, int bot_y, int top_x, int bot_x ) { + + //int top_width = width; /* frame in frame destination area */ + int top_height = height/(divider); + + int top_width = width/divider; + int bottom_width = width - top_width; + + //int bottom_width = width; /* frame in frame destionation area */ + + int x,y; + int yy=0; + + int y2 = bar_top_auto + top_y; /* destination */ + int x2 = bar_top_vert + top_x; + uint8_t *Y = frame->data[0]; + uint8_t *Cb = frame->data[1]; + uint8_t *Cr = frame->data[2]; + uint8_t *Y2 = frame2->data[0]; + uint8_t *Cb2 = frame2->data[1]; + uint8_t *Cr2 = frame2->data[2]; + int len = frame->len; + + + + if(y2 > height) { y2 = 0; bar_top_auto = 0; } + if(x2 > width) { x2 = 0; bar_top_vert = 0; } + + /* start with top frame in a frame */ + for( y = 0; y < height-y2; y++ ) { + for ( x = 0; x < top_width; x++ ) { + Y[ (y*width + x)] = Y2[ ( (y+y2) *width + x +x2)]; + Cb[ (y*width + x)] = Cb2[ ( (y+y2) *width + x +x2)]; + Cr[ (y*width + x)] = Cr2[ ( (y+y2) *width + x +x2)]; + } + } + + /* do bottom part */ + y2 = bar_bot_auto + bot_y; + x2 = bar_bot_vert + bot_x; + + if(y2 > height) { y2 = 0; bar_bot_auto = 0; } + if(x2 > width) { x2 = 0; bar_bot_vert = 0; } + + /* start with bottom frame in a frame */ + for ( y = 0; (yy+y2) < height; y++) { + yy++; + for(x=bottom_width; (x+x2) < width; x++ ) { + int pos = (yy+y2) * width +x + x2 ; + if(pos + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef VBAR_H +#define VBAR_H +#include +#include +#include + +vj_effect *vbar_init(int width, int height); +void vbar_apply( VJFrame *frame, VJFrame *frame2, + int width, int height, int d, int x1, int x2, int t1, int b1); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/wipe.c b/branches/V-1.5.3/veejay-server/libvje/transitions/wipe.c new file mode 100644 index 00000000..509ea237 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/wipe.c @@ -0,0 +1,66 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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 "wipe.h" +#include "transop.h" + +vj_effect *wipe_init(int w,int h) +{ + vj_effect *ve = (vj_effect *) vj_calloc(sizeof(vj_effect)); + ve->num_params = 2; + ve->defaults = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[0] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->limits[1] = (int *) vj_calloc(sizeof(int) * ve->num_params); + ve->defaults[0] = 150; + ve->defaults[1] = 0; + + ve->limits[0][0] = 0; + ve->limits[1][0] = 255; + ve->limits[0][1] = 0; + ve->limits[1][1] = 25; + ve->description = "Transition Wipe"; + ve->sub_format = 0; + ve->extra_frame = 1; + ve->has_user = 0; + ve->param_description = vje_build_param_list(ve->num_params, "Opacity", "Increment" ); + return ve; + +} +// FIXME private + +static int g_wipe_width = 0; +static int g_wipe_height = 0; +void wipe_apply( VJFrame *frame, VJFrame *frame2, + int w, int h, int opacity, int inc) +{ + /* w, h increasen */ + transop_apply(frame, frame2, g_wipe_width, g_wipe_height, 0, 0, 0, 0, w, + h, opacity); + g_wipe_width += inc; + g_wipe_height += ((w / h) - 0.5 + inc); + + if (g_wipe_width > w || g_wipe_height > h) { + g_wipe_width = 0; + g_wipe_height = 0; + } +} +void wipe_free(){} diff --git a/branches/V-1.5.3/veejay-server/libvje/transitions/wipe.h b/branches/V-1.5.3/veejay-server/libvje/transitions/wipe.h new file mode 100644 index 00000000..e8e0b6af --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/transitions/wipe.h @@ -0,0 +1,30 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef WIPE_H +#define WIPE_H +#include +#include +#include + +vj_effect *wipe_init(); +void wipe_apply( VJFrame *frame, VJFrame *frame2, + int width, int height, int opacity, int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvje/vj-effect.c b/branches/V-1.5.3/veejay-server/libvje/vj-effect.c new file mode 100644 index 00000000..a4cb88e8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/vj-effect.c @@ -0,0 +1,1013 @@ +/* + * Copyright (C) 2002-2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +// todo: clean up initialization (use function pointers!) + +#include +#include +#include +#include +#include +#include +#include +#include "effects/fibdownscale.h" +#include "effects/magicoverlays.h" +#include "effects/negation.h" +#include "effects/negatechannel.h" +#include "effects/radcor.h" +#include "effects/opacity.h" +#include "effects/posterize.h" +#include "effects/killchroma.h" +#include "effects/mirrors.h" +#include "effects/mirrors2.h" +#include "effects/colormap.h" +#include "effects/dices.h" +#include "effects/emboss.h" +#include "effects/flip.h" +#include "effects/revtv.h" +#include "effects/softblur.h" +#include "effects/split.h" +#include "effects/widthmirror.h" +#include "effects/dither.h" +#include "effects/borders.h" +#include "effects/dummy.h" +#include "effects/frameborder.h" +#include "effects/rawman.h" +#include "effects/rawval.h" +#include "effects/solarize.h" +#include "effects/smuck.h" +#include "effects/transform.h" +#include "effects/coloradjust.h" +#include "effects/gamma.h" +#include "effects/rgbkey.h" +#include "effects/median.h" +#include "transitions/transblend.h" +#include "transitions/slidingdoor.h" +#include "transitions/fadecolor.h" +#include "transitions/transop.h" +#include "transitions/transline.h" +#include "transitions/transcarot.h" +#include "transitions/wipe.h" +#include "transitions/vbar.h" +#include "effects/diff.h" +#include "effects/bgsubtract.h" +#include "effects/texmap.h" +#include "effects/contourextract.h" +#include "effects/autoeq.h" +#include "effects/colorhis.h" +#include "effects/diffimg.h" +#include "effects/whiteframe.h" +#include "effects/lumakey.h" +#include "effects/chromamagick.h" +#include "effects/lumablend.h" +#include "effects/magicoverlays.h" +#include "effects/lumamagick.h" +#include "transitions/fadecolorrgb.h" +#include "effects/reflection.h" +#include "effects/rotozoom.h" +#include "effects/scratcher.h" +#include "effects/colorshift.h" +#include "effects/opacitythreshold.h" +#include "effects/opacityadv.h" +#include "effects/iris.h" +#include "effects/rgbkeysmooth.h" +#include "effects/magicscratcher.h" +#include "effects/chromascratcher.h" +#include "effects/distort.h" +#include "effects/tracer.h" +#include "effects/mtracer.h" +#include "effects/dupmagic.h" +#include "effects/keyselect.h" +#include "effects/greyselect.h" +#include "effects/bwselect.h" +#include "effects/complexinvert.h" +#include "effects/complexthreshold.h" +#include "effects/complexsaturate.h" +#include "effects/complexsync.h" +#include "effects/isolate.h" +#include "transitions/3bar.h" +#include "effects/enhancemask.h" +#include "effects/noiseadd.h" +#include "effects/contrast.h" +#include "effects/motionblur.h" +#include "effects/sinoids.h" +#include "effects/average.h" +#include "effects/ripple.h" +#include "effects/rippletv.h" +#include "effects/waterrippletv.h" +#include "effects/bathroom.h" +#include "effects/slicer.h" +#include "effects/timedistort.h" +#include "effects/chameleon.h" +#include "effects/baltantv.h" +#include "effects/radioactive.h" +#include "effects/chameleonblend.h" +#include "effects/slice.h" +#include "effects/zoom.h" +#include "effects/deinterlace.h" +#include "effects/mask.h" +#include "effects/crosspixel.h" +#include "effects/color.h" +#include "effects/noisepencil.h" +#include "effects/pencilsketch.h" +#include "effects/magicmirror.h" +#include "effects/lumamask.h" +#include "effects/smear.h" +#include "effects/raster.h" +#include "effects/fisheye.h" +#include "effects/swirl.h" +#include "effects/radialblur.h" +#include "effects/binaryoverlays.h" +#include "effects/chromium.h" +#include "effects/chromapalette.h" +#include "effects/uvcorrect.h" +#include "effects/dissolve.h" +#include "effects/overclock.h" +#include "effects/cartonize.h" +#include "effects/nervous.h" +#include "effects/morphology.h" +#include "effects/threshold.h" +#include "effects/motionmap.h" +#include "effects/colmorphology.h" +#include "effects/blob.h" +#include "effects/ghost.h" +#include "effects/boids.h" +#include "effects/tripplicity.h" +#include "effects/neighbours.h" +#include "effects/neighbours2.h" +#include "effects/neighbours3.h" +#include "effects/neighbours4.h" +#include "effects/neighbours5.h" +#include "effects/cutstop.h" +#include "effects/maskstop.h" +#include "effects/photoplay.h" +#include "effects/videoplay.h" +#include "effects/videowall.h" +#include "effects/flare.h" +#include "effects/constantblend.h" +#include "effects/colflash.h" +#include "effects/rgbchannel.h" +#include "effects/diffmap.h" +#include "plugload.h" +#include "effects/picinpic.h" +#include "effects/cali.h" + +int pixel_Y_hi_ = 235; +int pixel_U_hi_ = 240; +int pixel_Y_lo_ = 16; +int pixel_U_lo_ = 16; + +int get_pixel_range_min_Y() { + return pixel_Y_lo_; +} +int get_pixel_range_min_UV() { + return pixel_U_lo_; +} + +void set_pixel_range(uint8_t Yhi,uint8_t Uhi, uint8_t Ylo, uint8_t Ulo) +{ + pixel_Y_hi_ = Yhi; + pixel_U_hi_ = Uhi; + pixel_U_lo_ = Ylo; + pixel_Y_lo_ = Ulo; +} + +static struct +{ + int (*mem_init)(int width, int height); + void (*free)(void); + int effect_id; +} simple_effect_index[] = { +{ bathroom_malloc , bathroom_free ,VJ_IMAGE_EFFECT_BATHROOM }, +{ chromascratcher_malloc , chromascratcher_free ,VJ_IMAGE_EFFECT_CHROMASCRATCHER}, +{ complexsync_malloc , complexsync_free ,VJ_VIDEO_EFFECT_COMPLEXSYNC }, +{ dices_malloc , dices_free ,VJ_IMAGE_EFFECT_DICES }, +{ colorhis_malloc, colorhis_free, VJ_IMAGE_EFFECT_COLORHIS }, +{ autoeq_malloc, autoeq_free ,VJ_IMAGE_EFFECT_AUTOEQ }, +{ magicscratcher_malloc , magicscratcher_free ,VJ_IMAGE_EFFECT_MAGICSCRATCHER }, +{ lumamask_malloc , lumamask_free ,VJ_VIDEO_EFFECT_LUMAMASK }, +{ motionblur_malloc , motionblur_free ,VJ_IMAGE_EFFECT_MOTIONBLUR }, +{ magicmirror_malloc , magicmirror_free ,VJ_IMAGE_EFFECT_MAGICMIRROR }, +{ mtracer_malloc , mtracer_free ,VJ_VIDEO_EFFECT_MTRACER }, +{ noiseadd_malloc , noiseadd_free ,VJ_IMAGE_EFFECT_NOISEADD }, +{ noisepencil_malloc , noisepencil_free ,VJ_IMAGE_EFFECT_NOISEPENCIL }, +{ reflection_malloc , reflection_free ,VJ_IMAGE_EFFECT_REFLECTION }, +{ ripple_malloc , ripple_free ,VJ_IMAGE_EFFECT_RIPPLE }, +{ rotozoom_malloc , rotozoom_free ,VJ_IMAGE_EFFECT_ROTOZOOM }, +{ scratcher_malloc , scratcher_free ,VJ_IMAGE_EFFECT_SCRATCHER }, +{ sinoids_malloc , sinoids_free ,VJ_IMAGE_EFFECT_SINOIDS }, +{ slice_malloc , slice_free ,VJ_IMAGE_EFFECT_SLICE }, +{ split_malloc , split_free ,VJ_VIDEO_EFFECT_SPLIT }, +{ tracer_malloc , tracer_free ,VJ_VIDEO_EFFECT_TRACER }, +{ zoom_malloc , zoom_free ,VJ_IMAGE_EFFECT_ZOOM }, +{ crosspixel_malloc , crosspixel_free ,VJ_IMAGE_EFFECT_CROSSPIXEL }, +{ fisheye_malloc, fisheye_free ,VJ_IMAGE_EFFECT_FISHEYE }, +{ swirl_malloc , swirl_free ,VJ_IMAGE_EFFECT_SWIRL }, +{ radialblur_malloc, radialblur_free, VJ_IMAGE_EFFECT_RADIALBLUR }, +{ uvcorrect_malloc, uvcorrect_free, VJ_IMAGE_EFFECT_UVCORRECT }, +{ overclock_malloc, overclock_free, VJ_IMAGE_EFFECT_OVERCLOCK }, +{ nervous_malloc, nervous_free, VJ_IMAGE_EFFECT_NERVOUS }, +{ morphology_malloc, morphology_free, VJ_IMAGE_EFFECT_MORPHOLOGY }, +{ differencemap_malloc, differencemap_free, VJ_VIDEO_EFFECT_EXTDIFF }, +{ threshold_malloc, threshold_free, VJ_VIDEO_EFFECT_EXTTHRESHOLD }, +{ motionmap_malloc, motionmap_free, VJ_IMAGE_EFFECT_MOTIONMAP }, +{ colmorphology_malloc, colmorphology_free, VJ_IMAGE_EFFECT_COLMORPH }, +{ blob_malloc, blob_free, VJ_IMAGE_EFFECT_VIDBLOB }, +{ boids_malloc, boids_free, VJ_IMAGE_EFFECT_VIDBOIDS }, +{ ghost_malloc, ghost_free, VJ_IMAGE_EFFECT_GHOST }, +{ neighbours_malloc, neighbours_free, VJ_IMAGE_EFFECT_NEIGHBOUR }, +{ neighbours2_malloc, neighbours2_free, VJ_IMAGE_EFFECT_NEIGHBOUR2 }, +{ neighbours3_malloc, neighbours3_free, VJ_IMAGE_EFFECT_NEIGHBOUR3 }, +{ neighbours4_malloc, neighbours4_free, VJ_IMAGE_EFFECT_NEIGHBOUR4 }, +{ neighbours5_malloc, neighbours5_free, VJ_IMAGE_EFFECT_NEIGHBOUR5 }, +{ cutstop_malloc, cutstop_free, VJ_IMAGE_EFFECT_CUTSTOP }, +{ maskstop_malloc, maskstop_free, VJ_IMAGE_EFFECT_MASKSTOP }, +{ photoplay_malloc, photoplay_free, VJ_IMAGE_EFFECT_PHOTOPLAY }, +{ videoplay_malloc, videoplay_free, VJ_VIDEO_EFFECT_VIDEOPLAY }, +{ videowall_malloc, videowall_free, VJ_VIDEO_EFFECT_VIDEOWALL }, +{ flare_malloc, flare_free, VJ_IMAGE_EFFECT_FLARE }, +{ rgbchannel_malloc, rgbchannel_free, VJ_IMAGE_EFFECT_RGBCHANNEL }, +{ timedistort_malloc, timedistort_free, VJ_IMAGE_EFFECT_TIMEDISTORT }, +{ chameleon_malloc, chameleon_free, VJ_IMAGE_EFFECT_CHAMELEON }, +{ chameleonblend_malloc, chameleonblend_free, VJ_VIDEO_EFFECT_CHAMBLEND }, +{ baltantv_malloc, baltantv_free, VJ_IMAGE_EFFECT_BALTANTV }, +{ radcor_malloc, radcor_free, VJ_IMAGE_EFFECT_LENSCORRECTION }, +{ radioactivetv_malloc, radioactivetv_free, VJ_VIDEO_EFFECT_RADIOACTIVE }, +{ waterrippletv_malloc, waterrippletv_free, VJ_IMAGE_EFFECT_RIPPLETV }, +{ bgsubtract_malloc, bgsubtract_free, VJ_IMAGE_EFFECT_BGSUBTRACT }, +{ slicer_malloc, slicer_free, VJ_VIDEO_EFFECT_SLICER }, +{ NULL , NULL ,0 }, +}; + +// complex effects have a buffer per instance +static struct +{ + int (*mem_init)(void **d,int w, int h ); + void (*free)(void *d); + int effect_id; +} complex_effect_index[] = +{ + { diff_malloc, diff_free, VJ_VIDEO_EFFECT_DIFF }, + { texmap_malloc, texmap_free, VJ_VIDEO_EFFECT_TEXMAP }, + { contourextract_malloc, contourextract_free, VJ_IMAGE_EFFECT_CONTOUR }, + { cali_malloc, cali_free, VJ_IMAGE_EFFECT_CALI }, + { picinpic_malloc, picinpic_free, VJ_VIDEO_EFFECT_PICINPIC }, + { water_malloc, water_free, VJ_VIDEO_EFFECT_RIPPLETV }, + { NULL, NULL, 0 }, +}; + +vj_effect *vj_effects[FX_LIMIT]; +int vj_effect_ready[FX_LIMIT]; + +static int max_width = 0; +static int max_height =0; + +static int n_ext_plugs_ = 0; + +int rgb_parameter_conversion_type_ = 0; + +static int _get_simple_effect( int effect_id) +{ + int i; + for(i = 0; simple_effect_index[i].effect_id != 0 ; i++) + { + if( simple_effect_index[i].effect_id == effect_id ) return i; + } + return -1; +} + +static int _get_complex_effect( int effect_id) +{ + int i; + for(i = 0; complex_effect_index[i].effect_id != 0 ; i++) + { + if( complex_effect_index[i].effect_id == effect_id ) return i; + } + return -1; +} + +static int _no_mem_required(int effect_id) +{ + if( effect_id >= VJ_EXT_EFFECT ) + return 0; + if( _get_simple_effect(effect_id) == -1 && _get_complex_effect(effect_id) == -1 ) + return 1; + return 0; +} + +int vj_effect_initialized(int effect_id) +{ + + int seq = vj_effect_real_to_sequence(effect_id); + if( seq < 0 ) + return 0; + if( _no_mem_required(effect_id) || vj_effect_ready[seq] == 1 ) + return 1; + + return 0; +} + +int vj_effect_activate_ext( int fx_id ) +{ + if( fx_id > (MAX_EFFECTS + n_ext_plugs_) ) + return 0; + int res = plug_activate( fx_id - MAX_EFFECTS ); + if(res) + { + vj_effect_ready[fx_id] = 1; + return 1; + } + return 0; +} + + +int vj_effect_activate(int effect_id) +{ + int seq = vj_effect_real_to_sequence(effect_id); + + if( seq < 0 || seq > (MAX_EFFECTS + n_ext_plugs_ )) + return 0; + + if(seq >= MAX_EFFECTS && seq < (MAX_EFFECTS + n_ext_plugs_)) + return vj_effect_activate_ext(seq); + + if( _no_mem_required(effect_id) ) + return 1; + + if( vj_effect_ready[seq] == 1 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Effect %s already initialized", + vj_effects[seq]->description); + return 1; + } + + if( vj_effect_ready[seq] == 0 ) + { + int index = _get_simple_effect(effect_id); + if(index==-1) + { + index = _get_complex_effect(effect_id); + if(index == -1) + { + return 0; + } + if(!complex_effect_index[index].mem_init( &(vj_effects[seq]->user_data), max_width, max_height )) + { + return 0; + } + else + { + veejay_msg(VEEJAY_MSG_DEBUG, "Initialized complex effects %s", + vj_effects[seq]->description); + vj_effect_ready[seq] = 1; + return 1; + } + //perhaps it is a complex effect + } + if(!simple_effect_index[index].mem_init( max_width, max_height )) + { + return 0; + } + else + { + veejay_msg(VEEJAY_MSG_DEBUG, "Initialized simple effect %s", + vj_effects[seq]->description); + vj_effect_ready[seq]= 1; + return 1; + } + } + return 1; +} + +void *vj_effect_get_data( int seq_id ) { + + return vj_effects[seq_id]->user_data; +} + +int vj_effect_deactivate(int effect_id) +{ + int seq = vj_effect_real_to_sequence(effect_id); + + if(seq < 0 || seq >= MAX_EFFECTS) + if( seq > n_ext_plugs_ + MAX_EFFECTS) return 0; + + if( vj_effect_ready[seq] == 0 ) + { + return 1; + } + if( vj_effect_ready[seq] == 1 ) + { + if( seq >= MAX_EFFECTS && seq < (n_ext_plugs_ + MAX_EFFECTS)) + { + plug_deactivate( seq - MAX_EFFECTS ); + vj_effect_ready[seq] = 0; + return 1; + } + else + { + int index = _get_simple_effect(effect_id); + if(index==-1) + { + index = _get_complex_effect(effect_id); + if(index == -1) + { + return 0; + } + complex_effect_index[index].free( vj_effects[seq]->user_data ); + vj_effect_ready[seq] = 0; + veejay_msg(VEEJAY_MSG_DEBUG, "Deactivated complex effect %s", + vj_effects[seq]->description); + return 1; + } + simple_effect_index[index].free( ); + vj_effect_ready[seq] = 0; + veejay_msg(VEEJAY_MSG_DEBUG, "Deactivated simple effect %s", + vj_effects[seq]->description); + return 1; + } + } + return 0; +} + +void vj_effect_deactivate_all() +{ + int i; + for(i = 0 ; i < MAX_EFFECTS + n_ext_plugs_; i++) + { + int effect_id = vj_effect_get_real_id( i ); + if( effect_id > 100) + { + vj_effect_deactivate( effect_id ); + } + } +} + +void vj_effect_initialize(int width, int height, int full_range) +{ + int i = VJ_VIDEO_COUNT; + int k; + + if( full_range ) + { + set_pixel_range( 255, 255,0,0 ); + } + + n_ext_plugs_ = plug_detect_plugins(); + + if( n_ext_plugs_ > 0 ) + plug_init( width,height ); + + for(k=0; k < MAX_EFFECTS; k++) + vj_effects[k] = NULL; + + vj_effects[0] = dummy_init(width,height); + vj_effects[1] = overlaymagic_init( width,height ); + vj_effects[2] = lumamagick_init( width,height ); + vj_effects[3] = diff_init(width, height); + vj_effects[4] = opacity_init( width,height ); + vj_effects[5] = lumakey_init(width, height); + vj_effects[6] = rgbkey_init( width,height ); + vj_effects[7] = chromamagick_init( width,height ); + vj_effects[8] = lumablend_init( width,height ); + vj_effects[9] = split_init(width,height); + vj_effects[10] = borders_init(width,height); + vj_effects[11] = frameborder_init(width,height); + vj_effects[12] = slidingdoor_init(width, height); + vj_effects[13] = transop_init(width, height); + vj_effects[14] = transcarot_init(width, height); + vj_effects[15] = transline_init(width, height); + vj_effects[16] = transblend_init(width, height); + vj_effects[17] = fadecolor_init(width,height); + vj_effects[18] = fadecolorrgb_init(width,height); + vj_effects[19] = whiteframe_init(width,height); + vj_effects[20] = simplemask_init(width,height); + vj_effects[21] = opacitythreshold_init(width,height); + vj_effects[22] = opacityadv_init(width,height); + vj_effects[23] = rgbkeysmooth_init(width,height); + vj_effects[24] = wipe_init(width,height); + vj_effects[25] = tracer_init(width, height); + vj_effects[26] = mtracer_init(width, height); + vj_effects[27] = dupmagic_init(width,height); + vj_effects[28] = keyselect_init(width,height); + vj_effects[29] = complexthreshold_init(width,height); + vj_effects[30] = complexsync_init(width,height); + vj_effects[31] = bar_init(width,height); + vj_effects[32] = vbar_init(width,height); + vj_effects[33] = lumamask_init(width,height); + vj_effects[34] = binaryoverlay_init(width,height); + vj_effects[35] = dissolve_init(width,height); + vj_effects[36] = tripplicity_init(width,height); + vj_effects[37] = videoplay_init(width,height); + vj_effects[38] = videowall_init(width,height); + vj_effects[39] = threshold_init(width,height); + vj_effects[40] = differencemap_init(width,height); + vj_effects[41] = picinpic_init(width,height); + vj_effects[42] = chameleonblend_init(width,height); + vj_effects[43] = radioactivetv_init(width,height); + vj_effects[44] = texmap_init( width,height); + vj_effects[45] = water_init(width,height); + vj_effects[46] = slicer_init(width,height); + vj_effects[47] = iris_init(width,height); + vj_effects[48] = dummy_init(width,height); + vj_effects[i + 1] = mirrors2_init(width,height); + vj_effects[i + 2] = mirrors_init(width,height); + vj_effects[i + 3] = widthmirror_init(width,height); + vj_effects[i + 4] = flip_init(width,height); + vj_effects[i + 5] = posterize_init(width,height); + vj_effects[i + 6] = negation_init(width,height); + vj_effects[i + 7] = solarize_init(width,height); + vj_effects[i + 8] = coloradjust_init(width,height); + vj_effects[i + 9] = gamma_init(width,height); + vj_effects[i + 10] = softblur_init(width,height); + vj_effects[i + 11] = revtv_init(width, height); + vj_effects[i + 12] = dices_init(width, height); + vj_effects[i + 13] = smuck_init(width,height); + vj_effects[i + 14] = killchroma_init(width,height); + vj_effects[i + 15] = emboss_init(width,height); + vj_effects[i + 16] = dither_init(width,height); + vj_effects[i + 17] = rawman_init(width,height); + vj_effects[i + 18] = rawval_init(width,height); + vj_effects[i + 19] = transform_init(width,height); + vj_effects[i + 20] = fibdownscale_init(width,height); + vj_effects[i + 21] = reflection_init( width,height ); + vj_effects[i + 22] = rotozoom_init(width, height); + vj_effects[i + 23] = colorshift_init(width,height); + vj_effects[i + 24] = scratcher_init(width, height); + vj_effects[i + 25] = magicscratcher_init(width, height); + vj_effects[i + 26] = chromascratcher_init(width, height); + vj_effects[i + 27] = distortion_init(width, height); + vj_effects[i + 28] = greyselect_init(width,height); + vj_effects[i + 29] = bwselect_init(width,height); + vj_effects[i + 30] = complexinvert_init(width,height); + vj_effects[i + 31] = complexsaturation_init(width,height); + vj_effects[i + 32] = isolate_init(width,height); + vj_effects[i + 33] = enhancemask_init(width,height); + vj_effects[i + 34] = noiseadd_init(width,height); + vj_effects[i + 35] = contrast_init(width,height); + vj_effects[i + 36] = motionblur_init(width,height); + vj_effects[i + 37] = sinoids_init(width,height); + vj_effects[i + 38] = average_init(width,height); + vj_effects[i + 39] = ripple_init(width,height); + vj_effects[i + 40] = bathroom_init(width,height); + vj_effects[i + 41] = slice_init(width,height); + vj_effects[i + 42] = zoom_init(width, height); + vj_effects[i + 44] = deinterlace_init(width,height); + vj_effects[i + 45] = crosspixel_init(width,height); + vj_effects[i + 46] = color_init(width,height); + vj_effects[i + 47] = diffimg_init(width,height); + vj_effects[i + 48] = noisepencil_init(width,height); + vj_effects[i + 43] = pencilsketch_init(width,height); + vj_effects[i + 50] = bgsubtract_init(width,height); + vj_effects[i + 51] = magicmirror_init(width,height); + vj_effects[i + 52] = smear_init(width,height); + vj_effects[i + 53] = raster_init(width,height); + vj_effects[i + 54] = fisheye_init(width,height); + vj_effects[i + 55] = swirl_init(width,height); + vj_effects[i + 56] = radialblur_init(width,height); + vj_effects[i + 57] = chromium_init(width,height); + vj_effects[i + 58] = chromapalette_init(width,height); + vj_effects[i + 59] = uvcorrect_init(width,height); + vj_effects[i + 60] = overclock_init(width,height); + vj_effects[i + 61] = cartonize_init(width,height); + vj_effects[i + 62] = nervous_init(width,height); + vj_effects[i + 63] = morphology_init(width,height); + vj_effects[i + 64] = blob_init(width,height); + vj_effects[i + 65] = boids_init(width,height); + vj_effects[i + 66] = ghost_init(width,height); + vj_effects[i + 67] = neighbours_init(width,height); + vj_effects[i + 68] = neighbours2_init(width,height); + vj_effects[i + 69] = neighbours3_init(width,height); + vj_effects[i + 70] = neighbours4_init(width,height); + vj_effects[i + 71] = neighbours5_init(width,height); + vj_effects[i + 72] = cutstop_init(width,height); + vj_effects[i + 73] = maskstop_init(width,height); + vj_effects[i + 74] = photoplay_init(width,height); + vj_effects[i + 75] = flare_init(width,height ); + vj_effects[i + 76] = constantblend_init(width,height); + vj_effects[i + 77] = colormap_init(width,height); + vj_effects[i + 78] = negatechannel_init(width,height); + vj_effects[i + 79] = colmorphology_init(width,height); + vj_effects[i + 80] = colflash_init(width,height); + vj_effects[i + 81] = rgbchannel_init(width,height); + vj_effects[i + 82] = autoeq_init(width,height); + vj_effects[i + 83] = colorhis_init(width,height); + vj_effects[i + 84] = motionmap_init(width,height); + vj_effects[i + 85] = timedistort_init(width,height); + vj_effects[i + 86] = chameleon_init(width,height); + vj_effects[i + 87] = baltantv_init(width,height); + vj_effects[i + 88] = contourextract_init(width,height); + vj_effects[i + 49] = waterrippletv_init(width,height); + vj_effects[i + 89 ]= radcor_init(width,height); + vj_effects[i + 90 ]= cali_init(width,height); + vj_effects[i + 91 ] = medianfilter_init(width,height); + + max_width = width; + max_height = height; + + for(i=0; i < MAX_EFFECTS; i++) + { + if(vj_effects[i]) + { + if(i!=3) vj_effects[i]->static_bg = 0; + vj_effects[i]->has_help = 0; + if(vj_effects[i]->rgb_conv != 1) + vj_effects[i]->rgb_conv = 0; + } + } + +//@ initialize external plugins + int p = 0; + int p_stop = MAX_EFFECTS + n_ext_plugs_; + + for( p = MAX_EFFECTS; p < p_stop; p ++ ) + vj_effects[p] = plug_get_plugin( (p-MAX_EFFECTS) ); + veejay_msg(VEEJAY_MSG_INFO, "Found %d effects", p_stop ); +} + +void vj_effect_free(vj_effect *ve) { + if(ve->limits[0]) free(ve->limits[0]); + if(ve->limits[1]) free(ve->limits[1]); + if(ve->defaults) free(ve->defaults); + int i = 0; + if( ve->param_description != NULL ) { + for( i = 0; ve->param_description[i] != NULL; i ++ ) + free(ve->param_description[i]); + + free(ve->param_description); + } + // if(ve->vjed) free(ve->vjed); + free(ve); +} + +void vj_effect_shutdown() { + int i; + vj_effect_deactivate_all(); + plug_free(); + for(i=0; i < vj_effect_max_effects(); i++) { + if(vj_effects[i]) { + if( i >= MAX_EFFECTS ) + if(vj_effects[i]->description) free(vj_effects[i]->description); + vj_effect_free(vj_effects[i]); + + } + } + + diff_destroy(); + texmap_destroy(); + contourextract_destroy(); + rotozoom_destroy(); + distortion_destroy(); + cali_destroy(); +} + +void vj_effect_dump() { + int i; + veejay_msg(VEEJAY_MSG_INFO, "Below follow all effects in Veejay,"); + veejay_msg(VEEJAY_MSG_INFO, "Effect numbers starting with 2xx are effects that use"); + veejay_msg(VEEJAY_MSG_INFO, "*two* sources (by default a copy of itself)"); + veejay_msg(VEEJAY_MSG_INFO, "Use the channel/source commands to select another sample/stream"); + veejay_msg(VEEJAY_MSG_INFO, "to mix with."); + veejay_msg(VEEJAY_MSG_INFO, "\n [effect num] [effect name] [arg 0 , min/max ] [ arg 1, min/max ] ..."); + for(i=0; i < vj_effect_max_effects(); i++) + { + if(vj_effects[i]) + { + printf("\t%d\t\t\t%s\t\t", vj_effect_get_real_id(i), vj_effects[i]->description); + if(vj_effects[i]->num_params > 0) + { + int j=0; + for(j=0; j < vj_effects[i]->num_params; j++) { + printf("\n\t\t\t%s\t\t\t%d\t%d - %d\n", vj_effects[i]->param_description[j] , j, vj_effects[i]->limits[0][j],vj_effects[i]->limits[1][j]); + } + } + else + printf("\n"); + } + + } +} + +/* figure out the position in the array, returns index of vj_effects array given an effect ID */ +int vj_effect_real_to_sequence(int effect_id) +{ + if( effect_id >= VJ_EXT_EFFECT ) + { + int n = effect_id; + effect_id -= VJ_EXT_EFFECT; + effect_id += MAX_EFFECTS; + return effect_id; + } + else + { + if (effect_id > VJ_IMAGE_EFFECT_MIN && effect_id < VJ_IMAGE_EFFECT_MAX) { + effect_id -= VJ_IMAGE_EFFECT_MIN; + effect_id += VJ_VIDEO_COUNT; + return effect_id; + } else if (effect_id > VJ_VIDEO_EFFECT_MIN && + effect_id < VJ_VIDEO_EFFECT_MAX) { + effect_id -= VJ_VIDEO_EFFECT_MIN; + return effect_id; + } + } + return -1; +} + + +int vj_effect_get_real_id(int effect_id) +{ + if (effect_id > 0 && effect_id < VJ_VIDEO_COUNT) + { /* video effect */ + effect_id += VJ_VIDEO_EFFECT_MIN; + return effect_id; + } + else + { + if (effect_id >= VJ_VIDEO_COUNT && effect_id < MAX_EFFECTS) + { /* image effect */ + effect_id -= VJ_VIDEO_COUNT; /* substract video count */ + effect_id += VJ_IMAGE_EFFECT_MIN; + return effect_id; + } + else + { + if( effect_id >= MAX_EFFECTS && effect_id <= vj_effect_max_effects()) + { + effect_id -= MAX_EFFECTS; + effect_id += VJ_EXT_EFFECT; + return effect_id; + } + } + } + return 0; +} + +int vj_effect_get_by_name(char *name) +{ + int i; + if(!name) return 0; + + for ( i = 0; i < vj_effect_max_effects(); i ++ ) + { + if( vj_effects[i]->description ) + { + if(strcasecmp(name, vj_effects[i]->description ) == 0 ) + return (int) vj_effect_get_real_id( i ); + } + } + + return 0; +} + +/* returns the description of an effect */ +char *vj_effect_get_description(int effect_id) +{ /* 115 */ + int entry = vj_effect_real_to_sequence(effect_id); + if (entry > 0) + return vj_effects[entry]->description; + + return ""; +} + +char *vj_effect_get_param_description(int effect_id, int param_nr) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry > 0 && param_nr < vj_effects[entry]->num_params) + return vj_effects[entry]->param_description[param_nr]; + return "Invalid paramater"; +} + +/* returns number of parameters */ +int vj_effect_get_num_params(int effect_id) +{ + int entry; + if(effect_id<0) return 0; + entry = vj_effect_real_to_sequence(effect_id); + if (entry > 0) + return vj_effects[entry]->num_params; + return 0; +} + +int vj_effect_get_static_bg(int effect_id) +{ + int entry; + if(effect_id < 0) return 0; + entry = vj_effect_real_to_sequence(effect_id); + if(entry>0) + return vj_effects[entry]->static_bg; + return 0; +} + +/* returns default value of a parameter */ +int vj_effect_get_default(int effect_id, int param_nr) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry > 0 && param_nr >= 0 + && param_nr < vj_effects[entry]->num_params) + return vj_effects[entry]->defaults[param_nr]; + return 0; +} + +/* returns minimum value of a parameter */ +int vj_effect_get_min_limit(int effect_id, int param_nr) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry > 0 && param_nr >= 0 + && param_nr < vj_effects[entry]->num_params) + return vj_effects[entry]->limits[0][param_nr]; + return 0; +} + +/* returns the maximum value of a parameter */ +int vj_effect_get_max_limit(int effect_id, int param_nr) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry > 0 && param_nr >= 0 + && param_nr < vj_effects[entry]->num_params) + return vj_effects[entry]->limits[1][param_nr]; + return 0; +} + +int vj_effect_get_extra_frame(int effect_id) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry > 0) + return vj_effects[entry]->extra_frame; + return 0; +} + +int vj_effect_get_help(int entry) +{ + if(!vj_effects[entry]) + return 0; + + return 0; +} + +int vj_effect_get_summary_len(int entry) +{ + if( !vj_effects[entry] ) + return 0; + + int p = vj_effects[entry]->num_params; + int len = strlen( vj_effects[entry]->description ); + len += 3; + len += 3; + len += 1; + len += 1; + len += 2; + len += 3; + len += ( p * 18 ); + int i; + for( i = 0; i < p; i ++ ) + len += (strlen(vj_effects[entry]->param_description[i])+3); + + + return len; +} + +int vj_effect_get_summary(int entry, char *dst) +{ + int p = vj_effects[entry]->num_params; + int i; + char tmp[512]; + + if(!vj_effects[entry]) + return 0; + + sprintf(dst,"%03d%s%03d%1d%1d%02d", + strlen( vj_effects[entry]->description), + vj_effects[entry]->description, + vj_effect_get_real_id(entry), + vj_effects[entry]->extra_frame, + vj_effects[entry]->rgb_conv, + p + ); + for(i=0; i < p; i++) + { + bzero(tmp,512); + sprintf(tmp, + "%06d%06d%06d%03d%s", + vj_effects[entry]->limits[0][i], + vj_effects[entry]->limits[1][i], + vj_effects[entry]->defaults[i], + strlen(vj_effects[entry]->param_description[i]), + vj_effects[entry]->param_description[i] + + ); + strncat( dst, tmp,strlen(tmp) ); + } + return 1; +} + +int vj_effect_max_effects() +{ + return MAX_EFFECTS + n_ext_plugs_; +} + +int vj_effect_get_subformat(int effect_id) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry >= 0) + return vj_effects[entry]->sub_format; + return 0; +} + +/* return 1 if suggested value is acceptable, 0 if not */ +int vj_effect_valid_value(int effect_id, int param_nr, int value) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry >= 0) { + if (param_nr >= 0 && param_nr < vj_effects[entry]->num_params) { + if ((value >= vj_effects[entry]->limits[0][param_nr]) && + (value <= vj_effects[entry]->limits[1][param_nr])) + return 1; + } + } + return 0; +} + +static int vj_is_complex_effect(int effect_id) +{ + int i; + for(i = 0; complex_effect_index[i].effect_id != 0; i ++ ) + { + if(effect_id == complex_effect_index[i].effect_id ) + return 1; + } + return 0; +} + +int vj_effect_has_cb(int effect_id) +{ + int entry = vj_effect_real_to_sequence( effect_id ); + if(entry < 0) return 0; + if( (vj_effects[entry]->has_user == 1 ) && + (vj_is_complex_effect(effect_id) == 1 ) ) + return 1; + return 0; +} + +int vj_effect_get_min_i() +{ + return VJ_IMAGE_EFFECT_MIN; +} + +int vj_effect_get_max_i() +{ + return VJ_IMAGE_EFFECT_MAX; +} + +int vj_effect_get_min_v() +{ + return VJ_VIDEO_EFFECT_MIN; +} + +int vj_effect_get_max_v() +{ + return VJ_VIDEO_EFFECT_MAX; +} + +int vj_effect_has_rgbkey(int effect_id) +{ + int entry; + entry = vj_effect_real_to_sequence(effect_id); + if (entry >= 0) + { + return ( vj_effects[entry]->rgb_conv); + + } + return 0; +} + +int vj_effect_is_valid(int effect_id) +{ + if( effect_id >= VJ_EXT_EFFECT && effect_id < VJ_EXT_EFFECT + n_ext_plugs_) + return 1; + if( effect_id > VJ_IMAGE_EFFECT_MIN && effect_id < VJ_IMAGE_EFFECT_MAX ) + return 1; + if( effect_id > VJ_VIDEO_EFFECT_MIN && effect_id < VJ_VIDEO_EFFECT_MAX ) + return 1; + return 0; +} diff --git a/branches/V-1.5.3/veejay-server/libvje/vj-effman.c b/branches/V-1.5.3/veejay-server/libvje/vj-effman.c new file mode 100644 index 00000000..bf8f8907 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/vj-effman.c @@ -0,0 +1,695 @@ +/* + * Copyright (C) 2002-2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern vj_effect *vj_effects[]; + +void vj_effman_apply_ff_effect( + VJFrame **frames, + VJFrameInfo *frameinfo, + vjp_kf *todo_info, + int *arg, + int entry, + int fx_id) + +{ + plug_control( entry - MAX_EFFECTS, arg ); + + plug_process( frames[0],frames[1],entry - MAX_EFFECTS, get_ffmpeg_pixfmt(frames[0]->format) ); +} + +void vj_effman_apply_image_effect( + VJFrame **frames, + VJFrameInfo *frameinfo, + vjp_kf *todo_info, + int *arg, + int entry, + int e) + + { + + int j; + + switch (e) { + case VJ_IMAGE_EFFECT_CONSTANTBLEND: + constantblend_apply( frames[0], frameinfo->width, + frameinfo->height, arg[0], arg[1], arg[2]); + break; + case VJ_IMAGE_EFFECT_FLARE: + flare_apply( frames[0], frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2] ); + break; + case VJ_IMAGE_EFFECT_PHOTOPLAY: + photoplay_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_MASKSTOP: + maskstop_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_CUTSTOP: + cutstop_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_NEIGHBOUR4: + neighbours4_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_NEIGHBOUR5: + neighbours5_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_NEIGHBOUR2: + neighbours2_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_NEIGHBOUR: + neighbours_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_NEIGHBOUR3: + neighbours3_apply(frames[0],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; + + case VJ_IMAGE_EFFECT_RIPPLETV: + waterrippletv_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_PENCILSKETCH: + pencilsketch_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_NOISEPENCIL: + noisepencil_apply(frames[0],frameinfo->width,frameinfo->height, + arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_CALI: + cali_apply( vj_effects[entry]->user_data,frames[0], frameinfo->width,frameinfo->height,arg[0], arg[1] ); + break; + case VJ_IMAGE_EFFECT_DIFF: + diffimg_apply(frames[0], + frameinfo->width, frameinfo->height, arg[0], arg[1], + arg[2]); + break; + + case VJ_IMAGE_EFFECT_COMPLEXINVERT: + complexinvert_apply(frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4]); + break; + case VJ_IMAGE_EFFECT_COMPLEXSATURATE: + complexsaturation_apply(frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]); + break; + case VJ_IMAGE_EFFECT_REFLECTION: + reflection_apply(frames[0], frameinfo->width, frameinfo->height, + arg[0], arg[1], arg[2]); + break; + case VJ_IMAGE_EFFECT_FIBDOWNSCALE: + for (j = 0; j < arg[1]; j++) { + fibdownscale_apply(frames[0], frames[0], frameinfo->width, + frameinfo->height, arg[0]); + } + break; + case VJ_IMAGE_EFFECT_NOISEADD: + noiseadd_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_CONTRAST: + contrast_apply(frames[0], frameinfo->width, frameinfo->height,arg); + break; + case VJ_IMAGE_EFFECT_ENHANCEMASK: + enhancemask_apply(frames[0],frameinfo->width,frameinfo->height,arg); + break; + case VJ_IMAGE_EFFECT_SOLARIZE: + solarize_apply(frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_DISTORTION: + distortion_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1]); + break; + case VJ_IMAGE_EFFECT_GAMMA: + gamma_apply( + frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_COLORADJUST: + coloradjust_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1]); + break; + case VJ_IMAGE_EFFECT_MOTIONBLUR: + motionblur_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + + case VJ_IMAGE_EFFECT_MAGICSCRATCHER: + magicscratcher_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1], arg[2]); + break; + case VJ_IMAGE_EFFECT_CHROMASCRATCHER: + chromascratcher_apply(frames[0], frameinfo->width, frameinfo->height, + arg[0], arg[1], arg[2], arg[3]); + break; + case VJ_IMAGE_EFFECT_SCRATCHER: + scratcher_apply(frames[0], frameinfo->width, frameinfo->height, + arg[0], arg[1], arg[2]); + break; + case VJ_IMAGE_EFFECT_KILLCHROMA: + killchroma_apply(frames[0], frameinfo->width, frameinfo->height, arg[0] + ); + break; + case VJ_IMAGE_EFFECT_MIRROR: + mirrors2_apply(frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_MIRRORS: + mirrors_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1]); + break; + case VJ_IMAGE_EFFECT_MAGICMIRROR: + magicmirror_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_RASTER: + raster_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_SWIRL: + swirl_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_RADIALBLUR: + radialblur_apply(frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_FISHEYE: + fisheye_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_PIXELSMEAR: + smear_apply(frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_UVCORRECT: + uvcorrect_apply(frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]); + break; + case VJ_IMAGE_EFFECT_CHROMAPALETTE: + chromapalette_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]); + break; + case VJ_IMAGE_EFFECT_CHROMIUM: + chromium_apply( frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_CARTONIZE: + cartonize_apply( frames[0], frameinfo->width,frameinfo->height, + arg[0],arg[1],arg[2] ); + break; + case VJ_IMAGE_EFFECT_VIDBLOB: + blob_apply( frames[0],frameinfo->width,frameinfo->height, + arg[0],arg[1],arg[2],arg[3] ); + break; + case VJ_IMAGE_EFFECT_VIDBOIDS: + boids_apply( frames[0],frameinfo->width,frameinfo->height, + arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],arg[7] ); + break; + case VJ_IMAGE_EFFECT_GHOST: + ghost_apply( frames[0], frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_MORPHOLOGY: + morphology_apply( frames[0], frameinfo->width,frameinfo->height, + arg[0],arg[1],arg[2] ); + break; + case VJ_IMAGE_EFFECT_COLMORPH: + colmorphology_apply( frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_NERVOUS: + nervous_apply( frames[0], frameinfo->width, frameinfo->height, + arg[0]); break; + case VJ_IMAGE_EFFECT_OVERCLOCK: + overclock_apply(frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_COLORHIS: + colorhis_apply( frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3] ); + break; + case VJ_IMAGE_EFFECT_AUTOEQ: + autoeq_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_BALTANTV: + baltantv_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_CHAMELEON: + chameleon_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_TIMEDISTORT: + timedistort_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_LENSCORRECTION: + radcor_apply( frames[0], frameinfo->width,frameinfo->height, arg[0],arg[1] ,arg[2]); + break; + case VJ_IMAGE_EFFECT_NEGATION: + negation_apply(frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_MEDIANFILTER: + medianfilter_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_NEGATECHANNEL: + negatechannel_apply(frames[0], frameinfo->width, frameinfo->height, arg[0],arg[1]); + break; + + case VJ_IMAGE_EFFECT_COLFLASH: + colflash_apply(frames[0], frameinfo->width,frameinfo->height,arg[0], + arg[1],arg[2],arg[3],arg[4] ); + break; + case VJ_IMAGE_EFFECT_COLORMAP: + colormap_apply(frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_POSTERIZE: + posterize_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_DITHER: + dither_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1]); + break; + case VJ_IMAGE_EFFECT_EMBOSS: + emboss_apply(frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_FLIP: + flip_apply(frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_REVTV: + revtv_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1], arg[2], arg[3]); + break; + case VJ_IMAGE_EFFECT_COLORSHIFT: + colorshift_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1]); + break; + case VJ_IMAGE_EFFECT_SOFTBLUR: + softblur_apply(frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_WIDTHMIRROR: + widthmirror_apply(frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_DICES: + dices_apply(vj_effects[entry], frames[0], frameinfo->width, + frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_COLORTEST: + color_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_RAWMAN: + rawman_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1]); + break; + case VJ_IMAGE_EFFECT_RAWVAL: + rawval_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], arg[1], + arg[2], arg[3]); + break; + case VJ_IMAGE_EFFECT_SMUCK: + smuck_apply(frames[0], frames[0], frameinfo->width, frameinfo->height, + arg[0]); + break; + case VJ_IMAGE_EFFECT_TRANSFORM: + transform_apply(frames[0], frames[0], frameinfo->width, frameinfo->height, + arg[0]); + break; + case VJ_IMAGE_EFFECT_BWSELECT: + bwselect_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], arg[1]); + break; + case VJ_IMAGE_EFFECT_GREYSELECT: + greyselect_apply(frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_ISOLATE: + isolate_apply(frames[0],frameinfo->width,frameinfo->height, + arg[0],arg[1],arg[2],arg[3],arg[4]); + break; + case VJ_IMAGE_EFFECT_ROTOZOOM: + rotozoom_apply(frames[0], + frameinfo->width, + frameinfo->height, arg[0], arg[1], arg[2], arg[3]); + break; + case VJ_IMAGE_EFFECT_SINOIDS: + sinoids_apply(frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_AVERAGE: + average_apply(frames[0],frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_IMAGE_EFFECT_RIPPLE: + ripple_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_BGSUBTRACT: + bgsubtract_apply( frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_BATHROOM: + bathroom_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_RGBCHANNEL: + rgbchannel_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_IMAGE_EFFECT_ZOOM: + zoom_apply(frames[0], frameinfo->width, frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_IMAGE_EFFECT_CROSSPIXEL: + crosspixel_apply(frames[0],frameinfo->width,frameinfo->height,arg[0],arg[1]); + break; + case VJ_IMAGE_EFFECT_DEINTERLACE: + deinterlace_apply( frames[0], frameinfo->width, frameinfo->height, arg[0]); + break; + case VJ_IMAGE_EFFECT_MOTIONMAP: + motionmap_apply( frames[0], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4]); + break; + case VJ_IMAGE_EFFECT_CONTOUR: + contourextract_apply( vj_effects[entry]->user_data, frames[0], + frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4] ); + break; + case VJ_IMAGE_EFFECT_SLICE: + if(arg[2] > 0) { + todo_info->tmp[0] ++; + if(todo_info->tmp[0] > arg[2]) { todo_info->tmp[0] = 0; todo_info->tmp[1] = 1; } + } else { + todo_info->tmp[1] = arg[1]; + } + + slice_apply(frames[0],frameinfo->width,frameinfo->height,arg[0], todo_info->tmp[1]); + todo_info->tmp[1] = 0; + break; + } +} + +void vj_effman_apply_video_effect( VJFrame **frames, VJFrameInfo *frameinfo ,vjp_kf *todo_info,int *arg, int entry, int e) { + + switch(e) { + case VJ_VIDEO_EFFECT_CHAMBLEND: + chameleonblend_apply(frames[0],frames[1], frameinfo->width,frameinfo->height,arg[0]); + break; + case VJ_VIDEO_EFFECT_EXTDIFF: + differencemap_apply( frames[0],frames[1],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_VIDEO_EFFECT_EXTTHRESHOLD: + threshold_apply( frames[0],frames[1],frameinfo->width,frameinfo->height,arg[0],arg[1]); + break; + case VJ_VIDEO_EFFECT_VIDEOWALL: + videowall_apply(frames[0],frames[1],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + case VJ_VIDEO_EFFECT_VIDEOPLAY: + videoplay_apply(frames[0],frames[1],frameinfo->width, + frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_VIDEO_EFFECT_TRIPPLICITY: + tripplicity_apply(frames[0],frames[1], + frameinfo->width,frameinfo->height, arg[0],arg[1],arg[2]); + break; + case VJ_VIDEO_EFFECT_COMPLEXTHRESHOLD: + complexthreshold_apply(frames[0],frames[1],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3], + arg[4], arg[5]); + break; + case VJ_VIDEO_EFFECT_DUPMAGIC: + dupmagic_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0]); + break; + case VJ_VIDEO_EFFECT_LUMAMAGICK: + lumamagic_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1],arg[2]); + break; + case VJ_VIDEO_EFFECT_BINARYOVERLAY: + binaryoverlay_apply(frames[0], frames[1],frameinfo->width,frameinfo->height,arg[0] ); break; + case VJ_VIDEO_EFFECT_OVERLAYMAGIC: + overlaymagic_apply(frames[0], frames[1], frameinfo->width,frameinfo->height, arg[0],arg[1]); + break; + case VJ_VIDEO_EFFECT_SLICER: + slicer_apply(frames[0],frames[1], frameinfo->width, frameinfo->height, arg[0],arg[1] ); + break; + case VJ_VIDEO_EFFECT_MASK: + simplemask_apply(frames[0],frames[1], frameinfo->width,frameinfo->height,arg[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_LUMAMASK: + lumamask_apply(frames[0], frames[1], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2]); + break; + case VJ_VIDEO_EFFECT_DISSOLVE: + dissolve_apply(frames[0],frames[1],frameinfo->width,frameinfo->height,arg[0]);break; + case VJ_VIDEO_EFFECT_OPACITY: + opacity_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, arg[0]); + break; + case VJ_VIDEO_EFFECT_IRIS: + iris_apply( frames[0],frames[1], frameinfo->width,frameinfo->height,arg[0],arg[1]); + break; + case VJ_VIDEO_EFFECT_THRESHOLDSMOOTH: + opacitythreshold_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, arg[0], arg[1],arg[2]); + break; + case VJ_VIDEO_EFFECT_THRESHOLD: + opacityadv_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, arg[0], arg[1], arg[2]); + break; + case VJ_VIDEO_EFFECT_RGBKEY: + rgbkey_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]); + break; + case VJ_VIDEO_EFFECT_KEYSELECT: + keyselect_apply(frames[0],frames[1],frameinfo->width,frameinfo->height, + arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]); + break; + case VJ_VIDEO_EFFECT_CHROMAMAGICK: + chromamagick_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, arg[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_LUMABLEND: + lumablend_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1], arg[2], arg[3]); + break; + case VJ_VIDEO_EFFECT_LUMAKEY: + lumakey_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[4], arg[1], arg[2], arg[0], arg[3]); + break; + case VJ_VIDEO_EFFECT_DIFF: + diff_apply( vj_effects[entry]->user_data, frames[0], frames[1], + frameinfo->width, frameinfo->height, arg[0], arg[1],arg[2],arg[3]); + break; + case VJ_VIDEO_EFFECT_TEXMAP: + texmap_apply( vj_effects[entry]->user_data, frames[0],frames[1], + frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4] ); + break; + case VJ_VIDEO_EFFECT_WHITEFRAME: + whiteframe_apply(frames[0], frames[1], frameinfo->width, frameinfo->height); + break; + case VJ_VIDEO_EFFECT_MTRACER: + mtracer_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_TRACER: + tracer_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, arg[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_CAROT: + transcarot_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[2], arg[3], arg[4], arg[5], arg[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_LINE: + transline_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[2], arg[1], arg[0], arg[3]); + break; + case VJ_VIDEO_EFFECT_TRANSOP: + transop_apply(frames[0], frames[1], arg[1], arg[2], arg[3], + arg[4], arg[5], arg[6], frameinfo->width, frameinfo->height, + arg[0]); + break; + case VJ_VIDEO_EFFECT_COMPLEXSYNC: + if(arg[1] == 1) { /* auto increment as option in effect*/ + if(arg[2]==0) arg[2]=1; + todo_info->tmp[0] += (arg[0]/arg[2] )+1; /* val / max frames */ + if(todo_info->tmp[0] > frameinfo->height-2) todo_info->tmp[0] = 1; + } else { /* arg1 = off , copy arg*/ + todo_info->tmp[0] = arg[0]; + } + complexsync_apply(frames[0], frames[1],frameinfo->width, frameinfo->height, + todo_info->tmp[0]); + break; + case VJ_VIDEO_EFFECT_FADECOLORRGB: + if (arg[4] == 0) { + if (todo_info->tmp[0] >= 255) + todo_info->tmp[0] = arg[0]; + todo_info->tmp[0] += (arg[0] / arg[5]); + } else { + if (todo_info->tmp[0] <= 0) + todo_info->tmp[0] = arg[0]; + + todo_info->tmp[0] -= (arg[0] / arg[5]); + } + + colorfadergb_apply(frames[0], frameinfo->width, frameinfo->height, + todo_info->tmp[0], arg[1], arg[2], arg[3]); + break; + case VJ_VIDEO_EFFECT_FADECOLOR: + if (arg[3] == 0) { + if (todo_info->tmp[0] >= 255) + todo_info->tmp[0] = arg[0]; + todo_info->tmp[0] += (arg[0] / arg[2]); + } else { + if (todo_info->tmp[0] <= 0) + todo_info->tmp[0] = arg[0]; + todo_info->tmp[0] -= (arg[0] / arg[2]); + } + + + colorfade_apply(frames[0], frameinfo->width, frameinfo->height, + todo_info->tmp[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_VBAR: + vbar_apply(frames[0],frames[1],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4]); + break; + case VJ_VIDEO_EFFECT_3BAR: + bar_apply(frames[0],frames[1],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4]); + break; + case VJ_VIDEO_EFFECT_SLIDINGDOOR: + if(arg[1] == 1) { /* auto increment as option in effect*/ + todo_info->tmp[0] ++; /* val / max frames */ + if(todo_info->tmp[0] >= (frameinfo->height/16)) + todo_info->tmp[0] = 1; + } else { /* arg1 = off , copy arg*/ + todo_info->tmp[0] = arg[0]; + } + + slidingdoor_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, todo_info->tmp[0] ); + break; + case VJ_VIDEO_EFFECT_WIPE: + wipe_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_RGBKEYSMOOTH: + rgbkeysmooth_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, arg[0], arg[1], arg[2], arg[3], + arg[4],arg[5]); + break; + case VJ_VIDEO_EFFECT_SPLIT: + split_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1]); + break; + case VJ_VIDEO_EFFECT_BORDERS: + borders_apply(frames[0], frameinfo->width, frameinfo->height, arg[0], + arg[1]); + break; + case VJ_VIDEO_EFFECT_FRAMEBORDER: + frameborder_apply(frames[0], frames[1], frameinfo->width, + frameinfo->height, arg[0]); + break; + case VJ_VIDEO_EFFECT_TRANSBLEND: + transblend_apply(frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], + arg[6]); + break; + case VJ_VIDEO_EFFECT_PICINPIC: + picinpic_apply( vj_effects[entry]->user_data,frames[0], frames[1], frameinfo->width, frameinfo->height, + arg[0], arg[1], arg[2], arg[3] ); + break; + case VJ_VIDEO_EFFECT_RIPPLETV: + water_apply( vj_effects[entry]->user_data,frames[0],frames[1],frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3],arg[4] ); + + break; + case VJ_VIDEO_EFFECT_RADIOACTIVE: + radioactivetv_apply( frames[0],frames[1], frameinfo->width,frameinfo->height,arg[0],arg[1],arg[2],arg[3]); + break; + + default: + break; + } + +} + +int vj_effect_prepare( VJFrame *frame, int selector) +{ + int fx_id = 0; + switch( selector ) { + case VJ_IMAGE_EFFECT_BGSUBTRACT: + fx_id = vj_effect_real_to_sequence( selector ); + if( fx_id >= 0 && vj_effects[fx_id] ) { + return bgsubtract_prepare( frame->data, frame->width,frame->height ); + } + break; + case VJ_IMAGE_EFFECT_CONTOUR: + fx_id = vj_effect_real_to_sequence(selector); + if(fx_id>=0 && vj_effects[fx_id] ) { + return contourextract_prepare(frame->data,frame->width,frame->height ); + } + break; + case VJ_VIDEO_EFFECT_DIFF: + if( !vj_effect_has_cb(selector)) + return 0; + fx_id = vj_effect_real_to_sequence( selector ); + if( fx_id >= 0 && vj_effects[fx_id]->user_data != NULL) + { + return diff_prepare( (void*) vj_effects[fx_id]->user_data, frame->data, frame->width, frame->height ); + } + break; + case VJ_IMAGE_EFFECT_CHAMELEON: + fx_id = vj_effect_real_to_sequence( selector ); + if( fx_id >= 0 && vj_effects[fx_id]) + { + return chameleon_prepare( frame->data, frame->width, frame->height ); + } + break; + case VJ_IMAGE_EFFECT_MOTIONMAP: + fx_id = vj_effect_real_to_sequence( selector ); + if( fx_id >= 0 && vj_effects[fx_id]) + { + return motionmap_prepare( frame->data, frame->width, frame->height ); + } + break; + case VJ_VIDEO_EFFECT_TEXMAP: + fx_id = vj_effect_real_to_sequence( selector ); + if( fx_id >= 0 && vj_effects[fx_id] ) + { + return texmap_prepare( frame->data, frame->width, frame->height ); + } + break; + case VJ_VIDEO_EFFECT_CHAMBLEND: + fx_id = vj_effect_real_to_sequence( selector ); + if( fx_id >= 0 && vj_effects[fx_id]) + { + return chameleonblend_prepare( frame->data, frame->width, frame->height ); + } + break; + + default: + break; + } + return 0; +} + + +int vj_effect_apply( VJFrame **frames, VJFrameInfo *frameinfo, vjp_kf *kf, int selector, int *arguments ) +{ + int entry = vj_effect_real_to_sequence( selector ); + int n_a = vj_effect_get_num_params( selector ); + + if( !frames || !frames[0] ) return VJE_NO_FRAMES; + + if(!vj_effect_initialized(selector)) + { + return VJE_NEED_INIT; + } + + if( selector >= 500 ) + vj_effman_apply_ff_effect( frames, frameinfo, kf, arguments, entry, selector ); + else + { + if( selector > 200 ) + vj_effman_apply_video_effect(frames,frameinfo,kf,arguments, entry,selector); + else + vj_effman_apply_image_effect( frames, frameinfo, kf, arguments,entry, selector); + } + return VJE_SUCCESS; +} + + diff --git a/branches/V-1.5.3/veejay-server/libvje/vje.h b/branches/V-1.5.3/veejay-server/libvje/vje.h new file mode 100644 index 00000000..f3bba4ea --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvje/vje.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2002-2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef VJE_H +#define VJE_H + +#define FX_LIMIT 1024 + +#define MAX_EFFECTS 140 +#define PARAM_WIDTH (1<<0x2) +#define PARAM_HEIGHT (1<<0x3) +#define PARAM_FADER (1<<0x1) + +typedef struct +{ + int type; + int tmp[10]; + int ref; +} vjp_kf; + + +typedef struct VJFrame_t +{ + uint8_t *data[4]; + int uv_len; + int len; + int uv_width; + int uv_height; + int shift_v; + int shift_h; + int format; + int width; + int height; + int ssm; + int alpha; + int stride[4]; + int stand; //ccir/jpeg +} VJFrame; + +typedef struct VJRectangle_t +{ + int top; + int bottom; + int left; + int right; +} VJRectangle; + +typedef struct VJFrameInfo_t +{ + int width; + int height; + float fps; + int64_t timecode; + uint8_t inverse; +} VJFrameInfo; + +typedef struct vj_effect_t { + + char *description; + int num_params; + char **param_description; + int *defaults; + int *flags; + int *limits[2]; + int extra_frame; + int sub_format; + int has_user; + int static_bg; + int has_help; + int rgb_conv; + int n_out; + int instance;//crap + void *user_data; + char padding[4]; +} vj_effect; + +extern int get_pixel_range_min_Y(); +extern int get_pixel_range_min_UV(); +extern void vj_effect_initialize(int width, int height, int range); +extern void vj_effect_shutdown(); +extern int vj_effect_max_effects(); +extern int vj_effect_real_to_sequence(int effect_id); +extern int vj_effect_get_real_id( int entry_num ); +extern char *vj_effect_get_description(int effect_id); +extern char *vj_effect_get_param_description(int effect_id, int param_nr); +extern int vj_effect_get_extra_frame(int effect_id); +extern int vj_effect_get_num_params(int effect_id); +extern int vj_effect_get_default(int effect_id, int param_nr); +extern int vj_effect_get_min_limit(int effect_id, int param_nr); +extern int vj_effect_get_max_limit(int effect_id, int param_nr); +extern int vj_effect_valid_value(int effect_id, int param_nr, int value); +extern int vj_effect_get_subformat(int effect_id); +extern int vj_effect_has_cb(int effect_id); +extern int vj_effect_has_rgbkey(int effect_id); +extern int vj_effect_is_valid(int effect_id); +extern int vj_effect_get_summary(int entry, char *dst); +extern int vj_effect_get_summary_len(int entry); +extern int vj_effect_activate(int e); +extern int vj_effect_deactivate(int e); +extern int vj_effect_initialized(int e); +extern int vj_effect_get_min_i(); +extern int vj_effect_get_max_i(); +extern int vj_effect_get_min_v(); +extern int vj_effect_get_max_v(); +extern int vj_effect_get_by_name(char *name); +extern int vj_effect_apply( VJFrame **frames, VJFrameInfo *frameinfo, vjp_kf *kf, int selector, int *arguments ); +extern int vj_effect_prepare( VJFrame *frame, int selector); +extern void vj_effect_dump(void); +extern int rgb_parameter_conversion_type_; +extern void *vj_effect_get_data( int seq_id ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvjmem/Makefile.am b/branches/V-1.5.3/veejay-server/libvjmem/Makefile.am new file mode 100644 index 00000000..7d372d0a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjmem/Makefile.am @@ -0,0 +1,8 @@ +# Makefile for memory managment / platform specific optimizations +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_builddir)/libvjmsg +AM_CFLAGS=$(OP_CFLAGS) +VJMEM_LIB_FILE = libvjmem.la +pkginclude_HEADERS = vjmem.h +noinst_LTLIBRARIES = $(VJMEM_LIB_FILE) +libvjmem_la_SOURCES = memcpy.c vj-x86.c + diff --git a/branches/V-1.5.3/veejay-server/libvjmem/memcpy.c b/branches/V-1.5.3/veejay-server/libvjmem/memcpy.c new file mode 100644 index 00000000..4553e28b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjmem/memcpy.c @@ -0,0 +1,1058 @@ +/* + (c) Copyright 2000-2002 convergence integrated media GmbH. + (c) Copyright 2002 convergence GmbH. + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt and + Sven Neumann . + + Fast memcpy code was taken from xine (see below). + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * Copyright (C) 2001 the xine project + * + * This file is part of xine, a unix video player. + * + * xine 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. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * These are the MMX/MMX2/SSE optimized versions of memcpy + * + * This code was adapted from Linux Kernel sources by Nick Kurshev to + * the mplayer program. (http://mplayer.sourceforge.net) + * + * Miguel Freitas split the #ifdefs into several specialized functions that + * are benchmarked at runtime by xine. Some original comments from Nick + * have been preserved documenting some MMX/SSE oddities. + * Also added kernel memcpy function that seems faster than glibc one. + * + */ + +/* Original comments from mplayer (file: aclib.c) This part of code + was taken by me from Linux-2.4.3 and slightly modified for MMX, MMX2, + SSE instruction set. I have done it since linux uses page aligned + blocks but mplayer uses weakly ordered data and original sources can + not speedup them. Only using PREFETCHNTA and MOVNTQ together have + effect! + + From IA-32 Intel Architecture Software Developer's Manual Volume 1, + + Order Number 245470: + "10.4.6. Cacheability Control, Prefetch, and Memory Ordering Instructions" + + Data referenced by a program can be temporal (data will be used + again) or non-temporal (data will be referenced once and not reused + in the immediate future). To make efficient use of the processor's + caches, it is generally desirable to cache temporal data and not + cache non-temporal data. Overloading the processor's caches with + non-temporal data is sometimes referred to as "polluting the + caches". The non-temporal data is written to memory with + Write-Combining semantics. + + The PREFETCHh instructions permits a program to load data into the + processor at a suggested cache level, so that it is closer to the + processors load and store unit when it is needed. If the data is + already present in a level of the cache hierarchy that is closer to + the processor, the PREFETCHh instruction will not result in any data + movement. But we should you PREFETCHNTA: Non-temporal data fetch + data into location close to the processor, minimizing cache + pollution. + + The MOVNTQ (store quadword using non-temporal hint) instruction + stores packed integer data from an MMX register to memory, using a + non-temporal hint. The MOVNTPS (store packed single-precision + floating-point values using non-temporal hint) instruction stores + packed floating-point data from an XMM register to memory, using a + non-temporal hint. + + The SFENCE (Store Fence) instruction controls write ordering by + creating a fence for memory store operations. This instruction + guarantees that the results of every store instruction that precedes + the store fence in program order is globally visible before any + store instruction that follows the fence. The SFENCE instruction + provides an efficient way of ensuring ordering between procedures + that produce weakly-ordered data and procedures that consume that + data. + + If you have questions please contact with me: Nick Kurshev: + nickols_k@mail.ru. +*/ + +/* mmx v.1 Note: Since we added alignment of destinition it speedups + of memory copying on PentMMX, Celeron-1 and P2 upto 12% versus + standard (non MMX-optimized) version. + Note: on K6-2+ it speedups memory copying upto 25% and + on K7 and P3 about 500% (5 times). +*/ + +/* Additional notes on gcc assembly and processors: [MF] + prefetch is specific for AMD processors, the intel ones should be + prefetch0, prefetch1, prefetch2 which are not recognized by my gcc. + prefetchnta is supported both on athlon and pentium 3. + + therefore i will take off prefetchnta instructions from the mmx1 + version to avoid problems on pentium mmx and k6-2. + + quote of the day: + "Using prefetches efficiently is more of an art than a science" +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#define BUFSIZE 1024 + +#ifndef HAVE_ASM_SSE +/* + P3 processor has only one SSE decoder so can execute only 1 sse insn per + cpu clock, but it has 3 mmx decoders (include load/store unit) + and executes 3 mmx insns per cpu clock. + P4 processor has some chances, but after reading: + http://www.emulators.com/pentium4.htm + I have doubts. Anyway SSE2 version of this code can be written better. +*/ +#undef HAVE_SSE +#endif + +#undef HAVE_ONLY_MMX1 +#if defined(HAVE_ASM_MMX) && !defined(HAVE_ASM_MMX2) && !defined(HAVE_ASM_3DNOW) && !defined(HAVE_ASM_SSE) +/* means: mmx v.1. Note: Since we added alignment of destinition it speedups + of memory copying on PentMMX, Celeron-1 and P2 upto 12% versus + standard (non MMX-optimized) version. + Note: on K6-2+ it speedups memory copying upto 25% and + on K7 and P3 about 500% (5 times). */ +#define HAVE_ONLY_MMX1 +#endif + + +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW) +#define HAVE_K6_2PLUS +#endif + + + +/* definitions */ +#define BLOCK_SIZE 4096 +#define CONFUSION_FACTOR 0 +//Feel free to fine-tune the above 2, it might be possible to get some speedup with them :) + +#if defined(ARCH_X86) || defined (ARCH_X86_64) +/* for small memory blocks (<256 bytes) this version is faster */ +#define small_memcpy(to,from,n)\ +{\ +register unsigned long int dummy;\ +__asm__ __volatile__(\ + "rep; movsb"\ + :"=&D"(to), "=&S"(from), "=&c"(dummy)\ + :"0" (to), "1" (from),"2" (n)\ + : "memory");\ +} + +/* for small memory blocks (<256 bytes) this version is faster */ +#define small_memset(to,val,n)\ +{\ +register unsigned long int dummy;\ +__asm__ __volatile__(\ + "rep; stosb"\ + :"=&D"(to), "=&c"(dummy)\ + :"0" (to), "1" (n), "a"((char)val)\ + :"memory");\ +} +static inline unsigned long long int rdtsc() +{ + unsigned long long int x; + __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x)); + return x; +} +#else +#define small_memcpy(to,from,n) memcpy( to,from,n ) +#define small_memset(to,val,n) memset(to,val,n) +char *veejay_strncpy( char *dest, const char *src, size_t n ) +{ +// dest[n-1] = '\0'; + return strncpy( dest,src, n-1 ); +} +char *veejay_strncat( char *s1, char *s2, size_t n ) { +// s2[n] = '\0'; + return strncat( s1,s2, n); +} + +void yuyv_plane_clear( size_t len, void *to ) +{ + uint8_t *t = (uint8_t*) to; + unsigned int i; + i = len; + for( ; i > 0 ; i -- ) + { + t[0] = 0; + t[1] = 128; + t[2] = 0; + t[3] = 128; + t += 4; + } +} +static inline unsigned long long int rdtsc() +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + return (tv.tv_sec * 1000000 + tv.tv_usec); +} +#endif + +#if defined(ARCH_X86) || defined (ARCH_X86_64) +static inline void * __memcpy(void * to, const void * from, size_t n) +{ + int d0, d1, d2; + if ( n < 4 ) { + small_memcpy(to,from,n); + } + else + __asm__ __volatile__( + "rep ; movsl\n\t" + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" + "2:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); + + return(to); +} + +#undef _MMREG_SIZE +#ifdef HAVE_SSE +#define _MMREG_SIZE 16 +#else +#define _MMREG_SIZE 64 +#endif + +#undef PREFETCH +#undef EMMS + +#undef _MIN_LEN +#ifdef HAVE_ASM_MMX2 //@ was ifndef HAVE_MMX1 +#define _MIN_LEN 0x40 +#else +#define _MIN_LEN 0x800 /* 2K blocks */ +#endif + + +#ifdef HAVE_ASM_MMX2 +#define PREFETCH "prefetchnta" +#elif defined ( HAVE_ASM_3DNOW ) +#define PREFETCH "prefetch" +#else +#define PREFETCH "/nop" +#endif + +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#ifdef HAVE_ASM_3DNOW +#define EMMS "femms" +#else +#define EMMS "emms" +#endif + +#undef MOVNTQ +#ifdef HAVE_ASM_MMX2 +#define MOVNTQ "movntq" +#else +#define MOVNTQ "movq" +#endif + + + +char *veejay_strncpy( char *dest, const char *src, size_t n ) +{ + dest[n] = '\0'; + if( n < 0xff ) { + small_memcpy( dest,src, n ); + } else if ( n < 512 ) { + small_memcpy( dest,src, n ); + } else { + return veejay_memcpy( dest,src, n ); + } + return dest; +} + + +char *veejay_strncat( char *s1, char *s2, size_t n ) +{ +#ifdef STRICT_CHECKING + assert( strlen(s2) == n ); +#endif + //@ run forward + char *s = s1; + while(*s != '\0' ) + *s ++; + //@ small + if( n < 0xff ) + { + s2[n] = '\0'; + small_memcpy( s, s2, n+1); + } + else if ( n < 512 ) // bit smaller + { + s2[n] = '\0'; + small_memcpy( s, s2, n+1); + } else + { + s2[n] = '\0'; + return veejay_memcpy(s,s2, n+1 ); + } + return s1; +} + +void prefetch_memory( void *from ) +{ +#ifndef HAVE_MMX1 + __asm__ __volatile__ ( + PREFETCH" (%0)\n" + PREFETCH" 64(%0)\n" + PREFETCH" 128(%0)\n" + PREFETCH" 192(%0)\n" + PREFETCH" 256(%0)\n" + :: "r" (from)); +#else +#ifdef HAVE_ASM_SSE + __asm__ __volatile__ ( + PREFETCH" 320(%0)\n" + :: "r" (from)); + +#endif +#endif +} + + +static uint8_t ppmask[16] = { 0,128,128,0, 128,128,0,128, 128,0,128,128,0,128,128, 0 }; +static uint8_t yuyv_mmreg_[_MMREG_SIZE]; + +void yuyv_plane_init() +{ + unsigned int i; + for( i = 0; i < _MMREG_SIZE ;i ++ ) + yuyv_mmreg_[i] = ( (i%2) ? 128: 0 ); +} + + +void yuyv_plane_clear( size_t len, void *to ) +{ + uint8_t *t = (uint8_t*) to; + unsigned int i; + +#ifdef HAVE_ASM_MMX2 + __asm __volatile( + "movq (%0), %%mm0\n" + :: "r" (yuyv_mmreg_) : "memory" ); + + i = len >> 7; + len = len % 128; + + for(; i > 0 ; i -- ) + { + __asm __volatile( + PREFETCH" 320(%0)\n" + MOVNTQ" %%mm0, (%0)\n" + MOVNTQ" %%mm0, 8(%0)\n" + MOVNTQ" %%mm0, 16(%0)\n" + MOVNTQ" %%mm0, 24(%0)\n" + MOVNTQ" %%mm0, 32(%0)\n" + MOVNTQ" %%mm0, 40(%0)\n" + MOVNTQ" %%mm0, 48(%0)\n" + MOVNTQ" %%mm0, 56(%0)\n" + MOVNTQ" %%mm0, 64(%0)\n" + MOVNTQ" %%mm0, 72(%0)\n" + MOVNTQ" %%mm0, 80(%0)\n" + MOVNTQ" %%mm0, 88(%0)\n" + MOVNTQ" %%mm0, 96(%0)\n" + MOVNTQ" %%mm0, 104(%0)\n" + MOVNTQ" %%mm0, 112(%0)\n" + MOVNTQ" %%mm0, 120(%0)\n" + :: "r" (t) : "memory" ); + t += 128; + } +#else +#ifdef HAVE_ASM_MMX + __asm __volatile( + "movq (%0), %%mm0\n\t" + :: "r" (yuyv_mmreg_): "memory"); + i = len >> 6; + len = len % 64; + + for(; i > 0 ; i -- ) + { + __asm__ __volatile__ ( + "movq %%mm0, (%0)\n" + "movq %%mm0, 8(%0)\n" + "movq %%mm0, 16(%0)\n" + "movq %%mm0, 24(%0)\n" + "movq %%mm0, 32(%0)\n" + "movq %%mm0, 40(%0)\n" + "movq %%mm0, 48(%0)\n" + "movq %%mm0, 56(%0)\n" + :: "r" (t) : "memory"); + t += 64; + } +#endif +#endif +#ifdef HAVE_ASM_MMX + i = len >> 3; + len = i % 8; + for( ; i > 0; i -- ) + { + __asm__ __volatile__ ( + "movq %%mm0, (%0)\n" + :: "r" (t) : "memory" ); + t += 8; + } +#endif + i = len; + for( ; i > 0 ; i -- ) + { + t[0] = 0; + t[1] = 128; + t[2] = 0; + t[3] = 128; + t += 4; + } +} + +void packed_plane_clear( size_t len, void *to ) +{ + uint8_t *t = (uint8_t*) to; + unsigned int i; + uint8_t *m = (uint8_t*) &ppmask; +#ifdef HAVE_ASM_MMX + __asm __volatile( + "movq (%0), %%mm0\n\t" + :: "r" (m)); + i = len / 64; + len = len % 64; + + for(; i > 0 ; i -- ) + { + __asm__ __volatile__ ( + "movq %%mm0, (%0)\n" + "movq %%mm0, 8(%0)\n" + "movq %%mm0, 16(%0)\n" + "movq %%mm0, 24(%0)\n" + "movq %%mm0, 32(%0)\n" + "movq %%mm0, 40(%0)\n" + "movq %%mm0, 48(%0)\n" + "movq %%mm0, 56(%0)\n" + :: "r" (t) : "memory"); + t += 64; + } +#endif + i = len; + for( ; i > 0 ; i -- ) + { + t[0] = 0; + t[1] = 128; + t[2] = 0; + t[3] = 128; + t += 4; + } +} + + +#if defined (HAVE_ASM_SSE) || defined (HAVE_ASM_MMX) || defined( HAVE_ASM_MMX2 ) +static void *fast_memcpy(void * to, const void * from, size_t len) +{ + void *retval; + size_t i; + retval = to; + unsigned char *t = to; + unsigned char *f = (unsigned char *)from; +#ifndef HAVE_ONLY_MMX1 + /* PREFETCH has effect even for MOVSB instruction ;) */ + __asm__ __volatile__ ( + PREFETCH" (%0)\n" + PREFETCH" 64(%0)\n" + PREFETCH" 128(%0)\n" + PREFETCH" 192(%0)\n" + PREFETCH" 256(%0)\n" + : : "r" (f) ); +#endif + if(len >= _MIN_LEN) + { + register unsigned long int delta; + /* Align destinition to MMREG_SIZE -boundary */ + delta = ((unsigned long int)to)&(_MMREG_SIZE-1); + if(delta) + { + delta=_MMREG_SIZE-delta; + len -= delta; + small_memcpy(t, f, delta); + } + i = len >> 6; /* len/64 */ + len&=63; + /* + This algorithm is top effective when the code consequently + reads and writes blocks which have size of cache line. + Size of cache line is processor-dependent. + It will, however, be a minimum of 32 bytes on any processors. + It would be better to have a number of instructions which + perform reading and writing to be multiple to a number of + processor's decoders, but it's not always possible. + */ +#ifdef HAVE_SSE /* Only P3 (may be Cyrix3) */ + if(((unsigned long)f) & 15) + /* if SRC is misaligned */ + for(; i>0; i--) + { + __asm__ __volatile__ ( + PREFETCH" 320(%0)\n" + "movups (%0), %%xmm0\n" + "movups 16(%0), %%xmm1\n" + "movups 32(%0), %%xmm2\n" + "movups 48(%0), %%xmm3\n" + "movntps %%xmm0, (%1)\n" + "movntps %%xmm1, 16(%1)\n" + "movntps %%xmm2, 32(%1)\n" + "movntps %%xmm3, 48(%1)\n" + :: "r" (f), "r" (t) : "memory"); + f+=64; + t+=64; + } + else + /* + Only if SRC is aligned on 16-byte boundary. + It allows to use movaps instead of movups, which required data + to be aligned or a general-protection exception (#GP) is generated. + */ + for(; i>0; i--) + { + __asm__ __volatile__ ( + PREFETCH" 320(%0)\n" + "movaps (%0), %%xmm0\n" + "movaps 16(%0), %%xmm1\n" + "movaps 32(%0), %%xmm2\n" + "movaps 48(%0), %%xmm3\n" + "movntps %%xmm0, (%1)\n" + "movntps %%xmm1, 16(%1)\n" + "movntps %%xmm2, 32(%1)\n" + "movntps %%xmm3, 48(%1)\n" + :: "r" (f), "r" (t) : "memory"); + // f+=64; + // t+=64; + f=((const unsigned char *)f)+64; + t=((unsigned char *)t)+64; + + } +#else + // Align destination at BLOCK_SIZE boundary + for(; ((int)to & (BLOCK_SIZE-1)) && i>0; i--) + { + __asm__ __volatile__ ( +#ifndef HAVE_ONLY_MMX1 + PREFETCH" 320(%0)\n" +#endif + "movq (%0), %%mm0\n" + "movq 8(%0), %%mm1\n" + "movq 16(%0), %%mm2\n" + "movq 24(%0), %%mm3\n" + "movq 32(%0), %%mm4\n" + "movq 40(%0), %%mm5\n" + "movq 48(%0), %%mm6\n" + "movq 56(%0), %%mm7\n" + MOVNTQ" %%mm0, (%1)\n" + MOVNTQ" %%mm1, 8(%1)\n" + MOVNTQ" %%mm2, 16(%1)\n" + MOVNTQ" %%mm3, 24(%1)\n" + MOVNTQ" %%mm4, 32(%1)\n" + MOVNTQ" %%mm5, 40(%1)\n" + MOVNTQ" %%mm6, 48(%1)\n" + MOVNTQ" %%mm7, 56(%1)\n" + :: "r" (f), "r" (t) : "memory"); + // f+=64; + // t+=64; + f=((const unsigned char *)f)+64; + t=((unsigned char *)t)+64; + + } + + // Pure Assembly cuz gcc is a bit unpredictable ;) + if(i>=BLOCK_SIZE/64) + asm volatile( + "xor %%"REG_a", %%"REG_a" \n\t" + ".balign 16 \n\t" + "1: \n\t" + "movl (%0, %%"REG_a"), %%ebx \n\t" + "movl 32(%0, %%"REG_a"), %%ebx \n\t" + "movl 64(%0, %%"REG_a"), %%ebx \n\t" + "movl 96(%0, %%"REG_a"), %%ebx \n\t" + "add $128, %%"REG_a" \n\t" + "cmp %3, %%"REG_a" \n\t" + " jb 1b \n\t" + + "xor %%"REG_a", %%"REG_a" \n\t" + + ".balign 16 \n\t" + "2: \n\t" + "movq (%0, %%"REG_a"), %%mm0\n" + "movq 8(%0, %%"REG_a"), %%mm1\n" + "movq 16(%0, %%"REG_a"), %%mm2\n" + "movq 24(%0, %%"REG_a"), %%mm3\n" + "movq 32(%0, %%"REG_a"), %%mm4\n" + "movq 40(%0, %%"REG_a"), %%mm5\n" + "movq 48(%0, %%"REG_a"), %%mm6\n" + "movq 56(%0, %%"REG_a"), %%mm7\n" + MOVNTQ" %%mm0, (%1, %%"REG_a")\n" + MOVNTQ" %%mm1, 8(%1, %%"REG_a")\n" + MOVNTQ" %%mm2, 16(%1, %%"REG_a")\n" + MOVNTQ" %%mm3, 24(%1, %%"REG_a")\n" + MOVNTQ" %%mm4, 32(%1, %%"REG_a")\n" + MOVNTQ" %%mm5, 40(%1, %%"REG_a")\n" + MOVNTQ" %%mm6, 48(%1, %%"REG_a")\n" + MOVNTQ" %%mm7, 56(%1, %%"REG_a")\n" + "add $64, %%"REG_a" \n\t" + "cmp %3, %%"REG_a" \n\t" + "jb 2b \n\t" + +#if CONFUSION_FACTOR > 0 + // a few percent speedup on out of order executing CPUs + "mov %5, %%"REG_a" \n\t" + "2: \n\t" + "movl (%0), %%ebx \n\t" + "movl (%0), %%ebx \n\t" + "movl (%0), %%ebx \n\t" + "movl (%0), %%ebx \n\t" + "dec %%"REG_a" \n\t" + " jnz 2b \n\t" +#endif + + "xor %%"REG_a", %%"REG_a" \n\t" + "add %3, %0 \n\t" + "add %3, %1 \n\t" + "sub %4, %2 \n\t" + "cmp %4, %2 \n\t" + " jae 1b \n\t" + : "+r" (from), "+r" (to), "+r" (i) + : "r" ((long)BLOCK_SIZE), "i" (BLOCK_SIZE/64), "i" ((long)CONFUSION_FACTOR) + : "%"REG_a, "%ebx" + ); + for(; i>0; i--) + { + __asm__ __volatile__ ( +#ifndef HAVE_ONLY_MMX1 + PREFETCH" 320(%0)\n" +#endif + "movq (%0), %%mm0\n" + "movq 8(%0), %%mm1\n" + "movq 16(%0), %%mm2\n" + "movq 24(%0), %%mm3\n" + "movq 32(%0), %%mm4\n" + "movq 40(%0), %%mm5\n" + "movq 48(%0), %%mm6\n" + "movq 56(%0), %%mm7\n" + MOVNTQ" %%mm0, (%1)\n" + MOVNTQ" %%mm1, 8(%1)\n" + MOVNTQ" %%mm2, 16(%1)\n" + MOVNTQ" %%mm3, 24(%1)\n" + MOVNTQ" %%mm4, 32(%1)\n" + MOVNTQ" %%mm5, 40(%1)\n" + MOVNTQ" %%mm6, 48(%1)\n" + MOVNTQ" %%mm7, 56(%1)\n" + :: "r" (from), "r" (to) : "memory"); + from=((const unsigned char *)from)+64; + to=((unsigned char *)to)+64; + } + +#endif /* Have SSE */ +#ifdef HAVE_ASM_MMX2 + /* since movntq is weakly-ordered, a "sfence" + * is needed to become ordered again. */ + __asm__ __volatile__ ("sfence":::"memory"); +#endif +#ifndef HAVE_SSE + /* enables to use FPU */ + + __asm__ __volatile__ (EMMS:::"memory"); +#endif + } + /* + * Now do the tail of the block + */ + if(len) small_memcpy(t, f, len); + return retval; +} +#endif + +void fast_memset_finish() +{ +#ifdef HAVE_ASM_MMX2 + /* since movntq is weakly-ordered, a "sfence" + * * is needed to become ordered again. */ + __asm__ __volatile__ ("sfence":::"memory"); +#endif +#ifdef HAVE_ASM_MMX + /* enables to use FPU */ + __asm__ __volatile__ (EMMS:::"memory"); +#endif + +} + +void fast_memset_dirty(void * to, int val, size_t len) +{ + size_t i; + unsigned char mm_reg[_MMREG_SIZE], *pmm_reg; + unsigned char *t = to; + if(len >= _MIN_LEN) + { + register unsigned long int delta; + delta = ((unsigned long int)to)&(_MMREG_SIZE-1); + if(delta) + { + delta=_MMREG_SIZE-delta; + len -= delta; + small_memset(t, val, delta); + } + i = len >> 7; /* len/128 */ + len&=127; + pmm_reg = mm_reg; + small_memset(pmm_reg,val,sizeof(mm_reg)); +#ifdef HAVE_ASM_SSE /* Only P3 (may be Cyrix3) */ + __asm__ __volatile__( + "movups (%0), %%xmm0\n" + :: "r"(mm_reg):"memory"); + for(; i>0; i--) + { + __asm__ __volatile__ ( + "movntps %%xmm0, (%0)\n" + "movntps %%xmm0, 16(%0)\n" + "movntps %%xmm0, 32(%0)\n" + "movntps %%xmm0, 48(%0)\n" + "movntps %%xmm0, 64(%0)\n" + "movntps %%xmm0, 80(%0)\n" + "movntps %%xmm0, 96(%0)\n" + "movntps %%xmm0, 112(%0)\n" + :: "r" (t) : "memory"); + t+=128; + } +#else + __asm__ __volatile__( + "movq (%0), %%mm0\n" + :: "r"(mm_reg):"memory"); + for(; i>0; i--) + { + __asm__ __volatile__ ( + MOVNTQ" %%mm0, (%0)\n" + MOVNTQ" %%mm0, 8(%0)\n" + MOVNTQ" %%mm0, 16(%0)\n" + MOVNTQ" %%mm0, 24(%0)\n" + MOVNTQ" %%mm0, 32(%0)\n" + MOVNTQ" %%mm0, 40(%0)\n" + MOVNTQ" %%mm0, 48(%0)\n" + MOVNTQ" %%mm0, 56(%0)\n" + MOVNTQ" %%mm0, 64(%0)\n" + MOVNTQ" %%mm0, 72(%0)\n" + MOVNTQ" %%mm0, 80(%0)\n" + MOVNTQ" %%mm0, 88(%0)\n" + MOVNTQ" %%mm0, 96(%0)\n" + MOVNTQ" %%mm0, 104(%0)\n" + MOVNTQ" %%mm0, 112(%0)\n" + MOVNTQ" %%mm0, 120(%0)\n" + :: "r" (t) : "memory"); + t+=128; + } +#endif /* Have SSE */ +//#ifdef HAVE_ASM_MMX2 +// /* since movntq is weakly-ordered, a "sfence" +// * is needed to become ordered again. */ +// __asm__ __volatile__ ("sfence":::"memory"); +//#endif +//#ifndef HAVE_ASM_SSE +// /* enables to use FPU */ +// __asm__ __volatile__ (EMMS:::"memory"); +//#endif + } + /* + * Now do the tail of the block + */ + if(len) small_memset(t, val, len); +} + + + +#if defined (HAVE_ASM_MMX) +/* Fast memory set. See comments for fast_memcpy */ +void * fast_memset(void * to, int val, size_t len) +{ + void *retval; + size_t i; + unsigned char mm_reg[_MMREG_SIZE], *pmm_reg; + unsigned char *t = to; + retval = to; +// veejay_msg(0, "clear %d bytes in %p",len,val); + if(len >= _MIN_LEN) + { + register unsigned long int delta; + delta = ((unsigned long int)to)&(_MMREG_SIZE-1); + if(delta) + { + delta=_MMREG_SIZE-delta; + len -= delta; + small_memset(t, val, delta); + } + i = len >> 7; /* len/128 */ + len&=127; + pmm_reg = mm_reg; + small_memset(pmm_reg,val,sizeof(mm_reg)); +/*#ifdef HAVE_ASM_SSE + //Only P3 (may be Cyrix3) + __asm__ __volatile__( + "movups (%0), %%xmm0\n" + :: "r"(mm_reg):"memory"); + for(; i>0; i--) + { + __asm__ __volatile__ ( + "movntps %%xmm0, (%0)\n" + "movntps %%xmm0, 16(%0)\n" + "movntps %%xmm0, 32(%0)\n" + "movntps %%xmm0, 48(%0)\n" + "movntps %%xmm0, 64(%0)\n" + "movntps %%xmm0, 80(%0)\n" + "movntps %%xmm0, 96(%0)\n" + "movntps %%xmm0, 112(%0)\n" + :: "r" (t) : "memory"); + t+=128; + } +#else +*/ + __asm__ __volatile__( + "movq (%0), %%mm0\n" + :: "r"(mm_reg):"memory"); + for(; i>0; i--) + { + __asm__ __volatile__ ( + MOVNTQ" %%mm0, (%0)\n" + MOVNTQ" %%mm0, 8(%0)\n" + MOVNTQ" %%mm0, 16(%0)\n" + MOVNTQ" %%mm0, 24(%0)\n" + MOVNTQ" %%mm0, 32(%0)\n" + MOVNTQ" %%mm0, 40(%0)\n" + MOVNTQ" %%mm0, 48(%0)\n" + MOVNTQ" %%mm0, 56(%0)\n" + MOVNTQ" %%mm0, 64(%0)\n" + MOVNTQ" %%mm0, 72(%0)\n" + MOVNTQ" %%mm0, 80(%0)\n" + MOVNTQ" %%mm0, 88(%0)\n" + MOVNTQ" %%mm0, 96(%0)\n" + MOVNTQ" %%mm0, 104(%0)\n" + MOVNTQ" %%mm0, 112(%0)\n" + MOVNTQ" %%mm0, 120(%0)\n" + :: "r" (t) : "memory"); + t+=128; + } +#ifdef HAVE_ASM_MMX2 + /* since movntq is weakly-ordered, a "sfence" + * is needed to become ordered again. */ + __asm__ __volatile__ ("sfence":::"memory"); + /* enables to use FPU */ + __asm__ __volatile__ (EMMS:::"memory"); +#endif + } + /* + * Now do the tail of the block + */ + if(len) small_memset(t, val, len); + return retval; +} +#endif + +static void *linux_kernel_memcpy(void *to, const void *from, size_t len) { + return __memcpy(to,from,len); +} + +#endif + +static struct { + char *name; + void *(*function)(void *to, const void *from, size_t len); + unsigned long long time; +} memcpy_method[] = +{ + { NULL, NULL, 0}, + { "glibc memcpy()", memcpy, 0}, +#if defined(ARCH_X86) || defined(ARCH_X86_64) + { "linux kernel memcpy()", linux_kernel_memcpy, 0}, +#endif +#if defined (HAVE_ASM_MMX) || defined( HAVE_ASM_SSE ) + { "MMX/MMX2/SSE optimized memcpy()", fast_memcpy, 0}, +#endif + { "aclib optimized ac_memcpy()", (void*) ac_memcpy, 0 }, + { NULL, NULL, 0}, +}; + +static struct { + char *name; + void *(*function)(void *to, uint8_t c, size_t len); + unsigned long long time; +} memset_method[] = +{ + { NULL, NULL, 0}, + { "glibc memset()", (void*)memset, 0}, +#if defined(HAVE_ASM_MMX) || defined(HAVE_ASM_MMX2) + { "MMX/MMX2 optimized memset()", (void*) fast_memset, 0}, +#endif + { NULL, NULL, 0}, +}; + + + + +void *(* veejay_memcpy)(void *to, const void *from, size_t len) = 0; + +void *(* veejay_memset)(void *what, uint8_t val, size_t len ) = 0; + +char *get_memcpy_descr( void ) +{ + int i = 1; + int best = 1; + for (i=1; memcpy_method[i].name; i++) + { + if( memcpy_method[i].time <= memcpy_method[best].time ) + best = i; + } + char *res = strdup( memcpy_method[best].name ); + return res; +} + +void find_best_memcpy() +{ + /* save library size on platforms without special memcpy impl. */ + unsigned long long t; + char *buf1, *buf2; + int i, best = 0; + int bufsize = 720 * 576 * 3; + if( bufsize == 0 ) + bufsize = BUFSIZE * 2000; + + if (!(buf1 = (char*) malloc( bufsize * sizeof(char) ))) + return; + + if (!(buf2 = (char*) malloc( bufsize * sizeof(char) ))) { + free( buf1 ); + return; + } + + memset(buf1,0, bufsize); + memset(buf2,0, bufsize); + + /* make sure buffers are present on physical memory */ + memcpy( buf1, buf2, bufsize); + memcpy( buf2, buf1, bufsize ); + + int c = 16; + int k; + unsigned long long statistics[c]; + for( k = 0; k < c; k ++ ) { + for (i=1; memcpy_method[i].name; i++) { + t = rdtsc(); + + memcpy_method[i].function( buf1 , buf2 , bufsize ); + + t = rdtsc() - t; + memcpy_method[i].time = t; + if (best == 0 || t < memcpy_method[best].time) + best = i; + } + if (best) { + veejay_memcpy = memcpy_method[best].function; + } + } + free( buf1 ); + free( buf2 ); +} + + + + +void find_best_memset() +{ + /* save library size on platforms without special memcpy impl. */ + unsigned long long t; + char *buf1, *buf2; + int i, best = 0; + + if (!(buf1 = (char*) malloc( BUFSIZE * 2000 * sizeof(char) ))) + return; + + if (!(buf2 = (char*) malloc( BUFSIZE * 2000 * sizeof(char) ))) { + free( buf1 ); + return; + } + + for( i = 0; i < (BUFSIZE*2000); i ++ ) + { + buf1[i] = 0; + buf2[i] = 0; + } + + for (i=1; memset_method[i].name; i++) + { + t = rdtsc(); + + memset_method[i].function( buf1 , 0 , 2000 * BUFSIZE ); + + t = rdtsc() - t; + + memset_method[i].time = t; + + if (best == 0 || t < memset_method[best].time) + best = i; + } + + if (best) { + veejay_memset = memset_method[best].function; + } + + free( buf1 ); + free( buf2 ); +} + diff --git a/branches/V-1.5.3/veejay-server/libvjmem/vj-x86.c b/branches/V-1.5.3/veejay-server/libvjmem/vj-x86.c new file mode 100644 index 00000000..69bad15e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjmem/vj-x86.c @@ -0,0 +1,215 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern void find_best_memcpy(void); +extern void find_best_memset(void); +extern void yuyv_plane_init(); + +static int MEM_ALIGNMENT_SIZE = 0; +static int CACHE_LINE_SIZE = 16; + + +#ifdef ARCH_X86 +int has_cpuid(void) +{ + int a, c; + +// code from libavcodec: + __asm__ __volatile__ ( + /* See if CPUID instruction is supported ... */ + /* ... Get copies of EFLAGS into eax and ecx */ + "pushf\n\t" + "popl %0\n\t" + "movl %0, %1\n\t" + + /* ... Toggle the ID bit in one copy and store */ + /* to the EFLAGS reg */ + "xorl $0x200000, %0\n\t" + "push %0\n\t" + "popf\n\t" + + /* ... Get the (hopefully modified) EFLAGS */ + "pushf\n\t" + "popl %0\n\t" + : "=a" (a), "=c" (c) + : + : "cc" + ); + + return (a!=c); +} + +// copied from Mplayer (want to have cache line size detection ;) ) +void +do_cpuid(unsigned int ax, unsigned int *p) +{ +// code from libavcodec: + __asm __volatile + ("movl %%ebx, %%esi\n\t" + "cpuid\n\t" + "xchgl %%ebx, %%esi" + : "=a" (p[0]), "=S" (p[1]), + "=c" (p[2]), "=d" (p[3]) + : "0" (ax)); +} + +int get_cache_line_size() +{ + unsigned int regs[4]; + unsigned int regs2[4]; + unsigned int ret = 32; // default cache line size + + if(!has_cpuid()) + { + return ret; + } + + do_cpuid( 0x00000000, regs); // get _max_ cpuid level and vendor name + if( regs[0] >= 0x00000001) + { + do_cpuid( 0x00000001, regs2 ); + ret = (( regs2[1] >> 8) & 0xff) * 8; + return ret; + } + do_cpuid(0x80000000, regs ); + if( regs[0] >= 0x80000006) { + do_cpuid( 0x80000001, regs2 ); + ret = (regs[2] & 0xff); + return ret; + } + return ret; +} + + +void mymemset_generic(void * s, char c,size_t count) +{ +int d0, d1; +__asm__ __volatile__( + "rep\n\t" + "stosb" + : "=&c" (d0), "=&D" (d1) + :"a" (c),"1" (s),"0" (count) + :"memory"); +} + +#else +void mymemset_generic(void *s, char c, size_t cc ) +{ + memset(s,c,cc); +} +#endif + +unsigned int vj_get_timer() +{ + struct timeval tv; + gettimeofday(&tv, 0); + return ((tv.tv_sec & 1000000) + tv.tv_usec); +} + +int cpu_cache_size() +{ + return CACHE_LINE_SIZE; +} + +void vj_mem_init(void) +{ + ac_init( AC_ALL ); + + ac_imgconvert_init(AC_ALL); + + +#ifdef ARCH_X86 + CACHE_LINE_SIZE = get_cache_line_size(); +#endif + if(MEM_ALIGNMENT_SIZE == 0) + MEM_ALIGNMENT_SIZE = getpagesize(); +#if defined (HAVE_ASM_MMX) || defined (HAVE_ASM_SSE) + yuyv_plane_init(); +#endif + find_best_memcpy(); + find_best_memset(); + +} + +void *vj_malloc_(unsigned int size) +{ + if( size == 0 ) + return NULL; + void *ptr = NULL; +#ifdef HAVE_POSIX_MEMALIGN + posix_memalign( &ptr, MEM_ALIGNMENT_SIZE, size ); +#else +#ifdef HAVE_MEMALIGN + ptr = memalign( MEM_ALIGNMENT_SIZE, size ); +#else + ptr = malloc ( size ) ; +#endif +#endif + if(!ptr) + return NULL; + + return ptr; +} +#ifdef STRICT_CHECKING +void *vj_strict_malloc( unsigned int size, const char *f, int line ) +{ + veejay_msg(0, "%d\t\tbytes\t\tin %s:%d",size,f,line); + return vj_malloc_( size ); +} +#endif +void *vj_calloc_( unsigned int size ) +{ + void *ptr = vj_malloc_( size ); + if(ptr) + veejay_memset( ptr, 0, size ); + return ptr; +} +#ifdef STRICT_CHECKING +void *vj_strict_calloc( unsigned int size, const char *f, int line ) +{ + veejay_msg(0, "%d\t\tbytes\t\tin %s:%d", size,f, line ); + return vj_calloc_(size); +} +#endif +#define RUP8(num)(((num)+8)&~8) + +void *vj_yuvalloc( unsigned int w, unsigned int h ) +{ + size_t len = RUP8(w * h * 3); + unsigned char *ptr = vj_malloc( len ); + + veejay_memset( ptr, 0, (w*h)); + veejay_memset( ptr + (w*h), 128, (w*h)*2); + return ptr; +} + + + + + diff --git a/branches/V-1.5.3/veejay-server/libvjmem/vjmem.h b/branches/V-1.5.3/veejay-server/libvjmem/vjmem.h new file mode 100644 index 00000000..af913e09 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjmem/vjmem.h @@ -0,0 +1,43 @@ +/* veejay - Linux VeeJay + * (C) 2002-2007 Niels Elburg + * + * + * 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. + */ + +#ifndef VJ_X86_H +#define VJ_X86_H + +extern void *(* veejay_memcpy)(void *to, const void *from, size_t len); +extern void *(* veejay_memset)(void *to, uint8_t val, size_t len); +extern void vj_mem_init(void); +extern char *get_memcpy_descr( void ); +extern void *vj_malloc_(unsigned int size); +#define vj_malloc(i) vj_malloc_(i) +extern void *vj_calloc_(unsigned int size ); +#define vj_calloc(i) vj_calloc_(i) +extern void *vj_yuvalloc( unsigned int w, unsigned int h ); +extern void fast_memset_dirty(void * to, int val, size_t len); +extern void fast_memset_finish(); +extern void packed_plane_clear( size_t len, void *to ); +extern void yuyv_plane_clear( size_t len, void *to ); +extern int cpu_cache_size(); +extern int get_cache_line_size(); +extern char *veejay_strncat( char *s1, char *s2, size_t n ); +extern char *veejay_strncpy( char *s1, const char *s2, size_t n ); +extern void yuyv_plane_init(); +extern void yuyv_plane_clear( size_t len, void *to ); +extern char **vje_build_param_list( int num, ... ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvjmsg/Makefile.am b/branches/V-1.5.3/veejay-server/libvjmsg/Makefile.am new file mode 100644 index 00000000..28290b74 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjmsg/Makefile.am @@ -0,0 +1,8 @@ +# Makefile for logging/messages +INCLUDES = -I$(top_srcdir) -I$(includedir) +AM_CLFAGS=$(OP_CFLAGS) +VJMSG_LIB_FILE = libvjmsg.la +noinst_LTLIBRARIES = $(VJMSG_LIB_FILE) +pkginclude_HEADERS= vj-msg.h +libvjmsg_la_SOURCES = vj-common.c + diff --git a/branches/V-1.5.3/veejay-server/libvjmsg/vj-common.c b/branches/V-1.5.3/veejay-server/libvjmsg/vj-common.c new file mode 100644 index 00000000..d174fa8e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjmsg/vj-common.c @@ -0,0 +1,510 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2010 Niels Elburg + * + * 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 + */ + + +/** + * Printing the stack trace, explanation by Jaco Kroon: + * http://tlug.up.ac.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV + * Author: Jaco Kroon + * Copyright (C) 2005 - 2008 Jaco Kroon + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Bug in gcc prevents from using CPP_DEMANGLE in pure "C" */ +#if !defined(__cplusplus) && !defined(NO_CPP_DEMANGLE) +#define NO_CPP_DEMANGLE +#endif +#ifndef NO_CPP_DEMANGLE +#include +#endif + +#if defined(REG_RIP) +#define SIGSEGV_STACK_IA64 +#elif defined(REG_EIP) +#define SIGSEGV_STACK_X86 +#else +#define SIGSEGV_STACK_GENERIC +#endif + +#define TXT_RED "\033[0;31m" +#define TXT_RED_B "\033[1;31m" +#define TXT_GRE "\033[0;32m" +#define TXT_GRE_B "\033[1;32m" +#define TXT_YEL "\033[0;33m" +#define TXT_YEL_B "\033[1;33m" +#define TXT_BLU "\033[0;34m" +#define TXT_BLU_B "\033[1;34m" +#define TXT_WHI "\033[0;37m" +#define TXT_WHI_B "\033[1;37m" +#define TXT_END "\033[0m" + + +static int _debug_level = 0; +static int _color_level = 1; +static int _no_msg = 0; + + +#define MAX_LINES 100 +typedef struct +{ + char *msg[MAX_LINES]; + int r_index; + int w_index; +} vj_msg_hist; +/* +static vj_msg_hist _message_history; +static int _message_his_status = 0; +*/ + + +static void veejay_addr2line_bt( int n, void *addr, char *sym ) +{ + int res; + Dl_info info; + const void *address; + FILE *out; + char cmd[1024]; + char line[1024], *line_ptr, *line_pos; + char func_name[1024]; + int line_no; + + res = dladdr( addr, &info ); + if( (res == 0) || !info.dli_fname || !info.dli_fname[0] ) { + veejay_msg(VEEJAY_MSG_INFO, "\t%d ?:ACCESS VIOLATION", n); + return; + } + + address = addr; + if( info.dli_fbase >= (const void*)0x40000000) + addr = (const char*) address - (unsigned int ) info.dli_fbase; + + snprintf( cmd,sizeof(cmd), "addr2line --functions --demangle -e $(which %s) %p", info.dli_fname, address); + out = popen( cmd, "r"); + if(!out) { + veejay_msg(VEEJAY_MSG_INFO, "\t%d %s (addr2line error)", n, sym ); + return; + } + + func_name[0] = '\0'; + line_no = 0; + + while( !feof(out)) { + line_ptr = fgets(line,sizeof(line)-1,out); + if(line_ptr && line_ptr[0]) { + line_pos = strchr( line_ptr, '\n'); + if( line_pos ) + line_pos[0] = '\0'; + if( strchr( line_ptr, ':' )) { + line_no = 1; + veejay_msg(VEEJAY_MSG_INFO, "\t%d %s %s (@%x)", + n, + line_ptr, + func_name, + addr); + func_name[0] = '\0'; + } else { + if( func_name[0] ) + veejay_msg(VEEJAY_MSG_INFO, "%d\t%s", n, func_name ); + snprintf(func_name, sizeof(func_name), "%s", line_ptr ); + } + } + } + if( func_name[0] ) + veejay_msg(VEEJAY_MSG_INFO, "%03d %s",n,func_name ); + fclose(out); +} + +void veejay_print_backtrace() +{ + void *space[100]; + size_t i,s; + char **strings; + + int i_size = sizeof(void*); + int n_size = i_size * 2 + 1; + + s = backtrace( space, 100 ); + strings = backtrace_symbols(space,s); + + for( i = 0; i < s ; i ++ ) + veejay_addr2line_bt( i + 1, space[i],strings[i] ); + + +} + +void veejay_backtrace_handler(int n , void *dist, void *x) +{ + siginfo_t *ist = (siginfo_t*) dist; + static char *strerr = "???"; + static struct ucontext *puc; + int i,f=0; + void *ip = NULL; + void **bp = NULL; + Dl_info info; + + puc = (struct ucontext*) x; +#define SICCASE(c) case c: strerr = #c + switch(n) { + case SIGSEGV: + switch(ist->si_code) { + SICCASE(SEGV_MAPERR); + SICCASE(SEGV_ACCERR); + } + + //@ print stack +#ifndef SIGSEGV_NOSTACK +#if defined(SIGSEGV_STACK_IA64) || defined(SIGSEGV_STACK_X86) +#if defined(SIGSEGV_STACK_IA64) + ip = (void*) puc->uc_mcontext.gregs[REG_RIP]; + bp= (void**) puc->uc_mcontext.gregs[REG_RBP]; +#elif defined(SIGSEGV_STACK_X86) + ip = (void*) puc->uc_mcontext.gregs[REG_EIP]; + bp = (void**) puc->uc_mcontext.gregs[REG_EBP]; +#endif +#endif +#endif + + veejay_msg(VEEJAY_MSG_ERROR,"Found Gremlins in your system."); //@ Suggested by Matthijs + veejay_msg(VEEJAY_MSG_WARNING, "No fresh ale found in the fridge."); //@ + veejay_msg(VEEJAY_MSG_INFO, "Running with sub-atomic precision..."); //@ + +#if defined(SIGSEGV_STACK_IA64) || defined(SIGSEGV_STACK_X86) +#if defined(SIGSEGV_STACK_X86) + veejay_msg(VEEJAY_MSG_INFO,"(%s) invalid access to %p at %x", + strerr,ist->si_addr, puc->uc_mcontext.gregs[REG_EIP]); + veejay_addr2line_bt( 0, puc->uc_mcontext.gregs[REG_EIP] , puc->uc_mcontext.gregs[REG_EIP] ); +#elif defined(SIGSEGV_STACK_IA64) + veejay_msg(VEEJAY_MSG_INFO,"(%s) invalid access to %p at %x", + strerr,ist->si_addr, puc->uc_mcontext.gregs[REG_RIP]); + veejay_addr2line_bt( 0, puc->uc_mcontext.gregs[REG_RIP], puc->uc_mcontext.gregs[REG_RIP] ); +#endif +#endif + for( i = 0; i < NGREG; i ++ ) { + veejay_msg(VEEJAY_MSG_INFO, "\tregister [%2d]\t=%x",i,puc->uc_mcontext.gregs[i]); + } + + while( bp && ip ) { + + if( !dladdr( ip, &info )) + break; + char *symname = info.dli_sname; +#ifndef NO_CPP_DEMANGLE + int status; + char *tmp = __cxa_demangle( symname, NULL, 0, + &status ); + if( status == 0 && tmp ) + symname = tmp; +#endif + + veejay_msg(VEEJAY_MSG_INFO,"\t\t%d\t: %p <%s+%lu> (%s)", + ++f, + ip, + symname, + (unsigned long) ip - (unsigned long) info.dli_saddr, + info.dli_fname ); +#ifndef NO_CPP_DEMANGLE + if(tmp) + free(tmp); +#endif + + if(info.dli_sname && !strcmp(info.dli_sname, "main")) + break; + + ip = bp[1]; + bp = (void**) bp[0]; + + } + + break; + } + +#if defined(SIGSEGV_STACK_IA64) || defined(SIGSEGV_STACK_X86) +#if defined(SIGSEGV_STACK_IA64) + veejay_print_backtrace(puc->uc_mcontext.gregs[REG_RIP]); +#elif defined(SIGSEGV_STACK_X86) + veejay_print_backtrace(puc->uc_mcontext.gregs[REG_EIP]); +#endif +#endif + //@ Bye + veejay_msg(VEEJAY_MSG_ERROR, "Bugs compromised the system."); + + report_bug(); + + exit(0); +} + +void veejay_set_debug_level(int level) +{ + if(level) + { + _debug_level = 1; + } + else + { + _debug_level = 0; + } +} +void veejay_set_colors(int l) +{ + if(l) _color_level = 1; + else _color_level = 0; +} + +int veejay_is_colored() +{ + return _color_level; +} + +void veejay_silent() +{ + _no_msg = 1; +} + +int veejay_is_silent() +{ + if(_no_msg) return 1; + return 0; +} + +void veejay_msg(int type, const char format[], ...) +{ + char prefix[64]; + char buf[256]; + va_list args; + int line = 0; + + FILE *out = (_no_msg ? stderr: stdout ); + + if( type != VEEJAY_MSG_ERROR && _no_msg ) + return; + + if( !_debug_level && type == VEEJAY_MSG_DEBUG ) + return ; // bye + + // parse arguments + va_start(args, format); + vsnprintf(buf, sizeof(buf) - 1, format, args); + /* + if(!_message_his_status) + { + veejay_memset( &_message_history , 0 , sizeof(vj_msg_hist)); + _message_his_status = 1; + } +*/ + if(_color_level) + { + switch (type) { + case 2: //info + sprintf(prefix, "%sI: ", TXT_GRE); + break; + case 1: //warning + sprintf(prefix, "%sW: ", TXT_YEL); + break; + case 0: // error + sprintf(prefix, "%sE: ", TXT_RED); + break; + case 3: + line = 1; + break; + case 4: // debug + sprintf(prefix, "%sD: ", TXT_BLU); + break; + } + + if(!line) + fprintf(out,"%s %s %s\n", prefix, buf, TXT_END); + else + fprintf(out,"%s%s%s", TXT_GRE, buf, TXT_END ); +/* + if( _message_history.w_index < MAX_LINES ) + { + if(type == 3) + sprintf(sline, "%s", buf ); + else + sprintf( sline, "%s\n", buf ); + _message_history.msg[_message_history.w_index ++ ] = strndup(sline,200); + }*/ + } + else + { + switch (type) { + case 2: //info + sprintf(prefix, "I: "); + break; + case 1: //warning + sprintf(prefix, "W: "); + break; + case 0: // error + sprintf(prefix, "E: "); + break; + case 3: + line = 1; + break; + case 4: // debug + sprintf(prefix, "D: "); + break; + } + + if(!line) + fprintf(out,"%s %s\n", prefix, buf); + else + fprintf(out,"%s", buf ); + + /* if( _message_history.w_index < MAX_LINES ) + { + if(type == 3 ) + sprintf(sline, "%s", buf ); + else + sprintf(sline, "%s\n", buf ); + _message_history.msg[_message_history.w_index ++ ] = strdup(sline); + }*/ + } + va_end(args); +} + +char *veejay_pop_messages(int *num_lines, int *total_len) +{ + char *res = NULL; +/* if( _message_his_status == 0 ) + return res; + if( _message_history.w_index == 0 ) + return res; + int i; + int len = 0; + for( i = 0; i < _message_history.w_index ; i ++ ) + len += strlen( _message_history.msg[i] ); + if(len <= 0) + return res; + + res = (char*) vj_malloc(sizeof(char) * (len+1) ); + if(!res) + return NULL; + bzero(res, len ); + *num_lines = i; + + for( i = 0; i < _message_history.w_index ; i ++ ) + { + if( strlen(_message_history.msg[i]) > 0 ) + strcat( res, _message_history.msg[i] ); + } + *total_len = len; + _message_history.r_index ++; +*/ + return res; + +} + +int veejay_keep_messages(void) +{ +/* if( _message_history.r_index ) + return 0; +*/ + return 1; +} + +void veejay_reap_messages(void) +{ +/* for( i = 0; i < _message_history.w_index ; i ++ ) + { + if( _message_history.msg[i] ) + { + free(_message_history.msg[i] ); + _message_history.msg[i] = NULL; + } + } + + _message_his_status = 0; + _message_history.w_index = 0; +*/ +} + +int veejay_get_file_ext( char *file, char *dst, int dlen) +{ + int len = strlen(file)-1; + int i = 0; + char tmp[dlen]; + bzero(tmp,dlen); + while(len) + { + if(file[len] == '.') + { + if(i==0) return 0; + int j; + int k = 0; + for(j = i-1; j >= 0;j--) + { + dst[k] = tmp[j]; + k ++; + } + return 1; + } + tmp[i] = file[len]; + i++; + if( i >= dlen) + return 0; + len --; + } + return 0; +} + +void veejay_strrep(char *s, char delim, char tok) +{ + unsigned int i; + unsigned int len = strlen(s); + if(!s) return; + for(i=0; i < len; i++) + { + if( s[i] == delim ) s[i] = tok; + } +} + +void veejay_chomp_str( char *msg, int *nlen ) +{ + int len = strlen( msg ) - 1; + if(len > 0 ) + { + if( msg[len] == '\n' ) + { + msg[len] = '\0'; + *nlen = len; + } + } +} + +void report_bug(void) +{ + veejay_msg(VEEJAY_MSG_WARNING, "Please report this error to http://groups.google.com/group/veejay-discussion?hl=en"); + veejay_msg(VEEJAY_MSG_WARNING, "Send at least veejay's output and include the command(s) you have used to start it."); + veejay_msg(VEEJAY_MSG_WARNING, "Also, please consider sending in the recovery files if any have been created."); + veejay_msg(VEEJAY_MSG_WARNING, "If you compiled it yourself, please include information about your system."); +} + diff --git a/branches/V-1.5.3/veejay-server/libvjmsg/vj-msg.h b/branches/V-1.5.3/veejay-server/libvjmsg/vj-msg.h new file mode 100644 index 00000000..0eb6b55c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjmsg/vj-msg.h @@ -0,0 +1,46 @@ +/* veejay - Linux VeeJay + * (C) 2002-2007 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_COMMON_H +#define VJ_COMMON_H +#include +#include + +enum { + VEEJAY_MSG_INFO = 2, + VEEJAY_MSG_WARNING = 1, + VEEJAY_MSG_ERROR = 0, + VEEJAY_MSG_PRINT = 3, + VEEJAY_MSG_DEBUG = 4, +}; + +extern void veejay_backtrace_handler(int n , void *ist, void *x); +extern void veejay_strrep(char *s, char delim, char tok); +extern void report_bug(); +extern void veejay_msg(int type, const char format[], ...); +extern int veejay_is_colored(); +extern void veejay_set_debug_level(int level); +extern void veejay_set_colors(int level); +extern void veejay_silent(); +extern int veejay_is_silent(); +extern int veejay_keep_messages(void); +extern void veejay_reap_messages(void); +extern char *veejay_pop_messages(int *num_lines, int *total_len); +extern int veejay_get_file_ext( char *file, char *dst, int dlen); +extern void veejay_chomp_str( char *str, int *dlen ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvjnet/Makefile.am b/branches/V-1.5.3/veejay-server/libvjnet/Makefile.am new file mode 100644 index 00000000..9357a65b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/Makefile.am @@ -0,0 +1,10 @@ +# Makefile for veejay + +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/libyuv -I$(top_srcdir)/liblzo -I$(top_srcdir)/vjmem -I$(top_srcdir)/vjmsg +VJNET_LIB_FILE = libvjnet.la +EXTRA_DIST= vj-client.h bswap.h cmd.h mcastreceiver.h mcastsender.h packet.h vj-server.h +pkginclude_HEADERS=vj-client.h +noinst_LTLIBRARIES = $(VJNET_LIB_FILE) +libvjnet_la_SOURCES = packet.c mcastsender.c mcastreceiver.c cmd.c vj-server.c vj-client.c diff --git a/branches/V-1.5.3/veejay-server/libvjnet/bswap.h b/branches/V-1.5.3/veejay-server/libvjnet/bswap.h new file mode 100644 index 00000000..864bedfd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/bswap.h @@ -0,0 +1,126 @@ +#ifndef __BSWAP_H__ +#define __BSWAP_H__ + +#ifdef HAVE_BYTESWAP_H +#include +#else + +#include + +#ifdef ARCH_X86 +static inline unsigned short ByteSwap16(unsigned short x) +{ + __asm("xchgb %b0,%h0" : + "=q" (x) : + "0" (x)); + return x; +} +#define bswap_16(x) ByteSwap16(x) + +static inline unsigned int ByteSwap32(unsigned int x) +{ +#if __CPU__ > 386 + __asm("bswap %0": + "=r" (x) : +#else + __asm("xchgb %b0,%h0\n" + " rorl $16,%0\n" + " xchgb %b0,%h0": + "=q" (x) : +#endif + "0" (x)); + return x; +} +#define bswap_32(x) ByteSwap32(x) + +static inline unsigned long long int ByteSwap64(unsigned long long int x) +{ + register union { __extension__ uint64_t __ll; + uint32_t __l[2]; } __x; + asm("xchgl %0,%1": + "=r"(__x.__l[0]),"=r"(__x.__l[1]): + "0"(bswap_32((unsigned long)x)),"1"(bswap_32((unsigned long)(x>>32)))); + return __x.__ll; +} +#define bswap_64(x) ByteSwap64(x) + +#elif defined(ARCH_SH4) + +static inline uint16_t ByteSwap16(uint16_t x) { + __asm__("swap.b %0,%0":"=r"(x):"0"(x)); + return x; +} + +static inline uint32_t ByteSwap32(uint32_t x) { + __asm__( + "swap.b %0,%0\n" + "swap.w %0,%0\n" + "swap.b %0,%0\n" + :"=r"(x):"0"(x)); + return x; +} + +#define bswap_16(x) ByteSwap16(x) +#define bswap_32(x) ByteSwap32(x) + +static inline uint64_t ByteSwap64(uint64_t x) +{ + union { + uint64_t ll; + struct { + uint32_t l,h; + } l; + } r; + r.l.l = bswap_32 (x); + r.l.h = bswap_32 (x>>32); + return r.ll; +} +#define bswap_64(x) ByteSwap64(x) + +#else + +#define bswap_16(x) (((x) & 0x00ff) << 8 | ((x) & 0xff00) >> 8) + + +// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc. +#define bswap_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +static inline uint64_t ByteSwap64(uint64_t x) +{ + union { + uint64_t ll; + uint32_t l[2]; + } w, r; + w.ll = x; + r.l[0] = bswap_32 (w.l[1]); + r.l[1] = bswap_32 (w.l[0]); + return r.ll; +} +#define bswap_64(x) ByteSwap64(x) + +#endif /* !ARCH_X86 */ + +#endif /* !HAVE_BYTESWAP_H */ + +// be2me ... BigEndian to MachineEndian +// le2me ... LittleEndian to MachineEndian + +#ifdef WORDS_BIGENDIAN +#define be2me_16(x) (x) +#define be2me_32(x) (x) +#define be2me_64(x) (x) +#define le2me_16(x) bswap_16(x) +#define le2me_32(x) bswap_32(x) +#define le2me_64(x) bswap_64(x) +#else +#define be2me_16(x) bswap_16(x) +#define be2me_32(x) bswap_32(x) +#define be2me_64(x) bswap_64(x) +#define le2me_16(x) (x) +#define le2me_32(x) (x) +#define le2me_64(x) (x) +#endif + +#endif /* __BSWAP_H__ */ diff --git a/branches/V-1.5.3/veejay-server/libvjnet/cmd.c b/branches/V-1.5.3/veejay-server/libvjnet/cmd.c new file mode 100644 index 00000000..38513a95 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/cmd.c @@ -0,0 +1,304 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005 Niels Elburg + * + * + * 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 "cmd.h" +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +vj_sock_t *alloc_sock_t(void) +{ + vj_sock_t *s = (vj_sock_t*) malloc(sizeof(vj_sock_t)); + if(!s) return NULL; + return s; +} + +void sock_t_free(vj_sock_t *s ) +{ + if(s) free(s); +} + +#define TIMEOUT 3 + +int sock_t_connect_and_send_http( vj_sock_t *s, char *host, int port, char *buf, int buf_len ) +{ + s->he = gethostbyname( host ); + if(s->he==NULL) + return 0; + s->sock_fd = socket( AF_INET, SOCK_STREAM , 0); + if(s->sock_fd < 0) + { + return 0; + } + s->port_num = port; + s->addr.sin_family = AF_INET; + s->addr.sin_port = htons( port ); + s->addr.sin_addr = *( (struct in_addr*) s->he->h_addr ); + if( connect( s->sock_fd, (struct sockaddr*) &s->addr, + sizeof( struct sockaddr )) == -1 ) + { + return 0; + } + + struct sockaddr_in sinfo; + socklen_t sinfolen=0; + char server_name[1024]; + if( getsockname(s->sock_fd,(struct sockaddr*) &sinfo,&sinfolen)==0) { + char *tmp = inet_ntoa( sinfo.sin_addr ); + strncpy( server_name, tmp, 1024); + } else { + return 0; + } + + int len = strlen(server_name) + 128 + buf_len; + char *msg = (char*) malloc(sizeof(char) * len ); + struct utsname name; + if( uname(&name) == -1 ) { + snprintf(msg,len,"%s%s/veejay-%s\n\n",buf,server_name,PACKAGE_VERSION); + } else { + snprintf(msg,len,"%s%s/veejay-%s/%s-%s\n\n",buf,server_name,PACKAGE_VERSION,name.sysname,name.release ); + } + int msg_len = strlen(msg); + int n = send(s->sock_fd,msg,msg_len, 0 ); + free(msg); + + if( n == -1 ) + { + return 0; + } + + return n; +} + +int sock_t_connect( vj_sock_t *s, char *host, int port ) +{ + s->he = gethostbyname( host ); + if(s->he==NULL) + return 0; + s->sock_fd = socket( AF_INET, SOCK_STREAM , 0); + if(s->sock_fd < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Socket error with Veejay host %s:%d %s ", host,port,strerror(errno)); + return 0; + } + s->port_num = port; + s->addr.sin_family = AF_INET; + s->addr.sin_port = htons( port ); + s->addr.sin_addr = *( (struct in_addr*) s->he->h_addr ); + + if( connect( s->sock_fd, (struct sockaddr*) &s->addr, + sizeof( struct sockaddr )) == -1 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Connection error with Veejay host %s:%d %s", + host, port, strerror(errno)); + return 0; + } + unsigned int tmp = sizeof(int); + if( getsockopt( s->sock_fd , SOL_SOCKET, SO_SNDBUF, (unsigned char*) &(s->send_size), &tmp) < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to get buffer size for output: %s", strerror(errno)); + return 0; + } + if( getsockopt( s->sock_fd, SOL_SOCKET, SO_RCVBUF, (unsigned char*) &(s->recv_size), &tmp) < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to get buffer size for input: %s", strerror(errno)); + return 0; + } + + return 1; +} + +int sock_t_wds_isset( vj_sock_t *s ) { + return FD_ISSET( s->sock_fd, &(s->wds)); +} + +int sock_t_rds_isset( vj_sock_t *s ) { + return FD_ISSET( s->sock_fd, &(s->rds) ); +} + +int sock_t_poll( vj_sock_t *s ) +{ + int status; + struct timeval no_wait; + memset( &no_wait, 0, sizeof(no_wait) ); + + FD_ZERO( &(s->rds) ); + FD_ZERO( &(s->wds) ); + + FD_SET( s->sock_fd, &(s->rds) ); + FD_SET( s->sock_fd, &(s->wds) ); + + status = select( s->sock_fd + 1, &(s->rds),&(s->wds), 0, &no_wait ); + + if( status == -1 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to poll socket for immediate read: %s", strerror(errno)); + return -1; + } + if( status == 0 ) + return -1; + + if( sock_t_rds_isset( s ) ) + return 1; + + return 0; +} + +/* +static int timed_recv( int fd, void *buf, const int len, int timeout ) +{ + fd_set fds; + int n; + + struct timeval tv; + memset( &tv, 0,sizeof(timeval)); + FD_ZERO(&fds); + FD_SET( fd,&fds ); + + tv.tv_sec = TIMEOUT; + + n = select( fd + 1, &fds, NULL, NULL, &tv ); + if( n == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "\tsocket %x :: requested %d bytes", fd, len ); + } + + if( n == -1 ) + return -1; + + if( n == 0 ) + return -5; + + return recv( fd, buf, len, 0 ); +}*/ + +void sock_t_set_timeout( vj_sock_t *s, int t ) +{ + int opt = t; + setsockopt( s->sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char*) &opt, sizeof(int)); + setsockopt( s->sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char*) &opt, sizeof(int)); +} + +int sock_t_recv( vj_sock_t *s, void *dst, int len ) +{ + int done = 0; + int bytes_left = s->recv_size; + int n; + + if( len < bytes_left ) + bytes_left = len; + + while( done < len ) + { + //@ setup socket with SO_RCVTIMEO + n = recv( s->sock_fd, dst+done,bytes_left, 0 ); + if ( n < 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, "%s", strerror(errno)); + return -1; + } else if ( n == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Remote closed connection."); + return -1; + } + + done += n; + + if( (len-done) < s->recv_size ) + bytes_left = len - done; + } + return done; +} + +int sock_t_send( vj_sock_t *s, unsigned char *buf, int len ) +{ + int n; +#ifdef STRICT_CHECKING + assert( buf != NULL ); +#endif +/* if( sock_t_wds_isset( s ) == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "%s", __FUNCTION__); + return 0; + }*/ + + int length = len; + int bw = 0; + int done = 0; + while( length > 0 ) { + bw = length; + n = send( s->sock_fd, buf, length , 0 ); + if( n == -1 ) { + veejay_msg(0, "Error sending buffer:%s",strerror(errno)); + return -1; + } + if( n == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Remote closed connection."); + return -1; + } + buf += n; + length -= n; + done += n; + } + return done; +} + +int sock_t_send_fd( int fd, int send_size, unsigned char *buf, int len ) +{ + int n; +#ifdef STRICT_CHECKING + assert( buf != NULL ); +#endif + + int length = len; + int bw = 0; + int done = 0; + while( length > 0 ) { + bw = length; + n = send( fd, buf, length , 0 ); + if( n == -1 ) { + veejay_msg(0, "Error sending buffer:%s", strerror(errno)); + return -1; + } + if( n == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Remote closed connection."); + return -1; + } + buf += n; + length -= n; + done += n; + } + return done; + +} + +void sock_t_close( vj_sock_t *s ) +{ + if(s) + { + close(s->sock_fd); + s->sock_fd = 0; + FD_ZERO(&(s->rds)); + FD_ZERO(&(s->wds)); + } +} diff --git a/branches/V-1.5.3/veejay-server/libvjnet/cmd.h b/branches/V-1.5.3/veejay-server/libvjnet/cmd.h new file mode 100644 index 00000000..93a40763 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/cmd.h @@ -0,0 +1,52 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005 Niels Elburg + * + * + * 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. + */ +#ifndef CMD_H_INCLUDED +#define CMD_H_INCLUDED +#include +#include +#include +#include +#include +typedef struct +{ + struct hostent *he; + struct sockaddr_in addr; + int sock_fd; + int port_num; + unsigned char *sbuf; + int send_size; + int recv_size; + fd_set rds; + fd_set wds; +} vj_sock_t; + +vj_sock_t *alloc_sock_t(void); +void sock_t_free(vj_sock_t *s); +int sock_t_wds_isset(vj_sock_t *s); +int sock_t_rds_isset(vj_sock_t *s); +int sock_t_connect( vj_sock_t *s, char *host, int port ); +int sock_t_poll( vj_sock_t *s ); +int sock_t_recv( vj_sock_t *s, void *dst, int len ); +int sock_t_send( vj_sock_t *s, unsigned char *buf, int len ); +int sock_t_send_fd( int fd, int sndsize, unsigned char *buf, int len ); +void sock_t_close( vj_sock_t *s ); +int sock_t_connect_and_send_http( vj_sock_t *s, char *host, int port, char *buf, int buf_len ); +void sock_t_set_timeout( vj_sock_t *s, int t ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvjnet/dummy.c b/branches/V-1.5.3/veejay-server/libvjnet/dummy.c new file mode 100644 index 00000000..7adf170f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/dummy.c @@ -0,0 +1,92 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005 Niels Elburg + * + * + * 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. + */ +/* + + very dumb server test code + +*/ +#include +#include "vj-server.h" + +int main( int argc, char *argv[] ) +{ + + vj_server *s = vj_server_alloc( 5000, NULL, V_CMD); + vj_server *k = vj_server_alloc( 5001, NULL, V_STATUS ); + int frame = 0; + + veejay_set_debug_level(4); + + while(1) + { + char status[30]; + int status_len; + sprintf(status, "%d %d %d", frame,frame,frame); + frame++; + status_len = strlen(status); + if( vj_server_poll(s) ) + { + int i; + if(!vj_server_new_connection( s )) + { + int res; + for(i = 0; i < s->nr_of_links; i ++ ) + { + res = vj_server_update(s, i ); + if( res == -1 ) + { + _vj_server_del_client( k, i ); + } + + if( res > 0 ) + { + char tmp[4096]; + bzero(tmp,4096); + while( vj_server_retrieve_msg(s,i, tmp ) ) + { + printf("recv [%s]\n", tmp ); + } + } + } + } + } + + + if( vj_server_poll(k) ) + { + + if(!vj_server_new_connection( k )) + { + int j ; + if( k->nr_of_links > 0 ) + for( j = 0; j < k->nr_of_links ; j ++ ) + vj_server_send( k, j, status, status_len ); + + } + + } + + usleep(40000); + } + vj_server_shutdown( s ); + + + return 0; +} diff --git a/branches/V-1.5.3/veejay-server/libvjnet/mcastreceiver.c b/branches/V-1.5.3/veejay-server/libvjnet/mcastreceiver.c new file mode 100644 index 00000000..3715e5a2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/mcastreceiver.c @@ -0,0 +1,403 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005-2007 Niels Elburg + * + * + * 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 "mcastreceiver.h" +#include +#include +#include +#include +#include "packet.h" +#include +#ifdef STRICT_CHECKING +#include +#endif + +static void print_error(char *msg) +{ + veejay_msg(VEEJAY_MSG_ERROR,"%s: %s\n", msg,strerror(errno)); +} + +typedef struct +{ + packet_header_t hdr; + frame_info_t inf; + uint8_t *buf; + int len; + int count; + int rdy; +} packet_buffer_t; + +#define PACKET_SLOTS 3 +typedef struct +{ + packet_buffer_t **slot; + int in_slot; + long last; +} packet_slot_t; + +mcast_receiver *mcast_new_receiver( const char *group_name, int port ) +{ + mcast_receiver *v = (mcast_receiver*) vj_calloc(sizeof(mcast_receiver)); + if(!v) return NULL; + int on = 1; + struct ip_mreq mcast_req; + int i; + veejay_memset( &mcast_req, 0, sizeof(mcast_req )); + veejay_memset( &(v->addr), 0, sizeof(struct sockaddr_in) ); + v->group = (char*) strdup( group_name ); + v->port = port; + + v->sock_fd = socket( AF_INET, SOCK_DGRAM, 0 ); + if(v->sock_fd < 0) + { + veejay_msg(0, "Unable to get a datagram socket: %s", strerror(errno)); + if(v->group) free(v->group); + if(v) free(v); + return NULL; + } + +#ifdef SO_REUSEADDR + if ( setsockopt( v->sock_fd, SOL_SOCKET, SO_REUSEADDR, &on,sizeof(on))<0) + { + veejay_msg(0, "Unable to set SO_REUSEADDR: %s", strerror(errno)); + if(v->group) free(v->group); + if(v) free(v); + return NULL; + } +#endif +#ifdef SO_REUSEPORT + if ( setsockopt( v->sock_fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))<0) + { + veejay_msg(0, "Unable to set SO_REUSEPORT: %s", strerror(errno)); + if(v->group) free(v->group); + if(v) free(v); + return NULL; + } +#endif + + v->addr.sin_addr.s_addr = htonl( INADDR_ANY ); + v->addr.sin_port = htons( v->port ); + + if( bind( v->sock_fd, (struct sockaddr*) &(v->addr), sizeof(struct sockaddr_in))<0) + { + veejay_msg(0, "Unable to bind to port %d : %s", v->port, strerror(errno)); + if(v->group) free(v->group); + if(v) free(v); + return NULL; + } + mcast_req.imr_multiaddr.s_addr = inet_addr( v->group ); + mcast_req.imr_interface.s_addr = htonl( INADDR_ANY ); + if( setsockopt( v->sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast_req, + sizeof(mcast_req) ) < 0 ) + { + veejay_msg(0, "Unable to join multicast group %s (port=%d)",group_name,port, strerror(errno)); + if(v->group) free(v->group); + if(v) free(v); + return NULL; + } + + packet_slot_t *q = (packet_slot_t*) vj_calloc(sizeof(packet_slot_t)); + q->slot = (packet_buffer_t**) vj_calloc(sizeof(packet_buffer_t*) * PACKET_SLOTS ); + for( i = 0; i < PACKET_SLOTS ; i ++ ) + q->slot[i] = (packet_buffer_t*) vj_calloc(sizeof(packet_buffer_t)); + v->next = (void*)q; + + return v; +} +int mcast_receiver_set_peer( mcast_receiver *v, const char *hostname ) +{ + struct hostent *host; + host = gethostbyname( hostname ); + if(host) + { + v->addr.sin_family = host->h_addrtype; + if( host->h_length > (int) sizeof(v->addr.sin_addr)) + host->h_length = sizeof( v->addr.sin_addr ); + memcpy( &(v->addr.sin_addr), host->h_addr, host->h_length ); + } + else + { + v->addr.sin_family = AF_INET; + if( !inet_aton( hostname, &(v->addr.sin_addr) ) ) + { + veejay_msg(0, "Invalid host '%s'", hostname ); + return 0; + } + } + return 1; +} + +int mcast_poll( mcast_receiver *v ) +{ +#ifdef STRICT_CHECKING + assert( v != NULL ); +#endif + fd_set fds; + struct timeval tv; + memset( &tv, 0, sizeof(tv) ); + FD_ZERO( &fds ); + FD_SET( v->sock_fd, &fds ); + + if( select( v->sock_fd + 1, &fds, 0,0, &tv ) <= 0 ) + return 0; + return 1; +} + +static int mcast_poll_timeout( mcast_receiver *v, long timeout ) +{ + fd_set fds; + struct timeval tv; + int n = 0; + tv.tv_sec = 0; + tv.tv_usec = timeout; // 0.05 seconds + FD_ZERO( &fds ); + FD_SET( v->sock_fd, &fds ); + + if( timeout == 0 ) + n = select( v->sock_fd + 1, &fds, NULL,NULL, NULL ); + else + n = select( v->sock_fd + 1, &fds, 0,0, &tv ); + if(n == -1) + veejay_msg(0, "Multicast receiver select error: %s", strerror(errno)); + + if( n <= 0) + return 0; + + return 1; +} + + + +int mcast_recv( mcast_receiver *v, void *buf, int len ) +{ + int n = recv( v->sock_fd, buf, len, 0 ); + if ( n == -1 ) + veejay_msg(0, "Multicast receive error: %s", strerror(errno)); + + return n; +} + +int mcast_recv_packet_frame( mcast_receiver *v ) +{ + uint8_t chunk[PACKET_PAYLOAD_SIZE]; + packet_slot_t *q = (packet_slot_t*) v->next; + + packet_header_t hdr; + frame_info_t inf; + + int res = recv(v->sock_fd, chunk, PACKET_PAYLOAD_SIZE, 0 ); + if( res <= 0 ) + { + if(res == - 1) + veejay_msg(VEEJAY_MSG_ERROR, "Error receiving multicast packet:%s", strerror(errno)); + + return 0; + } + hdr = packet_get_header(chunk); + packet_get_info( &inf, chunk ); + + //@ choose slot to fill + int i; + int d_slot = -1; + + for(i = 0; i < PACKET_SLOTS; i ++ ) + { + if( q->slot[i]->hdr.usec == hdr.usec ) { + d_slot = i; +#ifdef STRICT_CHECKING + assert( q->slot[i]->len == inf.len ); +#endif + break; + } + } + + if( d_slot == -1) { + //@ find slot with count == 0 (unused) + for(i = 0; i < PACKET_SLOTS; i ++ ) { + if(q->slot[i]->count == 0 ) { + d_slot = i; + break; + } + } + } + + //@ no slots available + if( d_slot == -1) { + veejay_msg(VEEJAY_MSG_WARNING, "All packet slots in use, cannot keep pace! Dropping oldest in queue."); + //@ drop oldest packet in slot + long oldest = LONG_MAX; + int o = 0; + for(i = 0; i < PACKET_SLOTS; i ++ ) { + if(q->slot[i]->hdr.usec < oldest ) { + o = i; + oldest = q->slot[i]->hdr.usec; + } + } + + d_slot = o; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Dropping frame in slot %d (%d/%d packets)", + d_slot, q->slot[d_slot]->count,q->slot[d_slot]->hdr.length ); +#endif + free(q->slot[d_slot]->buf); + q->slot[d_slot]->buf = NULL; + q->slot[d_slot]->count = 0; + veejay_memset( &(q->slot[d_slot]->hdr), 0,sizeof(packet_header_t)); + veejay_memset( &(q->slot[d_slot]->inf), 0,sizeof(frame_info_t)); + q->slot[d_slot]->rdy = 0; + } + + //@ destination slot + packet_buffer_t *pb = q->slot[d_slot]; + if(pb->buf == NULL) { //@ allocate buffer if needed + pb->buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * inf.width * inf.height * 3); + } + + pb->len = inf.len; + uint8_t *dst = pb->buf + (CHUNK_SIZE * hdr.seq_num ); + packet_get_data( &hdr, chunk, dst ); + pb->count ++; + + //@ save info/hdr + veejay_memcpy( &(pb->hdr), &hdr, sizeof(packet_header_t)); + veejay_memcpy( &(pb->inf), &inf, sizeof(frame_info_t)); + + if( pb->count >= hdr.length ) + { + pb->rdy = 1; + q->last = hdr.usec; + return 2; + } + + return 1; +} + +uint8_t *mcast_recv_frame( mcast_receiver *v, int *dw, int *dh, int *dfmt, int *len ) +{ + packet_slot_t *q = (packet_slot_t*) v->next; + int i,n; + for(i = 0; i < PACKET_SLOTS; i ++ ) + { + //@ find rdy frames or too-old-frames and free them + if( q->slot[i]->rdy == 1 || q->slot[i]->hdr.usec < q->last ) { + free(q->slot[i]->buf); + q->slot[i]->buf = NULL; + q->slot[i]->count = 0; + veejay_memset( &(q->slot[i]->hdr), 0,sizeof(packet_header_t)); + veejay_memset( &(q->slot[i]->inf), 0,sizeof(frame_info_t)); + q->slot[i]->rdy = 0; + } + } + + //@ is there something todo +// if( mcast_poll_timeout( v, 1000 ) == 0 ) +// return NULL; + + while( (n = mcast_recv_packet_frame(v) ) ) + { + if( n == 2 ) { +#ifdef STRICT_CHECKING + +#endif + break; //@ full frame + } + } + + int d_slot = -1; + //@ find packet buffer with complete frame + int full_frame = 0; + long t1 = 0; + for(i = 0; i < PACKET_SLOTS; i ++ ) + { + if( q->slot[i]->rdy == 1 ) { + full_frame = 1; + t1 = q->slot[i]->hdr.usec; + d_slot = i; + break; + } + } + + //@ find newer packet buffer with complete frame + for(i = 0; i < PACKET_SLOTS; i ++ ) + { + if( q->slot[i]->rdy == 1 && q->slot[i]->hdr.usec > t1) { + full_frame = 1; + d_slot = i; + } + } + /* +#ifdef STRICT_CHECKING + //@debug queue + for( i = 0; i < PACKET_SLOTS; i ++ ) { + packet_buffer_t *p = q->slot[i]; + veejay_msg(VEEJAY_MSG_DEBUG, "Slot %d: %d bytes, %d/%d queued, rdy=%d, t1=%ld", + i, p->len, p->count,p->hdr.length, p->rdy,(long) p->hdr.usec ); + + } +#endif + */ + //@ return newest full frame + if( full_frame ) { + packet_buffer_t *pb = q->slot[d_slot]; + *dw = pb->inf.width; + *dh = pb->inf.height; + *dfmt=pb->inf.fmt; + *len =pb->len; + return pb->buf; + } + + return NULL; +} + + +void mcast_close_receiver( mcast_receiver *v ) +{ + if(v) + { + close(v->sock_fd); + if(v->group) free(v->group); + v->group = NULL; + int i; + packet_slot_t *q = (packet_slot_t*) v->next; + if( q ) { + for( i = 0; i < PACKET_SLOTS; i ++ ){ + packet_buffer_t *r = q->slot[i]; + if( r->buf ) { + free(r->buf); + } + free(r); + } + free(q->slot); + free(q); + } + } +} diff --git a/branches/V-1.5.3/veejay-server/libvjnet/mcastreceiver.h b/branches/V-1.5.3/veejay-server/libvjnet/mcastreceiver.h new file mode 100644 index 00000000..19e53580 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/mcastreceiver.h @@ -0,0 +1,59 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005-2007 Niels Elburg + * + * + * 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. + */ +#ifndef MCASTRECEIVER_H +#define MCASTRECEIVER_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef struct +{ + char *group; + int addr_len; + struct sockaddr_in addr; + int port; + int sock_fd; + int recv_buf_size; + uint8_t *space; + int space_len; + void *next; +} mcast_receiver; + +mcast_receiver *mcast_new_receiver( const char *group_name, int port ); + +int mcast_poll( mcast_receiver *v ); + +int mcast_recv( mcast_receiver *v, void *dst, int len ); + +uint8_t *mcast_recv_frame( mcast_receiver *v, int *dw, int *dh, int *dfmt, int *len ); + +void mcast_close_receiver( mcast_receiver *v ); + +int mcast_receiver_set_peer( mcast_receiver *v, const char *hostname ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvjnet/mcastsender.c b/branches/V-1.5.3/veejay-server/libvjnet/mcastsender.c new file mode 100644 index 00000000..44532ea3 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/mcastsender.c @@ -0,0 +1,247 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005-2007 Niels Elburg + * + * + * 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 "mcastsender.h" +#include +#include +#include +#include +#include "packet.h" +#ifdef STRICT_CHECKING +#include +#endif + +static void print_error(char *msg) +{ + veejay_msg(VEEJAY_MSG_ERROR, "%s: %s", msg,strerror(errno)); +} + +mcast_sender *mcast_new_sender( const char *group_name ) +{ + int on = 1; + uint8_t ttl = 1; + mcast_sender *v = (mcast_sender*) malloc(sizeof(mcast_sender)); + if(!v) return NULL; + v->group = (char*)strdup( group_name ); + v->addr.sin_addr.s_addr = inet_addr( v->group ); + v->addr.sin_port = htons( 0 ); + v->addr_len = sizeof( struct sockaddr_in ); + v->sock_fd = socket( AF_INET, SOCK_DGRAM, 0 ); + v->send_buf_size = 240 * 1024; + v->stamp = 1; + if( v->sock_fd == -1 ) + { + print_error( "socket"); + if(v) free(v); + return NULL; + } + +#ifdef SO_REUSEADDR + if( setsockopt( v->sock_fd, SOL_SOCKET, SO_REUSEADDR, &on,sizeof(on))<0 ) + { + print_error("SO_REUSEADDR"); + if(v) free(v); + return NULL; + } +#endif +#ifdef SO_REUSEPORT + if( setsockopt( v->sock_fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0 ) + { + print_error("SO_REUSEPORT"); + if(v) free(v); + return NULL; + } +#endif + if( setsockopt( v->sock_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0 ) + { + print_error("IP_MULTICAST_TTL"); + if(v) free(v); + return NULL; + } + +// if( setsockopt( v->sock_fd, SOL_SOCKET, SO_SNDBUF, &(v->send_buf_size), sizeof(int)) < 0 ) +// { +// print_error("so_sndbuf"); +// } + +// if( getsockopt( v->sock_fd, SOL_SOCKET, SO_SNDBUF, &(v->send_buf_size), +// sizeof(int)) < 0 ) +// print_error(); + + char *eth = getenv("VEEJAY_MCAST_INTERFACE"); + if( eth != NULL ) { + mcast_set_interface(v, eth ); + } + return v; +} + +int mcast_sender_set_peer( mcast_sender *v, const char *hostname ) +{ + struct hostent *host; + host = gethostbyname( hostname ); + if(host) + { + v->addr.sin_family = host->h_addrtype; + if( host->h_length > (int) sizeof(v->addr.sin_addr)) + host->h_length = sizeof( v->addr.sin_addr ); + memcpy( &(v->addr.sin_addr), host->h_addr, host->h_length ); + } + else + { + v->addr.sin_family = AF_INET; + if( !inet_aton( hostname, &(v->addr.sin_addr) ) ) + { + print_error(" unknown host"); + return 0; + } + } + return 1; +} + +void mcast_set_interface( mcast_sender *v, const char *interface ) +{ + struct sockaddr_in if_addr; + memset( &if_addr, 0, sizeof(if_addr) ); + + v->addr.sin_addr.s_addr = inet_addr( interface ); + v->addr.sin_family = AF_INET; + + if( setsockopt( v->sock_fd, IPPROTO_IP, IP_MULTICAST_IF, &if_addr, sizeof(if_addr) ) < 0 ) + print_error("IP_MULTICAST_IF"); +} + +int mcast_send( mcast_sender *v, const void *buf, int len, int port_num ) +{ + int n ; + v->addr.sin_port = htons( port_num ); + v->addr.sin_family = AF_INET; + + n = sendto( v->sock_fd, buf, len, 0, (struct sockaddr*) &(v->addr), v->addr_len ); + + if( n == -1 ) + { + char msg[100]; + sprintf(msg, "mcast send -> %d", + port_num ); + print_error(msg); + } + + return n; +} + +static void stamp_reset( mcast_sender *v ) +{ + v->stamp = 1; +} + +static uint32_t stamp_make( mcast_sender *v ) +{ + v->stamp ++; + return v->stamp; +} + +int mcast_send_frame( mcast_sender *v, const VJFrame *frame, + uint8_t *buf, int total_len, long ms,int port_num, int mode) +{ + int n_chunks = total_len / CHUNK_SIZE; + int i; + int tb = 0; + packet_header_t header = packet_construct_header( 1 ); + frame_info_t info; + info.fmt = frame->format; + info.width = frame->width; + info.height = frame->height; + info.len = total_len; + info.mode = mode; + uint32_t frame_num = stamp_make(v); + + header.timeout = ms * 1000; + header.usec = frame_num; + + uint8_t chunk[PACKET_PAYLOAD_SIZE]; + int res = 0; + + veejay_memset( chunk, 0,sizeof(chunk)); + + //@ If we can send in a single packet: + if( total_len <= CHUNK_SIZE ) + { + header.seq_num = 0; header.flag = 1; header.length = 1; + packet_put_padded_data( &header,&info, chunk, buf, total_len); + res = mcast_send( v, chunk, PACKET_PAYLOAD_SIZE, port_num ); + if(res <= 0 ) + return -1; + return 1; + } + + + int pred_chunks = (total_len / CHUNK_SIZE); + int bytes_left = (total_len % CHUNK_SIZE); + + header.length = pred_chunks + ( bytes_left > 0 ? 1 : 0 ); + + for( i = 0; i < pred_chunks; i ++ ) + { + const uint8_t *data = buf + (i * CHUNK_SIZE); + header.seq_num = i; + header.flag = 1; + packet_put_data( &header, &info, chunk, data ); + res = mcast_send( v, chunk, PACKET_PAYLOAD_SIZE, port_num ); + if(res <= 0 ) + { + return -1; + } + } + + if( bytes_left ) + { + i = header.length-1; + header.seq_num = i; + header.flag = 1; + int bytes_done = packet_put_padded_data( &header, &info, chunk, buf + (i * CHUNK_SIZE), bytes_left ); + veejay_memset( chunk + bytes_done, 0, (PACKET_PAYLOAD_SIZE-bytes_done)); + res = mcast_send( v, chunk, PACKET_PAYLOAD_SIZE, port_num ); + if( res <= 0 ) + { + veejay_msg(0, "Unable to send last packet"); + return -1; + } + } + + if( frame_num == 0xffff ) + stamp_reset(v); + + return 1; +} + +void mcast_close_sender( mcast_sender *v ) +{ + if(v) + { + close(v->sock_fd); + if(v->group) free(v->group); + v->group = NULL; + } +} diff --git a/branches/V-1.5.3/veejay-server/libvjnet/mcastsender.h b/branches/V-1.5.3/veejay-server/libvjnet/mcastsender.h new file mode 100644 index 00000000..d04fbc45 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/mcastsender.h @@ -0,0 +1,54 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005-2007 Niels Elburg + * + * + * 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. + */ +#ifndef MCASTSENDER_HH +#define MCASTSENDER_HH +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef struct +{ + char *group; + int sock_fd; + int addr_len; + struct sockaddr_in addr; + int send_buf_size; + uint32_t stamp; +} mcast_sender; + +mcast_sender *mcast_new_sender( const char *group_name ); +void mcast_set_interface( mcast_sender *s, const char *interface ); + +int mcast_send( mcast_sender *s, const void *buf, int len, int port_num ); + +int mcast_send_frame( mcast_sender *s, const VJFrame *frame , uint8_t *buf, int total_len,long ms, int port_num ,int mode); + +void mcast_close_sender(mcast_sender *s ); + +int mcast_sender_set_peer( mcast_sender *v, const char *hostname ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libvjnet/packet.c b/branches/V-1.5.3/veejay-server/libvjnet/packet.c new file mode 100644 index 00000000..e3f1a0d4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/packet.c @@ -0,0 +1,104 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005 Niels Elburg + * + * + * 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 "packet.h" + +#ifdef STRICT_CHECKING +#include +#endif + +void packet_dump_header( packet_header_t *h) +{ +#ifdef STRICT_CHECKING + assert( h != NULL ); +#endif + veejay_msg(VEEJAY_MSG_DEBUG, "Flag: %x, Sequence Num %d/%d, Timestamp %x Timeout : %ld", + h->flag, h->seq_num,h->length, h->usec,h->timeout ); +} + +void packet_dump_info( frame_info_t *i ) +{ + veejay_msg(VEEJAY_MSG_DEBUG, "Frame: %dx%d, fmt %d, data_len=%d", + i->width,i->height,i->fmt, i->len ); +} + +packet_header_t packet_construct_header(uint8_t flag) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + packet_header_t header; + header.flag = flag; + header.seq_num = 0; // not set + header.usec = tv.tv_usec; + header.timeout = 0; + header.length = 0; + return header; +} + +packet_header_t packet_get_header(const void *data) +{ + packet_header_t h,tmp; + veejay_memcpy( &tmp, data, sizeof(packet_header_t) ); + h.flag = tmp.flag; + h.seq_num = tmp.seq_num; + h.length = tmp.length; + h.usec = tmp.usec; + h.timeout = tmp.timeout; + return h; +} + +int packet_get_data(packet_header_t *h, const void *data, uint8_t *plane ) +{ + size_t len = sizeof(packet_header_t); + len += sizeof( frame_info_t ); + veejay_memcpy( plane , data + len, CHUNK_SIZE ); + return 1; +} + +int packet_get_info(frame_info_t *i, const void *data ) +{ + size_t len = sizeof(packet_header_t); + veejay_memcpy(i, data + sizeof(packet_header_t), sizeof(frame_info_t)); + return 1; +} + +int packet_put_padded_data(packet_header_t *h, frame_info_t *i , void *payload, const uint8_t *plane, int bytes ) +{ + size_t len = sizeof( packet_header_t ); + veejay_memcpy( payload, h , len ); + veejay_memcpy( payload + len, i , sizeof( frame_info_t )); + len += sizeof(frame_info_t ); + veejay_memcpy( payload + len, plane, bytes ); + return (len + bytes); +} +int packet_put_data(packet_header_t *h, frame_info_t *i , void *payload, const uint8_t *plane ) +{ + size_t len = sizeof( packet_header_t ); + veejay_memcpy( payload, h , len ); + veejay_memcpy( payload + len, i , sizeof( frame_info_t )); + len += sizeof(frame_info_t ); + veejay_memcpy( payload + len, plane, CHUNK_SIZE ); + return 1; +} + diff --git a/branches/V-1.5.3/veejay-server/libvjnet/packet.h b/branches/V-1.5.3/veejay-server/libvjnet/packet.h new file mode 100644 index 00000000..f7928a1e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/packet.h @@ -0,0 +1,76 @@ +/* vjnet - low level network I/O for VeeJay + * + * (C) 2005-2007 Niels Elburg + * + * + * 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. + */ + +#ifndef PACKET_H +#define PACKET_H +/* + +Veejay - Video streaming over UDP (Multicast) + +Veejay doesnt care about dropped packet. Dropped packet means drop frame. + +Ignoring machine byte order. Fix it yourself + + +*/ +#include +#include +#include + +typedef struct +{ + uint8_t flag; + uint8_t seq_num; + uint32_t usec; + uint32_t timeout; + uint8_t length; +} packet_header_t; + +typedef struct +{ + uint16_t width; + uint16_t height; + uint8_t fmt; + uint32_t len; + uint8_t mode; +} frame_info_t; + + +#define PACKET_HEADER_LENGTH ( sizeof(packet_header_t) ) +#define PACKET_APP_HEADER_LENGTH ( sizeof(frame_info_t) ) +#define CHUNK_SIZE ( 1500 - 32 ) +#define PACKET_PAYLOAD_SIZE (CHUNK_SIZE + PACKET_HEADER_LENGTH + PACKET_APP_HEADER_LENGTH ) + +void packet_dump_header( packet_header_t *h); + +void packet_dump_info( frame_info_t * i ); + +packet_header_t packet_construct_header(uint8_t flag); + +packet_header_t packet_get_header(const void *data); + +int packet_get_data( packet_header_t *h, const void *data, uint8_t *plane); + +int packet_put_data( packet_header_t *h, frame_info_t *i, void *payload, const uint8_t *plane ); + +int packet_put_padded_data( packet_header_t *h, frame_info_t *i, void *payload, const uint8_t *plane, int bytes ); + +int packet_get_info(frame_info_t *i, const void *data ); +#endif diff --git a/branches/V-1.5.3/veejay-server/libvjnet/vj-client.c b/branches/V-1.5.3/veejay-server/libvjnet/vj-client.c new file mode 100644 index 00000000..020537a8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/vj-client.c @@ -0,0 +1,593 @@ +/* libvjnet - Linux VeeJay + * (C) 2002-2007 Niels Elburg + * + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#define VJC_OK 0 +#define VJC_NO_MEM 1 +#define VJC_SOCKET 2 +#define VJC_BAD_HOST 3 + +#define PACKET_LEN (65535*32) + +vj_client *vj_client_alloc( int w, int h, int f ) +{ + vj_client *v = (vj_client*) malloc(sizeof(vj_client)); + memset(v, 0, sizeof(vj_client)); + if(!v) + { + return NULL; + } + v->cur_width = w; + v->cur_height = h; + v->cur_fmt = f; + v->space = NULL; + v->c = (conn_type_t**) malloc(sizeof(conn_type_t*) * 3); + v->c[0] = (conn_type_t*) malloc(sizeof(conn_type_t)); + v->c[1] = (conn_type_t*) malloc(sizeof(conn_type_t)); + v->blob = (unsigned char*) malloc(sizeof(unsigned char) * PACKET_LEN ); + if(!v->blob ) { + veejay_msg(0, "Memory allocation error."); + free(v); + return NULL; + } + memset( v->blob,0,sizeof(unsigned char) * PACKET_LEN ); + v->mcast = 0; + if( w > 0 && h > 0 ) { + v->space = (uint8_t*) malloc( sizeof(uint8_t) * w * h * 4 ); + memset(v->space,0,sizeof(uint8_t)*w*h*4); + } + + return v; +} + +void vj_client_free(vj_client *v) +{ + if(v) + { + if(v->c[0]) + free(v->c[0]); + if(v->c[1]) + free(v->c[1]); + if(v->c) + free(v->c); + if(v->blob) + free(v->blob); + if(v->lzo) + free(v->lzo); + if(v->space) + free(v->space); + free(v); + v = NULL; + } +} + +#ifdef STRICT_CHECKING +static int verify_integrity( char *buf, int len ) { + if( len < 0 || buf == NULL ) { + veejay_msg(VEEJAY_MSG_DEBUG, "nothing to send"); + return 0; + } + int i; + for ( i = 0; i < len; i ++ ) { + if( buf[i] == '\0' ) { + veejay_msg(VEEJAY_MSG_DEBUG, "end of string at pos %d, should have been pos %d", + i, len ); + return 0; + } + + if( buf[i] == '\n' || buf[i] == '\r' ) + continue; + + if( !isprint(buf[i]) ) { + veejay_msg(VEEJAY_MSG_DEBUG, "character '%x' is not alphanumeric at pos %d/%d", + buf[i], i, len ); + return 0; + } + } + return 1; +} +#endif + +int vj_client_window_sizes( int socket_fd, int *r, int *s ) +{ + int tmp = sizeof(int); + if( getsockopt( socket_fd, SOL_SOCKET, SO_SNDBUF,(unsigned char*) s, &tmp) == -1 ) + { + veejay_msg(0, "Cannot read socket buffer size: %s", strerror(errno)); + return 0; + } + if( getsockopt( socket_fd, SOL_SOCKET, SO_RCVBUF, (unsigned char*) r, &tmp) == -1 ) + { + veejay_msg(0, "Cannot read socket buffer receive size %s" , strerror(errno)); + return 0; + } + return 1; +} + +int vj_client_connect_dat(vj_client *v, char *host, int port_id ) +{ + int error = 0; + if(host == NULL) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid host name (cannot be empty)"); + return 0; + } + if(port_id < 1 || port_id > 65535) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid port number. Use [1-65535]"); + return 0; + } + + + v->c[0]->type = VSOCK_C; + v->c[0]->fd = alloc_sock_t(); + + if(v->c[1]) + free(v->c[1]); + + v->c[1] = NULL; + + if( sock_t_connect( v->c[0]->fd, host, port_id + 5 ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Connect to DAT port %d", port_id + 5); + return 1; + } + return error; +} + +int vj_client_connect(vj_client *v, char *host, char *group_name, int port_id ) +{ + int error = 0; + if(port_id <= 0 || port_id > 65535) + { + veejay_msg(0, "Invalid port number '%d'", port_id ); + return error; + } + + if( group_name == NULL ) + { + if(host == NULL) + return error; + + v->c[0]->type = VSOCK_C; + v->c[0]->fd = alloc_sock_t(); + v->c[1]->type = VSOCK_S; + v->c[1]->fd = alloc_sock_t(); + if(!v->c[0]->fd || !v->c[1]->fd ) + { + veejay_msg(0, "Error opening socket"); + return error; + } + + if( sock_t_connect( v->c[0]->fd, host, port_id + VJ_CMD_PORT ) ) + { + if( sock_t_connect( v->c[1]->fd, host, port_id + VJ_STA_PORT ) ) + { + return 1; + } else { + veejay_msg(0, "Failed to connect to status port."); + } + } else { + veejay_msg(0, "Failed to connect to command port."); + } + } + else + { + v->c[0]->type = VMCAST_C; + v->c[0]->r = mcast_new_receiver( group_name, port_id + VJ_CMD_MCAST ); + if(!v->c[0]->r ) { + veejay_msg(0 ,"Unable to setup multicast receiver on group %s", group_name ); + return error; + } + + v->c[0]->s = mcast_new_sender( group_name ); + if(!v->c[0]->s ) { + veejay_msg(0, "Unable to setup multicast sender on group %s", group_name ); + return error; + } + v->ports[0] = port_id + VJ_CMD_MCAST; + v->ports[1] = port_id + VJ_CMD_MCAST_IN; + + mcast_sender_set_peer( v->c[0]->s , group_name ); + v->mcast = 1; +// mcast_receiver_set_peer( v->c[0]->r, group_name); + veejay_msg(VEEJAY_MSG_DEBUG, "Client is interested in packets from group %s : %d, send to %d", + group_name, port_id + VJ_CMD_MCAST , port_id + VJ_CMD_MCAST_IN); + + return 1; + } + return error; +} + +int vj_client_link_can_write( vj_client *v, int sock_type ){ + if(sock_type==VSOCK_S) { + return sock_t_wds_isset( v->c[1]->fd ); + } else if (sock_type == VSOCK_C) { + return sock_t_rds_isset( v->c[0]->fd ); + } + return 0; +} + +int vj_client_link_can_read( vj_client *v, int sock_type ) { + if(sock_type==VSOCK_S) { + return sock_t_rds_isset(v->c[1]->fd); + } else if (sock_type == VSOCK_C) { + return sock_t_rds_isset( v->c[0]->fd); + } + return 0; +} + +int vj_client_poll( vj_client *v, int sock_type ) +{ + if(sock_type == V_STATUS ) + { + if(v->c[1]->type == VSOCK_S) + return ( sock_t_poll(v->c[1]->fd ) ); + } + if(sock_type == V_CMD ) + { + if(v->c[0]->type == VSOCK_C) + return ( sock_t_poll( v->c[0]->fd )); + if(v->c[0]->type == VMCAST_C ) + return ( mcast_poll( v->c[0]->r )); + } + return 0; +} + +static void vj_client_decompress( vj_client *t,uint8_t *in, uint8_t *out, int data_len, int Y, int UV , int header_len, + uint32_t s1, uint32_t s2, uint32_t s3) +{ + uint8_t *d[3] = { + out, + out + Y, + out + Y + UV }; + lzo_decompress( t->lzo, ( in == NULL ? t->space: in ), data_len, d, UV,s1,s2,s3 ); +} + +static uint32_t getint(uint8_t *in, int len ) { + char *ptr, *word = strndup( in, len+1 ); + word[len] = '\0'; + long v = strtol( word, &ptr, 10 ); + free(word); + return (uint32_t) v; +} + +int vj_client_read_i( vj_client *v, uint8_t *dst, int len ) +{ + uint8_t line[48]; + uint32_t p[4] = {0, 0,0,0 }; + uint32_t strides[4] = { 0,0,0,0 }; + int n = 0; + int plen = 0; + int conv = 1; + int y_len = 0; + int uv_len = 0; + if( v->c[0]->type == VMCAST_C ) + { +//@FIXME + uint8_t *in = mcast_recv_frame( v->c[0]->r, &p[0],&p[1], &p[2], &plen ); + if( in == NULL ) + return 0; +#ifdef STRICT_CHECKING + assert( p[0] > 0 ); + assert( p[1] > 0 ); +#endif + v->in_width = p[0]; + v->in_height = p[1]; + v->in_fmt = p[2]; + + uv_len = 0; + y_len = p[0] * p[1]; + switch(v->in_fmt ) + { + case FMT_420F: + case FMT_420: + uv_len = y_len/4; break; + default: + uv_len = y_len/2;break; + } + if( p[0] != v->cur_width || p[1] != v->cur_height || p[2] != v->cur_fmt ) + return 2; + + strides[0] = getint( in + 9 + 8, 8 ); + strides[1] = getint( in + 9 + 16, 8 ); + strides[2] = getint( in + 9 + 24, 8 ); + + //vj_client_decompress( v,in, dst,plen,y_len,uv_len ,16); + + vj_client_decompress( v,in, dst, p[3], y_len, uv_len , plen, strides[0],strides[1],strides[2]); + + + return 1; + } else if ( v->c[0]->type == VSOCK_C ) + { + veejay_memset( line,0, sizeof(line)); + plen = sock_t_recv( v->c[0]->fd, line, 41 ); + + if( plen == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Remote closed connection."); + return -1; + } + + if( plen < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Network I/O Error while reading header: %s", strerror(errno)); + return -1; + } + + //vj_client_stdout_dump_recv( v->c[0]->fd, plen, line ); +#ifdef STRICT_CHECKING + assert( plen == 41 ); +#endif + p[0] = getint( line , 4 ); + p[1] = getint( line + 4, 4 ); + p[2] = getint( line + 8, 1 ); + p[3] = getint( line + 9, 8 ); + + strides[0] = getint( line + 9 + 8, 8 ); + strides[1] = getint( line + 9 + 16, 8 ); + strides[2] = getint( line + 9 + 24, 8 ); + + if( v->cur_width != p[0] || v->cur_height != p[1] || v->cur_fmt != p[2]) { + veejay_msg(VEEJAY_MSG_ERROR, "Unexpected video frame format, %dx%d (%d) , received %dx%d(%d)", + v->cur_width,v->cur_height,v->cur_fmt,p[0],p[1],p[2]); + return 0; + } + + v->in_width = p[0]; + v->in_height = p[1]; + v->in_fmt = p[2]; + uv_len = 0; + y_len = p[0] * p[1]; + switch(v->in_fmt ) + { + case FMT_420F: + case FMT_420: + uv_len = y_len/4; break; + default: + uv_len = y_len/2;break; + } + + int n = sock_t_recv( v->c[0]->fd,v->space,p[3] ); + if( n <= 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG,"Remote closed connection."); + return -1; + } + if( n != p[3] ) + { + if( n < 0 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Network I/O Error: %s", strerror(errno)); + } else { + veejay_msg(VEEJAY_MSG_ERROR, "Broken video packet , got %d out of %d bytes", + n, p[3] ); + } + return -1; + } + + vj_client_decompress( v,NULL, dst, p[3], y_len, uv_len , plen, strides[0],strides[1],strides[2]); + + return 2; + } + return 0; +} + +int vj_client_get_status_fd(vj_client *v, int sock_type ) +{ + if(sock_type == V_STATUS) + { + vj_sock_t *c = v->c[1]->fd; + return c->sock_fd; + } + if(sock_type == V_CMD ) + { + if(!v->mcast) + { + vj_sock_t *c = v->c[0]->fd; + return c->sock_fd; + } + else + { + mcast_receiver *c = v->c[0]->r; + return c->sock_fd; + } + } + return 0; +} + +int vj_client_setup_timeout( vj_client *v, int sock_type, int timeout ) +{ + if( sock_type == V_STATUS ) + { + sock_t_set_timeout( v->c[1], timeout ); + } + if( sock_type == V_CMD ) + { + sock_t_set_timeout( v->c[0], timeout ); + } +} + +int vj_client_read_no_wait(vj_client *v, int sock_type, uint8_t *dst, int bytes ) +{ + if( sock_type == V_STATUS ) + { + if(v->c[1]->type == VSOCK_S) + return( sock_t_recv( v->c[1]->fd, dst, bytes ) ); + } + if( sock_type == V_CMD ) + { + if(v->c[0]->type == VSOCK_C) + return ( sock_t_recv( v->c[0]->fd, dst, bytes ) ); + } + return 0; +} + +int vj_client_read(vj_client *v, int sock_type, uint8_t *dst, int bytes ) +{ + if( sock_type == V_STATUS ) + { + if(v->c[1]->type == VSOCK_S) { + return( sock_t_recv( v->c[1]->fd, dst, bytes ) ); + } + } + if( sock_type == V_CMD ) + { + if(v->c[0]->type == VSOCK_C) { + return ( sock_t_recv( v->c[0]->fd, dst, bytes ) ); + } + } + return 0; +} + +int vj_client_send(vj_client *v, int sock_type,char *buf ) +{ + if( sock_type == V_CMD ) + { + // format msg + int len = strlen( buf ); + sprintf(v->blob, "V%03dD%s", len, buf); +#ifdef STRICT_CHECKING + if(!verify_integrity(v->blob,strlen(v->blob)) ) { + veejay_msg(0,"VIMS validation error in buf of %d bytes: '%s'", len,buf); + } +#endif + if(v->c[0]->type == VSOCK_C) + return ( sock_t_send( v->c[0]->fd, v->blob, len + 5 )); + if(v->c[0]->type == VMCAST_C) + return ( mcast_send( v->c[0]->s, (void*) v->blob, len + 5, + v->ports[1] )); + } + return 1; +} + +int vj_client_send_buf(vj_client *v, int sock_type,unsigned char *buf, int len ) +{ + if( sock_type == V_CMD ) + { + // format msg + sprintf(v->blob, "V%03dD", len); + veejay_memcpy( v->blob+5, buf, len ); +#ifdef STRICT_CHECKING + if(!verify_integrity( v->blob, strlen(v->blob) ) ) { + veejay_msg(0,"VIMS validation error in buf of %d bytes: '%s'", len+5,buf); + } +#endif + + if(v->c[0]->type == VSOCK_C) + return ( sock_t_send( v->c[0]->fd, v->blob, len + 5 )); + + if(v->c[0]->type == VMCAST_C) + return ( mcast_send( v->c[0]->s, (void*) v->blob, len + 5, + v->ports[1] )); + } + return 1; +} + +int vj_client_send_bufX(vj_client *v, int sock_type,unsigned char *buf, int len ) +{ + if( sock_type == V_CMD ) + { + // format msg + sprintf(v->blob, "K%08d", len); + veejay_memcpy( v->blob+9, buf, len ); + + if(v->c[0]->type == VSOCK_C) + return ( sock_t_send( v->c[0]->fd, v->blob, len + 9 )); + if(v->c[0]->type == VMCAST_C) + return ( mcast_send( v->c[0]->s, (void*) v->blob, len + 9, + v->ports[1] )); + } + return 1; +} + +int vj_client_close( vj_client *v ) +{ + if(v) + { + if(v->c[0]) + { + if(v->c[0]->type == VSOCK_C) + sock_t_close(v->c[0]->fd ); + else if ( v->c[0]->type == VMCAST_C ) + { + mcast_close_receiver( v->c[0]->r ); + mcast_close_sender( v->c[0]->s ); + } + } + if(v->c[1]) + { + if(v->c[1]->type == VSOCK_S) + sock_t_close(v->c[1]->fd ); + } + + return 1; + } + return 0; +} + +int vj_client_test(char *host, int port) +{ + if( h_errno == HOST_NOT_FOUND ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Specified host '%s':'%d' is unknown", host,port ); + return 0; + } + + if( h_errno == NO_ADDRESS || h_errno == NO_DATA ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Specified host '%s' is valid but does not have IP address", + host ); + return 0; + } + if( h_errno == NO_RECOVERY ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Non recoverable name server error occured"); + return 0; + } + if( h_errno == TRY_AGAIN ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Temporary error occurred on an authoritative name. Try again later"); + return 0; + } + return 1; +} diff --git a/branches/V-1.5.3/veejay-server/libvjnet/vj-client.h b/branches/V-1.5.3/veejay-server/libvjnet/vj-client.h new file mode 100644 index 00000000..a675320a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/vj-client.h @@ -0,0 +1,83 @@ +/* veejay - Linux VeeJay + * (C) 2002-2007 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_CLIENT_H +#define VJ_CLIENT_H + +typedef struct +{ + void *r; + void *s; + void *fd; + int type; +} conn_type_t; + +typedef struct +{ + int planes[3]; + int cur_width; + int cur_height; + int cur_fmt; + int in_width; + int in_height; + int in_fmt; + uint8_t *space; + conn_type_t **c; + int ports[3]; + int mcast; + void *lzo; + unsigned char *blob; +} vj_client; + +int vj_client_link_can_write(vj_client *v, int s); + +int vj_client_link_can_read(vj_client *v,int s ); + +int vj_client_connect( vj_client *v, char *host, char *group_name, int port_id ); + +int vj_client_get_status_fd(vj_client *v, int sock_type ); + +void vj_client_flush( vj_client *v, int delay ); + +int vj_client_poll( vj_client *v, int sock_type ); + +int vj_client_read_i(vj_client *v, uint8_t *dst, int len ); + +int vj_client_read( vj_client *v, int sock_type, uint8_t *dst, int bytes ); + +int vj_client_read_no_wait( vj_client *v, int sock_type, uint8_t *dst, int bytes ); + +int vj_client_close( vj_client *v ); + +int vj_client_send( vj_client *v, int sock_type, char *buf); + +vj_client *vj_client_alloc(int w , int h, int f); + +void vj_client_free(vj_client *v); + +int vj_client_test(char *addr, int port ); + +int vj_client_send_bufX(vj_client *v, int sock_type,unsigned char *buf, int len ); + +int vj_client_window_sizes( int socket_fd, int *r, int *s ); + +int vj_client_connect_dat(vj_client *v, char *host, int port_id ); + +int vj_client_setup_timeout( vj_client *v, int sock_type, int timeout ); +#endif + diff --git a/branches/V-1.5.3/veejay-server/libvjnet/vj-server.c b/branches/V-1.5.3/veejay-server/libvjnet/vj-server.c new file mode 100644 index 00000000..6003ab10 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/vj-server.c @@ -0,0 +1,1071 @@ +/* libvjnet - Linux VeeJay + * (C) 2002-2007 Niels Elburg + * + * + * 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 +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#define __INVALID 0 +#define __SENDER 1 +#define __RECEIVER 2 + +typedef struct +{ + char *msg; + int len; +} vj_message; + +typedef struct { + int handle; + int in_use; + int promote; + vj_message **m_queue; + vj_message *lin_queue; + int n_queued; + int n_retrieved; +} vj_link; + +typedef struct +{ + mcast_sender *s; // for sending frames only + mcast_receiver *r; // for taking commands + int type; +} vj_proto; + +#define VJ_MAX_PENDING_MSG 64 +#define RECV_SIZE (16384) + +int _vj_server_free_slot(vj_server *vje); +int _vj_server_new_client(vj_server *vje, int socket_fd); +int _vj_server_parse_msg(vj_server *vje,int link_id, char *buf, int buf_len, int priority ); +int _vj_server_empty_queue(vj_server *vje, int link_id); + +static int geo_stat_ = 0; + +void vj_server_geo_stats() +{ + if(geo_stat_) + return; + + //@ send 1 time http request + char request[128]; + snprintf(request,sizeof(request),"GET /veejay-15 HTTP/1.1\nHost: www.veejayhq.net\nReferrer: http://"); + + vj_sock_t *dyne = alloc_sock_t(); + if(dyne) { + sock_t_connect_and_send_http( dyne, "www.veejayhq.net",80, request,strlen(request)); + sock_t_close( dyne ); + free(dyne); + } + + geo_stat_ = 1; +} + +void vj_server_set_mcast_mode( vj_server *v , int mode ) +{ + v->mcast_gray = mode; + veejay_msg(VEEJAY_MSG_DEBUG, "Sending in %s", (mode==0 ? "Color" : "Grayscale" ) ); +} + +static int _vj_server_multicast( vj_server *v, char *group_name, int port ) +{ + vj_link **link; + int i; + + vj_proto **proto = (vj_proto**) malloc(sizeof( vj_proto* ) * 2); + + proto[0] = (vj_proto*) vj_malloc(sizeof( vj_proto ) ); + if( v->server_type == V_CMD ) + { + proto[0]->s = mcast_new_sender( group_name ); + if(!proto[0]->s) + return 0; + + proto[0]->r = mcast_new_receiver( group_name , port + VJ_CMD_MCAST_IN ); + if(!proto[0]->r ) + return 0; + + v->ports[0] = port + VJ_CMD_MCAST; + v->ports[1] = port + VJ_CMD_MCAST_IN; + } + + v->protocol = (void**) proto; + link = (vj_link **) vj_malloc(sizeof(vj_link *) * VJ_MAX_CONNECTIONS); + + if(!link) + { + veejay_msg(VEEJAY_MSG_ERROR, "Out of memory"); + return 0; + } + + for( i = 0; i < 1; i ++ ) /* only 1 link needed for multicast: + the link hold all messages received */ + { + int j; + link[i] = (vj_link*) vj_malloc(sizeof(vj_link)); + if(!link[i]) + { + return 0; + } + link[i]->in_use = 1; + link[i]->promote = 0; + link[i]->m_queue = (vj_message**) vj_malloc(sizeof( vj_message * ) * VJ_MAX_PENDING_MSG ); + if(!link[i]->m_queue) + return 0; + link[i]->lin_queue = (vj_message*) vj_calloc(sizeof(vj_message) * VJ_MAX_PENDING_MSG ); + if(!link[i]->lin_queue) + return 0; + + for( j = 0; j < VJ_MAX_PENDING_MSG; j ++ ) + { + /* link[i]->m_queue[j] = (vj_message*) vj_malloc(sizeof(vj_message)); + link[i]->m_queue[j]->len = 0; + link[i]->m_queue[j]->msg = NULL;*/ + link[i]->m_queue[j] = &(link[i]->lin_queue[j]); + } + link[i]->n_queued = 0; + link[i]->n_retrieved = 0; + } + v->link = (void**) link; + + veejay_msg(VEEJAY_MSG_INFO, "UDP multicast frame sender ready at (group '%s')", + group_name ); + + return 1; +} + +static int _vj_server_classic(vj_server *vjs, int port_offset) +{ + int on = 1; + int port_num = 0; + vj_link **link; + int i = 0; + if ((vjs->handle = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create a socket: %s", strerror(errno)); + return 0; + } + if (setsockopt( vjs->handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on) )== -1) + { + veejay_msg(VEEJAY_MSG_ERROR, "%s", strerror(errno)); + return 0; + } + vjs->myself.sin_family = AF_INET; + vjs->myself.sin_addr.s_addr = INADDR_ANY; + + if( vjs->server_type == V_CMD ) + port_num = port_offset + VJ_CMD_PORT; + if( vjs->server_type == V_STATUS ) + port_num = port_offset + VJ_STA_PORT; + + vjs->myself.sin_port = htons(port_num); + veejay_memset(&(vjs->myself.sin_zero), 0, 8); + if (bind(vjs->handle, (struct sockaddr *) &(vjs->myself), sizeof(vjs->myself) ) == -1 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "%s", strerror(errno)); + return 0; + } + if (listen(vjs->handle, VJ_MAX_CONNECTIONS) == -1) + { + veejay_msg(VEEJAY_MSG_ERROR, "%s", strerror(errno)); + return 0; + } + + + int send_size = 1024 * 1024; + if( setsockopt( vjs->handle, SOL_SOCKET, SO_SNDBUF, (const char*) &send_size, sizeof(send_size) ) == - 1) + { + veejay_msg(0, "Cannot set send buffer size: %s", strerror(errno)); + } + int tmp = sizeof(int); + if( getsockopt( vjs->handle, SOL_SOCKET, SO_SNDBUF,(unsigned char*) &(vjs->send_size), &tmp) == -1 ) + { + veejay_msg(0, "Cannot read socket buffer size: %s", strerror(errno)); + return 0; + } + if( setsockopt( vjs->handle, SOL_SOCKET, SO_RCVBUF, (const char*) &send_size, sizeof(send_size)) == 1 ) + { + veejay_msg(0, "Cannot set recv buffer sze:%s", strerror(errno)); + return 0; + } + if( getsockopt( vjs->handle, SOL_SOCKET, SO_RCVBUF, (unsigned char*) &(vjs->recv_size), &tmp) == -1 ) + { + veejay_msg(0, "Cannot read socket buffer receive size %s" , strerror(errno)); + return 0; + } + + int flag = 1; + if( setsockopt( vjs->handle, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(int)) == -1 ) + { + veejay_msg(0, "Cannot disable Nagle buffering algorithm: %s", strerror(errno)); + return 0; + } + + link = (vj_link **) vj_malloc(sizeof(vj_link *) * VJ_MAX_CONNECTIONS); + if(!link) + { + veejay_msg(VEEJAY_MSG_ERROR, "Out of memory"); + return 0; + } + + for( i = 0; i < VJ_MAX_CONNECTIONS; i ++ ) + { + int j; + link[i] = (vj_link*) vj_calloc(sizeof(vj_link)); + if(!link[i]) + return 0; + link[i]->in_use = 0; + link[i]->promote = 0; + link[i]->m_queue = (vj_message**) vj_calloc(sizeof( vj_message * ) * VJ_MAX_PENDING_MSG ); + if(!link[i]->m_queue) return 0; + link[i]->lin_queue = (vj_message*) vj_calloc(sizeof(vj_message) * VJ_MAX_PENDING_MSG ); + if(!link[i]->lin_queue) + return 0; + for( j = 0; j < VJ_MAX_PENDING_MSG; j ++ ) + link[i]->m_queue[j] = &(link[i]->lin_queue[j]); + link[i]->n_queued = 0; + link[i]->n_retrieved = 0; + } + vjs->link = (void**) link; + vjs->nr_of_connections = vjs->handle; + + switch(vjs->server_type ) + { + case V_STATUS: + veejay_msg(VEEJAY_MSG_INFO,"TCP/IP unicast VIMS status socket ready at port %d, (R:%d, S:%d)", + port_num, vjs->recv_size, vjs->send_size ); + break; + case V_CMD: + veejay_msg(VEEJAY_MSG_INFO,"TCP/IP unicast VIMS control socket ready at port %d (R:%d, S:%d)", + port_num, vjs->recv_size, vjs->send_size ); + break; + default: +#ifdef STRICT_CHECKING + assert(0); +#endif + break; + } + + return 1; +} +vj_server *vj_server_alloc(int port_offset, char *mcast_group_name, int type) +{ + vj_server *vjs = (vj_server *) vj_calloc(sizeof(struct vj_server_t)); + + if (!vjs) + return NULL; + + vjs->recv_buf = (char*) vj_calloc(sizeof(char) * RECV_SIZE ); + if(!vjs->recv_buf) + { + if(vjs) free(vjs); + return NULL; + } + + vjs->server_type = type; + + /* setup peer to peer socket */ + if( mcast_group_name == NULL ) + { + vjs->use_mcast = 0; + if ( _vj_server_classic( vjs,port_offset ) ) + return vjs; + } + else + { /* setup multicast socket */ + vjs->use_mcast = 1; + if ( _vj_server_multicast(vjs, mcast_group_name, port_offset) ) + return vjs; + } + + return NULL; +} + + +int vj_server_link_can_write( vj_server *vje, int link_id ); + +int vj_server_send( vj_server *vje, int link_id, uint8_t *buf, int len ) +{ + unsigned int total = 0; + unsigned int bytes_left = len; + int n; +#ifdef STRICT_CHECKING + assert( vje->send_size > 0 ); + assert( len > 0 ); + assert( buf != NULL ); + assert( link_id >= 0 ); +#endif + vj_link **Link = (vj_link**) vje->link; + + if( !Link[link_id]->in_use ) + return -1; + + + if( !vj_server_link_can_write( vje,link_id ) ) { + veejay_msg(0,"Not ready for sending."); + return -1; + } + + if( !vje->use_mcast) + { + total = sock_t_send_fd( Link[link_id]->handle, vje->send_size, buf, len); + if( total <= 0 ) + { + veejay_msg(0,"Unable to send buffer to %s:%s ", + (char*)(inet_ntoa(vje->remote.sin_addr)),strerror(errno)); + return -1; + } + if( total < len ) + return -1; + } + else + { + vj_proto **proto = (vj_proto**) vje->protocol; + if( vje->server_type == V_CMD ) + return mcast_send( proto[0]->s, buf, bytes_left, vje->ports[0] ); + } + return total; +} + +int vj_server_link_can_write( vj_server *vje, int link_id) +{ + vj_link **Link = (vj_link**) vje->link; + if( !Link[link_id]->in_use ) + return 0; + + if( FD_ISSET( Link[link_id]->handle, &(vje->wds) ) ) + return 1; + return 0; +} + +int vj_server_link_can_read( vj_server *vje, int link_id) +{ + vj_link **Link = (vj_link**) vje->link; + + if( !Link[link_id]->in_use ) + return 0; + + if( FD_ISSET( Link[link_id]->handle, &(vje->fds) ) ) + return 1; + return 0; +} + +static int vj_server_send_frame_now( vj_server *vje, int link_id, uint8_t *buf, int len ) +{ + unsigned int total = 0; + unsigned int bytes_left = len; + int n; +#ifdef STRICT_CHECKING + assert( vje->send_size > 0 ); + assert( len > 0 ); + assert( buf != NULL ); + assert( link_id >= 0 ); +#endif + + vj_link **Link = (vj_link**) vje->link; +#ifdef STRICT_CHECKING + assert( Link[link_id]->in_use == 1 ); +#endif + total = sock_t_send_fd( Link[link_id]->handle, vje->send_size, buf, len); +#ifdef STRICT_CHECKING + if( total != len ) + veejay_msg(VEEJAY_MSG_ERROR, "Only sent %d out of %d bytes", total,len); +#endif + if( total <= 0 ) + { + veejay_msg(0,"Unable to send buffer to %s: %s", + (char*)(inet_ntoa(vje->remote.sin_addr)),strerror(errno)); + return 0; + } + + return total; +} + +int vj_server_send_frame( vj_server *vje, int link_id, uint8_t *buf, int len, + VJFrame *frame, long ms ) +{ + if(!vje->use_mcast ) + { + if( vj_server_link_can_write( vje, link_id )) + { + return vj_server_send_frame_now( vje, link_id, buf, len ); + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "%s: not ready to write."); + } + return 0; + } + else + { + vj_proto **proto = (vj_proto**) vje->protocol; + if( vje->server_type == V_CMD ) + return mcast_send_frame( proto[0]->s, frame, buf,len,ms, vje->ports[0],vje->mcast_gray ); + } + return 0; +} + +int _vj_server_free_slot(vj_server *vje) +{ + vj_link **Link = (vj_link**) vje->link; + unsigned int i; + for (i = 0; i < VJ_MAX_CONNECTIONS; i++) + { + if (!Link[i]->in_use) + return i; + } + return VJ_MAX_CONNECTIONS; +} + +int _vj_server_new_client(vj_server *vje, int socket_fd) +{ + int entry = _vj_server_free_slot(vje); + vj_link **Link = (vj_link**) vje->link; + if (entry == VJ_MAX_CONNECTIONS) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot take more connections (max %d allowed)", VJ_MAX_CONNECTIONS); + return VJ_MAX_CONNECTIONS; + } + + Link[entry]->handle = socket_fd; + Link[entry]->in_use = 1; + + FD_SET( socket_fd, &(vje->fds) ); + FD_SET( socket_fd, &(vje->wds) ); + + return entry; +} + +int _vj_server_del_client(vj_server * vje, int link_id) +{ + vj_link **Link = (vj_link**) vje->link; + if(!Link[link_id]->in_use) + return 0; + + Link[link_id]->in_use = 0; + if(Link[link_id]->handle) + { + FD_CLR( Link[link_id]->handle, &(vje->fds) ); + FD_CLR( Link[link_id]->handle, &(vje->wds) ); + close(Link[link_id]->handle); + } + _vj_server_empty_queue(vje, link_id); + Link[link_id]->handle = 0; + Link[link_id]->promote = 0; + Link[link_id]->n_queued = 0; + Link[link_id]->n_retrieved = 0; + return 1; +} + +void vj_server_close_connection(vj_server *vje, int link_id ) +{ + + _vj_server_del_client( vje, link_id ); + +} +int vj_server_client_promoted( vj_server *vje, int link_id) +{ + vj_link **Link= (vj_link**) vje->link; + return Link[link_id]->promote; +} +void vj_server_client_promote( vj_server *vje, int link_id) +{ + + vj_link **Link= (vj_link**) vje->link; +#ifdef STRICT_CHECKING + assert( Link[link_id]->in_use == 1 ); +#endif + Link[link_id]->promote = 1; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Knock knock %x", + Link[link_id]->handle ); +#endif +} + + +int vj_server_poll(vj_server * vje) +{ + int status = 0; + struct timeval t; + int i; + + if( vje->use_mcast ) + { + vj_proto **proto = (vj_proto**) vje->protocol; + return mcast_poll( proto[0]->r ); + } + + veejay_memset( &t, 0, sizeof(t)); + + FD_ZERO( &(vje->fds) ); + FD_ZERO( &(vje->wds) ); + + FD_SET( vje->handle, &(vje->fds) ); + if(vje->server_type == V_STATUS) + FD_SET( vje->handle, &(vje->wds) ); + + for( i = 0; i < VJ_MAX_CONNECTIONS; i ++ ) + { + vj_link **Link= (vj_link**) vje->link; + if( Link[i]->in_use ) + { + // if(vje->server_type == V_CMD ) + // { + FD_SET( Link[i]->handle, &(vje->fds) ); + FD_SET( Link[i]->handle, &(vje->wds) ); + // } + // if(vje->server_type == V_STATUS ) + // FD_SET( Link[i]->handle, &(vje->wds)); + } + } + + status = select(vje->nr_of_connections + 1, &(vje->fds), &(vje->wds), 0, &t); + + if( status == -1 ) { + veejay_msg(0, "Error while polling socket: %s", strerror(errno)); + return 0; + } else if ( status == 0 ) { + return 0; + } + + return 1; +} + +int _vj_server_empty_queue(vj_server *vje, int link_id) +{ + vj_link **Link = (vj_link**) vje->link; + vj_message **v = Link[link_id]->m_queue; + int i; + for( i = 0; i < VJ_MAX_PENDING_MSG; i ++ ) + { + if( v[i]->msg ) + free(v[i]->msg); + v[i]->msg = NULL; + v[i]->len = 0; + } + Link[link_id]->n_queued = 0; + Link[link_id]->n_retrieved = 0; + return 1; +} + +#define _vj_malfunction(msg,content,buflen, index)\ +{ \ +if(msg != NULL)\ +veejay_msg(VEEJAY_MSG_DEBUG,"%s",msg);\ +veejay_msg(VEEJAY_MSG_DEBUG,"Message content");\ +veejay_msg(VEEJAY_MSG_DEBUG,"msg [%s] (%d bytes) at position %d",\ + content, buflen, index);\ +int _foobar;\ +for ( _foobar = 0; _foobar < (index+4); _foobar++);\ +veejay_msg(VEEJAY_MSG_PRINT, " ");\ +veejay_msg(VEEJAY_MSG_PRINT, "^");\ +veejay_msg(VEEJAY_MSG_DEBUG, "VIMS (v) - dropped message");\ +} +static int _vj_verify_msg(vj_server *vje,int link_id, char *buf, int buf_len ) +{ + int i = 0; + char *s = buf; + int num_msg = 0; + //vj_link **Link = (vj_link**) vje->link; + + if( (i+4) > buf_len ) + _vj_malfunction("VIMS (v) Message too small", buf, buf_len, i ); + + while( (i+4) < buf_len ) + { + if( !(s[i]=='V' && s[i+4] == 'D') ) + { + if(s[i] != 'K') + { + _vj_malfunction( "VIMS (v) Cannot identify message as VIMS message", buf, buf_len, i); + return 0; + } + } + + if( s[i] != 'K' ) + { + char tmp_len[4]; + char net_id[4]; + int slen = 0; + int netid = 0; + + bzero(tmp_len,4); + bzero(net_id,4 ); + + char *str_ptr = &s[i]; + str_ptr ++; // skip 'V' + + veejay_strncpy( tmp_len,str_ptr, 3 ); // header length + + if( sscanf(tmp_len, "%03d", &slen) <= 0 ) + { + _vj_malfunction( "VIMS (v) Cannot read header length", buf, buf_len, i + 1); + return 0; + } + if( slen > buf_len ) + { + char msg[256]; + veejay_memset(msg,0,256); + snprintf(msg, 256,"VIMS (v) Remote %s is sending corrupted packets", (char*) (inet_ntoa( vje->remote.sin_addr ) ) ); + _vj_malfunction( NULL, buf, buf_len, i + 1 ); + vj_server_close_connection( vje, link_id ); + return 0; + } + if ( slen > 999 ) + { + char msg[256]; + veejay_memset(msg,0,256); + snprintf(msg, 256, "VIMS (v) Remote %s is acting very suspiciously", (char* )( inet_ntoa( vje->remote.sin_addr ) )); + _vj_malfunction( msg, buf, buf_len, i + 1); + vj_server_close_connection( vje, link_id ); + return 0; + } + + i += 4; // advance to message content + str_ptr += 4; + veejay_strncpy( net_id, str_ptr, 3 ); + + if( sscanf( net_id, "%03d", &netid ) <= 0 ) + { + _vj_malfunction( "VIMS (v) Corrupt VIMS selector", buf, buf_len, i ); + return 0; + } + if( netid < 0 && netid > 600 ) + { + _vj_malfunction( "VIMS (v) selector out of range", buf,buf_len, i ); + return 0; + } + if( vje->use_mcast ) + if( netid >= 400 && netid < 500 ) + { + _vj_malfunction( "VIMS (v) multicast doesnt allow querying of data",buf,buf_len,i); + return 0; + } + + + //FIXME: malformed endings + int last_char = slen - 1; + int failed = 1; + if( last_char > 1 ) + { + if(str_ptr[last_char] == '\n' && + str_ptr[last_char-1] == ';' ) + failed = 0; + else if(str_ptr[last_char] == ';' ) + failed = 0; + if(!failed) + { + num_msg ++; + i += slen + 1; + } + } + if(failed) + { + _vj_malfunction("VIMS (v) message does not end with ';'", buf, buf_len , i); + return 0; + } + } + else + { + int len = 0; + char *str_ptr = &s[i]; + + if(sscanf(str_ptr+1, "%8d",&len )) + { + i += len; + num_msg ++; + return num_msg; + } + else + { + _vj_malfunction("VIMS (v) keyframe packet length not set", str_ptr, buf_len, i ); + } + + } + } + if(num_msg > 0 ) + return num_msg; + return 0; +} + + +static int _vj_parse_msg(vj_server *vje,int link_id, char *buf, int buf_len, int priority ) +{ + int i = 0; + char *s = buf; + int num_msg = 0; + vj_link **Link = (vj_link**) vje->link; + vj_message **v = Link[link_id]->m_queue; + + while( (i+4) < buf_len ) + { + char tmp_len[8]; + char net_id[4]; + int slen = 0; + int netid = 0; + bzero(tmp_len,8); + bzero(net_id,4 ); + + char *str_ptr = &s[i]; + + if(s[i] == 'V') + { + str_ptr ++; + + veejay_strncpy( tmp_len,str_ptr, 3 ); // header length + if( sscanf(tmp_len, "%03d", &slen) <= 0 ) + { + veejay_msg(0, "Error parsing header in '%s' (%d bytes)", buf, buf_len ); + return 0; + } + i += 4; // advance to message content + str_ptr += 4; + veejay_strncpy( net_id, str_ptr, 3 ); + + if( sscanf( net_id, "%03d", &netid ) <= 0 ) + { + if( strncasecmp(net_id, "key",3) != 0 ) + { + veejay_msg(0, "Error parsing VIMS ID in '%s' (%d bytes)",buf,buf_len); + return 0; + } + else + { + v[num_msg]->msg = (char*) vj_malloc( slen ); + veejay_memcpy( v[num_msg]->msg, str_ptr, slen ); + v[num_msg]->len = slen; + num_msg++; + } + } + else + { + if(! priority ) + { + // store message anyway + int n_len = slen; + v[num_msg]->msg = (char*)strndup( str_ptr , slen ); + veejay_chomp_str( v[num_msg]->msg , &n_len ); + v[num_msg]->len = n_len; + num_msg++; + } + if(priority && netid > 255 ) + { + // store high priority only (reduce load) - + int n_len = slen; + v[num_msg]->msg = (char*)strndup( str_ptr , slen ); + veejay_chomp_str( v[num_msg]->msg, &n_len ); + v[num_msg]->len = n_len; + num_msg++; + } + } + + if(num_msg == VJ_MAX_PENDING_MSG ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "VIMS server queue full - max messages per interval is %d", + VJ_MAX_PENDING_MSG ); + return num_msg; // cant take more + } + // i += slen; + i += (slen+1); // try next message + + } + else if (s[i] == 'K' ) + { + str_ptr ++; + veejay_memcpy( tmp_len,str_ptr, 8 ); + if( sscanf(tmp_len, "%08d", &slen) <= 0 ) + { + veejay_msg(0, "Error parsing KF header in '%s' (%d bytes)", buf, buf_len ); + return 0; + } + + i += 8; // advance to message content + str_ptr += 8; + + v[num_msg]->msg = (char*) vj_calloc( slen ); + veejay_memcpy( v[num_msg]->msg, str_ptr, slen ); + v[num_msg]->len = slen; + num_msg++; + + i += slen; + } + } + + if( ! priority ) + { + Link[link_id]->n_queued = num_msg; + Link[link_id]->n_retrieved = 0; + } + return num_msg; +} + + +int vj_server_new_connection(vj_server *vje) +{ + if( FD_ISSET( vje->handle, &(vje->fds) ) ) + { + int addr_len = sizeof(vje->remote); + int n = 0; + int fd = accept( vje->handle, (struct sockaddr*) &(vje->remote), &addr_len ); + if(fd == -1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error accepting connection"); + return -1; + } + + char *host = inet_ntoa( vje->remote.sin_addr ); + veejay_msg(VEEJAY_MSG_INFO, "Connection with %s on port %d", host, + vje->remote.sin_port); + if( vje->nr_of_connections < fd ) + vje->nr_of_connections = fd; + + n = _vj_server_new_client(vje, fd); + if( n >= VJ_MAX_CONNECTIONS ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "No more connections allowed"); + close(fd); + return -1; + } + return n; + } + return -1; +} + +int vj_server_update( vj_server *vje, int id ) +{ + int sock_fd = vje->handle; + int n = 0; + _vj_server_empty_queue(vje, id); + + if(!vj_server_poll(vje)) + return 0; + + if(!vje->use_mcast) + { + vj_link **Link = (vj_link**) vje->link; + sock_fd = Link[id]->handle; + + if(!FD_ISSET( sock_fd, &(vje->fds)) ) + return 0; + } + + veejay_memset( vje->recv_buf, 0, RECV_SIZE ); + + if(!vje->use_mcast) + { + /*if(vj_server_link_can_read( vje,sock_fd ) == 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Not ready to receive yet"); + return 0; + }*/ + + n = recv( sock_fd, vje->recv_buf, RECV_SIZE, 0 ); + if( n < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Network error: %s", strerror(errno)); + return -1; + } + if( n == 0 ) + { + veejay_msg(VEEJAY_MSG_INFO ,"Connection closed by remote"); + return -1; + } + } + else + { + vj_proto **proto = (vj_proto**) vje->protocol; + n = mcast_recv( proto[0]->r, (void*) vje->recv_buf, RECV_SIZE ); + if( n <= 0 ) + { + return -1; + } + } + + + char *msg_buf = vje->recv_buf; + int bytes_left = n; + + int n_msg = _vj_verify_msg( vje, id, msg_buf, bytes_left ); + + if(n_msg == 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Invalid instruction '%s'", + msg_buf ); + return 0; + } + + + if( n_msg < VJ_MAX_PENDING_MSG ) + { + int nn = _vj_parse_msg( vje, id, msg_buf, bytes_left,0 ); + if(nn != n_msg) + { + veejay_msg(VEEJAY_MSG_ERROR, "Veejay's message queue corrupted (end session!)"); + return 0; + } + return nn; + } + return 0; +} + +void vj_server_shutdown(vj_server *vje) +{ + int j,i; + vj_link **Link = (vj_link**) vje->link; + int k = VJ_MAX_CONNECTIONS; + + if(vje->use_mcast) k = 1; + + for(i=0; i < k; i++) + { + if(Link[i]->in_use) + close(Link[i]->handle); + for( j = 0; j < VJ_MAX_PENDING_MSG; j ++ ) + { + if(Link[i]->m_queue[j]->msg ) + free( Link[i]->m_queue[j]->msg ); + //if(Link[i]->m_queue[j] ) free( Link[i]->m_queue[j] ); + } + if( Link[i]->lin_queue) + free( Link[i]->lin_queue ); + + if( Link[i]->m_queue ) free( Link[i]->m_queue ); + if( Link[i] ) free( Link[i] ); + } + + if(!vje->use_mcast) + { + close(vje->handle); + } + else + { + vj_proto **proto = (vj_proto**) vje->protocol; + mcast_close_sender( proto[0]->s ); + mcast_close_receiver( proto[0]->r ); + if(proto[0]) + free(proto[0]); + if(proto) free(proto); + } + + if( vje->recv_buf ) + free(vje->recv_buf); + + free(Link); + if(vje) free(vje); +} + +int vj_server_link_used( vj_server *vje, int link_id) +{ + vj_link **Link = (vj_link**) vje->link; +#ifdef STRICT_CHECKING + assert( link_id >= 0 && link_id < VJ_MAX_CONNECTIONS ); +#endif + return Link[link_id]->in_use; +/* + if( link_id < 0 || link_id >= VJ_MAX_CONNECTIONS ) + return 0; + if (Link[link_id]->in_use) + return 1; + return 0;*/ +} + + +int vj_server_min_bufsize( vj_server *vje, int id ) +{ + vj_link **Link = (vj_link**) vje->link; + if (!Link[id]->in_use) + return 0; + + int index = Link[id]->n_retrieved; + if( index >= Link[id]->n_queued ) + return 0; // done + + return Link[id]->m_queue[index]->len; +} + + +char *vj_server_retrieve_msg(vj_server *vje, int id, char *dst, int *str_len ) +{ + vj_link **Link = (vj_link**) vje->link; + if (!Link[id]->in_use) + return NULL; + + int index = Link[id]->n_retrieved; + + if( index >= Link[id]->n_queued ) + return NULL; // done + + char *msg = Link[id]->m_queue[index]->msg; +#ifdef STRICT_CHECKING + assert( msg != NULL ); +#endif + int len = Link[id]->m_queue[index]->len; + +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "L%2d queue [%4d]/[%d] [%4d] '%s'", + id, index, Link[id]->n_queued, len, msg ); + +#endif + + index ++; + Link[id]->n_retrieved = index; + + *str_len = len; + return msg; +} + +/* +int vj_server_retrieve_msg(vj_server *vje, int id, char *dst, int *str_len ) +{ + vj_link **Link = (vj_link**) vje->link; + if (!Link[id]->in_use) + return 0; + + int index = Link[id]->n_retrieved; + char *msg; + int len; + if( index >= Link[id]->n_queued ) + return 0; // done + + msg = Link[id]->m_queue[index]->msg; + len = Link[id]->m_queue[index]->len; +// strncpy( dst, msg, len ); + + veejay_memcpy(dst,msg, len ); + *str_len = len; + + index ++; + Link[id]->n_retrieved = index; + return 1; +} +*/ diff --git a/branches/V-1.5.3/veejay-server/libvjnet/vj-server.h b/branches/V-1.5.3/veejay-server/libvjnet/vj-server.h new file mode 100644 index 00000000..87427ded --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libvjnet/vj-server.h @@ -0,0 +1,77 @@ +/* libvjnet - Linux VeeJay + * (C) 2002-2007 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_SERVER_H +#define VJ_SERVER_H +#include +#include +#include + +#define VJ_PORT 3490 +#define VJ_MAX_CONNECTIONS 16 + +typedef struct vj_server_t { + struct sockaddr_in myself; + struct sockaddr_in remote; + int handle; + int nr_of_connections; + void **link; + fd_set fds; + fd_set wds; + int use_mcast; + int server_type; + int ports[2]; + void **protocol; + char *recv_buf; + int send_size; + int recv_size; + int mcast_gray; +} vj_server; + +vj_server *vj_server_alloc(int port, char *mcast_group_name, int type); + +int vj_server_update(vj_server * vje, int link_id); + +void vj_server_shutdown(vj_server *vje); + +char *vj_server_retrieve_msg(vj_server *vje, int link_id, char *dst, int *res); + +int vj_server_poll(vj_server * vje); + +int vj_server_send(vj_server *vje, int link_id, uint8_t *buf, int len); + +int vj_server_send_frame(vj_server *vje, int link_id, uint8_t *buf, int total_len, VJFrame *frame, long ms + ); + +int vj_server_init(void); + +int _vj_server_del_client(vj_server * vje, int link_id); + +void vj_server_set_mcast_mode( vj_server *vje, int mode ); + +void vj_server_close_connection( vj_server *vje, int link_id ); + +int vj_server_new_connection(vj_server *vje); + +int vj_server_client_promoted( vj_server *vje, int link_id); + +void vj_server_client_promote( vj_server *vje, int link_id); + +int vj_server_link_used(vj_server *vje , int link_id); + +#endif diff --git a/branches/V-1.5.3/veejay-server/libyuv/Makefile.am b/branches/V-1.5.3/veejay-server/libyuv/Makefile.am new file mode 100644 index 00000000..f50ad70a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libyuv/Makefile.am @@ -0,0 +1,10 @@ +# Makefile for veejay + +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(YUVCFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/aclib -I$(top_srcdir)/vjmem -I$(top_srcdir)/vjmsg -I$(top_srcdir)/libpostproc +YUV_LIB_FILE = libyuv.la +pkginclude_HEADERS=yuvconv.h +EXTRA_DIST = mmx.h yuvconv.h mmx_macros.h +noinst_LTLIBRARIES = $(YUV_LIB_FILE) +libyuv_la_SOURCES = subsample.c yuvconv.c diff --git a/branches/V-1.5.3/veejay-server/libyuv/mmx.h b/branches/V-1.5.3/veejay-server/libyuv/mmx.h new file mode 100644 index 00000000..952d27b4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libyuv/mmx.h @@ -0,0 +1,265 @@ +/* + * mmx.h + * Copyright (C) 2000-2001 Michel Lespinasse + * Copyright (C) 1999-2000 Aaron Holtzman + * + * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * See http://libmpeg2.sourceforge.net/ for updates. + * + * mpeg2dec 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. + * + * mpeg2dec is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * The type of an value that fits in an MMX register (note that long + * long constant values MUST be suffixed by LL and unsigned long long + * values by ULL, lest they be truncated by the compiler) + */ + +#define ATTR_ALIGN(align) __attribute__ ((__aligned__ (align))) + +typedef union { + long long q; /* Quadword (64-bit) value */ + unsigned long long uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */ + + +#define mmx_i2r(op,imm,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "i" (imm) ) + +#define mmx_m2r(op,mem,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) + +#define mmx_r2m(op,reg,mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */ ) + +#define mmx_r2r(op,regs,regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + + +#define emms() __asm__ __volatile__ ("emms") + +#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) +#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) +#define movd_v2r(var,reg) __asm__ __volatile__ ("movd %0, %%" #reg \ + : /* nothing */ \ + : "rm" (var)) +#define movd_r2v(reg,var) __asm__ __volatile__ ("movd %%" #reg ", %0" \ + : "=rm" (var) \ + : /* nothing */ ) + +#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) +#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) +#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) + +#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) +#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) +#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) +#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) + +#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) +#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) + +#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) +#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) +#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) +#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) +#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) +#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) + +#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) +#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) +#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) +#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) + +#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) +#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) +#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) +#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) + +#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) +#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) + +#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) +#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) + +#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) +#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) +#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) + +#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) +#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) +#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) + +#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) +#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) + +#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) +#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) + +#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) +#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) + +#define por_m2r(var,reg) mmx_m2r (por, var, reg) +#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) + +#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) +#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) +#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) +#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) +#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) +#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) +#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) +#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) +#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) + +#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) +#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) +#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) +#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) +#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) +#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) + +#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) +#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) +#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) +#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) +#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) +#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) +#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) +#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) +#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) + +#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) +#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) +#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) +#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) +#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) +#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) + +#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) +#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) +#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) +#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) + +#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) +#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) +#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) +#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) + +#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) +#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) +#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) +#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) +#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) +#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) + +#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) +#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) +#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) +#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) +#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) +#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) + +#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) +#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) + + +/* 3DNOW extensions */ + +#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) +#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) + + +/* AMD MMX extensions - also available in intel SSE */ + + +#define mmx_m2ri(op,mem,reg,imm) \ + __asm__ __volatile__ (#op " %1, %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem), "i" (imm)) + +#define mmx_r2ri(op,regs,regd,imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "i" (imm) ) + +#define mmx_fetch(mem,hint) \ + __asm__ __volatile__ ("prefetch" #hint " %0" \ + : /* nothing */ \ + : "m" (mem)) + + +#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) + +#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) + +#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) +#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) +#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) +#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) + +#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) + +#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) + +#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) +#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) + +#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) +#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) + +#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) +#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) + +#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) +#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) + +#define pmovmskb(mmreg,reg) \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) + +#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) +#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) + +#define prefetcht0(mem) mmx_fetch (mem, t0) +#define prefetcht1(mem) mmx_fetch (mem, t1) +#define prefetcht2(mem) mmx_fetch (mem, t2) +#define prefetchnta(mem) mmx_fetch (mem, nta) + +#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) +#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) + +#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) +#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) + +#define sfence() __asm__ __volatile__ ("sfence\n\t") diff --git a/branches/V-1.5.3/veejay-server/libyuv/mmx_macros.h b/branches/V-1.5.3/veejay-server/libyuv/mmx_macros.h new file mode 100644 index 00000000..bd22b2ce --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libyuv/mmx_macros.h @@ -0,0 +1,46 @@ +#include /* size_t */ +#include + +/* MMX memcpy stuff taken from MPlayer (http://www.mplayerhq.hu) */ + +#define BLOCK_SIZE 4096 +#define CONFUSION_FACTOR 0 +//Feel free to fine-tune the above 2, it might be possible to get some speedup with them :) + +#undef HAVE_MMX1 +#ifndef MMXEXT +/* means: mmx v.1. Note: Since we added alignment of destinition it speedups + of memory copying on PentMMX, Celeron-1 and P2 upto 12% versus + standard (non MMX-optimized) version. + Note: on K6-2+ it speedups memory copying upto 25% and + on K7 and P3 about 500% (5 times). */ +#define HAVE_MMX1 +#endif + +#undef MMREG_SIZE +#define MMREG_SIZE 64 //8 + +#undef PREFETCH +#undef EMMS + +#ifdef MMXEXT +#define PREFETCH "prefetchnta" +#else +#define PREFETCH "/nop" +#endif + +#define EMMS "emms" + +#undef MOVNTQ +#ifdef MMXEXT +#define MOVNTQ "movntq" +#else +#define MOVNTQ "movq" +#endif + +#undef MIN_LEN +#ifdef HAVE_MMX1 +#define MIN_LEN 0x800 /* 2K blocks */ +#else +#define MIN_LEN 0x40 /* 64-byte blocks */ +#endif diff --git a/branches/V-1.5.3/veejay-server/libyuv/subsample.c b/branches/V-1.5.3/veejay-server/libyuv/subsample.c new file mode 100644 index 00000000..0de99a86 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libyuv/subsample.c @@ -0,0 +1,857 @@ +/* + * subsample.c: Routines to do chroma subsampling. ("Work In Progress") + * + * + * Copyright (C) 2001 Matthew J. Marjanovic + * 2004 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + + +#include + +#ifdef HAVE_ASM_MMX +#include "mmx.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +const char *ssm_id[SSM_COUNT] = { + "unknown", + "420_jpeg", + "420_mpeg2", +#if 0 + "420_dv_pal", + "411_dv_ntsc" +#endif +}; + + +const char *ssm_description[SSM_COUNT] = { + "unknown/illegal", + "4:2:0, JPEG/MPEG-1, interstitial siting", + "4:2:0, MPEG-2, horizontal cositing", +#if 0 + "4:2:0, DV-PAL, cosited, Cb/Cr line alternating", + "4:1:1, DV-NTSC" + "4:2:2", +#endif +}; + + +#define RUP8(num)(((num)+8)&~8) + +// forward decl +void ss_420_to_422(uint8_t *buffer, int width, int height); +void ss_422_to_420(uint8_t *buffer, int width, int height); + +typedef struct +{ + uint8_t *buf; +} yuv_sampler_t; + +void *subsample_init(int len) +{ + yuv_sampler_t *s = (yuv_sampler_t*) vj_malloc(sizeof(yuv_sampler_t) ); + if(!s) + return NULL; + s->buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * RUP8(len*2) ); + if(!s->buf) + return NULL; + + return (void*) s; +} + +void subsample_free(void *data) +{ + yuv_sampler_t *sampler = (yuv_sampler_t*) data; + if(sampler) + { + if(sampler->buf) + free(sampler->buf); + free(sampler); + } + sampler = NULL; +} + +/************************************************************************* + * Chroma Subsampling + *************************************************************************/ + + +/* vertical/horizontal interstitial siting + * + * Y Y Y Y + * C C + * Y Y Y Y + * + * Y Y Y Y + * C C + * Y Y Y Y + * + */ + +/* +static void ss_444_to_420jpeg(uint8_t *buffer, int width, int height) +{ + uint8_t *in0, *in1, *out; + int x, y; + + in0 = buffer; + in1 = buffer + width; + out = buffer; + for (y = 0; y < height; y += 2) { + for (x = 0; x < width; x += 2) { + *out = (in0[0] + in0[1] + in1[0] + in1[1]) >> 2; + in0 += 2; + in1 += 2; + out++; + } + in0 += width; + in1 += width; + } +} +*/ +/* + + using weighted averaging for subsampling 2x2 -> 1x1 + here, 4 pixels are filled in each inner loop, (weighting + 16 source pixels) +*/ + +static void ss_444_to_420jpeg(uint8_t *buffer, int width, int height) +{ + const uint8_t *in0, *in1; + uint8_t *out; + int x, y = height; + in0 = buffer; + in1 = buffer + width; + out = buffer; + for (y = 0; y < height; y += 4) { + for (x = 0; x < width; x += 4) { + out[0] = (in0[0] + 3 * (in0[1] + in1[0]) + (9 * in1[1]) + 8) >> 4; + out[1] = (in0[2] + 3 * (in0[3] + in1[2]) + (9 * in1[3]) + 8) >> 4; + out[2] = (in0[4] + 3 * (in0[5] + in1[4]) + (9 * in1[5]) + 8) >> 4; + out[3] = (in0[6] + 3 * (in0[7] + in1[6]) + (9 * in1[7]) + 8) >> 4; + + in0 += 8; + in1 += 8; + out += 4; + } + for ( ; x < width; x +=2 ) + { + out[0] = (in0[0] + 3 * (in0[1] + in1[0]) + (9 * in1[1]) + 8) >> 4; + in0 += 2; + in1 += 2; + out++; + } + in0 += width*2; + in1 += width*2; + } +} +static void ss_444_to_420jpeg_cp(uint8_t *buffer,uint8_t *dest, int width, int height) +{ + const uint8_t *in0, *in1; + uint8_t *out; + int x, y = height; + in0 = buffer; + in1 = buffer + width; + out = dest; + for (y = 0; y < height; y += 4) { + for (x = 0; x < width; x += 4) { + out[0] = (in0[0] + 3 * (in0[1] + in1[0]) + (9 * in1[1]) + 8) >> 4; + out[1] = (in0[2] + 3 * (in0[3] + in1[2]) + (9 * in1[3]) + 8) >> 4; + out[2] = (in0[4] + 3 * (in0[5] + in1[4]) + (9 * in1[5]) + 8) >> 4; + out[3] = (in0[6] + 3 * (in0[7] + in1[6]) + (9 * in1[7]) + 8) >> 4; + + in0 += 8; + in1 += 8; + out += 4; + } + for ( ; x < width; x +=2 ) + { + out[0] = (in0[0] + 3 * (in0[1] + in1[0]) + (9 * in1[1]) + 8) >> 4; + in0 += 2; + in1 += 2; + out++; + } + in0 += width*2; + in1 += width*2; + } +} +/* horizontal interstitial siting + * + * Y Y Y Y + * C C C C in0 + * Y Y Y Y + * C C C C + * + * Y Y Y Y + * C C out0 + * Y Y Y Y + * C C + * + * + */ + + + + +/* vertical/horizontal interstitial siting + * + * Y Y Y Y + * C C C inm + * Y Y Y Y + * + * Y Y Y - Y out0 + * C | C | C in0 + * Y Y Y - Y out1 + * + * + * C C C inp + * + * + * Each iteration through the loop reconstitutes one 2x2 block of + * pixels from the "surrounding" 3x3 block of samples... + * Boundary conditions are handled by cheap reflection; i.e. the + * center sample is simply reused. + * + */ + + +#define BLANK_CRB in0[1] +#define BLANK_CRB_2 (in0[1] << 1) + +static void tr_420jpeg_to_444(void *data, uint8_t *buffer, int width, int height) +{ + uint8_t *inm, *in0, *inp, *out0, *out1; + uint8_t cmm, cm0, cmp, c0m, c00, c0p, cpm, cp0, cpp; + int x, y; + + yuv_sampler_t *sampler = (yuv_sampler_t*) data; + + uint8_t *saveme = sampler->buf; + + veejay_memcpy(saveme, buffer, width); + + in0 = buffer + ( width * height /4) - 2; + inm = in0 - width/2; + inp = in0 + width/2; + out1 = buffer + (width * height) - 1; + out0 = out1 - width; + + for (y = height; y > 0; y -= 2) { + if (y == 2) { + in0 = saveme + width/2 - 2; + inp = in0 + width/2; + } + for (x = width; x > 0; x -= 2) { +#if 0 + if ((x == 2) && (y == 2)) { + cmm = in0[1]; + cm0 = in0[1]; + cmp = in0[2]; + c0m = in0[1]; + c0p = in0[2]; + cpm = inp[1]; + cp0 = inp[1]; + cpp = inp[2]; + } else if ((x == 2) && (y == height)) { + cmm = inm[1]; + cm0 = inm[1]; + cmp = inm[2]; + c0m = in0[1]; + c0p = in0[2]; + cpm = in0[1]; + cp0 = in0[1]; + cpp = in0[2]; + } else if ((x == width) && (y == height)) { + cmm = inm[0]; + cm0 = inm[1]; + cmp = inm[1]; + c0m = in0[0]; + c0p = in0[1]; + cpm = in0[0]; + cp0 = in0[1]; + cpp = in0[1]; + } else if ((x == width) && (y == 2)) { + cmm = in0[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; + } else if (x == 2) { + cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; + } else if (y == 2) { + cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; + } else if (x == width) { + cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; + } else if (y == height) { + cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; + } else { + cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; + } + c00 = in0[1]; + + cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; +#else + cmm = ((x == 2) || (y == 2)) ? BLANK_CRB : inm[0]; + cm0 = (y == 2) ? BLANK_CRB : inm[1]; + cmp = ((x == width) || (y == 2)) ? BLANK_CRB : inm[2]; + c0m = (x == 2) ? BLANK_CRB : in0[0]; + c00 = in0[1]; + c0p = (x == width) ? BLANK_CRB : in0[2]; + cpm = ((x == 2) || (y == height)) ? BLANK_CRB : inp[0]; + cp0 = (y == height) ? BLANK_CRB : inp[1]; + cpp = ((x == width) || (y == height)) ? BLANK_CRB : inp[2]; +#endif + inm--; + in0--; + inp--; + + *(out1--) = (1*cpp + 3*(cp0+c0p) + 9*c00 + 8) >> 4; + *(out1--) = (1*cpm + 3*(cp0+c0m) + 9*c00 + 8) >> 4; + *(out0--) = (1*cmp + 3*(cm0+c0p) + 9*c00 + 8) >> 4; + *(out0--) = (1*cmm + 3*(cm0+c0m) + 9*c00 + 8) >> 4; + } + out1 -= width; + out0 -= width; + } +} + +// lame box filter +// the dampening of high frequencies depend +// on the directions these frequencies occur in the +// image, resulting in clear edges between certain +// group of pixels. + +static void ss_420jpeg_to_444(uint8_t *buffer, int width, int height) +{ +#ifndef HAVE_ASM_MMX + uint8_t *in, *out0, *out1; + int x, y; + in = buffer + (width * height / 4) - 1; + out1 = buffer + (width * height) - 1; + out0 = out1 - width; + for (y = height - 1; y >= 0; y -= 2) { + for (x = width - 1; x >= 0; x -=2) { + uint8_t val = *(in--); + *(out1--) = val; + *(out1--) = val; + *(out0--) = val; + *(out0--) = val; + } + out0 -= width; + out1 -= width; + } +#else + int x,y; + const int mmx_stride = width >> 3; + uint8_t *src = buffer + ((width * height) >> 2)-1; + uint8_t *dst = buffer + (width * height) -1; + uint8_t *dst2 = dst - width; + + for( y = height-1; y >= 0; y -= 2) + { + for( x = 0; x < mmx_stride; x ++ ) + { + movq_m2r( *src,mm0 ); + movq_m2r( *src,mm1 ); + movq_r2m(mm0, *dst ); + movq_r2m(mm1, *(dst+8) ); + movq_r2m(mm0, *dst2 ); + movq_r2m(mm1, *(dst2+8) ); + dst += 16; + dst2 += 16; + src += 8; + } + dst -= width; + dst2 -= width; + } +#endif +} + + +void ss_420_to_422(uint8_t *buffer, int width, int height) +{ + + //todo, 1x2 super sampling (box) +} + +void ss_422_to_420(uint8_t *buffer, int width, int height ) +{ + + //todo 2x1 down sampling (box) +} + +#ifdef HAVE_ASM_MMX +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW ) +#define HAVE_K6_2PLUS +#endif + +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif + +#endif + +#ifdef HAVE_ASM_MMX +/* for small memory blocks (<256 bytes) this version is faster */ +#define small_memcpy(to,from,n)\ +{\ +register unsigned long int dummy;\ +__asm__ __volatile__(\ + "rep; movsb"\ + :"=&D"(to), "=&S"(from), "=&c"(dummy)\ + :"0" (to), "1" (from),"2" (n)\ + : "memory");\ +} + +static inline void copy8( uint8_t *dst, uint8_t *in ) +{ + __asm__ __volatile__ ( + "movq (%0), %%mm0\n" + "movq %%mm0, (%1)\n" + :: "r" (in), "r" (dst) : "memory" ); +} + +static inline void copy16( uint8_t *dst, uint8_t *in) +{ + __asm__ __volatile__ ( + "movq (%0), %%mm0\n" + "movq 8(%0), %%mm1\n" + "movq %%mm0, (%1)\n" + "movq %%mm1, 8(%1)\n" + :: "r" (in), "r" (dst) : "memory" ); +} + +static inline void copy_width( uint8_t *dst, uint8_t *in, int width ) +{ + int w = width >> 4; + int x; + uint8_t *d = dst; + uint8_t *i = in; + + for( x = 0; x < w; x ++ ) + { + copy16( d, i ); + d += 16; + i += 16; + } + + x = (width % 16); + if( x ) + small_memcpy( d, i, x); +} + +static inline void load_mask16to8() +{ + const uint64_t mask = 0x00ff00ff00ff00ffLL; + const uint8_t *m = (uint8_t*)&mask; + + __asm __volatile( + "movq (%0), %%mm4\n\t" + :: "r" (m) + ); + +} + +static inline void down_sample16to8( uint8_t *out, uint8_t *in ) +{ + //@ down sample by dropping right pixels + __asm __volatile( + "movq (%0), %%mm1\n\t" + "movq 8(%0),%%mm3\n\t" + "pxor %%mm5,%%mm5\n\t" + "pand %%mm4,%%mm1\n\t" + "pand %%mm4,%%mm3\n\t" + "packuswb %%mm1,%%mm2\n\t" + "packuswb %%mm3,%%mm5\n\t" + "psrlq $32, %%mm2\n\t" + "por %%mm5,%%mm2\n\t" + "movq %%mm2, (%1)\n\t" + :: "r" (in), "r" (out) + ); +} +#endif +static void ss_444_to_422_cp(void *data, uint8_t *buffer, uint8_t *dest, int width, int height) +{ + const int dst_stride = width >> 1; + int x,y; +#ifdef HAVE_ASM_MMX + int mmxdst_stride=dst_stride >> 3; + int left = dst_stride % 8; +#endif + yuv_sampler_t *sampler = (yuv_sampler_t*) data; + uint8_t *src = sampler->buf; + uint8_t *dst; + +#ifdef HAVE_ASM_MMX + load_mask16to8(); +#endif + for(y = 0; y < height; y ++) + { + src = buffer + (y*width); + dst = dest + (y*dst_stride); + +#if defined (HAVE_ASM_MMX) || defined (HAVE_ASM_MMX2) + + for( x= 0; x < mmxdst_stride; x++ ) + { + down_sample16to8( dst, src ); + src += 16; + dst += 8; + } + for(x=0; x < left; x++) + { + *(dst++) = ( src[0] + src[1] + 1 ) >> 1; + src += 2; + } +#else + for(x=0; x < dst_stride; x++) + { + *(dst++) = ( src[0] + src[1] + 1 ) >> 1; + src += 2; + } + +#endif + } +} + + +static void ss_444_to_422(void *data, uint8_t *buffer, int width, int height) +{ + const int dst_stride = width >> 1; + int x,y; +#ifdef HAVE_ASM_MMX + int mmxdst_stride=dst_stride >> 3; + int left = dst_stride % 8; +#endif + yuv_sampler_t *sampler = (yuv_sampler_t*) data; + uint8_t *src = sampler->buf; + uint8_t *dst; + +#ifdef HAVE_ASM_MMX + load_mask16to8(); +#endif + for(y = 0; y < height; y ++) + { + src = sampler->buf; + dst = buffer + (y*dst_stride); + +#if defined (HAVE_ASM_MMX) || defined (HAVE_ASM_MMX2) + copy_width( src, buffer + (y*width), width ); + + for( x= 0; x < mmxdst_stride; x++ ) + { + down_sample16to8( dst, src ); + src += 16; + dst += 8; + } + for(x=0; x < left; x++) + { + *(dst++) = ( src[0] + src[1] + 1 ) >> 1; + src += 2; + } +#else + for( x = 0; x < dst_stride; x ++ ) + { + *(dst++) = (src[0] + src[1] + 1 ) >> 1; + src += 2; + } +#endif + } +} +#ifdef HAVE_ASM_MMX + +static inline void super_sample8to16( uint8_t *in, uint8_t *out ) +{ + //@ super sample by duplicating pixels + __asm__ __volatile__ ( + "\n\tpxor %%mm2,%%mm2" + "\n\tpxor %%mm4,%%mm4" + "\n\tmovq (%0), %%mm1" + "\n\tpunpcklbw %%mm1,%%mm2" + "\n\tpunpckhbw %%mm1,%%mm4" + "\n\tmovq %%mm2,%%mm5" + "\n\tmovq %%mm4,%%mm6" + "\n\tpsrlq $8, %%mm5" + "\n\tpsrlq $8, %%mm6" + "\n\tpor %%mm5,%%mm2" + "\n\tpor %%mm6,%%mm4" + "\n\tmovq %%mm2, (%1)" + "\n\tmovq %%mm4, 8(%1)" + :: "r" (in), "r" (out) + + ); +} +#endif + +static void tr_422_to_444(void *data, uint8_t *buffer, int width, int height) +{ + int x,y; + const int stride = width >> 1; + +#ifndef HAVE_ASM_MMX + for( y = height-1; y > 0 ; y -- ) + { + uint8_t *dst = buffer + (y * width); + uint8_t *src = buffer + (y * stride); + for(x=0; x < stride; x++) // for 1 row + { + dst[0] = src[x]; //put to dst + dst[1] = src[x]; + dst+=2; // increment dst + } + } +#else + + const int mmx_stride = stride >> 3; + int left = (mmx_stride % 8)-1; + if( left < 0 ) left = 0; + for( y = height-1; y > 0 ; y -- ) + { + uint8_t *src = buffer + (y * stride); + uint8_t *dst = buffer + (y * width); + for(x=0; x < mmx_stride; x++) // for 1 row + { + super_sample8to16(src,dst ); + src += 8; + dst += 16; + } + /* for(x=0; x < left; x++) // for 1 row + { + dst[0] = src[x]; //put to dst + dst[1] = src[x]; + dst+=2; // increment dst + }*/ + } +#endif +} + + + + +/* vertical intersitial siting; horizontal cositing + * + * Y Y Y Y + * C C + * Y Y Y Y + * + * Y Y Y Y + * C C + * Y Y Y Y + * + * [1,2,1] kernel for horizontal subsampling: + * + * inX[0] [1] [2] + * | | | + * C C C C + * \ | / + * \ | / + * C + */ + +static void ss_444_to_420mpeg2(uint8_t *buffer, int width, int height) +{ + uint8_t *in0, *in1, *out; + int x, y; + + in0 = buffer; /* points to */ + in1 = buffer + width; /* second of pair of lines */ + out = buffer; + for (y = 0; y < height; y += 2) { + /* first column boundary condition -- just repeat it to right */ + *out = (in0[0] + (2 * in0[0]) + in0[1] + + in1[0] + (2 * in1[0]) + in1[1]) >> 3; + out++; + in0++; + in1++; + /* rest of columns just loop */ + for (x = 2; x < width; x += 2) { + *out = (in0[0] + (2 * in0[1]) + in0[2] + + in1[0] + (2 * in1[1]) + in1[2]) >> 3; + in0 += 2; + in1 += 2; + out++; + } + in0 += width + 1; + in1 += width + 1; + } +} + + +void chroma_subsample_cp(subsample_mode_t mode, void *data, uint8_t *ycbcr[], uint8_t *dcbcr[], + int width, int height) +{ + switch (mode) { + case SSM_420_JPEG_BOX: + case SSM_420_JPEG_TR: + ss_444_to_420jpeg_cp(ycbcr[1],dcbcr[1], width, height); + ss_444_to_420jpeg_cp(ycbcr[2],dcbcr[2], width, height); + + break; + case SSM_420_MPEG2: + break; + case SSM_422_444: + ss_444_to_422_cp(data,ycbcr[1],dcbcr[1],width,height); + ss_444_to_422_cp(data,ycbcr[2],dcbcr[2],width,height); +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif + break; + case SSM_420_422: + break; + default: + break; + } +} + + + + + +void chroma_subsample(subsample_mode_t mode, void *data, uint8_t *ycbcr[], + int width, int height) +{ + switch (mode) { + case SSM_420_JPEG_BOX: + case SSM_420_JPEG_TR: + ss_444_to_420jpeg(ycbcr[1], width, height); + ss_444_to_420jpeg(ycbcr[2], width, height); +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif + break; + case SSM_420_MPEG2: + ss_444_to_420mpeg2(ycbcr[1], width, height); + ss_444_to_420mpeg2(ycbcr[2], width, height); + break; + case SSM_422_444: + ss_444_to_422(data,ycbcr[1],width,height); + ss_444_to_422(data,ycbcr[2],width,height); +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif + break; + case SSM_420_422: + ss_422_to_420(ycbcr[1],width,height); + ss_422_to_420(ycbcr[2],width,height); + break; + default: + break; + } +} + + +void chroma_supersample(subsample_mode_t mode,void *data, uint8_t *ycbcr[], + int width, int height) +{ + switch (mode) { + case SSM_420_JPEG_BOX: + ss_420jpeg_to_444(ycbcr[1], width, height); + ss_420jpeg_to_444(ycbcr[2], width, height); +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif + break; + case SSM_420_JPEG_TR: + tr_420jpeg_to_444(data,ycbcr[1], width, height); + tr_420jpeg_to_444(data,ycbcr[2], width, height); + break; + case SSM_422_444: + tr_422_to_444(data,ycbcr[1],width,height); + tr_422_to_444(data,ycbcr[2],width,height); +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif + break; + case SSM_420_422: + ss_420_to_422( ycbcr[1], width, height ); + ss_420_to_422( ycbcr[2], width, height ); + break; + case SSM_420_MPEG2: + // ss_420mpeg2_to_444(ycbcr[1], width, height); + // ss_420mpeg2_to_444(ycbcr[2], width, height); + break; + default: + break; + } + +} + + diff --git a/branches/V-1.5.3/veejay-server/libyuv/yuvconv.c b/branches/V-1.5.3/veejay-server/libyuv/yuvconv.c new file mode 100644 index 00000000..ed50eb22 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libyuv/yuvconv.c @@ -0,0 +1,1491 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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 +/* this routine is the same as frame_YUV422_to_YUV420P , unpack + * libdv's 4:2:2-packed into 4:2:0 planar + * See http://mjpeg.sourceforge.net/ (MJPEG Tools) (lav-common.c) + */ + +#ifdef STRICT_CHECKING +#include +#endif + + +#ifdef HAVE_ASM_MMX +#undef HAVE_K6_2PLUS +#if !defined( HAVE_ASM_MMX2) && defined( HAVE_ASM_3DNOW ) +#define HAVE_K6_2PLUS +#endif + +#undef _EMMS + +#ifdef HAVE_K6_2PLUS +/* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */ +#define _EMMS "femms" +#else +#define _EMMS "emms" +#endif + +#endif + + +static int sws_context_flags_ = 0; +static int ffmpeg_aclib[64]; + +#define put(a,b) ffmpeg_aclib[a] = b + +static struct { + int i; + char *s; +} pixstr[] = { + {PIX_FMT_YUV420P, "PIX_FMT_YUV420P"}, +{ PIX_FMT_YUV422P, "PIX_FMT_YUV422P"}, +{ PIX_FMT_YUVJ420P, "PIX_FMT_YUVJ420P"}, +{ PIX_FMT_YUVJ422P, "PIX_FMT_YUVJ422P"}, +{ PIX_FMT_RGB24, "PIX_FMT_RGB24"}, +{ PIX_FMT_BGR24, "PIX_FMT_BGR24"}, +{ PIX_FMT_YUV444P, "PIX_FMT_YUV444P"}, +{ PIX_FMT_YUVJ444P, "PIX_FMT_YUVJ444P"}, +{ PIX_FMT_RGB32, "PIX_FMT_RGB32"}, +{ PIX_FMT_BGR32, "PIX_FMT_BGR32"}, +{ PIX_FMT_GRAY8, "PIX_FMT_GRAY8"}, +{ PIX_FMT_RGB32_1, "PIX_FMT_RGB32_1"}, +{ PIX_FMT_YUYV422, "PIX_FMT_YUYV422"}, +{ 0 , NULL} + +}; + +void yuv_pixstr( const char *s, char *s2, int fmt ) { + char *str = NULL; + int i; + for( i = 0; pixstr[i].s != NULL ; i ++ ) + if( fmt == pixstr[i].i ) str = pixstr[i].s; + if( str ) + veejay_msg(0, "%s: %s format %d : %s", s,s2,fmt, str ); + else + veejay_msg(0, "%s: format %d invalid", s, fmt ); +} + +static float jpeg_to_CCIR_tableY[256]; +static float CCIR_to_jpeg_tableY[256]; +static float jpeg_to_CCIR_tableUV[256]; +static float CCIR_to_jpeg_tableUV[256]; +#define round1(x) ( (int32_t)( (x>0) ? (x) + 0.5 : (x) - 0.5 )) +#define _CLAMP(a,min,max) ( round1(a) < min ? min : ( round1(a) > max ? max : round1(a) )) + +static struct { + int id; +} ccir_pixfmts[] = +{ + { PIX_FMT_YUV420P }, + { PIX_FMT_YUYV422 }, + { PIX_FMT_YUV422P }, + { PIX_FMT_YUV444P }, + { -1 } +}; +static struct { + int id; +} jpeg_pixfmts[] = +{ + { PIX_FMT_YUVJ420P }, + { PIX_FMT_YUVJ422P }, + { PIX_FMT_YUVJ444P }, + { -1 }, +}; + +static int auto_conversion_ccir_jpeg_ = 0; + +static int is_CCIR(int a) { + int i; + for( i = 0; ccir_pixfmts[i].id != -1; i ++ ) + if( a == ccir_pixfmts[i].id ) + return 1; + return 0; +} +static int is_JPEG(int a) { + int i; + for( i = 0; jpeg_pixfmts[i].id != -1 ; i ++ ) + if( a == jpeg_pixfmts[i].id ) + return 1; + return 0; +} + +static void verify_CCIR_auto(int a, int b, VJFrame *dst ) +{ + int a_is_CCIR = is_CCIR(a); + int a_is_JPEG = is_JPEG(a); + + int b_is_CCIR = is_CCIR(b); + int b_is_JPEG = is_JPEG(b); + + + if( a_is_JPEG && b_is_CCIR ) { + yuv_scale_pixels_from_y( dst->data[0], dst->len ); + yuv_scale_pixels_from_uv( dst->data[1], dst->uv_len ); + yuv_scale_pixels_from_uv( dst->data[2], dst->uv_len ); + } + else if( a_is_CCIR && b_is_JPEG ) { + yuv_scale_pixels_from_ycbcr( dst->data[0], 16.0f, 235.0f, dst->len ); + yuv_scale_pixels_from_ycbcr( dst->data[1], 16.0f, 240.0f, dst->uv_len ); + yuv_scale_pixels_from_ycbcr( dst->data[2], 16.0f, 240.0f, dst->uv_len ); + } + + +} + +static void verify_CCIR_( int a, int b, char *caller, int line ) { + + int a_is_CCIR = is_CCIR(a); + int a_is_JPEG = is_JPEG(a); + + int b_is_CCIR = is_CCIR(b); + int b_is_JPEG = is_JPEG(b); + + + if( a_is_JPEG && b_is_CCIR ) { + if(caller) { + veejay_msg(VEEJAY_MSG_ERROR, "Output is expecting CCIR, but source still in JPEG %s:%d", + caller,line ); + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "Output is expecting CCIR, but source still in JPEG!"); + } + } + if( a_is_CCIR && b_is_JPEG ) { + if(caller) { + veejay_msg(VEEJAY_MSG_ERROR, "Input is CCIR, but output is expecting JPEG %s:%d", + caller,line ); + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "Input is CCIR, but output is in JPEG"); + } + } +} + +#ifdef STRICT_CHECKING +#define verify_CCIR( a,b ) verify_CCIR_( a,b,__FUNCTION__,__LINE__ ) +#else +#define verify_CCIR( a,b ) return +#endif + +int yuv_use_auto_ccir_jpeg() +{ + return auto_conversion_ccir_jpeg_; +} + +static int global_scaler_ = SWS_FAST_BILINEAR; +static int full_chroma_interpolation_ = 0; +int yuv_which_scaler() +{ + return global_scaler_; +} +void yuv_init_lib(int extra_flags, int auto_ccir_jpeg, int default_zoomer) +{ + sws_context_flags_ = yuv_sws_get_cpu_flags(); + if(extra_flags) { + full_chroma_interpolation_ = 1; + veejay_msg(VEEJAY_MSG_WARNING, + "Interpolating full chroma in converter/scaler"); + } + if( default_zoomer ) { + if( default_zoomer == 1 ) { + global_scaler_ = SWS_FAST_BILINEAR; + } else if (default_zoomer == 2 ) { + global_scaler_ = SWS_BICUBIC; + } + } + + auto_conversion_ccir_jpeg_ = auto_ccir_jpeg; + if( auto_conversion_ccir_jpeg_ ) { + veejay_msg(VEEJAY_MSG_WARNING, + "On-the-fly conversion between CCIR 601 and JPEG color range!"); + auto_conversion_ccir_jpeg_ = 1; + } + + int my_ac_flags = ac_cpuinfo(); + + veejay_msg(VEEJAY_MSG_DEBUG, "CPU Flags available:", ac_flagstotext( my_ac_flags )); + + // initialize tables for jpeg <-> ccir conversion + veejay_memset( jpeg_to_CCIR_tableY, 0, sizeof( jpeg_to_CCIR_tableY ) ); + veejay_memset( CCIR_to_jpeg_tableY, 0, sizeof( CCIR_to_jpeg_tableY ) ); + veejay_memset( jpeg_to_CCIR_tableUV, 0, sizeof( jpeg_to_CCIR_tableUV ) ); + veejay_memset( CCIR_to_jpeg_tableUV, 0, sizeof( CCIR_to_jpeg_tableUV ) ); + + unsigned int i; + float s = (235.0f - 16.0f) / 255.0f; + float u = (240.0f - 16.0f) / 255.0f; + float c = 255.0f / ( 235.0f-16.0f ); + float d = 255.0f / ( 240.0f-16.0f ); + + for( i = 0; i < 256 ; i ++ ) { + jpeg_to_CCIR_tableY[i] = _CLAMP( (float)i * s + 16.0f , 16.0f, 235.0f ); + jpeg_to_CCIR_tableUV[i]= _CLAMP( (float)i * u + 16.0f , 16.0f, 240.0f ); + CCIR_to_jpeg_tableY[i] = _CLAMP( (float)i * c - 16.0f , 0.0f, 255.0f ); + CCIR_to_jpeg_tableUV[i]= _CLAMP( (float)i * d - 16.0f , 0.0f, 255.0f ); + } + + //ac_init( AC_ALL ); + + //ac_imgconvert_init(AC_ALL); + + veejay_memset( ffmpeg_aclib, 0, sizeof(ffmpeg_aclib )); + + put( PIX_FMT_YUV420P, IMG_YUV420P ); + put( PIX_FMT_YUV422P, IMG_YUV422P ); + put( PIX_FMT_YUV444P, IMG_YUV444P ); + put( PIX_FMT_YUVJ420P, IMG_YUV420P ); //@wrong, but size fits + put( PIX_FMT_YUVJ422P, IMG_YUV422P ); + put( PIX_FMT_YUVJ422P, IMG_YUV422P ); +// put( PIX_FMT_RGB24, IMG_RGB24 ); +// put( PIX_FMT_BGR24, IMG_BGR24 ); + put( PIX_FMT_RGB24, IMG_BGR24 ); + put( PIX_FMT_BGR24, IMG_RGB24 ); +// put( PIX_FMT_RGB32, IMG_ARGB32 ); + put( PIX_FMT_RGB32, IMG_RGBA32 ); + put( PIX_FMT_RGBA, IMG_RGBA32 ); + put( PIX_FMT_RGB32_1, IMG_RGBA32 ); + put( PIX_FMT_YUYV422, IMG_YUY2); + put( PIX_FMT_GRAY8, IMG_Y8 ); +} + +VJFrame *yuv_yuv_template( uint8_t *Y, uint8_t *U, uint8_t *V, int w, int h, int fmt ) +{ + VJFrame *f = (VJFrame*) vj_calloc(sizeof(VJFrame)); + f->format = fmt; + f->data[0] = Y; + f->data[1] = U; + f->data[2] = V; + f->data[3] = NULL; + f->width = w; + f->height = h; + + switch(fmt) + { + case PIX_FMT_YUV422P: + case PIX_FMT_YUVJ422P: + f->uv_width = w>>1; + f->uv_height= f->height; + f->stride[0] = w; + f->stride[1] = w>>1; + f->stride[2] = w>>1; + break; + case PIX_FMT_YUV420P: + case PIX_FMT_YUVJ420P: + f->uv_width = w>>1; + f->uv_height=f->height>>1; + f->stride[0] = w; + f->stride[1] = f->stride[2] = f->stride[0]>>1; + break; + case PIX_FMT_YUV444P: + case PIX_FMT_YUVJ444P: + f->uv_width = w; + f->uv_height=f->height; + f->stride[0] = w; + f->stride[1] = f->stride[2] = f->stride[0]; + break; + case PIX_FMT_GRAY8: + f->uv_width = 0; + f->uv_height = 0; + f->stride[0] = w; + f->stride[1] = f->stride[2] = 0; + break; + case PIX_FMT_YUYV422: + case PIX_FMT_UYVY422: + f->uv_width = w>>1; + f->uv_height = f->height; + f->stride[0] = w * 2; + f->stride[1] = f->stride[2] = 0; + break; + default: +#ifdef STRICT_CHECKING + yuv_pixstr( __FUNCTION__, "fmt", fmt ); + + assert(0); +#endif + break; + } + f->len = w*h; + f->uv_len = f->uv_width*f->uv_height; + + return f; +} + +VJFrame *yuv_rgb_template( uint8_t *rgb_buffer, int w, int h, int fmt ) +{ +#ifdef STRICT_CHECKING + assert( fmt == PIX_FMT_RGB24 || fmt == PIX_FMT_BGR24 || + fmt == PIX_FMT_RGBA || fmt == PIX_FMT_RGB32_1 || fmt == PIX_FMT_RGB32); + assert( w > 0 ); + assert( h > 0 ); +#endif + VJFrame *f = (VJFrame*) vj_calloc(sizeof(VJFrame)); + f->format = fmt; + f->data[0] = rgb_buffer; + f->data[1] = NULL; + f->data[2] = NULL; + f->data[3] = NULL; + f->width = w; + f->height = h; + + switch( fmt ) + { + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + f->stride[0] = w * 3; + break; + default: + f->stride[0] = w * 4; + break; + } + f->stride[1] = 0; + f->stride[2] = 0; + + return f; +} + +#define ru4(num) (((num)+3)&~3) + + +static struct +{ + int ffmpeg; + int aclib; +} ffmpegaclib[] = +{ + { PIX_FMT_YUV420P, IMG_YUV420P }, + { PIX_FMT_YUV422P, IMG_YUV422P }, + { PIX_FMT_YUV444P, IMG_YUV444P }, + { PIX_FMT_RGB24, IMG_RGB24 }, + { PIX_FMT_BGR24, IMG_BGR24 }, + { PIX_FMT_RGB32, IMG_ARGB32 }, + { PIX_FMT_RGBA, IMG_RGBA32 }, + { PIX_FMT_RGB32_1, IMG_RGBA32 }, + { PIX_FMT_GRAY8, IMG_GRAY8 }, + { -1, -1}, +}; + +void yuv_convert_any_ac_packed( VJFrame *src, uint8_t *dst, int src_fmt, int dst_fmt ) +{ +#ifdef STRICT_CHECKING + assert( dst_fmt >= 0 && dst_fmt < 32 ); + assert( src_fmt == PIX_FMT_YUV420P || src_fmt == PIX_FMT_YUVJ420P || + src_fmt == PIX_FMT_YUV422P || src_fmt == PIX_FMT_YUVJ422P || + src_fmt == PIX_FMT_YUV444P || src_fmt == PIX_FMT_YUVJ444P || + src_fmt == PIX_FMT_RGB24 || src_fmt == PIX_FMT_RGBA || + src_fmt == PIX_FMT_BGR24 || src_fmt == PIX_FMT_RGB32 || + src_fmt == PIX_FMT_RGB32_1 || src_fmt == PIX_FMT_GRAY8 ); + assert( src->width > 0 ); +#endif + uint8_t *dst_planes[3] = { dst, NULL, NULL }; + if(!ac_imgconvert( src->data, ffmpeg_aclib[ src_fmt ], + dst_planes, ffmpeg_aclib[ dst_fmt] , src->width,src->height )) + { + veejay_msg(VEEJAY_MSG_WARNING, + "Unable to convert image %dx%d in %x to %dx%d in %x!", + src->width,src->height,src_fmt, + src->width,src->height,dst_fmt ); + yuv_pixstr( __FUNCTION__, "src_fmt", src_fmt ); + yuv_pixstr( __FUNCTION__, "dst_fmt", dst_fmt ); + + } +} + +void yuv_convert_any_ac( VJFrame *src, VJFrame *dst, int src_fmt, int dst_fmt ) +{ +#ifdef STRICT_CHECKING + assert( dst_fmt >= 0 && dst_fmt < 32 ); + assert( src_fmt == PIX_FMT_YUV420P || src_fmt == PIX_FMT_YUVJ420P || + src_fmt == PIX_FMT_YUV422P || src_fmt == PIX_FMT_YUVJ422P || + src_fmt == PIX_FMT_YUV444P || src_fmt == PIX_FMT_YUVJ444P || + src_fmt == PIX_FMT_RGB24 || src_fmt == PIX_FMT_RGBA || + src_fmt == PIX_FMT_YUYV422 || + src_fmt == PIX_FMT_BGR24 || src_fmt == PIX_FMT_RGB32 || + src_fmt == PIX_FMT_RGB32_1 || src_fmt == PIX_FMT_GRAY8 ); + assert( src->width > 0 ); + assert( dst->width > 0 ); +#endif + if(!ac_imgconvert( src->data, ffmpeg_aclib[ src_fmt ], + dst->data, ffmpeg_aclib[ dst_fmt] , dst->width,dst->height )) + { + veejay_msg(VEEJAY_MSG_WARNING, + "Unable to convert image %dx%d in %x to %dx%d in %x!", + src->width,src->height,src_fmt, + dst->width,dst->height,dst_fmt ); + yuv_pixstr( __FUNCTION__, "src_fmt", src_fmt ); + yuv_pixstr( __FUNCTION__, "dst_fmt", dst_fmt ); + + } + if( auto_conversion_ccir_jpeg_ ) + verify_CCIR_auto( src_fmt,dst_fmt, dst ); + +} +/* +void yuv_convert_any( VJFrame *src, VJFrame *dst, int src_fmt, int dst_fmt ) +{ + yuv_pixstr( __FUNCTION__, "src_fmt", src_fmt ); + yuv_pixstr( __FUNCTION__, "dst_fmt", dst_fmt ); + +#ifdef STRICT_CHECKING + assert( dst_fmt >= 0 && dst_fmt < 32 ); + assert( src_fmt == PIX_FMT_YUV420P || src_fmt == PIX_FMT_YUVJ420P || + src_fmt == PIX_FMT_YUV422P || src_fmt == PIX_FMT_YUVJ422P || + src_fmt == PIX_FMT_YUV444P || src_fmt == PIX_FMT_YUVJ444P || + src_fmt == PIX_FMT_RGB24 || src_fmt == PIX_FMT_RGBA || + src_fmt == PIX_FMT_BGR24 || src_fmt == PIX_FMT_RGB32 || + src_fmt == PIX_FMT_RGB32_1 || src_fmt == PIX_FMT_GRAY8 ); + assert( src->width > 0 ); + assert( dst->width > 0 ); +#endif + + struct SwsContext *ctx = sws_getContext( + src->width, + src->height, + src_fmt, + dst->width, + dst->height, + dst_fmt, + sws_context_flags_, + NULL,NULL,NULL ); + + sws_scale( ctx, src->data, src->stride,0, src->height,dst->data, dst->stride ); + + sws_freeContext( ctx ); +}*/ + +void *yuv_fx_context_create( VJFrame *src, VJFrame *dst, int src_fmt, int dst_fmt ) +{ + struct SwsContext *ctx = sws_getContext( src->width,src->height,src_fmt, dst->width,dst->height,dst_fmt, + sws_context_flags_, NULL,NULL,NULL ); + return (void*) ctx; +} + +void yuv_fx_context_process( void *ctx, VJFrame *src, VJFrame *dst ) +{ + sws_scale( ctx, src->data, src->stride,0,src->height,dst->data,dst->stride ); +} + +void yuv_fx_context_destroy( void *ctx ) +{ + struct SwsContext *stx = (struct SwsContext*) ctx; + sws_freeContext( stx ); +} + + +void yuv_convert_any3( VJFrame *src, int src_stride[3], VJFrame *dst, int src_fmt, int dst_fmt ) +{ +#ifdef STRICT_CHECKING + assert( dst_fmt >= 0 && dst_fmt < 32 ); + assert( src_fmt == PIX_FMT_YUV420P || src_fmt == PIX_FMT_YUVJ420P || + src_fmt == PIX_FMT_YUV422P || src_fmt == PIX_FMT_YUVJ422P || + src_fmt == PIX_FMT_YUV444P || src_fmt == PIX_FMT_YUVJ444P || + src_fmt == PIX_FMT_RGB24 || src_fmt == PIX_FMT_RGBA ); + assert( src_stride[0] > 0 ); + assert( dst->width > 0 ); + assert( dst->height > 0 ); + assert( dst->data[0] != NULL ); + assert( dst->data[1] != NULL ); + assert( dst->data[2] != NULL ); +#endif + struct SwsContext *ctx = sws_getContext( + src->width, + src->height, + src_fmt, + dst->width, + dst->height, + dst_fmt, + sws_context_flags_, + NULL,NULL,NULL ); + int dst_stride[3] = { ru4(dst->width),ru4(dst->uv_width),ru4(dst->uv_width) }; + + sws_scale( ctx, src->data, src_stride, 0, src->height, dst->data, dst_stride); + + sws_freeContext( ctx ); + +} + + +/* convert 4:2:0 to yuv 4:2:2 packed */ +void yuv422p_to_yuv422(uint8_t * yuv420[3], uint8_t * dest, int width, + int height) +{ + unsigned int x, y; + uint8_t *Cb = yuv420[1]; + uint8_t *Cr = yuv420[2]; + uint8_t *Y = yuv420[0]; + for (y = 0; y < height; ++y) { + for (x = 0; x < width; x +=2) { + *(dest + 0) = Y[0]; + *(dest + 1) = Cb[0]; + *(dest + 2) = Y[1]; + *(dest + 3) = Cr[0]; + dest += 4; + Y += 2; + ++Cb; + ++Cr; + } + Y += width; + Cb += (width>>1); + Cr += (height>>1); + } +} + + + +/* convert 4:2:0 to yuv 4:2:2 */ +void yuv420p_to_yuv422(uint8_t * yuv420[3], uint8_t * dest, int width, + int height) +{ + unsigned int x, y; + + + for (y = 0; y < height; ++y) { + uint8_t *Y = yuv420[0] + y * width; + uint8_t *Cb = yuv420[1] + (y >> 1) * (width >> 1); + uint8_t *Cr = yuv420[2] + (y >> 1) * (width >> 1); + for (x = 0; x < width; x += 2) { + *(dest + 0) = Y[0]; + *(dest + 1) = Cb[0]; + *(dest + 2) = Y[1]; + *(dest + 3) = Cr[0]; + dest += 4; + Y += 2; + ++Cb; + ++Cr; + } + } +} + +#ifdef HAVE_ASM_MMX +#include "mmx_macros.h" +#include "mmx.h" + +/***************************************************************** + + _yuv_yuv_mmx.c + + Copyright (c) 2001-2002 by Burkhard Plaum - plaum@ipf.uni-stuttgart.de + + http://gmerlin.sourceforge.net + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + + + - took yuy2 -> planar 422 and 422 planar -> yuy2 mmx conversion + routines. + (Niels, 02/2005) + +*****************************************************************/ + +static mmx_t mmx_00ffw = { 0x00ff00ff00ff00ffLL }; + +#ifdef HAVE_ASM_MMX2 +//#ifdef MMXEXT +#define MOVQ_R2M(reg,mem) movntq_r2m(reg, mem) +#else +#define MOVQ_R2M(reg,mem) movq_r2m(reg, mem) +#endif + +#define PLANAR_TO_YUY2 movq_m2r(*src_y, mm0);/* mm0: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */\ + movd_m2r(*src_u, mm1);/* mm1: 00 00 00 00 U6 U4 U2 U0 */\ + movd_m2r(*src_v, mm2);/* mm2: 00 00 00 00 V6 V4 V2 V0 */\ + pxor_r2r(mm3, mm3);/* Zero mm3 */\ + movq_r2r(mm0, mm7);/* mm7: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */\ + punpcklbw_r2r(mm3, mm0);/* mm0: 00 Y3 00 Y2 00 Y1 00 Y0 */\ + punpckhbw_r2r(mm3, mm7);/* mm7: 00 Y7 00 Y6 00 Y5 00 Y4 */\ + pxor_r2r(mm4, mm4); /* Zero mm4 */\ + punpcklbw_r2r(mm1, mm4);/* mm4: U6 00 U4 00 U2 00 U0 00 */\ + pxor_r2r(mm5, mm5); /* Zero mm5 */\ + punpcklbw_r2r(mm2, mm5);/* mm5: V6 00 V4 00 V2 00 V0 00 */\ + movq_r2r(mm4, mm6);/* mm6: U6 00 U4 00 U2 00 U0 00 */\ + punpcklwd_r2r(mm3, mm6);/* mm6: 00 00 U2 00 00 00 U0 00 */\ + por_r2r(mm6, mm0); /* mm0: 00 Y3 U2 Y2 00 Y1 U0 Y0 */\ + punpcklwd_r2r(mm3, mm4);/* mm4: 00 00 U6 00 00 00 U4 00 */\ + por_r2r(mm4, mm7); /* mm7: 00 Y7 U6 Y6 00 Y5 U4 Y4 */\ + pxor_r2r(mm6, mm6); /* Zero mm6 */\ + punpcklwd_r2r(mm5, mm6);/* mm6: V2 00 00 00 V0 00 00 00 */\ + por_r2r(mm6, mm0); /* mm0: V2 Y3 U2 Y2 V0 Y1 U0 Y0 */\ + punpckhwd_r2r(mm5, mm3);/* mm3: V6 00 00 00 V4 00 00 00 */\ + por_r2r(mm3, mm7); /* mm7: V6 Y7 U6 Y6 V4 Y5 U4 Y4 */\ + MOVQ_R2M(mm0, *dst);\ + MOVQ_R2M(mm7, *(dst+8)); + + +#define YUY2_TO_YUV_PLANAR movq_m2r(*src,mm0);\ + movq_m2r(*(src+8),mm1);\ + movq_r2r(mm0,mm2);/* mm2: V2 Y3 U2 Y2 V0 Y1 U0 Y0 */\ + pand_m2r(mmx_00ffw,mm2);/* mm2: 00 Y3 00 Y2 00 Y1 00 Y0 */\ + pxor_r2r(mm4, mm4);/* Zero mm4 */\ + packuswb_r2r(mm4,mm2);/* mm2: 00 00 00 00 Y3 Y2 Y1 Y0 */\ + movq_r2r(mm1,mm3);/* mm3: V6 Y7 U6 Y6 V4 Y5 U4 Y4 */\ + pand_m2r(mmx_00ffw,mm3);/* mm3: 00 Y7 00 Y6 00 Y5 00 Y4 */\ + pxor_r2r(mm6, mm6);/* Zero mm6 */\ + packuswb_r2r(mm3,mm6);/* mm6: Y7 Y6 Y5 Y4 00 00 00 00 */\ + por_r2r(mm2,mm6);/* mm6: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 */\ + psrlw_i2r(8,mm0);/* mm0: 00 V2 00 U2 00 V0 00 U0 */\ + psrlw_i2r(8,mm1);/* mm1: 00 V6 00 U6 00 V4 00 U4 */\ + packuswb_r2r(mm1,mm0);/* mm0: V6 U6 V4 U4 V2 U2 V0 U0 */\ + movq_r2r(mm0,mm1);/* mm1: V6 U6 V4 U4 V2 U2 V0 U0 */\ + pand_m2r(mmx_00ffw,mm0);/* mm0: 00 U6 00 U4 00 U2 00 U0 */\ + psrlw_i2r(8,mm1);/* mm1: 00 V6 00 V4 00 V2 00 V0 */\ + packuswb_r2r(mm4,mm0);/* mm0: 00 00 00 00 U6 U4 U2 U0 */\ + packuswb_r2r(mm4,mm1);/* mm1: 00 00 00 00 V6 V4 V2 V0 */\ + MOVQ_R2M(mm6, *dst_y);\ + movd_r2m(mm0, *dst_u);\ + movd_r2m(mm1, *dst_v); + +#define MMX_YUV422_YUYV " \n\ +movq (%1), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\ +movd (%2), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\ +movd (%3), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\ +punpcklbw %%mm2, %%mm1 # v3 u3 v2 u2 v1 u1 v0 u0 \n\ +movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\ +punpcklbw %%mm1, %%mm2 # v1 y3 u1 y2 v0 y1 u0 y0 \n\ +movq %%mm2, (%0) # Store low YUYV \n\ +punpckhbw %%mm1, %%mm0 # v3 y7 u3 y6 v2 y5 u2 y4 \n\ +movq %%mm0, 8(%0) # Store high YUYV \n\ +" + + +void yuv422_to_yuyv(uint8_t *src[3], uint8_t *dstI, int w, int h) +{ + int j,jmax,imax,i; + uint8_t *dst = dstI; + uint8_t *src_y = src[0]; + uint8_t *src_u = src[1]; + uint8_t *src_v = src[2]; + + jmax = w >> 3; + imax = h; + + for( i = imax; i-- ; ) + { + for( j = jmax ; j -- ; ) + { + /* __asm__( ".align 8" MMX_YUV422_YUYV + : : "r" (dst), "r" (src_y), "r" (src_u), + "r" (src_v) ); + */ + __asm__( ".p2align 3" MMX_YUV422_YUYV + : : "r" (dst), "r" (src_y), "r" (src_u), "r" (src_v) ); + + dst += 16; + src_y += 8; + src_u += 4; + src_v += 4; + } + } +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif +} + + +void yuy2toyv16(uint8_t *dst_y, uint8_t *dst_u, uint8_t *dst_v, uint8_t *srcI, int w, int h ) +{ + int j,jmax,imax,i; + uint8_t *src = srcI; + + jmax = w / 8; + imax = h; + + for( i = 0; i < imax ;i ++ ) + { + for( j = 0; j < jmax ; j ++ ) + { + YUY2_TO_YUV_PLANAR; + src += 16; + dst_y += 8; + dst_u += 4; + dst_v += 4; + } + } +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif +} + +void vj_yuy2toyv12(uint8_t * _y, uint8_t * _u, uint8_t * _v, uint8_t * input, + int width, int height) +{ + int j,jmax,imax,i; + uint8_t *src = input; + uint8_t *dst_y = _y; + uint8_t *dst_u = _u; + uint8_t *dst_v = _v; + jmax = width / 8; + imax = height; + + for( i = 0; i < imax ;i ++ ) + { + for( j = 0; j < jmax ; j ++ ) + { + YUY2_TO_YUV_PLANAR; + src += 16; + dst_y += 8; + dst_u += 4; + dst_v += 4; + } + dst_u += width; + dst_v += width; + } +#ifdef HAVE_ASM_MMX + __asm__ __volatile__ ( _EMMS:::"memory"); +#endif +} +#else +// non mmx functions + +void vj_yuy2toyv12(uint8_t * _y, uint8_t * _u, uint8_t * _v, uint8_t * input, + int width, int height) +{ + int i, j, w2; + uint8_t *y, *u, *v; + + w2 = width / 2; + + //I420 + y = _y; + v = _v; + u = _u; + + for (i = 0; i < height; i += 4) { + /* top field scanline */ + for (j = 0; j < w2; j++) { + /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */ + *(y++) = *(input++); + *(u++) = *(input++); + *(y++) = *(input++); + *(v++) = *(input++); + } + for (j = 0; j < w2; j++) + { + *(y++) = *(input++); + *(u++) = *(input++); + *(y++) = *(input++); + *(v++) = *(input++); + + } + + /* next two scanlines, one frome each field , interleaved */ + for (j = 0; j < w2; j++) { + /* skip every second line for U and V */ + *(y++) = *(input++); + input++; + *(y++) = *(input++); + input++; + } + /* bottom field scanline*/ + for (j = 0; j < w2; j++) { + /* skip every second line for U and V */ + *(y++) = *(input++); + input++; + *(y++) = *(input++); + input++; + } + + } +} + +void yuy2toyv16(uint8_t * _y, uint8_t * _u, uint8_t * _v, uint8_t * input, + int width, int height) +{ + + int i, j, w2; + uint8_t *y, *u, *v; + + w2 = width / 2; + + //YV16 + y = _y; + v = _v; + u = _u; + + for (i = 0; i < height; i ++ ) + { + for (j = 0; j < w2; j++) { + /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */ + *(y++) = *(input++); + *(u++) = *(input++); + *(y++) = *(input++); + *(v++) = *(input++); + } + } +} + +void yuv422_to_yuyv(uint8_t *yuv422[3], uint8_t *pixels, int w, int h) +{ + int x,y; + uint8_t *Y = yuv422[0]; + uint8_t *U = yuv422[1]; + uint8_t *V = yuv422[2]; // U Y V Y + for(y = 0; y < h; y ++ ) + { + Y = yuv422[0] + y * w; + U = yuv422[1] + (y>>1) * w; + V = yuv422[2] + (y>>1) * w; + for( x = 0 ; x < w ; x += 4 ) + { + *(pixels + 0) = Y[0]; + *(pixels + 1) = U[0]; + *(pixels + 2) = Y[1]; + *(pixels + 3) = V[0]; + *(pixels + 4) = Y[2]; + *(pixels + 5) = U[1]; + *(pixels + 6) = Y[3]; + *(pixels + 7) = V[1]; + pixels += 8; + Y+=4; + U+=2; + V+=2; + } + } +} + +#endif + + +/* lav_common - some general utility functionality used by multiple + lavtool utilities. */ + +/* Copyright (C) 2000, Rainer Johanni, Andrew Stevens */ +/* - added scene change detection code 2001, pHilipp Zabel */ +/* - broke some code out to lav_common.h and lav_common.c + * July 2001, Shawn Sulma . In doing this, + * I replaced the large number of globals with a handful of structs + * that are passed into the appropriate methods. Check lav_common.h + * for the structs. I'm sure some of what I've done is inefficient, + * subtly incorrect or just plain Wrong. Feedback is welcome. + */ + + +int luminance_mean(uint8_t * frame[], int w, int h) +{ + uint8_t *p; + uint8_t *lim; + int sum = 0; + int count = 0; + p = frame[0]; + lim = frame[0] + w * (h - 1); + while (p < lim) { + sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); + p += 31; + count += 4; + } + + w = w / 2; + h = h / 2; + + p = frame[1]; + lim = frame[1] + w * (h - 1); + while (p < lim) { + sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); + p += 31; + count += 4; + } + p = frame[2]; + lim = frame[2] + w * (h - 1); + while (p < lim) { + sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); + p += 31; + count += 4; + } + return sum / count; +} + +typedef struct +{ + struct SwsContext *sws; + SwsFilter *src_filter; + SwsFilter *dst_filter; +} vj_sws; + +void* yuv_init_swscaler(VJFrame *src, VJFrame *dst, sws_template *tmpl, int cpu_flagss) +{ + vj_sws *s = (vj_sws*) vj_malloc(sizeof(vj_sws)); + if(!s) + return NULL; + + int sws_type = 0; + + veejay_memset( s, 0, sizeof(vj_sws) ); + + int cpu_flags = 0; +#ifdef STRICT_CHECKING + cpu_flags = cpu_flags | SWS_PRINT_INFO; +#endif + +#ifdef HAVE_ASM_MMX + cpu_flags = cpu_flags | SWS_CPU_CAPS_MMX; +#endif +//#ifdef HAVE_ASM_3DNOW +// cpu_flags = cpu_flags | SWS_CPU_CAPS_3DNOW; +//#endif +//#ifdef HAVE_ASM_MMX2 +// cpu_flags = cpu_flags | SWS_CPU_CAPS_MMX2; +//#endif +//#ifdef HAVE_ALTIVEC +// cpu_flags = cpu_flags | SWS_CPU_CAPS_ALTIVEC; +//#endif + switch(tmpl->flags) + { + case 1: + cpu_flags = cpu_flags|SWS_FAST_BILINEAR; + break; + case 2: + cpu_flags = cpu_flags|SWS_BILINEAR; + break; + case 4: + cpu_flags = cpu_flags|SWS_BICUBIC; + break; + case 3: + cpu_flags = cpu_flags |SWS_POINT; + break; + case 5: + cpu_flags = cpu_flags|SWS_X; + break; + case 6: + cpu_flags = cpu_flags | SWS_AREA; + break; + case 7: + cpu_flags = cpu_flags | SWS_BICUBLIN; + break; + case 8: + cpu_flags = cpu_flags | SWS_GAUSS; + break; + case 9: + cpu_flags = cpu_flags | SWS_SINC; + break; + case 10: + cpu_flags = cpu_flags |SWS_LANCZOS; + break; + case 11: + cpu_flags = cpu_flags | SWS_SPLINE; + break; + } + + if( full_chroma_interpolation_ ) + cpu_flags = cpu_flags | SWS_FULL_CHR_H_INT; + + s->sws = sws_getContext( + src->width, + src->height, + src->format, + dst->width, + dst->height, + dst->format, + cpu_flags, + s->src_filter, + s->dst_filter, + NULL + ); + + if(!s->sws) + { + veejay_msg(0,"sws_getContext failed."); + if(s)free(s); + return NULL; + } + + return ((void*)s); + +} + +void yuv_crop(VJFrame *src, VJFrame *dst, VJRectangle *rect ) +{ + int x; + int y; + uint8_t *sy = src->data[0]; + uint8_t *su = src->data[1]; + uint8_t *sv = src->data[2]; + + uint8_t *dstY = dst->data[0]; + uint8_t *dstU = dst->data[1]; + uint8_t *dstV = dst->data[2]; + int i = 0; + + for( i = 0 ; i < 3 ; i ++ ) + { + int j = 0; + uint8_t *srcPlane = src->data[i]; + uint8_t *dstPlane = dst->data[i]; + for( y = rect->top ; y < ( src->height - rect->bottom ); y ++ ) + { + for ( x = rect->left ; x < ( src->width - rect->right ); x ++ ) + { + dstPlane[j] = srcPlane[ y * src->width + x ]; + j++; + } + } + } + +} + +VJFrame *yuv_allocate_crop_image( VJFrame *src, VJRectangle *rect ) +{ + int w = src->width - rect->left - rect->right; + int h = src->height - rect->top - rect->bottom; + + if( w <= 0 ) + return NULL; + if( h <= 0 ) + return NULL; + + VJFrame *new = (VJFrame*) vj_malloc(sizeof(VJFrame)); + if(!new) + return NULL; + + new->width = w; + new->height = h; + new->uv_len = (w >> src->shift_h) * (h >> src->shift_v ); + new->len = w * h; + new->uv_width = (w >> src->shift_h ); + new->uv_height = (h >> src->shift_v ); + new->shift_v = src->shift_v; + new->shift_h = src->shift_h; + + return new; +} + + +void yuv_free_swscaler(void *sws) +{ + if(sws) + { + vj_sws *s = (vj_sws*) sws; + if(s->sws) + sws_freeContext( s->sws ); + if(s) free(s); + } +} + +void yuv_convert_and_scale_gray_rgb(void *sws,VJFrame *src, VJFrame *dst) +{ + vj_sws *s = (vj_sws*) sws; + int src_stride[3] = { src->width,0,0 }; + int dst_stride[3] = { src->width * 3, 0,0 }; + + sws_scale( s->sws, src->data,src_stride, 0,src->height, + dst->data, dst_stride ); +} +void yuv_convert_and_scale_from_rgb(void *sws , VJFrame *src, VJFrame *dst) +{ + vj_sws *s = (vj_sws*) sws; + int src_stride[3] = { src->width*3,0,0}; + int dst_stride[3] = { dst->width,dst->uv_width,dst->uv_width }; + + sws_scale( s->sws, src->data, src_stride, 0, src->height, + dst->data, dst_stride ); +} + +void yuv_convert_and_scale_rgb(void *sws , VJFrame *src, VJFrame *dst) +{ + vj_sws *s = (vj_sws*) sws; + int src_stride[3] = { src->width,src->uv_width,src->uv_width }; + int dst_stride[3] = { dst->width*3,0,0 }; + + sws_scale( s->sws, src->data, src_stride, 0, src->height, + dst->data, dst_stride ); +} +void yuv_convert_and_scale(void *sws , VJFrame *src, VJFrame *dst) +{ + vj_sws *s = (vj_sws*) sws; + int src_stride[3] = { src->width,src->uv_width,src->uv_width }; + int dst_stride[3] = { dst->width,dst->uv_width,dst->uv_width }; + + sws_scale( s->sws, src->data, src_stride, 0, src->height, + dst->data, dst_stride ); +} +void yuv_convert_and_scale_grey(void *sws , VJFrame *src, VJFrame *dst) +{ + vj_sws *s = (vj_sws*) sws; + int src_stride[3] = { src->width,0,0 }; + int dst_stride[3] = { dst->width,0,0 }; + + sws_scale( s->sws, src->data, src_stride, 0, src->height, + dst->data, dst_stride ); +} +void yuv_convert_and_scale_packed(void *sws , VJFrame *src, VJFrame *dst) +{ + vj_sws *s = (vj_sws*) sws; + int src_stride[3] = { src->width,src->uv_width,src->uv_width }; + int dst_stride[3] = { dst->width * 2,0,0 }; + + sws_scale( s->sws, src->data, src_stride, 0, src->height, + dst->data, dst_stride ); +} + +int yuv_sws_get_cpu_flags(void) +{ + int cpu_flags = 0; +#ifdef HAVE_ASM_MMX + cpu_flags = cpu_flags | SWS_CPU_CAPS_MMX; +#endif +#ifdef HAVE_ASM_3DNOW + cpu_flags = cpu_flags | SWS_CPU_CAPS_3DNOW; +#endif +#ifdef HAVE_ASM_MMX2 + cpu_flags = cpu_flags | SWS_CPU_CAPS_MMX2; +#endif +#ifdef HAVE_ALTIVEC + cpu_flags = cpu_flags | SWS_CPU_CAPS_ALTIVEC; +#endif + + cpu_flags = cpu_flags | SWS_FAST_BILINEAR; + + return cpu_flags; +} + +void yuv_deinterlace( + uint8_t *data[3], + const int width, + const int height, + int out_pix_fmt, + int shift, + uint8_t *Y,uint8_t *U, uint8_t *V ) +{ + AVPicture p,q; + p.data[0] = data[0]; + p.data[1] = data[1]; + p.data[2] = data[2]; + p.linesize[0] = width; + p.linesize[1] = width >> shift; + p.linesize[2] = width >> shift; + q.data[0] = Y; + q.data[1] = U; + q.data[2] = V; + q.linesize[0] = width; + q.linesize[1] = width >> shift; + q.linesize[2] = width >> shift; + avpicture_deinterlace( &p,&q, out_pix_fmt, width, height ); +} + + +void rgb_deinterlace( + uint8_t *data[3], + const int width, + const int height, + int out_pix_fmt, + int shift, + uint8_t *R,uint8_t *G, uint8_t *B ) +{ + AVPicture p,q; + p.data[0] = data[0]; + p.data[1] = data[1]; + p.data[2] = data[2]; + p.linesize[0] = width * 3; + p.linesize[1] = 0; + p.linesize[2] = 0; + q.data[0] = R; + q.data[1] = G; + q.data[2] = B; + q.linesize[0] = width; + q.linesize[1] = 0; + q.linesize[2] = 0; + avpicture_deinterlace( &p,&q, out_pix_fmt, width, height ); +} + + +static struct +{ + int i; + const char *name; +} sws_scaler_types[] = +{ + { 1, "Fast bilinear (default)" }, + { 2, "Bilinear" }, + { 3, "Bicubic" }, + { 4, "Nearest neighbour"}, + { 5, "Experimental"}, + { 6, "Area"}, + { 7, "Linear bicubic"}, + { 8, "Gaussian"}, + { 9, "Sinc"}, + { 10, "Lanzcos"}, + { 11, "Natural bicubic spline"}, + { 0, NULL } +}; + +const char *yuv_get_scaler_name(int id) +{ + int i; + for( i = 0; sws_scaler_types[i].i != 0 ; i ++ ) + if( id == sws_scaler_types[i].i ) + return sws_scaler_types[i].name; + return NULL; +} + +void yuv422to420planar( uint8_t *src[3], uint8_t *dst[3], int w, int h ) +{ + unsigned int x,y,k=0; + const int hei = h >> 1; + const int wid = w >> 1; + uint8_t *u = dst[1]; + uint8_t *v = dst[2]; + uint8_t *a = src[1]; + uint8_t *b = src[2]; + for( y = 0 ; y < hei; y ++ ) { + for( x= 0; x < wid ; x ++ ) { + u[k] = a[ (y<<1) * wid + x ]; //@ drop left chroma + v[k] = b[ (y<<1) * wid + x ]; + k++; + } + } +} +#ifndef HAVE_ASM_MMX +void yuv420to422planar( uint8_t *src[3], uint8_t *dst[3], int w, int h ) +{ + unsigned int x,y; + unsigned int k=0; + const int hei = h >> 1; + const int wid = w >> 1; + uint8_t *u = dst[1]; + uint8_t *v = dst[2]; + uint8_t *a = src[1]; + uint8_t *b = src[2]; + for( y = 0 ; y < hei; y ++ ) { + u = dst[1] + ( (y << 1 ) * wid ); //@ dup + v = dst[2] + ( (y << 1 ) * wid ); + for( x= 0; x < wid ; x ++ ) { + u[k] = a[ y * wid + x]; + u[k + wid ] = a[y*wid+x]; + v[k] = b[ y * wid + x]; + v[k + wid ] = b[y * wid + x ]; + } + } +} +#else +static inline copy8( uint8_t *to, uint8_t *to2, uint8_t *from ) { + __asm__ __volatile__ ( + "movq (%0), %%mm0\n" + "movq %%mm0, (%1)\n" + "movq %%mm0, (%2)\n" + :: "r" (from), "r" (to) , "r" (to2) : "memory" + ); +} + +void yuv420to422planar( uint8_t *src[3], uint8_t *dst[3], int w, int h ) +{ + unsigned int x,y; + const int hei = (h >> 1); + const int work = (w >> 1) / 8; + const int wid = w >> 1; + uint8_t *u = dst[1]; + uint8_t *v = dst[2]; + uint8_t *a = src[1]; + uint8_t *b = src[2]; + uint8_t *u2 = dst[1]; + uint8_t *v2 = dst[2]; + for( y = 0; y < hei; y ++ ) { + u = dst[1] + ( (y << 1 ) * wid ); + u2 = dst[1] + (( (y+1)<<1) * wid); + a = src[1] + ( y * wid ); + for( x = 0; x < work; x ++ ) { + copy8( u,u2, a ); + u += 8; + u2 += 8; + a += 8; + } + } + for( y = 0; y < hei; y ++ ) { + v = dst[2] + ( (y << 1 ) * wid ); + v2 = dst[2] + (( (y+1)<<1) * wid ); + b = src[2] + ( y * wid ); + for( x = 0; x < work; x ++ ) { + copy8( v,v2, b ); + v += 8; + v2 += 8; + b += 8; + } + } + __asm__ __volatile__ ( _EMMS:::"memory"); +} +#endif + +void yuy2_scale_pixels_from_yuv( uint8_t *plane, int len ) +{ + unsigned int rlen = 2 * len ; + unsigned int i; + for( i = 0; i < rlen; i += 4 ) { + plane[i+0] = jpeg_to_CCIR_tableY[ plane[i+0] ]; + plane[i+1] = jpeg_to_CCIR_tableUV[plane[i+1] ]; + plane[i+2] = jpeg_to_CCIR_tableY[ plane[i+2] ]; + plane[i+3] = jpeg_to_CCIR_tableUV[ plane[i+3] ]; + } +} + +void yuy2_scale_pixels_from_ycbcr( uint8_t *plane, int len ) +{ + unsigned int rlen = 2 * len ; + unsigned int i; + for( i = 0; i < rlen; i += 4 ) { + plane[i+0] = CCIR_to_jpeg_tableY[ plane[i+0] ]; + plane[i+1] = CCIR_to_jpeg_tableUV[plane[i+1] ]; + plane[i+2] = CCIR_to_jpeg_tableY[ plane[i+2] ]; + plane[i+3] = CCIR_to_jpeg_tableUV[ plane[i+3] ]; + } +} + +void yuv_scale_pixels_from_yuv( uint8_t *src[3], uint8_t *dst[3], int len ) +{ + unsigned int i; + uint8_t *y = src[0]; + uint8_t *u = src[1]; + uint8_t *v = src[2]; + uint8_t *dY = dst[0]; + uint8_t *dU = dst[1]; + uint8_t *dV = dst[2]; + for( i = 0; i < len ; i ++ ) { + dY[i] = jpeg_to_CCIR_tableY[ y[i] ]; + } + len = len / 2; + for( i = 0; i < len ; i ++ ) { + dU[i] = jpeg_to_CCIR_tableUV[ u[i] ]; + dV[i] = jpeg_to_CCIR_tableUV[ v[i] ]; + } +} + +void yuv_scale_pixels_from_y( uint8_t *plane, int len ) +{ + unsigned int i; +// float s = (max - min) / 255.0f; + + for( i = 0; i < len ; i ++ ) { + plane[i] = jpeg_to_CCIR_tableY[ plane[i] ]; + } +} +void yuv_scale_pixels_from_uv( uint8_t *plane, int len ) +{ + unsigned int i; +// float s = (max - min) / 255.0f; + + for( i = 0; i < len ; i ++ ) { + plane[i] = jpeg_to_CCIR_tableUV[ plane[i] ]; + } +} + + +void yuv_scale_pixels_from_ycbcr( uint8_t *plane, float min, float max, int len ) +{ + unsigned int i; +// float s = 255.0f / ( max-min ); + + if( max == 235.0f ) { + for( i = 0; i < len ; i ++ ) { +/* float res = ( (float) plane[i] * s - 16.0f ); + if( res > 255.0f ) + res = 255.0f; + else if ( res < 0.0f ) + res = 0.0f; + plane[i] = (uint8_t) res;*/ + plane[i] = CCIR_to_jpeg_tableY[ plane[i] ]; + } + } else if ( max == 240.0f ) { + for( i = 0; i < len ; i ++ ) { + plane[i] = CCIR_to_jpeg_tableUV[ plane[i] ]; + } + } +} +void yuv_scale_pixels_from_ycbcr2( uint8_t *plane[3], uint8_t *dst[3], int len ) +{ + unsigned int i; + uint8_t *y = plane[0]; + uint8_t *u = plane[1]; + uint8_t *v = plane[2]; + uint8_t *dy = dst[0]; + uint8_t *du = dst[1]; + uint8_t *dv = dst[2]; + for( i = 0; i < len ; i ++ ) { + dy[i] = CCIR_to_jpeg_tableY[ y[i] ]; + } + + len = len / 2; + for( i = 0; i < len ; i ++ ) { + du[i] = CCIR_to_jpeg_tableUV[ u[i] ]; + dv[i] = CCIR_to_jpeg_tableUV[ v[i] ]; + } +} + + +#define packv0__( y0,u0,v0,y1 ) (( (int) y0 ) & 0xff ) +\ + ( (((int) u0 ) & 0xff) << 8) +\ + ( ((((int) v0) & 0xff) << 16 )) +\ + ( ((((int) y1) & 0xff) << 24 ) ) + +#define packv1__( u1,v1,y2,u2 )(( (int) u1 ) & 0xff ) +\ + ( (((int) v1 ) & 0xff) << 8) +\ + ( ((((int) y2) & 0xff) << 16 )) +\ + ( ((((int) u2) & 0xff) << 24 ) ) + + +#define packv2__( v2,y3,u3,v3 )(( (int) v2 ) & 0xff ) +\ + ( (((int) y3 ) & 0xff) << 8) +\ + ( ((((int) u3) & 0xff) << 16 )) +\ + ( ((((int) v3) & 0xff) << 24 ) ) + +//! YUV 4:2:4 Planar to 4:4:4 Packed: Y, V, U, Y,V, U , .... */ +void yuv444_yvu444_1plane( + uint8_t *data[3], + const int width, + const int height, + uint8_t *dst_buffer) +{ + unsigned int x; + uint8_t *yp = data[0]; + uint8_t *up = data[2]; + uint8_t *vp = data[1]; + int len = (width * height) / 4; + uint8_t *dst = dst_buffer; + + __builtin_prefetch( yp, 0 ,3); + __builtin_prefetch( up, 0 ,3); + __builtin_prefetch( vp, 0 ,3); + __builtin_prefetch( dst, 1,3); + + for( x=0; x < len; x ++ ) + { + dst[0] = packv0__( yp[0],up[0],vp[0],yp[1]); + dst[1] = packv1__( up[1],vp[1],yp[2],up[2]); + dst[2] = packv2__( vp[2],yp[3],up[3],vp[3]); + + yp += 4; + up += 4; + vp += 4; + dst += 3; + } + +} + diff --git a/branches/V-1.5.3/veejay-server/libyuv/yuvconv.h b/branches/V-1.5.3/veejay-server/libyuv/yuvconv.h new file mode 100644 index 00000000..90b1a4ad --- /dev/null +++ b/branches/V-1.5.3/veejay-server/libyuv/yuvconv.h @@ -0,0 +1,159 @@ +#ifndef YUVCONF_H +#define YUVCONF_H +/* Veejay - A visual instrument and realtime video sampler + * Copyright (C) 2004 Niels Elburg + * + * YUV library for veejay. + * + * Mjpegtools, (C) The Mjpegtools Development Team (http://mjpeg.sourceforge.net) + * Copyright (C) 2001 Matthew J. Marjanovic + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +typedef enum subsample_mode { + SSM_UNKNOWN = 0, + SSM_420_JPEG_TR = 1, + SSM_420_JPEG_BOX = 2, + SSM_420_MPEG2 = 3, + SSM_422_444 = 4, + SSM_420_422 = 5, + SSM_COUNT = 6, +} subsample_mode_t; + +extern const char *ssm_id[SSM_COUNT]; +extern const char *ssm_description[SSM_COUNT]; + +void *subsample_init(int buf_len); +void subsample_free(void *sampler); + +void chroma_subsample(subsample_mode_t mode, void *sampler, uint8_t * ycbcr[], + int width, int height); +void chroma_subsample_cp(subsample_mode_t mode, void *data, uint8_t *ycbcr[], uint8_t *dcbcr[], + int width, int height); + +void chroma_supersample(subsample_mode_t mode, void *sampler, uint8_t * ycbcr[], + int width, int height); + +// yuv 4:2:2 packed to yuv 4:2:0 planar +void vj_yuy2toyv12( uint8_t *y, uint8_t *u, uint8_t *v, uint8_t *in, int w, int h); +// yuv 4:2:2 packet to yuv 4:2:2 planar +void yuy2toyv16( uint8_t *y, uint8_t *u, uint8_t *v, uint8_t *in, int w, int h); +// yuv 4:2:2 planar to yuv 4:2:2 packed +void yuv422p_to_yuv422( uint8_t *yuv422[3], uint8_t *dst, int w, int h ); + +// yuv 4:2:2 planar to yuv 4:2:0 planar +void yuv420p_to_yuv422( uint8_t *yuv420[3], uint8_t *dst, int w, int h ); + +// yuv 4:2:2 planar to YUYV +void yuv422_to_yuyv( uint8_t *yuv422[3], uint8_t *dst, int w, int h ); + +// scene detection +int luminance_mean(uint8_t * frame[], int w, int h); + +/* software scaler from ffmpeg project: */ + +typedef struct +{ + float lumaGBlur; + float chromaGBlur; + float lumaSarpen; + float chromaSharpen; + float chromaHShift; + float chromaVShift; + int verbose; + int flags; + int use_filter; +} sws_template; + +void yuv_init_lib(int sws_extra_flags, int auto_jpeg_ccir, int scaler_type); + +void* yuv_init_swscaler(VJFrame *src, VJFrame *dst, sws_template *templ, int cpu_flags); +void yuv_convert_and_scale_packed( void *sws, VJFrame *src, VJFrame *dst ); + +void yuv_convert_and_scale( void *sws, VJFrame *src, VJFrame *dst ); + +void yuv_convert_and_scale_rgb( void *sws, VJFrame *src, VJFrame *dst ); + +void yuv_convert_and_scale_gray_rgb(void *sws,VJFrame *src, VJFrame *dst); +void yuv_convert_and_scale_from_rgb(void *sws , VJFrame *src, VJFrame *dst); +void yuv_convert_and_scale_grey(void *sws , VJFrame *src, VJFrame *dst); + +int yuv_sws_get_cpu_flags(void); + +void yuv_free_swscaler(void *sws); + +void yuv_crop(VJFrame *src, VJFrame *dst, VJRectangle *rect ); + +VJFrame *yuv_allocate_crop_image( VJFrame *src, VJRectangle *rect ); + +void yuv_deinterlace( + uint8_t *data[3], + const int width, + const int height, + int out_pix_fmt, + int shift, + uint8_t *Y,uint8_t *U, uint8_t *V ); + + +void yuv_init_lib(); + +void yuv_free_lib(); + +void yuv_convert_ac( VJFrame *src, VJFrame *dst, int a, int b ); + +//void yuv_convert_any( VJFrame *src, VJFrame *dst, int a, int b ); + + +void yuv_convert_any_ac_packed( VJFrame *src, uint8_t *dst, int src_fmt, int dst_fmt ); + +void yuv_convert_any3( VJFrame *src,int strides[], VJFrame *dst, int a, int b ); + + +VJFrame *yuv_rgb_template( uint8_t *rgb_buffer, int w, int h, int fmt ); + +VJFrame *yuv_yuv_template( uint8_t *Y, uint8_t *U, uint8_t *V, int w, int h, int fmt ); + +const char *yuv_get_scaler_name(int id); + +void yuv_convert_any_ac( VJFrame *src, VJFrame *dst, int src_fmt, int dst_fmt ); + +void *yuv_fx_context_create( VJFrame *src, VJFrame *dst, int src_fmt, int dst_fmt ); + +void yuv_fx_context_process( void *ctx, VJFrame *src, VJFrame *dst ); + +void yuv_fx_context_destroy( void *ctx ); + + +void yuv420to422planar( uint8_t *src[3], uint8_t *dst[3], int w, int h ); +void yuv422to420planar( uint8_t *src[3], uint8_t *dst[3], int w, int h ); + +void yuv_scale_pixels_from_yuv( uint8_t *src[3], uint8_t *dst[3], int len ); + +void yuv_scale_pixels_from_y( uint8_t *plane, int len ); +void yuv_scale_pixels_from_uv( uint8_t *plane, int len ); +void yuv_scale_pixels_from_ycbcr( uint8_t *plane, float min, float max, int len ); +int yuv_use_auto_ccir_jpeg(); + +void yuy2_scale_pixels_from_yuv( uint8_t *plane, int len ); +void yuy2_scale_pixels_from_ycbcr( uint8_t *plane, int len ); +void yuv_scale_pixels_from_ycbcr2( uint8_t *plane[3], uint8_t *dst[3], int len ); +void yuv444_yvu444_1plane( + uint8_t *data[3], + const int width, + const int height, + uint8_t *dst_buffer); + +#endif diff --git a/branches/V-1.5.3/veejay-server/man/Makefile.am b/branches/V-1.5.3/veejay-server/man/Makefile.am new file mode 100644 index 00000000..78c6e812 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/man/Makefile.am @@ -0,0 +1,3 @@ +man_MANS = veejay.1 +EXTRA_DIST = veejay.1 +MAINTAINERCLEANFILES = Makefile.in diff --git a/branches/V-1.5.3/veejay-server/man/veejay.1 b/branches/V-1.5.3/veejay-server/man/veejay.1 new file mode 100644 index 00000000..2f4eb419 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/man/veejay.1 @@ -0,0 +1,550 @@ +.TH "veejay" 1 +.SH NAME +veejay - a visual (video) instrument and video sampler for GNU/Linux +.SH SYNOPSIS +.B veejay [options] Videofile1 [Videofile2 ... VideofileN] +.SH DESCRIPTION +.B veejay +Veejay is a visual instrument and realtime video sampler. It allos you +to "play" the video like you would play a Piano. +While playing, you can record the resulting video directly to disk (video sampling). Veejay keeps audio in sync and pitches when needed through trickplay (slow , faster, reverse, loop ) and delivered to JACK for possible further processing. + +Veejay can be operated live by using the keyboard (which is 100% user definable) +and remotely over network (both unicast and multicast) using an inhouse message +system that allows mapping of various protocols on top of it, including OSC. + +Veejay is beeing developed in the hope it will be usefull for VJ's , media artists +theathers and other interested users that want to use Free Software for their +performances and/or video installations. + +.TP +.SH Supported video codecs/formats +.TP + +.TP +MJPEG AVI / Quicktime +.TP +Lossless JPEG AVI +.TP +MJPEG-b AVI / Quicktime +.TP +Quasar DV codec (NTSC/PAL) AVI / Quicktime +.TP +YUV4MPEG (chroma 4:2:0 jpeg/mpeg2, chroma 4:2:2) AVI / Y4M +.TP +RAW YUV 4:2:2 planar JPEG/JFIF (sample range 0-255,8 bit, 3 planes) +.TP +RAW YUV 4:2:2 planar Rec. 601 (Y’CbCr) (sample range 16-235 Y, 16-240 UV, 8 bit, 3 planes) +.TP +MLZO (YUV 4:2:2 planar compressed with OberHumer's LZO real-time data compression library) +.TP +.SH Supported video containers +AVI , QuickTime, DVVideo +.TP +.SH Audio +.TP +Veejay uses Jack , a low latency audio server, to transport (playback) audio in sync with video. This allows you to process veejay's audio output in another sound processing application. +.TP +.SH General Usage (How to work with veejay) +.TP +Veejay has a console- and a video window ; the console is used for displaying messages only. If the mouse is moved over to the video window, you can use the keyboard like a piano to play/manipulate the video. +.TP +You can start veejay with multiple files , video files and/or Mjpegtools' EditList files. Upon startup, veejay creates a new EditList in memory containing all the files you have loaded. As a result, all files will appear as a single large video file.Next you can start making selections (samples) of your EditList. These samples will be placed in so called 'sample banks' and they can be triggered for playback by pressing the F-keys (1 to 12). You can select a bank by pressing a number 1 to 9. +.TP +Note that if you change the EditList (for example , when deleting portions of your editlist) you should save your editlist as well as your samplelist. +.TP +You can select effects to put on your samples by pressing the cursor keys up and down, once you have found an effect you would like to use, press ENTER and it will be added to the current chain entry. The current chain entry can be changed with the PLUG and MINUS key on your numeric keyboard. Look at the KEYBINDS in this manual page to see what other possibilities you could have. +.TP +.SH Interactive camera/projection system +.TP +You can use veejay to calibrate a camera (or another input source) against a projector screen to map a physical position to veejay's projection. To use this feature, you can press CTRL\-s to activate the projection/camera calibration setup. This will render a graphical OSD on top of the video.Next, you need to play the live input source in order to find veejay's projection in the camera image. Set the points to the edges of the screen and right-click. Now press CTRL\-s or the middle mouse button to leave setup. Press CTRL-i to enable transforming the camera input and press CTRL-p to bring the projection screen in front. +.TP +.SH Interoperability +.TP +Veejay can be used with PD (PureData) by using sendVIMS, a small commandline utility that translates PD's symbols to veejay and vice versa.Look at the REFERENCES to find out where to download this utility. Also, by using the OpenSoundControl veejay can be used with a great number of sound and video processing applications.Also veejay can record video data to the yuv4mpeg format (mjpegtools), or stream uncompressed video over the network (uni - and multicast) +.SH OPTIONS +.TP +.B \-w/--output-width +Specify video output width for projection / on screen purposes +.TP +.B \-h/--output-height +Specify video output height for projection / on screen purposes +.TP +.B \-p/--port +TCP port offset for communication with clients like 'reloaded' , 'sayVIMS' or sendVIMS for PD (default 3490) +.TP +.B \-O/--output [01234] +specify video output 0 = SDL (default) 1 = DirectFB 2 = SDL and DirectFB 3 = Open GL (requires ARB fragment shader), 4 = Silent (no visual output) +.TP +.B \-s/--size NxN +Scaled video dimensions for SDL video output +.TP +.B \-a/--audio [01] +Play audio 0 = off , 1 = on (default) +.TP +.B \-c/--synchronization [01] +Sync correction off/on (default on) +.TP +.B \-P/--preverse-pathnames +Do not 'canonicalise' pathnames in editlists +.TP +.B \-v/--verbose +verbosity on/off +.TP +.B \-t/--timer [012] +timer to use ( none, normal, rtc ) +.TP +.B \-f/--fps +Override framerate of video +.TP +.B \-x/--geometryx +Geometry x offset for SDL video window +.TP +.B \-y/--geometryy +Geometry y offset for SDL video window +.TP +.B \-F/--action-file +Configuration File to load at initialization. +The configuration file stores custom keybindings, custom bundles, available VIMS events, editlist,samplelist,streamlist +and commandline options. +.TP +.B \-b/--bezerk +Bezerk mode, if enabled it allows you to change input channels on the fly (without restarting the samples) +.TP +.B \-g/--clip-as-sample +Load every file on the commandline as a new sample +.TP +.B \-q/--quit +Quit at end of video +.TP +.B \-n/--no-color +Dont use colored text. +.TP +.B \-m/--memory [0-100] +Frame cache size in percentage of total system RAM +.TP +.B \-j/--max_cache [0-100] +Maximum number of samples to cache +.TP +.B \-B/--features +Show compiled in options +.TP +.B \-Y/--yuv [01] +Use 0 for YUV 4:2:2 Rec 601 or 1 for YUV 4:2:2 JPEG/JFIF +.TP +.B \-e/--swap-range +Overwrite pixel sample range from input source ( Rec. 601 or JPEG/JFIF ) +.TP +.B \-d/--dummy +Start veejay with no video files (dummy mode). By default it will play black video (Stream 1 [F1]) +.TP +.B \-W/--width +Specify width of dummy video. +.TP +.B \-H/--height +Specify height of dummy video +.TP +.B \-R/--framerate +Specify framerate of dummy video +.TP +.B \-N [01] +Specify norm of dummy video (0=PAL, 1=NTSC). defaults to PAL +.TP +.B \-M/--multicast-osc
+Starts OSC receiver in multicast mode +.TP +.B \-T/--multicast-vims
+Setup additional multicast frame sender / command receiver. +The frame sender transmits on port offset + 3, send commands to port offset + 4, +.TP +.B \ /--map-from-file +To reduce transfers between memory and disk, you can set a number +of frames to be cached in memory from file (only valid for rawDV and AVI) +Use smaller values for better performance +.TP +.B \-V/--viewport +Start with source viewport enabled. Use this if you have previously setup +a viewport. Use CTRL+v to enable the viewport setup. +.TP +.B \-A/--all +Start with all capture devices active as streams +.TP +.B \-D/--composite +Do not start with projection enabled. +.TP +.SH Environment variables +.TP +.B VEEJAY_CAPTURE_DEVICE +You can set this environment variable to 'unicap' for capture +device detection and grabbing. +.TP +.B VEEJAY_SET_CPU +Tell veejay which CPU to use (and lock) for rendering. By default +veejay will lock CPU #1 if running on a SMP machine. +Use "0" to disable this behaviour. Use 1 for CPU#1, etc. +.TP +.B VEEJAY_AUTO_SCALE_PIXELS +Tell veejay to automatically convert between CCIR 601 and JPEG +pixels - hence, it scales YUV values from 0 - 255 to YCbCr 16-235/16-240 +and vice versa. Use "0" to disable this behaviour, "1" to enable. +.TP +.B SDL_VIDEO_HWACCEL +Set to 1 to use SDL video hardware accel (default=on) +.TP +.B VEEJAY_PERFORMANCE +Set to "quality" or "fastest" (default is fastest) +.TP +.B VEEJAY_AUTO_SCALE_PIXELS +Set to 1 to convert between CCIR 601 and JPEG automatically (default=dont care,white != white) +.TP +.B VEEJAY_INTERPOLATE_CHROMA +Set to 1 if you wish to interpolate every chroma sample when scaling (default=0) +.TP +.B VEEJAY_SDL_KEY_REPEAT_INTERVAL +Interval of key pressed to repeat while pressed down. +.TP +.B VEEJAY_PLAYBACK_CACHE +Sample cache size in MB - by default, veejay will consume up to 30% of your total RAM to cache video samples. +.TP +.B VEEJAY_SDL_KEY_REPEAT_DELAY +Delay key repeat in ms +.TP +.B VEEJAY_FULLSCREEN +Fullscreen (1) or windowed (0) mode +.TP +.B VEEJAY_SCREEN_GEOMETRY +Specifiy a geometry for veejay to position the video window. Use this feature to specificy where a video window appears in TwinView or One Big Desktop +.TP +.B VEEJAY_SCREEN_SIZE +Specifiy the size of the video window. +.TP +.B VEEJAY_DEFAULT_CHANNEL +Specify the default video4linux channel id +.TP +.B VEEJAY_SWAP_RGB +Capture in RGB or BGR (Video4Linux) +.TP +.B VEEJAY_RUN_MODE +Set this to "CLASSIC" if you want to startup in low resolution +.B Examples +.TP +.B VEEJAY_SCREEN_GEOMETRY=2624x1024+1600x0 +The video window will be displayed on the second screen, first screen is 1600 pixels wide. Specify this and VEEJAY_SCREEN_SIZE to create a borderless video window for use on one of your monitors in TwinView or One Big Desktop mode. +.TP +.B VEEJAY_SCREEN_SIZE=1024x768 +The second screen is 1024x768, the video window will appear fullscreen +.TP +.B VEEJAY_DEFAULT_CHANNEL +Set the Video4Linux Channel ID for veejay to use by default. +.TP +.SH Home directory +.TP +Veejay creates a new directory in your $HOME , ".veejay". +You must put a TrueType font file in $HOME/.veejay/fonts for veejay's OSD functionality. +.TP +.B .veejay/recovery +If veejay stops unexpectedly, it will try to save your samplelist and editlist before aborting. Most of the time, veejay will be able to fully recover. +.TP +.B .veejay/theme +Theme directory for GVeejayReloaded. +.TP +.B .veejay/plugins.cfg +If you want to load frei0r or freeframe plugins , set the paths +to the .so files in the plugins.cfg file. Only support for single +channel plugins. +.TP +.SH EXAMPLES +.TP +.B veejay -u |less +Startup veejay and list all events (VIMS/OSC) and effect descriptions +.TP +.B veejay -p 4000 ~/my_video1.avi +Startup veejay listening on port 4000 (use this to use multiple veejays) +.TP +.B veejay -d -W 352 -H 288 -R 25 -N 0 +Startup veejay using dummy video at 25 frames per second, dimensions 352x288 +and using PAL. +.TP +.B veejay movie1.avi -V 224.0.0.50 -p 5000 -n -v +Startup veejay, using multicast protocol on port 5000 , with autolooping +and no colored verbose output +.TP +.B veejay -O4 ~/my_video1.avi +Startup veejay with openGL video window +.TP +.SH INTERFACE COMMANDS (STDIN) +When you are running veejay with a SDL window you can use keybindings for +realtime interaction. See +.B KEYBINDINGS +for details. +.TP + +.SH KEYBINDINGS +.TP +.B [Keypad *] +Set sample looptype +.TP +.B [Keypad -] +Decrease chain index pointer +.TP +.B [Keypad +] +Increase chain index pointer +.TP +.B [Keypad 1] +Goto start of sample +.TP +.B [Keypad 2] +Go back 25 frames +.TP +.B [Keypad 3] +Goto end of sample +.TP +.B [Keypad 4] +Play backward +.TP +.B [Keypad 5] +Pause +.TP +.B [Keypad 6] +Play forward +.TP +.B [Keypad 7] +Goto previous frame +.TP +.B [Keypad 8] +Go forward 25 frames +.TP +.B [Keypad 9] +Goto next frame +.TP +.B [Keypad /] +Switch to Plain video playback mode (from Sample or Tag mode) +.TP +.B [LEFT BRACKET] +Set sample start +.TP +.B [RIGHT BRACKET] +Set sample end and create new sample +.TP +.B [ALT] + [LEFT BRACKET] +Set marker start +.TP +.B [ALT] + [LEFT BRACKET] +Set marker end and activate marker +.TP +.B [Backspace] +Delete current marker +.TP +.B [a,s,d,f,g,h,j,k,l] +Set playback speed to 1,2,3,4,5,6,7,8, or 9 +.TP +.B [ALT] + [a|s|d|f|g|h|j|k|l] +Set frame duplicator to 1,2,3,4,5,6,7,8 or 9. Interpolates missing frames. +.TP +.B [1..9] +Set sample range 0-12, 12-24, 24-36 etc. +.TP +.B ALT + [1..9] +Set channel ID 1-9, depending on sample range +.TP +.B [F1..F12] +Select and play sample 1 .. 12 +.TP +.B [DELETE] +Delete selected effect +.TP +.B [Home] +Print sample/tag information +.TP +.B [ESC] +Switch between Plain -> Tag or Sample playback mode +.TP +.B [CURSOR RIGHT] +Go up 5 positions in the effect list +.TP +.B [CURSOR LEFT] +Go back 5 positions in the effect list +.TP +.B [UP] +Go up 1 position in the effect list +.TP +.B [DOWN] +Go down 1 position in the effect list +.TP +.B [RETURN | ENTER] +Add selected effect from list to sample +.TP +.B [v] +Toggle sample's playlist +.TP +.B [-] +Decrease mixing channel ID +.TP +.B [=] +Increase mixing channel ID +.TP +.B SLASH +Toggle mixing source between Clips and Streams +.TP +.B [z] +Audio Fade in decrease (*) +.TP +.B [x] +Audio Fade in increase (*) +.TP +.B [b] +Toggle a selected effect on/off +.TP +.B [END] +Enable/Disable Effect Chain +.TP +.B [Left ALT] + [END] +Enable/Disable Video on selected Entry +.TP +.B [Right ALT] + [END] +Enable/Disable Audio on selected Entry +.TP +.B [LCTRL] + [END] +Enable/Disable Video on selected Entry +.TP +.B [RCTRL] + [END] +Enable/Disable Audio on selected Entry +.TP +.B [NUMLOCK] +Auto increment/decrement of a parameter-key +.TP +.B [n] +Decrease trimmer value of selected effect +.TP +.B [m] +Increase trimmer value of selected effect +.TP +.B [x] +Decrease audio volume (not functional) +.TP +.B [c] +Increase audio volume (not functional) +.TP +.B [0] +Capture frame to jpeg file +.TP +.B [PgUp] +Increase parameter 0 of selected effect +.TP +.B [PgDn] +Decrease parameter 0 of selected effect +.TP +.B [Keypad 0] +Decrease parameter 1 of selected effect +.TP +.B [Keypad .] +Increase parameter 1 of selected effect +.TP +.B [.] +Increase parameter 2 of selected effect +.TP +.B [,] +Decrease parameter 2 of selected effect +.TP +.B [QUOTE] +Increase parameter 3 of selected effect +.TP +.B [SEMICOLON] +Decrease parameter 3 of selected effect +.TP +.B [q] +Decrease parameter 4 of selected effect +.TP +.B [w] +Increase parameter 4 of selected effect +.TP +.B [e] +Decrease parameter 5 of selected effect +.TP +.B [r] +Increase parameter 5 of selected effect +.TP +.B [t] +Decrease parameter 6 of selected effect +.TP +.B [y] +Increase parameter 6 of selected effect +.TP +.B [u] +Decrease parameter 7 of selected effect +.TP +.B [i] +Increase parameter 7 of selected effect +.TP + +.B SHIFT + spacebar +Start keystroke recorder. The keystroke recorder +records most of the received VIMS messages and plays them +back in order and on the position you have pressed them. +Instead of using the keyboard, you can also use 'Reloaded', +and record the buttons pressed. However, some VIMS messages +are excluded from the keystroke recorder for safety reasons. +.TP +.B spacebar +(re)play recorded VIMS messages. The keystroke recorder +will jump to the starting position and replay all +recorded VIMS messages. +.TP +.B CTRL + spacebar +Clear recorded keystrokes. This clears all VIMS messages +in the current selected macro slot. +.TP +.B CTRL + [ F1 - F12 ] +Select a slot to record keystrokes to (default=0) +Use this if you want to record multiple keystrokes. You +can switch slots while in keystroke playback. +.TP +.B ALT + B +Take a snapshot of a video frame and put it in a seperate +buffer (used by some effects like Difference Overlay) +.TP +.B CTRL + s +Show/hide interactive camera/projector calibration setup +.TP +.B CTRL + p +Focus on front (primary output) or back (secundary input) projection +.TP +.B CTRL + i +Toggle current playing sample/stream as input source to be transformed +.TP +.B CTRL + v +Toggle grayscale/color mode for unicap streams +.TP +.B CTRL + h +Toggle OSD help for camera/projector setup +.TP +.B CTRL + o +Toggle OSD help for general status messages and mouse coordinates +.TP +.B CTRL + d +Toggle rendering of single source FX on underlying samples +.TP +.B CTRL + r +Start recording +.TP +.B CTRL + t +Stop recording +.TP +.SH REFERENCES +.TP +http://veejay.sourceforge.net +http://veejayhq.net +.TP +.SH BUGS +see BUGS in the source package +.SH AUTHOR +This man page was written by Niels Elburg. +If you have questions, remarks or you just want to +contact the developers, the main mailing list for this +project is: +.I http://groups.google.com/group/veejay-discussion/post?hl=en +For more info see the website at +.I http://veejayhq.net +.I http://veejay.dyne.org +.SH "SEE ALSO" +.B veejay sayVIMS reloaded diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/Makefile.am b/branches/V-1.5.3/veejay-server/mjpegtools/Makefile.am new file mode 100644 index 00000000..2dd5796c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/Makefile.am @@ -0,0 +1,8 @@ +EXTRA_DIST= fastintfns.h mjpeg_logging.h mpegconsts.h videodev_mjpeg.h yuv4mpeg_intern.h format_codes.h \ +mjpeg_types.h mpegtimecode.h yuv4mpeg.h +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) -I$(top_srcdir)/mjpegtools $(PTHREAD_CFLAGS) +MJPEGUTILS_LIB_FILE = libmjpegutils.la +noinst_LTLIBRARIES = $(MJPEGUTILS_LIB_FILE) +libmjpegutils_la_SOURCES = mjpeg_logging.c mpegconsts.c mpegtimecode.c yuv4mpeg.c yuv4mpeg_ratio.c diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/fastintfns.h b/branches/V-1.5.3/veejay-server/mjpegtools/fastintfns.h new file mode 100644 index 00000000..41c611c9 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/fastintfns.h @@ -0,0 +1,18 @@ +/* fast int primitives. min,max,rnddiv2 + * + * WARNING: Assumes 2's complement arithmetic. + */ +static inline int intmax( register int x, register int y ) +{ + return x < y ? y : x; +} + +static inline int intmin( register int x, register int y ) +{ + return x < y ? x : y; +} + +static inline int rnddiv2( int x ) +{ + return (x+(x>0))>>1; +} diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/format_codes.h b/branches/V-1.5.3/veejay-server/mjpegtools/format_codes.h new file mode 100644 index 00000000..2c958f04 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/format_codes.h @@ -0,0 +1,46 @@ +/* + $Id: format_codes.h,v 1.10 2005/12/09 23:07:56 wackston2 Exp $ + + Copyright (C) 2001 Andrew Stevens + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __FORMAT_CODES_H__ +#define __FORMAT_CODES_H__ + +#define MPEG_FORMAT_MPEG1 0 +#define MPEG_FORMAT_VCD 1 +#define MPEG_FORMAT_VCD_NSR 2 +#define MPEG_FORMAT_MPEG2 3 +#define MPEG_FORMAT_SVCD 4 +#define MPEG_FORMAT_SVCD_NSR 5 +#define MPEG_FORMAT_VCD_STILL 6 +#define MPEG_FORMAT_SVCD_STILL 7 +#define MPEG_FORMAT_DVD_NAV 8 +#define MPEG_FORMAT_DVD 9 +#define MPEG_FORMAT_ATSC480i 10 +#define MPEG_FORMAT_ATSC480p 11 +#define MPEG_FORMAT_ATSC720p 12 +#define MPEG_FORMAT_ATSC1080i 13 + +#define MPEG_FORMAT_FIRST 0 +#define MPEG_FORMAT_LAST MPEG_FORMAT_ATSC1080i + +#define MPEG_STILLS_FORMAT(x) ((x)==MPEG_FORMAT_VCD_STILL||(x)==MPEG_FORMAT_SVCD_STILL) +#define MPEG_ATSC_FORMAT(x) ((x)>=MPEG_FORMAT_ATSC480i && (x)<=MPEG_FORMAT_ATSC1080i) +#define MPEG_HDTV_FORMAT(x) MPEG_ATSC_FORMAT(x) +#define MPEG_SDTV_FORMAT(x) (!MPEG_HDTV_FORMAT(x)) +#endif /* __FORMAT_CODES_H__ */ diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_logging.c b/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_logging.c new file mode 100644 index 00000000..3d43fd8d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_logging.c @@ -0,0 +1,230 @@ +/* + $Id: mjpeg_logging.c,v 1.16 2007/04/01 18:06:06 sms00 Exp $ + + Copyright (C) 2000 Herbert Valerio Riedel + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include "mjpeg_logging.h" + +#ifdef HAVE___PROGNAME +extern const char *__progname; +#endif + +/* + * Put these here and NOT in the exported header file mjpeg_logging.h + * + * since ALL program use of these should use the API below (mjpeg_warn, + * mjpeg_error,etc) these symbols do not need to be exported and possibly + * conflict with syslog.h +*/ + +#define LOG_DEBUG 1 +#define LOG_INFO 2 +#define LOG_WARN 3 +#define LOG_ERROR 4 + +static log_level_t mjpeg_log_verbosity = 0; +static char *default_handler_id = NULL; + +static int default_mjpeg_log_filter( log_level_t level ) +{ + int verb_from_env; + if( mjpeg_log_verbosity == 0 ) + { + char *mjpeg_verb_env = getenv("MJPEG_VERBOSITY"); + if( mjpeg_verb_env != NULL ) + { + verb_from_env = LOG_WARN-atoi(mjpeg_verb_env); + if( verb_from_env >= LOG_DEBUG && verb_from_env <= LOG_ERROR ) + mjpeg_log_verbosity = (log_level_t)verb_from_env; + } + } + return (level < LOG_WARN && level < mjpeg_log_verbosity); +} + +static mjpeg_log_filter_t _filter = default_mjpeg_log_filter; + +static void +default_mjpeg_log_handler(log_level_t level, const char message[]) +{ + const char *ids; + + if( (*_filter)( level ) ) + return; + if (default_handler_id != NULL) { + ids = default_handler_id; + } else { +#ifdef HAVE___PROGNAME + ids = __progname; +#else + ids = "???"; +#endif + } + switch(level) { + case LOG_ERROR: + fprintf(stderr, "**ERROR: [%s] %s\n", ids, message); + break; + case LOG_DEBUG: + fprintf(stderr, "--DEBUG: [%s] %s\n", ids, message); + break; + case LOG_WARN: + fprintf(stderr, "++ WARN: [%s] %s\n", ids, message); + break; + case LOG_INFO: + fprintf(stderr, " INFO: [%s] %s\n", ids, message); + break; + default: + assert(0); + } +} + +static mjpeg_log_handler_t _handler = default_mjpeg_log_handler; + + +mjpeg_log_handler_t +mjpeg_log_set_handler(mjpeg_log_handler_t new_handler) +{ + mjpeg_log_handler_t old_handler = _handler; + + _handler = new_handler; + return old_handler; +} + +/*************** + * Set default log handlers degree of verboseity. + * 0 = quiet, 1 = info, 2 = debug + *************/ + +int +mjpeg_default_handler_verbosity(int verbosity) +{ + int prev_verb = mjpeg_log_verbosity; + mjpeg_log_verbosity = (log_level_t)(LOG_WARN - verbosity); + return prev_verb; +} + +/* + * Set identifier string used by default handler + */ +int +mjpeg_default_handler_identifier(const char *new_id) +{ + const char *s; + if (new_id == NULL) { + if (default_handler_id != NULL) + free(default_handler_id); + default_handler_id = NULL; + return 0; + } + /* find basename of new_id (remove any directory prefix) */ + if ((s = strrchr(new_id, '/')) == NULL) + s = new_id; + else + s = s + 1; + default_handler_id = strdup(s); + return 0; +} + +static void +mjpeg_logv(log_level_t level, const char format[], va_list args) +{ + char buf[1024] = { 0, }; + + /* TODO: Original had a re-entrancy error trap to assist bug + finding. To make this work with multi-threaded applications a + lock is needed hence delete. + */ + + vsnprintf(buf, sizeof(buf)-1, format, args); + _handler(level, buf); +} + +void +mjpeg_log(log_level_t level, const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(level, format, args); + va_end (args); +} + +void +mjpeg_debug(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_DEBUG, format, args); + va_end (args); +} + +void +mjpeg_info(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_INFO, format, args); + va_end (args); +} + +void +mjpeg_warn(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_WARN, format, args); + va_end (args); +} + +void +mjpeg_error(const char format[], ...) +{ + va_list args; + va_start (args, format); + mjpeg_logv(LOG_ERROR, format, args); + va_end (args); +} + +void +mjpeg_error_exit1(const char format[], ...) +{ + va_list args; + va_start( args, format ); + mjpeg_logv( LOG_ERROR, format, args); + va_end(args); + exit(EXIT_FAILURE); +} + +log_level_t +mjpeg_loglev_t(const char *level) +{ + if (strcasecmp("debug", level) == 0) return(LOG_DEBUG); + else if (strcasecmp("info", level) == 0) return(LOG_INFO); + else if (strcasecmp("warn", level) == 0) return(LOG_WARN); + else if (strcasecmp("error", level) == 0) return(LOG_ERROR); + return(0); +} diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_logging.h b/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_logging.h new file mode 100644 index 00000000..9918af48 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_logging.h @@ -0,0 +1,77 @@ +/* + $Id: mjpeg_logging.h,v 1.11 2007/04/01 18:06:06 sms00 Exp $ + + Copyright (C) 2000 Herbert Valerio Riedel + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __MJPEG_LOGGING_H__ +#define __MJPEG_LOGGING_H__ + +#include + +/* to avoid changing all the places log_level_t is used */ +typedef int log_level_t; + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) +#define GNUC_PRINTF( format_idx, arg_idx ) \ + __attribute__((format (printf, format_idx, arg_idx))) +#else /* !__GNUC__ */ +#define GNUC_PRINTF( format_idx, arg_idx ) +#endif /* !__GNUC__ */ + +#ifdef __cplusplus +extern "C" { +#endif +void +mjpeg_log(log_level_t level, const char format[], ...) GNUC_PRINTF(2, 3); + +typedef int(*mjpeg_log_filter_t)(log_level_t level); + +typedef void(*mjpeg_log_handler_t)(log_level_t level, const char message[]); + +mjpeg_log_handler_t +mjpeg_log_set_handler(mjpeg_log_handler_t new_handler); + +int +mjpeg_default_handler_identifier(const char *new_id); + +int +mjpeg_default_handler_verbosity(int verbosity); + +void +mjpeg_debug(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_info(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_warn(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_error(const char format[], ...) GNUC_PRINTF(1,2); + +void +mjpeg_error_exit1(const char format[], ...) GNUC_PRINTF(1,2); + +log_level_t +mjpeg_loglev_t(const char *str); + +#ifdef __cplusplus +} +#endif + +#endif /* __MJPEG_LOGGING_H__ */ diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_types.h b/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_types.h new file mode 100644 index 00000000..88b461c1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/mjpeg_types.h @@ -0,0 +1,28 @@ +/* + $Id: mjpeg_types.h,v 1.16 2006/05/18 18:19:05 sms00 Exp $ + + Copyright (C) 2000 Herbert Valerio Riedel + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __MJPEG_TYPES_H__ +#define __MJPEG_TYPES_H__ + +#include /* FreeBSD, others - ssize_t */ +#include +#include + +#endif /* __MJPEG_TYPES_H__ */ diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/mpegconsts.c b/branches/V-1.5.3/veejay-server/mjpegtools/mpegconsts.c new file mode 100644 index 00000000..4d80af28 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/mpegconsts.c @@ -0,0 +1,513 @@ + +/* + * mpegconsts.c: Video format constants for MPEG and utilities for display + * and conversion to format used for yuv4mpeg + * + * Copyright (C) 2001 Andrew Stevens + * Copyright (C) 2001 Matthew Marjanovic + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include "mpegconsts.h" +#include "yuv4mpeg.h" +#include "yuv4mpeg_intern.h" +#include "format_codes.h" + +static y4m_ratio_t +mpeg_framerates[] = { + Y4M_FPS_UNKNOWN, + Y4M_FPS_NTSC_FILM, + Y4M_FPS_FILM, + Y4M_FPS_PAL, + Y4M_FPS_NTSC, + Y4M_FPS_30, + Y4M_FPS_PAL_FIELD, + Y4M_FPS_NTSC_FIELD, + Y4M_FPS_60 +}; + + +#define MPEG_NUM_RATES (sizeof(mpeg_framerates)/sizeof(mpeg_framerates[0])) +static const mpeg_framerate_code_t mpeg_num_framerates = MPEG_NUM_RATES; + +static const char * +framerate_definitions[MPEG_NUM_RATES] = +{ + "illegal", + "24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)", + "24.0 (NATIVE FILM)", + "25.0 (PAL/SECAM VIDEO / converted FILM)", + "30000.0/1001.0 (NTSC VIDEO)", + "30.0", + "50.0 (PAL FIELD RATE)", + "60000.0/1001.0 (NTSC FIELD RATE)", + "60.0" +}; + + +static const char *mpeg1_aspect_ratio_definitions[] = +{ + "illegal", + "1:1 (square pixels)", + "1:0.6735", + "1:0.7031 (16:9 Anamorphic PAL/SECAM for 720x578/352x288 images)", + "1:0.7615", + "1:0.8055", + "1:0.8437 (16:9 Anamorphic NTSC for 720x480/352x240 images)", + "1:0.8935", + "1:0.9375 (4:3 PAL/SECAM for 720x578/352x288 images)", + "1:0.9815", + "1:1.0255", + "1:1:0695", + "1:1.1250 (4:3 NTSC for 720x480/352x240 images)", + "1:1.1575", + "1:1.2015" +}; + +static const y4m_ratio_t mpeg1_aspect_ratios[] = +{ + Y4M_SAR_UNKNOWN, + Y4M_SAR_MPEG1_1, + Y4M_SAR_MPEG1_2, + Y4M_SAR_MPEG1_3, /* Anamorphic 16:9 PAL */ + Y4M_SAR_MPEG1_4, + Y4M_SAR_MPEG1_5, + Y4M_SAR_MPEG1_6, /* Anamorphic 16:9 NTSC */ + Y4M_SAR_MPEG1_7, + Y4M_SAR_MPEG1_8, /* PAL/SECAM 4:3 */ + Y4M_SAR_MPEG1_9, + Y4M_SAR_MPEG1_10, + Y4M_SAR_MPEG1_11, + Y4M_SAR_MPEG1_12, /* NTSC 4:3 */ + Y4M_SAR_MPEG1_13, + Y4M_SAR_MPEG1_14, +}; + +static const char *mpeg2_aspect_ratio_definitions[] = +{ + "illegal", + "1:1 pixels", + "4:3 display", + "16:9 display", + "2.21:1 display" +}; + + +static const y4m_ratio_t mpeg2_aspect_ratios[] = +{ + Y4M_DAR_UNKNOWN, + Y4M_DAR_MPEG2_1, + Y4M_DAR_MPEG2_2, + Y4M_DAR_MPEG2_3, + Y4M_DAR_MPEG2_4 +}; + +static const char **aspect_ratio_definitions[2] = +{ + mpeg1_aspect_ratio_definitions, + mpeg2_aspect_ratio_definitions +}; + +static const y4m_ratio_t *mpeg_aspect_ratios[2] = +{ + mpeg1_aspect_ratios, + mpeg2_aspect_ratios +}; + +static const mpeg_aspect_code_t mpeg_num_aspect_ratios[2] = +{ + sizeof(mpeg1_aspect_ratios)/sizeof(mpeg1_aspect_ratios[0]), + sizeof(mpeg2_aspect_ratios)/sizeof(mpeg2_aspect_ratios[0]) +}; + +static const char *mjpegtools_format_code_definitions[MPEG_FORMAT_LAST+1] = +{ + "Generic MPEG1", + "Standard VCD", + "Stretched VCD", + "Generic MPEG2", + "Standard SVCD", + "Stretched SVCD", + "VCD Still", + "SVCD Still", + "DVD with dummy navigation packets", + "Standard DVD", + "ATSC 480i", + "ATSC 480p", + "ATSC 720p", + "ATSC 1080i" +}; + +/* + * Is code a valid MPEG framerate code? + */ + +int +mpeg_valid_framerate_code( mpeg_framerate_code_t code ) +{ + return ((code > 0) && (code < mpeg_num_framerates)) ? 1 : 0; +} + + +/* + * Convert MPEG frame-rate code to corresponding frame-rate + */ + +y4m_ratio_t +mpeg_framerate( mpeg_framerate_code_t code ) +{ + if ((code > 0) && (code < mpeg_num_framerates)) + return mpeg_framerates[code]; + else + return y4m_fps_UNKNOWN; +} + +/* + * Look-up MPEG frame rate code for a (exact) frame rate. + */ + + +mpeg_framerate_code_t +mpeg_framerate_code( y4m_ratio_t framerate ) +{ + mpeg_framerate_code_t i; + + y4m_ratio_reduce(&framerate); + /* start at '1', because 0 is unknown/illegal */ + for (i = 1; i < mpeg_num_framerates; ++i) { + if (Y4M_RATIO_EQL(framerate, mpeg_framerates[i])) + return i; + } + return 0; +} + + +/* small enough to distinguish 1/1000 from 1/1001 */ +#define MPEG_FPS_TOLERANCE 0.0001 + + +y4m_ratio_t +mpeg_conform_framerate( double fps ) +{ + mpeg_framerate_code_t i; + y4m_ratio_t result; + + /* try to match it to a standard frame rate */ + /* (start at '1', because 0 is unknown/illegal) */ + for (i = 1; i < mpeg_num_framerates; i++) + { + double deviation = 1.0 - (Y4M_RATIO_DBL(mpeg_framerates[i]) / fps); + if ( (deviation > -MPEG_FPS_TOLERANCE) && + (deviation < +MPEG_FPS_TOLERANCE) ) + return mpeg_framerates[i]; + } + /* no luck? just turn it into a ratio (6 decimal place accuracy) */ + result.n = (int)((fps * 1000000.0) + 0.5); + result.d = 1000000; + y4m_ratio_reduce(&result); + return result; +} + + + +/* + * Is code a valid MPEG aspect-ratio code? + */ + +int +mpeg_valid_aspect_code( int version, mpeg_framerate_code_t c ) +{ + if ((version == 1) || (version == 2)) + return ((c > 0) && (c < mpeg_num_aspect_ratios[version-1])) ? 1 : 0; + else + return 0; +} + + +/* + * Convert MPEG aspect-ratio code to corresponding aspect-ratio + */ + +y4m_ratio_t +mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code ) +{ + y4m_ratio_t ratio; + if ((mpeg_version >= 1) && (mpeg_version <= 2) && + (code > 0) && (code < mpeg_num_aspect_ratios[mpeg_version-1])) + { + ratio = mpeg_aspect_ratios[mpeg_version-1][code]; + y4m_ratio_reduce(&ratio); + return ratio; + } + else + return y4m_sar_UNKNOWN; +} + + + +/* + * Look-up corresponding MPEG aspect ratio code given an exact aspect ratio. + * + * WARNING: The semantics of aspect ratio coding *changed* between + * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In + * MPEG2 it is the (far more sensible) aspect ratio of the eventual + * display. + * + */ + +mpeg_aspect_code_t +mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio ) +{ + mpeg_aspect_code_t i; + y4m_ratio_t red_ratio = aspect_ratio; + y4m_ratio_reduce( &red_ratio ); + if( mpeg_version < 1 || mpeg_version > 2 ) + return 0; + /* (start at '1', because 0 is unknown/illegal) */ + for( i = 1; i < mpeg_num_aspect_ratios[mpeg_version-1]; ++i ) + { + y4m_ratio_t red_entry = mpeg_aspect_ratios[mpeg_version-1][i]; + y4m_ratio_reduce( &red_entry ); + if( Y4M_RATIO_EQL( red_entry, red_ratio) ) + return i; + } + + return 0; + +} + + + +/* + * Guess the correct MPEG aspect ratio code, + * given the true sample aspect ratio and frame size of a video stream + * (and the MPEG version, 1 or 2). + * + * Returns 0 if it has no good guess. + * + */ + + +/* this is big enough to accommodate the difference between 720 and 704 */ +#define GUESS_ASPECT_TOLERANCE 0.03 + +mpeg_aspect_code_t +mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect, + int frame_width, int frame_height) +{ + if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_UNKNOWN)) + { + return 0; + } + switch (mpeg_version) { + case 1: + if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE)) + { + return 1; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_CCIR601)) + { + return 12; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_16_9)) + { + return 6; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_CCIR601)) + { + return 8; + } + else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_16_9)) + { + return 3; + } + return 0; + break; + case 2: + if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE)) + { + return 1; /* '1' means square *pixels* in MPEG-2; go figure. */ + } + else + { + int i; + double true_far; /* true frame aspect ratio */ + true_far = + (double)(sampleaspect.n * frame_width) / + (double)(sampleaspect.d * frame_height); + /* start at '2'... */ + for (i = 2; i < (int)(mpeg_num_aspect_ratios[mpeg_version-1]); i++) + { + double ratio = + true_far / Y4M_RATIO_DBL(mpeg_aspect_ratios[mpeg_version-1][i]); + if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && + (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) ) + return i; + } + return 0; + } + break; + default: + return 0; + break; + } +} + + + + +/* + * Guess the true sample aspect ratio of a video stream, + * given the MPEG aspect ratio code and the actual frame size + * (and the MPEG version, 1 or 2). + * + * Returns y4m_sar_UNKNOWN if it has no good guess. + * + */ +y4m_ratio_t +mpeg_guess_sample_aspect_ratio(int mpeg_version, + mpeg_aspect_code_t code, + int frame_width, int frame_height) +{ + switch (mpeg_version) + { + case 1: + /* MPEG-1 codes turn into SAR's, just not quite the right ones. + For the common/known values, we provide the ratio used in practice, + otherwise say we don't know.*/ + switch (code) + { + case 1: return y4m_sar_SQUARE; break; + case 3: return y4m_sar_PAL_16_9; break; + case 6: return y4m_sar_NTSC_16_9; break; + case 8: return y4m_sar_PAL_CCIR601; break; + case 12: return y4m_sar_NTSC_CCIR601; break; + default: + return y4m_sar_UNKNOWN; break; + } + break; + case 2: + /* MPEG-2 codes turn into Display Aspect Ratios, though not exactly the + DAR's used in practice. For common/standard frame sizes, we provide + the original SAR; otherwise, we say we don't know. */ + if (code == 1) + { + return y4m_sar_SQUARE; /* '1' means square *pixels* in MPEG-2 */ + } + else if ((code >= 2) && (code <= 4)) + { + return y4m_guess_sar(frame_width, frame_height, + mpeg2_aspect_ratios[code]); + } + else + { + return y4m_sar_UNKNOWN; + } + break; + default: + return y4m_sar_UNKNOWN; + break; + } +} + + + + + +/* + * Look-up MPEG explanatory definition string for frame rate code + * + */ + + +const char * +mpeg_framerate_code_definition( mpeg_framerate_code_t code ) +{ + if( code == 0 || code >= mpeg_num_framerates ) + return "UNDEFINED: illegal/reserved frame-rate ratio code"; + + return framerate_definitions[code]; +} + +/* + * Look-up MPEG explanatory definition string aspect ratio code for an + * aspect ratio code + * + */ + +const char * +mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code ) +{ + if( mpeg_version < 1 || mpeg_version > 2 ) + return "UNDEFINED: illegal MPEG version"; + + if( code < 1 || code >= mpeg_num_aspect_ratios[mpeg_version-1] ) + return "UNDEFINED: illegal aspect ratio code"; + + return aspect_ratio_definitions[mpeg_version-1][code]; +} + + +/* + * Look-up explanatory definition of interlace field order code + * + */ + +const char * +mpeg_interlace_code_definition( int yuv4m_interlace_code ) +{ + const char *def; + switch( yuv4m_interlace_code ) + { + case Y4M_UNKNOWN : + def = "unknown"; + break; + case Y4M_ILACE_NONE : + def = "none/progressive"; + break; + case Y4M_ILACE_TOP_FIRST : + def = "top-field-first"; + break; + case Y4M_ILACE_BOTTOM_FIRST : + def = "bottom-field-first"; + break; + default : + def = "UNDEFINED: illegal video interlacing type-code!"; + break; + } + return def; +} + +/* + * Look-up explanatory definition of mjepgtools preset format code + * + */ +const char *mpeg_format_code_defintion( int format_code ) +{ + if(format_code >= MPEG_FORMAT_FIRST && format_code <= MPEG_FORMAT_LAST ) + return mjpegtools_format_code_definitions[format_code]; + else + return "UNDEFINED: illegal format code!"; +}; + +/* + * Local variables: + * c-file-style: "stroustrup" + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/mpegconsts.h b/branches/V-1.5.3/veejay-server/mjpegtools/mpegconsts.h new file mode 100644 index 00000000..9ea32895 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/mpegconsts.h @@ -0,0 +1,171 @@ + +/* + * mpegconsts.c: Video format constants for MPEG and utilities for display + * and conversion to format used for yuv4mpeg + * + * Copyright (C) 2001 Andrew Stevens + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __MPEGCONSTS_H__ +#define __MPEGCONSTS_H__ + +#include + +typedef unsigned int mpeg_framerate_code_t; +typedef unsigned int mpeg_aspect_code_t; + +#ifdef __cplusplus +#define START_CPP_WRAP extern "C" { +#define END_CPP_WRAP }; +#else +#define START_CPP_WRAP +#define END_CPP_WRAP +#endif + +START_CPP_WRAP + + +/* + * Convert MPEG frame-rate code to corresponding frame-rate + * y4m_fps_UNKNOWN = { 0, 0 } = Undefined/resrerved code. + */ + +y4m_ratio_t +mpeg_framerate( mpeg_framerate_code_t code ); + + +/* + * Is code a valid MPEG frame-rate code? + * Return 1 if true; 0 otherwise. + */ + +int +mpeg_valid_framerate_code( mpeg_framerate_code_t code ); + + +/* + * Look-up MPEG frame rate code for a (exact) frame rate. + * 0 = No MPEG code defined for frame-rate + */ + +mpeg_framerate_code_t +mpeg_framerate_code( y4m_ratio_t framerate ); + + +/* + * Convert floating-point framerate to an exact ratio. + * Uses a standard MPEG rate, if it finds one within MPEG_FPS_TOLERANCE + * (see mpegconsts.c), otherwise uses "fps:1000000" as the ratio. + */ + +y4m_ratio_t +mpeg_conform_framerate( double fps ); + + +/* + * Convert MPEG aspect ratio code to corresponding aspect ratio + * + * WARNING: The semantics of aspect ratio coding *changed* between + * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In + * MPEG2 it is the (far more sensible) aspect ratio of the eventual + * display. + * + */ + +y4m_ratio_t +mpeg_aspect_ratio( int mpeg_version, mpeg_aspect_code_t code ); + + +/* + * Is code a valid MPEG(1,2) aspect-ratio code? + * Return 1 if true; 0 otherwise. + */ + +int +mpeg_valid_aspect_code( int mpeg_version, mpeg_aspect_code_t code ); + + +/* + * Look-up MPEG aspect ratio code for an aspect ratio - tolerance + * is Y4M_ASPECT_MULT used by YUV4MPEG (see yuv4mpeg_intern.h) + * + * WARNING: The semantics of aspect ratio coding *changed* between + * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In + * MPEG2 it is the (far more sensible) aspect ratio of the eventual + * display. + * + */ + +mpeg_aspect_code_t +mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio ); + +/* + * Look-up MPEG explanatory definition string aspect ratio code for an + * aspect ratio code + * + */ + +const char * +mpeg_aspect_code_definition( int mpeg_version, mpeg_aspect_code_t code ); + +/* + * Look-up MPEG explanatory definition string aspect ratio code for an + * frame rate code + * + */ + +const char * +mpeg_framerate_code_definition( mpeg_framerate_code_t code ); + +const char * +mpeg_interlace_code_definition( int yuv4m_interlace_code ); + + +/* + * Guess the correct MPEG aspect ratio code, + * given the true sample aspect ratio and frame size of a video stream + * (and the MPEG version, 1 or 2). + * + * Returns 0 if it has no good answer. + * + */ +mpeg_aspect_code_t +mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect, + int frame_width, int frame_height); + +/* + * Guess the true sample aspect ratio of a video stream, + * given the MPEG aspect ratio code and the actual frame size + * (and the MPEG version, 1 or 2). + * + * Returns y4m_sar_UNKNOWN if it has no good answer. + * + */ +y4m_ratio_t +mpeg_guess_sample_aspect_ratio(int mpeg_version, + mpeg_aspect_code_t code, + int frame_width, int frame_height); + +/* + * Look-up MJPEGTOOLS MPEG preset format code explanatory definition string a + * + */ +const char *mpeg_format_code_defintion( int format_code ); + +END_CPP_WRAP + +#endif /* __MPEGCONSTS_H__ */ diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/mpegtimecode.c b/branches/V-1.5.3/veejay-server/mjpegtools/mpegtimecode.c new file mode 100644 index 00000000..09986739 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/mpegtimecode.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2001 Kawamata/Hitoshi + * + * 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 "mpegtimecode.h" + +/************************************************************** + * // NTSC DROP FRAME TIMECODE / 29.97fps (SMTPE) + * // hh:mm:ss:ff + * // hh: 0.. + * // mm: 0..59 + * // ss: 0..59 + * // ff: 0..29 # ss != 0 || mm % 10 == 0 + * // 2..29 # ss == 0 && mm % 10 != 0 + * // + * // 00:00:00:00 00:00:00:01 00:00:00:02 ... 00:00:00:29 + * // 00:00:01:00 00:00:01:01 00:00:01:02 ... 00:00:01:29 + * // : + * // 00:00:59:00 00:00:59:01 00:00:59:02 ... 00:00:59:29 + * // 00:01:00:02 ... 00:01:00:29 + * // 00:01:01:00 00:01:01:01 00:01:01:02 ... 00:01:00:29 + * // : + * // 00:01:59:00 00:01:59:01 00:01:59:02 ... 00:01:59:29 + * // 00:02:00:02 ... 00:02:00:29 + * // 00:02:01:00 00:02:01:01 00:02:01:02 ... 00:02:00:29 + * // : + * // : + * // 00:09:59:00 00:09:59:01 00:09:59:02 ... 00:09:59:29 + * // 00:10:00:00 00:10:00:01 00:10:00:02 ... 00:10:00:29 + * // 00:10:01:00 00:10:01:01 00:10:01:02 ... 00:10:01:29 + * // : + * // 00:10:59:00 00:10:59:01 00:10:59:02 ... 00:10:59:29 + * // 00:11:00:02 ... 00:11:00:29 + * // 00:11:01:00 00:11:01:01 00:11:01:02 ... 00:11:00:29 + * // : + * // : + * // DROP FRAME / 59.94fps (no any standard) + * // DROP FRAME / 23.976fps (no any standard) + ***************************************************************/ + +int dropframetimecode = -1; + +/* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */ +int +mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps) +{ + static const int ifpss[] = { 0, 24, 24, 25, 30, 30, 50, 60, 60, }; + int h, m, s; + + if (dropframetimecode < 0) { + char *env = getenv("MJPEG_DROP_FRAME_TIME_CODE"); + dropframetimecode = (env && *env != '0' && *env != 'n' && *env != 'N'); + } + if (dropframetimecode && + 0 < fpscode && fpscode + 1 < sizeof ifpss / sizeof ifpss[0] && + ifpss[fpscode] == ifpss[fpscode + 1]) { + int topinmin = 0, k = (30*4) / ifpss[fpscode]; + f *= k; /* frame# when 119.88fps */ + h = (f / ((10*60*30-18)*4)); /* # of 10min. */ + f %= ((10*60*30-18)*4); /* frame# in 10min. */ + f -= (2*4); /* frame# in 10min. - (2*4) */ + m = (f / ((60*30-2)*4)); /* min. in 10min. */ + topinmin = ((f - k) / ((60*30-2)*4) < m); + m += (h % 6 * 10); /* min. */ + h /= 6; /* hour */ + f %= ((60*30-2)*4); /* frame# in min. - (2*4)*/ + f += (2*4); /* frame# in min. */ + s = f / (30*4); /* sec. */ + f %= (30*4); /* frame# in sec. */ + f /= k; /* frame# in sec. on original fps */ + tc->f = f; + if (topinmin) + f = -f; + } else { + int ifps = ((0 < fpscode && fpscode < sizeof ifpss / sizeof ifpss[0])? + ifpss[fpscode]: (int)(fps + .5)); + s = f / ifps; + f %= ifps; + m = s / 60; + s %= 60; + h = m / 60; + m %= 60; + tc->f = f; + } + tc->s = s; + tc->m = m; + tc->h = h; + return f; +} diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/mpegtimecode.h b/branches/V-1.5.3/veejay-server/mjpegtools/mpegtimecode.h new file mode 100644 index 00000000..e702a9b7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/mpegtimecode.h @@ -0,0 +1,39 @@ +/* -*- mode:C -*- */ +/* + * Copyright (C) 2001 Kawamata/Hitoshi + * + * 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. + */ + +#ifndef __MPEGTIMECODE_H__ +#define __MPEGTIMECODE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char h, m, s, f; +} MPEG_timecode_t; + +extern int dropframetimecode; +extern int mpeg_timecode(MPEG_timecode_t *tc, int f, int fpscode, double fps); +/* mpeg_timecode() return -tc->f on first frame in the minute, tc->f on other. */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/videodev_mjpeg.h b/branches/V-1.5.3/veejay-server/mjpegtools/videodev_mjpeg.h new file mode 100644 index 00000000..68fd79c5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/videodev_mjpeg.h @@ -0,0 +1,118 @@ +/* These are the MJPEG API extensions for the Video4Linux API, + first introduced by the Iomega Buz driver by Rainer Johanni + +*/ + +/* This is identical with the mgavideo internal params struct, + please tell me if you change this struct here ! top-field-first */ + + int APPn; /* Number of APP segment to be written, must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + unsigned long jpeg_markers; /* Which markers should go into the JPEG output. + Unless you exactly know what you do, leave them untouched. + Inluding less markers will make the resulting code + smaller, but there will be fewer aplications + which can read it. + The presence of the APP and COM marker is + influenced by APP0_len and COM_len ONLY! */ +#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ + + int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. + If this flag is turned on and JPEG decompressing + is going to the screen, the decompress process + is stopped every time the Video Fifo is full. + This enables a smooth decompress to the screen + but the video output signal will get scrambled */ + + /* Misc */ + + char reserved[312]; /* Makes 512 bytes for this structure */ +}; + +struct mjpeg_requestbuffers +{ + unsigned long count; /* Number of buffers for MJPEG grabbing */ + unsigned long size; /* Size PER BUFFER in bytes */ +}; + +struct mjpeg_sync +{ + unsigned long frame; /* Frame (0 - n) for double buffer */ + unsigned long length; /* number of code bytes in buffer (capture only) */ + unsigned long seq; /* frame sequence number */ + struct timeval timestamp; /* timestamp */ +}; + +struct mjpeg_status +{ + int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ + int signal; /* Returned: 1 if valid video signal detected */ + int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ + int color; /* Returned: 1 if color signal detected */ +}; + +/* +Private IOCTL to set up for displaying MJPEG +*/ +#define MJPIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct mjpeg_params) +#define MJPIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct mjpeg_params) +#define MJPIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct mjpeg_requestbuffers) +#define MJPIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) +#define MJPIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) +#define MJPIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct mjpeg_sync) +#define MJPIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct mjpeg_status) diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg.c b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg.c new file mode 100644 index 00000000..0d42fea1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg.c @@ -0,0 +1,1415 @@ +/* + * yuv4mpeg.c: Functions for reading and writing "new" YUV4MPEG streams + * + * Copyright (C) 2001 Matthew J. Marjanovic + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include +#include +#include +#define INTERNAL_Y4M_LIBCODE_STUFF_QPX +#include "yuv4mpeg.h" +#include "yuv4mpeg_intern.h" +#include +#include + + +static int _y4mparam_allow_unknown_tags = 1; /* default is forgiveness */ +static int _y4mparam_feature_level = 0; /* default is ol YUV4MPEG2 */ + +static void *(*_y4m_alloc)(size_t bytes) = malloc; +static void (*_y4m_free)(void *ptr) = free; + + +int y4m_allow_unknown_tags(int yn) +{ + int old = _y4mparam_allow_unknown_tags; + if (yn >= 0) + _y4mparam_allow_unknown_tags = (yn) ? 1 : 0; + return old; +} + +int y4m_accept_extensions(int level) +{ + int old = _y4mparam_feature_level; + if (level >= 0) + _y4mparam_feature_level = level; + return old; +} + + +/************************************************************************* + * + * Convenience functions for fd read/write + * + * - guaranteed to transfer entire payload (or fail) + * - returns: + * 0 on complete success + * +(# of remaining bytes) on eof (for y4m_read) + * -(# of rem. bytes) on error (and ERRNO should be set) + * + *************************************************************************/ + +ssize_t y4m_read(int fd, void *buf, size_t len) +{ + ssize_t n; + uint8_t *ptr = (uint8_t *)buf; + + while (len > 0) { + n = read(fd, ptr, len); + if (n <= 0) { + /* return amount left to read */ + if (n == 0) + return len; /* n == 0 --> eof */ + else + return -len; /* n < 0 --> error */ + } + ptr += n; + len -= n; + } + return 0; +} + +ssize_t y4m_write(int fd, const void *buf, size_t len) +{ + ssize_t n; + const uint8_t *ptr = (const uint8_t *)buf; + + while (len > 0) { + n = write(fd, ptr, len); + if (n <= 0) return -len; /* return amount left to write */ + ptr += n; + len -= n; + } + return 0; +} + +/* read len bytes from fd into buf */ +ssize_t y4m_read_cb(y4m_cb_reader_t * fd, void *buf, size_t len) + { + return fd->read(fd->data, buf, len); + } + +/* write len bytes from fd into buf */ +ssize_t y4m_write_cb(y4m_cb_writer_t * fd, const void *buf, size_t len) + { + return fd->write(fd->data, buf, len); + } + +/* Functions to use the callback interface from plain filedescriptors */ + +/* read len bytes from fd into buf */ +ssize_t y4m_read_fd(void * data, void *buf, size_t len) + { + int * f = (int*)data; + return y4m_read(*f, buf, len); + } + +/* write len bytes from fd into buf */ +ssize_t y4m_write_fd(void * data, const void *buf, size_t len) + { + int * f = (int*)data; + return y4m_write(*f, buf, len); + } + +static void set_cb_reader_from_fd(y4m_cb_reader_t * ret, int * fd) + { + ret->read = y4m_read_fd; + ret->data = fd; + } + +static void set_cb_writer_from_fd(y4m_cb_writer_t * ret, int * fd) + { + ret->write = y4m_write_fd; + ret->data = fd; + } + + +/************************************************************************* + * + * "Extra tags" handling + * + *************************************************************************/ + +static char *y4m_new_xtag(void) +{ + return _y4m_alloc(Y4M_MAX_XTAG_SIZE * sizeof(char)); +} + +void y4m_init_xtag_list(y4m_xtag_list_t *xtags) +{ + int i; + xtags->count = 0; + for (i = 0; i < Y4M_MAX_XTAGS; i++) { + xtags->tags[i] = NULL; + } +} + +void y4m_fini_xtag_list(y4m_xtag_list_t *xtags) +{ + int i; + for (i = 0; i < Y4M_MAX_XTAGS; i++) { + if (xtags->tags[i] != NULL) { + _y4m_free(xtags->tags[i]); + xtags->tags[i] = NULL; + } + } + xtags->count = 0; +} + +void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src) +{ + int i; + for (i = 0; i < src->count; i++) { + if (dest->tags[i] == NULL) + dest->tags[i] = y4m_new_xtag(); + strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); + } + dest->count = src->count; +} + +static int y4m_snprint_xtags(char *s, int maxn, const y4m_xtag_list_t *xtags) +{ + int i, room; + + for (i = 0, room = maxn - 1; i < xtags->count; i++) { + int n = snprintf(s, room + 1, " %s", xtags->tags[i]); + if ((n < 0) || (n > room)) return Y4M_ERR_HEADER; + s += n; + room -= n; + } + s[0] = '\n'; /* finish off header with newline */ + s[1] = '\0'; /* ...and end-of-string */ + return Y4M_OK; +} + +int y4m_xtag_count(const y4m_xtag_list_t *xtags) +{ + return xtags->count; +} + +const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n) +{ + if (n >= xtags->count) + return NULL; + else + return xtags->tags[n]; +} + +int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag) +{ + if (xtags->count >= Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS; + if (xtags->tags[xtags->count] == NULL) + xtags->tags[xtags->count] = y4m_new_xtag(); + strncpy(xtags->tags[xtags->count], tag, Y4M_MAX_XTAG_SIZE); + (xtags->count)++; + return Y4M_OK; +} + +int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n) +{ + int i; + char *q; + + if ((n < 0) || (n >= xtags->count)) return Y4M_ERR_RANGE; + q = xtags->tags[n]; + for (i = n; i < (xtags->count - 1); i++) + xtags->tags[i] = xtags->tags[i+1]; + xtags->tags[i] = q; + (xtags->count)--; + return Y4M_OK; +} + +int y4m_xtag_clearlist(y4m_xtag_list_t *xtags) +{ + xtags->count = 0; + return Y4M_OK; +} + +int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src) +{ + int i, j; + + if ((dest->count + src->count) > Y4M_MAX_XTAGS) return Y4M_ERR_XXTAGS; + for (i = dest->count, j = 0; + j < src->count; + i++, j++) { + if (dest->tags[i] == NULL) + dest->tags[i] = y4m_new_xtag(); + strncpy(dest->tags[i], src->tags[i], Y4M_MAX_XTAG_SIZE); + } + dest->count += src->count; + return Y4M_OK; +} + + +/************************************************************************* + * + * Creators/destructors for y4m_*_info_t structures + * + *************************************************************************/ + +void y4m_init_stream_info(y4m_stream_info_t *info) +{ + if (info == NULL) return; + /* init substructures */ + y4m_init_xtag_list(&(info->x_tags)); + /* set defaults */ + y4m_clear_stream_info(info); +} + +void y4m_clear_stream_info(y4m_stream_info_t *info) +{ + if (info == NULL) return; + /* clear/initialize info */ + info->width = Y4M_UNKNOWN; + info->height = Y4M_UNKNOWN; + info->interlace = Y4M_UNKNOWN; + info->framerate = y4m_fps_UNKNOWN; + info->sampleaspect = y4m_sar_UNKNOWN; + if (_y4mparam_feature_level < 1) { + info->chroma = Y4M_CHROMA_420JPEG; + } else { + info->chroma = Y4M_UNKNOWN; + } + y4m_xtag_clearlist(&(info->x_tags)); +} + +void y4m_copy_stream_info(y4m_stream_info_t *dest, + const y4m_stream_info_t *src) +{ + if ((dest == NULL) || (src == NULL)) return; + /* copy info */ + dest->width = src->width; + dest->height = src->height; + dest->interlace = src->interlace; + dest->framerate = src->framerate; + dest->sampleaspect = src->sampleaspect; + dest->chroma = src->chroma; + y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags)); +} + +// returns 0 if equal, nonzero if different +static int y4m_compare_stream_info(const y4m_stream_info_t *s1,const y4m_stream_info_t *s2) +{ + int i,j; + + if( s1->width != s2->width || + s1->height != s2->height || + s1->interlace != s2->interlace || + s1->framerate.n != s2->framerate.n || + s1->framerate.d != s2->framerate.d || + s1->sampleaspect.n != s2->sampleaspect.n || + s1->sampleaspect.d != s2->sampleaspect.d || + s1->chroma != s2->chroma || + s1->x_tags.count != s2->x_tags.count ) + return 1; + + // the tags may not be in the same order + for( i=0; ix_tags.count; i++ ) { + for( j=0; jx_tags.count; j++ ) + if( !strncmp(s1->x_tags.tags[i],s2->x_tags.tags[j],Y4M_MAX_XTAG_SIZE) ) + goto next; + return 1; + next:; + } + return 0; +} + +void y4m_fini_stream_info(y4m_stream_info_t *info) +{ + if (info == NULL) return; + y4m_fini_xtag_list(&(info->x_tags)); +} + +void y4m_si_set_width(y4m_stream_info_t *si, int width) +{ + si->width = width; +} + +int y4m_si_get_width(const y4m_stream_info_t *si) +{ return si->width; } + +void y4m_si_set_height(y4m_stream_info_t *si, int height) +{ + si->height = height; +} + +int y4m_si_get_height(const y4m_stream_info_t *si) +{ return si->height; } + +void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace) +{ si->interlace = interlace; } + +int y4m_si_get_interlace(const y4m_stream_info_t *si) +{ return si->interlace; } + +void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate) +{ si->framerate = framerate; } + +y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si) +{ return si->framerate; } + +void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar) +{ si->sampleaspect = sar; } + +y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si) +{ return si->sampleaspect; } + +void y4m_si_set_chroma(y4m_stream_info_t *si, int chroma_mode) +{ si->chroma = chroma_mode; } + +int y4m_si_get_chroma(const y4m_stream_info_t *si) +{ return si->chroma; } + + +int y4m_si_get_plane_count(const y4m_stream_info_t *si) +{ + switch (si->chroma) { + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + case Y4M_CHROMA_444: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + return 3; + case Y4M_CHROMA_MONO: + return 1; + case Y4M_CHROMA_444ALPHA: + return 4; + default: + return Y4M_UNKNOWN; + } +} + +int y4m_si_get_plane_width(const y4m_stream_info_t *si, int plane) +{ + switch (plane) { + case 0: + return (si->width); + case 1: + case 2: + switch (si->chroma) { + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + return (si->width) / 2; + case Y4M_CHROMA_444: + case Y4M_CHROMA_444ALPHA: + return (si->width); + case Y4M_CHROMA_422: + return (si->width) / 2; + case Y4M_CHROMA_411: + return (si->width) / 4; + default: + return Y4M_UNKNOWN; + } + case 3: + switch (si->chroma) { + case Y4M_CHROMA_444ALPHA: + return (si->width); + default: + return Y4M_UNKNOWN; + } + default: + return Y4M_UNKNOWN; + } +} + +int y4m_si_get_plane_height(const y4m_stream_info_t *si, int plane) +{ + switch (plane) { + case 0: + return (si->height); + case 1: + case 2: + switch (si->chroma) { + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + return (si->height) / 2; + case Y4M_CHROMA_444: + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + return (si->height); + default: + return Y4M_UNKNOWN; + } + case 3: + switch (si->chroma) { + case Y4M_CHROMA_444ALPHA: + return (si->height); + default: + return Y4M_UNKNOWN; + } + default: + return Y4M_UNKNOWN; + } +} + +int y4m_si_get_plane_length(const y4m_stream_info_t *si, int plane) +{ + int w = y4m_si_get_plane_width(si, plane); + int h = y4m_si_get_plane_height(si, plane); + if ((w != Y4M_UNKNOWN) && (h != Y4M_UNKNOWN)) + return (w * h); + else + return Y4M_UNKNOWN; +} + +int y4m_si_get_framelength(const y4m_stream_info_t *si) +{ + int total = 0; + int planes = y4m_si_get_plane_count(si); + int p; + for (p = 0; p < planes; p++) { + int plen = y4m_si_get_plane_length(si, p); + if (plen == Y4M_UNKNOWN) return Y4M_UNKNOWN; + total += plen; + } + return total; +} + +y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si) +{ return &(si->x_tags); } + + +void y4m_init_frame_info(y4m_frame_info_t *info) +{ + if (info == NULL) return; + /* init substructures */ + y4m_init_xtag_list(&(info->x_tags)); + /* set defaults */ + y4m_clear_frame_info(info); +} + +void y4m_clear_frame_info(y4m_frame_info_t *info) +{ + if (info == NULL) return; + /* clear/initialize info */ + info->spatial = Y4M_UNKNOWN; + info->temporal = Y4M_UNKNOWN; + info->presentation = Y4M_UNKNOWN; + y4m_xtag_clearlist(&(info->x_tags)); +} + +void y4m_copy_frame_info(y4m_frame_info_t *dest, const y4m_frame_info_t *src) +{ + if ((dest == NULL) || (src == NULL)) return; + /* copy info */ + dest->spatial = src->spatial; + dest->temporal = src->temporal; + dest->presentation = src->presentation; + y4m_copy_xtag_list(&(dest->x_tags), &(src->x_tags)); +} + +void y4m_fini_frame_info(y4m_frame_info_t *info) +{ + if (info == NULL) return; + y4m_fini_xtag_list(&(info->x_tags)); +} + +void y4m_fi_set_presentation(y4m_frame_info_t *fi, int pres) +{ fi->presentation = pres; } + +int y4m_fi_get_presentation(const y4m_frame_info_t *fi) +{ return fi->presentation; } + +void y4m_fi_set_temporal(y4m_frame_info_t *fi, int sampling) +{ fi->temporal = sampling; } + +int y4m_fi_get_temporal(const y4m_frame_info_t *fi) +{ return fi->temporal; } + +void y4m_fi_set_spatial(y4m_frame_info_t *fi, int sampling) +{ fi->spatial = sampling; } + +int y4m_fi_get_spatial(const y4m_frame_info_t *fi) +{ return fi->spatial; } + +y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi) +{ return &(fi->x_tags); } + + +/************************************************************************* + * + * Tag parsing + * + *************************************************************************/ + +int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i) +{ + char *token, *value; + char tag; + int err; + + /* parse fields */ + for (token = strtok(s, Y4M_DELIM); + token != NULL; + token = strtok(NULL, Y4M_DELIM)) { + if (token[0] == '\0') continue; /* skip empty strings */ + tag = token[0]; + value = token + 1; + switch (tag) { + case 'W': /* width */ + i->width = atoi(value); + if (i->width <= 0) return Y4M_ERR_RANGE; + break; + case 'H': /* height */ + i->height = atoi(value); + if (i->height <= 0) return Y4M_ERR_RANGE; + break; + case 'F': /* frame rate (fps) */ + if ((err = y4m_parse_ratio(&(i->framerate), value)) != Y4M_OK) + return err; + if (i->framerate.n < 0) return Y4M_ERR_RANGE; + break; + case 'I': /* interlacing */ + switch (value[0]) { + case 'p': i->interlace = Y4M_ILACE_NONE; break; + case 't': i->interlace = Y4M_ILACE_TOP_FIRST; break; + case 'b': i->interlace = Y4M_ILACE_BOTTOM_FIRST; break; + case 'm': i->interlace = Y4M_ILACE_MIXED; break; + case '?': + default: + i->interlace = Y4M_UNKNOWN; break; + } + break; + case 'A': /* sample (pixel) aspect ratio */ + if ((err = y4m_parse_ratio(&(i->sampleaspect), value)) != Y4M_OK) + return err; + if (i->sampleaspect.n < 0) return Y4M_ERR_RANGE; + break; + case 'C': + i->chroma = y4m_chroma_parse_keyword(value); + if (i->chroma == Y4M_UNKNOWN) + return Y4M_ERR_HEADER; + break; + case 'X': /* 'X' meta-tag */ + if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; + break; + default: + /* possible error on unknown options */ + if (_y4mparam_allow_unknown_tags) { + /* unknown tags ok: store in xtag list and warn... */ + if ((err = y4m_xtag_add(&(i->x_tags), token)) != Y4M_OK) return err; + mjpeg_warn("Unknown stream tag encountered: '%s'", token); + } else { + /* unknown tags are *not* ok */ + return Y4M_ERR_BADTAG; + } + break; + } + } + + /* Without 'C' tag or any other chroma spec, default to 420jpeg */ + if (i->chroma == Y4M_UNKNOWN) + i->chroma = Y4M_CHROMA_420JPEG; + + /* Error checking... */ + /* - Width and Height are required. */ + if ((i->width == Y4M_UNKNOWN) || (i->height == Y4M_UNKNOWN)) + return Y4M_ERR_HEADER; + /* - Non-420 chroma and mixed interlace require level >= 1 */ + if (_y4mparam_feature_level < 1) { + if ((i->chroma != Y4M_CHROMA_420JPEG) && + (i->chroma != Y4M_CHROMA_420MPEG2) && + (i->chroma != Y4M_CHROMA_420PALDV)) + return Y4M_ERR_FEATURE; + if (i->interlace == Y4M_ILACE_MIXED) + return Y4M_ERR_FEATURE; + } + + /* ta da! done. */ + return Y4M_OK; +} + + + +static int y4m_parse_frame_tags(char *s, const y4m_stream_info_t *si, + y4m_frame_info_t *fi) +{ + char *token, *value; + char tag; + int err; + + /* parse fields */ + for (token = strtok(s, Y4M_DELIM); + token != NULL; + token = strtok(NULL, Y4M_DELIM)) { + if (token[0] == '\0') continue; /* skip empty strings */ + tag = token[0]; + value = token + 1; + switch (tag) { + case 'I': + /* frame 'I' tag requires feature level >= 1 */ + if (_y4mparam_feature_level < 1) return Y4M_ERR_FEATURE; + if (si->interlace != Y4M_ILACE_MIXED) return Y4M_ERR_BADTAG; + switch (value[0]) { + case 't': fi->presentation = Y4M_PRESENT_TOP_FIRST; break; + case 'T': fi->presentation = Y4M_PRESENT_TOP_FIRST_RPT; break; + case 'b': fi->presentation = Y4M_PRESENT_BOTTOM_FIRST; break; + case 'B': fi->presentation = Y4M_PRESENT_BOTTOM_FIRST_RPT; break; + case '1': fi->presentation = Y4M_PRESENT_PROG_SINGLE; break; + case '2': fi->presentation = Y4M_PRESENT_PROG_DOUBLE; break; + case '3': fi->presentation = Y4M_PRESENT_PROG_TRIPLE; break; + default: + return Y4M_ERR_BADTAG; + } + switch (value[1]) { + case 'p': fi->temporal = Y4M_SAMPLING_PROGRESSIVE; break; + case 'i': fi->temporal = Y4M_SAMPLING_INTERLACED; break; + default: + return Y4M_ERR_BADTAG; + } + switch (value[2]) { + case 'p': fi->spatial = Y4M_SAMPLING_PROGRESSIVE; break; + case 'i': fi->spatial = Y4M_SAMPLING_INTERLACED; break; + case '?': fi->spatial = Y4M_UNKNOWN; break; + default: + return Y4M_ERR_BADTAG; + } + break; + case 'X': /* 'X' meta-tag */ + if ((err = y4m_xtag_add(&(fi->x_tags), token)) != Y4M_OK) return err; + break; + default: + /* possible error on unknown options */ + if (_y4mparam_allow_unknown_tags) { + /* unknown tags ok: store in xtag list and warn... */ + if ((err = y4m_xtag_add(&(fi->x_tags), token)) != Y4M_OK) return err; + mjpeg_warn("Unknown frame tag encountered: '%s'", token); + } else { + /* unknown tags are *not* ok */ + return Y4M_ERR_BADTAG; + } + break; + } + } + /* error-checking and/or non-mixed defaults */ + switch (si->interlace) { + case Y4M_ILACE_MIXED: + /* T and P are required if stream "Im" */ + if ((fi->presentation == Y4M_UNKNOWN) || (fi->temporal == Y4M_UNKNOWN)) + return Y4M_ERR_HEADER; + /* and S is required if stream is also 4:2:0 */ + if ( ((si->chroma == Y4M_CHROMA_420JPEG) || + (si->chroma == Y4M_CHROMA_420MPEG2) || + (si->chroma == Y4M_CHROMA_420PALDV)) && + (fi->spatial == Y4M_UNKNOWN) ) + return Y4M_ERR_HEADER; + break; + case Y4M_ILACE_NONE: + /* stream "Ip" --> equivalent to frame "I1pp" */ + fi->spatial = Y4M_SAMPLING_PROGRESSIVE; + fi->temporal = Y4M_SAMPLING_PROGRESSIVE; + fi->presentation = Y4M_PRESENT_PROG_SINGLE; + break; + case Y4M_ILACE_TOP_FIRST: + /* stream "It" --> equivalent to frame "Itii" */ + fi->spatial = Y4M_SAMPLING_INTERLACED; + fi->temporal = Y4M_SAMPLING_INTERLACED; + fi->presentation = Y4M_PRESENT_TOP_FIRST; + break; + case Y4M_ILACE_BOTTOM_FIRST: + /* stream "Ib" --> equivalent to frame "Ibii" */ + fi->spatial = Y4M_SAMPLING_INTERLACED; + fi->temporal = Y4M_SAMPLING_INTERLACED; + fi->presentation = Y4M_PRESENT_BOTTOM_FIRST; + break; + default: + /* stream unknown: then, whatever */ + break; + } + /* ta da! done. */ + return Y4M_OK; +} + + + + + +/************************************************************************* + * + * Read/Write stream header + * + *************************************************************************/ + + +static int y4m_read_stream_header_line_cb(y4m_cb_reader_t * fd, y4m_stream_info_t *i,char *line,int n) +{ + int err; + + /* start with a clean slate */ + y4m_clear_stream_info(i); + /* read the header line */ + for (; n < Y4M_LINE_MAX; n++) { + if (y4m_read_cb(fd, line+n, 1)) + return Y4M_ERR_SYSTEM; + if (line[n] == '\n') { + line[n] = '\0'; /* Replace linefeed by end of string */ + break; + } + } + /* look for keyword in header */ + if (strncmp(line, Y4M_MAGIC, strlen(Y4M_MAGIC))) + return Y4M_ERR_MAGIC; + if (n >= Y4M_LINE_MAX) + return Y4M_ERR_HEADER; + if ((err = y4m_parse_stream_tags(line + strlen(Y4M_MAGIC), i)) != Y4M_OK) + return err; + + return Y4M_OK; +} + +static int y4m_reread_stream_header_line_cb(y4m_cb_reader_t *fd,const y4m_stream_info_t *si,char *line,int n) +{ + y4m_stream_info_t i; + int err=y4m_read_stream_header_line_cb(fd,&i,line,n); + if( err==Y4M_OK && y4m_compare_stream_info(si,&i) ) + err=Y4M_ERR_HEADER; + y4m_fini_stream_info(&i); + return err; +} + +int y4m_read_stream_header_cb(y4m_cb_reader_t *fd, y4m_stream_info_t *i) +{ + char line[Y4M_LINE_MAX]; + + return y4m_read_stream_header_line_cb(fd,i,line,0); +} + +int y4m_read_stream_header(int fd, y4m_stream_info_t *i) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_stream_header_cb(&r, i); +} + +int y4m_write_stream_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *i) +{ + char s[Y4M_LINE_MAX+1]; + int n; + int err; + y4m_ratio_t rate = i->framerate; + y4m_ratio_t aspect = i->sampleaspect; + const char *chroma_keyword = y4m_chroma_keyword(i->chroma); + + if ((i->chroma == Y4M_UNKNOWN) || (chroma_keyword == NULL)) + return Y4M_ERR_HEADER; + if (_y4mparam_feature_level < 1) { + if ((i->chroma != Y4M_CHROMA_420JPEG) && + (i->chroma != Y4M_CHROMA_420MPEG2) && + (i->chroma != Y4M_CHROMA_420PALDV)) + return Y4M_ERR_FEATURE; + if (i->interlace == Y4M_ILACE_MIXED) + return Y4M_ERR_FEATURE; + } + y4m_ratio_reduce(&rate); + y4m_ratio_reduce(&aspect); + n = snprintf(s, sizeof(s), "%s W%d H%d F%d:%d I%s A%d:%d C%s", + Y4M_MAGIC, + i->width, + i->height, + rate.n, rate.d, + (i->interlace == Y4M_ILACE_NONE) ? "p" : + (i->interlace == Y4M_ILACE_TOP_FIRST) ? "t" : + (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "b" : + (i->interlace == Y4M_ILACE_MIXED) ? "m" : "?", + aspect.n, aspect.d, + chroma_keyword + ); + if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; + if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(i->x_tags))) + != Y4M_OK) + return err; + /* non-zero on error */ + return (y4m_write_cb(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK); +} + +int y4m_write_stream_header(int fd, const y4m_stream_info_t *i) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_stream_header_cb(&w, i); +} + + + + +/************************************************************************* + * + * Read/Write frame header + * + *************************************************************************/ + +int y4m_read_frame_header_cb(y4m_cb_reader_t * fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi) +{ + char line[Y4M_LINE_MAX]; + char *p; + int n; + ssize_t remain; + + again: + /* start with a clean slate */ + y4m_clear_frame_info(fi); + /* This is more clever than read_stream_header... + Try to read "FRAME\n" all at once, and don't try to parse + if nothing else is there... + */ + remain = y4m_read_cb(fd, line, sizeof(Y4M_FRAME_MAGIC)-1+1); /* -'\0', +'\n' */ + if (remain < 0) return Y4M_ERR_SYSTEM; + if (remain > 0) { + /* A clean EOF should end exactly at a frame-boundary */ + if (remain == sizeof(Y4M_FRAME_MAGIC)) + return Y4M_ERR_EOF; + else + return Y4M_ERR_BADEOF; + } + if (strncmp(line, Y4M_FRAME_MAGIC, sizeof(Y4M_FRAME_MAGIC)-1)) { + int err=y4m_reread_stream_header_line_cb(fd,si,line,sizeof(Y4M_FRAME_MAGIC)-1+1); + if( err!=Y4M_OK ) + return err; + goto again; + } + if (line[sizeof(Y4M_FRAME_MAGIC)-1] == '\n') + return Y4M_OK; /* done -- no tags: that was the end-of-line. */ + + if (line[sizeof(Y4M_FRAME_MAGIC)-1] != Y4M_DELIM[0]) { + return Y4M_ERR_MAGIC; /* wasn't a space -- what was it? */ + } + + /* proceed to get the tags... (overwrite the magic) */ + for (n = 0, p = line; n < Y4M_LINE_MAX; n++, p++) { + if (y4m_read_cb(fd, p, 1)) + return Y4M_ERR_SYSTEM; + if (*p == '\n') { + *p = '\0'; /* Replace linefeed by end of string */ + break; + } + } + if (n >= Y4M_LINE_MAX) return Y4M_ERR_HEADER; + /* non-zero on error */ + return y4m_parse_frame_tags(line, si, fi); +} + +int y4m_read_frame_header(int fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi) + { + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_frame_header_cb(&r, si, fi); + } + + +int y4m_write_frame_header_cb(y4m_cb_writer_t * fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi) +{ + char s[Y4M_LINE_MAX+1]; + int n, err; + + if (si->interlace == Y4M_ILACE_MIXED) { + if (_y4mparam_feature_level < 1) return Y4M_ERR_FEATURE; + n = snprintf(s, sizeof(s), "%s I%c%c%c", Y4M_FRAME_MAGIC, + (fi->presentation == Y4M_PRESENT_TOP_FIRST) ? 't' : + (fi->presentation == Y4M_PRESENT_TOP_FIRST_RPT) ? 'T' : + (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST) ? 'b' : + (fi->presentation == Y4M_PRESENT_BOTTOM_FIRST_RPT) ? 'B' : + (fi->presentation == Y4M_PRESENT_PROG_SINGLE) ? '1' : + (fi->presentation == Y4M_PRESENT_PROG_DOUBLE) ? '2' : + (fi->presentation == Y4M_PRESENT_PROG_TRIPLE) ? '3' : + '?', + (fi->temporal == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : + (fi->temporal == Y4M_SAMPLING_INTERLACED) ? 'i' : + '?', + (fi->spatial == Y4M_SAMPLING_PROGRESSIVE) ? 'p' : + (fi->spatial == Y4M_SAMPLING_INTERLACED) ? 'i' : + '?' + ); + } else { + n = snprintf(s, sizeof(s), "%s", Y4M_FRAME_MAGIC); + } + + if ((n < 0) || (n > Y4M_LINE_MAX)) return Y4M_ERR_HEADER; + if ((err = y4m_snprint_xtags(s + n, sizeof(s) - n - 1, &(fi->x_tags))) + != Y4M_OK) + return err; + /* non-zero on error */ + return (y4m_write_cb(fd, s, strlen(s)) ? Y4M_ERR_SYSTEM : Y4M_OK); +} + +int y4m_write_frame_header(int fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_frame_header_cb(&w, si, fi); +} + +/************************************************************************* + * + * Read/Write entire frame + * + *************************************************************************/ + +int y4m_read_frame_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + int planes = y4m_si_get_plane_count(si); + int p; + + /* Read each plane */ + for (p = 0; p < planes; p++) { + int w = y4m_si_get_plane_width(si, p); + int h = y4m_si_get_plane_height(si, p); + if (y4m_read_cb(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; + } + return Y4M_OK; +} + +int y4m_read_frame_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_frame_data_cb(&r, si, fi, frame); +} + +int y4m_read_frame_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + int err; + + /* Read frame header */ + if ((err = y4m_read_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Read date */ + return y4m_read_frame_data_cb(fd, si, fi, frame); +} + +int y4m_read_frame(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *frame) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_frame_cb(&r, si, fi, frame); +} + + + +int y4m_write_frame_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *frame) +{ + int planes = y4m_si_get_plane_count(si); + int err, p; + + /* Write frame header */ + if ((err = y4m_write_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Write each plane */ + for (p = 0; p < planes; p++) { + int w = y4m_si_get_plane_width(si, p); + int h = y4m_si_get_plane_height(si, p); + if (y4m_write_cb(fd, frame[p], w*h)) return Y4M_ERR_SYSTEM; + } + return Y4M_OK; +} + +int y4m_write_frame(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *frame) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_frame_cb(&w, si, fi, frame); +} + +/************************************************************************* + * + * Read/Write entire frame, (de)interleaved (to)from two separate fields + * + *************************************************************************/ + + +int y4m_read_fields_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + int p; + int planes = y4m_si_get_plane_count(si); + const int maxrbuf=32*1024; + uint8_t *rbuf=_y4m_alloc(maxrbuf); + int rbufpos=0,rbuflen=0; + + /* Read each plane */ + for (p = 0; p < planes; p++) { + uint8_t *dsttop = upper_field[p]; + uint8_t *dstbot = lower_field[p]; + int height = y4m_si_get_plane_height(si, p); + int width = y4m_si_get_plane_width(si, p); + int y; + /* alternately read one line into each field */ + for (y = 0; y < height; y += 2) { + if( width*2 >= maxrbuf ) { + if (y4m_read_cb(fd, dsttop, width)) goto y4merr; + if (y4m_read_cb(fd, dstbot, width)) goto y4merr; + } else { + if( rbufpos==rbuflen ) { + rbuflen=(height-y)*width; + if( rbuflen>maxrbuf ) + rbuflen=maxrbuf-maxrbuf%(2*width); + if( y4m_read_cb(fd,rbuf,rbuflen) ) + goto y4merr; + rbufpos=0; + } + + veejay_memcpy(dsttop,rbuf+rbufpos,width); rbufpos+=width; + veejay_memcpy(dstbot,rbuf+rbufpos,width); rbufpos+=width; + } + dsttop+=width; + dstbot+=width; + } + } + _y4m_free(rbuf); + return Y4M_OK; + + y4merr: + _y4m_free(rbuf); + return Y4M_ERR_SYSTEM; +} + +int y4m_read_fields_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_fields_data_cb(&r, si, fi, upper_field, lower_field); +} + + +int y4m_read_fields_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + int err; + /* Read frame header */ + if ((err = y4m_read_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Read data */ + return y4m_read_fields_data_cb(fd, si, fi, upper_field, lower_field); +} + +int y4m_read_fields(int fd, const y4m_stream_info_t *si, y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + y4m_cb_reader_t r; + set_cb_reader_from_fd(&r, &fd); + return y4m_read_fields_cb(&r, si, fi, upper_field, lower_field); +} + +int y4m_write_fields_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + int p, err; + int planes = y4m_si_get_plane_count(si); + int numwbuf=0; + const int maxwbuf=32*1024; + uint8_t *wbuf; + + /* Write frame header */ + if ((err = y4m_write_frame_header_cb(fd, si, fi)) != Y4M_OK) return err; + /* Write each plane */ + wbuf=_y4m_alloc(maxwbuf); + for (p = 0; p < planes; p++) { + uint8_t *srctop = upper_field[p]; + uint8_t *srcbot = lower_field[p]; + int height = y4m_si_get_plane_height(si, p); + int width = y4m_si_get_plane_width(si, p); + int y; + /* alternately write one line from each field */ + for (y = 0; y < height; y += 2) { + if( width*2 >= maxwbuf ) { + if (y4m_write_cb(fd, srctop, width)) goto y4merr; + if (y4m_write_cb(fd, srcbot, width)) goto y4merr; + } else { + if (numwbuf + 2 * width > maxwbuf) { + if(y4m_write_cb(fd, wbuf, numwbuf)) goto y4merr; + numwbuf=0; + } + + veejay_memcpy(wbuf+numwbuf,srctop,width); numwbuf += width; + veejay_memcpy(wbuf+numwbuf,srcbot,width); numwbuf += width; + } + srctop += width; + srcbot += width; + } + } + if( numwbuf ) + if( y4m_write_cb(fd, wbuf, numwbuf) ) + goto y4merr; + _y4m_free(wbuf); + return Y4M_OK; + + y4merr: + _y4m_free(wbuf); + return Y4M_ERR_SYSTEM; +} + +int y4m_write_fields(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field) +{ + y4m_cb_writer_t w; + set_cb_writer_from_fd(&w, &fd); + return y4m_write_fields_cb(&w, si, fi, upper_field, lower_field); +} + +/************************************************************************* + * + * Handy logging of stream info + * + *************************************************************************/ + +void y4m_log_stream_info(log_level_t level, const char *prefix, + const y4m_stream_info_t *i) +{ + char s[256]; + + snprintf(s, sizeof(s), " frame size: "); + if (i->width == Y4M_UNKNOWN) + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?)x"); + else + snprintf(s+strlen(s), sizeof(s)-strlen(s), "%dx", i->width); + if (i->height == Y4M_UNKNOWN) + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(?) pixels "); + else + snprintf(s+strlen(s), sizeof(s)-strlen(s), "%d pixels ", i->height); + { + int framelength = y4m_si_get_framelength(i); + if (framelength == Y4M_UNKNOWN) + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(? bytes)"); + else + snprintf(s+strlen(s), sizeof(s)-strlen(s), "(%d bytes)", framelength); + mjpeg_log(level, "%s%s", prefix, s); + } + { + const char *desc = y4m_chroma_description(i->chroma); + if (desc == NULL) desc = "unknown!"; + mjpeg_log(level, "%s chroma: %s", prefix, desc); + } + if ((i->framerate.n == 0) && (i->framerate.d == 0)) + mjpeg_log(level, "%s frame rate: ??? fps", prefix); + else + mjpeg_log(level, "%s frame rate: %d/%d fps (~%f)", prefix, + i->framerate.n, i->framerate.d, + (double) i->framerate.n / (double) i->framerate.d); + mjpeg_log(level, "%s interlace: %s", prefix, + (i->interlace == Y4M_ILACE_NONE) ? "none/progressive" : + (i->interlace == Y4M_ILACE_TOP_FIRST) ? "top-field-first" : + (i->interlace == Y4M_ILACE_BOTTOM_FIRST) ? "bottom-field-first" : + (i->interlace == Y4M_ILACE_MIXED) ? "mixed-mode" : + "anyone's guess"); + if ((i->sampleaspect.n == 0) && (i->sampleaspect.d == 0)) + mjpeg_log(level, "%ssample aspect ratio: ?:?", prefix); + else + mjpeg_log(level, "%ssample aspect ratio: %d:%d", prefix, + i->sampleaspect.n, i->sampleaspect.d); +} + + +/************************************************************************* + * + * Convert error code to string + * + *************************************************************************/ + +const char *y4m_strerr(int err) +{ + switch (err) { + case Y4M_OK: return "no error"; + case Y4M_ERR_RANGE: return "parameter out of range"; + case Y4M_ERR_SYSTEM: return "system error (failed read/write)"; + case Y4M_ERR_HEADER: return "bad stream or frame header"; + case Y4M_ERR_BADTAG: return "unknown header tag"; + case Y4M_ERR_MAGIC: return "bad header magic"; + case Y4M_ERR_XXTAGS: return "too many xtags"; + case Y4M_ERR_EOF: return "end-of-file"; + case Y4M_ERR_BADEOF: return "stream ended unexpectedly (EOF)"; + case Y4M_ERR_FEATURE: return "stream requires unsupported features"; + default: + return "unknown error code"; + } +} + + +/************************************************************************* + * + * Chroma subsampling stuff + * + *************************************************************************/ + +y4m_ratio_t y4m_chroma_ss_x_ratio(int chroma_mode) +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + r.n = 1; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + case Y4M_CHROMA_422: + r.n = 1; r.d = 2; break; + case Y4M_CHROMA_411: + r.n = 1; r.d = 4; break; + default: + r.n = 0; r.d = 0; + } + return r; +} + +y4m_ratio_t y4m_chroma_ss_y_ratio(int chroma_mode) +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + r.n = 1; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + r.n = 1; r.d = 2; break; + default: + r.n = 0; r.d = 0; + } + return r; +} + + +#if 0 /* unfinished work here */ +y4m_ratio_t y4m_chroma_ss_x_offset(int chroma_mode, int field, int plane) +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + r.n = 0; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + r.n = 1; r.d = 2; break; + default: + r.n = 0; r.d = 0; + } + return r; +} + +y4m_ratio_t y4m_chroma_ss_y_offset(int chroma_mode, int field, int plane); +{ + y4m_ratio_t r; + switch (chroma_mode) { + case Y4M_CHROMA_444ALPHA: + case Y4M_CHROMA_444: + case Y4M_CHROMA_MONO: + case Y4M_CHROMA_422: + case Y4M_CHROMA_411: + r.n = 0; r.d = 1; break; + case Y4M_CHROMA_420JPEG: + case Y4M_CHROMA_420MPEG2: + case Y4M_CHROMA_420PALDV: + r.n = 1; r.d = 2; break; + default: + r.n = 0; r.d = 0; + } + return r; +} +#endif + +int y4m_chroma_parse_keyword(const char *s) +{ + if (!strcasecmp("420jpeg", s)) + return Y4M_CHROMA_420JPEG; + else if (!strcasecmp("420mpeg2", s)) + return Y4M_CHROMA_420MPEG2; + else if (!strcasecmp("420paldv", s)) + return Y4M_CHROMA_420PALDV; + else if (!strcasecmp("444", s)) + return Y4M_CHROMA_444; + else if (!strcasecmp("422", s)) + return Y4M_CHROMA_422; + else if (!strcasecmp("411", s)) + return Y4M_CHROMA_411; + else if (!strcasecmp("mono", s)) + return Y4M_CHROMA_MONO; + else if (!strcasecmp("444alpha", s)) + return Y4M_CHROMA_444ALPHA; + else + return Y4M_UNKNOWN; +} + +const char *y4m_chroma_keyword(int chroma_mode) +{ + switch (chroma_mode) { + case Y4M_CHROMA_420JPEG: return "420jpeg"; + case Y4M_CHROMA_420MPEG2: return "420mpeg2"; + case Y4M_CHROMA_420PALDV: return "420paldv"; + case Y4M_CHROMA_444: return "444"; + case Y4M_CHROMA_422: return "422"; + case Y4M_CHROMA_411: return "411"; + case Y4M_CHROMA_MONO: return "mono"; + case Y4M_CHROMA_444ALPHA: return "444alpha"; + default: + return NULL; + } +} + +const char *y4m_chroma_description(int chroma_mode) +{ + switch (chroma_mode) { + case Y4M_CHROMA_420JPEG: return "4:2:0 JPEG/MPEG-1 (interstitial)"; + case Y4M_CHROMA_420MPEG2: return "4:2:0 MPEG-2 (horiz. cositing)"; + case Y4M_CHROMA_420PALDV: return "4:2:0 PAL-DV (altern. siting)"; + case Y4M_CHROMA_444: return "4:4:4 (no subsampling)"; + case Y4M_CHROMA_422: return "4:2:2 (horiz. cositing)"; + case Y4M_CHROMA_411: return "4:1:1 (horiz. cositing)"; + case Y4M_CHROMA_MONO: return "luma plane only"; + case Y4M_CHROMA_444ALPHA: return "4:4:4 with alpha channel"; + default: + return NULL; + } +} diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg.h b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg.h new file mode 100644 index 00000000..79a41f64 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg.h @@ -0,0 +1,757 @@ +/* + * yuv4mpeg.h: Functions for reading and writing "new" YUV4MPEG2 streams. + * + * Stream format is described at the end of this file. + * + * + * Copyright (C) 2004 Matthew J. Marjanovic + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __YUV4MPEG_H__ +#define __YUV4MPEG_H__ + +#include +#include +#ifndef _WIN32 +#include +#endif +#include + + +/************************************************************************ + * error codes returned by y4m_* functions + ************************************************************************/ +#define Y4M_OK 0 +#define Y4M_ERR_RANGE 1 /* argument or tag value out of range */ +#define Y4M_ERR_SYSTEM 2 /* failed system call, check errno */ +#define Y4M_ERR_HEADER 3 /* illegal/malformed header */ +#define Y4M_ERR_BADTAG 4 /* illegal tag character */ +#define Y4M_ERR_MAGIC 5 /* bad header magic */ +#define Y4M_ERR_EOF 6 /* end-of-file (clean) */ +#define Y4M_ERR_XXTAGS 7 /* too many xtags */ +#define Y4M_ERR_BADEOF 8 /* unexpected end-of-file */ +#define Y4M_ERR_FEATURE 9 /* stream requires features beyond allowed level */ + + +/* generic 'unknown' value for integer parameters (e.g. interlace, height) */ +#define Y4M_UNKNOWN -1 + +/************************************************************************ + * values for the "interlace" parameter [y4m_*_interlace()] + ************************************************************************/ +#define Y4M_ILACE_NONE 0 /* non-interlaced, progressive frame */ +#define Y4M_ILACE_TOP_FIRST 1 /* interlaced, top-field first */ +#define Y4M_ILACE_BOTTOM_FIRST 2 /* interlaced, bottom-field first */ +#define Y4M_ILACE_MIXED 3 /* mixed, "refer to frame header" */ + +/************************************************************************ + * values for the "chroma" parameter [y4m_*_chroma()] + ************************************************************************/ +#define Y4M_CHROMA_420JPEG 0 /* 4:2:0, H/V centered, for JPEG/MPEG-1 */ +#define Y4M_CHROMA_420MPEG2 1 /* 4:2:0, H cosited, for MPEG-2 */ +#define Y4M_CHROMA_420PALDV 2 /* 4:2:0, alternating Cb/Cr, for PAL-DV */ +#define Y4M_CHROMA_444 3 /* 4:4:4, no subsampling, phew. */ +#define Y4M_CHROMA_422 4 /* 4:2:2, H cosited */ +#define Y4M_CHROMA_411 5 /* 4:1:1, H cosited */ +#define Y4M_CHROMA_MONO 6 /* luma plane only */ +#define Y4M_CHROMA_444ALPHA 7 /* 4:4:4 with an alpha channel */ + +/************************************************************************ + * values for sampling parameters [y4m_*_spatial(), y4m_*_temporal()] + ************************************************************************/ +#define Y4M_SAMPLING_PROGRESSIVE 0 +#define Y4M_SAMPLING_INTERLACED 1 + +/************************************************************************ + * values for "presentation" parameter [y4m_*_presentation()] + ************************************************************************/ +#define Y4M_PRESENT_TOP_FIRST 0 /* top-field-first */ +#define Y4M_PRESENT_TOP_FIRST_RPT 1 /* top-first, repeat top */ +#define Y4M_PRESENT_BOTTOM_FIRST 2 /* bottom-field-first */ +#define Y4M_PRESENT_BOTTOM_FIRST_RPT 3 /* bottom-first, repeat bottom */ +#define Y4M_PRESENT_PROG_SINGLE 4 /* single progressive frame */ +#define Y4M_PRESENT_PROG_DOUBLE 5 /* progressive frame, repeat once */ +#define Y4M_PRESENT_PROG_TRIPLE 6 /* progressive frame, repeat twice */ + +#define Y4M_MAX_NUM_PLANES 4 + +/************************************************************************ + * 'ratio' datatype, for rational numbers + * (see 'ratio' functions down below) + ************************************************************************/ +typedef struct _y4m_ratio { + int n; /* numerator */ + int d; /* denominator */ +} y4m_ratio_t; + + +/************************************************************************ + * useful standard framerates (as ratios) + ************************************************************************/ +extern const y4m_ratio_t y4m_fps_UNKNOWN; +extern const y4m_ratio_t y4m_fps_NTSC_FILM; /* 24000/1001 film (in NTSC) */ +extern const y4m_ratio_t y4m_fps_FILM; /* 24fps film */ +extern const y4m_ratio_t y4m_fps_PAL; /* 25fps PAL */ +extern const y4m_ratio_t y4m_fps_NTSC; /* 30000/1001 NTSC */ +extern const y4m_ratio_t y4m_fps_30; /* 30fps */ +extern const y4m_ratio_t y4m_fps_PAL_FIELD; /* 50fps PAL field rate */ +extern const y4m_ratio_t y4m_fps_NTSC_FIELD; /* 60000/1001 NTSC field rate */ +extern const y4m_ratio_t y4m_fps_60; /* 60fps */ + +/************************************************************************ + * useful standard sample (pixel) aspect ratios (W:H) + ************************************************************************/ +extern const y4m_ratio_t y4m_sar_UNKNOWN; +extern const y4m_ratio_t y4m_sar_SQUARE; /* square pixels */ +extern const y4m_ratio_t y4m_sar_NTSC_CCIR601; /* 525-line (NTSC) Rec.601 */ +extern const y4m_ratio_t y4m_sar_NTSC_16_9; /* 16:9 NTSC/Rec.601 */ +extern const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3; /* NTSC SVCD 4:3 */ +extern const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9;/* NTSC SVCD 16:9 */ +extern const y4m_ratio_t y4m_sar_PAL_CCIR601; /* 625-line (PAL) Rec.601 */ +extern const y4m_ratio_t y4m_sar_PAL_16_9; /* 16:9 PAL/Rec.601 */ +extern const y4m_ratio_t y4m_sar_PAL_SVCD_4_3; /* PAL SVCD 4:3 */ +extern const y4m_ratio_t y4m_sar_PAL_SVCD_16_9; /* PAL SVCD 16:9 */ +extern const y4m_ratio_t y4m_sar_SQR_ANA16_9; /* anamorphic 16:9 sampled */ + /* from 4:3 with square pixels */ + +/************************************************************************ + * useful standard display aspect ratios (W:H) + ************************************************************************/ +extern const y4m_ratio_t y4m_dar_UNKNOWN; +extern const y4m_ratio_t y4m_dar_4_3; /* standard TV */ +extern const y4m_ratio_t y4m_dar_16_9; /* widescreen TV */ +extern const y4m_ratio_t y4m_dar_221_100; /* word-to-your-mother TV */ + + +#define Y4M_MAX_XTAGS 32 /* maximum number of xtags in list */ +#define Y4M_MAX_XTAG_SIZE 32 /* max length of an xtag (including 'X') */ + +typedef struct _y4m_xtag_list y4m_xtag_list_t; +typedef struct _y4m_stream_info y4m_stream_info_t; +typedef struct _y4m_frame_info y4m_frame_info_t; + + +#ifdef __cplusplus +#define BEGIN_CDECLS extern "C" { +#define END_CDECLS } +#else +#define BEGIN_CDECLS +#define END_CDECLS +#endif + +BEGIN_CDECLS + +/************************************************************************ + * 'ratio' functions + ************************************************************************/ + +/* 'normalize' a ratio (remove common factors) */ +void y4m_ratio_reduce(y4m_ratio_t *r); + +/* parse "nnn:ddd" into a ratio (returns Y4M_OK or Y4M_ERR_RANGE) */ +int y4m_parse_ratio(y4m_ratio_t *r, const char *s); + +/* quick test of two ratios for equality (i.e. identical components) */ +#define Y4M_RATIO_EQL(a,b) ( ((a).n == (b).n) && ((a).d == (b).d) ) + +/* quick conversion of a ratio to a double (no divide-by-zero check!) */ +#define Y4M_RATIO_DBL(r) ((double)(r).n / (double)(r).d) + +/************************************************************************* + * + * Guess the true SAR (sample aspect ratio) from a list of commonly + * encountered values, given the "suggested" display aspect ratio (DAR), + * and the true frame width and height. + * + * Returns y4m_sar_UNKNOWN if no match is found. + * + *************************************************************************/ +y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar); + + +/************************************************************************* + * + * Chroma Subsampling Mode information + * + * x_ratio, y_ratio - subsampling of chroma planes + * x_offset, y_offset - offset of chroma sample grid, + * relative to luma (0,0) sample + * + *************************************************************************/ + +y4m_ratio_t y4m_chroma_ss_x_ratio(int chroma_mode); +y4m_ratio_t y4m_chroma_ss_y_ratio(int chroma_mode); +#if 0 +y4m_ratio_t y4m_chroma_ss_x_offset(int chroma_mode, int field, int plane); +y4m_ratio_t y4m_chroma_ss_y_offset(int chroma_mode, int field, int plane); +#endif + +/* Given a string containing a (case-insensitive) chroma-tag keyword, + return appropriate chroma mode (or Y4M_UNKNOWN) */ +int y4m_chroma_parse_keyword(const char *s); + +/* Given a Y4M_CHROMA_* mode, return appropriate chroma-tag keyword, + or NULL if there is none. */ +const char *y4m_chroma_keyword(int chroma_mode); + +/* Given a Y4M_CHROMA_* mode, return appropriate chroma mode description, + or NULL if there is none. */ +const char *y4m_chroma_description(int chroma_mode); + + + +/************************************************************************ + * 'xtag' functions + * + * o Before using an xtag_list (but after the structure/memory has been + * allocated), you must initialize it via y4m_init_xtag_list(). + * o After using an xtag_list (but before the structure is released), + * call y4m_fini_xtag_list() to free internal memory. + * + ************************************************************************/ + +/* initialize an xtag_list structure */ +void y4m_init_xtag_list(y4m_xtag_list_t *xtags); + +/* finalize an xtag_list structure */ +void y4m_fini_xtag_list(y4m_xtag_list_t *xtags); + +/* make one xtag_list into a copy of another */ +void y4m_copy_xtag_list(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); + +/* return number of tags in an xtag_list */ +int y4m_xtag_count(const y4m_xtag_list_t *xtags); + +/* access n'th tag in an xtag_list */ +const char *y4m_xtag_get(const y4m_xtag_list_t *xtags, int n); + +/* append a new tag to an xtag_list + returns: Y4M_OK - success + Y4M_ERR_XXTAGS - list is already full */ +int y4m_xtag_add(y4m_xtag_list_t *xtags, const char *tag); + +/* remove a tag from an xtag_list + returns: Y4M_OK - success + Y4M_ERR_RANGE - n is out of range */ +int y4m_xtag_remove(y4m_xtag_list_t *xtags, int n); + +/* remove all tags from an xtag_list + returns: Y4M_OK - success */ +int y4m_xtag_clearlist(y4m_xtag_list_t *xtags); + +/* append copies of tags from src list to dest list + returns: Y4M_OK - success + Y4M_ERR_XXTAGS - operation would overfill dest list */ +int y4m_xtag_addlist(y4m_xtag_list_t *dest, const y4m_xtag_list_t *src); + + + +/************************************************************************ + * '*_info' functions + * + * o Before using a *_info structure (but after the structure/memory has + * been allocated), you must initialize it via y4m_init_*_info(). + * o After using a *_info structure (but before the structure is released), + * call y4m_fini_*_info() to free internal memory. + * o Use the 'set' and 'get' accessors to modify or access the fields in + * the structures; don't touch the structure directly. (Ok, so there + * is no really convenient C syntax to prevent you from doing this, + * but we are all responsible programmers here, so just don't do it!) + * + ************************************************************************/ + +/* initialize a stream_info structure */ +void y4m_init_stream_info(y4m_stream_info_t *i); + +/* finalize a stream_info structure */ +void y4m_fini_stream_info(y4m_stream_info_t *i); + +/* reset stream_info back to default/unknown values */ +void y4m_clear_stream_info(y4m_stream_info_t *info); + +/* make one stream_info into a copy of another */ +void y4m_copy_stream_info(y4m_stream_info_t *dest, + const y4m_stream_info_t *src); + +/* access or set stream_info fields */ +/* level 0 */ +int y4m_si_get_width(const y4m_stream_info_t *si); +int y4m_si_get_height(const y4m_stream_info_t *si); +int y4m_si_get_interlace(const y4m_stream_info_t *si); +y4m_ratio_t y4m_si_get_framerate(const y4m_stream_info_t *si); +y4m_ratio_t y4m_si_get_sampleaspect(const y4m_stream_info_t *si); +void y4m_si_set_width(y4m_stream_info_t *si, int width); +void y4m_si_set_height(y4m_stream_info_t *si, int height); +void y4m_si_set_interlace(y4m_stream_info_t *si, int interlace); +void y4m_si_set_framerate(y4m_stream_info_t *si, y4m_ratio_t framerate); +void y4m_si_set_sampleaspect(y4m_stream_info_t *si, y4m_ratio_t sar); +/* level 1 */ +void y4m_si_set_chroma(y4m_stream_info_t *si, int chroma_mode); +int y4m_si_get_chroma(const y4m_stream_info_t *si); + +/* derived quantities (no setter) */ +/* level 0 */ +int y4m_si_get_framelength(const y4m_stream_info_t *si); +/* level 1 */ +int y4m_si_get_plane_count(const y4m_stream_info_t *si); +int y4m_si_get_plane_width(const y4m_stream_info_t *si, int plane); +int y4m_si_get_plane_height(const y4m_stream_info_t *si, int plane); +int y4m_si_get_plane_length(const y4m_stream_info_t *si, int plane); + + +/* access stream_info xtag_list */ +y4m_xtag_list_t *y4m_si_xtags(y4m_stream_info_t *si); + + +/* initialize a frame_info structure */ +void y4m_init_frame_info(y4m_frame_info_t *i); + +/* finalize a frame_info structure */ +void y4m_fini_frame_info(y4m_frame_info_t *i); + +/* reset frame_info back to default/unknown values */ +void y4m_clear_frame_info(y4m_frame_info_t *info); + +/* make one frame_info into a copy of another */ +void y4m_copy_frame_info(y4m_frame_info_t *dest, + const y4m_frame_info_t *src); + + +/* access or set frame_info fields (level 1) */ +int y4m_fi_get_presentation(const y4m_frame_info_t *fi); +int y4m_fi_get_temporal(const y4m_frame_info_t *fi); +int y4m_fi_get_spatial(const y4m_frame_info_t *fi); + +void y4m_fi_set_presentation(y4m_frame_info_t *fi, int pres); +void y4m_fi_set_temporal(y4m_frame_info_t *fi, int sampling); +void y4m_fi_set_spatial(y4m_frame_info_t *fi, int sampling); + + +/* access frame_info xtag_list */ +y4m_xtag_list_t *y4m_fi_xtags(y4m_frame_info_t *fi); + + +/************************************************************************ + * blocking read and write functions + * + * o guaranteed to transfer entire payload (or fail) + * o return values: + * 0 (zero) complete success + * -(# of remaining bytes) error (and errno left set) + * +(# of remaining bytes) EOF (for y4m_read only) + * + ************************************************************************/ + +/* read len bytes from fd into buf */ +ssize_t y4m_read(int fd, void *buf, size_t len); + +/* write len bytes from fd into buf */ +ssize_t y4m_write(int fd, const void *buf, size_t len); + +/************************************************************************ + * callback based read and write + * + * The structures y4m_cb_reader_t and y4m_cb_writer_t must be + * set up by the caller before and of the *_read_*_cb() or + * *_write_*_cb() functions are called. Te return values of + * the read() and write() members have the same meaning as for + * y4m_read() and y4m_write() + * + ************************************************************************/ + +typedef struct y4m_cb_reader_s + { + void * data; + ssize_t (*read)(void * data, void *buf, size_t len); + } y4m_cb_reader_t; + +typedef struct y4m_cb_writer_s + { + void * data; + ssize_t (*write)(void * data, const void *buf, size_t len); + } y4m_cb_writer_t; + +/* read len bytes from fd into buf */ +ssize_t y4m_read_cb(y4m_cb_reader_t * fd, void *buf, size_t len); + +/* write len bytes from fd into buf */ +ssize_t y4m_write_cb(y4m_cb_writer_t * fd, const void *buf, size_t len); + + +/************************************************************************ + * stream header processing functions + * + * o return values: + * Y4M_OK - success + * Y4M_ERR_* - error (see y4m_strerr() for descriptions) + * + ************************************************************************/ + +/* parse a string of stream header tags */ +int y4m_parse_stream_tags(char *s, y4m_stream_info_t *i); + +/* read a stream header from file descriptor fd + (the current contents of stream_info are erased first) */ +int y4m_read_stream_header(int fd, y4m_stream_info_t *i); + +/* read a stream header with a callback reader + (the current contents of stream_info are erased first) */ +int y4m_read_stream_header_cb(y4m_cb_reader_t * fd, y4m_stream_info_t *i); + +/* write a stream header to file descriptor fd */ +int y4m_write_stream_header(int fd, const y4m_stream_info_t *i); + +/* write a stream header with a callback writer */ +int y4m_write_stream_header_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *i); + + +/************************************************************************ + * frame processing functions + * + * o return values: + * Y4M_OK - success + * Y4M_ERR_* - error (see y4m_strerr() for descriptions) + * + ************************************************************************/ + +/* write a frame header to file descriptor fd */ +int y4m_write_frame_header(int fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi); + +/* write a frame header with a callback writer fd */ +int y4m_write_frame_header_cb(y4m_cb_writer_t * fd, + const y4m_stream_info_t *si, + const y4m_frame_info_t *fi); + +/* write a complete frame (header + data) to file descriptor fd + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_write_frame(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *planes); + +/* write a complete frame (header + data) with a callback writer fd + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_write_frame_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, uint8_t * const *planes); + +/* write a complete frame (header + data), to file descriptor fd + but interleave fields from two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_write_fields(int fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* write a complete frame (header + data), with a callback writer fd + but interleave fields from two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_write_fields_cb(y4m_cb_writer_t * fd, const y4m_stream_info_t *si, + const y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read a frame header from file descriptor fd + (the current contents of frame_info are erased first) */ +int y4m_read_frame_header(int fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi); + +/* read a frame header with callback reader fd + (the current contents of frame_info are erased first) */ +int y4m_read_frame_header_cb(y4m_cb_reader_t * fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi); + +/* read frame data from file descriptor fd + [to be called after y4m_read_frame_header()] + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read frame data with callback reader fd + [to be called after y4m_read_frame_header_cb()] + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame_data_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read frame data from file descriptor fd, + but de-interleave fields into two separate buffers + [to be called after y4m_read_frame_header()] + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields_data(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read frame data with callback reader fd, + but de-interleave fields into two separate buffers + [to be called after y4m_read_frame_header_cb()] + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields_data_cb(y4m_cb_reader_t * fd, + const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read a complete frame (header + data) from file descriptor fd, + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read a complete frame (header + data) from callback reader fd, + o planes[] points to 1-4 buffers, one each for image plane */ +int y4m_read_frame_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, uint8_t * const *planes); + +/* read a complete frame (header + data) from file descriptor fd, + but de-interleave fields into two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields(int fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/* read a complete frame (header + data) from callback_reader fd, + but de-interleave fields into two separate buffers + o upper_field[] same as planes[] above, but for upper field only + o lower_field[] same as planes[] above, but for lower field only +*/ +int y4m_read_fields_cb(y4m_cb_reader_t * fd, const y4m_stream_info_t *si, + y4m_frame_info_t *fi, + uint8_t * const *upper_field, + uint8_t * const *lower_field); + +/************************************************************************ + * miscellaneous functions + ************************************************************************/ + +/* convenient dump of stream header info via mjpeg_log facility + * - each logged/printed line is prefixed by 'prefix' + */ +void y4m_log_stream_info(log_level_t level, const char *prefix, + const y4m_stream_info_t *i); + +/* convert a Y4M_ERR_* error code into mildly explanatory string */ +const char *y4m_strerr(int err); + +/* set 'allow_unknown_tag' flag for library... + o yn = 0 : unknown header tags will produce a parsing error + o yn = 1 : unknown header tags/values will produce a warning, but + are otherwise passed along via the xtags list + o yn = -1: don't change, just return current setting + + return value: previous setting of flag +*/ +int y4m_allow_unknown_tags(int yn); + + +/* set level of "accepted extensions" for the library... + o level = 0: default - conform to original YUV4MPEG2 spec; yield errors + when reading or writing a stream which exceeds it. + o level = 1: allow reading/writing streams which contain non-420jpeg + chroma and/or mixed-mode interlacing + o level = -1: don't change, just return current setting + + return value: previous setting of level + */ +int y4m_accept_extensions(int level); + + +END_CDECLS + + +/************************************************************************ + ************************************************************************ + + Description of the (new!, forever?) YUV4MPEG2 stream format: + + STREAM consists of + o one '\n' terminated STREAM-HEADER + o unlimited number of FRAMEs + + FRAME consists of + o one '\n' terminated FRAME-HEADER + o "length" octets of planar YCrCb 4:2:0 image data + (if frame is interlaced, then the two fields are interleaved) + + + STREAM-HEADER consists of + o string "YUV4MPEG2" + o unlimited number TAGGED-FIELDs, each preceded by ' ' separator + o '\n' line terminator + + FRAME-HEADER consists of + o string "FRAME" + o unlimited number of TAGGED-FIELDs, each preceded by ' ' separator + o '\n' line terminator + + + TAGGED-FIELD consists of + o single ascii character tag + o VALUE (which does not contain whitespace) + + VALUE consists of + o integer (base 10 ascii representation) + or o RATIO + or o single ascii character + or o non-whitespace ascii string + + RATIO consists of + o numerator (integer) + o ':' (a colon) + o denominator (integer) + + + The currently supported tags for the STREAM-HEADER: + W - [integer] frame width, pixels, should be > 0 + H - [integer] frame height, pixels, should be > 0 + C - [string] chroma-subsampling/data format + 420jpeg (default) + 420mpeg2 + 420paldv + 411 + 422 + 444 - non-subsampled Y'CbCr + 444alpha - Y'CbCr with alpha channel (with Y' black/white point) + mono - Y' plane only + I - [char] interlacing: p - progressive (none) + t - top-field-first + b - bottom-field-first + m - mixed -- see 'I' tag in frame header + ? - unknown + F - [ratio] frame-rate, 0:0 == unknown + A - [ratio] sample (pixel) aspect ratio, 0:0 == unknown + X - [character string] 'metadata' (unparsed, but passed around) + + The currently supported tags for the FRAME-HEADER: + Ixyz - framing/sampling (required if-and-only-if stream is "Im") + x: t - top-field-first + T - top-field-first and repeat + b - bottom-field-first + B - bottom-field-first and repeat + 1 - single progressive frame + 2 - double progressive frame (repeat) + 3 - triple progressive frame (repeat twice) + + y: p - progressive: fields sampled at same time + i - interlaced: fields sampled at different times + + z: p - progressive: subsampling over whole frame + i - interlaced: each field subsampled independently + ? - unknown (allowed only for non-4:2:0 subsampling) + + X - character string 'metadata' (unparsed, but passed around) + + ************************************************************************ + ************************************************************************/ + + +/* + + THAT'S ALL FOLKS! + + Thank you for reading the source code. We hope you have thoroughly + enjoyed the experience. + +*/ + + + + + +#ifdef INTERNAL_Y4M_LIBCODE_STUFF_QPX +#define Y4MPRIVATIZE(identifier) identifier +#else +#define Y4MPRIVATIZE(identifier) PRIVATE##identifier +#endif + +/* + * Actual structure definitions of structures which you shouldn't touch. + * + */ + +/************************************************************************ + * 'xtag_list' --- list of unparsed and/or meta/X header tags + * + * Do not touch this structure directly! + * + * Use the y4m_xtag_*() functions (see below). + * You must initialize/finalize this structure before/after use. + ************************************************************************/ +struct _y4m_xtag_list { + int Y4MPRIVATIZE(count); + char *Y4MPRIVATIZE(tags)[Y4M_MAX_XTAGS]; +}; + + +/************************************************************************ + * 'stream_info' --- stream header information + * + * Do not touch this structure directly! + * + * Use the y4m_si_*() functions (see below). + * You must initialize/finalize this structure before/after use. + ************************************************************************/ +struct _y4m_stream_info { + /* values from header/setters */ + int Y4MPRIVATIZE(width); + int Y4MPRIVATIZE(height); + int Y4MPRIVATIZE(interlace); /* see Y4M_ILACE_* definitions */ + y4m_ratio_t Y4MPRIVATIZE(framerate); /* see Y4M_FPS_* definitions */ + y4m_ratio_t Y4MPRIVATIZE(sampleaspect); /* see Y4M_SAR_* definitions */ + int Y4MPRIVATIZE(chroma); /* see Y4M_CHROMA_* definitions */ + + /* mystical X tags */ + y4m_xtag_list_t Y4MPRIVATIZE(x_tags); +}; + + +/************************************************************************ + * 'frame_info' --- frame header information + * + * Do not touch this structure directly! + * + * Use the y4m_fi_*() functions (see below). + * You must initialize/finalize this structure before/after use. + ************************************************************************/ + +struct _y4m_frame_info { + int Y4MPRIVATIZE(spatial); /* see Y4M_SAMPLING_* definitions */ + int Y4MPRIVATIZE(temporal); /* see Y4M_SAMPLING_* definitions */ + int Y4MPRIVATIZE(presentation); /* see Y4M_PRESENT_* definitions */ + /* mystical X tags */ + y4m_xtag_list_t Y4MPRIVATIZE(x_tags); +}; + + +#undef Y4MPRIVATIZE + + +#endif /* __YUV4MPEG_H__ */ + + diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg_intern.h b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg_intern.h new file mode 100644 index 00000000..3ada1cba --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg_intern.h @@ -0,0 +1,85 @@ +/* + * yuv4mpeg_intern.h: Internal constants for "new" YUV4MPEG streams + * + * Copyright (C) 2001 Andrew Stevens + * Copyright (C) 2001 Matthew J. Marjanovic + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __YUV4MPEG_INTERN_H__ +#define __YUV4MPEG_INTERN_H__ + + +#define Y4M_MAGIC "YUV4MPEG2" +#define Y4M_FRAME_MAGIC "FRAME" + +#define Y4M_DELIM " " /* single-character(space) separating tagged fields */ + +#define Y4M_LINE_MAX 256 /* max number of characters in a header line + (including the '\n', but not the '\0') */ + + +/* standard framerate ratios */ +#define Y4M_FPS_UNKNOWN { 0, 0 } +#define Y4M_FPS_NTSC_FILM { 24000, 1001 } +#define Y4M_FPS_FILM { 24, 1 } +#define Y4M_FPS_PAL { 25, 1 } +#define Y4M_FPS_NTSC { 30000, 1001 } +#define Y4M_FPS_30 { 30, 1 } +#define Y4M_FPS_PAL_FIELD { 50, 1 } +#define Y4M_FPS_NTSC_FIELD { 60000, 1001 } +#define Y4M_FPS_60 { 60, 1 } + +/* standard sample/pixel aspect ratios */ +#define Y4M_SAR_UNKNOWN { 0, 0 } +#define Y4M_SAR_SQUARE { 1, 1 } +#define Y4M_SAR_SQR_ANA_16_9 { 4, 3 } +#define Y4M_SAR_NTSC_CCIR601 { 10, 11 } +#define Y4M_SAR_NTSC_16_9 { 40, 33 } +#define Y4M_SAR_NTSC_SVCD_4_3 { 15, 11 } +#define Y4M_SAR_NTSC_SVCD_16_9 { 20, 11 } +#define Y4M_SAR_PAL_CCIR601 { 59, 54 } +#define Y4M_SAR_PAL_16_9 { 118, 81 } +#define Y4M_SAR_PAL_SVCD_4_3 { 59, 36 } +#define Y4M_SAR_PAL_SVCD_16_9 { 59, 27 } + +#define Y4M_SAR_MPEG1_1 Y4M_SAR_SQUARE +#define Y4M_SAR_MPEG1_2 { 10000, 6735 } +#define Y4M_SAR_MPEG1_3 { 10000, 7031 } /* Anamorphic 16:9 PAL */ +#define Y4M_SAR_MPEG1_4 { 10000, 7615 } +#define Y4M_SAR_MPEG1_5 { 10000, 8055 } +#define Y4M_SAR_MPEG1_6 { 10000, 8437 } /* Anamorphic 16:9 NTSC */ +#define Y4M_SAR_MPEG1_7 { 10000, 8935 } +#define Y4M_SAR_MPEG1_8 { 10000, 9375 } /* PAL/SECAM 4:3 */ +#define Y4M_SAR_MPEG1_9 { 10000, 9815 } +#define Y4M_SAR_MPEG1_10 { 10000, 10255 } +#define Y4M_SAR_MPEG1_11 { 10000, 10695 } +#define Y4M_SAR_MPEG1_12 { 10000, 11250 } /* NTSC 4:3 */ +#define Y4M_SAR_MPEG1_13 { 10000, 11575 } +#define Y4M_SAR_MPEG1_14 { 10000, 12015 } + +#define Y4M_DAR_UNKNOWN { 0, 0 } +#define Y4M_DAR_4_3 { 4, 3 } +#define Y4M_DAR_16_9 { 16, 9 } +#define Y4M_DAR_221_100 { 221, 100 } + +#define Y4M_DAR_MPEG2_1 { 1, 1 } +#define Y4M_DAR_MPEG2_2 { 4, 3 } +#define Y4M_DAR_MPEG2_3 { 16, 9 } +#define Y4M_DAR_MPEG2_4 { 221, 100 } + +#endif /* __YUV4MPEG_INTERN_H__ */ + diff --git a/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg_ratio.c b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg_ratio.c new file mode 100644 index 00000000..7b50578c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/mjpegtools/yuv4mpeg_ratio.c @@ -0,0 +1,157 @@ +/* + * yuv4mpeg_ratio.c: Functions for dealing with y4m_ratio_t datatype. + * + * Copyright (C) 2001 Matthew J. Marjanovic + * + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include + +#include +#include "yuv4mpeg.h" +#include "yuv4mpeg_intern.h" + + +/* useful list of standard framerates */ +const y4m_ratio_t y4m_fps_UNKNOWN = Y4M_FPS_UNKNOWN; +const y4m_ratio_t y4m_fps_NTSC_FILM = Y4M_FPS_NTSC_FILM; +const y4m_ratio_t y4m_fps_FILM = Y4M_FPS_FILM; +const y4m_ratio_t y4m_fps_PAL = Y4M_FPS_PAL; +const y4m_ratio_t y4m_fps_NTSC = Y4M_FPS_NTSC; +const y4m_ratio_t y4m_fps_30 = Y4M_FPS_30; +const y4m_ratio_t y4m_fps_PAL_FIELD = Y4M_FPS_PAL_FIELD; +const y4m_ratio_t y4m_fps_NTSC_FIELD = Y4M_FPS_NTSC_FIELD; +const y4m_ratio_t y4m_fps_60 = Y4M_FPS_60; + +/* useful list of standard sample aspect ratios */ +const y4m_ratio_t y4m_sar_UNKNOWN = Y4M_SAR_UNKNOWN; +const y4m_ratio_t y4m_sar_SQUARE = Y4M_SAR_SQUARE; +const y4m_ratio_t y4m_sar_SQR_ANA_16_9 = Y4M_SAR_SQR_ANA_16_9; +const y4m_ratio_t y4m_sar_NTSC_CCIR601 = Y4M_SAR_NTSC_CCIR601; +const y4m_ratio_t y4m_sar_NTSC_16_9 = Y4M_SAR_NTSC_16_9; +const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3 = Y4M_SAR_NTSC_SVCD_4_3; +const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9 = Y4M_SAR_NTSC_SVCD_16_9; +const y4m_ratio_t y4m_sar_PAL_CCIR601 = Y4M_SAR_PAL_CCIR601; +const y4m_ratio_t y4m_sar_PAL_16_9 = Y4M_SAR_PAL_16_9; +const y4m_ratio_t y4m_sar_PAL_SVCD_4_3 = Y4M_SAR_PAL_SVCD_4_3; +const y4m_ratio_t y4m_sar_PAL_SVCD_16_9 = Y4M_SAR_PAL_SVCD_16_9; + +/* useful list of standard display aspect ratios */ +const y4m_ratio_t y4m_dar_UNKNOWN = Y4M_DAR_UNKNOWN; +const y4m_ratio_t y4m_dar_4_3 = Y4M_DAR_4_3; +const y4m_ratio_t y4m_dar_16_9 = Y4M_DAR_16_9; +const y4m_ratio_t y4m_dar_221_100 = Y4M_DAR_221_100; + +/* + * Euler's algorithm for greatest common divisor + */ + +static int gcd(int a, int b) +{ + a = (a >= 0) ? a : -a; + b = (b >= 0) ? b : -b; + + while (b > 0) { + int x = b; + b = a % b; + a = x; + } + return a; +} + + +/************************************************************************* + * + * Remove common factors from a ratio + * + *************************************************************************/ + + +void y4m_ratio_reduce(y4m_ratio_t *r) +{ + int d; + if ((r->n == 0) && (r->d == 0)) return; /* "unknown" */ + d = gcd(r->n, r->d); + r->n /= d; + r->d /= d; +} + + + +/************************************************************************* + * + * Parse "nnn:ddd" into a ratio + * + * returns: Y4M_OK - success + * Y4M_ERR_RANGE - range error + * + *************************************************************************/ + +int y4m_parse_ratio(y4m_ratio_t *r, const char *s) +{ + char *t = strchr(s, ':'); + if (t == NULL) return Y4M_ERR_RANGE; + r->n = atoi(s); + r->d = atoi(t+1); + if (r->d < 0) return Y4M_ERR_RANGE; + /* 0:0 == unknown, so that is ok, otherwise zero denominator is bad */ + if ((r->d == 0) && (r->n != 0)) return Y4M_ERR_RANGE; + y4m_ratio_reduce(r); + return Y4M_OK; +} + + + +/************************************************************************* + * + * Guess the true SAR (sample aspect ratio) from a list of commonly + * encountered values, given the "suggested" display aspect ratio, and + * the true frame width and height. + * + * Returns y4m_sar_UNKNOWN if no match is found. + * + *************************************************************************/ + +/* this is big enough to accommodate the difference between 720 and 704 */ +#define GUESS_ASPECT_TOLERANCE 0.03 + +y4m_ratio_t y4m_guess_sar(int width, int height, y4m_ratio_t dar) +{ + int i; + double implicit_sar = (double)(dar.n * height) / (double)(dar.d * width); + const y4m_ratio_t *sarray[] = + { + &y4m_sar_SQUARE, + &y4m_sar_NTSC_CCIR601, + &y4m_sar_NTSC_16_9, + &y4m_sar_NTSC_SVCD_4_3, + &y4m_sar_NTSC_SVCD_16_9, + &y4m_sar_PAL_CCIR601, + &y4m_sar_PAL_16_9, + &y4m_sar_PAL_SVCD_4_3, + &y4m_sar_PAL_SVCD_16_9, + &y4m_sar_UNKNOWN + }; + for (i = 0; !(Y4M_RATIO_EQL(*(sarray[i]),y4m_sar_UNKNOWN)); i++) { + double ratio = implicit_sar / Y4M_RATIO_DBL(*(sarray[i])); + if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && + (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) ) + return *(sarray[i]); + } + return y4m_sar_UNKNOWN; +} diff --git a/branches/V-1.5.3/veejay-server/test/OSC/README b/branches/V-1.5.3/veejay-server/test/OSC/README new file mode 100644 index 00000000..2349f972 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/README @@ -0,0 +1,4 @@ +1. run make in libOSC +2. run make in send+dump + +now you have a sendOSC utility in send+dump diff --git a/branches/V-1.5.3/veejay-server/test/OSC/libOSC/Makefile b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/Makefile new file mode 100644 index 00000000..6261b37b --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/Makefile @@ -0,0 +1,21 @@ +CFLAGS= -O2 +LIB=libOSC.a + +LIBOBJS= ${LIB}(OSC-client.o) ${LIB}(OSC-timetag.o) + +all: ${LIBOBJS} + +.c.a: + ${CC} -c ${CFLAGS} $< + ${AR} ${ARFLAGS} $@ $*.o + rm -f $*.o + +test_OSC: test_OSC.o ${LIB} + cc -o test_OSC test_OSC.o ${LIB} + +test_OSC_timeTag: test_OSC_timeTag.o OSC-timetag.o + cc -o test_OSC_timeTag test_OSC_timeTag.o OSC-timetag.o + + +clean: + rm -f ${LIB} *.o diff --git a/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-client.c b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-client.c new file mode 100644 index 00000000..0a77ecf8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-client.c @@ -0,0 +1,470 @@ +/* +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03 +The Regents of the University of California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + + +/* + Author: Matt Wright + Version 2.2: Calls htonl in the right places 20000620 + Version 2.3: Gets typed messages right. + Version 2.4: 031215: (re)added ChangeOutermostTimestamp(), htonl() OSX kludge + + */ + + +/* Here are the possible values of the state field: */ + +#define EMPTY 0 /* Nothing written to packet yet */ +#define ONE_MSG_ARGS 1 /* Packet has a single message; gathering arguments */ +#define NEED_COUNT 2 /* Just opened a bundle; must write message name or + open another bundle */ +#define GET_ARGS 3 /* Getting arguments to a message. If we see a message + name or a bundle open/close then the current message + will end. */ +#define DONE 4 /* All open bundles have been closed, so can't write + anything else */ + +#include "OSC-client.h" + +#ifdef TARGET_API_MAC_CARBON +/* KLUDGE for OSX: */ +#define htonl(x) (x) +#endif + +char *OSC_errorMessage; + + +static int strlen(char *s); +static int OSC_padString(char *dest, char *str); +static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str); +static int OSC_WritePadding(char *dest, int i); +static int CheckTypeTag(OSCbuf *buf, char expectedType); + +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray) { + buf->buffer = byteArray; + buf->size = size; + OSC_resetBuffer(buf); +} + +void OSC_resetBuffer(OSCbuf *buf) { + buf->bufptr = buf->buffer; + buf->state = EMPTY; + buf->bundleDepth = 0; + buf->prevCounts[0] = 0; + buf->outerMostTimeStamp = 0; + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; +} + +int OSC_isBufferEmpty(OSCbuf *buf) { + return buf->bufptr == buf->buffer; +} + +int OSC_freeSpaceInBuffer(OSCbuf *buf) { + return buf->size - (buf->bufptr - buf->buffer); +} + +int OSC_isBufferDone(OSCbuf *buf) { + return (buf->state == DONE || buf->state == ONE_MSG_ARGS); +} + +char *OSC_getPacket(OSCbuf *buf) { +#ifdef ERROR_CHECK_GETPACKET + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return buf->buffer; + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return buf->buffer; +#endif +} + +int OSC_packetSize(OSCbuf *buf) { +#ifdef ERROR_CHECK_PACKETSIZE + if (buf->state == DONE || buf->state == ONE_MSG_ARGS) { + return (buf->bufptr - buf->buffer); + } else { + OSC_errorMessage = "Packet has unterminated bundles"; + return 0; + } +#else + return (buf->bufptr - buf->buffer); +#endif +} + +#define CheckOverflow(buf, bytesNeeded) { \ + if ((bytesNeeded) > OSC_freeSpaceInBuffer(buf)) { \ + OSC_errorMessage = "buffer overflow"; \ + return 1; \ + } \ +} + +static void PatchMessageSize(OSCbuf *buf) { + int4byte size; + size = buf->bufptr - ((char *) buf->thisMsgSize) - 4; + *(buf->thisMsgSize) = htonl(size); +} + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt) { + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "Can't open a bundle in a one-message packet"; + return 3; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't open a new bundle"; + return 4; + } + + if (++(buf->bundleDepth) >= MAX_BUNDLE_NESTING) { + OSC_errorMessage = "Bundles nested too deeply; change MAX_BUNDLE_NESTING in OpenSoundControl.h"; + return 2; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->state == EMPTY) { + /* Need 16 bytes for "#bundle" and time tag */ + CheckOverflow(buf, 16); + } else { + /* This bundle is inside another bundle, so we need to leave + a blank size count for the size of this current bundle. */ + CheckOverflow(buf, 20); + *((int4byte *)buf->bufptr) = 0xaaaaaaaa; + buf->prevCounts[buf->bundleDepth] = (int4byte *)buf->bufptr; + + buf->bufptr += 4; + } + + buf->bufptr += OSC_padString(buf->bufptr, "#bundle"); + + + *((OSCTimeTag *) buf->bufptr) = tt; + if (buf->state == EMPTY) { + buf->outerMostTimeStamp = (OSCTimeTag *) buf->bufptr; + } + + + if (htonl(1) != 1) { + /* Byte swap the 8-byte integer time tag */ + int4byte *intp = (int4byte *)buf->bufptr; + intp[0] = htonl(intp[0]); + intp[1] = htonl(intp[1]); + +#ifdef HAS8BYTEINT + { /* tt is a 64-bit int so we have to swap the two 32-bit words. + (Otherwise tt is a struct of two 32-bit words, and even though + each word was wrong-endian, they were in the right order + in the struct.) */ + int4byte temp = intp[0]; + intp[0] = intp[1]; + intp[1] = temp; + } +#endif + } + + buf->bufptr += sizeof(OSCTimeTag); + + buf->state = NEED_COUNT; + + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; + return 0; +} + + + +int ChangeOutermostTimestamp(OSCbuf *buf, OSCTimeTag tt) { + if (buf->outerMostTimeStamp == 0) { + OSC_errorMessage = "No outermost timestamp to change."; + return 1; + } else { + *(buf->outerMostTimeStamp) = tt; + return 0; + } +} + + +int OSC_closeBundle(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close bundle; no bundle is open!"; + return 5; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + if (buf->state == GET_ARGS) { + PatchMessageSize(buf); + } + + if (buf->bundleDepth == 1) { + /* Closing the last bundle: No bundle size to patch */ + buf->state = DONE; + } else { + /* Closing a sub-bundle: patch bundle size */ + int size = buf->bufptr - ((char *) buf->prevCounts[buf->bundleDepth]) - 4; + *(buf->prevCounts[buf->bundleDepth]) = htonl(size); + buf->state = NEED_COUNT; + } + + --buf->bundleDepth; + buf->gettingFirstUntypedArg = 0; + buf->typeStringPtr = 0; + return 0; +} + + +int OSC_closeAllBundles(OSCbuf *buf) { + if (buf->bundleDepth == 0) { + /* This handles EMPTY, ONE_MSG, ARGS, and DONE */ + OSC_errorMessage = "Can't close all bundles; no bundle is open!"; + return 6; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + while (buf->bundleDepth > 0) { + OSC_closeBundle(buf); + } + buf->typeStringPtr = 0; + return 0; +} + +int OSC_writeAddress(OSCbuf *buf, char *name) { + int4byte paddedLength; + + if (buf->state == ONE_MSG_ARGS) { + OSC_errorMessage = "This packet is not a bundle, so you can't write another address"; + return 7; + } + + if (buf->state == DONE) { + OSC_errorMessage = "This packet is finished; can't write another address"; + return 8; + } + + if (CheckTypeTag(buf, '\0')) return 9; + + paddedLength = OSC_effectiveStringLength(name); + + if (buf->state == EMPTY) { + /* This will be a one-message packet, so no sizes to worry about */ + CheckOverflow(buf, paddedLength); + buf->state = ONE_MSG_ARGS; + } else { + /* GET_ARGS or NEED_COUNT */ + CheckOverflow(buf, 4+paddedLength); + if (buf->state == GET_ARGS) { + /* Close the old message */ + PatchMessageSize(buf); + } + buf->thisMsgSize = (int4byte *)buf->bufptr; + *(buf->thisMsgSize) = 0xbbbbbbbb; + buf->bufptr += 4; + buf->state = GET_ARGS; + } + + /* Now write the name */ + buf->bufptr += OSC_padString(buf->bufptr, name); + buf->typeStringPtr = 0; + buf->gettingFirstUntypedArg = 1; + + return 0; +} + +int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types) { + int result; + int4byte paddedLength; + + if (CheckTypeTag(buf, '\0')) return 9; + + result = OSC_writeAddress(buf, name); + + if (result) return result; + + paddedLength = OSC_effectiveStringLength(types); + + CheckOverflow(buf, paddedLength); + + buf->typeStringPtr = buf->bufptr + 1; /* skip comma */ + buf->bufptr += OSC_padString(buf->bufptr, types); + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +static int CheckTypeTag(OSCbuf *buf, char expectedType) { + if (buf->typeStringPtr) { + if (*(buf->typeStringPtr) != expectedType) { + if (expectedType == '\0') { + OSC_errorMessage = + "According to the type tag I expected more arguments."; + } else if (*(buf->typeStringPtr) == '\0') { + OSC_errorMessage = + "According to the type tag I didn't expect any more arguments."; + } else { + OSC_errorMessage = + "According to the type tag I expected an argument of a different type."; + /* printf("* Expected %c, string now %s\n", expectedType, buf->typeStringPtr); */ + } + return 9; + } + ++(buf->typeStringPtr); + } + return 0; +} + + +int OSC_writeFloatArg(OSCbuf *buf, float arg) { + int4byte *intp; + int result; + + CheckOverflow(buf, 4); + + if (CheckTypeTag(buf, 'f')) return 9; + + /* Pretend arg is a long int so we can use htonl() */ + intp = ((int4byte *) &arg); + *((int4byte *) buf->bufptr) = htonl(*intp); + + buf->bufptr += 4; + + buf->gettingFirstUntypedArg = 0; + return 0; +} + + + +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args) { + int i; + int4byte *intp; + + CheckOverflow(buf, 4 * numFloats); + + /* Pretend args are long ints so we can use htonl() */ + intp = ((int4byte *) args); + + for (i = 0; i < numFloats; i++) { + if (CheckTypeTag(buf, 'f')) return 9; + *((int4byte *) buf->bufptr) = htonl(intp[i]); + buf->bufptr += 4; + } + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +int OSC_writeIntArg(OSCbuf *buf, int4byte arg) { + CheckOverflow(buf, 4); + if (CheckTypeTag(buf, 'i')) return 9; + + *((int4byte *) buf->bufptr) = htonl(arg); + buf->bufptr += 4; + + buf->gettingFirstUntypedArg = 0; + return 0; +} + +int OSC_writeStringArg(OSCbuf *buf, char *arg) { + int len; + + if (CheckTypeTag(buf, 's')) return 9; + + len = OSC_effectiveStringLength(arg); + + if (buf->gettingFirstUntypedArg && arg[0] == ',') { + /* This un-type-tagged message starts with a string + that starts with a comma, so we have to escape it + (with a double comma) so it won't look like a type + tag string. */ + + CheckOverflow(buf, len+4); /* Too conservative */ + buf->bufptr += + OSC_padStringWithAnExtraStupidComma(buf->bufptr, arg); + + } else { + CheckOverflow(buf, len); + buf->bufptr += OSC_padString(buf->bufptr, arg); + } + + buf->gettingFirstUntypedArg = 0; + return 0; + +} + +/* String utilities */ + +static int strlen(char *s) { + int i; + for (i=0; s[i] != '\0'; i++) /* Do nothing */ ; + return i; +} + +#define STRING_ALIGN_PAD 4 +int OSC_effectiveStringLength(char *string) { + int len = strlen(string) + 1; /* We need space for the null char. */ + + /* Round up len to next multiple of STRING_ALIGN_PAD to account for alignment padding */ + if ((len % STRING_ALIGN_PAD) != 0) { + len += STRING_ALIGN_PAD - (len % STRING_ALIGN_PAD); + } + return len; +} + +static int OSC_padString(char *dest, char *str) { + int i; + + for (i = 0; str[i] != '\0'; i++) { + dest[i] = str[i]; + } + + return OSC_WritePadding(dest, i); +} + +static int OSC_padStringWithAnExtraStupidComma(char *dest, char *str) { + int i; + + dest[0] = ','; + for (i = 0; str[i] != '\0'; i++) { + dest[i+1] = str[i]; + } + + return OSC_WritePadding(dest, i+1); +} + +static int OSC_WritePadding(char *dest, int i) { + dest[i] = '\0'; + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + dest[i] = '\0'; + } + + return i; +} diff --git a/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-client.h b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-client.h new file mode 100644 index 00000000..f9cf0bd8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-client.h @@ -0,0 +1,180 @@ +/* +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1996,97,98,99,2000,01,02,03 +The Regents of the University of California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +/* + + OSC-client.h: library for constructing OpenSoundControl messages. + Derived from SynthControl.h + Author: Matt Wright + Version 0.1: 6/13/97 + Version 0.2: 7/21/2000: Support for type-tagged messages + Version 0.3: 031215: (re)added ChangeOutermostTimestamp() + + + General notes: + + This library abstracts away the data format for the OpenSoundControl + protocol. Users of this library can construct OpenSoundControl packets + with a function call interface instead of knowing how to lay out the bits. + + All issues of memory allocation are deferred to the user of this library. + There are two data structures that the user must allocate. The first + is the actual buffer that the message will be written into. This buffer + can be any size, but if it's too small there's a possibility that it + will become overfull. The other data structure is called an OSCbuf, + and it holds all the state used by the library as it's constructing + a buffer. + + All procedures that have the possibility of an error condition return int, + with 0 indicating no error and nonzero indicating an error. The variable + OSC_errorMessage will be set to point to a string containing an error + message explaining what the problem is. + +*/ + + +#include "OSC-timetag.h" + +/* The int4byte type has to be a 4-byte integer. You may have to + change this to long or something else on your system. */ +#ifdef __MWERKS__ + /* In Metrowerks you can set ints to be 2 or 4 bytes on 68K, but long is + always 4 bytes */ + typedef long int4byte; +#else + typedef int int4byte; +#endif + +/* The maximum depth of bundles within bundles within bundles within... + This is the size of a static array. If you exceed this limit you'll + get an error message. */ +#define MAX_BUNDLE_NESTING 32 + + +/* Don't ever manipulate the data in the OSCbuf struct directly. (It's + declared here in the header file only so your program will be able to + declare variables of type OSCbuf and have the right amount of memory + be allocated.) */ + +typedef struct OSCbuf_struct { + char *buffer; /* The buffer to hold the OSC packet */ + int size; /* Size of the buffer */ + char *bufptr; /* Current position as we fill the buffer */ + int state; /* State of partially-constructed message */ + int4byte *thisMsgSize; /* Pointer to count field before + currently-being-written message */ + int4byte *prevCounts[MAX_BUNDLE_NESTING]; + /* Pointers to count field before each currently + open bundle */ + int bundleDepth; /* How many sub-sub-bundles are we in now? */ + OSCTimeTag *outerMostTimeStamp; /* Pointer to highest-level enclosing timestamp */ + char *typeStringPtr; /* This pointer advances through the type + tag string as you add arguments. */ + int gettingFirstUntypedArg; /* nonzero if this message doesn't have + a type tag and we're waiting for the 1st arg */ +} OSCbuf; + + + +/* Initialize the given OSCbuf. The user of this module must pass in the + block of memory that this OSCbuf will use for a buffer, and the number of + bytes in that block. (It's the user's job to allocate the memory because + you do it differently in different systems.) */ +void OSC_initBuffer(OSCbuf *buf, int size, char *byteArray); + + +/* Reset the given OSCbuf. Do this after you send out the contents of + the buffer and want to start writing new data into it. */ +void OSC_resetBuffer(OSCbuf *buf); + + +/* Is the buffer empty? (I.e., would it be stupid to send the buffer + contents to the synth?) */ +int OSC_isBufferEmpty(OSCbuf *buf); + + +/* How much space is left in the buffer? */ +int OSC_freeSpaceInBuffer(OSCbuf *buf); + +/* Does the buffer contain a valid OSC packet? (Returns nonzero if yes.) */ +int OSC_isBufferDone(OSCbuf *buf); + +/* When you're ready to send out the buffer (i.e., when OSC_isBufferDone() + returns true), call these two procedures to get the OSC packet that's been + assembled and its size in bytes. (And then call OSC_resetBuffer() if you + want to re-use this OSCbuf for the next packet.) */ +char *OSC_getPacket(OSCbuf *buf); +int OSC_packetSize(OSCbuf *buf); + +/* If a packet already has a timestamp, change it to the given new one. */ +int ChangeOutermostTimestamp(OSCbuf *buf, OSCTimeTag tt); + + +/* Here's the basic model for building up OSC messages in an OSCbuf: + + - Make sure the OSCbuf has been initialized with OSC_initBuffer(). + + - To open a bundle, call OSC_openBundle(). You can then write + messages or open new bundles within the bundle you opened. + Call OSC_closeBundle() to close the bundle. Note that a packet + does not have to have a bundle; it can instead consist of just a + single message. + + + - For each message you want to send: + + - Call OSC_writeAddress() with the name of your message. (In + addition to writing your message name into the buffer, this + procedure will also leave space for the size count of this message.) + + - Alternately, call OSC_writeAddressAndTypes() with the name of + your message and with a type string listing the types of all the + arguments you will be putting in this message. + + - Now write each of the arguments into the buffer, by calling one of: + OSC_writeFloatArg() + OSC_writeFloatArgs() + OSC_writeIntArg() + OSC_writeStringArg() + + - Now your message is complete; you can send out the buffer or you can + add another message to it. +*/ + +int OSC_openBundle(OSCbuf *buf, OSCTimeTag tt); +int OSC_closeBundle(OSCbuf *buf); +int OSC_closeAllBundles(OSCbuf *buf); + +int OSC_writeAddress(OSCbuf *buf, char *name); +int OSC_writeAddressAndTypes(OSCbuf *buf, char *name, char *types); +int OSC_writeFloatArg(OSCbuf *buf, float arg); +int OSC_writeFloatArgs(OSCbuf *buf, int numFloats, float *args); +int OSC_writeIntArg(OSCbuf *buf, int4byte arg); +int OSC_writeStringArg(OSCbuf *buf, char *arg); + +extern char *OSC_errorMessage; + +/* How many bytes will be needed in the OSC format to hold the given + string? The length of the string, plus the null char, plus any padding + needed for 4-byte alignment. */ +int OSC_effectiveStringLength(char *string); diff --git a/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-timetag.c b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-timetag.c new file mode 100644 index 00000000..1ea2f6d4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-timetag.c @@ -0,0 +1,170 @@ +/* +Copyright (c) 1998,99,2000,01,02,03. The Regents of the University of California (Regents). +All Rights Reserved. Written by Matt Wright, Center for New Music and Audio Technologies, +University of California, Berkeley. + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + +/* + + OSC_timeTag.c: library for manipulating OSC time tags + Matt Wright, 5/29/97 + + Version 0.2 (9/11/98): cleaned up so no explicit type names in the .c file. + +*/ + +#include "OSC-timetag.h" + + +#ifdef HAS8BYTEINT +#define TWO_TO_THE_32_FLOAT 4294967296.0f + +OSCTimeTag OSCTT_Immediately(void) { + return (OSCTimeTag) 1; +} + +OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) { + return (OSCTimeTag) 0xffffffffffffffff; +} + +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) { + int64 offset = (int64) (secondsOffset * TWO_TO_THE_32_FLOAT); + +/* printf("* OSCTT_PlusSeconds %llx plus %f seconds (i.e., %lld offset) is %llx\n", original, + secondsOffset, offset, original + offset); */ + + return original + offset; +} + +int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) { +#if 0 + printf("***** OSCTT_Compare(%llx, %llx): %d\n", left, right, + (left + +#define SECONDS_FROM_1900_to_1970 2208988800 /* 17 leap years */ +#define TWO_TO_THE_32_OVER_ONE_MILLION 4295 + + +OSCTimeTag OSCTT_CurrentTime(void) { + uint64 result; + uint32 usecOffset; + struct timeval tv; + struct timezone tz; + + BSDgettimeofday(&tv, &tz); + + /* First get the seconds right */ + result = (unsigned) SECONDS_FROM_1900_to_1970 + + (unsigned) tv.tv_sec - + (unsigned) 60 * tz.tz_minuteswest + + (unsigned) (tz.tz_dsttime ? 3600 : 0); + +#if 0 + /* No timezone, no DST version ... */ + result = (unsigned) SECONDS_FROM_1900_to_1970 + + (unsigned) tv.tv_sec; +#endif + + + /* make seconds the high-order 32 bits */ + result = result << 32; + + /* Now get the fractional part. */ + usecOffset = (unsigned) tv.tv_usec * (unsigned) TWO_TO_THE_32_OVER_ONE_MILLION; + /* printf("** %ld microsec is offset %x\n", tv.tv_usec, usecOffset); */ + + result += usecOffset; + +/* printf("* OSCTT_CurrentTime is %llx\n", result); */ + return result; +} + +#else /* __sgi */ + +/* Instead of asking your operating system what time it is, it might be + clever to find out the current time at the instant your application + starts audio processing, and then keep track of the number of samples + output to know how much time has passed. */ + +/* Loser version for systems that have no ability to tell the current time: */ +OSCTimeTag OSCTT_CurrentTime(void) { + return (OSCTimeTag) 1; +} + +#endif /* __sgi */ + + +#else /* Not HAS8BYTEINT */ + +OSCTimeTag OSCTT_CurrentTime(void) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + +OSCTimeTag OSCTT_BiggestPossibleTimeTag(void) { + OSCTimeTag result; + result.seconds = 0xffffffff; + result.fraction = 0xffffffff; + return result; +} + +OSCTimeTag OSCTT_Immediately(void) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset) { + OSCTimeTag result; + result.seconds = 0; + result.fraction = 1; + return result; +} + +int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right) { + /* Untested! */ + int highResult = left.seconds - right.seconds; + + if (highResult != 0) return highResult; + + return left.fraction - right.fraction; +} + + +#endif /* HAS8BYTEINT */ + diff --git a/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-timetag.h b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-timetag.h new file mode 100644 index 00000000..8d5af5e7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/OSC-timetag.h @@ -0,0 +1,88 @@ +/* +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. Copyright (c) 1998,99,2000,01,02,03,04 +The Regents of the University of California (Regents). + +Permission to use, copy, modify, distribute, and distribute modified versions +of this software and its documentation without fee and without a signed +licensing agreement, is hereby granted, provided that the above copyright +notice, this paragraph and the following two paragraphs appear in all copies, +modifications, and distributions. + +IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +The OpenSound Control WWW page is + http://www.cnmat.berkeley.edu/OpenSoundControl +*/ + +/* + OSC_timeTag.h: library for manipulating OSC time tags + Matt Wright, 5/29/97 + + Time tags in OSC have the same format as in NTP: 64 bit fixed point, with the + top 32 bits giving number of seconds sinve midnight 1/1/1900 and the bottom + 32 bits giving fractional parts of a second. We represent this by a 64-bit + unsigned long if possible, or else a struct. + + NB: On many architectures with 64-bit ints, it's illegal (like maybe a bus error) + to dereference a pointer to a 64-bit int that's not 64-bit aligned. +*/ + +#ifndef OSC_TIMETAG +#define OSC_TIMETAG + +#ifdef __sgi + #define HAS8BYTEINT + /* You may have to change this typedef if there's some other + way to specify 64 bit ints on your system */ + typedef long long int64; + typedef unsigned long long uint64; + typedef unsigned long uint32; +#else + /* You may have to redefine this typedef if ints on your system + aren't 32 bits. */ + typedef unsigned int uint32; +#endif + + +#ifdef HAS8BYTEINT + typedef uint64 OSCTimeTag; +#else + typedef struct { + uint32 seconds; + uint32 fraction; + } OSCTimeTag; +#endif + + + +/* Return a time tag representing the current time (as of when this + procedure is called). */ +OSCTimeTag OSCTT_CurrentTime(void); + +/* Return the time tag 0x0000000000000001, indicating to the receiving device + that it should process the message immediately. */ +OSCTimeTag OSCTT_Immediately(void); + +/* Return the time tag 0xffffffffffffffff, a time so far in the future that + it's effectively infinity. */ +OSCTimeTag OSCTT_BiggestPossibleTimeTag(void); + +/* Given a time tag and a number of seconds to add to the time tag, return + the new time tag */ +OSCTimeTag OSCTT_PlusSeconds(OSCTimeTag original, float secondsOffset); + +/* Compare two time tags. Return negative if first is < second, 0 if + they're equal, and positive if first > second. */ +int OSCTT_Compare(OSCTimeTag left, OSCTimeTag right); + +#endif /* OSC_TIMETAG */ diff --git a/branches/V-1.5.3/veejay-server/test/OSC/libOSC/index.html b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/index.html new file mode 100644 index 00000000..b759addd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/libOSC/index.html @@ -0,0 +1,20 @@ + + + + Index of /OpenSoundControl/src/libOSC + + +

Index of /OpenSoundControl/src/libOSC

+
      Name                    Last modified       Size  Description
+
+[DIR] Parent Directory 02-Feb-2004 11:51 - +[TXT] Makefile 24-Sep-2003 13:10 1k +[TXT] OSC-client.c 06-Jan-2004 08:21 12k +[TXT] OSC-client.h 06-Jan-2004 08:20 7k +[TXT] OSC-timetag.c 12-Apr-2004 11:05 5k +[TXT] OSC-timetag.h 12-Apr-2004 11:05 3k +[TXT] test_OSC.c 24-Sep-2003 13:10 3k +[TXT] test_OSC_timeTag.c 24-Sep-2003 13:10 1k +

+
Apache/1.3.27 Server at cnmat.cnmat.berkeley.edu Port 80
+ diff --git a/branches/V-1.5.3/veejay-server/test/OSC/presveejay.sh b/branches/V-1.5.3/veejay-server/test/OSC/presveejay.sh new file mode 100644 index 00000000..be511e55 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/presveejay.sh @@ -0,0 +1,23 @@ +#!/bin/perl + +my $CMD="./sendOSC -h localhost 3492"; + +system( "$CMD /clip/new,1,1000" ); +system( "$CMD /clip/select,1"); + + +for (my $l = 0; $l < 4; $l ++ ) +{ + for (my $i = 0; $i < 20; $i ++ ) + { + system( "$CMD /entry/preset,0,0,151,$i,0,$i,0" ); + } + + for ( my $i = 60; $i > 0 ; $i -- ) + { + system( "$CMD /entry/preset,0,0,151,$i,0,$i,0" ); + } +} + + + diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/Makefile b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/Makefile new file mode 100644 index 00000000..9961ad96 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/Makefile @@ -0,0 +1,29 @@ +LIBOSCDIR = ../libOSC +LIBOSC = ${LIBOSCDIR}/libOSC.a +CFLAGS= -O2 -I$(LIBOSCDIR) -Wall -g +DEFS= -Dunix + +DUMPOBJS=dumpOSC.o + + +both: sendOSC dumpOSC mcastOSC + +mcastOSC: mcastOSC.o mcastsocket.o ${LIBOSC} + ${CC} ${CFLAGS} ${DEFS} -o mcastOSC mcastOSC.o mcastsocket.o ${LIBOSC} + +sendOSC: sendOSC.o htmsocket.o ${LIBOSC} + ${CC} ${CFLAGS} ${DEFS} -o sendOSC sendOSC.o htmsocket.o ${LIBOSC} + +dumpOSC: ${DUMPOBJS} + ${CC} ${CFLAGS} ${DEFS} -o $@ ${DUMPOBJS} + +dumpUDP: dumpUDP.o + ${CC} ${CFLAGS} ${DEFS} -o dumpUDP dumpUDP.o + +${LIBOSC}: + echo "You need to go to " ${LIBOSCDIR} " and do a make." + +clean: + rm -f sendOSC dumpOSC *.o + + diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/dumpOSC.c b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/dumpOSC.c new file mode 100644 index 00000000..fc53fd5d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/dumpOSC.c @@ -0,0 +1,717 @@ +/* +Copyright (c) 1992,1993,1994,1995,1996,1997,2000. +The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright and Adrian Freed, The Center for New Music and Audio +Technologies, University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. +*/ + + /* + + dumpOSC.c + server that displays OpenSoundControl messages sent to it + for debugging client udp and UNIX protocol + + by Matt Wright, 6/3/97 + modified from dumpSC.c, by Matt Wright and Adrian Freed + + version 0.2: Added "-silent" option a.k.a. "-quiet" + + version 0.3: Incorporated patches from Nicola Bernardini to make + things Linux-friendly. Also added ntohl() in the right places + to support little-endian architectures. + + + + compile: + cc -o dumpOSC dumpOSC.c + + to-do: + + More robustness in saying exactly what's wrong with ill-formed + messages. (If they don't make sense, show exactly what was + received.) + + Time-based features: print time-received for each packet + + Clean up to separate OSC parsing code from socket/select stuff + +*/ + + +#ifdef unix +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NEED_SCHEDCTL_AND_LOCK +#include +#include +#endif + + +char *htm_error_string; +typedef int Boolean; +typedef void *OBJ; + +typedef struct ClientAddressStruct { + struct sockaddr_in cl_addr; + int clilen; + int sockfd; +} *ClientAddr; + +Boolean ShowBytes = FALSE; +Boolean Silent = FALSE; + +/* Declarations */ +static int unixinitudp(int chan); +static int initudp(int chan); +static void closeudp(int sockfd); +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength); +void sgi_CleanExit(void); +Boolean sgi_HaveToQuit(void); +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy); +static void catch_sigint(); +static int Synthmessage(char *m, int n, void *clientdesc, int clientdesclength, int fd) ; +void ParseOSCPacket(char *buf, int n, ClientAddr returnAddr); +static void Smessage(char *address, void *v, int n, ClientAddr returnAddr); +static void PrintTypeTaggedArgs(void *v, int n); +static void PrintHeuristicallyTypeGuessedArgs(void *v, int n, int skipComma); +char *DataAfterAlignedString(char *string, char *boundary) ; +Boolean IsNiceString(char *string, char *boundary) ; +void complain(char *s, ...); + + +#define UNIXDG_PATH "/tmp/htm" +#define UNIXDG_TMP "/tmp/htm.XXXXXX" +static int unixinitudp(int chan) +{ + struct sockaddr_un serv_addr; + int sockfd; + + if((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) + return sockfd; + + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, UNIXDG_PATH); + sprintf(serv_addr.sun_path+strlen(serv_addr.sun_path), "%d", chan); + unlink(serv_addr.sun_path); + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr.sun_family)+strlen(serv_addr.sun_path)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; +} + +static int initudp(int chan) +{ + struct sockaddr_in serv_addr; + int sockfd; + + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return sockfd; + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(chan); + + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; +} + +static void closeudp(int sockfd) { + close(sockfd); +} + +static Boolean catchupflag=FALSE; +Boolean ClientReply(int packetsize, void *packet, int socketfd, + void *clientaddresspointer, int clientaddressbufferlength) +{ + if(!clientaddresspointer) return FALSE; + catchupflag= TRUE; + return packetsize==sendto(socketfd, packet, packetsize, 0, clientaddresspointer, clientaddressbufferlength); +} + +static Boolean exitflag= FALSE; +void sgi_CleanExit(void) { + exitflag = TRUE; +} + +Boolean sgi_HaveToQuit(void) { + return exitflag; +} + + +/* file descriptor poll table */ +static int npolldevs =0; +typedef struct polldev +{ + int fd; + void (*callbackfunction)(int , void *); + void *dummy; +} polldev; +#define TABMAX 8 +static polldev polldevs[TABMAX]; + + +/* Register a device (referred to by a file descriptor that the caller + should have already successfully obtained from a system call) to be + polled as real-time constraints allowed. + + When a select(2) call indicates activity on the file descriptor, the + callback function is called with the file descripter as first + argument and the given dummy argument (presumably a pointer to the + instance variables associated with the device). +*/ +int RegisterPollingDevice(int fd, void (*callbackfunction)(int , void *), void *dummy) +{ + if(npolldevscl_addr.sin_addr.s_addr; + printf("Client address %p:\n", CA); + printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd); + printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family, + CA->cl_addr.sin_port); + printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr)); + + printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n", + CA->cl_addr.sin_zero[0], + CA->cl_addr.sin_zero[1], + CA->cl_addr.sin_zero[2], + CA->cl_addr.sin_zero[3], + CA->cl_addr.sin_zero[4], + CA->cl_addr.sin_zero[5], + CA->cl_addr.sin_zero[6], + CA->cl_addr.sin_zero[7]); + + printf("\n"); +} + + +void ParseOSCPacket(char *buf, int n, ClientAddr returnAddr) { + int size, messageLen, i; + char *messageName; + char *args; + +#ifdef PRINTADDRS + PrintClientAddr(returnAddr); +#endif + + + if ((n%4) != 0) { + complain("SynthControl packet size (%d) not a multiple of 4 bytes: dropping", + n); + return; + } + + if ((n >= 8) && (strncmp(buf, "#bundle", 8) == 0)) { + /* This is a bundle message. */ + + if (n < 16) { + complain("Bundle message too small (%d bytes) for time tag", n); + return; + } + + /* Print the time tag */ + printf("[ %lx%08lx\n", ntohl(*((unsigned long *)(buf+8))), + ntohl(*((unsigned long *)(buf+12)))); + /* Note: if we wanted to actually use the time tag as a little-endian + 64-bit int, we'd have to word-swap the two 32-bit halves of it */ + + i = 16; /* Skip "#group\0" and time tag */ + while(i n) { + complain("Bad size count %d in bundle (only %d bytes left in entire bundle)", + size, n-i-4); + return; + } + + /* Recursively handle element of bundle */ + ParseOSCPacket(buf+i+4, size, returnAddr); + i += 4 + size; + } + if (i != n) { + complain("This can't happen"); + } + printf("]\n"); + } else { + /* This is not a bundle message */ + + messageName = buf; + args = DataAfterAlignedString(messageName, buf+n); + if (args == 0) { + complain("Bad message name string: %s\nDropping entire message.\n", + htm_error_string); + return; + } + messageLen = args-messageName; + Smessage(messageName, (void *)args, n-messageLen, returnAddr); + } +} + +#define SMALLEST_POSITIVE_FLOAT 0.000001f + +static void Smessage(char *address, void *v, int n, ClientAddr returnAddr) { + char *chars = v; + + printf("%s ", address); + + if (n != 0) { + if (chars[0] == ',') { + if (chars[1] != ',') { + /* This message begins with a type-tag string */ + PrintTypeTaggedArgs(v, n); + } else { + /* Double comma means an escaped real comma, not a type string */ + PrintHeuristicallyTypeGuessedArgs(v, n, 1); + } + } else { + PrintHeuristicallyTypeGuessedArgs(v, n, 0); + } + } + + printf("\n"); + fflush(stdout); /* Added for Sami 5/21/98 */ +} + +static void PrintTypeTaggedArgs(void *v, int n) { + char *typeTags, *thisType; + char *p; + + typeTags = v; + + if (!IsNiceString(typeTags, typeTags+n)) { + /* No null-termination, so maybe it wasn't a type tag + string after all */ + PrintHeuristicallyTypeGuessedArgs(v, n, 0); + return; + } + + p = DataAfterAlignedString(typeTags, typeTags+n); + + + for (thisType = typeTags + 1; *thisType != 0; ++thisType) { + switch (*thisType) { + case 'i': case 'r': case 'm': case 'c': + printf("%d ", ntohl(*((int *) p))); + p += 4; + break; + + case 'f': { + int i = ntohl(*((int *) p)); + float *floatp = ((float *) (&i)); + printf("%f ", *floatp); + p += 4; + } + break; + + case 'h': case 't': + printf("[A 64-bit int] "); + p += 8; + break; + + case 'd': + printf("[A 64-bit float] "); + p += 8; + break; + + case 's': case 'S': + if (!IsNiceString(p, typeTags+n)) { + printf("Type tag said this arg is a string but it's not!\n"); + return; + } else { + printf("\"%s\" ", p); + p = DataAfterAlignedString(p, typeTags+n); + } + break; + + case 'T': printf("[True] "); break; + case 'F': printf("[False] "); break; + case 'N': printf("[Nil]"); break; + case 'I': printf("[Infinitum]"); break; + + default: + printf("[Unrecognized type tag %c]", *thisType); + return; + } + } +} + +static void PrintHeuristicallyTypeGuessedArgs(void *v, int n, int skipComma) { + int i, thisi; + float thisf; + int *ints; + char *chars; + char *string, *nextString; + + + /* Go through the arguments 32 bits at a time */ + ints = v; + chars = v; + + for (i = 0; i= -1000 && thisi <= 1000000) { + printf("%d ", thisi); + i++; + } else if (thisf >= -1000.f && thisf <= 1000000.f && + (thisf <=0.0f || thisf >= SMALLEST_POSITIVE_FLOAT)) { + printf("%f ", thisf); + i++; + } else if (IsNiceString(string, chars+n)) { + nextString = DataAfterAlignedString(string, chars+n); + printf("\"%s\" ", (i == 0 && skipComma) ? string +1 : string); + i += (nextString-string) / 4; + } else { + printf("0x%x ", ints[i]); + i++; + } + } +} + + +#define STRING_ALIGN_PAD 4 + +char *DataAfterAlignedString(char *string, char *boundary) +{ + /* The argument is a block of data beginning with a string. The + string has (presumably) been padded with extra null characters + so that the overall length is a multiple of STRING_ALIGN_PAD + bytes. Return a pointer to the next byte after the null + byte(s). The boundary argument points to the character after + the last valid character in the buffer---if the string hasn't + ended by there, something's wrong. + + If the data looks wrong, return 0, and set htm_error_string */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: DataAfterAlignedString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + } + + /* Now string[i] is the first null character */ + i++; + + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string + i >= boundary) { + htm_error_string = "DataAfterAlignedString: Unreasonably long string"; + return 0; + } + if (string[i] != '\0') { + htm_error_string = "DataAfterAlignedString: Incorrectly padded string."; + return 0; + } + } + + return string+i; +} + +Boolean IsNiceString(char *string, char *boundary) +{ + /* Arguments same as DataAfterAlignedString(). Is the given "string" + really a string? I.e., is it a sequence of isprint() characters + terminated with 1-4 null characters to align on a 4-byte boundary? */ + + int i; + + if ((boundary - string) %4 != 0) { + fprintf(stderr, "Internal error: IsNiceString: bad boundary\n"); + return 0; + } + + for (i = 0; string[i] != '\0'; i++) { + if (!isprint(string[i])) return FALSE; + if (string + i >= boundary) return FALSE; + } + + /* If we made it this far, it's a null-terminated sequence of printing characters + in the given boundary. Now we just make sure it's null padded... */ + + /* Now string[i] is the first null character */ + i++; + for (; (i % STRING_ALIGN_PAD) != 0; i++) { + if (string[i] != '\0') return FALSE; + } + + return TRUE; +} + + + + + + + +#define MAXMESG 32768 +static char mbuf[MAXMESG]; + +int main(int argc, char **argv) { + int udp_port; /* port to receive parameter updates from */ + + struct sockaddr_in cl_addr; + int clilen,maxclilen=sizeof(cl_addr); + struct sockaddr_un ucl_addr; + int uclilen,umaxclilen=sizeof(ucl_addr); + int i,n; + + + clilen = maxclilen; + uclilen = umaxclilen; + + udp_port = -1; + for (i=1; i < argc; ++i) { + if (strcmp(argv[i], "-showbytes") == 0) { + ShowBytes = TRUE; + } else if (strcmp(argv[i], "-silent") == 0 || + strcmp(argv[i], "-quiet") == 0) { + Silent = TRUE; + } else if (udp_port != -1) { + goto usageError; + } else { + udp_port = atoi(argv[i]); + if (udp_port == 0) { + goto usageError; + } + } + } + + if (udp_port == -1) { + usageError: + fprintf(stderr, "Usage\n\tdumpOSC portno [-showbytes] [-quiet]\n\t(responds to udp and UNIX packets on that port no)\n"); + exit(1); + } + + + n = recvfrom(0, mbuf, MAXMESG, 0, &cl_addr, &clilen); + if(n>0) + { + sockfd = 0; + udp_port = -1; + Synthmessage(mbuf, n, &cl_addr, clilen,sockfd) ; + } + else + { sockfd=initudp(udp_port); + usockfd=unixinitudp(udp_port); + } + + if (!Silent) { + printf("dumpOSC version 0.2 (6/18/97 Matt Wright). Unix/UDP Port %d \n", udp_port); + printf("Copyright (c) 1992,1996,1997 Regents of the University of California.\n"); + } + if(sockfd>=0 && usockfd>=0) + { + fd_set read_fds, write_fds; + int nfds; +#define max(a,b) (((a) > (b)) ? (a) : (b)) + nfds = max(sockfd, usockfd)+ 1; + { + int j; + for(j=0;j=nfds) + { + nfds = polldevs[j].fd+1; +/* +printf("polldev %d\n", polldevs[j].fd); +*/ + } + } +/* + printf("nfds %d\n", nfds); +*/ + caught_sigint = 0; + sigset(SIGINT, catch_sigint); /* set sig handler */ + + while(!caught_sigint) + { + + int r; + + back: + + FD_ZERO(&read_fds); /* clear read_fds */ + FD_ZERO(&write_fds); /* clear write_fds */ + FD_SET(sockfd, &read_fds); + FD_SET(usockfd, &read_fds); + { + int j; + + for(j=0;j0) + { + int r; + /* printf("received UDP packet of length %d\n", n); */ + r = Synthmessage(mbuf, n, &cl_addr, clilen, sockfd) ; + + if( sgi_HaveToQuit()) goto out; + if(r>0) goto back; + clilen = maxclilen; + } + } + if(FD_ISSET(usockfd, &read_fds)) + { + uclilen = umaxclilen; + while( (n = recvfrom(usockfd, mbuf, MAXMESG, 0, &ucl_addr, &uclilen)) >0) + { + int r; + /* printf("received UNIX packet of length %d\n", n); */ + + r=Synthmessage(mbuf, n, &ucl_addr, uclilen,usockfd) ; + + if( sgi_HaveToQuit()) goto out; + if(r>0) goto back; + uclilen = umaxclilen; + } + } + } /* End of while(!caught_sigint) */ + closeudp(sockfd); + +out: ; + } + else + perror("initudp"); + + return 0; +} + + +#include +void complain(char *s, ...) { + va_list ap; + va_start(ap, s); + fprintf(stderr, "*** ERROR: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +#endif /* __sgi or LINUX */ diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/dumpUDP.c b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/dumpUDP.c new file mode 100644 index 00000000..38768124 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/dumpUDP.c @@ -0,0 +1,191 @@ +/* +Copyright (c) 1998. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. + +dumpUDP.c: smallest UDP receiving application +by Matt Wright, 9/9/98 + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef struct ClientAddressStruct { + struct sockaddr_in cl_addr; + int clilen; + int sockfd; +} *ClientAddr; + +void PrintClientAddr(ClientAddr CA) { + unsigned long addr = CA->cl_addr.sin_addr.s_addr; + printf("Client address %p:\n", CA); + printf(" clilen %d, sockfd %d\n", CA->clilen, CA->sockfd); + printf(" sin_family %d, sin_port %d\n", CA->cl_addr.sin_family, + CA->cl_addr.sin_port); + printf(" address: (%x) %s\n", addr, inet_ntoa(CA->cl_addr.sin_addr)); + + printf(" sin_zero = \"%c%c%c%c%c%c%c%c\"\n", + CA->cl_addr.sin_zero[0], + CA->cl_addr.sin_zero[1], + CA->cl_addr.sin_zero[2], + CA->cl_addr.sin_zero[3], + CA->cl_addr.sin_zero[4], + CA->cl_addr.sin_zero[5], + CA->cl_addr.sin_zero[6], + CA->cl_addr.sin_zero[7]); + + printf("\n"); +} + + +static int initudp(int port) { + struct sockaddr_in serv_addr; + int n, sockfd; + + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return sockfd; + bzero((char *)&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + serv_addr.sin_port = htons(port); + + if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + perror("unable to bind\n"); + return -1; + } + + fcntl(sockfd, F_SETFL, FNDELAY); + return sockfd; +} + + +static void closeudp(int sockfd) { + close(sockfd); +} + + +static int time_to_quit; + +static void catch_sigint() { + time_to_quit = 1; +} + +void GotAPacket(char *buf, int n, ClientAddr returnAddr) { + printf("received UDP packet of length %d\n", n); + PrintClientAddr(returnAddr); +} + +#define MAXMESG 32768 +static char mbuf[MAXMESG]; + +void ReceivePacket(int sockfd) { + struct ClientAddressStruct returnAddress; + int maxclilen=sizeof(returnAddress.cl_addr); + int n; + + returnAddress.clilen = maxclilen; + while( (n = recvfrom(sockfd, mbuf, MAXMESG, 0, &(returnAddress.cl_addr), + &(returnAddress.clilen))) >0) { + GotAPacket(mbuf, n, &returnAddress); + + if (time_to_quit) return; + returnAddress.clilen = maxclilen; + } +} + +void main(int argc, char **argv) { + int udp_port; /* port to receive parameter updates from */ + int sockfd; + int i; + + fd_set read_fds, write_fds; + int nfds; + + udp_port = 7000; + + sockfd=initudp(udp_port); + + if(sockfd<0) { + perror("initudp"); + return; + } + + nfds = sockfd + 1; + + time_to_quit = 0; + sigset(SIGINT, catch_sigint); /* set sig handler */ + + while(!time_to_quit) + { + + int c,r; + + back: + + FD_ZERO(&read_fds); /* clear read_fds */ + FD_ZERO(&write_fds); /* clear write_fds */ + FD_SET(sockfd, &read_fds); + + + r = select(nfds, &read_fds, &write_fds, (fd_set *)0, + (struct timeval *)0); + if (r < 0) /* select reported an error */ + goto out; + + if(FD_ISSET(sockfd, &read_fds)) { + ReceivePacket(sockfd); + } + + } /* End of while(!time_to_quit) */ +out: ; +} diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/htmsocket.c b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/htmsocket.c new file mode 100644 index 00000000..34e3f2cd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/htmsocket.c @@ -0,0 +1,235 @@ +/* +Copyright (c) 1992,1996,1998. +The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Adrian Freed, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. +*/ + + /* htmsocket.c + + Adrian Freed + send parameters to htm servers by udp or UNIX protocol + + Modified 6/6/96 by Matt Wright to understand symbolic host names + in addition to X.X.X.X addresses. + */ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define UNIXDG_PATH "/tmp/htm" +#define UNIXDG_TMP "/tmp/htm.XXXXXX" +#include "htmsocket.h" +typedef struct +{ + float srate; + + struct sockaddr_in serv_addr; /* udp socket */ + struct sockaddr_un userv_addr; /* UNIX socket */ + int sockfd; /* socket file descriptor */ + int index, len,uservlen; + void *addr; + int id; +} desc; + +/* open a socket for HTM communication to given host on given portnumber */ +/* if host is 0 then UNIX protocol is used (i.e. local communication */ +void *OpenHTMSocket(char *host, int portnumber) +{ + int sockfd; + int oval = 1; + struct sockaddr_in cl_addr; + struct sockaddr_un ucl_addr; + desc *o; + o = malloc(sizeof(*o)); + if(!o) + return 0; + if(!host) + { + // char *mkstemp(char *); + int clilen; + o->len = sizeof(ucl_addr); + /* + * Fill in the structure "userv_addr" with the address of the + * server that we want to send to. + */ + + bzero((char *) &o->userv_addr, sizeof(o->userv_addr)); + o->userv_addr.sun_family = AF_UNIX; + strcpy(o->userv_addr.sun_path, UNIXDG_PATH); + sprintf(o->userv_addr.sun_path+strlen(o->userv_addr.sun_path), "%d", portnumber); + o->uservlen = sizeof(o->userv_addr.sun_family) + strlen(o->userv_addr.sun_path); + o->addr = &(o->userv_addr); + /* + * Open a socket (a UNIX domain datagram socket). + */ + + if ( (sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0) + { + /* + * Bind a local address for us. + * In the UNIX domain we have to choose our own name (that + * should be unique). We'll use mktemp() to create a unique + * pathname, based on our process id. + */ + + bzero((char *) &ucl_addr, sizeof(ucl_addr)); /* zero out */ + ucl_addr.sun_family = AF_UNIX; + strcpy(ucl_addr.sun_path, UNIXDG_TMP); + + mkstemp(ucl_addr.sun_path); + clilen = sizeof(ucl_addr.sun_family) + strlen(ucl_addr.sun_path); + + if (bind(sockfd, (struct sockaddr *) &ucl_addr, clilen) < 0) + { + perror("client: can't bind local address"); + close(sockfd); + sockfd = -1; + } + } + else + perror("unable to make socket\n"); + + }else + { + /* + * Fill in the structure "serv_addr" with the address of the + * server that we want to send to. + */ + o->len = sizeof(cl_addr); + bzero((char *)&o->serv_addr, sizeof(o->serv_addr)); + o->serv_addr.sin_family = AF_INET; + + /* MW 6/6/96: Call gethostbyname() instead of inet_addr(), + so that host can be either an Internet host name (e.g., + "les") or an Internet address in standard dot notation + (e.g., "128.32.122.13") */ + { + struct hostent *hostsEntry; + unsigned long address; + + hostsEntry = gethostbyname(host); + if (hostsEntry == NULL) { + fprintf(stderr, "Couldn't decipher host name \"%s\"\n", + host); + herror(NULL); + return 0; + } + + address = *((unsigned long *) hostsEntry->h_addr_list[0]); + o->serv_addr.sin_addr.s_addr = address; + } + + /* was: o->serv_addr.sin_addr.s_addr = inet_addr(host); */ + + /* End MW changes */ + + o->serv_addr.sin_port = htons(portnumber); + o->addr = &(o->serv_addr); + /* + * Open a socket (a UDP domain datagram socket). + */ + if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) + { + bzero((char *)&cl_addr, sizeof(cl_addr)); + cl_addr.sin_family = AF_INET; + cl_addr.sin_addr.s_addr = htonl(INADDR_ANY); + cl_addr.sin_port = htons(0); + + if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &oval, sizeof(int)) == -1) { + perror("setsockopt"); + } + + if(bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) + { + perror("could not bind\n"); + close(sockfd); + sockfd = -1; + } + } + else + { + perror("unable to make socket\n"); + } + + } + if(sockfd<0) + { + free(o); o = 0; + } + else + o->sockfd = sockfd; + return o; +} +#include + +static bool sendudp(const struct sockaddr *sp, int sockfd,int length, int count, void *b) +{ + int rcount; + if((rcount=sendto(sockfd, b, count, 0, sp, length)) != count) + { +/* printf("sockfd %d count %d rcount %dlength %d errno %d\n", sockfd,count,rcount,length, + errno); */ + return FALSE; + } + return TRUE; +} +bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer) +{ + desc *o = (desc *)htmsendhandle; + return sendudp(o->addr, o->sockfd, o->len, length_in_bytes, buffer); +} +void CloseHTMSocket(void *htmsendhandle) +{ + desc *o = (desc *)htmsendhandle; + close(o->sockfd); + free(o); +} diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/htmsocket.h b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/htmsocket.h new file mode 100644 index 00000000..b035b57f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/htmsocket.h @@ -0,0 +1,49 @@ +/* +Copyright (c) 1992,1996. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Adrian Freed, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. +*/ + + /* htmparam.h + + Adrian Freed + send parameters to htm servers by udp or UNIX protocol + */ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +typedef int bool; + +/* open a socket for HTM communication to given host on given portnumber */ +/* if host is 0 then UNIX protocol is used (i.e. local communication) */ +void *OpenHTMSocket(char *host, int portnumber); + +/* send a buffer of data over htm socket, returns TRUE on success. + Note that udp sends rarely fail. UNIX sends fail if a kernal buffer overflows */ +bool SendHTMSocket(void *htmsendhandle, int length_in_bytes, void *buffer); + +/* close the socket(2) and release memory associated with it */ +void CloseHTMSocket(void *htmsendhandle); diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastOSC.c b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastOSC.c new file mode 100644 index 00000000..e87419dc --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastOSC.c @@ -0,0 +1,610 @@ +/* +Copyright (c) 1996,1997. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. +*/ + +/* sendOSC.c + + Matt Wright, 6/3/97 + based on sendSC.c, which was based on a version by Adrian Freed + + Text-based OpenSoundControl client. User can enter messages via command + line arguments or standard input. + + Version 0.1: "play" feature + Version 0.2: Message type tags. + +*/ + +#define VERSION "http://cnmat.berkeley.edu/OpenSoundControl/sendOSC-0.1.html" + +/* +compiling: + cc -o sendOSC sendOSC.c htmsocket.c OpenSoundControl.c OSC_timeTag.c +*/ + +/* mcastOSC.c + Niels Elburg 10/01/05 + based on sendOSC.c , modified to send using multicast protocol +*/ +#include "OSC-client.h" +#include "mcastsocket.h" + +#include +#include +/* #include */ +#include + +#ifdef unix + #include + #include +#endif + +static int portnumber = 0; + +typedef struct { + enum {INT, FLOAT, STRING} type; + union { + int i; + float f; + char *s; + } datum; +} typedArg; + +void CommandLineMode(int argc, char *argv[], void *handle); +void InteractiveMode(void *handle); +OSCTimeTag ParseTimeTag(char *s); +void ParseInteractiveLine(OSCbuf *buf, char *mesg); +typedArg ParseToken(char *token); +int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args); +void SendBuffer(void *handle, OSCbuf *buf, int port); +void SendData(void *handle,int size, char *data, int port); +void fatal_error(char *s); +void complain(char *s, ...); + +/* Exit status codes: + 0: successful + 2: Message(s) dropped because of buffer overflow + 3: Socket error + 4: Usage error + 5: Internal error +*/ +static int exitStatus = 0; + + +static int useTypeTags = 1; + +int main(int argc, char *argv[]) { + char *hostname = 0; + void *handle; + + argc--; + argv++; + + if (argc == 0) { + goto usageerror; + } + + if (argc >= 1 && (strncmp(*argv, "-notypetags", 2) == 0)) { + useTypeTags = 0; + argv++; + argc--; + } + + if (argc >= 2 && (strncmp(*argv, "-r", 2) == 0)) { + hostname = getenv("MCAST_ADDR"); + if (hostname == NULL) { + complain("sendSC -r: MCAST_ADDR not in environment\n"); + exit(4); + } + argv++; + argc--; + } + + if (argc >= 3 && (strncmp(*argv, "-g", 2) == 0)) { + hostname = argv[1]; + argv += 2; + argc -= 2; + } + portnumber = atoi(*argv); + argv++; + argc--; + + printf("Multicast sender on %s\n", hostname ); + + handle = OpenMCASTSocket(hostname); + if (!handle) { + perror("Couldn't open socket: "); + exit(3); + } + + if (argc > 0) { + printf("host %s, port %d, %s\n", hostname, portnumber, + useTypeTags ? "use type tags" : "don't use type tags"); + CommandLineMode(argc, argv, handle); + } else { + printf("sendOSC version " VERSION "\n"); + printf("by Matt Wright. Copyright (c) 1996, 1997 Regents of the University of California.\n"); + printf("host %s, port %d, %s\n", hostname, portnumber, + useTypeTags ? "use type tags" : "don't use type tags"); + InteractiveMode(handle); + } + CloseMCASTSocket(handle); + exit(exitStatus); + + + usageerror: + complain("usage: %s [-notypetags] [-r] [-g group_name] port_number [message...]\n", + argv[-1]); + exit(4); + +} + + +#define MAX_ARGS 2000 +#define SC_BUFFER_SIZE 32000 +static char bufferForOSCbuf[SC_BUFFER_SIZE]; + +void CommandLineMode(int argc, char *argv[], void *handle) { + char *messageName; + char *token; + typedArg args[MAX_ARGS]; + int i,j, numArgs; + OSCbuf buf[1]; + + OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); + + if (argc > 1) { + if (OSC_openBundle(buf, OSCTT_Immediately())) { + complain("Problem opening bundle: %s\n", OSC_errorMessage); + return; + } + } + + for (i = 0; i < argc; i++) { + messageName = strtok(argv[i], ","); + if (messageName == NULL) { + break; + } + + j = 0; + while ((token = strtok(NULL, ",")) != NULL) { + args[j] = ParseToken(token); + j++; + if (j >= MAX_ARGS) { + complain("Sorry; your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n", + MAX_ARGS); + break; + } + } + numArgs = j; + + WriteMessage(buf, messageName, numArgs, args); + } + + if (argc > 1) { + if (OSC_closeBundle(buf)) { + complain("Problem closing bundle: %s\n", OSC_errorMessage); + return; + } + } + + SendBuffer(handle, buf, portnumber); +} + +#define MAXMESG 2048 + +void InteractiveMode(void *handle) { + char mesg[MAXMESG]; + OSCbuf buf[1]; + int bundleDepth = 0; /* At first, we haven't seen "[". */ + + OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); + + while (fgets(mesg, MAXMESG, stdin) != NULL) { + if (mesg[0] == '\n') { + if (bundleDepth > 0) { + /* Ignore blank lines inside a group. */ + } else { + /* blank line => repeat previous send */ + SendBuffer(handle, buf, portnumber); + } + continue; + } + + if (bundleDepth == 0) { + OSC_resetBuffer(buf); + } + + if (mesg[0] == '[') { + OSCTimeTag tt = ParseTimeTag(mesg+1); + if (OSC_openBundle(buf, tt)) { + complain("Problem opening bundle: %s\n", OSC_errorMessage); + OSC_resetBuffer(buf); + bundleDepth = 0; + continue; + } + bundleDepth++; + } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') { + if (bundleDepth == 0) { + complain("Unexpected ']': not currently in a bundle.\n"); + } else { + if (OSC_closeBundle(buf)) { + complain("Problem closing bundle: %s\n", OSC_errorMessage); + OSC_resetBuffer(buf); + bundleDepth = 0; + continue; + } + + bundleDepth--; + if (bundleDepth == 0) { + SendBuffer(handle, buf, portnumber); + } + } + } else { + ParseInteractiveLine(buf, mesg); + if (bundleDepth != 0) { + /* Don't send anything until we close all bundles */ + } else { + SendBuffer(handle, buf, portnumber); + } + } + } +} + +OSCTimeTag ParseTimeTag(char *s) { + char *p, *newline; + typedArg arg; + + p = s; + while (isspace(*p)) p++; + if (*p == '\0') return OSCTT_Immediately(); + + if (*p == '+') { + /* Time tag is for some time in the future. It should be a + number of seconds as an int or float */ + + newline = strchr(s, '\n'); + if (newline != NULL) *newline = '\0'; + + p++; /* Skip '+' */ + while (isspace(*p)) p++; + + arg = ParseToken(p); + if (arg.type == STRING) { + complain("warning: inscrutable time tag request: %s\n", s); + return OSCTT_Immediately(); + } else if (arg.type == INT) { + return OSCTT_PlusSeconds(OSCTT_CurrentTime(), + (float) arg.datum.i); + } else if (arg.type == FLOAT) { + return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f); + } else { + fatal_error("This can't happen!"); + } + } + + if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) { + /* They specified the 8-byte tag in hex */ + OSCTimeTag tt; + if (sscanf(p, "%llx", &tt) != 1) { + complain("warning: couldn't parse time tag %s\n", s); + return OSCTT_Immediately(); + } +#ifndef HAS8BYTEINT + if (ntohl(1) != 1) { + /* tt is a struct of seconds and fractional part, + and this machine is little-endian, so sscanf + wrote each half of the time tag in the wrong half + of the struct. */ + uint32 temp; + temp = tt.seconds; + tt.seconds = tt.fraction ; + tt.fraction = temp; + } +#endif + return tt; + } + + complain("warning: invalid time tag: %s\n", s); + return OSCTT_Immediately(); +} + + +void ParseInteractiveLine(OSCbuf *buf, char *mesg) { + char *messageName, *token, *p; + typedArg args[MAX_ARGS]; + int thisArg; + + p = mesg; + while (isspace(*p)) p++; + if (*p == '\0') return; + + messageName = p; + + if (strcmp(messageName, "play\n") == 0) { + /* Special kludge feature to save typing */ + typedArg arg; + + if (OSC_openBundle(buf, OSCTT_Immediately())) { + complain("Problem opening bundle: %s\n", OSC_errorMessage); + return; + } + + arg.type = INT; + arg.datum.i = 0; + WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg); + + arg.type = FLOAT; + arg.datum.i = 0.0f; + WriteMessage(buf, "/voices/0/tm/goto", 1, &arg); + + if (OSC_closeBundle(buf)) { + complain("Problem closing bundle: %s\n", OSC_errorMessage); + } + + return; + } + + while (!isspace(*p) && *p != '\0') p++; + if (isspace(*p)) { + *p = '\0'; + p++; + } + + thisArg = 0; + while (*p != '\0') { + /* flush leading whitespace */ + while (isspace(*p)) p++; + if (*p == '\0') break; + + if (*p == '"') { + /* A string argument: scan for close quotes */ + p++; + args[thisArg].type = STRING; + args[thisArg].datum.s = p; + + while (*p != '"') { + if (*p == '\0') { + complain("Unterminated quote mark: ignoring line\n"); + return; + } + p++; + } + *p = '\0'; + p++; + } else { + token = p; + while (!isspace(*p) && (*p != '\0')) p++; + if (isspace(*p)) { + *p = '\0'; + p++; + } + args[thisArg] = ParseToken(token); + } + thisArg++; + if (thisArg >= MAX_ARGS) { + complain("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n", + MAX_ARGS); + break; + } + } + + if (WriteMessage(buf, messageName, thisArg, args) != 0) { + complain("Problem sending message: %s\n", OSC_errorMessage); + } +} + +typedArg ParseToken(char *token) { + char *p = token; + typedArg returnVal; + + /* It might be an int, a float, or a string */ + + if (*p == '-') p++; + + if (isdigit(*p) || *p == '.') { + while (isdigit(*p)) p++; + if (*p == '\0') { + returnVal.type = INT; + returnVal.datum.i = atoi(token); + return returnVal; + } + if (*p == '.') { + p++; + while (isdigit(*p)) p++; + if (*p == '\0') { + returnVal.type = FLOAT; + returnVal.datum.f = atof(token); + return returnVal; + } + } + } + + returnVal.type = STRING; + returnVal.datum.s = token; + return returnVal; +} + +int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) { + int j, returnVal; + + returnVal = 0; + +#ifdef DEBUG + printf("WriteMessage: %s ", messageName); + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT: + printf("%d ", args[j].datum.i); + break; + + case FLOAT: + printf("%f ", args[j].datum.f); + break; + + case STRING: + printf("%s ", args[j].datum.s); + break; + + default: + fatal_error("Unrecognized arg type"); + exit(5); + } + } + printf("\n"); +#endif + + if (!useTypeTags) { + returnVal = OSC_writeAddress(buf, messageName); + if (returnVal) { + complain("Problem writing address: %s\n", OSC_errorMessage); + } + } else { + /* First figure out the type tags */ + char typeTags[MAX_ARGS+2]; + int i; + + typeTags[0] = ','; + + for (i = 0; i < numArgs; ++i) { + switch (args[i].type) { + case INT: + typeTags[i+1] = 'i'; + break; + + case FLOAT: + typeTags[i+1] = 'f'; + break; + + case STRING: + typeTags[i+1] = 's'; + break; + + default: + fatal_error("Unrecognized arg type"); + exit(5); + } + } + typeTags[i+1] = '\0'; + + returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags); + if (returnVal) { + complain("Problem writing address: %s\n", OSC_errorMessage); + } + } + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT: + if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) { + return returnVal; + } + break; + + case FLOAT: + if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) { + return returnVal; + } + break; + + case STRING: + if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) { + return returnVal; + } + break; + + default: + fatal_error("Unrecognized arg type"); + exit(5); + } + } + + return returnVal; +} + +void SendBuffer(void *handle, OSCbuf *buf, int portnum) { +#ifdef DEBUG + printf("Sending buffer...\n"); +#endif + if (OSC_isBufferEmpty(buf)) return; + if (!OSC_isBufferDone(buf)) { + fatal_error("SendBuffer() called but buffer not ready!"); + exit(5); + } + SendData(handle, OSC_packetSize(buf), OSC_getPacket(buf), portnum); +} + +void SendData(void *handle, int size, char *data, int port) { + if (!SendMCASTSocket(handle,port, data, size)) { + perror("Couldn't send out socket: "); + CloseMCASTSocket(handle); + exit(3); + } +} + +void fatal_error(char *s) { + fprintf(stderr, "%s\n", s); + exit(4); +} + +#include +void complain(char *s, ...) { + va_list ap; + va_start(ap, s); + vfprintf(stderr, s, ap); + va_end(ap); +} + + +#ifdef COMPUTE_MESSAGE_SIZE + /* Unused code to find the size of a message */ + + /* Compute size */ + size = SynthControl_effectiveStringLength(messageName); + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT: case FLOAT: + size += 4; + break; + + case STRING: + size += SynthControl_effectiveStringLength(args[j].datum.s); + break; + + default: + fatal_error("Unrecognized token type"); + exit(4); + } + } + + if (!SynthControl_willMessageFit(buf, size)) { + complain("Message \"%s\" won't fit in buffer: dropping.", messageName); + return; + } +#endif diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastsocket.c b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastsocket.c new file mode 100644 index 00000000..f1d9b541 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastsocket.c @@ -0,0 +1,125 @@ +/* +Copyright (c) 1992,1996,1998. +The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Adrian Freed, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. +*/ + + /* htmsocket.c + + Adrian Freed + send parameters to htm servers by udp or UNIX protocol + + Modified 6/6/96 by Matt Wright to understand symbolic host names + in addition to X.X.X.X addresses. + */ + +/* + mcastsocket.c + + Niels Elburg + send using multicast protocol + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "mcastsocket.h" + +typedef struct +{ + char *group_name; + struct sockaddr_in mcast_addr_; + socklen_t mcast_addr_len_; + int sock_; +} mcast_; + +void *OpenMCASTSocket(const char *mcast_groupname) +{ + mcast_ *mc = (mcast_*) malloc(sizeof( mcast_ )); + int on = 1; + unsigned char ttl = 1; + if(!mc) return NULL; + + memset( &mc->mcast_addr_, 0, sizeof( mc->mcast_addr_ )); + mc->mcast_addr_len_ = sizeof( struct sockaddr_in ); + + mc->group_name = (char*) strdup( mcast_groupname ); + mc->mcast_addr_.sin_addr.s_addr = inet_addr( mcast_groupname ); + mc->mcast_addr_.sin_family = AF_INET; + mc->mcast_addr_.sin_port = htons( 0 ); // filled on demand + mc->sock_ = socket( AF_INET, SOCK_DGRAM, 0 ); +#ifdef SO_REUSEADDR + setsockopt( mc->sock_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); +#endif +#ifdef SO_REUSEPORT + setsockopt( mc->sock_ , SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)); +#endif + setsockopt( mc->sock_ , IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)); + return (void*) mc; +} + +void SetInterface( void *handle, const char *ip_address ) +{ + struct sockaddr_in if_addr; + mcast_ *mc = (mcast_*) handle; + memset( &if_addr, 0, sizeof(if_addr)); + mc->mcast_addr_.sin_addr.s_addr = inet_addr( ip_address ); + mc->mcast_addr_.sin_family = AF_INET; + setsockopt( mc->sock_, IPPROTO_IP, IP_MULTICAST_IF, &if_addr, + sizeof( if_addr ) ); +} + +int SendMCASTSocket(void *handle, int port, const void *buffer, int len) +{ + mcast_ *mc = (mcast_*) handle; + mc->mcast_addr_.sin_port = htons( port ); + int n = sendto( mc->sock_, buffer, len, 0, + (struct sockaddr *) &mc->mcast_addr_, mc->mcast_addr_len_ ); + printf("Send %d bytes \n"); + return n; +} +void CloseMCASTSocket(void *handle) +{ + mcast_ *mc = (mcast_*) handle; + close(mc->sock_); +} diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastsocket.h b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastsocket.h new file mode 100644 index 00000000..c0cba199 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/mcastsocket.h @@ -0,0 +1,51 @@ +/* +Copyright (c) 1992,1996. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Adrian Freed, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. +*/ + + /* htmparam.h + + Adrian Freed + send parameters to htm servers by udp or UNIX protocol + */ + +/* + mcastsocket.h + Niels Elburg + header file for multicast sender +*/ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +void *OpenMCASTSocket(const char *groupname ); + +int SendMCASTSocket(void *handle, int port,const void *buf, int length_in_bytes); + +void CloseMCASTSocket(void *handle); + +void SetInterface( void *handle, const char *group_name ); diff --git a/branches/V-1.5.3/veejay-server/test/OSC/send+dump/sendOSC.c b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/sendOSC.c new file mode 100644 index 00000000..d37a539c --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/OSC/send+dump/sendOSC.c @@ -0,0 +1,604 @@ +/* +Copyright (c) 1996,1997. The Regents of the University of California (Regents). +All Rights Reserved. + +Permission to use, copy, modify, and distribute this software and its +documentation for educational, research, and not-for-profit purposes, without +fee and without a signed licensing agreement, is hereby granted, provided that +the above copyright notice, this paragraph and the following two paragraphs +appear in all copies, modifications, and distributions. Contact The Office of +Technology Licensing, UC Berkeley, 2150 Shattuck Avenue, Suite 510, Berkeley, +CA 94720-1620, (510) 643-7201, for commercial licensing opportunities. + +Written by Matt Wright, The Center for New Music and Audio Technologies, +University of California, Berkeley. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, + ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING + DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". + REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, + ENHANCEMENTS, OR MODIFICATIONS. +*/ + +/* sendOSC.c + + Matt Wright, 6/3/97 + based on sendSC.c, which was based on a version by Adrian Freed + + Text-based OpenSoundControl client. User can enter messages via command + line arguments or standard input. + + Version 0.1: "play" feature + Version 0.2: Message type tags. + +*/ + +#define VERSION "http://cnmat.berkeley.edu/OpenSoundControl/sendOSC-0.1.html" + +/* +compiling: + cc -o sendOSC sendOSC.c htmsocket.c OpenSoundControl.c OSC_timeTag.c +*/ + + +#include "OSC-client.h" +#include "htmsocket.h" + +#include +#include +/* #include */ +#include + +#ifdef unix + #include + #include +#endif + +typedef struct { + enum {INT, FLOAT, STRING} type; + union { + int i; + float f; + char *s; + } datum; +} typedArg; + +void CommandLineMode(int argc, char *argv[], void *htmsocket); +void InteractiveMode(void *htmsocket); +OSCTimeTag ParseTimeTag(char *s); +void ParseInteractiveLine(OSCbuf *buf, char *mesg); +typedArg ParseToken(char *token); +int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args); +void SendBuffer(void *htmsocket, OSCbuf *buf); +void SendData(void *htmsocket, int size, char *data); +void fatal_error(char *s); +void complain(char *s, ...); + +/* Exit status codes: + 0: successful + 2: Message(s) dropped because of buffer overflow + 3: Socket error + 4: Usage error + 5: Internal error +*/ +static int exitStatus = 0; + + +static int useTypeTags = 1; + +int main(int argc, char *argv[]) { + int portnumber; + char *hostname = 0; + void *htmsocket; + + argc--; + argv++; + + if (argc == 0) { + goto usageerror; + } + + if (argc >= 1 && (strncmp(*argv, "-notypetags", 2) == 0)) { + useTypeTags = 0; + argv++; + argc--; + } + + if (argc >= 2 && (strncmp(*argv, "-r", 2) == 0)) { + hostname = getenv("REMOTE_ADDR"); + if (hostname == NULL) { + complain("sendSC -r: REMOTE_ADDR not in environment\n"); + exit(4); + } + argv++; + argc--; + } + + if (argc >= 3 && (strncmp(*argv, "-h", 2) == 0)) { + hostname = argv[1]; + argv += 2; + argc -= 2; + } + portnumber = atoi(*argv); + argv++; + argc--; + + htmsocket = OpenHTMSocket(hostname, portnumber); + if (!htmsocket) { + perror("Couldn't open socket: "); + exit(3); + } + + if (argc > 0) { + printf("host %s, port %d, %s\n", hostname, portnumber, + useTypeTags ? "use type tags" : "don't use type tags"); + CommandLineMode(argc, argv, htmsocket); + } else { + printf("sendOSC version " VERSION "\n"); + printf("by Matt Wright. Copyright (c) 1996, 1997 Regents of the University of California.\n"); + printf("host %s, port %d, %s\n", hostname, portnumber, + useTypeTags ? "use type tags" : "don't use type tags"); + InteractiveMode(htmsocket); + } + CloseHTMSocket(htmsocket); + exit(exitStatus); + + + usageerror: + complain("usage: %s [-notypetags] [-r] [-h target_host_name] port_number [message...]\n", + argv[-1]); + exit(4); + +} + + +#define MAX_ARGS 2000 +#define SC_BUFFER_SIZE 32000 +static char bufferForOSCbuf[SC_BUFFER_SIZE]; + +void CommandLineMode(int argc, char *argv[], void *htmsocket) { + char *messageName; + char *token; + typedArg args[MAX_ARGS]; + int i,j, numArgs; + OSCbuf buf[1]; + + OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); + + if (argc > 1) { + if (OSC_openBundle(buf, OSCTT_Immediately())) { + complain("Problem opening bundle: %s\n", OSC_errorMessage); + return; + } + } + + for (i = 0; i < argc; i++) { + messageName = strtok(argv[i], ","); + if (messageName == NULL) { + break; + } + + j = 0; + while ((token = strtok(NULL, ",")) != NULL) { + args[j] = ParseToken(token); + j++; + if (j >= MAX_ARGS) { + complain("Sorry; your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n", + MAX_ARGS); + break; + } + } + numArgs = j; + + WriteMessage(buf, messageName, numArgs, args); + } + + if (argc > 1) { + if (OSC_closeBundle(buf)) { + complain("Problem closing bundle: %s\n", OSC_errorMessage); + return; + } + } + + SendBuffer(htmsocket, buf); +} + +#define MAXMESG 2048 + +void InteractiveMode(void *htmsocket) { + char mesg[MAXMESG]; + OSCbuf buf[1]; + int bundleDepth = 0; /* At first, we haven't seen "[". */ + + OSC_initBuffer(buf, SC_BUFFER_SIZE, bufferForOSCbuf); + + while (fgets(mesg, MAXMESG, stdin) != NULL) { + if (mesg[0] == '\n') { + if (bundleDepth > 0) { + /* Ignore blank lines inside a group. */ + } else { + /* blank line => repeat previous send */ + SendBuffer(htmsocket, buf); + } + continue; + } + + if (bundleDepth == 0) { + OSC_resetBuffer(buf); + } + + if (mesg[0] == '[') { + OSCTimeTag tt = ParseTimeTag(mesg+1); + if (OSC_openBundle(buf, tt)) { + complain("Problem opening bundle: %s\n", OSC_errorMessage); + OSC_resetBuffer(buf); + bundleDepth = 0; + continue; + } + bundleDepth++; + } else if (mesg[0] == ']' && mesg[1] == '\n' && mesg[2] == '\0') { + if (bundleDepth == 0) { + complain("Unexpected ']': not currently in a bundle.\n"); + } else { + if (OSC_closeBundle(buf)) { + complain("Problem closing bundle: %s\n", OSC_errorMessage); + OSC_resetBuffer(buf); + bundleDepth = 0; + continue; + } + + bundleDepth--; + if (bundleDepth == 0) { + SendBuffer(htmsocket, buf); + } + } + } else { + ParseInteractiveLine(buf, mesg); + if (bundleDepth != 0) { + /* Don't send anything until we close all bundles */ + } else { + SendBuffer(htmsocket, buf); + } + } + } +} + +OSCTimeTag ParseTimeTag(char *s) { + char *p, *newline; + typedArg arg; + + p = s; + while (isspace(*p)) p++; + if (*p == '\0') return OSCTT_Immediately(); + + if (*p == '+') { + /* Time tag is for some time in the future. It should be a + number of seconds as an int or float */ + + newline = strchr(s, '\n'); + if (newline != NULL) *newline = '\0'; + + p++; /* Skip '+' */ + while (isspace(*p)) p++; + + arg = ParseToken(p); + if (arg.type == STRING) { + complain("warning: inscrutable time tag request: %s\n", s); + return OSCTT_Immediately(); + } else if (arg.type == INT) { + return OSCTT_PlusSeconds(OSCTT_CurrentTime(), + (float) arg.datum.i); + } else if (arg.type == FLOAT) { + return OSCTT_PlusSeconds(OSCTT_CurrentTime(), arg.datum.f); + } else { + fatal_error("This can't happen!"); + } + } + + if (isdigit(*p) || (*p >= 'a' && *p <='f') || (*p >= 'A' && *p <='F')) { + /* They specified the 8-byte tag in hex */ + OSCTimeTag tt; + if (sscanf(p, "%llx", &tt) != 1) { + complain("warning: couldn't parse time tag %s\n", s); + return OSCTT_Immediately(); + } +#ifndef HAS8BYTEINT + if (ntohl(1) != 1) { + /* tt is a struct of seconds and fractional part, + and this machine is little-endian, so sscanf + wrote each half of the time tag in the wrong half + of the struct. */ + uint32 temp; + temp = tt.seconds; + tt.seconds = tt.fraction ; + tt.fraction = temp; + } +#endif + return tt; + } + + complain("warning: invalid time tag: %s\n", s); + return OSCTT_Immediately(); +} + + +void ParseInteractiveLine(OSCbuf *buf, char *mesg) { + char *messageName, *token, *p; + typedArg args[MAX_ARGS]; + int thisArg; + + p = mesg; + while (isspace(*p)) p++; + if (*p == '\0') return; + + messageName = p; + + if (strcmp(messageName, "play\n") == 0) { + /* Special kludge feature to save typing */ + typedArg arg; + + if (OSC_openBundle(buf, OSCTT_Immediately())) { + complain("Problem opening bundle: %s\n", OSC_errorMessage); + return; + } + + arg.type = INT; + arg.datum.i = 0; + WriteMessage(buf, "/voices/0/tp/timbre_index", 1, &arg); + + arg.type = FLOAT; + arg.datum.i = 0.0f; + WriteMessage(buf, "/voices/0/tm/goto", 1, &arg); + + if (OSC_closeBundle(buf)) { + complain("Problem closing bundle: %s\n", OSC_errorMessage); + } + + return; + } + + while (!isspace(*p) && *p != '\0') p++; + if (isspace(*p)) { + *p = '\0'; + p++; + } + + thisArg = 0; + while (*p != '\0') { + /* flush leading whitespace */ + while (isspace(*p)) p++; + if (*p == '\0') break; + + if (*p == '"') { + /* A string argument: scan for close quotes */ + p++; + args[thisArg].type = STRING; + args[thisArg].datum.s = p; + + while (*p != '"') { + if (*p == '\0') { + complain("Unterminated quote mark: ignoring line\n"); + return; + } + p++; + } + *p = '\0'; + p++; + } else { + token = p; + while (!isspace(*p) && (*p != '\0')) p++; + if (isspace(*p)) { + *p = '\0'; + p++; + } + args[thisArg] = ParseToken(token); + } + thisArg++; + if (thisArg >= MAX_ARGS) { + complain("Sorry, your message has more than MAX_ARGS (%d) arguments; ignoring the rest.\n", + MAX_ARGS); + break; + } + } + + if (WriteMessage(buf, messageName, thisArg, args) != 0) { + complain("Problem sending message: %s\n", OSC_errorMessage); + } +} + +typedArg ParseToken(char *token) { + char *p = token; + typedArg returnVal; + + /* It might be an int, a float, or a string */ + + if (*p == '-') p++; + + if (isdigit(*p) || *p == '.') { + while (isdigit(*p)) p++; + if (*p == '\0') { + returnVal.type = INT; + returnVal.datum.i = atoi(token); + return returnVal; + } + if (*p == '.') { + p++; + while (isdigit(*p)) p++; + if (*p == '\0') { + returnVal.type = FLOAT; + returnVal.datum.f = atof(token); + return returnVal; + } + } + } + + returnVal.type = STRING; + returnVal.datum.s = token; + return returnVal; +} + +int WriteMessage(OSCbuf *buf, char *messageName, int numArgs, typedArg *args) { + int j, returnVal; + + returnVal = 0; + +#ifdef DEBUG + printf("WriteMessage: %s ", messageName); + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT: + printf("%d ", args[j].datum.i); + break; + + case FLOAT: + printf("%f ", args[j].datum.f); + break; + + case STRING: + printf("%s ", args[j].datum.s); + break; + + default: + fatal_error("Unrecognized arg type"); + exit(5); + } + } + printf("\n"); +#endif + + if (!useTypeTags) { + returnVal = OSC_writeAddress(buf, messageName); + if (returnVal) { + complain("Problem writing address: %s\n", OSC_errorMessage); + } + } else { + /* First figure out the type tags */ + char typeTags[MAX_ARGS+2]; + int i; + + typeTags[0] = ','; + + for (i = 0; i < numArgs; ++i) { + switch (args[i].type) { + case INT: + typeTags[i+1] = 'i'; + break; + + case FLOAT: + typeTags[i+1] = 'f'; + break; + + case STRING: + typeTags[i+1] = 's'; + break; + + default: + fatal_error("Unrecognized arg type"); + exit(5); + } + } + typeTags[i+1] = '\0'; + + returnVal = OSC_writeAddressAndTypes(buf, messageName, typeTags); + if (returnVal) { + complain("Problem writing address: %s\n", OSC_errorMessage); + } + } + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT: + if ((returnVal = OSC_writeIntArg(buf, args[j].datum.i)) != 0) { + return returnVal; + } + break; + + case FLOAT: + if ((returnVal = OSC_writeFloatArg(buf, args[j].datum.f)) != 0) { + return returnVal; + } + break; + + case STRING: + if ((returnVal = OSC_writeStringArg(buf, args[j].datum.s)) != 0) { + return returnVal; + } + break; + + default: + fatal_error("Unrecognized arg type"); + exit(5); + } + } + + return returnVal; +} + +void SendBuffer(void *htmsocket, OSCbuf *buf) { +#ifdef DEBUG + printf("Sending buffer...\n"); +#endif + if (OSC_isBufferEmpty(buf)) return; + if (!OSC_isBufferDone(buf)) { + fatal_error("SendBuffer() called but buffer not ready!"); + exit(5); + } + SendData(htmsocket, OSC_packetSize(buf), OSC_getPacket(buf)); +} + +void SendData(void *htmsocket, int size, char *data) { + if (!SendHTMSocket(htmsocket, size, data)) { + perror("Couldn't send out socket: "); + CloseHTMSocket(htmsocket); + exit(3); + } +} + +void fatal_error(char *s) { + fprintf(stderr, "%s\n", s); + exit(4); +} + +#include +void complain(char *s, ...) { + va_list ap; + va_start(ap, s); + vfprintf(stderr, s, ap); + va_end(ap); +} + + +#ifdef COMPUTE_MESSAGE_SIZE + /* Unused code to find the size of a message */ + + /* Compute size */ + size = SynthControl_effectiveStringLength(messageName); + + for (j = 0; j < numArgs; j++) { + switch (args[j].type) { + case INT: case FLOAT: + size += 4; + break; + + case STRING: + size += SynthControl_effectiveStringLength(args[j].datum.s); + break; + + default: + fatal_error("Unrecognized token type"); + exit(4); + } + } + + if (!SynthControl_willMessageFit(buf, size)) { + complain("Message \"%s\" won't fit in buffer: dropping.", messageName); + return; + } +#endif diff --git a/branches/V-1.5.3/veejay-server/test/README b/branches/V-1.5.3/veejay-server/test/README new file mode 100644 index 00000000..d634cfdf --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/README @@ -0,0 +1,26 @@ + + +In this directory: + + OSC/ + Open Sound Control 'sendOSC' utility + Use 'veejay -u |less' to find out what to send. + + examples/ + perl scripts that generate the files in vims/ are found here + + livecinema/ + action-file.xml ;example action file for veejay , run with -l or --action-file + + vims/ + the files in this directory can be send to veejay, it demonstrates series of effect chains. + + sendVIMS -f montevideo-auto.txt + + + Example to produce a vims file and to send it to veejay: + + $ perl examples/swirl.nl > vims/swirl.vims + + $ sendVIMS -f vims/swirl.vims + diff --git a/branches/V-1.5.3/veejay-server/test/examples/auto-vj.nl b/branches/V-1.5.3/veejay-server/test/examples/auto-vj.nl new file mode 100644 index 00000000..ce6b9929 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/auto-vj.nl @@ -0,0 +1,30 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +for(my $k =0; $k < 3; $k++) +{ + for(my $j = 0; $j < 25; $j ++) + { + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 -1 102 $k $j;\n"; + + } +} + +for(my $i = 0 ; $i < 100; $i ++) +{ + $max = int(rand(75)); + $delay = int(rand(25 + max)); + print "+$delay\n"; + + + $type = int(rand( 3 )); + $count =int(rand( 10 )); + print "361:0 -1 102 $type $count;\n" +} diff --git a/branches/V-1.5.3/veejay-server/test/examples/colorenhancedemo1.pl b/branches/V-1.5.3/veejay-server/test/examples/colorenhancedemo1.pl new file mode 100644 index 00000000..c7886142 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/colorenhancedemo1.pl @@ -0,0 +1,27 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + + +print "177:;\n"; + +for ($k=60; $k < 255; $k+=4) +{ +print "361:0 4 146 $k 60 60;\n"; +print "+1\n"; +} + +for ($k=60; $k < 255; $k+=4) +{ +print "361:0 4 146 60 $k 60;\n"; +print "+1\n"; +} + + +for ($k=60; $k < 255; $k+=4) +{ +print "361:0 4 146 60 60 $k;\n"; +print "+1\n"; +} + diff --git a/branches/V-1.5.3/veejay-server/test/examples/demo1.pl b/branches/V-1.5.3/veejay-server/test/examples/demo1.pl new file mode 100644 index 00000000..bb4ad64f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/demo1.pl @@ -0,0 +1,112 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +my $p1_end = 90; +my $p1_start = 0; +my $p2_start = 0; +my $p2_end = 20; +my $p3_start = 0; +my $p3_end = 200; +my $p4_start = 0; +my $p4_end = 40; + +my $j=0; +my $k=0; +my $l=0; + +print "355:;\n"; + + +for (my $i = 2; $i < 25; $i+=2) +{ +print "361:0 3 154 $i;\n"; +print "+10;\n"; +} + +for (my $i = 2; $i < 25; $i+=2) +{ +print "361:0 3 154 -$i;\n"; +print "+10;\n"; +} + + +print "+200;\n"; + + +print "361:0 3 154 -100;\n"; + +print "+200;\n"; + +print "361:0 3 154 40;\n"; + +print "+200;\n"; + +for(my $r=0; $r < 5; $r++) +{ +for(my $i=$p1_start; $i < $p1_end; $i+=2) +{ + $l++; + $k++; + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 1 151 $i $j $k $l;\n"; +} +for(my $i=$p1_end; $i != $p1_start; $i-=2) +{ + $l--; + $k--; + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 1 151 $i $j $k $l;\n"; +} + + + +} + + + + +# smear: +print "361:0 5 152 0 31;\n"; + + +print "+100;\n"; + +for(my $r=0; $r < 5; $r++) +{ +for(my $i=$p1_start; $i < $p1_end; $i+=2) +{ + $l++; + $k++; + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 1 151 $i $j $k $l;\n"; +} +for(my $i=$p1_end; $i != $p1_start; $i-=2) +{ + $l--; + $k--; + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 1 151 $i $j $k $l;\n"; +} + + + +} + diff --git a/branches/V-1.5.3/veejay-server/test/examples/demo2.pl b/branches/V-1.5.3/veejay-server/test/examples/demo2.pl new file mode 100644 index 00000000..41187e63 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/demo2.pl @@ -0,0 +1,34 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +for(my $k =0; $k < 2; $k++) +{ + for(my $j = 0; $j < 20; $j ++) + { + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 -1 102 $k $j;\n"; + + } +} +for(my $k =1; $k != 0; $k--) +{ + for(my $j = 20; $j != 0; $j --) + { + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 -1 102 $k $j;\n"; + + } +} + +print "177:;\n"; + diff --git a/branches/V-1.5.3/veejay-server/test/examples/displace.pl b/branches/V-1.5.3/veejay-server/test/examples/displace.pl new file mode 100644 index 00000000..5e588094 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/displace.pl @@ -0,0 +1,17 @@ +my $i; + +for(my $j = 0; $j < 40; $j++) +{ + +for($i = 0; $i < 100; $i ++ ) +{ + print("361:0 9 233 $i $i;\n"); + print("+25\n"); +} +for($i = 100; $i > 1 ; $i -- ) +{ + print("361:0 9 233 $i $i;\n"); + print("+25\n"); + +} +} diff --git a/branches/V-1.5.3/veejay-server/test/examples/fortune.pl b/branches/V-1.5.3/veejay-server/test/examples/fortune.pl new file mode 100644 index 00000000..066e7f18 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/fortune.pl @@ -0,0 +1,22 @@ + +print "310:/usr/local/lib/libvj_drawtext_plugin.so;\n"; +print "+10\n"; +for ( my $m = 0; $m < 200 ; $m ++ ) +{ + + my @text = `/usr/games/fortune|tr -d [:cntrl:]`; + my $lines = join "\n", @text; + my $size = 12 + int(rand(15)); + my $y = 10 + int(rand(400)); + $lines =~ s/\n/\" \"/g; + $lines =~ s/":"//; + $lines =~ s/"="//; + $lines =~ s/";"//; + + print "312:DrawText::text=$lines:size=$size:x=2:y=$y:rand=41;\n"; + + + + print "+200\n"; + +} diff --git a/branches/V-1.5.3/veejay-server/test/examples/keydemo2.pl b/branches/V-1.5.3/veejay-server/test/examples/keydemo2.pl new file mode 100644 index 00000000..b6aebd83 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/keydemo2.pl @@ -0,0 +1,22 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +my $len = 100; + +print "355:;\n"; + + +#clip a = blue, clip b = green + +print "361:0 1 242 44 255;\n"; + +print "+$len\n"; + +print "361:0 1 223 2990 255 0 0;\n"; +print "+$len\n"; + + + + diff --git a/branches/V-1.5.3/veejay-server/test/examples/magicmirror.nl b/branches/V-1.5.3/veejay-server/test/examples/magicmirror.nl new file mode 100644 index 00000000..4101ef64 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/magicmirror.nl @@ -0,0 +1,46 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +my $p1_end = 80; +my $p1_start = 0; +my $p2_start = 0; +my $p2_end = 40; +my $p3_start = 0; +my $p3_end = 200; +my $p4_start = 0; +my $p4_end = 40; + +my $j=0; +my $k=0; +my $l=0; +for(my $bla = 0; $bla < 50; $bla ++ ) +{ + +for(my $i=$p1_start; $i < $p1_end; $i++) +{ + #$$l++; +# $j++; +# $k++; + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 -1 151 $i $j $i $l;\n"; +} +for(my $i=$p1_end; $i != $p1_start; $i--) +{ +# $l--; +# $j--; +# $k--; + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 -1 151 $i $j $i $l;\n"; +} + +} diff --git a/branches/V-1.5.3/veejay-server/test/examples/noisedemo2.pl b/branches/V-1.5.3/veejay-server/test/examples/noisedemo2.pl new file mode 100644 index 00000000..c372f518 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/noisedemo2.pl @@ -0,0 +1,33 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +my $len = 50; + +print "355:;\n"; + +print "361:0 1 207 9 60;\n"; + +print "+$len\n"; + +print "361:0 2 106 255;\n"; + +print "+$len\n"; + +print "361:0 3 205 255 0 100 352 0;\n"; + +print "+$len\n"; + +print "361:0 4 134 0 1568;\n"; + +print "+$len\n"; + +for(my $i=1; $i < 50; $i++) +{ + print "+2\n"; + print "361:0 3 141 $len 1 0;\n"; +} + +print "+1\n"; + diff --git a/branches/V-1.5.3/veejay-server/test/examples/overlaydemo2.pl b/branches/V-1.5.3/veejay-server/test/examples/overlaydemo2.pl new file mode 100644 index 00000000..dae5452a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/overlaydemo2.pl @@ -0,0 +1,43 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +my $len = 50; + +print "355:;\n"; + + +for(my $mode =0; $mode < 31; $mode++) +{ + print "361:0 1 201 $mode;\n"; + print "+$len\n"; +} + + +for(my $mode=0; $mode < 23; $mode++) +{ +for(my $val = 0; $val < 255; $val+=8) +{ +print "361:0 1 207 $mode $val;\n"; +} +for(my $val = 255; $val > 1; $val-=8) +{ +print "361:0 1 207 $mode $val;\n"; +} +} + + +for(my $mode=0; $mode < 31; $mode++) +{ +for(my $val = 0; $val < 100; $val+=4) +{ +print "361:0 1 202 $mode $val;\n"; +} +for(my $val = 100; $val > 1; $val-=4) +{ +print "361:0 1 202 $mode $val;\n"; +} +} + + diff --git a/branches/V-1.5.3/veejay-server/test/examples/pixelate.pl b/branches/V-1.5.3/veejay-server/test/examples/pixelate.pl new file mode 100644 index 00000000..0900c005 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/pixelate.pl @@ -0,0 +1,25 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +for(my $j = 0; $j < 25; $j ++) +{ + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 -1 150 $j;\n"; +} + + +for(my $j = 25; $j != 0 ; $j --) +{ + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # somewhere on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 -1 150 $j;\n"; +} diff --git a/branches/V-1.5.3/veejay-server/test/examples/split.pl b/branches/V-1.5.3/veejay-server/test/examples/split.pl new file mode 100644 index 00000000..eaa50ce8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/split.pl @@ -0,0 +1,12 @@ + +printf("361:0 0 209 10 1;\n"); + + +for (my $j = 1; $j < 100; $j ++ ) +{ +for ( my $r = 1; $r < 10; $r ++ ) +{ + printf("366:0 0 $r;\n"); + printf("+100\n"); +} +} diff --git a/branches/V-1.5.3/veejay-server/test/examples/swirl.nl b/branches/V-1.5.3/veejay-server/test/examples/swirl.nl new file mode 100644 index 00000000..656b1fc1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/swirl.nl @@ -0,0 +1,25 @@ + +my $w = 0; +my $h = 0; +for(my $j = 0; $j != 360 ; $j ++) +{ + # 1 frame delay before sending message + print "+1\n"; + # preset effect 102 (multi mirrors) + # 0 on the current playing clip/stream + # with sequenced parameters 0..3 0..25 + print "361:0 2 155 $j;\n"; + print "+1\n"; + print "361:0 4 142 $w $h 1;\n"; + print "+1\n"; + for(my $k = 2; $k < 8; $k++) { + print "361:0 6 141 $k 1;\n"; + print "+1\n"; + } + for(my $k = 8; $k > 2 ; $k--) { + print "361:0 6 141 $k 1;\n"; + print "+1\n"; + } + + +} diff --git a/branches/V-1.5.3/veejay-server/test/examples/zoomdemo.pl b/branches/V-1.5.3/veejay-server/test/examples/zoomdemo.pl new file mode 100644 index 00000000..c7481a7e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/examples/zoomdemo.pl @@ -0,0 +1,24 @@ + +# show multi mirrors, +# type 0,1 = vertical, 1,2 = horizontal +# count is meaningfull below ~30 + +my $len = 100; + +print "177:0;\n"; +print "176:0;\n"; +print "182:0 1 142 0 62 1;\n"; +print "178:0 100;\n"; +print "175:0;\n"; +print "179:0 100;\n"; +print "+200\n"; + +print "177:0;\n"; +print "175:0;\n"; + +for(my $i=0; $i < 255; $i++) +{ +print "182:0 1 204 $i;\n"; +print "+1\n"; +} + diff --git a/branches/V-1.5.3/veejay-server/test/livecinema/action-file.xml b/branches/V-1.5.3/veejay-server/test/livecinema/action-file.xml new file mode 100644 index 00000000..3f118880 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/livecinema/action-file.xml @@ -0,0 +1,301 @@ + + + + 501 + BUN:007{112:;096:4 7;361:0 3 129 68 152;361:0 4 134 1 112;361:0 5 126 3 255 24 1;369:0 6;369:0 5;} + 110 + 3 + + + + 502 + BUN:006{112:;361:0 3 129 68 152;361:0 4 134 1 112;361:0 5 126 3 255 24 1;361:0 6 124 165 5 0;369:0 5;} + 122 + 3 + + + + 503 + BUN:006{112:;361:0 3 129 68 152;361:0 4 134 1 112;361:0 5 126 3 255 24 1;361:0 6 205 255 0 0 1 0;369:0 5;} + 109 + 3 + + + + 504 + BUN:006{112:;361:0 3 101 5;361:0 4 101 4;361:0 5 102 1 1 0;361:0 5 212 1 18 1;361:0 6 106 45;} + 120 + 3 + + + + 505 + BUN:004{112:;369:0 3;361:0 4 106 255;361:0 5 129 68 152;361:0 6 136 15;} + 112 + 3 + + + + 506 + BUN:004{112:;369:0 3;361:0 4 106 255;361:0 5 134 2 958 ;361:0 6 126 23 92 20 0;} + 103 + 3 + + + + 507 + BUN:004{112:;369:0 3;361:0 4 106 255;361:0 5 129 16 62 205;361:0 6 124 170 20 0;} + 104 + 3 + + + + 508 + BUN:005{113:;369:0 3;361:0 4 146 196 150 150;361:0 5 142 50 20;369:0 6;356:0 200;112:;} + 106 + 3 + + + + 509 + BUN:006{113:;369:0 3;361:0 4 106 255;361:0 5 134 2 958 ;361:0 6 207 23 40 190;356:0 200;112:;} + 102 + 3 + + + + 510 + BUN:003{113:;369:0 3;361:0 4 113 2;369:0 5;369:0 6;F1356:0 200;112:;} + 108 + 3 + + + + 511 + BUN:003{113:;369:0 3;361:0 4 141 34 0 4;361:0 5 227 5;112:;369:0 6;356:0 200;} + 121 + 3 + + + + 512 + BUN:001{357:0 200; + 105 + 3 + + + + + 513 + BUN:006{113:;369:0 3;361:0 4 134 1 1000;361:0 5 207 17 150;361:0 6 227 5;356:0 100;112:;} + 60 + 3 + + + + 514 + BUN:001{357:0 100;} + 50 + 3 + + + + 515 + BUN:001{357:0 50;} + 51 + 3 + + + + 516 + BUN:002{112:;356:0 100;} + 57 + 3 + + + + 517 + BUN:002{112:;356:0 50;} + 59 + 3 + + + + + 518 + BUN:002{112:;356:0 200;} + 55 + 3 + + + + 519 + BUN:005{112:;361:0 3 106 54 1;361:0 4 205 255 0 80 2;361:0 5 201 2;361:0 6 134 2 1568;} + 99 + 3 + + + + 520 + BUN:006{112:;361:0 3 105 54 1;361:0 4 205 255 0 80 2;361:0 5 201 2;361:0 6 134 2 1568;} + 118 + 3 + + + + 522 + BUN:005{112:;361:0 3 207 9 0;361:0 4 106 255;361:0 5 205 255 0 30 352 0;361:0 6 134 2 1568;} + 98 + 3 + + + + 523 + BUN:005{112:;361:0 5 105 54 1;361:0 6 205 255 0 80 30 2;078:0 6 1 2;361:0 8 134 2 1568;} + 115 + 3 + + + + + 524 + BUN:006{112:;361:0 5 125 3 3 1;361:0 6 123 5 237;361:0 7 134 0 1089;361:0 8 227 9;361:0 9 114 3 1;} + 100 + 3 + + + + 525 + BUN:006{112:;361:0 5 105 54 1;361:0 6 205 255 0 80 30 2;361:0 8 134 2 1568;361:0 9 126 1 150 15 1;} + 99 + 3 + + + + 526 + BUN:001{355:0;} + 113 + 3 + + + + 527 + BUN:002{112:0;361:0 3 126 1 150 24 1;} + 114 + 3 + + + + 528 + BUN:008{112:;361:0 3 112 5;361:0 4 227 5;361:0 5 112 4;361:0 6 207 22 245;361:0 7 112 4;361:0 8 126 0 150 19 1;361:0 9 148 1 1961 0 0;} + 119 + 3 + + + + + 529 + BUN:005{112:;361:0 3 230 10 1 1;361:0 4 134 1 197;361:0 5 231 4 1 3 1 1;361:0 6 148 0 1000 25 100;} + 101 + 3 + + + + 530 + BUN:003{112:;361:0 3 124 230 93 0;361:0 4 201 7;} + 117 + 3 + + + + 531 + BUN:004{112:;361:0 3 124 230 93 0;361:0 4 201 7;361:0 5 201 7;} + 111 + 3 + + + + 532 + BUN:004{112:;361:0 3 124 230 93 0;361:0 4 201 7;361:0 5 201 8;} + 52 + 3 + + + + + 533 + BUN:004{112:;361:0 3 124 230 93 0;361:0 4 201 7;361:0 5 201 25;} + 53 + 3 + + + + 534 + BUN:005{112:;361:0 3 124 230 93 0;361:0 4 201 7;361:0 5 201 25;361:0 6 201 8;} + 54 + 3 + + + + 535 + BUN:004{112:;361:0 2 145 0 2;361:0 3 124 230 93 0;361:0 4 201 7;} + 55 + 3 + + + + 536 + BUN:004{112:;361:0 2 142 0 0 1;361:0 3 124 230 93 0;361:0 4 201 7;} + 56 + 3 + + + + + 537 + BUN:005{112:;361:0 3 124 209 93 0;361:0 4 201 7;361:0 5 142 0 0 1;361:0 6 201 25;} + 123 + 3 + + + + 538 + BUN:005{112:;361:0 3 124 209 93 0;361:0 4 201 7;361:0 5 142 0 0 1;361:0 6 201 25;} + 124 + 3 + + + + 539 + BUN:004{112:;361:0 3 149 90;361:0 4 201 8;361:0 5 148 2 1000 68 110;} + 44 + 3 + + + + 540 + BUN:004{112:;361:0 3 201 8;361:0 4 148 2 1000 68 110;361:0 5 143 0 16 235;} + 91 + 3 + + + + + 541 + BUN:004{112:;361:0 3 201 8;361:0 4 148 2 1000 68 110;361:0 5 143 6 16 235;} + 93 + 3 + + + + 542 + BUN:004{112:;361:0 3 120 0 1;361:0 4 207 12 152;361:0 5 201 6;} + 39 + 3 + + + + + + + diff --git a/branches/V-1.5.3/veejay-server/test/startup/veejay.env.bash b/branches/V-1.5.3/veejay-server/test/startup/veejay.env.bash new file mode 100644 index 00000000..0574fa29 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/test/startup/veejay.env.bash @@ -0,0 +1,22 @@ +#!/bin/bash +# use SDL hardware acceleration + +if [ -z $@ ] +then + veejay + exit +fi + +export SDL_VIDEO_HWACCEL=1 + +# setup video window on secundary monitor (twinview desktop) +# desktop=2526x1024, second screen starts at 1600, size is 1024x768 +export VEEJAY_SCREEN_GEOMETRY=2624x1024+1600x0 +export VEEJAY_SCREEN_SIZE=1024x768 + +# highest possible quest +export VEEJAY_PERFORMANCE=quality + +# start veejay in verbose, output video in 1024x768 +# expand parameters given to script +veejay -v -w1024 -h768 $@ diff --git a/branches/V-1.5.3/veejay-server/veejay.pc.in b/branches/V-1.5.3/veejay-server/veejay.pc.in new file mode 100644 index 00000000..4acebc8f --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/@PACKAGE@ + +Name: veejay +Description: visual instrument and realtime video sampler +Version: @VERSION@ +Libs: -L${libdir} -lveejay +Cflags: -I${includedir} diff --git a/branches/V-1.5.3/veejay-server/veejay.spec.in b/branches/V-1.5.3/veejay-server/veejay.spec.in new file mode 100644 index 00000000..f3794bc5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay.spec.in @@ -0,0 +1,131 @@ +# norootforbuild +# neededforbuild update-desktop-files gtk2-devel-packages glib2 gtk2 libglade3 libdv libxml2 jack DirectFB SDL libjpeg freetype2 gtk2-devel glib2-devel libglade-devel libxml2-devel jack-devel pkgconfig SDL-devel libjpeg-devel freetype2-devel valgrind alsa-devel alsa slang-devel slang libstdc++-devel libstdc++ zlib-devel zlib + +%define name veejay +%define version 1.3 +%define release stable +%define prefix /usr + +%define builddir $RPM_BUILD_DIR/%{name}-%{version} + +Summary: Video Mixing/Editing Instrument +Name: %{name} +Version: %{version} +Release: %{release} +Prefix: %{prefix} +Copyright: GNU GPL +URL: http://veejayhq.net +Packager: oc2pus +Group: Productivity/Multimedia/Video/Editors and Convertors +Source: %{name}-%{version}.tar.bz2 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Prereq: /sbin/ldconfig +#Requires: libdv >= 0.102 +#Requires: libxml2 >= 2.5.4 +#Requires: jack >= 0.98 +#Requires: SDL >= 1.2.3 +#Requires: libjpeg +#Requires: freetype2 +#Requires: alsa +#Requires: slang +#Requires: libstdc++ +#Requires: zlib +#Requires: gtk2 +#Requires: glib2 +#Requires: libglade2 +#Requires: libxml2 >= 2.5.4 +#Requires: cairo +#Requires: gtkcairo +#Requires: unicap +#BuildRequires: libdv >= 0.102 +#BuildRequires: libxml2-devel >= 2.5.4 +#BuildRequires: jack-devel >= 0.98 +#BuildRequires: pkgconfig +#BuildRequires: SDL-devel >= 1.2.3 +#BuildRequires: libjpeg-devel +#BuildRequires: freetype2-devel +#BuildRequires: alsa-devel +#BuildRequires: slang-devel +#BuildRequires: libstdc++-devel +#BuildRequires: zlib-devel +#BuildRequires: gtk2-devel +#BuildRequires: glib2-devel +#BuildRequires: libglade2-devel +#BuildRequires: valgrind +#BuildRequires: gtkcairo-devel +#BuildRequires: cairo-devel +#BuildRequires: unicap + +%description +Veejay is a visual instrument and realtime video sampler. +It allows you to 'play' the video like you would play a Piano and it allows +you to record the resulting video directly to disk for immediate playback (video sampling). + +Veejay is beeing developed in the hope it will be usefull for VJ's, +media artists and other interested users that want to use Free Software for +their performances and/or video installations. + +Author: Niels Elburg + +Requires: libxml2 >= 2.5.4 + +%prep +%setup -q -n %{name}-%{version} + +./autogen.sh +%{?suse_update_config:%{suse_update_config -f}} + +CFLAGS="$RPM_OPT_FLAGS" \ +CXXFLAGS="$RPM_OPT_FLAGS" \ +./configure \ + --prefix=%{prefix} \ + --mandir=%{_mandir} \ + --with-gveejayreloaded \ + --with-swscaler + +%build +# Setup for parallel builds +numprocs=`egrep -c ^cpu[0-9]+ /proc/stat || :` +if [ "$numprocs" = "0" ]; then + numprocs=1 +fi +make -j$numprocs + +%install +[ -d %{buildroot} -a "%{buildroot}" != "" ] && rm -rf %{buildroot} + +make install-strip \ + DESTDIR=%{buildroot} + +# remove static libs +rm -f %{buildroot}%{_libdir}/lib*.a +rm -f %{buildroot}%{_libdir}/lib*.la + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%clean +[ -d %{buildroot} -a "%{buildroot}" != "" ] && rm -rf %{buildroot} + +%files +%defattr(-, root, root) +%doc AUTHORS BUGS COPYING ChangeLog INSTALL README* +%doc doc +%{_bindir}/%{name} +%{_libdir}/*.so* +%{_libdir}/pkgconfig/%{name}.pc +%{_mandir}/man1/* + +%changelog -n veejay +* Wed Mar 21 2007 - cleanup +* Sat Nov 20 2005 - bla +* Sat Apr 23 2005 - oc2pus@arcor.de 0.8-0.oc2pus.1 +- update to 0.8 +- patched configure for using glib2-2.4.*, gtk2-2.4.*, libglade2-2.2.* +- patched gveejay sources for using gtk2-2.4 +* Fri Apr 15 2005 - oc2pus@arcor.de 0.7.3-0.oc2pus.2 +- directfb re-enabled +* Mon Mar 21 2005 - oc2pus@arcor.de 0.7.3-0.oc2pus.1 +- initial rpm +- directfb disabled, doesn't compile diff --git a/branches/V-1.5.3/veejay-server/veejay/Makefile.am b/branches/V-1.5.3/veejay-server/veejay/Makefile.am new file mode 100644 index 00000000..2ccf168d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/Makefile.am @@ -0,0 +1,78 @@ +# Makefile for veejay + +MAINTAINERCLEANFILES = Makefile.in +AM_CFLAGS=$(OP_CFLAGS) +INCLUDES = -I$(top_srcdir) -I$(includedir) \ + -DG_LOG_DOMAIN=\"veejay\" -DVEEJAY_VERSION=\"$(VERSION)\" \ + -I$(top_srcdir)/mjpegtools \ + -I /usr/X11R6/include -I$(top_srcdir)/libOSC \ + -I$(top_srcdir)/libhash \ + -I$(top_srcdir)/libvje \ + -I$(top_srcdir)/libvjmem \ + -I$(top_srcdir)/libvjmsg \ + -I$(top_srcdir)/libvjnet \ + -I$(top_srcdir)/libel \ + -I$(top_srcdir)/libstream \ + -I$(top_scrdir)/libyuv \ + -I$(top_srcdir)/libsamplerec \ + -I$(top_srcdir)/libvevo \ + -I$(top_srcdir)/liblzo \ + -I$(top_srcdir)/bio2jack \ + $(FFMPEG_CFLAGS) $(LIBQUICKTIME_CFLAGS) $(FT_CFLAGS) \ + $(AVIPLAY_CFLAGS) $(XML2_CFLAGS) $(GTK_CFLAGS) $(DV_FLAGS) $(X_CFLAGS) $(LIBLO_CFLAGS) \ + $(DIRECTFB_CFLAGS) $(SDL_CFLAGS) $(JPEG_CFLAGS) $(JACK_CFLAGS) $(PTHREAD_CFLAGS) $(SAMPLERATE_CFLAGS) + +pkginclude_HEADERS = vims.h + +VEEJAY_LIB_FILE = libveejay.la + +lib_LTLIBRARIES = $(VEEJAY_LIB_FILE) + +libveejay_la_SOURCES = jpegutils.c vj-misc.c \ + vj-osc.c vjkf.c vj-event.c vj-eventman.c vj-perform.c \ + x11misc.c vj-sdl.c vj-dfb.c vj-viewport.c vj-composite.c \ + vj-font.c vj-pjack.c liblavplayvj.c + +libveejay_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -release $(LT_RELEASE) -no-undefined -export-dynamic $(DEBUGLIBS) + + +libveejay_la_LIBADD = -L$(top_builddir)/mjpegtools/ -lmjpegutils \ + -L$(top_builddir)/libOSC -lOSC \ + -L$(top_builddir)/libhash -lhash \ + -L$(top_builddir)/liblzo -lminilzo \ + -L$(top_builddir)/bio2jack -lbio2jack4vj \ + -L$(top_builddir)/libvjmsg -lvjmsg \ + -L$(top_builddir)/libvjmem -lvjmem \ + -L$(top_builddir)/libvje -lvje \ + -L$(top_builddir)/libsample -lsample \ + -L$(top_builddir)/libvjnet -lvjnet \ + -L$(top_builddir)/libel -lel \ + -L$(top_builddir)/libstream -lstream \ + -L$(top_builddir)/aclib -lac \ + -L$(top_builddir)/libyuv -lyuv \ + -L$(top_builddir)/libsamplerec -lsamplerec \ + -L$(top_builddir)/libvevo -lvevo + +libveejay_la_LDFLAGS += $(SDL_LIBS) $(DIRECTFB_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(FT_LDFLAGS) $(FT_LIBS) \ + $(XML2_LIBS) $(JPEG_LIBS) $(UNICAP_LIBS) $(LIBLO_LIBS) \ + $(FFMPEG_LIBS) $(XINERAMA_LIBS) \ + $(LIBDV_LIBS) $(LIBM_LIBS) $(PIXBUF_LIBS) $(JACK_LIBS) $(LIBQUICKTIME_LIBS) $(SAMPLERATE_LIBS) \ + -DDYNAMIC -O3 -Wall -rdynamic + +# ********************************************************************* +# The tools themselves +VEEJAY_BIN = veejay + +bin_PROGRAMS = $(VEEJAY_BIN) + +veejay_headers = vims.h jpegutils.h vevo.h vj-composite.h vj-jack.h \ + vj-OSC.h vj-viewport.h lav_common.h vims.h vj-dfb.h \ + vjkf.h vj-perform.h vj-viewport-xml.h libveejay.h \ + vj-audio.h vj-event.h vj-lib.h vj-plug.h x11misc.h \ + veejay.h vj-bjack.h vj-font.h vj-misc.h vj-sdl.h + + +veejay_SOURCES = veejay.c ${veejay_headers} +veejay_LDADD = libveejay.la @LIBGETOPT_LIB@ + diff --git a/branches/V-1.5.3/veejay-server/veejay/jpegutils.c b/branches/V-1.5.3/veejay-server/veejay/jpegutils.c new file mode 100644 index 00000000..280ecfec --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/jpegutils.c @@ -0,0 +1,1105 @@ +/* + * jpegutils.c: Some Utility programs for dealing with + * JPEG encoded images + * + * Copyright (C) 1999 Rainer Johanni + * Copyright (C) 2001 pHilipp Zabel + * + * based on jdatasrc.c and jdatadst.c from the Independent + * JPEG Group's software by Thomas G. Lane + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#ifdef HAVE_JPEG +#include +#include +#include +#include + +#include +#include + +#include + +#include "jpegutils.h" +#include + + /* + * jpeg_data: buffer with input / output jpeg + * len: Length of jpeg buffer + * itype: 0: Not interlaced + * 1: Interlaced, Top field first + * 2: Interlaced, Bottom field first + * ctype Chroma format for decompression. + * Currently always 420 and hence ignored. + * raw0 buffer with input / output raw Y channel + * raw1 buffer with input / output raw U/Cb channel + * raw2 buffer with input / output raw V/Cr channel + * width width of Y channel (width of U/V is width/2) + * height height of Y channel (height of U/V is height/2) + */ + + +static void jpeg_buffer_src(j_decompress_ptr cinfo, unsigned char *buffer, + long num); +static void jpeg_buffer_dest(j_compress_ptr cinfo, unsigned char *buffer, + long len); +static void jpeg_skip_ff(j_decompress_ptr cinfo); + +/******************************************************************* + * * + * The following routines define a JPEG Source manager which * + * just reads from a given buffer (instead of a file as in * + * the jpeg library) * + * * + *******************************************************************/ + + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +static void init_source(j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * Should never be called since all data should be allready provided. + * Is nevertheless sometimes called - sets the input buffer to data + * which is the JPEG EOI marker; + * + */ + +static uint8_t EOI_data[2] = { 0xFF, 0xD9 }; + +static boolean fill_input_buffer(j_decompress_ptr cinfo) +{ + cinfo->src->next_input_byte = EOI_data; + cinfo->src->bytes_in_buffer = 2; + return TRUE; +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + */ + +static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + if (num_bytes > 0) { + if (num_bytes > (long) cinfo->src->bytes_in_buffer) + num_bytes = (long) cinfo->src->bytes_in_buffer; + cinfo->src->next_input_byte += (size_t) num_bytes; + cinfo->src->bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + */ + +static void term_source(j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a data buffer. + */ + +static void +jpeg_buffer_src(j_decompress_ptr cinfo, unsigned char *buffer, long num) +{ + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same buffer by calling jpeg_buffer_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if (cinfo->src == NULL) { /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, + JPOOL_PERMANENT, + sizeof(struct jpeg_source_mgr)); + } + + cinfo->src->init_source = init_source; + cinfo->src->fill_input_buffer = fill_input_buffer; + cinfo->src->skip_input_data = skip_input_data; + cinfo->src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ + cinfo->src->term_source = term_source; + cinfo->src->bytes_in_buffer = num; + cinfo->src->next_input_byte = (JOCTET *) buffer; +} + + +/* + * jpeg_skip_ff is not a part of the source manager but it is + * particularly useful when reading several images from the same buffer: + * It should be called to skip padding 0xff bytes beetween images. + */ + +static void jpeg_skip_ff(j_decompress_ptr cinfo) +{ + while (cinfo->src->bytes_in_buffer > 1 + && cinfo->src->next_input_byte[0] == 0xff + && cinfo->src->next_input_byte[1] == 0xff) { + cinfo->src->bytes_in_buffer--; + cinfo->src->next_input_byte++; + } +} + + +/******************************************************************* + * * + * The following routines define a JPEG Destination manager * + * which just reads from a given buffer (instead of a file * + * as in the jpeg library) * + * * + *******************************************************************/ + + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +static void init_destination(j_compress_ptr cinfo) +{ + /* No work necessary here */ +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * Should never be called since all data should be written to the buffer. + * If it gets called, the given jpeg buffer was too small. + * + */ + +static boolean empty_output_buffer(j_compress_ptr cinfo) +{ + /*FIXME: */ + mjpeg_error("Given jpeg buffer was too small!"); + ERREXIT(cinfo, JERR_BUFFER_SIZE); /* shouldn't be FILE_WRITE but BUFFER_OVERRUN! */ + return TRUE; +} + + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +static void term_destination(j_compress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +static void +jpeg_buffer_dest(j_compress_ptr cinfo, unsigned char *buf, long len) +{ + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, + JPOOL_PERMANENT, + sizeof(struct + jpeg_destination_mgr)); + } + + cinfo->dest->init_destination = init_destination; + cinfo->dest->empty_output_buffer = empty_output_buffer; + cinfo->dest->term_destination = term_destination; + cinfo->dest->free_in_buffer = len; + cinfo->dest->next_output_byte = (JOCTET *) buf; +} + + +/******************************************************************* + * * + * decode_jpeg_data: Decode a (possibly interlaced) JPEG frame * + * * + *******************************************************************/ + +/* + * ERROR HANDLING: + * + * We want in all cases to return to the user. + * The following kind of error handling is from the + * example.c file in the Independent JPEG Group's JPEG software + */ + +struct my_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + jmp_buf setjmp_buffer; /* for return to caller */ +}; + +static void my_error_exit(j_common_ptr cinfo) +{ + /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ + struct my_error_mgr *myerr = (struct my_error_mgr *) cinfo->err; + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + (*cinfo->err->output_message) (cinfo); + + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} + +#define MAX_LUMA_WIDTH 4096 +#define MAX_CHROMA_WIDTH 2048 + +static unsigned char buf0[16][MAX_LUMA_WIDTH]; +static unsigned char buf1[8][MAX_CHROMA_WIDTH]; +static unsigned char buf2[8][MAX_CHROMA_WIDTH]; +static unsigned char chr1[8][MAX_CHROMA_WIDTH]; +static unsigned char chr2[8][MAX_CHROMA_WIDTH]; + + + +#if 1 /* generation of 'std' Huffman tables... */ + +static void add_huff_table(j_decompress_ptr dinfo, + JHUFF_TBL ** htblptr, + const UINT8 * bits, const UINT8 * val) +/* Define a Huffman table */ +{ + int nsymbols, len; + + if (*htblptr == NULL) + *htblptr = jpeg_alloc_huff_table((j_common_ptr) dinfo); + + /* Copy the number-of-symbols-of-each-code-length counts */ + memcpy((*htblptr)->bits, bits, sizeof((*htblptr)->bits)); + + /* Validate the counts. We do this here mainly so we can copy the right + * number of symbols from the val[] array, without risking marching off + * the end of memory. jchuff.c will do a more thorough test later. + */ + nsymbols = 0; + for (len = 1; len <= 16; len++) + nsymbols += bits[len]; + if (nsymbols < 1 || nsymbols > 256) + mjpeg_error_exit1("jpegutils.c: add_huff_table failed badly. "); + + memcpy((*htblptr)->huffval, val, nsymbols * sizeof(UINT8)); +} + + + +static void std_huff_tables(j_decompress_ptr dinfo) +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +{ + static const UINT8 bits_dc_luminance[17] = + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_luminance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_dc_chrominance[17] = + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + static const UINT8 val_dc_chrominance[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + + static const UINT8 bits_ac_luminance[17] = + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, + 0x7d + }; + static const UINT8 val_ac_luminance[] = + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + static const UINT8 bits_ac_chrominance[17] = + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, + 0x77 + }; + static const UINT8 val_ac_chrominance[] = + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa + }; + + add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[0], + bits_dc_luminance, val_dc_luminance); + add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[0], + bits_ac_luminance, val_ac_luminance); + add_huff_table(dinfo, &dinfo->dc_huff_tbl_ptrs[1], + bits_dc_chrominance, val_dc_chrominance); + add_huff_table(dinfo, &dinfo->ac_huff_tbl_ptrs[1], + bits_ac_chrominance, val_ac_chrominance); +} + + + +static void guarantee_huff_tables(j_decompress_ptr dinfo) +{ + if ((dinfo->dc_huff_tbl_ptrs[0] == NULL) && + (dinfo->dc_huff_tbl_ptrs[1] == NULL) && + (dinfo->ac_huff_tbl_ptrs[0] == NULL) && + (dinfo->ac_huff_tbl_ptrs[1] == NULL)) { + mjpeg_debug("Generating standard Huffman tables for this frame."); + std_huff_tables(dinfo); + } +} + + +#endif /* ...'std' Huffman table generation */ + + + +/* + * jpeg_data: Buffer with jpeg data to decode + * len: Length of buffer + * itype: 0: Not interlaced + * 1: Interlaced, Top field first + * 2: Interlaced, Bottom field first + * ctype Chroma format for decompression. + * Currently always 420 and hence ignored. + */ + +int decode_jpeg_raw(unsigned char *jpeg_data, int len, + int itype, int ctype, int width, int height, + unsigned char *raw0, unsigned char *raw1, + unsigned char *raw2) +{ + int numfields, hsf[3], vsf[3], field, yl, yc, x, y = + 0, i, xsl, xsc, xs, xd, hdown; + + JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3], + buf0[4], buf0[5], buf0[6], buf0[7], + buf0[8], buf0[9], buf0[10], buf0[11], + buf0[12], buf0[13], buf0[14], buf0[15] + }; + JSAMPROW row1[8] = { buf1[0], buf1[1], buf1[2], buf1[3], + buf1[4], buf1[5], buf1[6], buf1[7] + }; + JSAMPROW row2[16] = { buf2[0], buf2[1], buf2[2], buf2[3], + buf2[4], buf2[5], buf2[6], buf2[7] + }; + JSAMPROW row1_444[16], row2_444[16]; + JSAMPARRAY scanarray[3] = { row0, row1, row2 }; + struct jpeg_decompress_struct dinfo; + struct my_error_mgr jerr; + + /* We set up the normal JPEG error routines, then override error_exit. */ + dinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + jpeg_destroy_decompress(&dinfo); + return -1; + } + + jpeg_create_decompress(&dinfo); + + jpeg_buffer_src(&dinfo, jpeg_data, len); + + /* Read header, make some checks and try to figure out what the + user really wants */ + + jpeg_read_header(&dinfo, TRUE); + dinfo.raw_data_out = TRUE; + dinfo.out_color_space = JCS_YCbCr; +// dinfo.dct_method = (_dct_method == 0 ? JDCT_DEFAULT : JDCT_FLOAT); + dinfo.dct_method = JDCT_DEFAULT; + guarantee_huff_tables(&dinfo); + jpeg_start_decompress(&dinfo); + + if (dinfo.output_components != 3) { + mjpeg_error("Output components of JPEG image = %d, must be 3", + dinfo.output_components); + goto ERR_EXIT; + } + + for (i = 0; i < 3; i++) { + hsf[i] = dinfo.comp_info[i].h_samp_factor; + vsf[i] = dinfo.comp_info[i].v_samp_factor; + } + + mjpeg_error( "Sampling factors, hsf=(%d, %d, %d) vsf=(%d, %d, %d) !", hsf[0], hsf[1], hsf[2], vsf[0], vsf[1], vsf[2]); + if ((hsf[0] != 2 && hsf[0] != 1) || hsf[1] != 1 || hsf[2] != 1 || + (vsf[0] != 1 && vsf[0] != 2) || vsf[1] != 1 || vsf[2] != 1) { + mjpeg_error + ("Unsupported sampling factors, hsf=(%d, %d, %d) vsf=(%d, %d, %d) !", + hsf[0], hsf[1], hsf[2], vsf[0], vsf[1], vsf[2]); + goto ERR_EXIT; + } + + if (hsf[0] == 1) { + if (height % 8 != 0) { + mjpeg_error + ("YUV 4:4:4 sampling, but image height %d not dividable by 8 !\n", + height); + goto ERR_EXIT; + } + + mjpeg_info + ("YUV 4:4:4 sampling encountered ! Allocating special row buffer\n"); + for (y = 0; y < 16; y++) // allocate a special buffer for the extra sampling depth + { + //mjpeg_info("YUV 4:4:4 %d.\n",y); + row1_444[y] = + (unsigned char *) malloc(dinfo.output_width * + sizeof(char)); + row2_444[y] = + (unsigned char *) malloc(dinfo.output_width * + sizeof(char)); + } + //mjpeg_info("YUV 4:4:4 sampling encountered ! Allocating done.\n"); + scanarray[1] = row1_444; + scanarray[2] = row2_444; + } + + /* Height match image height or be exact twice the image height */ + + if (dinfo.output_height == height) { + numfields = 1; + } else if (2 * dinfo.output_height == height) { + numfields = 2; + } else { + mjpeg_error + ("Read JPEG: requested height = %d, height of image = %d", + height, dinfo.output_height); + goto ERR_EXIT; + } + + /* Width is more flexible */ + + if (dinfo.output_width > MAX_LUMA_WIDTH) { + mjpeg_error("Image width of %d exceeds max", dinfo.output_width); + goto ERR_EXIT; + } + if (width < 2 * dinfo.output_width / 3) { + /* Downclip 2:1 */ + + hdown = 1; + if (2 * width < dinfo.output_width) + xsl = (dinfo.output_width - 2 * width) / 2; + else + xsl = 0; + } else if (width == 2 * dinfo.output_width / 3) { + /* special case of 3:2 downsampling */ + + hdown = 2; + xsl = 0; + } else { + /* No downsampling */ + + hdown = 0; + if (width < dinfo.output_width) + xsl = (dinfo.output_width - width) / 2; + else + xsl = 0; + } + + /* Make xsl even, calculate xsc */ + + xsl = xsl & ~1; + xsc = xsl / 2; + + yl = yc = 0; + + for (field = 0; field < numfields; field++) { + if (field > 0) { + jpeg_read_header(&dinfo, TRUE); + dinfo.raw_data_out = TRUE; + dinfo.out_color_space = JCS_YCbCr; + dinfo.dct_method = JDCT_FLOAT; //JDCT_DEFAULT; + jpeg_start_decompress(&dinfo); + } + + if (numfields == 2) { + switch (itype) { + case LAV_INTER_TOP_FIRST: + yl = yc = field; + break; + case LAV_INTER_BOTTOM_FIRST: + yl = yc = (1 - field); + break; + default: + mjpeg_error("Input is interlaced but no interlacing set"); + goto ERR_EXIT; + } + } else + yl = yc = 0; + + while (dinfo.output_scanline < dinfo.output_height) { + /* read raw data */ + jpeg_read_raw_data(&dinfo, scanarray, 8 * vsf[0]); + + for (y = 0; y < 8 * vsf[0]; yl += numfields, y++) { + xd = yl * width; + xs = xsl; + + if (hdown == 0) + for (x = 0; x < width; x++) + raw0[xd++] = row0[y][xs++]; + else if (hdown == 1) + for (x = 0; x < width; x++, xs += 2) + raw0[xd++] = (row0[y][xs] + row0[y][xs + 1]) >> 1; + else + for (x = 0; x < width / 2; x++, xd += 2, xs += 3) { + raw0[xd] = (2 * row0[y][xs] + row0[y][xs + 1]) / 3; + raw0[xd + 1] = + (2 * row0[y][xs + 2] + row0[y][xs + 1]) / 3; + } + } + + /* Horizontal downsampling of chroma */ + + for (y = 0; y < 8; y++) { + xs = xsc; + + if (hsf[0] == 1) + for (x = 0; x < width / 2; x++, xs++) { + row1[y][xs] = + (row1_444[y][2 * x] + + row1_444[y][2 * x + 1]) >> 1; + row2[y][xs] = + (row2_444[y][2 * x] + + row2_444[y][2 * x + 1]) >> 1; + } + + xs = xsc; + if (hdown == 0) + for (x = 0; x < width / 2; x++, xs++) { + chr1[y][x] = row1[y][xs]; + chr2[y][x] = row2[y][xs]; + } else if (hdown == 1) + for (x = 0; x < width / 2; x++, xs += 2) { + chr1[y][x] = (row1[y][xs] + row1[y][xs + 1]) >> 1; + chr2[y][x] = (row2[y][xs] + row2[y][xs + 1]) >> 1; + } else + for (x = 0; x < width / 2; x += 2, xs += 3) { + chr1[y][x] = + (2 * row1[y][xs] + row1[y][xs + 1]) / 3; + chr1[y][x + 1] = + (2 * row1[y][xs + 2] + row1[y][xs + 1]) / 3; + chr2[y][x] = + (2 * row2[y][xs] + row2[y][xs + 1]) / 3; + chr2[y][x + 1] = + (2 * row2[y][xs + 2] + row2[y][xs + 1]) / 3; + } + } + + /* Vertical downsampling of chroma */ + + if (vsf[0] == 1) { + for (y = 0; y < 8 /*&& yc < height/2 */ ; + y += 2, yc += numfields) { + xd = yc * width / 2; + for (x = 0; x < width / 2; x++, xd++) { + assert(xd < (width * height / 4)); + raw1[xd] = (chr1[y][x] + chr1[y + 1][x]) >> 1; + raw2[xd] = (chr2[y][x] + chr2[y + 1][x]) >> 1; + } + } + + } else { + /* Just copy */ + for (y = 0; y < 8 /*&& yc < height/2 */ ; + y++, yc += numfields) { + xd = yc * width / 2; + for (x = 0; x < width / 2; x++, xd++) { + raw1[xd] = chr1[y][x]; + raw2[xd] = chr2[y][x]; + } + } + } + } + + (void) jpeg_finish_decompress(&dinfo); + if (field == 0 && numfields > 1) + jpeg_skip_ff(&dinfo); + } + + if (hsf[0] == 1) { + //mjpeg_info("YUV 4:4:4 sampling encountered ! Deallocating special row buffer\n"); + for (y = 0; y < 16; y++) // allocate a special buffer for the extra sampling depth + { + free(row1_444[y]); + free(row2_444[y]); + } + } + + jpeg_destroy_decompress(&dinfo); + return 0; + + ERR_EXIT: + jpeg_destroy_decompress(&dinfo); + return -1; +} + +/* + * jpeg_data: Buffer with jpeg data to decode, must be grayscale mode + * len: Length of buffer + * itype: 0: Not interlaced + * 1: Interlaced, Top field first + * 2: Interlaced, Bottom field first + * ctype Chroma format for decompression. + * Currently always 420 and hence ignored. + */ + + +int decode_jpeg_gray_raw(unsigned char *jpeg_data, int len, + int itype, int ctype, int width, int height, + unsigned char *raw0, unsigned char *raw1, + unsigned char *raw2) +{ + int numfields, hsf[3], vsf[3], field, yl, yc, x, y, xsl, xsc, xs, xd, + hdown; + + JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3], + buf0[4], buf0[5], buf0[6], buf0[7], + buf0[8], buf0[9], buf0[10], buf0[11], + buf0[12], buf0[13], buf0[14], buf0[15] + }; + JSAMPARRAY scanarray[3] = { row0 }; + struct jpeg_decompress_struct dinfo; + struct my_error_mgr jerr; + + mjpeg_info("decoding jpeg gray\n"); + + /* We set up the normal JPEG error routines, then override error_exit. */ + dinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + jpeg_destroy_decompress(&dinfo); + return -1; + } + + jpeg_create_decompress(&dinfo); + + jpeg_buffer_src(&dinfo, jpeg_data, len); + + /* Read header, make some checks and try to figure out what the + user really wants */ + + jpeg_read_header(&dinfo, TRUE); + dinfo.raw_data_out = TRUE; + dinfo.out_color_space = JCS_GRAYSCALE; +// dinfo.dct_method = ( _dct_method == 0 ? JDCT_DEFAULT: JDCT_FLOAT); + dinfo.dct_method = JDCT_DEFAULT; + + if (dinfo.jpeg_color_space != JCS_GRAYSCALE) { + mjpeg_error + ("FATAL: Expected grayscale colorspace for JPEG raw decoding"); + goto ERR_EXIT; + } + + guarantee_huff_tables(&dinfo); + jpeg_start_decompress(&dinfo); + + hsf[0] = 1; + hsf[1] = 1; + hsf[2] = 1; + vsf[0] = 1; + vsf[1] = 1; + vsf[2] = 1; + + /* Height match image height or be exact twice the image height */ + + if (dinfo.output_height == height) { + numfields = 1; + } else if (2 * dinfo.output_height == height) { + numfields = 2; + } else { + mjpeg_error + ("Read JPEG: requested height = %d, height of image = %d", + height, dinfo.output_height); + goto ERR_EXIT; + } + + /* Width is more flexible */ + + if (dinfo.output_width > MAX_LUMA_WIDTH) { + mjpeg_error("Image width of %d exceeds max", dinfo.output_width); + goto ERR_EXIT; + } + if (width < 2 * dinfo.output_width / 3) { + /* Downclip 2:1 */ + + hdown = 1; + if (2 * width < dinfo.output_width) + xsl = (dinfo.output_width - 2 * width) / 2; + else + xsl = 0; + } else if (width == 2 * dinfo.output_width / 3) { + /* special case of 3:2 downsampling */ + + hdown = 2; + xsl = 0; + } else { + /* No downsampling */ + + hdown = 0; + if (width < dinfo.output_width) + xsl = (dinfo.output_width - width) / 2; + else + xsl = 0; + } + + /* Make xsl even, calculate xsc */ + + xsl = xsl & ~1; + xsc = xsl / 2; + + yl = yc = 0; + + for (field = 0; field < numfields; field++) { + if (field > 0) { + jpeg_read_header(&dinfo, TRUE); + dinfo.raw_data_out = TRUE; + dinfo.out_color_space = JCS_GRAYSCALE; + dinfo.dct_method = JDCT_FLOAT;//DCT_DEFAULT; + jpeg_start_decompress(&dinfo); + } + + if (numfields == 2) { + switch (itype) { + case LAV_INTER_TOP_FIRST: + yl = yc = field; + break; + case LAV_INTER_BOTTOM_FIRST: + yl = yc = (1 - field); + break; + default: + mjpeg_error("Input is interlaced but no interlacing set"); + goto ERR_EXIT; + } + } else + yl = yc = 0; + + while (dinfo.output_scanline < dinfo.output_height) { + jpeg_read_raw_data(&dinfo, scanarray, 16); + + for (y = 0; y < 8 * vsf[0]; yl += numfields, y++) { + xd = yl * width; + xs = xsl; + + if (hdown == 0) // no horiz downsampling + for (x = 0; x < width; x++) + raw0[xd++] = row0[y][xs++]; + else if (hdown == 1) // half the res + for (x = 0; x < width; x++, xs += 2) + raw0[xd++] = (row0[y][xs] + row0[y][xs + 1]) >> 1; + else // 2:3 downsampling + for (x = 0; x < width / 2; x++, xd += 2, xs += 3) { + raw0[xd] = (2 * row0[y][xs] + row0[y][xs + 1]) / 3; + raw0[xd + 1] = + (2 * row0[y][xs + 2] + row0[y][xs + 1]) / 3; + } + } + + //mjpeg_info("/* Horizontal downsampling of chroma - in Grayscale, all this is ZERO ! */"); + + for (y = 0; y < 8; y++) { + xs = xsc; + + if (hdown == 0) + for (x = 0; x < width / 2; x++, xs++) { + chr1[y][x] = 0; //row1[y][xs]; + chr2[y][x] = 0; //row2[y][xs]; + } else if (hdown == 1) + for (x = 0; x < width / 2; x++, xs += 2) { + chr1[y][x] = 0; //(row1[y][xs] + row1[y][xs + 1]) >> 1; + chr2[y][x] = 0; //(row2[y][xs] + row2[y][xs + 1]) >> 1; + } else + for (x = 0; x < width / 2; x += 2, xs += 3) { + chr1[y][x] = 0; //(2 * row1[y][xs] + row1[y][xs + 1]) / 3; + chr1[y][x + 1] = 0; + //(2 * row1[y][xs + 2] + row1[y][xs + 1]) / 3; + chr2[y][x] = 0; // (2 * row2[y][xs] + row2[y][xs + 1]) / 3; + chr2[y][x + 1] = 0; + //(2 * row2[y][xs + 2] + row2[y][xs + 1]) / 3; + } + } + + //mjpeg_info("/* Vertical downsampling of chroma, line %d, max %d */", dinfo.output_scanline, dinfo.output_height); + + if (vsf[0] == 1) { + /* Really downclip */ + for (y = 0; y < 8; y += 2, yc += numfields) { + xd = yc * width / 2; + for (x = 0; x < width / 2; x++, xd++) { + raw1[xd] = 127; //(chr1[y][x] + chr1[y + 1][x]) >> 1; + raw2[xd] = 127; //(chr2[y][x] + chr2[y + 1][x]) >> 1; + } + } + } else { + /* Just copy */ + + for (y = 0; y < 8; y++, yc += numfields) { + xd = yc * width / 2; + for (x = 0; x < width / 2; x++, xd++) { + raw1[xd] = 127; //chr1[y][x]; + raw2[xd] = 127; //chr2[y][x]; + } + } + } + } + + (void) jpeg_finish_decompress(&dinfo); + if (field == 0 && numfields > 1) + jpeg_skip_ff(&dinfo); + } + + jpeg_destroy_decompress(&dinfo); + return 0; + + ERR_EXIT: + jpeg_destroy_decompress(&dinfo); + return -1; +} + + +/******************************************************************* + * * + * encode_jpeg_data: Compress raw YCbCr data (output JPEG * + * may be interlaced * + * * + *******************************************************************/ + + /* + * jpeg_data: Buffer to hold output jpeg + * len: Length of buffer + * itype: 0: Not interlaced + * 1: Interlaced, Top field first + * 2: Interlaced, Bottom field first + * ctype Chroma format for decompression. + * Currently always 420 and hence ignored. + */ + +int encode_jpeg_raw(unsigned char *jpeg_data, int len, int quality,int dct_method, + int itype, int ctype, int width, int height, + unsigned char *raw0, unsigned char *raw1, + unsigned char *raw2) +{ + int numfields, field, yl, yc, y, i; + + JSAMPROW row0[16] = { buf0[0], buf0[1], buf0[2], buf0[3], + buf0[4], buf0[5], buf0[6], buf0[7], + buf0[8], buf0[9], buf0[10], buf0[11], + buf0[12], buf0[13], buf0[14], buf0[15] + }; + JSAMPROW row1[8] = { buf1[0], buf1[1], buf1[2], buf1[3], + buf1[4], buf1[5], buf1[6], buf1[7] + }; + JSAMPROW row2[8] = { buf2[0], buf2[1], buf2[2], buf2[3], + buf2[4], buf2[5], buf2[6], buf2[7] + }; + JSAMPARRAY scanarray[3] = { row0, row1, row2 }; + + struct jpeg_compress_struct cinfo; + struct my_error_mgr jerr; + + /* We set up the normal JPEG error routines, then override error_exit. */ + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + jpeg_destroy_compress(&cinfo); + return -1; + } + + jpeg_create_compress(&cinfo); + + jpeg_buffer_dest(&cinfo, jpeg_data, len); + + /* Set some jpeg header fields */ + + cinfo.input_components = 3; + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, FALSE); + + cinfo.raw_data_in = TRUE; + cinfo.in_color_space = JCS_YCbCr; + cinfo.dct_method = JDCT_FLOAT;// CT_DEFAULT; + + cinfo.input_gamma = 1.0; + + cinfo.comp_info[0].h_samp_factor = 2; + cinfo.comp_info[0].v_samp_factor = 1; /*1||2 */ + cinfo.comp_info[1].h_samp_factor = 1; + cinfo.comp_info[1].v_samp_factor = 1; + cinfo.comp_info[2].h_samp_factor = 1; /*1||2 */ + cinfo.comp_info[2].v_samp_factor = 1; + + + if ((width > 4096) || (height > 4096)) { + mjpeg_error + ("Image dimensions (%dx%d) exceed veejay' max (4096x4096)", + width, height); + goto ERR_EXIT; + } + if ((width % 16) || (height % 16)) { + mjpeg_error("Image dimensions (%dx%d) not multiples of 16", width, + height); + goto ERR_EXIT; + } + cinfo.image_width = width; + switch (itype) { + case LAV_INTER_TOP_FIRST: + case LAV_INTER_BOTTOM_FIRST: /* interlaced */ + numfields = 2; + break; + default: + numfields = 1; + if (height > 2048) { + mjpeg_error + ("Image height (%d) exceeds lavtools max for non-interlaced frames", + height); + goto ERR_EXIT; + } + } + cinfo.image_height = height / numfields; + + yl = yc = 0; /* y luma, chroma */ + + for (field = 0; field < numfields; field++) { + + jpeg_start_compress(&cinfo, FALSE); + + if (numfields == 2) { + static const JOCTET marker0[40]; + + jpeg_write_marker(&cinfo, JPEG_APP0, marker0, 14); + jpeg_write_marker(&cinfo, JPEG_APP0 + 1, marker0, 40); + + switch (itype) { + case LAV_INTER_TOP_FIRST: /* top field first */ + yl = yc = field; + break; + case LAV_INTER_BOTTOM_FIRST: /* bottom field first */ + yl = yc = (1 - field); + break; + default: + mjpeg_error("Input is interlaced but no interlacing set"); + goto ERR_EXIT; + } + } else + yl = yc = 0; + + while (cinfo.next_scanline < cinfo.image_height) { + + for (y = 0; y < 8 * cinfo.comp_info[0].v_samp_factor; + yl += numfields, y++) { + row0[y] = &raw0[yl * width]; + } + for (y = 0; y < 8; y++) { + row1[y] = &raw1[yc * width / 2]; + row2[y] = &raw2[yc * width / 2]; + if (y % 2) + yc += numfields; + } + + jpeg_write_raw_data(&cinfo, scanarray, + 8 * cinfo.comp_info[0].v_samp_factor); + + } + + (void) jpeg_finish_compress(&cinfo); + } + + /* FIXME */ + i = len - cinfo.dest->free_in_buffer; + + jpeg_destroy_compress(&cinfo); + + return i; /* size of jpeg */ + + ERR_EXIT: + jpeg_destroy_compress(&cinfo); + return -1; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/jpegutils.h b/branches/V-1.5.3/veejay-server/veejay/jpegutils.h new file mode 100644 index 00000000..030d22ab --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/jpegutils.h @@ -0,0 +1,59 @@ +/* + * jpegutils.h: Some Utility programs for dealing with + * JPEG encoded images + * + * Copyright (C) 1999 Rainer Johanni + * Copyright (C) 2001 pHilipp Zabel + * + * based on jdatasrc.c and jdatadst.c from the Independent + * JPEG Group's software by Thomas G. Lane + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef __JPEGUTILS_H__ +#define __JPEGUTILS_H__ + + /* + * jpeg_data: buffer with input / output jpeg + * len: Length of jpeg buffer + * itype: LAV_INTER_NONE: Not interlaced + * LAV_INTER_TOP_FIRST: Interlaced, top-field-first + * LAV_INTER_BOTTOM_FIRST: Interlaced, bottom-field-first + * ctype Chroma format for decompression. + * Currently always 420 and hence ignored. + * dtype DCT Method ( + * raw0 buffer with input / output raw Y channel + * raw1 buffer with input / output raw U/Cb channel + * raw2 buffer with input / output raw V/Cr channel + * width width of Y channel (width of U/V is width/2) + * height height of Y channel (height of U/V is height/2) + */ + +int decode_jpeg_raw(unsigned char *jpeg_data, int len, + int itype, int ctype, int width, int height, + unsigned char *raw0, unsigned char *raw1, + unsigned char *raw2); +int decode_jpeg_gray_raw(unsigned char *jpeg_data, int len, + int itype, int ctype, int width, int height, + unsigned char *raw0, unsigned char *raw1, + unsigned char *raw2); +int encode_jpeg_raw(unsigned char *jpeg_data, int len, int quality,int dct, + int itype, int ctype, int width, int height, + unsigned char *raw0, unsigned char *raw1, + unsigned char *raw2); +/* +void jpeg_skip_ff (j_decompress_ptr cinfo); +*/ +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/lav_common.c b/branches/V-1.5.3/veejay-server/veejay/lav_common.c new file mode 100644 index 00000000..242ae23e --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/lav_common.c @@ -0,0 +1,204 @@ +/* lav_common - some general utility functionality used by multiple + lavtool utilities. */ + +/* Copyright (C) 2000, Rainer Johanni, Andrew Stevens */ +/* - added scene change detection code 2001, pHilipp Zabel */ +/* - broke some code out to lav_common.h and lav_common.c + * July 2001, Shawn Sulma . In doing this, + * I replaced the large number of globals with a handful of structs + * that are passed into the appropriate methods. Check lav_common.h + * for the structs. I'm sure some of what I've done is inefficient, + * subtly incorrect or just plain Wrong. Feedback is welcome. + */ +/* - removed a lot of subsumed functionality and unnecessary cruft + * March 2002, Matthew Marjanovic . + */ + + +/* + 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 + +static uint8_t jpeg_data[MAX_JPEG_LEN]; + + +#ifdef SUPPORT_READ_DV2 + +dv_decoder_t *decoder; +#ifdef LIBDV_PRE_0_9_5 +gint pitches[3]; +#else +int pitches[3]; +#endif +uint8_t *dv_frame[3] = { NULL, NULL, NULL }; + +/* + * As far as I (maddog) can tell, this is what is going on with libdv-0.9 + * and the unpacking routine... + * o Ft/Fb refer to top/bottom scanlines (interleaved) --- each sample + * is implicitly tagged by 't' or 'b' (samples are not mixed between + * fields) + * o Indices on Cb and Cr samples indicate the Y sample with which + * they are co-sited. + * o '^' indicates which samples are preserved by the unpacking + * + * libdv packs both NTSC 4:1:1 and PAL 4:2:0 into a common frame format of + * packed 4:2:2 pixels as follows: + * + * + ***** NTSC 4:1:1 ***** + * + * libdv's 4:2:2-packed representation (chroma repeated horizontally) + * + *Ft Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + *Fb Y00.Cb00.Y01.Cr00.Y02.Cb00.Y03.Cr00 Y04.Cb04.Y05.Cr04.Y06.Cb04.Y07.Cr04 + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + *Ft Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 + * ^ ^ ^ ^ ^ ^ ^ ^ + *Fb Y10.Cb10.Y11.Cr10.Y12.Cb10.Y13.Cr10 Y14.Cb14.Y15.Cr14.Y16.Cb14.Y17.Cr14 + * ^ ^ ^ ^ ^ ^ ^ ^ + * + * lavtools unpacking into 4:2:0-planar (note lossiness) + * + *Ft Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... + *Fb Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... + *Ft Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... + *Fb Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... + * + *Ft Cb00.Cb00.Cb04.Cb04... Cb00,Cb04... are doubled + *Fb Cb00.Cb00.Cb04.Cb04... Cb10,Cb14... are ignored + * + *Ft Cr00.Cr00.Cr04.Cr04... + *Fb Cr00.Cr00.Cr04.Cr04... + * + * + ***** PAL 4:2:0 ***** + * + * libdv's 4:2:2-packed representation (chroma repeated vertically) + * + *Ft Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + *Fb Y00.Cb00.Y01.Cr10.Y02.Cb02.Y03.Cr12 Y04.Cb04.Y05.Cr14.Y06.Cb06.Y07.Cr16 + * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ + *Ft Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 + * ^ ^ ^ ^ ^ ^ ^ ^ + *Fb Y10.Cb00.Y11.Cr10.Y12.Cb02.Y13.Cr12 Y14.Cb04.Y15.Cr14.Y16.Cb06.Y17.Cr16 + * ^ ^ ^ ^ ^ ^ ^ ^ + * + * lavtools unpacking into 4:2:0-planar + * + *Ft Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... + *Fb Y00.Y01.Y02.Y03.Y04.Y05.Y06.Y07... + *Ft Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... + *Fb Y10.Y11.Y12.Y13.Y14.Y15.Y16.Y17... + * + *Ft Cb00.Cb02.Cb04.Cb06... + *Fb Cb00.Cb02.Cb04.Cb06... + * + *Ft Cr10.Cr12.Cr14.Cr16... + *Fb Cr10.Cr12.Cr14.Cr16... + * + */ + +/* + * Unpack libdv's 4:2:2-packed into our 4:2:0-planar + * + */ +void frame_YUV422_to_YUV420P(uint8_t ** output, uint8_t * input, + int width, int height) +{ + int i, j, w2; + uint8_t *y, *cb, *cr; + + w2 = width / 2; + y = output[0]; + cb = output[1]; + cr = output[2]; + + for (i = 0; i < height; i += 2) { + /* process two scanlines (one from each field, interleaved) */ + for (j = 0; j < w2; j++) { + /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */ + *(y++) = *(input++); + *(cb++) = *(input++); + *(y++) = *(input++); + *(cr++) = *(input++); + } + /* process next two scanlines (one from each field, interleaved) */ + for (j = 0; j < w2; j++) { + /* skip every second line for U and V */ + *(y++) = *(input++); + input++; + *(y++) = *(input++); + input++; + } + } +} + +#endif /* SUPPORT_READ_DV2 */ + + + +/*********************** + * + * Take a random(ish) sampled mean of a frame luma and chroma + * Its intended as a rough and ready hash of frame content. + * The idea is that changes above a certain threshold are treated as + * scene changes. + * + **********************/ + +int luminance_mean(uint8_t * frame[], int w, int h) +{ + uint8_t *p; + uint8_t *lim; + int sum = 0; + int count = 0; + p = frame[0]; + lim = frame[0] + w * (h - 1); + while (p < lim) { + sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); + p += 31; + count += 4; + } + + w = w / 2; + h = h / 2; + + p = frame[1]; + lim = frame[1] + w * (h - 1); + while (p < lim) { + sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); + p += 31; + count += 4; + } + p = frame[2]; + lim = frame[2] + w * (h - 1); + while (p < lim) { + sum += (p[0] + p[1]) + (p[w - 3] + p[w - 2]); + p += 31; + count += 4; + } + return sum / count; +} diff --git a/branches/V-1.5.3/veejay-server/veejay/lav_common.h b/branches/V-1.5.3/veejay-server/veejay/lav_common.h new file mode 100644 index 00000000..e4164fa2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/lav_common.h @@ -0,0 +1,100 @@ +/* lav_common - some general utility functionality used by multiple + lavtool utilities. */ + +/* Copyright (C) 2000, Rainer Johanni, Andrew Stevens */ +/* - added scene change detection code 2001, pHilipp Zabel */ +/* - broke some code out to lav_common.h and lav_common.c + * July 2001, Shawn Sulma . Part of these changes were + * to replace the large number of globals with a handful of structs that + * get passed in to the relevant functions. Some of this may be + * inefficient, subtly broken, or Wrong. Helpful feedback is certainly + * welcome. + */ +/* - removed a lot of subsumed functionality and unnecessary cruft + * March 2002, Matthew Marjanovic . + */ + +/* + 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 "editlist.h" +#include "yuv4mpeg.h" + + + +#include "mjpeg_logging.h" + + +#define MAX_EDIT_LIST_FILES 4096 +#define MAX_JPEG_LEN (3*576*768/2) + +#define BUFFER_ALIGN 16 + +/** + * (SS 2001-July-13) + * The split of the globals into three structs is somewhat arbitrary, but + * I've tried to do them based on role as used in lav2yuv and (my own) + * lav2divx. + * - LavParam handles data that is generally per-run dependent + * (e.g. from the command line). + * - LavBounds contains data about bounds used in processing. It is generally + * not dependent on command line alteration. + * - LavBuffer contains buffers used to perform various tasks. + * + **/ + +typedef struct { + int offset; + int frames; + int mono; + char *scenefile; + int delta_lum_threshold; /* = 4; */ + unsigned int scene_detection_decimation; /* = 2; */ + int output_width; + int output_height; + int interlace; + y4m_ratio_t sar; /* sample aspect ratio (default 0:0 == unspecified) */ + y4m_ratio_t dar; /* 'suggested' display aspect ratio */ + + int chroma_width; + int chroma_height; + int luma_size; + int chroma_size; +} LavParam; + + +int luminance_mean(uint8_t * frame[], int w, int h); + +int readframe(int numframe, uint8_t * frame[], + LavParam * param, EditList el); + +void writeoutYUV4MPEGheader(int out_fd, LavParam * param, EditList el, + y4m_stream_info_t * streaminfo); + +void init(LavParam * param, uint8_t * frame[]); + + +#ifdef SUPPORT_READ_DV2 + +#include + +void frame_YUV422_to_YUV420P(uint8_t ** output, uint8_t * input, + int width, int height); +void lav_init_dv_decoder(void); + +#endif /* SUPPORT_READ_DV2 */ diff --git a/branches/V-1.5.3/veejay-server/veejay/liblavplayvj.c b/branches/V-1.5.3/veejay-server/veejay/liblavplayvj.c new file mode 100644 index 00000000..e9c59f39 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/liblavplayvj.c @@ -0,0 +1,3801 @@ +/*liblavplayvj - a extended librarified Linux Audio Video playback/Editing + * VJ'fied by Niels Elburg + * + * + * libveejay - a librarified Linux Audio Video PLAYback + * + * Copyright (C) 2000 Rainer Johanni + * Extended by: Gernot Ziegler + * Ronald Bultje + * & many others + * + * A library for playing back MJPEG video via softwastre MJPEG + * decompression (using SDL) + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* this is a junkyard, need more modular structure + input / output modules for pulling/pushing of video frames + codecs for encoding/decoding video frames + fancy dlopen and family here +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jpegutils.h" +#include "vj-event.h" +#ifndef X_DISPLAY_MISSING +#include +#include +#endif +#ifdef HAVE_FREETYPE +#include +#endif +#ifndef X_DISPLAY_MISSING +#include +#endif +#include +#include +#ifdef HAVE_SYS_SOUNDCARD_H +#include +#endif +#define VIDEO_MODE_PAL 0 +#define VIDEO_MODE_NTSC 1 +#define VIDEO_MODE_SECAM 2 +#define VIDEO_MODE_AUTO 3 + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_JACK +#include +#endif +#include +#include +#include +#include +#define QUEUE_LEN 1 +#include +#ifdef STRICT_CHECKING +#include +#endif +/* +#ifdef HAVE_GL +#include +#endif +*/ +#include + +static veejay_t *veejay_instance_ = NULL; +static int best_performance_ = 0; + +void veejay_set_instance( veejay_t *info ) +{ + veejay_instance_ = info; +} + + +static void veejay_schedule_fifo( veejay_t *info, int pid ); + +// following struct copied from ../utils/videodev.h + +/* This is identical with the mgavideo internal params struct, + please tell me if you change this struct here ! top-field-first */ + + int APPn; /* Number of APP segment to be written, must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + unsigned long jpeg_markers; /* Which markers should go into the JPEG output. + Unless you exactly know what you do, leave them untouched. + Inluding less markers will make the resulting code + smaller, but there will be fewer aplications + which can read it. + The presence of the APP and COM marker is + influenced by APP0_len and COM_len ONLY! */ +#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ + + int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. + If this flag is turned on and JPEG decompressing + is going to the screen, the decompress process + is stopped every time the Video Fifo is full. + This enables a smooth decompress to the screen + but the video output signal will get scrambled */ + + /* Misc */ + + char reserved[312]; /* Makes 512 bytes for this structure */ +}; + +//#include +#include +#include +#ifdef HAVE_SDL +#include +#define MAX_SDL_OUT 2 +#endif +#include +#include +#include +#include "libveejay.h" +#include +#include "vj-perform.h" +#include +#include "mjpeg_types.h" +#ifdef HAVE_DIRECTFB +#include +#endif + +#ifdef HAVE_V4L +#include +#endif + +/* On some systems MAP_FAILED seems to be missing */ +#ifndef MAP_FAILED +#define MAP_FAILED ( (caddr_t) -1 ) +#endif +#define HZ 100 +#include +#define VALUE_NOT_FILLED -10000 + +extern void vj_osc_set_veejay_t(veejay_t *t); + +#ifdef HAVE_SDL +extern int vj_event_single_fire(void *ptr, SDL_Event event, int pressed); +#endif +static int total_mem_mb_ = 0; +static int chunk_size_ = 0; +static int n_cache_slots_ = 0; +int get_num_slots(void) +{ + return n_cache_slots_; +} +int get_total_mem(void) +{ + return total_mem_mb_; +} +int get_chunk_size(void) +{ + return chunk_size_; +} + +int veejay_get_state(veejay_t *info) { + video_playback_setup *settings = (video_playback_setup*)info->settings; + + return settings->state; +} +int veejay_set_yuv_range(veejay_t *info) { + switch(info->pixel_format) { + case FMT_422: + // rgb_parameter_conversion_type_ = 3; //JPEG/JFIF + // rgb_parameter_conversion_type_ = 1; //CCIR601_RGB; + set_pixel_range( 235,240,16,16 ); + veejay_msg(VEEJAY_MSG_DEBUG, "Using CCIR601 RGB <-> YUV "); + return 0; + break; + default: + // rgb_parameter_conversion_type_ = 0; //GIMP_RGB; + set_pixel_range( 255, 255,0,0 ); + veejay_msg(VEEJAY_MSG_DEBUG, "Using GIMP RGB <-> YUV "); + break; + } + return 1; +} + +/****************************************************** + * veejay_change_state() + * change the state + ******************************************************/ +static void veejay_reset_el_buffer( veejay_t *info ); + +#ifdef STRICT_CHECKING +void veejay_change_state1(veejay_t * info, int new_state) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + +// pthread_mutex_lock(&(settings->valid_mutex)); + settings->state = new_state; +// pthread_mutex_unlock(&(settings->valid_mutex)); +} + +#define veejay_change_state(a,b) vcs(a,b,__FUNCTION__,__LINE__) +void vcs(veejay_t *info, int new_state,const char *caller_func,const int caller_line) +{ + veejay_msg(VEEJAY_MSG_DEBUG, + "Change state to %d by %s:%d",new_state, + caller_func,caller_line); + veejay_change_state1(info,new_state); +} +#else + +void veejay_change_state(veejay_t * info, int new_state) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + +// pthread_mutex_lock(&(settings->valid_mutex)); + settings->state = new_state; +// pthread_mutex_unlock(&(settings->valid_mutex)); +} +#endif +void veejay_change_state_save(veejay_t * info, int new_state) +{ + if(new_state == LAVPLAY_STATE_STOP ) + { + char recover_samples[1024]; + char recover_edl[1024]; + pid_t my_pid = getpid(); + snprintf(recover_samples,1024, "%s/recovery/recovery_samplelist_p%d.sl", info->homedir, (int) my_pid); + snprintf(recover_edl, 1024, "%s/recovery/recovery_editlist_p%d.edl", info->homedir, (int) my_pid); + + int rs = sample_writeToFile( recover_samples,info->composite,info->seq,info->font, + info->uc->sample_id, info->uc->playback_mode ); + int re = veejay_save_all( info, recover_edl, 0, 0 ); + if(rs) + veejay_msg(VEEJAY_MSG_WARNING, "Saved samplelist to %s", recover_samples ); + if(re) + veejay_msg(VEEJAY_MSG_WARNING, "Saved Editlist to %s", recover_edl ); + } + + report_bug(); + + veejay_change_state( info, new_state ); +} + +int veejay_set_framedup(veejay_t *info, int n) { + video_playback_setup *settings = (video_playback_setup*) settings; + + switch(info->uc->playback_mode) { + case VJ_PLAYBACK_MODE_PLAIN: + info->sfd = n; + break; + case VJ_PLAYBACK_MODE_SAMPLE: + sample_set_framedup(info->uc->sample_id,n); + sample_set_framedups(info->uc->sample_id,0); + break; + default: + return -1; + } + return 1; +} + +/****************************************************** + * veejay_set_speed() + * set the playback speed (<0 is play backwards) + * + * return value: 1 on success, 0 on error + ******************************************************/ +int veejay_set_speed(veejay_t * info, int speed) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + int len=0; + + + if( speed > MAX_SPEED ) + speed = MAX_SPEED; + if( speed < -(MAX_SPEED)) + speed = -(MAX_SPEED); + + switch (info->uc->playback_mode) + { + + case VJ_PLAYBACK_MODE_PLAIN: + len = info->current_edit_list->total_frames; + if( abs(speed) <= len ) + settings->current_playback_speed = speed; + else + veejay_msg(VEEJAY_MSG_DEBUG, "Speed %d too high to set!", speed); + + break; + case VJ_PLAYBACK_MODE_SAMPLE: + len = sample_get_endFrame(info->uc->sample_id) - sample_get_startFrame(info->uc->sample_id); + if( speed < 0) + { + if ( (-1*len) > speed ) + { + veejay_msg(VEEJAY_MSG_ERROR,"Speed %d too high to set!",speed); + return 1; + } + } + else + { + if(speed >= 0) + { + if( len < speed ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Speed %d too high to set",speed); + return 1; + } + } + } + if(sample_set_speed(info->uc->sample_id, speed) != -1) + settings->current_playback_speed = speed; + break; + + case VJ_PLAYBACK_MODE_TAG: + + settings->current_playback_speed = 1; + break; + default: + veejay_msg(VEEJAY_MSG_ERROR, "Unknown playback mode"); + break; + } + + + return 1; +} + + +/****************************************************** + * veejay_increase_frame() + * increase (or decrease) a num of frames + * + * return value: 1 on succes, 0 if we had to change state + ******************************************************/ +int veejay_increase_frame(veejay_t * info, long num) +{ + + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + if( info->uc->playback_mode == VJ_PLAYBACK_MODE_PLAIN) + { + if(settings->current_frame_num < settings->min_frame_num) return 0; + if(settings->current_frame_num > settings->max_frame_num) return 0; + } + else if (info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE) + { + if ((settings->current_frame_num + num) <= + sample_get_startFrame(info->uc->sample_id)) return 0; + if((settings->current_frame_num + num) >= + sample_get_endFrame(info->uc->sample_id)) return 0; + + } + + settings->current_frame_num += num; + + return 1; +} + + +/****************************************************** + * veejay_free() + * free() the struct + * + * return value: 1 on succes, 0 on error + ******************************************************/ +int veejay_free(veejay_t * info) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + veejay_reap_messages(); + + vj_event_stop(); + + vj_effect_shutdown(); + + vj_tag_free(); + vj_el_free(info->current_edit_list); + vj_avcodec_free(); + + vj_el_deinit(); + + sample_free(); + +// vj_tag_free(); + + if( info->settings->composite ) + composite_destroy( info->composite ); + if( info->settings->action_scheduler.state ) + { + if(info->settings->action_scheduler.sl ) + free(info->settings->action_scheduler.sl ); + info->settings->action_scheduler.state = 0; + } + +// if( info->plugin_frame) vj_perform_free_plugin_frame(info->plugin_frame); +// if( info->plugin_frame_info) free(info->plugin_frame_info); + if( info->effect_frame1) free(info->effect_frame1); + if( info->effect_frame_info) free(info->effect_frame_info); + if( info->effect_frame2) free(info->effect_frame2); + if( info->effect_info) free( info->effect_info ); + if( info->dummy ) free(info->dummy ); +#ifdef HAVE_SDL + free(info->sdl); +#endif + free( info->seq->samples ); + free( info->seq ); + + free(info->status_msg); + free(info->status_what); + free(info->homedir); + free(info->uc); + if(info->cpumask) free(info->cpumask); + if(info->mask) free(info->mask); + if(info->rlinks) free(info->rlinks); + free(settings); + free(info); + return 1; +} + +/****************************************************** + * veejay_busy() + * Wait until playback is finished + ******************************************************/ + +void veejay_busy(veejay_t * info) +{ + pthread_join( ((video_playback_setup*)(info->settings))->playback_thread, NULL ); +} + +void veejay_quit(veejay_t * info) +{ + vj_lock(info); + veejay_change_state(info, LAVPLAY_STATE_STOP); + vj_unlock(info); +} + + + +/****************************************************** + * veejay_set_frame() + * set the current framenum + * + * return value: 1 on success, 0 if we had to change state + ******************************************************/ +int veejay_set_frame(veejay_t * info, long framenum) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + if(framenum < settings->min_frame_num) + framenum = settings->min_frame_num; + + if( framenum > settings->max_frame_num ) + framenum = settings->max_frame_num; + + if(info->uc->playback_mode==VJ_PLAYBACK_MODE_SAMPLE) + { + int start,end,loop,speed; + sample_get_short_info(info->uc->sample_id,&start,&end,&loop,&speed); + if(framenum < start) + framenum = start; + if(framenum > end) + framenum = end; + if(framenum == start || framenum == end ) + sample_set_framedups(info->uc->sample_id,0); + } + else if( info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) + { + if( framenum > settings->max_frame_num ) + framenum = settings->max_frame_num; + } + + settings->current_frame_num = framenum; + + return 1; +} + +int veejay_composite_active( veejay_t *info ) +{ + return info->settings->composite; +} + +void veejay_auto_loop(veejay_t *info) +{ + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_PLAIN) + { + char sam[32]; + sprintf(sam, "%03d:0 -1;", VIMS_SAMPLE_NEW); + vj_event_parse_msg(info, sam,strlen(sam)); + sprintf(sam, "%03d:-1;", VIMS_SAMPLE_SELECT); + vj_event_parse_msg(info,sam,strlen(sam)); + } +} +/****************************************************** + * veejay_init() + * check the given settings and initialize almost + * everything + * return value: 0 on success, -1 on error + ******************************************************/ +void veejay_set_framerate( veejay_t *info , float fps ) +{ + video_playback_setup *settings = (video_playback_setup*) info->settings; + settings->spvf = 1.0 / fps; + settings->msec_per_frame = 1000 / settings->spvf; + if (info->current_edit_list->has_audio && (info->audio==AUDIO_PLAY || info->audio==AUDIO_RENDER)) + settings->spas = 1.0 / (double) info->current_edit_list->audio_rate; + else + settings->spas = 0; + + settings->usec_per_frame = (int)(1000000.0 / fps); +} + + +int veejay_init_editlist(veejay_t * info) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + editlist *el = info->edit_list; + + /* Set min/max options so that it runs like it should */ + settings->min_frame_num = 1; +// settings->max_frame_num = el->video_frames - 1; + settings->max_frame_num = el->total_frames; + settings->current_frame_num = settings->min_frame_num; + settings->previous_frame_num = 1; + settings->spvf = 1.0 / el->video_fps; + settings->msec_per_frame = 1000 / settings->spvf; + + /* Seconds per audio sample: */ + + if( !el->has_audio ) + veejay_msg(VEEJAY_MSG_DEBUG, "EditList has no audio"); + + if (el->has_audio && info->audio==AUDIO_PLAY) + { + settings->spas = 1.0 / (double) el->audio_rate; + } + else + { + settings->spas = 0.; + } + veejay_msg(VEEJAY_MSG_DEBUG, "1.0/Seconds per video Frame = %4.4f", 1.0 / settings->spvf); + veejay_msg(VEEJAY_MSG_DEBUG, "1.0/%ld = %g Seconds per audio Frame", el->audio_rate, settings->spas ); + + vj_el_set_image_output_size( el, info->dummy->width, info->dummy->height, + info->dummy->fps, info->pixel_format ); + + return 0; +} + +static int veejay_stop_playing_sample( veejay_t *info, int new_sample_id ) +{ + if(!sample_stop_playing( info->uc->sample_id, new_sample_id ) ) + { + veejay_msg(0, "Error while stopping sample %d", new_sample_id ); + return 0; + } + if( info->composite ) { + if( info->settings->composite == 2 ) { + info->settings->composite = 1; // back to top + } + } + + sample_chain_free( info->uc->sample_id ); + int n; + for( n = 0; n < 3 ; n ++ ) { + if(info->settings->fxrow[n] ) { + vj_effect_deactivate( info->settings->fxrow[n] ); + info->settings->fxrow[n] = 0; + } + } + + veejay_reset_el_buffer(info); + sample_set_framedups(info->uc->sample_id,0); + return 1; +} +static void veejay_stop_playing_stream( veejay_t *info, int new_stream_id ) +{ + vj_tag_disable( info->uc->sample_id ); + if( info->composite ) { + if( info->settings->composite == 2 ) { + info->settings->composite = 1; + } + } + + vj_tag_chain_free( info->uc->sample_id ); + int n; + for( n = 0; n < 3 ; n ++ ) { + if(info->settings->fxrow[n] ) { + vj_effect_deactivate( info->settings->fxrow[n] ); + info->settings->fxrow[n] = 0; + } + } + +} +static int veejay_start_playing_sample( veejay_t *info, int sample_id ) +{ + int looptype,speed,start,end; + video_playback_setup *settings = info->settings; + + editlist *E = sample_get_editlist( sample_id ); +#ifdef STRICT_CHECKING + assert( E != NULL ); +#endif + info->current_edit_list = E; + veejay_reset_el_buffer(info); + + sample_start_playing( sample_id, info->no_caching ); + int tmp = sample_chain_malloc( sample_id ); + + sample_get_short_info( sample_id , &start,&end,&looptype,&speed); + + settings->min_frame_num = 0; + settings->max_frame_num = sample_video_length( sample_id ); + + sample_reset_loopcount( sample_id ); + +#ifdef HAVE_FREETYPE + if(info->font && info->uc->sample_id != sample_id) + { + void *dict = sample_get_dict( sample_id ); + vj_font_set_dict( info->font, dict ); + vj_font_prepare( info->font,start,end ); + + veejay_msg(VEEJAY_MSG_DEBUG, "Subtitling sample %d: %ld - %ld", sample_id, + start, end ); + + } +#endif + if(info->composite ) + { + int cur_composite = info->settings->composite; + info->settings->composite = sample_load_composite_config( info->composite , sample_id ); + void *cur = sample_get_composite_view(sample_id); + switch(info->settings->composite) { + case 1: + case 2: +#ifdef STRICT_CHECKING + assert( cur != NULL ); +#endif + composite_set_backing(info->composite,cur); + veejay_msg(VEEJAY_MSG_INFO, "Using perspective transform for this Sample"); + break; + case 0: + info->settings->composite = 2; //cur_composite; + break; + } + } + + + info->uc->sample_id = sample_id; + info->last_sample_id = sample_id; + + info->sfd = sample_get_framedup(sample_id); + + info->uc->render_changed = 1; /* different render list */ + + sample_reset_offset( sample_id ); /* reset mixing offsets */ + + + if( info->settings->sample_restart ) { + veejay_set_frame(info, start); + veejay_set_speed(info, speed); + veejay_msg(VEEJAY_MSG_INFO, "Playing sample %d (FX=%x, Sl=%d, Speed=%d, Start=%d, Loop=%d)", + sample_id, tmp,info->sfd, speed, start, looptype ); + } else { + veejay_msg(VEEJAY_MSG_INFO, "Playing sample %d (FX=%x, Sl=%d, Speed=%d, Start=%d, Loop=%d, Continue=%ld)", + sample_id,tmp,info->sfd,speed,start,looptype,info->settings->current_frame_num ); + } + return 1; +} + +static int veejay_start_playing_stream(veejay_t *info, int stream_id ) +{ + video_playback_setup *settings = info->settings; + + if(vj_tag_enable( stream_id ) <= 0 ) + { + veejay_msg(0, "Unable to activate stream ?"); + return 0; + } + + vj_tag_set_active( stream_id, 1 ); + + int tmp = vj_tag_chain_malloc( stream_id); + + info->uc->render_changed = 1; + settings->min_frame_num = 1; + settings->max_frame_num = vj_tag_get_n_frames( stream_id ); + +#ifdef HAVE_FREETYPE + if(info->font ) + { + void *dict = vj_tag_get_dict( stream_id ); + vj_font_set_dict( info->font, dict ); + + vj_font_prepare( info->font, settings->min_frame_num, + settings->max_frame_num ); + + } +#endif + info->last_tag_id = stream_id; + info->uc->sample_id = stream_id; + if(info->composite ) + { + int cur_composite = info->settings->composite; + info->settings->composite = vj_tag_load_composite_config( info->composite , stream_id ); + void *cur =vj_tag_get_composite_view(stream_id); + switch(info->settings->composite) { + case 1: + case 2: +#ifdef STRICT_CHECKING + assert( cur != NULL ); +#endif + composite_set_backing(info->composite,cur); + veejay_msg(VEEJAY_MSG_INFO, "Using perspective transform for this Stream"); + break; + case 0: info->settings->composite = 2; break; + } + } + + veejay_msg(VEEJAY_MSG_INFO,"Playing stream %d (FX=%x) (Ff=%d)", stream_id, tmp, + settings->max_frame_num ); + + info->current_edit_list = info->edit_list; + + veejay_reset_el_buffer(info); + + return 1; +} + +void veejay_change_playback_mode( veejay_t *info, int new_pm, int sample_id ) +{ + //@ check safity of samples + if( new_pm == VJ_PLAYBACK_MODE_SAMPLE ) { + if(!sample_exists(sample_id)) { + veejay_msg(0,"Sample %d does not exist!"); + return; + } + } else if (new_pm == VJ_PLAYBACK_MODE_TAG ) { + if(!vj_tag_exists(sample_id)) { + veejay_msg(0,"Stream %d does not exist!"); + return; + } + } else if ( new_pm == VJ_PLAYBACK_MODE_PLAIN ) { + if( info->edit_list->video_frames < 1 ) { + veejay_msg( 0, "No video frames in EDL!"); + return; + } + } + + if( info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) + { + int cur_id = info->uc->sample_id; + if( cur_id == sample_id && new_pm == VJ_PLAYBACK_MODE_SAMPLE ) + { + int start = sample_get_startFrame( cur_id ); + veejay_set_frame(info,start); + veejay_msg(VEEJAY_MSG_INFO, "Sample %d starts playing from frame %d",sample_id,start); + return; + } + else + { + veejay_stop_playing_sample(info, cur_id ); + } + } + if( info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) + { + int cur_id = info->uc->sample_id; + if( cur_id == sample_id && new_pm == VJ_PLAYBACK_MODE_TAG ) + { + veejay_msg(0, "Already playing stream %d", cur_id ); + return; + } + else + { + veejay_stop_playing_stream(info, cur_id ); + } + } + + if(new_pm == VJ_PLAYBACK_MODE_PLAIN ) + { + if(info->uc->playback_mode==VJ_PLAYBACK_MODE_TAG) + veejay_stop_playing_stream( info , info->uc->sample_id); + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) + veejay_stop_playing_sample( info, info->uc->sample_id ); + info->uc->playback_mode = new_pm; + info->current_edit_list = info->edit_list; +#ifdef STRICT_CHECKING + assert(info->current_edit_list != NULL ); +#endif + video_playback_setup *settings = info->settings; + settings->min_frame_num = 1; + settings->max_frame_num = info->edit_list->total_frames; + veejay_msg(VEEJAY_MSG_INFO, "Playing plain video, frames %d - %d", + (int)settings->min_frame_num, (int)settings->max_frame_num ); + + } + if(new_pm == VJ_PLAYBACK_MODE_TAG) + { + info->uc->playback_mode = new_pm; + veejay_start_playing_stream(info,sample_id); + } + if(new_pm == VJ_PLAYBACK_MODE_SAMPLE) + { + info->uc->playback_mode = new_pm; + veejay_start_playing_sample(info,sample_id ); + } +} + +void veejay_set_sample_f(veejay_t *info, int sample_id, int offset ) +{ + if ( info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG) + { + veejay_start_playing_stream(info,sample_id ); + } + else if( info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE) + { + if( info->uc->sample_id == sample_id ) + { + int start = sample_get_startFrame( info->uc->sample_id ); + veejay_set_frame(info,start+offset); + veejay_msg(VEEJAY_MSG_INFO, "Sample %d starts playing from frame %d",sample_id,start); + } + else + { + veejay_start_playing_sample(info,sample_id ); + veejay_set_frame( info, sample_get_startFrame(sample_id)+offset ); + } + } +} + +void veejay_set_sample(veejay_t * info, int sampleid) +{ + if ( info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG) + { + veejay_start_playing_stream(info,sampleid ); + } + else if( info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE) + { + if( info->uc->sample_id == sampleid ) + { + int start = sample_get_startFrame( info->uc->sample_id ); + veejay_set_frame(info,start); + veejay_msg(VEEJAY_MSG_INFO, "Sample %d starts playing from frame %d",sampleid,start); + } + else + veejay_start_playing_sample(info,sampleid ); + } +} + +/****************************************************** + * veejay_create_sample + * create a new sample + * return value: 1 on success, -1 on error + ******************************************************/ +int veejay_create_tag(veejay_t * info, int type, char *filename, + int index, int palette, int channel) +{ + + if( type == VJ_TAG_TYPE_NET || type == VJ_TAG_TYPE_MCAST ) { + if( (filename != NULL) && ((strcasecmp( filename, "localhost" ) == 0) || (strcmp( filename, "127.0.0.1" ) == 0)) ) { + if( channel == info->uc->port ) { + veejay_msg(VEEJAY_MSG_ERROR, "It makes no sense to connect to myself (%s - %d)", + filename,channel); + return 0; + } + } + } + + int id = vj_tag_new(type, filename, index, info->edit_list, info->pixel_format, palette, channel,info->settings->composite ); + char descr[200]; + veejay_memset(descr,0,200); + vj_tag_get_by_type(type,descr); + if(id > 0 ) { + info->nstreams++; + veejay_msg(VEEJAY_MSG_INFO, "New Input Stream '%s' with ID %d created",descr, id ); + return id; + } else { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to create new Input Stream '%s'", descr ); + } + + return 0; +} + +/****************************************************** + * veejay_stop() + * stop playing + * + * return value: 1 on succes, 0 on error + ******************************************************/ + +int veejay_stop(veejay_t * info) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + if (settings->state == LAVPLAY_STATE_STOP) { + if(info->uc->playback_mode==VJ_PLAYBACK_MODE_TAG) { + vj_tag_set_active(info->uc->sample_id,0); + } + } + + veejay_change_state(info, LAVPLAY_STATE_STOP); + + /*pthread_cancel( settings->playback_thread ); */ + pthread_join(settings->playback_thread, NULL); + return 1; +} + +/* stop playing a sample, continue with video */ +void veejay_stop_sampling(veejay_t * info) +{ + info->uc->playback_mode = VJ_PLAYBACK_MODE_PLAIN; + info->uc->sample_id = 0; + info->uc->sample_start = 0; + info->uc->sample_end = 0; + info->current_edit_list = info->edit_list; +#ifdef STRICT_CHECKING + assert(info->edit_list != NULL ); +#endif +} + +/****************************************************** + * veejay_SDL_update() + * when using software playback - there's a new frame + * new frame can enter by body, or be put in info->vb->yuv. + * this will probably change. + * return value: 1 on success, 0 on error + ******************************************************/ +static int veejay_screen_update(veejay_t * info ) +{ + uint8_t *frame[3]; + uint8_t *c_frame[3]; + int i = 0; + int skip_update = 0; + + video_playback_setup *settings = info->settings; + int check_vp = settings->composite; + vj_perform_get_primary_frame(info,frame); + if(check_vp) + { + if( info->video_out == 0 ) { + + if(!vj_sdl_lock( info->sdl[0] ) ) + return 0; + + composite_blit_yuyv( info->composite,frame, vj_sdl_get_yuv_overlay(info->sdl[0]),settings->composite); + if(!vj_sdl_unlock( info->sdl[0]) ) + return 0; + } + if( info->video_out != 4 ) { + skip_update = 1; + } + } + + + +#ifdef HAVE_V4L + if( info->vloopback ) + { + vj_vloopback_fill_buffer( info->vloopback , frame ); + if( vj_vloopback_get_mode( info->vloopback )) + vj_vloopback_write_pipe( info->vloopback ); + } +#endif + + if( info->settings->unicast_frame_sender ) + { + vj_perform_send_primary_frame_s2(info, 0, info->settings->unicast_link_id); + info->settings->unicast_frame_sender = 0; + } + if( info->settings->mcast_frame_sender && info->settings->use_vims_mcast ) + { + vj_perform_send_primary_frame_s2(info, 1, info->uc->current_link); + } + + //@ FIXME: Both pixbuf and jpeg method is broken for screenshot +#ifdef HAVE_JPEG +#ifdef USE_GDK_PIXBUF + if (info->uc->hackme == 1) + { + info->uc->hackme = 0; +#ifdef USE_GDK_PIXBUF + if(!vj_picture_save( info->settings->export_image, frame, + info->video_output_width, info->video_output_height, + get_ffmpeg_pixfmt( info->pixel_format )) ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Unable to write frame %ld to image as '%s'", + info->settings->current_frame_num, info->settings->export_image ); + } +#else +#ifdef HAVE_JPEG + vj_perform_screenshot2(info, frame); + if(info->uc->filename) free(info->uc->filename); +#endif +#endif + } +#endif +#endif + if(skip_update) { + if(info->video_out == 0 ) { + for(i = 0 ; i < MAX_SDL_OUT; i ++ ) + if( info->sdl[i] ) + vj_sdl_flip(info->sdl[i]); + } + /* +#ifdef HAVE_GL + else if (info->video_out == 3 ) { + composite_blit_ycbcr( info->composite, frame, settings->composite, info->gl ); + x_display_push_yvu( info->gl, info->video_output_width,info->video_output_height, + info->pixel_format ); + } +#endif +*/ + return 1; + } + + switch (info->video_out) + { +#ifdef HAVE_SDL + case 0: + for(i = 0 ; i < MAX_SDL_OUT; i ++ ) + if( info->sdl[i] ) + if(!vj_sdl_update_yuv_overlay( info->sdl[i], frame ) ) return 0; + break; +#endif + case 1: +#ifdef HAVE_DIRECTFB + vj_perform_get_primary_frame_420p(info,c_frame); + if (vj_dfb_update_yuv_overlay(info->dfb, c_frame) != 0) + { + return 0; + } +#endif + break; + case 2: +#ifdef HAVE_DIRECTFB +#ifdef HAVE_SDL + for( i = 0; i < MAX_SDL_OUT; i ++ ) + if( info->sdl[i] ) + if(!vj_sdl_update_yuv_overlay( info->sdl[i], frame ) ) + return 0; +#endif + vj_perform_get_primary_frame_420p(info,c_frame); + if (vj_dfb_update_yuv_overlay(info->dfb, c_frame) != 0) + { + return 0; + } +#endif + break; + /* + case 3: +#ifdef HAVE_GL + x_display_push( info->gl, frame , info->current_edit_list->video_width, + info->current_edit_list->video_height, + info->current_edit_list->pixel_format ); +#endif + break;*/ + case 3: + break; + case 4: + if( vj_yuv_put_frame( info->y4m, frame ) == -1 ) { + veejay_msg(0, "Failed to write a frame!"); + veejay_change_state(info,LAVPLAY_STATE_STOP); + + return 0; + + } + break; + default: + veejay_change_state(info,LAVPLAY_STATE_STOP); + return 0; + break; + } + + + return 1; +} + + + + +/****************************************************** + * veejay_mjpeg_software_frame_sync() + * Try to keep in sync with nominal frame rate, + * timestamp frame with actual completion time + * (after any deliberate sleeps etc) + * + * return value: 1 on success, 0 on error + ******************************************************/ + +static void veejay_mjpeg_software_frame_sync(veejay_t * info, + int frame_periods) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + if (info->uc->use_timer ) { + + /* I really *wish* the timer was higher res on x86 Linux... 10mSec + * is a *pain*. Sooo wasteful here... + */ + + struct timeval now; + struct timespec nsecsleep; + + int usec_since_lastframe=0; + + for (;;) { + gettimeofday(&now, 0); + + usec_since_lastframe = + now.tv_usec - settings->lastframe_completion.tv_usec; + //usec_since_lastframe = vj_get_relative_time(); + if (usec_since_lastframe < 0) + usec_since_lastframe += 1000000; + if (now.tv_sec > settings->lastframe_completion.tv_sec + 1) + usec_since_lastframe = 1000000; + + + if (settings->first_frame || + (frame_periods * settings->usec_per_frame - + usec_since_lastframe) < (1000000 / HZ)) + break; + + /* Assume some other process will get a time-slice before + * we do... and hence the worst-case delay of 1/HZ after + * sleep timer expiry will apply. Reasonable since X will + * probably do something... + */ + nsecsleep.tv_nsec = (frame_periods * settings->usec_per_frame - usec_since_lastframe - 1000000 / HZ) * 1000; + nsecsleep.tv_sec = 0; + nanosleep(&nsecsleep, NULL); + } + } + + settings->first_frame = 0; + /* We are done with writing the picture - Now update all surrounding info */ + gettimeofday(&(settings->lastframe_completion), 0); + settings->syncinfo[settings->currently_processed_frame].timestamp = + settings->lastframe_completion; + +} +void veejay_pipe_write_status(veejay_t * info, int link_id) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + int d_len = 0; + int res = 0; + int pm = info->uc->playback_mode; + int total_slots = sample_size()-1; + int tags = vj_tag_true_size() -1; + int cache_used = 0; + if(tags>0) + total_slots+=tags; + if(total_slots < 0) + total_slots = 0; + + int mstatus = vj_event_macro_status(); + + + int curfps = (int) ( 100.0f / settings->spvf ); + + + switch (info->uc->playback_mode) { + case VJ_PLAYBACK_MODE_SAMPLE: + cache_used = sample_cache_used(0); + + if( info->settings->randplayer.mode == + RANDMODE_SAMPLE) + pm = VJ_PLAYBACK_MODE_PATTERN; + if( sample_chain_sprint_status + (info->uc->sample_id,cache_used,info->seq->active,info->seq->current,info->real_fps,settings->current_frame_num, pm, total_slots,info->seq->rec_id,curfps,settings->cycle_count[0],settings->cycle_count[1],mstatus,info->status_what ) != 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Fatal error, tried to collect properties of invalid sample"); +#ifdef STRICT_CHECKING + assert(0); +#else + veejay_change_state( info, LAVPLAY_STATE_STOP ); +#endif + } + break; + case VJ_PLAYBACK_MODE_PLAIN: + veejay_sprintf(info->status_what,1024, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %ld %d %d %d %d %d", + info->real_fps, + settings->current_frame_num, + info->uc->playback_mode, + 0, + 0, + settings->min_frame_num, + settings->max_frame_num, + settings->current_playback_speed, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + total_slots, + cache_used, + curfps, + settings->cycle_count[0], + settings->cycle_count[1], + 0, + 0, + 0, + 0, + mstatus ); + break; + case VJ_PLAYBACK_MODE_TAG: + if( vj_tag_sprint_status( info->uc->sample_id,cache_used,info->seq->active,info->seq->current, info->real_fps, + settings->current_frame_num, info->uc->playback_mode,total_slots,curfps,settings->cycle_count[0],settings->cycle_count[1],mstatus, info->status_what ) != 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid status!"); + } + break; + } + + d_len = strlen(info->status_what); + snprintf(info->status_msg,MESSAGE_SIZE, "V%03dS", d_len ); + + res = vj_server_send(info->vjs[VEEJAY_PORT_STA],link_id, info->status_msg, 5); + if( res <= 0) + { /* close command socket */ + veejay_msg(VEEJAY_MSG_DEBUG ,"Error sending status message , closing connection(s)"); + _vj_server_del_client(info->vjs[VEEJAY_PORT_CMD], link_id ); + _vj_server_del_client(info->vjs[VEEJAY_PORT_STA], link_id ); + } + res = vj_server_send(info->vjs[VEEJAY_PORT_STA], link_id, info->status_what, d_len ); + if( res <= 0) + { /* close command socket */ + veejay_msg(VEEJAY_MSG_DEBUG ,"Error sending status message , closing connection(s)"); + _vj_server_del_client(info->vjs[VEEJAY_PORT_CMD], link_id ); + _vj_server_del_client(info->vjs[VEEJAY_PORT_STA], link_id ); + } + + if (info->uc->chain_changed == 1) + info->uc->chain_changed = 0; + if (info->uc->render_changed == 1) + info->uc->render_changed = 0; +} +static char *veejay_concat_paths(char *path, char *suffix) +{ + int n = strlen(path) + strlen(suffix) + 2; + char *str = vj_calloc( n * sizeof(char)); + sprintf(str, "%s/%s", path,suffix); + return str; +} + +static int veejay_is_dir(char *path) +{ + struct stat s; + if( stat( path, &s ) == -1 ) + { + veejay_msg(0, "%s (%s)", strerror(errno),path); + return 0; + } + if( !S_ISDIR( s.st_mode )) { + veejay_msg(0, "%s is not a valid path."); + return 0; + } + return 1; +} +static int veejay_valid_homedir(char *path) +{ + char *recovery_dir = veejay_concat_paths( path, "recovery" ); + char *theme_dir = veejay_concat_paths( path, "theme" ); + int sum = veejay_is_dir( recovery_dir ); + sum += veejay_is_dir( theme_dir ); + sum += veejay_is_dir( path ); + free(theme_dir); + free(recovery_dir); + if( sum == 3 ) + return 1; + return 0; +} +static int veejay_create_homedir(char *path) +{ + if( mkdir(path,0700 ) == -1 ) + { + if( errno != EEXIST ) + { + veejay_msg(0, "Unable to create %s - No veejay home setup (error=%s)", strerror(errno)); + return 0; + } + } + + char *recovery_dir = veejay_concat_paths( path, "recovery" ); + if( mkdir(recovery_dir,0700) == -1 ) { + if( errno != EEXIST ) + { + veejay_msg(0, "%s", strerror(errno)); + free(recovery_dir); + return 0; + } + } + free(recovery_dir); + + char *theme_dir = veejay_concat_paths( path, "theme" ); + if( mkdir(theme_dir,0700) == -1 ) { + if( errno != EEXIST ) + { + veejay_msg(0, "%s", strerror(errno)); + free(theme_dir); + return 0; + } + } + free(theme_dir); + + char *font_dir = veejay_concat_paths( path, "fonts" ); + if( mkdir(font_dir,0700) == -1 ) { + if( errno != EEXIST ) + { + veejay_msg(0, "%s", strerror(errno)); + free(font_dir); + return 0; + } + } + free(font_dir); +// on dynebolic, we copy mplayer's font to veejay's homedir + system("cp /usr/share/mplayer/font/arial.ttf ~/.veejay/fonts"); + + veejay_msg(VEEJAY_MSG_INFO, "veejay home is setup"); + return 1; +} +void veejay_check_homedir(void *arg) +{ + veejay_t *info = (veejay_t *) arg; + char path[1024]; + char tmp[1024]; + struct stat s; + char *home = getenv("HOME"); + if(!home) + { + veejay_msg(VEEJAY_MSG_ERROR, + "HOME environment variable not set."); + return; + } + sprintf(path, "%s/.veejay", home ); + info->homedir = strndup( path, 1024 ); + + + if( veejay_valid_homedir(path) == 0) + { + if( veejay_create_homedir(path) == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Can't create %s",path); + return; + } + + } + + sprintf(tmp, "%s/plugins.cfg", path ); + struct statfs ts; + if( statfs( tmp, &ts ) != 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING,"\tNo plugins.cfg found (see DOC/HowtoPlugins)"); + } + sprintf(tmp, "%s/viewport.cfg", path); + memset( &ts,0,sizeof(struct statfs)); + if( statfs( tmp, &ts ) != 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING,"\tNo viewport.cfg found (start veejay with -D -w -h and press CTRL-V to setup viewport)"); + } + +} + +/****************************************************** + * veejay_mjpeg_playback_thread() + * the main (software) video playback thread + * + * return value: 1 on success, 0 on error + ******************************************************/ +void veejay_handle_signal(void *arg, int sig) +{ + veejay_t *info = (veejay_t *) arg; + if (sig == SIGINT || sig == SIGQUIT ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Veejay interrupted by user. Bye!"); + veejay_change_state(info, LAVPLAY_STATE_STOP); + } + else + { + if( sig == SIGPIPE || sig == SIGSEGV || sig == SIGBUS || sig == SIGPWR || sig == SIGABRT || sig == SIGFPE ) + { + if(info->homedir) + veejay_change_state_save(info,LAVPLAY_STATE_STOP); + else + veejay_change_state( info, LAVPLAY_STATE_STOP ); + signal( sig, SIG_DFL ); + } + } +} + + +static void veejay_handle_callbacks(veejay_t *info) { + + /* check for OSC events */ + vj_osc_get_packet(info->osc); + + /* update network */ + vj_event_update_remote( (void*)info ); +} +void vj_lock(veejay_t *info) +{ + video_playback_setup *settings = info->settings; + pthread_mutex_lock(&(settings->valid_mutex)); +} +void vj_unlock(veejay_t *info) +{ + video_playback_setup *settings = info->settings; + pthread_mutex_unlock(&(settings->valid_mutex)); +} +static void donothing2(int sig) +{ + veejay_msg(VEEJAY_MSG_WARNING,"Catched signal %x (ignored)",sig ); +} + +static void veejay_event_handle(veejay_t *info) +{ + veejay_handle_callbacks(info); +#ifdef HAVE_SDL + if( info->video_out == 0 || info->video_out == 2) + { + SDL_Event event; + int ctrl_pressed = 0; + int shift_pressed = 0; + int alt_pressed = 0; + int mouse_x=0,mouse_y=0,but=0; + int res = 0; + while(SDL_PollEvent(&event) == 1) + { + SDL_KeyboardEvent *k = &event.key; + int mod = SDL_GetModState(); + if( event.type == SDL_KEYDOWN || event.type == SDL_MOUSEBUTTONDOWN) + { + res = vj_event_single_fire( (void*) info, event, 0); + } + if( event.type == SDL_MOUSEMOTION ) + { + mouse_x = event.button.x; + mouse_y = event.button.y; + } + + if( event.type == SDL_MOUSEBUTTONDOWN ) + { + mouse_x = event.button.x; + mouse_y = event.button.y; + shift_pressed = (mod & KMOD_LSHIFT ); + alt_pressed = (mod & KMOD_RSHIFT ); + if( mod == 0x1080 || mod == 0x1040 || (mod & KMOD_LCTRL) || (mod & KMOD_RCTRL) ) + ctrl_pressed = 1; + else + ctrl_pressed = 0; + + SDL_MouseButtonEvent *mev = &(event.button); + + if( mev->button == SDL_BUTTON_LEFT && shift_pressed) + { + but = 6; + info->uc->mouse[3] = 1; + } else if( mev->button == SDL_BUTTON_LEFT && ctrl_pressed ) + { + but = 10; + info->uc->mouse[3] = 4; + } + if (mev->button == SDL_BUTTON_MIDDLE && shift_pressed ) + { + but = 7; + info->uc->mouse[3] = 2; + } + if( mev->button == SDL_BUTTON_LEFT && alt_pressed ) + { + but = 11; + info->uc->mouse[3] = 11; + } + } + + if( event.type == SDL_MOUSEBUTTONUP ) + { + SDL_MouseButtonEvent *mev = &(event.button); + alt_pressed = (mod & KMOD_RSHIFT ); + shift_pressed = (mod & KMOD_LSHIFT ); + if( mod == 0x1080 || mod == 0x1040 || (mod & KMOD_LCTRL) || (mod & KMOD_RCTRL) ) + ctrl_pressed = 1; + else + ctrl_pressed = 0; + + if( mev->button == SDL_BUTTON_LEFT ) + { + if( info->uc->mouse[3] == 1 ) + { + but = 6; + info->uc->mouse[3] = 0; + } + else if (info->uc->mouse[3] == 4 ) + { + but = 10; + info->uc->mouse[3] = 0; + } else if (info->uc->mouse[3] == 0 ) + { + but = 1; + } else if ( info->uc->mouse[3] == 11 ) + { + but = 12; + info->uc->mouse[3] = 0; + } + } + else if (mev->button == SDL_BUTTON_RIGHT ) { + but = 2; + } + else if (mev->button == SDL_BUTTON_MIDDLE ) { + if( info->uc->mouse[3] == 2 ) + { but = 0; + info->uc->mouse[3] = 0; + } + else {if( info->uc->mouse[3] == 0 ) + but = 3;} + } + else if ((mev->button == SDL_BUTTON_WHEELUP ) && !alt_pressed && !ctrl_pressed) + { + but = 4; + } + else if ((mev->button == SDL_BUTTON_WHEELDOWN ) && !alt_pressed && !ctrl_pressed) + { + but = 5; + } + else if ((mev->button == SDL_BUTTON_WHEELUP) && alt_pressed && !ctrl_pressed ) + { + but = 13; + } + else if ((mev->button == SDL_BUTTON_WHEELDOWN) && alt_pressed && !ctrl_pressed ) + { + but = 14; + } + else if (mev->button == SDL_BUTTON_WHEELUP ) + { + but = 15; + } + else if (mev->button == SDL_BUTTON_WHEELDOWN ) + { + but = 16; + } + mouse_x = event.button.x; + mouse_y = event.button.y; + } + + } + info->uc->mouse[0] = mouse_x; + info->uc->mouse[1] = mouse_y; + info->uc->mouse[2] = but; + } +#endif + /* +#ifdef HAVE_GL + if(info->video_out == 3 ) + { + x_display_mouse_grab( info->gl, info->uc->mouse[0],info->uc->mouse[1],info->uc->mouse[2], + info->uc->mouse[3] ); + + x_display_event( info->gl, info->current_edit_list->video_width, info->current_edit_list->video_hei,,ght ); + + x_display_mouse_update( info->gl, &(info->uc->mouse[0]), &(info->uc->mouse[1]), &(info->uc->mouse[2]), + &(info->uc->mouse[3])); + } +#endif + */ + +} + +static void *veejay_geo_stat_thread(void *arg) +{ + veejay_t *info = (veejay_t *) arg; + /* Allow easy shutting down by other processes... */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + vj_server_geo_stats(); + + return NULL; +} + + +static void *veejay_mjpeg_playback_thread(void *arg) +{ + veejay_t *info = (veejay_t *) arg; + video_playback_setup *settings = + (video_playback_setup *) info->settings; + /* Allow easy shutting down by other processes... */ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + /* schedule FIFO */ + + veejay_schedule_fifo( info, getpid()); + + vj_get_relative_time(); + + vj_osc_set_veejay_t(info); + vj_tag_set_veejay_t(info); + +#ifdef HAVE_SDL + if( info->settings->repeat_delay > 0 && info->settings->repeat_interval ) { + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + } +#endif + while (settings->state != LAVPLAY_STATE_STOP) { + pthread_mutex_lock(&(settings->valid_mutex)); + while (settings->valid[settings->currently_processed_frame] == 0) { +#ifdef STRICT_CHECKING + // veejay_msg(VEEJAY_MSG_DEBUG, "Playback thread: sleeping for new frames (waiting for frame %d)", + // settings->currently_processed_frame); +#endif + pthread_cond_wait(& + (settings-> + buffer_filled[settings-> + currently_processed_frame]), + &(settings->valid_mutex)); + if (settings->state == LAVPLAY_STATE_STOP) { + // Ok, we shall exit, that's the reason for the wakeup + veejay_msg(VEEJAY_MSG_DEBUG,"Veejay was told to exit"); + pthread_mutex_unlock(&(settings->valid_mutex)); + pthread_exit(NULL); + return NULL; + } + } + pthread_mutex_unlock(&(settings->valid_mutex)); + + if( settings->currently_processed_entry != settings->buffer_entry[settings->currently_processed_frame] && + !veejay_screen_update(info) ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Error playing frame %d", settings->current_frame_num); + } + settings->currently_processed_entry = + settings->buffer_entry[settings->currently_processed_frame]; + + // timestamp frame after sync + + veejay_mjpeg_software_frame_sync(info, + settings->valid[settings-> + currently_processed_frame]); + settings->syncinfo[settings->currently_processed_frame].frame = + settings->currently_processed_frame; + + pthread_mutex_lock(&(settings->valid_mutex)); + settings->valid[settings->currently_processed_frame] = 0; + pthread_mutex_unlock(&(settings->valid_mutex)); + + pthread_cond_broadcast(& + (settings-> + buffer_done[settings-> + currently_processed_frame])); + + settings->currently_processed_frame = + (settings->currently_processed_frame + 1) % 1; + } + veejay_msg( VEEJAY_MSG_INFO, "Playback thread: was told to exit"); + pthread_exit(NULL); + + return NULL; +} + + +char *veejay_title(veejay_t *info) +{ + char tmp[64]; + sprintf(tmp, "Veejay %s on port %d in %dx%d@%2.2f", VERSION, + info->uc->port, info->video_output_width,info->video_output_height,info->edit_list->video_fps ); + return strdup(tmp); +} + + +int veejay_open(veejay_t * info) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + int i; + veejay_msg(VEEJAY_MSG_DEBUG, + "Initializing the threading system"); + + memset( &(settings->lastframe_completion), 0, sizeof(struct timeval)); + + pthread_mutex_init(&(settings->valid_mutex), NULL); + pthread_mutex_init(&(settings->syncinfo_mutex), NULL); + /* Invalidate all buffers, and initialize the conditions */ + for(i = 0; i < QUEUE_LEN ;i ++ ) { + settings->valid[i] = 0; + settings->buffer_entry[i] = 0; + pthread_cond_init(&(settings->buffer_filled[i]), NULL); + pthread_cond_init(&(settings->buffer_done[i]), NULL); + + veejay_memset( &(settings->syncinfo[i]), 0, sizeof(struct mjpeg_sync)); + } + + /* Now do the thread magic */ + settings->currently_processed_frame = 0; + settings->currently_processed_entry = -1; + + veejay_msg(VEEJAY_MSG_DEBUG,"Starting software playback thread"); + + + if( pthread_create(&(settings->software_playback_thread), NULL, + veejay_mjpeg_playback_thread, (void *) info)) { + veejay_msg(VEEJAY_MSG_ERROR, + "Could not create software playback thread"); + return 0; + + + } + //@ collect geo statistics; how many times was veejay started from which geographical location + //@ - do we do internationalization + //@ - do we do veejay 2.0 + if( pthread_create( &(settings->geo_stat), NULL, veejay_geo_stat_thread, (void*) info ) ) { + veejay_msg(VEEJAY_MSG_ERROR, "Could not start geo stat thread."); + return 0; + } + return 1; +} + +static int veejay_mjpeg_get_params(veejay_t * info, + struct mjpeg_params *bp) +{ + int i; + /* Set some necessary params */ + bp->decimation = 1; + bp->quality = 50; /* default compression factor 8 */ + bp->odd_even = 1; + bp->APPn = 0; + bp->APP_len = 0; /* No APPn marker */ + for (i = 0; i < 60; i++) + bp->APP_data[i] = 0; + bp->COM_len = 0; /* No COM marker */ + for (i = 0; i < 60; i++) + bp->COM_data[i] = 0; + bp->VFIFO_FB = 1; + veejay_memset( bp->reserved, 0, sizeof(bp->reserved)); + + return 1; +} + + +static int veejay_mjpeg_set_playback_rate(veejay_t * info, + double video_fps, int norm) +{ + int norm_usec_per_frame = 0; + int target_usec_per_frame; + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + switch (norm) { + case VIDEO_MODE_PAL: + case VIDEO_MODE_SECAM: + norm_usec_per_frame = 1000000 / 25; /* 25Hz */ + break; + case VIDEO_MODE_NTSC: + norm_usec_per_frame = 1001000 / 30; /* 30ish Hz */ + break; + default: + veejay_msg(VEEJAY_MSG_WARNING, + "Unknown video norm! Use PAL , SECAM or NTSC"); + norm_usec_per_frame = 1000000 / (long) video_fps; + break; + } + + if (video_fps != 0.0) + target_usec_per_frame = (int) (1000000.0 / video_fps); + else + target_usec_per_frame = norm_usec_per_frame; + + settings->usec_per_frame = target_usec_per_frame; + + return 1; +} + +/****************************************************** + * veejay_mjpeg_queue_buf() + * queue a buffer + * + * return value: 1 on success, 0 on error + ******************************************************/ + +static void veejay_mjpeg_queue_buf(veejay_t * info,int frame, int frame_periods) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + /* mark this buffer as playable and tell the software playback thread to wake up if it sleeps */ + pthread_mutex_lock(&(settings->valid_mutex)); + settings->valid[frame] = frame_periods; + pthread_cond_broadcast(&(settings->buffer_filled[frame])); + pthread_mutex_unlock(&(settings->valid_mutex)); +} + + +/****************************************************** + * veejay_mjpeg_sync_buf() + * sync on a buffer + * + * return value: 1 on success, 0 on error + ******************************************************/ + +static int veejay_mjpeg_sync_buf(veejay_t * info, struct mjpeg_sync *bs) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + /* Wait until this buffer has been played */ + + pthread_mutex_lock(&(settings->valid_mutex)); + while (settings->valid[settings->currently_synced_frame] != 0) { + pthread_cond_wait(& + (settings-> + buffer_done[settings->currently_synced_frame]), + &(settings->valid_mutex)); + } + pthread_mutex_unlock(&(settings->valid_mutex)); + veejay_memcpy(bs, &(settings->syncinfo[settings->currently_synced_frame]),sizeof(struct mjpeg_sync)); + + settings->currently_synced_frame = + (settings->currently_synced_frame + 1) % QUEUE_LEN; + + return 1; +} +/****************************************************** + * veejay_mjpeg_close() + * close down + * + * return value: 1 on success, 0 on error + ******************************************************/ + + int veejay_close(veejay_t * info) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + veejay_msg(VEEJAY_MSG_DEBUG, + "Closing down the threading system "); + + pthread_cancel(settings->software_playback_thread); + if (pthread_join(settings->software_playback_thread, NULL)) { + veejay_msg(VEEJAY_MSG_ERROR, + "Failure deleting software playback thread"); + return 0; + } + + return 1; +} + +/****************************************************** + * veejay_init() + * check the given settings and initialize everything + * + * return value: 0 on success, -1 on error + ******************************************************/ + + +int veejay_init(veejay_t * info, int x, int y,char *arg, int def_tags) +{ + editlist *el = NULL; + video_playback_setup *settings = info->settings; + + available_diskspace(); + + int id=0; + int mode=0; + int has_config = 0; + + if(info->load_action_file) + { + if(veejay_load_action_file(info, info->action_file[0] )) + { + veejay_msg(VEEJAY_MSG_INFO, "Loaded configuration file %s", info->action_file[0] ); + has_config = 1; + } else { + veejay_msg(VEEJAY_MSG_WARNING, "File %s is not an action file", info->action_file[0]); + } + } + + if(info->video_out<0) + { + veejay_msg(VEEJAY_MSG_ERROR, "No video output driver selected (see man veejay)"); + return -1; + } + // override geometry set in config file + if( info->uc->geox != 0 && info->uc->geoy != 0 ) + { + x = info->uc->geox; + y = info->uc->geoy; + } + + vj_event_init(); + + switch (info->uc->use_timer) + { + case 0: + veejay_msg(VEEJAY_MSG_WARNING, "Not timing audio/video"); + break; + default: + veejay_msg(VEEJAY_MSG_DEBUG, "Using nanosleep timer"); + break; + } +#ifdef STRICT_CHECKING + assert(info->edit_list != NULL ); +#endif + + if (veejay_init_editlist(info) != 0) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Cannot initialize the EditList"); + return -1; + } + + vj_tag_set_veejay_t(info); + + el = info->edit_list; + + + int driver = 1; + char *driver_str = getenv("VEEJAY_CAPTURE_DRIVER"); + if( driver_str != NULL ) { + if( strncasecmp( "unicap",driver_str, 6) == 0 ) + driver = 0; + } + + if (vj_tag_init(el->video_width, el->video_height, info->pixel_format,driver) != 0) { + veejay_msg(VEEJAY_MSG_ERROR, "Error while initializing Stream Manager"); + return -1; + } + + if( info->video_output_width <= 0 || info->video_output_height <= 0 ) { + info->video_output_width = el->video_width; + info->video_output_height = el->video_height; + } + + info->font = vj_font_init( el->video_width, el->video_height, el->video_fps,0 ); + + if(!info->font) { + veejay_msg(VEEJAY_MSG_ERROR, "Error while initializing font system."); + return -1; + } + + + if(info->settings->composite) + { + info->osd = vj_font_single_init( info->video_output_width,info->video_output_height, + el->video_fps ,info->homedir ); + + } + else + { + info->osd = vj_font_single_init( el->video_width, + el->video_height, + el->video_fps, + info->homedir ); + } + + + if(!info->osd) { + veejay_msg(VEEJAY_MSG_ERROR, "Error while initializing font system for OSD."); + return -1; + } + + + sample_init( (el->video_width * el->video_height), info->font ); + + sample_set_project( info->pixel_format, + info->auto_deinterlace, + info->preserve_pathnames, + 0, + el->video_norm ); + + int full_range = veejay_set_yuv_range( info ); + + if(!vj_el_init_422_frame( el, info->effect_frame1)) return 0; + if(!vj_el_init_422_frame( el, info->effect_frame2)) return 0; + info->settings->sample_mode = SSM_422_444; + + veejay_msg(VEEJAY_MSG_DEBUG, "Internal YUV format is 4:2:2 Planar, %d x %d", + el->video_width, + el->video_height); + + if(!vj_perform_init(info)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize Veejay Performer"); + return -1; + } + + + if( info->settings->composite ) + { + int o1 = info->video_output_width * info->video_output_height; + int o2 = el->video_width * el->video_height; + int comp_mode = 2; + if( o2 > o1 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to perform viewport rendering when input resolution is larger then output resolution."); + return -1; + } + + info->composite = composite_init( info->video_output_width, info->video_output_height, + el->video_width, el->video_height, + info->homedir, + info->settings->sample_mode, + yuv_which_scaler(), + info->pixel_format, + &comp_mode ); + if(!info->composite) { + return -1; + } + info->settings->zoom = 0; + info->settings->composite = comp_mode; + } + if(!has_config) { + if(info->video_output_width <= 0 ) { + info->video_output_width = el->video_width; + info->video_output_height = el->video_height; + } + } + + if(!info->bes_width) + info->bes_width = info->video_output_width; + if(!info->bes_height) + info->bes_height = info->video_output_height; + + if(el->has_audio) + { + if (vj_perform_init_audio(info)) + veejay_msg(VEEJAY_MSG_INFO, "Initialized Audio Task"); + else + info->audio = NO_AUDIO; + } + + veejay_msg(VEEJAY_MSG_INFO, + "Initialized %d Image- and Video Effects", vj_effect_max_effects()); + vj_effect_initialize( el->video_width,el->video_height, full_range); + veejay_msg(VEEJAY_MSG_DEBUG, + "BES %d x %d, Video %d x %d , Screen %d x %d", + info->bes_width, + info->bes_height, + el->video_width, + el->video_height, + info->video_output_width, + info->video_output_height); + + if(info->dump) vj_effect_dump(); + + if( info->settings->action_scheduler.sl && info->settings->action_scheduler.state ) + { + + if(sample_readFromFile( info->settings->action_scheduler.sl, + info->composite, + info->seq, info->font, el, &(info->uc->sample_id), &(info->uc->playback_mode) ) ) + veejay_msg(VEEJAY_MSG_INFO, "Loaded sample list %s from actionfile - ", + info->settings->action_scheduler.sl ); + } + + + if( settings->action_scheduler.state ) + { + settings->action_scheduler.state = 0; + } + + int instances = 0; + + char *title = NULL; + + while( (instances < 4 ) && !vj_server_setup(info)) + { + int port = info->uc->port; + int new_port = info->uc->port + 1000; + instances ++; + veejay_msg(VEEJAY_MSG_ERROR,"Port %d in use, trying to start on port %d (%d/%d attempts)", port, new_port , 4 - instances, instances); + info->uc->port = new_port; + } + + if( instances >= 4 ) { + veejay_msg(VEEJAY_MSG_ERROR,"Unable to start network server. Most likely, there is already a veejay running"); + veejay_msg(VEEJAY_MSG_ERROR,"If you want to run multiple veejay's on the same machine, use the '-p/--port'"); + veejay_msg(VEEJAY_MSG_ERROR,"commandline option. For example: $ veejay -p 4490 -d"); + return -1; + } + + /* now setup the output driver */ + switch (info->video_out) + { + /* + case 3: +#ifdef HAVE_GL + veejay_msg(VEEJAY_MSG_INFO, "Using output driver OpenGL"); + info->gl = (void*) x_display_init(info); + x_display_open(info->gl, el->video_width, el->video_height ); +#endif + break; + */ + case 0: + veejay_msg(VEEJAY_MSG_INFO, "Using output driver SDL"); +#ifdef HAVE_SDL + info->sdl[0] = + (vj_sdl *) vj_sdl_allocate( info->video_output_width,info->video_output_height,info->pixel_format); + if( !info->sdl[0] ) + return -1; + + if( x != -1 && y != -1 ) + vj_sdl_set_geometry(info->sdl[0],x,y); + + title = veejay_title( info ); + + if (!vj_sdl_init(info->settings->ncpu, info->sdl[0], info->bes_width, info->bes_height, title,1,info->settings->full_screen)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error initializing SDL"); + free(title); + return -1; + } + free(title); +#endif + break; + case 1: + + veejay_msg(VEEJAY_MSG_INFO, "Using output driver DirectFB"); +#ifdef HAVE_DIRECTFB + info->dfb =(vj_dfb *) vj_dfb_allocate(info->video_output_width,info->video_output_height, + el->video_norm); + if( !info->dfb ) + return -1; + if (vj_dfb_init(info->dfb) != 0) + return -1; +#endif + break; + + + case 2: + veejay_msg(VEEJAY_MSG_INFO, + "Using output driver SDL & DirectFB"); +#ifdef HAVE_SDL + info->sdl[0] = (vj_sdl *) vj_sdl_allocate(info->video_output_width,info->video_output_height, info->pixel_format); + if(!info->sdl[0]) + return -1; + + title = veejay_title(info); + if (!vj_sdl_init(info->settings->ncpu, info->sdl[0], info->bes_width, info->bes_height,title,1,info->settings->full_screen)) { + free(title); + return -1; + } + free(title); +#endif +#ifdef HAVE_DIRECTFB + info->dfb = (vj_dfb *) vj_dfb_allocate( info->video_output_width, info->video_output_height, el->video_norm); + if(!info->dfb) + return -1; + + if (vj_dfb_init(info->dfb) != 0) + return -1; +#endif + break; + + case 3: + veejay_msg(VEEJAY_MSG_INFO, "Entering headless mode (no visual output)"); + break; + + case 4: + veejay_msg(VEEJAY_MSG_INFO, "Entering Y4M streaming mode."); + info->y4m = vj_yuv4mpeg_alloc( el, info->video_output_width,info->video_output_height, info->pixel_format ); + if( vj_yuv_stream_start_write( info->y4m, el, info->y4m_file, Y4M_CHROMA_420JPEG ) == -1 ) { + return -1; + } + break; + + default: + veejay_msg(VEEJAY_MSG_ERROR, "Invalid playback mode. Use -O [012345]"); + return -1; + break; + } + + + if(def_tags && id <= 0) + { + int n = vj_tag_num_devices(); + int default_chan = 1; + char *chanid = getenv("VEEJAY_DEFAULT_CHANNEL"); + if(chanid != NULL ) + default_chan = atoi(chanid); + int nid = veejay_create_tag( info, VJ_TAG_TYPE_V4L, "bogus", info->nstreams, default_chan, (def_tags-1) ); + if( nid> 0) + { + veejay_msg(VEEJAY_MSG_INFO, "Requested capture device available as stream %d", nid ); + } + else + { + return -1; + } + info->uc->playback_mode = VJ_PLAYBACK_MODE_TAG; + info->uc->sample_id = nid; + } + else if( info->uc->file_as_sample && id <= 0 && !has_config) + { + long i,n=el->num_video_files; + for(i = 0; i < n; i ++ ) + { + long start=0,end=2; + if(vj_el_get_file_entry( info->edit_list, &start,&end, i )) + { + editlist *sample_el = veejay_edit_copy_to_new( info,info->edit_list,start,end ); + if(!el) + { + veejay_msg(0, "Unable to start from file, Abort"); + return -1; + } + sample_info *skel = sample_skeleton_new( 0, info->edit_list->total_frames ); + if(skel) + { + skel->edit_list = sample_el; + sample_store(skel); + } + } + } + info->uc->playback_mode = VJ_PLAYBACK_MODE_SAMPLE; + info->uc->sample_id = 1; + } + else if(info->dummy->active && id <= 0) + { + int dummy_id; + /* Use dummy mode, action file could have specified something */ + if( vj_tag_size()-1 <= 0 ) + dummy_id = vj_tag_new( VJ_TAG_TYPE_COLOR, "Solid", -1, el,info->pixel_format,-1,0,0); + else + dummy_id = vj_tag_size()-1; + info->uc->playback_mode = VJ_PLAYBACK_MODE_TAG; + info->uc->sample_id = dummy_id; + } + + /* After we have fired up the audio and video threads system (which + * are assisted if we're installed setuid root, we want to set the + * effective user id to the real user id + */ + + if (seteuid(getuid()) < 0) + { + /* fixme: get rid of sys_errlist and use sys_strerror */ + veejay_msg(VEEJAY_MSG_ERROR, "Can't set effective user-id: %s", sys_errlist[errno]); + return -1; + } + if(info->load_action_file ) { + if(sample_readFromFile( info->action_file[1],info->composite,info->seq,info->font,info->edit_list, + &(info->uc->sample_id), &(info->uc->playback_mode) )) + { + veejay_msg(VEEJAY_MSG_INFO, "Loaded samplelist %s", info->action_file[1]); + } + } + + + //@ FIXME + // + veejay_change_state( info, LAVPLAY_STATE_PLAYING ); + + if (!veejay_mjpeg_set_playback_rate(info, el->video_fps, el->video_norm == 'p' ? VIDEO_MODE_PAL : VIDEO_MODE_NTSC)) { + return -1; + } + + if(veejay_open(info) != 1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to initialize the threading system"); + return -1; + } + + + return 0; +} + +static int sched_ncpus() { + return sysconf( _SC_NPROCESSORS_ONLN ); +} + +static void veejay_schedule_fifo(veejay_t *info, int pid ) +{ + struct sched_param schp; + veejay_memset( &schp, 0, sizeof(schp)); + schp.sched_priority = sched_get_priority_max( SCHED_FIFO ); + + if( sched_setscheduler( pid, SCHED_FIFO, &schp ) != 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Cannot set First-In-First-Out scheduling for process %d",pid); + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Using First-In-First-Out II scheduling for process %d", pid); + veejay_msg(VEEJAY_MSG_INFO, "\tPriority is set to %d (RT)", schp.sched_priority ); + } +} + +/****************************************************** + * veejay_playback_cycle() + * the playback cycle + ******************************************************/ +static void veejay_playback_cycle(veejay_t * info) +{ + video_playback_stats stats; + video_playback_setup *settings = + (video_playback_setup *) info->settings; + editlist *el = info->edit_list; + struct mjpeg_sync bs; + + struct timeval time_now; + double tdiff1=0.0, tdiff2=0.0; + int first_free, skipv, skipa, skipi, nvcorr,frame; + struct mjpeg_params bp; + long ts, te; + long frame_number[2]; + int n; + + veejay_set_instance( info ); + stats.tdiff = 0.0; + stats.stats_changed = 0; + stats.num_corrs_a = 0; + stats.num_corrs_b = 0; + stats.nsync = 0; + stats.audio = 0; + stats.norm = el->video_norm == 'n' ? 1 : 0; + tdiff1 = 0.; + tdiff2 = 0.; + nvcorr = 0; + stats.audio = 0; + + if(info->current_edit_list->has_audio && info->audio == AUDIO_PLAY) + { +#ifdef HAVE_JACK + info->audio_running = vj_perform_audio_start(info); + stats.audio = 1; +#endif + } + veejay_set_speed(info,1); + + switch(info->uc->playback_mode) { + case VJ_PLAYBACK_MODE_PLAIN: + info->current_edit_list = info->edit_list; +#ifdef STRICT_CHECKING + assert( info->edit_list != NULL ); +#endif + video_playback_setup *settings = info->settings; + settings->min_frame_num = 1; + settings->max_frame_num = info->edit_list->total_frames; + veejay_msg(VEEJAY_MSG_INFO, "Playing plain video, frames %d - %d", + (int)settings->min_frame_num, (int)settings->max_frame_num ); + settings->current_playback_speed = 1; + break; + case VJ_PLAYBACK_MODE_TAG: + veejay_start_playing_stream(info,info->uc->sample_id); + veejay_msg(VEEJAY_MSG_INFO, "Playing stream %d", info->uc->sample_id); + break; + case VJ_PLAYBACK_MODE_PATTERN: //@ randomizer + info->uc->playback_mode = VJ_PLAYBACK_MODE_SAMPLE; + case VJ_PLAYBACK_MODE_SAMPLE: + veejay_start_playing_sample(info, info->uc->sample_id); + veejay_msg(VEEJAY_MSG_INFO, "Playing sample %d", info->uc->sample_id); + break; + } + vj_perform_queue_audio_frame(info); + vj_perform_queue_video_frame(info,0); + + if (vj_perform_queue_frame(info, 0) != 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Unable to queue frame"); + return; + } + + bp.input = 0; + bp.norm = + (el->video_norm == 'n') ? VIDEO_MODE_NTSC : VIDEO_MODE_PAL; + + veejay_msg(VEEJAY_MSG_DEBUG, "Output norm: %s", + bp.norm == VIDEO_MODE_NTSC ? "NTSC" : "PAL"); + + bp.norm = el->video_norm == VIDEO_MODE_NTSC ? 480 : 576; + + veejay_msg(VEEJAY_MSG_DEBUG, + "Output dimensions: %dx%d, backend scaler: %dx%d", + info->video_output_width,info->video_output_height,info->bes_width,info->bes_height ); + + bp.odd_even = (el->video_inter == LAV_INTER_TOP_FIRST); + + if (!veejay_mjpeg_get_params(info, &bp)) { + veejay_msg(VEEJAY_MSG_ERROR, "Uhm?"); + return ; + } + + + for(n = 0; n < QUEUE_LEN ; n ++ ) { + frame_number[n] = settings->current_frame_num; + veejay_mjpeg_queue_buf(info, n,1 ); + } + stats.nqueue = QUEUE_LEN; + settings->spas = 1.0 / (double) el->audio_rate; + + while (settings->state != LAVPLAY_STATE_STOP) { + first_free = stats.nsync; + + int current_speed = settings->current_playback_speed; +#ifdef HAVE_JACK + if(info->audio == AUDIO_PLAY ) + vj_jack_continue( current_speed ); +#endif + + do { + if (settings->state == LAVPLAY_STATE_STOP) { + goto FINISH; + } + + if (!veejay_mjpeg_sync_buf(info, &bs)) { + veejay_change_state_save(info, LAVPLAY_STATE_STOP); + goto FINISH; + } + frame = bs.frame; + /* Since we queue the frames in order, we have to get them back in order */ + if (frame != stats.nsync % QUEUE_LEN) + { + veejay_msg(0,"**INTERNAL ERROR: Bad frame order on sync: frame = %d, nsync = %d, br.count = %ld", + frame, stats.nsync, QUEUE_LEN); + } + + /* Broadcast & wake up the waiting processes */ + /* Now update the internal variables */ + + stats.nsync++; + gettimeofday(&time_now, 0); + stats.tdiff = time_now.tv_sec - bs.timestamp.tv_sec + + (time_now.tv_usec - bs.timestamp.tv_usec)*1.e-6; + } + while (stats.tdiff > settings->spvf && (stats.nsync - first_free) < (QUEUE_LEN-1)); + + if ((stats.nsync - first_free) > ( QUEUE_LEN - 3)) + veejay_msg(VEEJAY_MSG_WARNING, "Source too slow, can not keep pace!"); + + veejay_event_handle(info); +#ifdef HAVE_JACK + if ( info->audio==AUDIO_PLAY && el->has_audio ) + { + struct timeval audio_tmstmp; + long int sec=0; + long int usec=0; + long num_audio_bytes_written = vj_jack_get_status( &sec,&usec); + + audio_tmstmp.tv_sec = sec; + audio_tmstmp.tv_usec = usec; + + if (audio_tmstmp.tv_sec) + { + tdiff1 = settings->spvf * (stats.nsync - nvcorr) - + settings->spas * num_audio_bytes_written; + tdiff2 = (bs.timestamp.tv_sec - audio_tmstmp.tv_sec) + (bs.timestamp.tv_usec - audio_tmstmp.tv_usec) * 1.e-6; + } + } +#endif + stats.tdiff = (tdiff1 - tdiff2); + + /* Fill and queue free buffers again */ + for (n = first_free; n < stats.nsync;) { + /* Audio/Video sync correction */ + skipv = 0; + skipa = 0; + skipi = 0; + + if (info->sync_correction) { + if (stats.tdiff > settings->spvf) { + /* Video is ahead audio */ + skipa = 1; + if (info->sync_ins_frames && current_speed != 0) + skipi = 1; + nvcorr++; + stats.num_corrs_a++; + stats.tdiff -= settings->spvf; + stats.stats_changed = 1; + } + if (stats.tdiff < -settings->spvf) { + /* Video is behind audio */ + skipv = 1; + if (!info->sync_skip_frames && current_speed != 0) + skipi = 1; + + nvcorr--; + stats.num_corrs_b++; + stats.tdiff += settings->spvf; + stats.stats_changed = 1; + } + } + + frame = n % QUEUE_LEN; + frame_number[frame] = settings->current_frame_num; +#ifdef HAVE_SDL + ts= SDL_GetTicks(); +#endif + settings->buffer_entry[frame] = settings->current_frame_num; + + if (!skipa) + vj_perform_queue_audio_frame(info); + if (!skipv) + vj_perform_queue_video_frame(info,skipi); + + vj_perform_queue_frame( info, skipi ); + +#ifdef HAVE_SDL + te = SDL_GetTicks(); + info->real_fps = (int)( te - ts ); +#else + info->real_fps = 0; +#endif + if(skipv ) continue; + + veejay_mjpeg_queue_buf(info,frame, 1 ); + + stats.nqueue ++; + n++; + } + /* output statistics */ + if (el->has_audio && (info->audio==AUDIO_PLAY)) + stats.audio = settings->audio_mute ? 0 : 1; + stats.stats_changed = 0; +// stats.frame = settings->current_frame_num; +// stats.nsync = 0; + } + + FINISH: + + /* All buffers are queued, sync on the outstanding buffers + * Never try to sync on the last buffer, it is a hostage of + * the codec since it is played over and over again + */ + if (info->audio_running || info->audio ==AUDIO_PLAY) + vj_perform_audio_stop(info); +} + +/****************************************************** + * veejay_playback_thread() + * The main playback thread + ******************************************************/ + +static void Welcome(veejay_t *info) +{ + veejay_msg(VEEJAY_MSG_WARNING, "Video project settings: %ldx%ld, Norm: [%s], fps [%2.2f], %s", + info->current_edit_list->video_width, + info->current_edit_list->video_height, + info->current_edit_list->video_norm == 'n' ? "NTSC" : "PAL", + info->current_edit_list->video_fps, + info->current_edit_list->video_inter==0 ? "Not interlaced" : "Interlaced" ); + if(info->audio==AUDIO_PLAY && info->edit_list->has_audio) + veejay_msg(VEEJAY_MSG_WARNING, " %ldHz %d Channels %dBps (%d Bit) %s %s", + info->current_edit_list->audio_rate, + info->current_edit_list->audio_chans, + info->current_edit_list->audio_bps, + info->current_edit_list->audio_bits, + (info->no_bezerk==0?"[Bezerk]" : " " ), + (info->verbose==0?" " : "[Debug]") ); + + if(info->settings->composite ) + { + veejay_msg(VEEJAY_MSG_INFO, "Software composite - projection screen is %d x %d", + info->video_output_width, info->video_output_height ); + } + + + veejay_msg(VEEJAY_MSG_INFO,"Type 'man veejay' in a shell to learn more about veejay"); + veejay_msg(VEEJAY_MSG_INFO,"For a list of events, type 'veejay -u |less' in a shell"); + veejay_msg(VEEJAY_MSG_INFO,"Use 'reloaded' to enter interactive mode"); + veejay_msg(VEEJAY_MSG_INFO,"Alternatives are OSC applications or 'sendVIMS' extension for PD"); + + int k = verify_working_dir(); + if( k > 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING, + "Found %d veejay project files in current working directory (.edl,.sl, .cfg,.avi).",k); + veejay_msg(VEEJAY_MSG_WARNING, + "If you want to start a new project, start veejay in an empty directory"); + } +} +static void *veejay_playback_thread(void *data) +{ + veejay_t *info = (veejay_t *) data; + int i; + sigset_t mask; + struct sigaction act; + sigemptyset(&mask); + sigaddset( &mask, SIGPIPE ); + act.sa_handler = donothing2; + act.sa_flags = SA_SIGINFO | SA_ONESHOT; + sigemptyset(&act.sa_mask); + + + pthread_sigmask( SIG_BLOCK, &mask, NULL ); + int mode, id; + Welcome(info); + veejay_playback_cycle(info); + veejay_close(info); + if(info->uc->is_server) { + for(i = 0; i < 4; i ++ ) + if(info->vjs[i]) vj_server_shutdown(info->vjs[i]); + } + + if(info->osc) vj_osc_free(info->osc); + +#ifdef HAVE_SDL + for ( i = 0; i < MAX_SDL_OUT ; i ++ ) + if( info->sdl[i] ) + { +#ifndef X_DISPLAY_MISSING + if(info->sdl[i]->display) + x11_enable_screensaver( info->sdl[i]->display); +#endif + vj_sdl_free(info->sdl[i]); + } + + vj_sdl_quit(); +#endif +#ifdef HAVE_DIRECTFB + if( info->dfb ) + { + vj_dfb_free(info->dfb); + free(info->dfb); + } +#endif + if( info->y4m ) { + vj_yuv_stream_stop_write( info->y4m ); + vj_yuv4mpeg_free(info->y4m ); + info->y4m = NULL; + } +/* +#ifdef HAVE_GL +#ifndef X_DISPLAY_MISSING + if( info->video_out == 3 ) + { + x11_enable_screensaver( x_get_display(info->gl) ); + x_display_close( info->gl ); + } +#endif +#endif +*/ +#ifdef HAVE_FREETYPE + vj_font_destroy( info->font ); + vj_font_destroy( info->osd ); +#endif + veejay_msg(VEEJAY_MSG_DEBUG,"Exiting playback thread"); + vj_perform_free(info); + + pthread_exit(NULL); + return NULL; +} + +/* + port 3490 = command, 3491 = status + port 3492 = OSC + port 3493 = mcast frame sender (optional) + port 3494 = mcast command receiver (optional) + */ + +int vj_server_setup(veejay_t * info) +{ + if (info->uc->port == 0) + info->uc->port = VJ_PORT; + info->vjs[VEEJAY_PORT_CMD] = vj_server_alloc(info->uc->port, NULL, V_CMD); + if(!info->vjs[VEEJAY_PORT_CMD]) + return 0; + + info->vjs[VEEJAY_PORT_STA] = vj_server_alloc(info->uc->port, NULL, V_STATUS); + if(!info->vjs[VEEJAY_PORT_STA]) + return 0; + + //@ second VIMS control port + info->vjs[VEEJAY_PORT_DAT] = vj_server_alloc(info->uc->port + 5, NULL, V_CMD ); + if(!info->vjs[VEEJAY_PORT_DAT]) + return 0; + + info->vjs[VEEJAY_PORT_MAT] = NULL; + if( info->settings->use_vims_mcast ) + { + info->vjs[VEEJAY_PORT_MAT] = + vj_server_alloc(info->uc->port, info->settings->vims_group_name, V_CMD ); + if(!info->vjs[VEEJAY_PORT_MAT]) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Unable to initialize mcast sender"); + return 0; + } + } + if(info->settings->use_mcast) + { + GoMultiCast( info->settings->group_name ); + } + + info->osc = (void*) vj_osc_allocate(info->uc->port+6); + + if(!info->osc) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Unable to start OSC server at port %d", + info->uc->port + 6 ); + return 0; + } + + if( info->settings->use_mcast ) + veejay_msg(VEEJAY_MSG_INFO, "UDP multicast OSC channel ready at port %d (group '%s')", + info->uc->port + 6, info->settings->group_name ); + else + veejay_msg(VEEJAY_MSG_INFO, "UDP unicast OSC channel ready at port %d", + info->uc->port + 6 ); + + if(vj_osc_setup_addr_space(info->osc) == 0) + veejay_msg(VEEJAY_MSG_INFO, "Initialized OSC (http://www.cnmat.berkeley.edu/OpenSoundControl/)"); + + if (info->osc == NULL || info->vjs[VEEJAY_PORT_CMD] == NULL || info->vjs[VEEJAY_PORT_STA] == NULL) + { + veejay_msg(0, "Unable to setup basic network I/O. Abort"); + return 0; + } + info->uc->is_server = 1; + + return 1; +} + +/****************************************************** + * veejay_malloc() + * malloc the pointer and set default options + * + * return value: a pointer to an allocated veejay_t + ******************************************************/ +int prepare_cache_line(int perc, int n_slots) +{ + int total = 0; + char line[128]; + FILE *file = fopen( "/proc/meminfo","r"); + if(!file) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cant open proc, memory size cannot be determined"); + veejay_msg(VEEJAY_MSG_ERROR, "Cache disabled"); + return 1; + } + + fgets(line, 128, file ); + sscanf( line, "%*s %i", &total ); + fclose(file); +/* fgets( line,128, file ); + fgets( line,128, file ); + fclose( file ); + sscanf( line, "%*s %i %i %i %i", &total,&avail,&buffer,&cache ); +*/ + double p = (double) perc * 0.01; + int max_memory = (p * total); + if( n_slots <= 0) + n_slots = 1; + + int chunk_size = (max_memory <= 0 ? 0: max_memory / n_slots ); + + chunk_size_ = chunk_size; + n_cache_slots_ = n_slots; + + total_mem_mb_ = total / 1024; + if(chunk_size > 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "%d Kb total system RAM , Consuming up to %2.2f Mb", + total, (float)max_memory / 1024.0 ); + veejay_msg(VEEJAY_MSG_INFO, "Cache line size is %d Kb (%2.2f Mb) per sample", + chunk_size, (float) chunk_size/1024.0); + vj_el_init_chunk( chunk_size ); + } + else + veejay_msg(VEEJAY_MSG_INFO, "Memory cache disabled"); + + return 1; +} + +int smp_check() +{ + return get_nprocs(); +} + +veejay_t *veejay_malloc() +{ + + veejay_t *info; + int i; + + info = (veejay_t *) vj_calloc(sizeof(veejay_t)); + if (!info) + return NULL; + + info->settings = (video_playback_setup *) vj_calloc(sizeof(video_playback_setup)); + if (!(info->settings)) + return NULL; + info->settings->sample_restart = 1; //@ default to on + veejay_memset( &(info->settings->action_scheduler), 0, sizeof(vj_schedule_t)); + veejay_memset( &(info->settings->viewport ), 0, sizeof(VJRectangle)); + + info->status_what = (char*) vj_calloc(sizeof(char) * MESSAGE_SIZE ); + info->status_msg = (char*) vj_calloc(sizeof(char) * MESSAGE_SIZE+5); + + info->uc = (user_control *) vj_calloc(sizeof(user_control)); + if (!(info->uc)) + return NULL; + + info->effect_frame1 = (VJFrame*) vj_calloc(sizeof(VJFrame)); + if(!info->effect_frame1) + return NULL; + + info->effect_frame2 = (VJFrame*) vj_calloc(sizeof(VJFrame)); + if(!info->effect_frame2) + return NULL; + + info->effect_frame_info = (VJFrameInfo*) vj_calloc(sizeof(VJFrameInfo)); + if(!info->effect_frame_info) + return NULL; + + info->effect_info = (vjp_kf*) vj_calloc(sizeof(vjp_kf)); + if(!info->effect_info) + return NULL; + + info->dummy = (dummy_t*) vj_calloc(sizeof(dummy_t)); + if(!info->dummy) + return NULL; + memset( info->dummy, 0, sizeof(dummy_t)); + + memset(&(info->settings->sws_templ), 0, sizeof(sws_template)); + + info->seq = (sequencer_t*) vj_calloc(sizeof( sequencer_t) ); + if(!info->seq) + return NULL; + + info->seq->samples = (int*) vj_calloc(sizeof(int) * MAX_SEQUENCES ); + + info->audio = AUDIO_PLAY; + info->continuous = 1; + info->sync_correction = 1; + info->sync_ins_frames = 1; + info->sync_skip_frames = 1; + info->double_factor = 1; + info->no_bezerk = 1; + info->nstreams = 1; + info->stream_outformat = -1; + info->rlinks = (int*) vj_calloc(sizeof(int) * 8 ); + info->settings->currently_processed_entry = -1; + info->settings->first_frame = 1; + info->settings->state = LAVPLAY_STATE_STOP; + info->settings->composite = 1; + info->uc->playback_mode = VJ_PLAYBACK_MODE_PLAIN; + info->uc->use_timer = 2; + info->uc->sample_key = 1; + info->uc->direction = 1; /* pause */ + info->uc->sample_start = 0; + info->uc->sample_end = 0; + info->net = 1; + + for( i =0; i < 8 ; i ++ ) + info->rlinks[i] = -1; + + veejay_memset(info->action_file[0],0,256); + veejay_memset(info->action_file[1],0,256); + + for (i = 0; i < SAMPLE_MAX_PARAMETERS; i++) + info->effect_info->tmp[i] = 0; + +#ifdef HAVE_SDL + info->video_out = 0; +#else +#ifdef HAVE_DIRECTFB + info->video_out = 1; +#else + info->video_out = 3; +#endif +#endif + + +#ifdef HAVE_SDL + info->sdl = (vj_sdl**) vj_calloc(sizeof(vj_sdl*) * MAX_SDL_OUT ); +#endif + + info->pixel_format = FMT_422F; //@default + info->settings->ncpu = smp_check(); + + int status = 0; + int acj = 0; + int tl = 0; + char *interpolate_chroma = getenv("VEEJAY_INTERPOLATE_CHROMA"); + if( interpolate_chroma ) { + sscanf( interpolate_chroma, "%d", &status ); + } + + char *auto_ccir_jpeg = getenv("VEEJAY_AUTO_SCALE_PIXELS"); + if( auto_ccir_jpeg ) { + sscanf( auto_ccir_jpeg, "%d", &acj ); + } + + char *key_repeat_interval = getenv("VEEJAY_SDL_KEY_REPEAT_INTERVAL"); + char *key_repeat_delay = getenv("VEEJAY_SDL_KEY_REPEAT_DELAY"); + if(key_repeat_interval) { + sscanf( key_repeat_interval, "%d", &(info->settings->repeat_interval)); + } + if( key_repeat_delay) { + sscanf( key_repeat_delay, "%d", &(info->settings->repeat_delay)); + } + + char *best_performance = getenv( "VEEJAY_PERFORMANCE"); + int default_zoomer = 1; + + char *max_cache = getenv( "VEEJAY_PLAYBACK_CACHE"); + if( max_cache ) { + long mb = 0; + if( sscanf( max_cache,"%ld",&mb ) ) { + veejay_msg(VEEJAY_MSG_WARNING, "Maximum memory for sample cache is %ld Mb, per sample %ld", mb ); + vj_el_set_caching(1); + vj_el_init_chunk( (mb * 1024) / 4 ); + } + if( mb == 0 ) + info->no_caching = 0; + } + + char *sdlfs = getenv("VEEJAY_FULLSCREEN"); + if( sdlfs ) { + int val = 0; + if( sscanf( sdlfs, "%d", &val ) ) { + veejay_msg(VEEJAY_MSG_WARNING, "Playing in %s mode", + (val== 1 ? "fullscreen" : "windowed" ) ); + info->settings->full_screen = val; + } + } + + if( best_performance) { + if (strncasecmp( best_performance, "quality", 7 ) == 0 ) { + best_performance_ = 1; + default_zoomer = 2; + status = 1; + veejay_msg(VEEJAY_MSG_WARNING, "Performance set to maximum quality"); + } + else if( strncasecmp( best_performance, "fastest", 7) == 0 ) { + best_performance_ = 0; + veejay_msg(VEEJAY_MSG_WARNING, "Performance set to maximum speed"); + if( acj ) { + veejay_msg(VEEJAY_MSG_WARNING, "\tdisabling flag VEEJAY_AUTO_SCALE_PIXELS"); + acj = 0; + } + if( status ) { + veejay_msg(VEEJAY_MSG_WARNING, "\tdisabling flag VEEJAY_INTERPOLATE_CHROMA"); + status = 0; + } + default_zoomer = 1; + } + } + + yuv_init_lib( status ,acj, default_zoomer); + + if(!vj_avcodec_init( info->pixel_format, info->verbose)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot initialize encoders!"); + return 0; + } + + + + return info; +} + + + + +/****************************************************** + * veejay_main() + * the whole video-playback cycle + * return value: 1 on succes, 0 on error + ******************************************************/ + +int veejay_main(veejay_t * info) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + /* Flush the Linux File buffers to disk */ + sync(); + if (pthread_create(&(settings->playback_thread),NULL, + veejay_playback_thread, (void *) info)) { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to create thread"); + return -1; + } + + return 1; +} + + + +/*** Methods for simple video editing (cut/paste) ***/ + +/****************************************************** + * veejay_edit_copy() + * copy a number of frames into a buffer + * + * return value: 1 on succes, 0 on error + ******************************************************/ + +static void veejay_reset_el_buffer( veejay_t *info ) +{ + + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + if (settings->save_list) + free(settings->save_list); + + settings->save_list = NULL; + settings->save_list_len = 0; + +} + +int veejay_edit_copy(veejay_t * info, editlist *el, long start, long end) +{ + + if(el->is_empty) + { + veejay_msg(VEEJAY_MSG_ERROR, "No frames in EDL to copy"); + return 0; + } + + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + uint64_t k, i; + uint64_t n1 = (uint64_t) start; + uint64_t n2 = (uint64_t) end; + if (settings->save_list) + free(settings->save_list); + + settings->save_list = + (uint64_t *) vj_calloc((n2 - n1 + 1) * sizeof(uint64_t)); + + if (!settings->save_list) + { + veejay_change_state_save(info, LAVPLAY_STATE_STOP); + return 0; + } + + k = 0; + + for (i = n1; i <= n2; i++) + settings->save_list[k++] = el->frame_list[i]; + + settings->save_list_len = k; + + veejay_msg(VEEJAY_MSG_DEBUG, "Copied frames %d - %d to buffer (of size %d)",n1,n2,k ); + + return 1; +} +editlist *veejay_edit_copy_to_new(veejay_t * info, editlist *el, long start, long end) +{ + uint64_t k, i; + uint64_t n1 = (uint64_t) start; + uint64_t n2 = (uint64_t) end; + + long len = end - start + 1; + + if(el->is_empty) + { + veejay_msg(VEEJAY_MSG_ERROR, "No frames in EDL to copy"); + return 0; + } + + if( n2 >= el->video_frames) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample end is outside of editlist"); + return NULL; + } + + if(len <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample too short!"); + return NULL; + } + + /* Copy edl */ + editlist *new_el = vj_el_soft_clone( el ); + + if(!new_el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot soft clone EDL"); + return NULL; + } + + /* copy edl frames */ + new_el->frame_list = (uint64_t *) vj_malloc( sizeof(uint64_t) * len ); + + if (!new_el->frame_list) + { + veejay_msg(0, "Out of memory, unable to allocate editlist of %ld bytes", len); + veejay_change_state_save(info, LAVPLAY_STATE_STOP); + return NULL; + } + + k = 0; + + +//veejay_msg(0, "start of framelist: %p, end = %p", &(el->frame_list[n1]), &(el->frame_list[n2+1]) ); +//veejay_msg(0, "memcpy %p, %p", el->frame_list + n1, el->frame_list + n1 + len ); + veejay_memcpy( new_el->frame_list , el->frame_list + n1, sizeof(uint64_t) * len ); + new_el->video_frames = len; + new_el->total_frames = len - 1; +// for (i = n1; i <= n2; i++) +// new_el->frame_list[k++] = el->frame_list[i]; + +// new_el->video_frames = k; + return new_el; +} + +/****************************************************** + * veejay_edit_delete() + * delete a number of frames from the current movie + * + * return value: 1 on succes, 0 on error + ******************************************************/ + +int veejay_edit_delete(veejay_t * info, editlist *el, long start, long end) +{ + if(el->is_empty) + { + veejay_msg(VEEJAY_MSG_ERROR, "Nothing in EDL to delete"); + return 0; + } + + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + + uint64_t i; + uint64_t n1 = (uint64_t) start; + uint64_t n2 = (uint64_t) end; + + if(info->dummy->active) + { + veejay_msg(VEEJAY_MSG_ERROR, "Playing dummy video!"); + return 0; + } + + if (n2 < n1 || n1 > el->total_frames || n2 > el->total_frames ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Incorrect parameters for deleting frames"); + return 0; + } + + for (i = n2 + 1; i < el->video_frames; i++) + el->frame_list[i - (n2 - n1 + 1)] = el->frame_list[i]; + + if (n1 - 1 < settings->min_frame_num) + { + if (n2 < settings->min_frame_num) + settings->min_frame_num -= (n2 - n1 + 1); + else + settings->min_frame_num = n1; + } + + if (n1 - 1 < settings->max_frame_num) + { + if (n2 <= settings->max_frame_num) + settings->max_frame_num -= (n2 - n1 + 1); + else + settings->max_frame_num = n1 - 1; + } + + if (n1 <= settings->current_frame_num) { + + if (settings->current_frame_num <= n2) + { + settings->current_frame_num = n1; + } + else + { + settings->current_frame_num -= (n2 - n1 + 1); + } + } + + el->video_frames -= (n2 - n1 + 1); + el->total_frames = el->video_frames - 1; + return 1; +} + + + + +/****************************************************** + * veejay_edit_cut() + * cut a number of frames into a buffer + * + * return value: 1 on succes, 0 on error + ******************************************************/ + +int veejay_edit_cut(veejay_t * info, editlist *el, long start, long end) +{ + if( el->is_empty ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Nothing to cut in EDL"); + return 0; + } + if (!veejay_edit_copy(info, el,start, end)) + return 0; + if (!veejay_edit_delete(info, el,start, end)) + return 0; + + return 1; +} + + +/****************************************************** + * veejay_edit_paste() + * paste frames from the buffer into a certain position + * + * return value: 1 on succes, 0 on error + ******************************************************/ + +int veejay_edit_paste(veejay_t * info, editlist *el, long destination) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + uint64_t i, k; + + if (!settings->save_list_len || !settings->save_list) + { + veejay_msg(VEEJAY_MSG_ERROR, + "No frames in the buffer to paste"); + return 0; + } + + if(el->is_empty) + { + destination = 0; + } + else + { + if (destination < 0 || destination > el->total_frames) + { + if(destination < 0) + veejay_msg(VEEJAY_MSG_ERROR, + "Destination cannot be negative"); + if(destination > el->total_frames) + veejay_msg(VEEJAY_MSG_ERROR, "Cannot paste beyond Edit List!"); + return 0; + } + } + + el->frame_list = (uint64_t*)realloc(el->frame_list, + ((el->is_empty ? 0 :el->video_frames) + + settings->save_list_len) * + sizeof(uint64_t)); + if (!el->frame_list) + { + veejay_change_state_save(info, LAVPLAY_STATE_STOP); + return 0; + } + + k = (uint64_t)settings->save_list_len; + for (i = el->total_frames; i >= destination && i > 0; i--) + el->frame_list[i + k] = el->frame_list[i]; + k = destination; + for (i = 0; i < settings->save_list_len; i++) + { + if (k <= settings->min_frame_num) + settings->min_frame_num++; + if (k < settings->max_frame_num) + settings->max_frame_num++; + + el->frame_list[k] = settings->save_list[i]; + k++; + } + el->video_frames += settings->save_list_len; + el->total_frames = el->video_frames - 1; + if(el->is_empty) + el->is_empty = 0; + veejay_increase_frame(info, 0); + + + veejay_msg(VEEJAY_MSG_DEBUG, + "Pasted %lld frames from buffer into position %ld in movie", + settings->save_list_len, destination ); + return 1; +} + + +/****************************************************** + * veejay_edit_move() + * move a number of frames to a different position + * + * return value: 1 on succes, 0 on error + ******************************************************/ + +int veejay_edit_move(veejay_t * info,editlist *el, long start, long end, + long destination) +{ + long dest_real; + if( el->is_empty ) + return 0; + + if (destination > el->total_frames || destination < 0 + || start < 0 || end < 0 || start >= el->video_frames + || end > el->total_frames || end < start) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid parameters for moving video from %ld - %ld to position %ld", + start,end,destination); + veejay_msg(VEEJAY_MSG_ERROR, "Range is 0 - %ld", el->total_frames); + return 0; + } + + if (destination < start) + dest_real = destination; + else if (destination > end) + dest_real = destination - (end - start + 1); + else + dest_real = start; + + if (!veejay_edit_cut(info, el, start, end)) + return 0; + + if (!veejay_edit_paste(info, el,dest_real)) + return 0; + + + return 1; +} + + +/****************************************************** + * veejay_edit_addmovie() + * add a number of frames from a new movie to a + * certain position in the current movie + * + * return value: 1 on succes, 0 on error + ******************************************************/ + +int veejay_edit_addmovie_sample(veejay_t * info, char *movie, int id ) +{ + char *files[1]; + + files[0] = strdup(movie); + sample_info *sample = NULL; + editlist *sample_edl = NULL; + // if sample exists, get it for update + if(sample_exists(id) ) + sample = sample_get(id); + + // if sample exists, it could have a edit list */ + if( sample ) + { + if( !sample_usable_edl( id ) ) + { + veejay_msg(0, "Sample %d has no EDL (its a picture!)", id ); + return -1; + } + + sample_edl = sample_get_editlist( id ); + } + + // if both, append it to sample's edit list + if(sample_edl && sample) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Adding video file to existing sample %d", id ); + if(veejay_edit_addmovie_sample( info, movie, id)) + return 0; + return -1; + } + + // create initial edit list for sample (is currently playing) + if(!sample_edl) + sample_edl = vj_el_init_with_args( files,1,info->preserve_pathnames,info->auto_deinterlace,0, + info->edit_list->video_norm , info->pixel_format); + // if that fails, bye + if(!sample_edl) + { + veejay_msg(0, "Error while creating EDL"); + return -1; + } + // the editlist dimensions must match (there's more) + if( sample_edl->video_width != info->edit_list->video_width || + sample_edl->video_height != info->edit_list->video_height ) + { + if(sample_edl) + vj_el_free(sample_edl); + veejay_msg(0, "Frame dimensions do not match. Abort"); + return -1; + } + + // the sample is not there yet,create it + if(!sample) + { + sample = sample_skeleton_new( 0, sample_edl->total_frames ); + if(sample) + { + sample->edit_list = sample_edl; + sample_store(sample); + // sample_set_editlist( sample->sample_id , sample_edl ); + + veejay_msg(VEEJAY_MSG_INFO, + "Created new sample %d from file %s",sample->sample_id, + files[0]); + } + else + veejay_msg(VEEJAY_MSG_ERROR, + "Failed to create new sample from file '%s'", + files[0]); + + } + + // free temporary values + if(files[0]) free(files[0]); + + // return new id + return sample->sample_id; +} + +int veejay_edit_addmovie(veejay_t * info, editlist *el, char *movie, long start,long end ) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + uint64_t n, i; + uint64_t c = el->video_frames; + if( el->is_empty ) + c -= 2; + + int res = open_video_file(movie, el, info->preserve_pathnames, info->auto_deinterlace,1, + info->edit_list->video_norm ); + + if (res < 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Error adding file '%s' to EDL", movie ); + return 0; + } + + end = el->video_frames; + + el->frame_list = (uint64_t *) realloc(el->frame_list, (end + el->num_frames[n])*sizeof(uint64_t)); + if (el->frame_list==NULL) + { + veejay_msg(VEEJAY_MSG_ERROR, "Insufficient memory to allocate frame_list"); + vj_el_free(el); + return 0; + } + + for (i = 0; i < el->num_frames[n]; i++) + { + el->frame_list[c] = EL_ENTRY(n, i); + c++; + } + + el->video_frames = c; + el->total_frames = el->video_frames - 1; + settings->max_frame_num = el->total_frames; + settings->min_frame_num = 1; + + return 1; +} + + + +/****************************************************** + * veejay_toggle_audio() + * mutes or unmutes audio (1 = on, 0 = off) + * + * return value: 1 on succes, 0 on error + ******************************************************/ + + +int veejay_toggle_audio(veejay_t * info, int audio) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + editlist *el = info->current_edit_list; + + if( !(el->has_audio) ) { + veejay_msg(VEEJAY_MSG_WARNING, + "Audio playback has not been enabled"); + info->audio = 0; + return 0; + } + + settings->audio_mute = !settings->audio_mute; + + veejay_msg(VEEJAY_MSG_DEBUG, + "Audio playback was %s", audio == 0 ? "muted" : "unmuted"); + + + return 1; +} + + + +/*** Methods for saving the currently played movie to editlists or open new movies */ + +/****************************************************** + * veejay_save_selection() + * save a certain range of frames to an editlist + * + * return value: 1 on succes, 0 on error + ******************************************************/ + + +/****************************************************** + * veejay_save_all() + * save the whole current movie to an editlist + * + * return value: 1 on succes, 0 on error + ******************************************************/ +int veejay_save_all(veejay_t * info, char *filename, long n1, long n2) +{ + editlist *e = info->edit_list; + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) { + e = info->current_edit_list; + } + if( e->num_video_files <= 0 ) + return 0; + + if(n1 == 0 && n2 == 0 ) + n2 = e->total_frames; + + if( vj_el_write_editlist( filename, n1,n2, e ) ) + veejay_msg(VEEJAY_MSG_INFO, "Saved EDL to file %s", filename); + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Error while saving EDL to %s", filename); + return 0; + } + + return 1; +} + +/****************************************************** + * veejay_open() + * open a new (series of) movie + * + * return value: 1 on succes, 0 on error + ******************************************************/ +/****************************************************** + * veejay_open() + * open a new (series of) movie + * + * return value: 1 on succes, 0 on error + ******************************************************/ +// open_video_files is called BEFORE init +static int veejay_open_video_files(veejay_t *info, char **files, int num_files, int force , char override_norm) +{ + + video_playback_setup *settings = + (video_playback_setup *) info->settings; + vj_el_frame_cache(info->seek_cache ); + + if(num_files<=0 || files == NULL) + { + veejay_msg(VEEJAY_MSG_WARNING, "Fallback to dummy - no video files given at commandline"); + info->dummy->active = 1; + } + + //@ set dummy to output dimensions, fallback to internal defaults if fail + info->dummy->width = info->video_output_width; + info->dummy->height= info->video_output_height; + + //TODO: pass yuv sampling to dummy + if( info->dummy->active ) + { + info->dummy->norm = override_norm; + if( override_norm == 'n' ) { + if(!info->dummy->fps) //@ if not set + info->dummy->fps = 30000.0/1001; + } + if(!info->dummy->fps) + info->dummy->fps = settings->output_fps; + + if(!info->dummy->fps) + info->dummy->fps = 25.0f; + + int dw = 720; + int dh = (override_norm == 'p' ? 576 : 480); + + char *runClassic = getenv( "VEEJAY_RUN_MODE" ); + if( runClassic ) { + if( strncasecmp("CLASSIC",runClassic,7 ) == 0 ) { + dw = (override_norm == 'p' ? 352 : 360 ); + dh = dh / 2; + } + } + + if( !info->dummy->width ) + info->dummy->width = dw; + if( !info->dummy->height) + info->dummy->height = dh; + + info->dummy->chroma = CHROMA422; + if( info->audio ) { + if( !info->dummy->arate) + info->dummy->arate = 48000; + } + + info->edit_list = vj_el_dummy( 0, + info->auto_deinterlace, + info->dummy->chroma, + info->dummy->norm, + info->dummy->width, + info->dummy->height, + info->dummy->fps, + info->pixel_format + ); + + if( info->dummy->arate ) + { + editlist *el = info->edit_list; + el->has_audio = 1; + el->audio_rate = info->dummy->arate; + el->audio_chans = 2; + el->audio_bits = 16; + el->audio_bps = 4; + veejay_msg(VEEJAY_MSG_DEBUG, "Dummy Audio: %f KHz, %d channels, %d bps, %d bit audio", + (float)el->audio_rate/1000.0,el->audio_chans,el->audio_bps,el->audio_bits); + } + veejay_msg(VEEJAY_MSG_DEBUG,"Dummy Video: %dx%d, chroma %x, framerate %2.2f, norm %s", + info->dummy->width,info->dummy->height, info->dummy->chroma,info->dummy->fps, + (info->dummy->norm == 'n' ? "NTSC" :"PAL")); + + } + else + { + info->edit_list = + vj_el_init_with_args( + files, + num_files, + info->preserve_pathnames, + info->auto_deinterlace, + force, + override_norm, + info->pixel_format); + if(!info->edit_list ) + return 0; + } + + //@ set current + info->current_edit_list = info->edit_list; + info->effect_frame_info->width = info->current_edit_list->video_width; + info->effect_frame_info->height= info->current_edit_list->video_height; + + if(info->settings->output_fps > 0.0) + { + veejay_msg(VEEJAY_MSG_WARNING, "Overriding Framerate with %2.2f", + info->settings->output_fps); + info->current_edit_list->video_fps = info->settings->output_fps; + } + else + { + info->settings->output_fps = info->current_edit_list->video_fps; + } + + return 1; +} + +int veejay_open_files(veejay_t * info, char **files, int num_files, float ofps, int force,int force_pix_fmt, char override_norm, int switch_jpeg) +{ + int ret = 0; + video_playback_setup *settings = + (video_playback_setup *) info->settings; + + switch( force_pix_fmt ) { + case 1: info->pixel_format = FMT_422;break; + case 2: info->pixel_format = FMT_422F;break; + default: + break; + } + + char text[24]; + switch(info->pixel_format) { + case FMT_422: + sprintf(text, "4:2:2 [16-235][16-240]");break; + case FMT_422F: + sprintf(text, "4:2:2 [0-255]");break; + default: + veejay_msg(VEEJAY_MSG_ERROR, "Unknown pixel format set"); + return 0; + } + + if(force_pix_fmt > 0 ) { + veejay_msg(VEEJAY_MSG_WARNING , "Output pixel format set to %s by user", text ); + } + else + veejay_msg(VEEJAY_MSG_DEBUG, "Processing set to YUV %s", text ); + + vj_el_init( info->pixel_format, switch_jpeg, info->dummy->width,info->dummy->height, info->dummy->fps ); +#ifdef USE_GDK_PIXBUF + vj_picture_init( &(info->settings->sws_templ)); +#endif + + + /* override options */ + if(ofps<=0.0) + ofps = settings->output_fps; + + settings->output_fps = ofps; + + if(num_files == 0) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Trying to start without video"); + ret = veejay_open_video_files( info, NULL, 0 , force, + override_norm ); + } + else + { + ret = veejay_open_video_files( info, files, num_files, force, + override_norm ); + } + + return ret; +} + diff --git a/branches/V-1.5.3/veejay-server/veejay/libveejay.h b/branches/V-1.5.3/veejay-server/veejay/libveejay.h new file mode 100644 index 00000000..02dcba00 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/libveejay.h @@ -0,0 +1,134 @@ + /* + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* todo: cleanup. lots bad things. */ +#ifndef VJ_LIBLAVPLAY_H +#define VJ_LIBLAVPLAY_H +#include "vj-lib.h" + +void veejay_set_instance( veejay_t *info ); + +veejay_t *veejay_malloc(); + +void veejay_change_playback_mode(veejay_t *info, int pm, int sample); + +int veejay_free(veejay_t *info); +void vj_lock(veejay_t *info); + +void vj_unlock(veejay_t *info); +void veejay_busy(veejay_t * info); +void veejay_signal_loop(void *); + +int veejay_init_editlist(veejay_t * info); + +int veejay_init(veejay_t *info,int w, int h, char *arg, int td); + +int veejay_open(veejay_t *info); + +int veejay_open_files(veejay_t * info, char **files, int num_files, float fps, int force, int pixfmt, char norm, int switch_jpeg); + +int veejay_main(veejay_t * info); + +void veejay_quit(veejay_t *info); + +int veejay_dummy_open(veejay_t * info,int ofps, char *file, int pixfmt); + +int veejay_close(veejay_t *info); + +int get_total_mem(void); + +char *veejay_title(veejay_t *info); + +void veejay_stop_sampling(veejay_t *info); +void veejay_set_sample_f(veejay_t *info, int sample, int offset ); +void veejay_set_sample(veejay_t *info, int sample); + +int veejay_set_frame(veejay_t *info, long frame_num); + +#ifdef STRICT_CHECKING +#define veejay_change_state(a,b) vcs(a,b,__FUNCTION__,__LINE__) +void vcs(veejay_t *info, int new_state,const char *caller_func,const int caller_line); +#else +void veejay_change_state(veejay_t *info, int new_state); +#endif +int veejay_set_speed(veejay_t *info , int speed); + +int veejay_increase_frame(veejay_t * info, long numframes); + +void veejay_composite_transform_points( veejay_t *info, void *coords, int points, int blob_id, int cx, int cy,int w, int h, int num_objects,uint8_t *plane ); + +void veejay_composite_dummy( ); + +int veejay_composite_active( veejay_t *info ); + + +int veejay_create_tag(veejay_t * info, int type, char *filename, + int index, int palette, int channel); + +int veejay_set_framedup(veejay_t *info, int n); + +void veejay_set_framerate( veejay_t *info , float fps ); + +int veejay_get_state(veejay_t *info); + +int veejay_create_sample(veejay_t * info, long start, long end); + +int veejay_edit_copy(veejay_t *info, editlist *el, long start, long end); + +int veejay_edit_delete(veejay_t *info, editlist *el, long start, long end); + +int veejay_edit_cut(veejay_t * info, editlist *el, long start, long end); + +int veejay_edit_paste(veejay_t * info, editlist *el, long destination); + +int veejay_edit_move(veejay_t * info, editlist *el , long start, long end,long dest); + +int veejay_edit_addmovie(veejay_t * info, editlist *el, char *movie, long start, + long end); +int veejay_edit_addmovie_sample(veejay_t * info, char *movie , int new_s); + +int veejay_edit_set_playable(veejay_t * info, long start, long end); + +void veejay_set_sampling(veejay_t *info, subsample_mode_t m); + + +int veejay_toggle_audio(veejay_t * info, int audio); + +int veejay_save_selection(veejay_t * info, char *filename, long start,long end); + +int veejay_save_all(veejay_t * info, char *filename, long n1, long n2); + +int vj_server_setup(veejay_t *info); + +void veejay_default_tags(veejay_t *info); + +void veejay_loop_count(veejay_t *info); + +editlist *veejay_edit_copy_to_new(veejay_t * info, editlist *el, long start, long end); + +void veejay_change_state_save(veejay_t * info, int new_state); + +void veejay_handle_signal(void *arg, int sig); + +void veejay_check_homedir(void *arg); + +void veejay_auto_loop(veejay_t *info); + +int prepare_cache_line(int perc, int n_slots); + +int veejay_set_yuv_range( veejay_t *info ); + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/veejay.c b/branches/V-1.5.3/veejay-server/veejay/veejay.c new file mode 100644 index 00000000..024dcc11 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/veejay.c @@ -0,0 +1,757 @@ +/* veejay - Linux VeeJay + * (C) 2002-2010 Niels Elburg + * + * + * 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 +#define VJ_PROMPT "$> " +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef X_DISPLAY_MISSING +#include +#endif +#include +#include +#include +#include +#include +extern long vj_el_get_mem_size(); + +static int run_server = 1; +static veejay_t *info = NULL; +static float override_fps = 0.0; +static int default_geometry_x = -1; +static int default_geometry_y = -1; +static int force_video_file = 0; // unused +static int override_pix_fmt = 0; +static int switch_jpeg = 0; +static char override_norm = 'p'; +static int auto_loop = 0; +static int n_slots_ = 4; +static int max_mem_ = 30; +static int live =0; + +static void CompiledWith() +{ + veejay_msg(VEEJAY_MSG_INFO,"Compilation flags:"); +#ifdef ARCH_MIPS + veejay_msg(VEEJAY_MSG_INFO, "\tCompiled for MIPS"); +#endif +#ifdef ARCH_PPC + veejay_msg(VEEJAY_MSG_INFO, "\tCompiled for PPC"); +#endif +#ifdef ARCH_X86_64 + veejay_msg(VEEJAY_MSG_INFO, "\tCompiled for X86_64"); +#endif +#ifdef ARCH_X86 + veejay_msg(VEEJAY_MSG_INFO, "\tCompiled for X86"); +#endif +#ifdef HAVE_DARWIN + veejay_msg(VEEJAY_MSG_INFO, "\tCompiled for Darwin"); +#endif +#ifdef HAVE_PS2 + veejay_msg(VEEJAY_MSG_INFO, "\tCompiled for Sony Playstation 2 (TM)"); +#endif +#ifdef HAVE_ALTIVEC + veejay_msg(VEEJAY_MSG_INFO,"\tUsing Altivec"); +#endif +#ifdef HAVE_ASM_SSE + veejay_msg(VEEJAY_MSG_INFO,"\tUsing SSE instruction set"); +#endif +#ifdef HAVE_CMOV + veejay_msg(VEEJAY_MSG_INFO,"\tUsing CMOV"); +#endif +#ifdef HAVE_ASM_SSE2 + veejay_msg(VEEJAY_MSG_INFO,"\tUsing SSE2 instruction set"); +#endif +#ifdef HAVE_ASM_MMX + veejay_msg(VEEJAY_MSG_INFO,"\tUsing MMX instruction set"); +#endif +#ifdef HAVE_ASM_MMX2 + veejay_msg(VEEJAY_MSG_INFO,"\tUsing MMX2 instruction set"); +#endif +#ifdef HAVE_ASM_3DNOW + veejay_msg(VEEJAY_MSG_INFO,"\tUsing 3Dnow instruction set"); +#endif + +#ifdef USE_GDK_PIXBUF + veejay_msg(VEEJAY_MSG_INFO,"\tUse GDK Pixbuf"); +#endif + veejay_msg(VEEJAY_MSG_INFO,"\tUse software scaler"); +#ifdef HAVE_JACK + veejay_msg(VEEJAY_MSG_INFO,"\tUsing Jack audio server"); +#endif +#ifdef HAVE_UNICAP + veejay_msg(VEEJAY_MSG_INFO,"\tSupport for Unicap ( setenv VEEJAY_CAPTURE_DRIVER=unicap )"); +#endif + veejay_msg(VEEJAY_MSG_INFO,"\tUsing Video4linux"); +#ifdef SUPPORT_READ_DV2 + veejay_msg(VEEJAY_MSG_INFO,"\tSupport for Digital Video enabled"); +#endif +#ifdef HAVE_XML2 + veejay_msg(VEEJAY_MSG_INFO,"\tUsing XML library for Gnome"); +#endif +#ifdef SUPPORT_READ_DV2 + veejay_msg(VEEJAY_MSG_INFO,"\tSupport for Digital Video enabled"); +#endif +#ifdef HAVE_SDL + veejay_msg(VEEJAY_MSG_INFO,"\tUsing Simple Direct Media Layer"); +#endif +#ifdef HAVE_JPEG + veejay_msg(VEEJAY_MSG_INFO,"\tUsing libjpeg"); +#endif +#ifdef HAVE_LIBPTHREAD + veejay_msg(VEEJAY_MSG_INFO,"\tUsing libpthread"); +#endif +#ifdef HAVE_V4L + veejay_msg(VEEJAY_MSG_INFO,"\tUsing Video4Linux"); +#endif + + /* +#ifdef HAVE_GL + veejay_msg( VEEJAY_MSG_INFO, "\tUsing openGL "); +#endif + */ +#ifdef HAVE_DIRECTFB + veejay_msg(VEEJAY_MSG_INFO,"\tUsing DirectFB"); +#endif + exit(0); +} + +static void Usage(char *progname) +{ + fprintf(stderr, "This is Veejay %s\n\n", VERSION); + fprintf(stderr, "Usage: %s [options] [ ...]\n", progname); + fprintf(stderr,"where options are:\n\n"); + fprintf(stderr, + " -v/--verbose \t\tEnable debugging output (default off)\n"); + fprintf(stderr, + " -n/--no-color \t\tDo not use colored text\n"); + fprintf(stderr, + " -u/--dump-events \t\tDump veejay's documentation to stdout\n"); + fprintf(stderr, + " -B/--features \t\tList of compiled features\n"); + fprintf(stderr, + " -D/--composite \t\tDo not start with camera/projection calibration viewport \n"); + + fprintf(stderr, + " -p/--port \t\tTCP port to accept/send messages (default: 3490)\n"); + fprintf(stderr, + " -M/--multicast-osc \t\tmulticast OSC\n"); + fprintf(stderr, + " -T/--multicast-vims \t\tmulticast VIMS\n"); + + fprintf(stderr, + " --map-from-file \tmap N frames to memory\n"); + fprintf(stderr, + " -m/--memory \t\tMaximum memory to use for cache (0=disable, default=30 max=100)\n"); + fprintf(stderr, + " -j/--max_cache \t\tDivide cache memory over N samples (default=4)\n"); + + fprintf(stderr, + " -Y/--yuv [01]\t\t\tForce YCbCr (defaults to YUV)\n"); + + fprintf(stderr, + " -t/--timer \t\tspecify timer to use (none:0,normal:2,rtc:1) default is 1\n"); + + fprintf(stderr, + " -P/--preserve-pathnames\tDo not 'canonicalise' pathnames in edit lists\n"); + fprintf(stderr, + " -e/--swap-range \t\tSwap YUV range [0..255] <-> [16..235] on videofiles\n"); + fprintf(stderr, + "\t\t\t\t 0 = YUV 4:2:0 Planar\n"); + fprintf(stderr, + "\t\t\t\t 1 = YUV 4:2:2 Planar (default)\n"); + fprintf(stderr, + "\t\t\t\t 2 = YUV 4:2:0 Planar full range\n"); + fprintf(stderr, + "\t\t\t\t 3 = YUV 4:2:2 Planar full range\n"); + fprintf(stderr, + " -L/--auto-loop \t\tStart with default sample\n"); + fprintf(stderr, + " -b/--bezerk \t\tBezerk (default off) \n"); + fprintf(stderr, + " -l/--sample-file \tLoad a sample list file (none at default)\n"); + fprintf(stderr, + " -F/--action-file \tLoad an action file (none at default)\n"); + + + fprintf(stderr, + " -g/--clip-as-sample\t\tLoad every video clip as a new sample\n"); + + fprintf(stderr, + " -a/--audio [01]\t\tEnable (1) or disable (0) audio (default 1)\n"); + + fprintf(stderr, + " -c/--synchronization [01]\tSync correction off/on (default on)\n"); + + fprintf(stderr, + " -O/--output [0..4]\t\tOutput video\n"); +#ifdef HAVE_SDL + fprintf(stderr, + "\t\t\t\t0 = SDL (default)\t\n"); +#endif +#ifdef HAVE_DIRECTFB + fprintf(stderr, + "\t\t\t\t1 = DirectDB\t\n"); +#ifdef HAVE_SDL + fprintf(stderr, + "\t\t\t\t2 = SDL and DirectDB secondary head (TV-Out) clone mode\n"); +#endif +#endif + fprintf(stderr, + "\t\t\t\t3 = Head less (no video output)\n"); + fprintf(stderr, + "\t\t\t\t4 = Y4M Stream\n"); + fprintf(stderr, + " -o/--output-file [file]\tWrite to file (for use with Y4M Stream)\n"); +#ifdef HAVE_SDL + fprintf(stderr, + " -s/--size NxN\t\t\tDisplay dimension for video window, use Width x Height\n"); + + fprintf(stderr, + " -x/--geometry-x \tTop left x offset for SDL video window\n"); + fprintf(stderr, + " -y/--geometry-y \tTop left y offset for SDL video window\n"); + +#endif + fprintf(stderr, + " -A/--all [num] \t\tStart with capture device \n"); + + fprintf(stderr, + " -d/--dummy \t\tStart with no video (black frames)\n"); + fprintf(stderr, + " -W/--input-width \tSet input video width\n"); + fprintf(stderr, + " -H/--input-height \tSet input video height\n"); + fprintf(stderr, + " -f/--fps \t\tOverride default frame rate (default: read from first loaded file)\n"); + fprintf(stderr, + " -r/--audiorate \t\tSet audio rate (defaults to 48Khz)\n"); + fprintf(stderr, + " -I/--deinterlace\t\tDeinterlace video if it is interlaced\n"); + fprintf(stderr, + " -N/--norm \t\tSet video norm [0=PAL, 1=NTSC (defaults to PAL)]\n"); + + fprintf(stderr, + " -w/--output-width \tSet output video width (Projection)\n"); + fprintf(stderr, + " -h/--output-height \tSet output video height (Projection)\n"); + + fprintf(stderr," -q/--quit \t\t\tQuit at end of file\n"); + fprintf(stderr,"\n\n"); +} + +#define OUT_OF_RANGE(val) ( val < 0 ? 1 : ( val > 100 ? 1 : 0) ) + +#define OUT_OF_RANGE_ERR(val) if(OUT_OF_RANGE(val)) { fprintf(stderr,"\tValue must be 0-100\n"); exit(1); } + +#define check_val(val,msg) {\ +char *v = strdup(val);\ +if(v==NULL){\ +fprintf(stderr, " Invalid argument given for %s\n",msg);\ +}\ +else\ +{\ +free(v);\ +}\ +} +static int set_option(const char *name, char *value) +{ + /* return 1 means error, return 0 means okay */ + int nerr = 0; + if (strcmp(name, "port") == 0 || strcmp(name, "p") == 0) { + info->uc->port = atoi(optarg); + } else if (strcmp(name, "verbose") == 0 || strcmp(name, "v") == 0) { + info->verbose = 1; + } else if (strcmp(name, "no-color") == 0 || strcmp(name,"n") == 0) + { + veejay_set_colors(0); + } else if (strcmp(name, "audio") == 0 || strcmp(name, "a") == 0) { + info->audio = atoi(optarg); + } else if ( strcmp(name, "A" ) == 0 || strcmp(name, "capture-device" ) == 0 ) { + live = atoi(optarg); + } else if (strcmp(name, "bezerk") == 0 || strcmp(name, "b") == 0) { + info->no_bezerk = 0; + } else if (strcmp(name, "timer") == 0 || strcmp(name, "t") == 0) { + info->uc->use_timer = atoi(optarg); + if (info->uc->use_timer < 0 || info->uc->use_timer > 2) { + printf("Valid timers:\n\t0=none\n\t2=normal\n\t1=rtc\n"); + nerr++; + } + } else if (strcmp(name, "multicast-vims") == 0 || strcmp(name,"T")==0) + { + check_val(optarg, name); + info->settings->use_vims_mcast = 1; + info->settings->vims_group_name = strdup(optarg); + } + else if (strcmp(name, "multicast-osc") == 0 || strcmp(name, "M") == 0 ) + { + check_val(optarg,name); + info->settings->use_mcast = 1; + info->settings->group_name = strdup( optarg ); + } + else if (strcmp(name, "max_cache" )== 0 || strcmp(name, "j" ) == 0 ) + { + n_slots_ = atoi( optarg ); + if(n_slots_ < 0 ) n_slots_ = 0; else if (n_slots_ > 100) n_slots_ = 100; + } + else if (strcmp(name, "memory" ) == 0 || strcmp(name, "m" ) == 0) + { + max_mem_ = atoi(optarg); + if(max_mem_ < 0 ) max_mem_ = 0; else if (max_mem_ > 100) max_mem_ = 100; + } else if (strcmp(name, "synchronization") == 0 + || strcmp(name, "c") == 0) { + info->sync_correction = atoi(optarg); + } else if (strcmp(name, "version") == 0 ) + { printf("Veejay %s\n", VERSION); exit(0); + } else if (strcmp(name, "graphics-driver") == 0 + || strcmp(name, "G") == 0 + || strcmp(name, "output") == 0 + || strcmp(name, "O") == 0) { + info->video_out = atoi(optarg); /* use SDL */ +/*#ifndef HAVE_GL + if(info->video_out==3) + { + fprintf(stderr, "OpenGL support not enabled at compile time\n"); + exit(-1); + } +#endif +*/ + if( info->video_out < 0 || info->video_out > 4 ) { + fprintf(stderr, "Select a valid output display driver\n"); + exit(-1); + } + } else if (strcmp(name, "B") == 0 || strcmp(name, "features")==0) { + CompiledWith(); + nerr++; + } else if ( strcmp(name, "output-file" ) == 0 || strcmp(name, "o") == 0 ) { + check_val(optarg,name); + veejay_strncpy(info->y4m_file,(char*) optarg, strlen( (char*) optarg)); + } else if (strcmp(name, "preserve-pathnames") == 0 + || strcmp(name, "P") == 0) { + info->preserve_pathnames = 1; + } else if (strcmp(name, "deinterlace") == 0 || strcmp(name, "I" )==0) { + info->auto_deinterlace = 1; + } else if (strcmp(name, "size") == 0 || strcmp(name, "s") == 0) { + if (sscanf(value, "%dx%d", &info->bes_width, &info->bes_height) != + 2) { + mjpeg_error("--size parameter requires NxN argument"); + nerr++; + } + } +#ifdef HAVE_XINERAMA +#ifndef X_DISPLAY_MISSING + else if (strcmp(name, "xinerama") == 0 || strcmp(name, "X") == 0 ) { + x11_user_select( atoi(optarg) ); + } +#endif +#endif + else if (strcmp(name, "action-file")==0 || strcmp(name,"F")==0) { + check_val(optarg,name); + veejay_strncpy(info->action_file[0],(char*) optarg, strlen( (char*) optarg)); + info->load_action_file = 1; + }else if (strcmp(name, "sample-file")==0 || strcmp(name,"l")==0) { + check_val(optarg,name); + veejay_strncpy(info->action_file[1],(char*) optarg, strlen( (char*) optarg)); + info->load_action_file = 1; + } + else if(strcmp(name,"map-from-file") == 0 ) { + info->seek_cache = atoi(optarg); + } + else if (strcmp(name, "geometry-x") == 0 || strcmp(name, "x")==0) { + default_geometry_x = atoi(optarg); + } + else if (strcmp(name, "geometry-y") == 0 || strcmp(name,"y")==0) { + default_geometry_y = atoi(optarg); + } + else if(strcmp(name,"dump-events")==0 || strcmp(name,"u")==0) { + info->dump = 1; + } + else if(strcmp(name, "input-width") == 0 || strcmp(name, "W") == 0 ) { + info->dummy->width = atoi(optarg); + } + else if(strcmp(name, "input-height") == 0 || strcmp(name, "H") == 0 ) { + info->dummy->height = atoi(optarg); + } + else if(strcmp(name, "norm") == 0 || strcmp(name, "N") == 0 ) { + int val = atoi(optarg); + if(val == 1 ) + override_norm = 'n'; + } + else if(strcmp(name, "D") == 0 || strcmp(name, "composite") == 0) + { + info->settings->composite = 0; + } + else if(strcmp(name, "output-width") == 0 || strcmp(name, "w") == 0) { + info->video_output_width = atoi(optarg); + } + else if(strcmp(name, "output-height") == 0 || strcmp(name, "h") == 0) { + info->video_output_height = atoi(optarg); + } + else if(strcmp(name, "audiorate") == 0 || strcmp(name, "r") == 0 ) + { + info->dummy->arate = atoi(optarg); + } + else if (strcmp(name,"fps")==0 || strcmp(name, "f")==0) { + override_fps = atof(optarg); + } + else if(strcmp(name,"yuv")==0 || strcmp(name,"Y")==0) + { + override_pix_fmt = atoi(optarg); + if( override_pix_fmt < 0 || override_pix_fmt > 2 ) + override_pix_fmt = 0; + } + else if(strcmp(name, "swap-range") == 0 || strcmp(name, "e") == 0 ) + { + switch_jpeg = 1; + } + else if( strcmp(name,"auto-loop")==0 || strcmp(name,"L") == 0) + { + auto_loop = 1; + } + else if (strcmp(name, "quit") == 0 || strcmp(name, "q") == 0 ) + { + info->continuous = 0; + } + else if (strcmp(name, "clip-as-sample") == 0 || strcmp(name, "g") == 0 ) + { + info->uc->file_as_sample = 1; + } + else if (strcmp(name, "dummy") == 0 || strcmp(name, "d" ) == 0 ) + { + info->dummy->active = 1; // enable DUMMY MODE + } + else + nerr++; /* unknown option - error */ + + return nerr; +} + +static int check_command_line_options(int argc, char *argv[]) +{ + int nerr, n, option_index = 0; + char option[2]; +#ifdef HAVE_GETOPT_LONG + /* getopt_long options */ + static struct option long_options[] = { + {"verbose", 0, 0, 0}, /* -v/--verbose */ + {"skip", 1, 0, 0}, /* -s/--skip */ + {"synchronization", 1, 0, 0}, /* -c/--synchronization */ + {"preserve-pathnames", 0, 0, 0}, /* -P/--preserve-pathnames */ + {"audio", 1, 0, 0}, /* -a/--audio num */ + {"size", 1, 0, 0}, /* -S/--size */ +/*#ifdef HAVE_XINERAMA +#ifndef X_DISPLAY_MISSING + {"xinerama",1,0,0}, +#endif +#endif +*/ + {"graphics-driver", 1, 0, 0}, + {"timer", 1, 0, 0}, /* timer */ + {"dump-events",0,0,0}, + {"bezerk",0,0,0}, + {"sample-file",1,0,0}, + {"action-file",1,0,0}, + {"features",0,0,0}, + {"deinterlace",0,0,0}, + {"clip-as-sample",0,0,0}, + {"port", 1, 0, 0}, + {"sample-mode",1,0,0}, + {"dummy",0,0,0}, + {"geometry-x",1,0,0}, + {"geometry-y",1,0,0}, + {"auto-loop",0,0,0}, + {"fps",1,0,0}, + {"no-color",0,0,0}, + {"version",0,0,0}, + {"input-width",1,0,0}, + {"input-height",1,0,0}, + {"output-width", 1,0,0 }, + {"output",1,0,0}, + {"output-file",1,0,0}, + {"output-height", 1,0,0 }, + {"norm",1,0,0}, + {"audiorate",1,0,0}, + {"yuv",1,0,0}, + {"multicast-osc",1,0,0}, + {"multicast-vims",1,0,0}, + {"map-from-file",1,0,0}, + {"composite",0,0,0}, + {"quit",0,0,0}, + {"memory",1,0,0}, + {"max_cache",1,0,0}, + {"capture-device",1,0,0}, + {"swap-range",0,0,0}, + {0, 0, 0, 0} + }; +#endif + if (argc < 2) { + Usage(argv[0]); + return 0; + } + +/* Get options */ + nerr = 0; +#ifdef HAVE_GETOPT_LONG + while ((n = + getopt_long(argc, argv, + "o:G:O:a:H:s:c:t:j:l:p:m:h:w:x:y:r:f:Y:A:N:H:W:M:T:F:nILPVDugvBdibjqe", + long_options, &option_index)) != EOF) +#else + while ((n = + getopt(argc, argv, + "o:G:O:a:H:s:c:t:j:l:p:m:h:w:x:y:r:f:Y:A:N:H:W:M:T:F:nILPVDugvBdibjqe" + )) != EOF) +#endif + { + switch (n) { +#ifdef HAVE_GETOPT_LONG + /* getopt_long values */ + case 0: + nerr += set_option(long_options[option_index].name, optarg); + break; +#endif + + /* These are the old getopt-values (non-long) */ + default: + sprintf(option, "%c", n); +#ifdef STRICT_CHECKING + { + int tmpn = set_option( option,optarg ); + if(tmpn) + veejay_msg(VEEJAY_MSG_ERROR, "Error setting option '%c'", option ); + nerr += tmpn; + } +#else + nerr += set_option(option, optarg); +#endif + break; + } + + } + if (optind > argc) + nerr++; + + if (nerr) + Usage(argv[0]); + + veejay_set_debug_level(info->verbose); + mjpeg_default_handler_verbosity( (info->verbose ? 1:0) ); + + if(!info->dump) + { + if(veejay_open_files( + info, + argv + optind, + argc - optind, + override_fps, + force_video_file, + override_pix_fmt, + override_norm, + switch_jpeg )<=0) + { + vj_el_show_formats(); + veejay_msg(VEEJAY_MSG_ERROR, "Unable to open video file(s), codec/format not supported)"); + nerr++; + } + } + + if(!nerr) + return 1; + return 0; +} + +static void print_license() +{ + veejay_msg(VEEJAY_MSG_INFO, + "Veejay -<|Classic +|>- %s Copyright (C) Niels Elburg and others",VERSION); + veejay_msg(VEEJAY_MSG_INFO, + "Build for %s/%s arch %s on %s", + BUILD_OS, + BUILD_KERNEL, + BUILD_MACHINE, + BUILD_DATE ); + veejay_msg(VEEJAY_MSG_INFO, + "This software is subject to the GNU GENERAL PUBLIC LICENSE"); + + veejay_msg(VEEJAY_MSG_INFO, + "Veejay comes with ABSOLUTELY NO WARRANTY; this is free software and"); + veejay_msg(VEEJAY_MSG_INFO, + "you are welcome to redistribute it under certain conditions."); + veejay_msg(VEEJAY_MSG_INFO, + "The license must be included in the (source) package (COPYING)"); +} + +static void donothing(int sig) +{ + vj_lock(info); + veejay_handle_signal( info, sig ); + vj_unlock(info); +} + +static void sigsegfault_handler(void) { + struct sigaction sigst; + sigst.sa_sigaction = veejay_backtrace_handler; + sigemptyset(&sigst.sa_mask); + sigaddset(&sigst.sa_mask, SIGSEGV ); + sigst.sa_flags = SA_SIGINFO | SA_ONESHOT; + if( sigaction(SIGSEGV, &sigst, NULL == - 1) ) + veejay_msg(0,"sigaction"); +} + +int main(int argc, char **argv) +{ + video_playback_setup *settings; + char *dont_use; + sigset_t allsignals; + struct sigaction action; + struct sched_param schp; + int i; + fflush(stdout); + + vj_mem_init(); + vevo_strict_init(); + + info = veejay_malloc(); + if (!info) + return 1; + + settings = (video_playback_setup *) info->settings; + + if(!check_command_line_options(argc, argv)) + { + veejay_free(info); + return 0; + } + + + if(info->dump) + { + veejay_set_colors(0); + vj_event_init(); + vj_effect_initialize(720,576,0); + vj_osc_allocate(VJ_PORT+2); + vj_event_dump(); + vj_effect_dump(); + fprintf(stdout, "Environment variables:\n\tSDL_VIDEO_HWACCEL\t\tSet to 1 to use SDL video hardware accel (default=on)\n\tVEEJAY_PERFORMANCE\t\tSet to \"quality\" or \"fastest\" (default is fastest)\n\tVEEJAY_AUTO_SCALE_PIXELS\tSet to 1 to convert between CCIR 601 and JPEG automatically (default=dont care)\n\tVEEJAY_INTERPOLATE_CHROMA\tSet to 1 if you wish to interpolate every chroma sample when scaling (default=0)\n\tVEEJAY_CAPTURE_DRIVER\t\tSet to \"unicap\" or \"v4lutils\" (default=v4lutils)\n\tVEEJAY_SDL_KEY_REPEAT_INTERVAL\tinterval of key pressed to repeat while pressed down.\n\tVEEJAY_PLAYBACK_CACHE\t\tSample cache size in MB - by default, veejay takes 30 percent of total RAM\n\tVEEJAY_SDL_KEY_REPEAT_DELAY\tDelay key repeat in ms\n\tVEEJAY_FULLSCREEN\t\tStart in fullscreen (1) or windowed (0) mode\n\tVEEJAY_SCREEN_GEOMETRY\t\tSpecifiy a geometry for veejay to position the video window.\n\tVEEJAY_SCREEN_SIZE\t\tSize of video window, defaults to full screen size.\n\tVEEJAY_RUN_MODE\t\t\tRun in \"classic\" (352x288 Dummy) or default (720x576). \n"); + fprintf(stdout, "\n\n\tExample for bash:\n\t\t\t$ export VEEJAY_AUTO_SCALE_PIXEL=1\n"); + + + veejay_free(info); + return 0; + } + + if( vj_el_get_mem_size() == 0 ) + prepare_cache_line( max_mem_, n_slots_ ); + veejay_check_homedir( info ); + + sigsegfault_handler(); + + sigemptyset(&(settings->signal_set)); + sigaddset(&(settings->signal_set), SIGINT); + sigaddset(&(settings->signal_set), SIGPIPE); + sigaddset(&(settings->signal_set), SIGILL); +// sigaddset(&(settings->signal_set), SIGSEGV); + sigaddset(&(settings->signal_set), SIGFPE ); + sigaddset(&(settings->signal_set), SIGTERM ); + sigaddset(&(settings->signal_set), SIGABRT); + sigaddset(&(settings->signal_set), SIGPWR ); + sigaddset(&(settings->signal_set), SIGQUIT ); + + sigfillset( &allsignals ); + action.sa_handler = donothing; + action.sa_mask = allsignals; + action.sa_flags = SA_SIGINFO | SA_ONESHOT ; //SA_RESTART | SA_RESETHAND; + + signal( SIGPIPE, SIG_IGN ); + + for( i = 1; i < NSIG; i ++ ) + if( sigismember( &(settings->signal_set), i )) + sigaction( i, &action, 0 ); + + char *mem_func = get_memcpy_descr(); + if(mem_func) + { + veejay_msg(VEEJAY_MSG_INFO, "Using SIMD %s", mem_func); + free(mem_func); + } + + if(veejay_init( + info, + default_geometry_x, + default_geometry_y, + NULL, + live )< 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot start Vveejay"); + return 0; + } + + if(auto_loop) + veejay_auto_loop(info); + + print_license(); + + if(!veejay_main(info)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot start main playback cycle"); + return 1; + } + + + veejay_msg(VEEJAY_MSG_DEBUG, "Started playback"); + +// veejay_set_frame(info, 0); +// veejay_set_speed(info, 1); + + int sig; + int current_state = LAVPLAY_STATE_PLAYING; + + while( 1 ) { //@ until your PC stops working + + usleep(50000); + vj_lock(info); + current_state = veejay_get_state(info); + vj_unlock(info); + if( current_state == LAVPLAY_STATE_STOP ) + break; + } + + veejay_quit(info); + veejay_busy(info); + veejay_free(info); + + veejay_msg(VEEJAY_MSG_INFO, "Thank you for using Veejay"); + + return 0; +} diff --git a/branches/V-1.5.3/veejay-server/veejay/veejay.h b/branches/V-1.5.3/veejay-server/veejay/veejay.h new file mode 100644 index 00000000..b4e3fb22 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/veejay.h @@ -0,0 +1,26 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002 Niels Elburg < elburg@hio.hen.nl> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + * + * + */ + + + +#define MIN_EFFECTS 1 +#define MAX_REALTIME_EFFECTS 10 diff --git a/branches/V-1.5.3/veejay-server/veejay/vevo.h b/branches/V-1.5.3/veejay-server/veejay/vevo.h new file mode 100644 index 00000000..268e7065 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vevo.h @@ -0,0 +1,54 @@ +/* veejay - Linux VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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. + */ +#ifndef VEVO_H_INC +#define VEVO_H_INC + +#ifndef HAVE_LIVIDO_PORT_T +#define HAVE_LIVIDO_PORT_T +typedef struct livido_port_t void +#endif + +#include + +// rename functions +/* +#define vevo_port_free livido_port_free +#define vevo_port_new livido_port_new +#define vevo_property_set livido_property_set +#define vevo_property_get livido_property_get +#define vevo_property_element_size livido_property_element_size +#define vevo_property_num_elements livido_property_num_elements +#define vevo_property_atom_type livido_property_atom_type +#define vevo_list_properties livido_list_properties*/ + +void *vj_event_vevo_get_event_function( int id ); +char *vj_event_vevo_get_event_name( int id ); +char *vj_event_vevo_get_event_format( int id ); +int vj_event_vevo_get_num_args(int id); +int vj_event_vevo_get_flags( int id ); +int vj_event_vevo_get_vims_id( int id ); +void vj_init_vevo_events(void); +void vj_event_vevo_inline_fire_default( void *super, int vims_id, const char *format ); +void vj_event_vevo_inline_fire(void *super, int vims_id, const char *format, ... ); +char *vj_event_vevo_list_serialize(void); +void vj_event_vevo_dump(void); +char *vj_event_vevo_help_vims( int id, int n ); +int vj_event_vevo_get_default_value(int id, int p); +void vj_event_vevo_free(void); +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vims.h b/branches/V-1.5.3/veejay-server/veejay/vims.h new file mode 100644 index 00000000..5bb580b8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vims.h @@ -0,0 +1,317 @@ +/* veejay - Linux VeeJay + * (C) 2002-2008 Niels Elburg + * + * + * 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. + */ +#ifndef VIMS_H +#define VIMS_H + +enum { + VIMS_BUNDLE_START = 500, + VIMS_BUNDLE_END = 599, + VIMS_MAX = 602, +}; + +enum { + VIMS_FXLIST_INC = 1, + VIMS_FXLIST_DEC = 2, + VIMS_FXLIST_ADD = 3, + VIMS_PRINT_INFO = 4, + VIMS_PREVIEW_BW = 8, + VIMS_VIEWPORT = 9, + VIMS_FRONTBACK = 6, + VIMS_PROJECTION = 7, + VIMS_COMPOSITE = 47, + VIMS_RENDER_DEPTH = 48, + VIMS_MACRO = 33, + VIMS_MACRO_SELECT = 34, + VIMS_CONTINUOUS_PLAY = 35, + VIMS_RECVIEWPORT = 90, + VIMS_VIDEO_INFORMATION = 400, + VIMS_EFFECT_LIST = 401, + VIMS_EDITLIST_LIST = 402, + VIMS_BUNDLE_LIST = 403, + VIMS_STREAM_LIST = 405, + VIMS_STREAM_DEVICES = 406, + VIMS_SAMPLE_HISTORY_LIST = 407, + VIMS_SAMPLE_LIST = 408, + VIMS_STREAM_GET_V4L = 409, + VIMS_CHAIN_GET_ENTRY = 410, + VIMS_VIMS_LIST = 411, + VIMS_LOG = 412, + VIMS_SAMPLE_INFO = 413, + VIMS_SAMPLE_OPTIONS = 414, + VIMS_DEVICE_LIST = 415, + VIMS_FONT_LIST = 416, + VIMS_SRT_LIST = 417, + VIMS_SRT_INFO = 418, + VIMS_TRACK_LIST = 5, + VIMS_SEQUENCE_LIST = 419, + VIMS_KEYLIST = 420, + VIMS_WORKINGDIR = 421, + VIMS_SAMPLE_STACK = 422, + VIMS_SET_VOLUME = 300, + VIMS_FULLSCREEN = 301, + VIMS_SUSPEND = 254, + VIMS_QUIT = 600, + VIMS_CLOSE = 601, + VIMS_LOAD_PLUGIN = 310, + VIMS_UNLOAD_PLUGIN = 311, + VIMS_CMD_PLUGIN = 312, + VIMS_RECORD_DATAFORMAT = 302, + VIMS_SET_PLAIN_MODE = 303, + VIMS_INIT_GUI_SCREEN = 304, + VIMS_SWITCH_SAMPLE_STREAM = 305, + VIMS_AUDIO_ENABLE = 306, + VIMS_AUDIO_DISABLE = 307, + VIMS_SELECT_BANK = 308, + VIMS_SELECT_ID = 309, + VIMS_SAMPLE_RAND_START = 315, + VIMS_SAMPLE_RAND_STOP = 316, + VIMS_REC_AUTO_START = 320, + VIMS_REC_STOP = 321, + VIMS_REC_START = 322, + VIMS_EFFECT_SET_BG = 339, + VIMS_SAMPLE_MODE = 323, + VIMS_BEZERK = 324, + VIMS_DEBUG_LEVEL = 325, + VIMS_RESIZE_SDL_SCREEN = 326, + VIMS_SET_PLAY_MODE = 327, + VIMS_SET_MODE_AND_GO = 328, + VIMS_RGB_PARAMETER_TYPE = 329, + VIMS_SCREENSHOT = 330, + VIMS_NO_CACHING = 331, + VIMS_RGB24_IMAGE = 333, + VIMS_CALI_IMAGE = 332, + VIMS_SYNC_CORRECTION = 334, + VIMS_FRAMERATE = 335, + VIMS_VIDEO_PLAY_FORWARD = 10, + VIMS_VIDEO_PLAY_BACKWARD = 11, + VIMS_VIDEO_PLAY_STOP = 12, + VIMS_VIDEO_SKIP_FRAME = 13, + VIMS_VIDEO_PREV_FRAME = 14, + VIMS_VIDEO_SKIP_SECOND = 15, + VIMS_VIDEO_PREV_SECOND = 16, + VIMS_VIDEO_GOTO_START = 17, + VIMS_VIDEO_GOTO_END = 18, + VIMS_VIDEO_SET_FRAME = 19, + VIMS_VIDEO_SET_SPEED = 20, + VIMS_VIDEO_SET_SLOW = 21, + VIMS_VIDEO_MCAST_START = 22, + VIMS_VIDEO_MCAST_STOP = 23, + VIMS_VIDEO_SET_SPEEDK = 24, + VIMS_EDITLIST_PASTE_AT = 50, + VIMS_EDITLIST_COPY = 51, + VIMS_EDITLIST_DEL = 52, + VIMS_EDITLIST_CROP = 53, + VIMS_EDITLIST_CUT = 54, + VIMS_EDITLIST_ADD = 55, + VIMS_EDITLIST_ADD_SAMPLE = 56, + VIMS_EDITLIST_SAVE = 58, + VIMS_EDITLIST_LOAD = 59, + VIMS_BUNDLE = 80, + VIMS_BUNDLE_DEL = 81, + VIMS_BUNDLE_ADD = 82, + VIMS_BUNDLE_ATTACH_KEY = 83, + VIMS_BUNDLE_FILE = 84, + VIMS_BUNDLE_SAVE = 85, + VIMS_BUNDLE_CAPTURE = 86, + VIMS_SET_SAMPLE_START = 150, + VIMS_SET_SAMPLE_END = 151, + VIMS_SAMPLE_NEW = 100, + VIMS_SAMPLE_SELECT = 101, + VIMS_SAMPLE_DEL = 120, + VIMS_SAMPLE_SET_LOOPTYPE = 102, + VIMS_SAMPLE_SET_DESCRIPTION = 103, + VIMS_SAMPLE_SET_SPEED = 104, + VIMS_SAMPLE_SET_START = 105, + VIMS_SAMPLE_SET_END = 106, + VIMS_SAMPLE_SET_DUP = 107, + VIMS_SAMPLE_SET_MARKER_START = 108, + VIMS_SAMPLE_SET_MARKER_END = 109, + VIMS_SAMPLE_SET_MARKER = 110, + VIMS_SAMPLE_CLEAR_MARKER = 111, + VIMS_SAMPLE_LOAD_SAMPLELIST = 125, + VIMS_SAMPLE_SAVE_SAMPLELIST = 126, + VIMS_SAMPLE_DEL_ALL = 121, + VIMS_SAMPLE_COPY = 127, + VIMS_SAMPLE_REC_START = 130, + VIMS_SAMPLE_REC_STOP = 131, + VIMS_SAMPLE_CHAIN_ENABLE = 112, + VIMS_SAMPLE_CHAIN_DISABLE = 113, + VIMS_SAMPLE_UPDATE = 143, + VIMS_SAMPLE_TOGGLE_LOOP = 144, + VIMS_SAMPLE_KF_STATUS = 145, + VIMS_SAMPLE_KF_GET = 146, + VIMS_SAMPLE_KF_RESET = 147, + VIMS_STREAM_COLOR = 202, + VIMS_STREAM_SELECT = 201, + VIMS_STREAM_ACTIVATE = 205, + VIMS_STREAM_DEACTIVATE = 206, + VIMS_STREAM_DELETE = 220, + VIMS_STREAM_NEW_V4L = 240, + VIMS_STREAM_NEW_DV1394 = 241, + VIMS_STREAM_NEW_COLOR = 242, + VIMS_STREAM_NEW_Y4M = 243, + VIMS_STREAM_NEW_CALI = 244, + VIMS_V4L_BLACKFRAME = 248, + VIMS_V4L_CALI = 249, + VIMS_STREAM_NEW_UNICAST = 245, + VIMS_STREAM_NEW_MCAST = 246, + VIMS_STREAM_NEW_PICTURE = 247, + VIMS_STREAM_OFFLINE_REC_START = 228, + VIMS_STREAM_OFFLINE_REC_STOP = 229, + VIMS_STREAM_REC_START = 230, + VIMS_STREAM_REC_STOP = 231, + VIMS_STREAM_CHAIN_ENABLE = 212, + VIMS_STREAM_CHAIN_DISABLE = 213, + VIMS_STREAM_SET_DESCRIPTION = 203, + VIMS_STREAM_SET_BRIGHTNESS = 207, + VIMS_STREAM_SET_CONTRAST = 208, + VIMS_STREAM_SET_HUE = 209, + VIMS_STREAM_SET_COLOR = 210, + VIMS_STREAM_SET_WHITE = 211, + VIMS_STREAM_SET_SATURATION = 215, + VIMS_STREAM_SET_LENGTH = 212, + VIMS_SEQUENCE_STATUS = 340, + VIMS_SEQUENCE_ADD = 341, + VIMS_SEQUENCE_DEL = 342, + VIMS_PROJ_INC = 160, + VIMS_PROJ_DEC = 161, + VIMS_PROJ_SET_POINT = 162, + VIMS_PROJ_GET_POINT = 163, + VIMS_PROJ_STACK = 164, + VIMS_PROJ_TOGGLE = 165, + VIMS_CHAIN_ENTRY_CHANNEL_INC = 350, + VIMS_CHAIN_ENTRY_CHANNEL_DEC = 351, + VIMS_CHAIN_TOGGLE_ALL = 352, + VIMS_CHAIN_ENABLE = 353, + VIMS_CHAIN_DISABLE = 354, + VIMS_CHAIN_CLEAR = 355, + VIMS_CHAIN_FADE_IN = 356, + VIMS_CHAIN_FADE_OUT = 357, + VIMS_CHAIN_LIST = 358, + VIMS_CHAIN_SET_ENTRY = 359, + VIMS_CHAIN_ENTRY_SET_EFFECT = 360, + VIMS_CHAIN_ENTRY_SET_PRESET = 361, + VIMS_CHAIN_ENTRY_SET_ARG_VAL = 362, + VIMS_CHAIN_ENTRY_SET_VIDEO_ON = 363, + VIMS_CHAIN_ENTRY_SET_VIDEO_OFF = 364, + VIMS_CHAIN_ENTRY_SET_DEFAULTS = 365, + VIMS_CHAIN_ENTRY_SET_CHANNEL = 366, + VIMS_CHAIN_ENTRY_SET_SOURCE = 367, + VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL = 368, + VIMS_CHAIN_ENTRY_CLEAR = 369, + VIMS_CHAIN_MANUAL_FADE = 370, + VIMS_CHAIN_ENTRY_DOWN = 371, + VIMS_CHAIN_ENTRY_UP = 372, + VIMS_CHAIN_ENTRY_SOURCE_TOGGLE = 373, + VIMS_CHAIN_ENTRY_INC_ARG = 374, + VIMS_CHAIN_ENTRY_DEC_ARG = 375, + VIMS_CHAIN_TOGGLE = 376, + VIMS_CHAIN_ENTRY_SET_STATE = 377, + VIMS_ENTRY_CHANNEL_UP = 378, + VIMS_ENTRY_CHANNEL_DOWN = 379, + VIMS_ENTRY_VIDEO_TOGGLE = 380, + VIMS_ENTRY_SOURCE_TOGGLE = 381, + VIMS_CHAIN_FOLLOW_FADE = 382, + VIMS_OSD_EXTRA = 388, + VIMS_COPYRIGHT = 389, + VIMS_FONT_POS = 390, + VIMS_FONT_COL = 391, + VIMS_FONT_SIZE_FONT = 392, + VIMS_SRT_ADD = 393, + VIMS_SRT_DEL = 394, + VIMS_SRT_UPDATE = 395, + VIMS_SRT_SAVE = 396, + VIMS_SRT_LOAD = 397, + VIMS_SRT_SELECT = 398, + VIMS_OSD = 399, + VIMS_OUTPUT_Y4M_START = 40, + VIMS_OUTPUT_Y4M_STOP = 41, + VIMS_GET_FRAME = 42, + VIMS_VLOOPBACK_START = 45, + VIMS_VLOOPBACK_STOP = 46, +}; + + +enum { + VJ_PLAYBACK_MODE_PLAIN = 2, + VJ_PLAYBACK_MODE_SAMPLE = 0, + VJ_PLAYBACK_MODE_PATTERN = 3, + VJ_PLAYBACK_MODE_TAG = 1, + VJ_PLAYBACK_MODE_MEM = 4, +}; + +enum { + VJ_MAX_V4L_DEVICES = 2, + VJ_MAX_IN_STREAMS = 4, + VJ_MAX_OUT_STREAMS = 1, + VJ_MAX_VLOOPBACK_PIPES = 8, +}; + +/* request messages, global */ +#define MAX_SEQUENCES 100 +#define MAX_SPEED 12 +#define SAMPLE_MAX_EFFECTS 20 +#define PATTERN_MAX_TRACKS 3 +#define CELL_LENGTH 30 +#define ROW_SIZE (PATTERN_MAX_TRACKS * CELL_LENGTH) +#define PATTERN_DEFAULT_LENGTH (25*60) +#define EDIT_CUT 101 +#define EDIT_PASTE_AT 102 +#define EDIT_COPY 103 +#define EDIT_CROP 104 +#define EDIT_DEL 105 +#define MESSAGE_SIZE 1024 +#define EL_MIN_BUF (65535 * 4) +#define XMLTAG_BUNDLE_FILE "ACTIONFILE" +#define XMLTAG_EVENT_AS_KEY "BUNDLE" +#define SOCKETFRAMELEN (1024*4096) +#define FMT_420 0 +#define FMT_420F 2 +#define FMT_422 1 +#define FMT_422F 3 + +#define VEEJAY_PORT_CMD 0 +#define VEEJAY_PORT_STA 1 +#define VEEJAY_PORT_DAT 3 +#define VEEJAY_PORT_MAT 2 + +#define FMT_RGB24 2 +#define FMT_RGB32 1 + +#define MAX_EDIT_LIST_FILES 4096 + +#define VSOCK_S 0 +#define VSOCK_C 1 +#define V_STATUS 0 +#define V_CMD 1 +#define VMCAST_S 4 +#define VMCAST_C 5 + +enum +{ + VJ_CMD_PORT=0, + VJ_STA_PORT=1, + VJ_CMD_MCAST=3, + VJ_CMD_MCAST_IN=4, + VJ_MSG_PORT=5, + VJ_CMD_OSC=2, +}; + + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-OSC.h b/branches/V-1.5.3/veejay-server/veejay/vj-OSC.h new file mode 100644 index 00000000..54e2cf42 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-OSC.h @@ -0,0 +1,31 @@ +/* + * veejay - Linux VeeJay + * (C) 2003 Niels Elburg + * + * + * 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. + */ + +#ifndef VJ_OSC +#define VJ_OSC + + +int vj_osc_setup_addr_space(void *o); +int vj_osc_get_packet(void *o); +void vj_osc_free(void *o); +void vj_osc_dump(); +void* vj_osc_allocate(int port_id); + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-audio.c b/branches/V-1.5.3/veejay-server/veejay/vj-audio.c new file mode 100644 index 00000000..5eb511c0 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-audio.c @@ -0,0 +1,491 @@ +/* + * JACK audio output driver for MPlayer + * + * Copyleft 2001 by Felix Bĵnemann (atmosfear@users.sf.net) + * and Reimar Dĥffinger (Reimar.Doeffinger@stud.uni-karlsruhe.de) + * + * This file is part of MPlayer. + * Modified by Niels Elburg for the Veejay project, April 2009 + * + * MPlayer 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. + * + * MPlayer 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 + * along with MPlayer; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* + * a very simple circular buffer FIFO implementation + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * Copyright (c) 2006 Roman Shaposhnik + * + * This file is part of FFmpeg. + */ + +#include +#ifdef HAVE_JACK +#include +#include +#include +#include +#include +#include +#define FFMIN(a,b) ((a) > (b) ? (b) : (a)) + +#define MAX_CHANS 2 +#define CHUNK_SIZE (16*1024) +#define NUM_CHUNKS 8 +#define BUFFSIZE (NUM_CHUNKS * CHUNK_SIZE) +typedef struct AVFifoBuffer { + uint8_t *buffer; + uint8_t *rptr, *wptr, *end; + uint32_t rndx, wndx; +} AVFifoBuffer; + +struct deinterleave { + float **bufs; + int num_bufs; + int cur_buf; + int pos; +}; + +static jack_port_t *ports[MAX_CHANS]; +static int num_ports = 0; +static jack_client_t *client = NULL; +static float latency =0; +static int estimate = 1; +static int bps = 0; +static int audio_rate = 0; +static int paused = 0; +static int underrun = 0; +static float callback_interval = 0; +static float callback_time = 0; +static AVFifoBuffer *buffer = NULL; +static struct timeval callbackTime; +static long bytes_buffered = 0; + +static void av_fifo_reset(AVFifoBuffer *f); +static int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); +static void av_fifo_drain(AVFifoBuffer *f, int size); +static void silence(float **bufs, int cnt, int num_bufs); +static unsigned int GetTimer(void); +static int usec_sleep(int usec_delay); + +static AVFifoBuffer *av_fifo_alloc(unsigned int size) +{ + AVFifoBuffer *f= (AVFifoBuffer*)vj_calloc(sizeof(AVFifoBuffer)); + if(!f) + return NULL; + f->buffer = (uint8_t*)vj_malloc(size); + f->end = f->buffer + size; + av_fifo_reset(f); + if (!f->buffer) + av_freep(&f); + return f; +} + +static inline uint8_t av_fifo_peek(AVFifoBuffer *f, int offs) +{ + uint8_t *ptr = f->rptr + offs; + if (ptr >= f->end) + ptr -= f->end - f->buffer; + return *ptr; +} +static void av_fifo_free(AVFifoBuffer *f) +{ + if(f){ + free(f->buffer); + free(f); + } +} +static void av_fifo_reset(AVFifoBuffer *f) +{ + f->wptr = f->rptr = f->buffer; + f->wndx = f->rndx = 0; +} +static int av_fifo_size(AVFifoBuffer *f) +{ + return (uint32_t)(f->wndx - f->rndx); +} + +static int av_fifo_space(AVFifoBuffer *f) +{ + return f->end - f->buffer - av_fifo_size(f); +} +static int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) { + unsigned int old_size= f->end - f->buffer; + + if(old_size < new_size){ + int len= av_fifo_size(f); + AVFifoBuffer *f2= av_fifo_alloc(new_size); + + if (!f2) + return -1; + av_fifo_generic_read(f, f2->buffer, len, NULL); + f2->wptr += len; + f2->wndx += len; + av_free(f->buffer); + *f= *f2; + av_free(f2); + } + return 0; +} +static int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)) +{ + int total = size; + do { + int len = FFMIN(f->end - f->wptr, size); + if(func) { + if(func(src, f->wptr, len) <= 0) + break; + } else { + veejay_memcpy(f->wptr, src, len); + src = (uint8_t*)src + len; + } +// Write memory barrier needed for SMP here in theory + f->wptr += len; + if (f->wptr >= f->end) + f->wptr = f->buffer; + f->wndx += len; + size -= len; + } while (size > 0); + return total - size; +} +static int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)) +{ +// Read memory barrier needed for SMP here in theory + do { + int len = FFMIN(f->end - f->rptr, buf_size); + if(func) func(dest, f->rptr, len); + else{ + veejay_memcpy(dest, f->rptr, len); + dest = (uint8_t*)dest + len; + } +// memory barrier needed for SMP here in theory + av_fifo_drain(f, len); + buf_size -= len; + } while (buf_size > 0); + return 0; +} + +/** Discard data from the FIFO. */ +static void av_fifo_drain(AVFifoBuffer *f, int size) +{ + f->rptr += size; + if (f->rptr >= f->end) + f->rptr -= f->end - f->buffer; + f->rndx += size; +} + + +static int write_buffer(unsigned char* data, int len) { + int free = av_fifo_space(buffer); + if (len > free) len = free; + int res = av_fifo_generic_write(buffer,data,len,NULL ); + return res; +} + +static void deinterleave(void *info, void *src, int len) { + struct deinterleave *di = info; + float *s = src; + int i; + len /= sizeof(float); + for (i = 0; i < len; i++) { + di->bufs[di->cur_buf++][di->pos] = s[i]; + if (di->cur_buf >= di->num_bufs) { + di->cur_buf = 0; + di->pos++; + } + } +} + +/** + * \brief read data from buffer and splitting it into channels + * \param bufs num_bufs float buffers, each will contain the data of one channel + * \param cnt number of samples to read per channel + * \param num_bufs number of channels to split the data into + * \return number of samples read per channel, equals cnt unless there was too + * little data in the buffer + * + * Assumes the data in the buffer is of type float, the number of bytes + * read is res * num_bufs * sizeof(float), where res is the return value. + * If there is not enough data in the buffer remaining parts will be filled + * with silence. + */ +static int read_buffer(float **bufs, int cnt, int num_bufs) { + struct deinterleave di = {bufs, num_bufs, 0, 0}; + int buffered = av_fifo_size(buffer); + if (cnt * sizeof(float) * num_bufs > buffered) { + silence(bufs, cnt, num_bufs); + cnt = buffered / sizeof(float) / num_bufs; + } + av_fifo_generic_read(buffer, &di, cnt * num_bufs * sizeof(float), deinterleave); + return cnt; +} + +static void silence(float **bufs, int cnt, int num_bufs) { + int i; + for (i = 0; i < num_bufs; i++) + veejay_memset(bufs[i], 0, cnt * sizeof(float)); +} +/** + * \brief JACK Callback function + * \param nframes number of frames to fill into buffers + * \param arg unused + * \return currently always 0 + * + * Write silence into buffers if paused or an underrun occured + */ +static int outputaudio(jack_nframes_t nframes, void *arg) { + float *bufs[MAX_CHANS]; + int i; + + gettimeofday(&callbackTime,NULL); + + veejay_msg(0, "write to jack at time: %ld,%ld", + callbackTime.tv_sec,callbackTime.tv_usec); + + for (i = 0; i < num_ports; i++) + bufs[i] = jack_port_get_buffer(ports[i], nframes); + + if (paused || underrun) + silence(bufs, nframes, num_ports); + else + if (read_buffer(bufs, nframes, num_ports) < nframes) + underrun = 1; + + if (estimate) { + float now = (float)GetTimer() / 1000000.0; + float diff = callback_time + callback_interval - now; + if ((diff > -0.002) && (diff < 0.002)) + callback_time += callback_interval; + else + callback_time = now; + callback_interval = (float)nframes / (float)audio_rate; + } + + bytes_buffered += (nframes * 4); + return 0; +} + +int audio_init(int rate, int channels, char *port_name, char *client_name) { + const char **matching_ports = NULL; + int autostart = 0; + estimate = 0; +// jack_options_t open_options = JackUseExactName; + jack_options_t open_options = JackNullOption; + jack_status_t status; + int port_flags = JackPortIsInput; + int i; + +//@ server_name specificed ? open_options |= JackServerName + + if (channels > MAX_CHANS) { + veejay_msg(0, "[JACK] Invalid number of channels: %i\n", channels ); + goto err_out; + } + + if (!autostart) + open_options |= JackNoStartServer; + + client = jack_client_open(client_name, open_options,&status, NULL); + if (!client) { + veejay_msg(0, "[JACK] cannot open server status = 0x%2.0x", status); + goto err_out; + } + if( status & JackServerStarted) { + veejay_msg(VEEJAY_MSG_INFO, "Jack Server started"); + } + if( status & JackNameNotUnique) { + veejay_msg(VEEJAY_MSG_INFO, "Client name not unique, could use ", + jack_get_client_name(client)); + } + + buffer = av_fifo_alloc(BUFFSIZE); + jack_set_process_callback(client, outputaudio, 0); + + // list matching ports + if (!port_name) + port_flags |= JackPortIsPhysical; + + veejay_msg(VEEJAY_MSG_DEBUG, "Jack client: %s, port %s", client_name, port_name ); + + matching_ports = jack_get_ports(client, port_name, NULL, port_flags); + if (!matching_ports || !matching_ports[0]) { + veejay_msg(0, "[JACK] no physical ports available\n"); + goto err_out; + } + + i = 1; + while (matching_ports[i]) i++; + if (channels > i) channels = i; + num_ports = channels; + + // create out output ports + for (i = 0; i < num_ports; i++) { + char pname[30]; + snprintf(pname, 30, "output_%d", i); + ports[i] = jack_port_register(client, pname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + if (!ports[i]) { + veejay_msg(0, "[JACK] not enough ports available\n"); + goto err_out; + } + } + if (jack_activate(client)) { + veejay_msg(0,"[JACK] activate failed\n"); + goto err_out; + } + for (i = 0; i < num_ports; i++) { + if (jack_connect(client, jack_port_name(ports[i]), matching_ports[i])) { + veejay_msg(0, "[JACK] connecting failed\n"); + goto err_out; + } + } + rate = jack_get_sample_rate(client); + latency = (float)(jack_port_get_total_latency(client, ports[0]) + + jack_get_buffer_size(client)) / (float)rate; + callback_interval = 0; +/* + ao_data.channels = channels; + ao_data.samplerate = rate; + ao_data.format = AF_FORMAT_FLOAT_NE; + ao_data.bps = channels * rate * sizeof(float); + ao_data.buffersize = CHUNK_SIZE * NUM_CHUNKS; + ao_data.outburst = CHUNK_SIZE; +*/ + bps = channels * rate * sizeof(float); + audio_rate = rate; + veejay_msg(0, "Channels:%d, Rate:%d, BPS:%d, BufferSize: %d, OutBurst:%d", + channels,rate,channels*rate*sizeof(float), CHUNK_SIZE*NUM_CHUNKS, CHUNK_SIZE ); + + free(matching_ports); + //free(port_name); + //free(client_name); + return 1; + +err_out: + if( matching_ports ) + free(matching_ports); +// free(port_name); +// free(client_name); + if (client) + jack_client_close(client); + av_fifo_free(buffer); + buffer = NULL; + return 0; +} + +// close audio device +void audio_uninit(int immed) {//@FIXME NULL + struct timeval tv; + if (!immed) + usec_sleep(audio_get_delay(tv) * 1000 * 1000); + // HACK, make sure jack doesn't loop-output dirty buffers + audio_reset(); + usec_sleep(100 * 1000); + jack_client_close(client); + av_fifo_free(buffer); + buffer = NULL; +} + +/** + * \brief stop playing and empty buffers (for seeking/pause) + */ +void audio_reset(void) { + paused = 1; + av_fifo_reset(buffer); + paused = 0; +} + +/** + * \brief stop playing, keep buffers (for pause) + */ +void audio_pause(void) { + paused = 1; +} + + +void audio_continue(int speed) +{ + if( speed == 0 ) + audio_pause; + else + audio_resume; +} + +/** + * \brief resume playing, after audio_pause() + */ +void audio_resume(void) { + paused = 0; +} + +static int get_space(void) { + return av_fifo_space(buffer); +} +#define AOPLAY_FINAL_CHUNK 1 +/** + * \brief write data into buffer and reset underrun flag + */ +int audio_play(void *data, int len, int flags) { +// if (!(flags & AOPLAY_FINAL_CHUNK)) +// len -= len % CHUNK_SIZE; //@ OutBurst + underrun = 0; + return write_buffer(data, len); +} + +static int usec_sleep(int usec_delay) +{ +#ifdef HAVE_NANOSLEEP + struct timespec ts; + ts.tv_sec = usec_delay / 1000000; + ts.tv_nsec = (usec_delay % 1000000) * 1000; + return nanosleep(&ts, NULL); +#else + return usleep(usec_delay); +#endif +} + +static unsigned int GetTimer(void){ + struct timeval tv; + gettimeofday(&tv,NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +float audio_get_delay(struct timeval bs) { + if( buffer == NULL ) + return 0.0f; + int buffered = av_fifo_size(buffer); // could be less + float in_jack = latency; + float b=0.0f,elapsed=0.0; + if (estimate && callback_interval > 0) { + unsigned int b1 = bs.tv_sec * 1000000 + bs.tv_usec; + b = (float) b1/1000000.0; + elapsed = (float)GetTimer() / 1000000.0 ; + elapsed -= callback_time; + in_jack += callback_interval - elapsed; + if (in_jack < 0) in_jack = 0; + } + return (float)buffered / (float)bps + in_jack; +} + +int audio_get_buffered_bytes(long *sec, long *usec) +{ + if( buffer == NULL ) { + veejay_msg(0, "Audio buffer not ready."); + return 0; + } + int buffered = av_fifo_size(buffer); + *sec = callbackTime.tv_sec; + *usec = callbackTime.tv_usec; + veejay_msg(0, "%s: %d %ld, %ld",__FUNCTION__,buffered, callbackTime.tv_sec,callbackTime.tv_usec ); + return buffered; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-audio.h b/branches/V-1.5.3/veejay-server/veejay/vj-audio.h new file mode 100644 index 00000000..9e1d023a --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-audio.h @@ -0,0 +1,12 @@ +#ifndef VJAUDIO_H +#define VJAUDIO_H +int audio_init(int rate, int channels,char *port_name, char *client_name); +void audio_uninit(int immed); +void audio_reset(void); +void audio_pause(void); +void audio_resume(void); +int audio_play(void *data, int len, int flags); +float audio_get_delay(struct timeval bs); +void audio_continue(int speed); +int audio_get_buffered_bytes(long *sec, long *usec); +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-bjack.h b/branches/V-1.5.3/veejay-server/veejay/vj-bjack.h new file mode 100644 index 00000000..e98658f6 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-bjack.h @@ -0,0 +1,34 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_BIOJACK_H +#define VJ_BIOJACK_H +int vj_jack_initialize(); +int vj_jack_init(int rate_hz, int channels, int bps); +int vj_jack_stop(); +int vj_jack_reset(); +int vj_jack_play(void *data, int len); +int vj_jack_pause(); +int vj_jack_resume(); +int vj_jack_rate(); +int vj_jack_get_space(); +long vj_jack_get_status(long int *sec, long int *usec); +int vj_jack_set_volume(int v); +int vj_jack_c_play(void *data, int len, int entry); + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-composite.c b/branches/V-1.5.3/veejay-server/veejay/vj-composite.c new file mode 100644 index 00000000..310e5418 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-composite.c @@ -0,0 +1,555 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + + this c file does a perspective transform on an input image in software. + + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_XML2 +#include +#include +#endif + +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#ifdef HAVE_GL +#include +#endif +typedef struct +{ + uint8_t *proj_plane[3]; + void *vp1; + void *back1; + void *sampler; + void *scaler; + void *back_scaler; + VJFrame *frame1; + VJFrame *frame2; + VJFrame *frame3; + VJFrame *frame4; + VJFrame *frame5; + int sample_mode; + int pf; + int use_back; + int Y_only; + int run; + int back_run; + int has_back; + int proj_width; /* projection (output) */ + int proj_height; + int img_width; /* image (input) */ + int img_height; +} composite_t; + +//@ round to multiple of 8 +#define RUP8(num)(((num)+8)&~8) + + +void *composite_get_vp( void *data ) +{ + composite_t *c = (composite_t*) data; + return c->vp1; +} + +int composite_get_ui(void *data ) +{ + composite_t *c = (composite_t*) data; + return viewport_get_mode(c->vp1); +} + +int composite_has_back(void *data) +{ + composite_t *c = (composite_t*) data; + return c->has_back; +} + +void *composite_init( int pw, int ph, int iw, int ih, const char *homedir, int sample_mode, int zoom_type, int pf, int *vp1_e ) +{ + composite_t *c = (composite_t*) vj_calloc(sizeof(composite_t)); + int vp1_frontback = 0; + int vp1_enabled = 0; + if( pw <= 0 || ph <= 0 ) { + veejay_msg(VEEJAY_MSG_WARNING ,"Missing projection dimensions,using image dimensions %dx%d",iw,ih); + pw = iw; + ph = ih; + } + + c->sample_mode = sample_mode; + c->proj_width = pw; + c->proj_height = ph; + c->img_width = iw; + c->img_height = ih; + c->pf = pf; + c->Y_only = 0; + + c->vp1 = viewport_init( 0,0,pw,ph,pw, ph,iw,ih, homedir, &vp1_enabled, &vp1_frontback, 1); + if(!c->vp1) { + free(c); + return NULL; + } + + c->proj_plane[0] = (uint8_t*) vj_calloc( RUP8( pw * ph * 3) + RUP8(pw * 3) * sizeof(uint8_t)); + c->proj_plane[1] = c->proj_plane[0] + RUP8(pw * ph) + RUP8(pw); + c->proj_plane[2] = c->proj_plane[1] + RUP8(pw * ph) + RUP8(pw); + viewport_set_marker( c->vp1, 1 ); + + c->sampler = subsample_init( pw ); + + sws_template sws_templ; + veejay_memset(&sws_templ,0,sizeof(sws_template)); + sws_templ.flags = zoom_type; + + c->frame1 = yuv_yuv_template( c->proj_plane[0],c->proj_plane[1],c->proj_plane[2],iw,ih,get_ffmpeg_pixfmt( pf )); + c->frame2 = yuv_yuv_template( c->proj_plane[0],c->proj_plane[1],c->proj_plane[2],pw, ph, (pf == FMT_422 ? PIX_FMT_YUV444P: PIX_FMT_YUVJ444P )); + c->frame3 = yuv_yuv_template( c->proj_plane[0],c->proj_plane[1],c->proj_plane[2],pw,ph,c->frame1->format ); + c->frame4 = yuv_yuv_template( c->proj_plane[0],c->proj_plane[1],c->proj_plane[2],iw,ih,c->frame1->format ); + + c->scaler = yuv_init_swscaler( c->frame1, c->frame2, &sws_templ, 0 ); +#ifdef STRICT_CHECKING + assert(c->scaler != NULL ); +#endif + c->back_scaler = yuv_init_swscaler( c->frame4, c->frame3, &sws_templ, 0 ); +#ifdef STRICT_CHECKING + assert(c->back_scaler!=NULL); +#endif + + c->back1 = NULL; + +/* c->back1 = viewport_clone( c->vp1, iw, ih ); + if(!c->back1 ) { + return NULL; + } + viewport_reconfigure(c->back1);*/ + + veejay_msg(VEEJAY_MSG_INFO, "Configuring projection:"); + veejay_msg(VEEJAY_MSG_INFO, "\tSoftware scaler : %s", yuv_get_scaler_name(zoom_type) ); + veejay_msg(VEEJAY_MSG_INFO, "\tVideo resolution : %dx%d", iw,ih ); + veejay_msg(VEEJAY_MSG_INFO, "\tScreen resolution: %dx%d", pw,ph ); + veejay_msg(VEEJAY_MSG_INFO, "\tStatus : %s", + (vp1_enabled ? "Active":"Inactive")); + veejay_msg(VEEJAY_MSG_INFO, "Press Middle-Mouse button to activate setup."); + *vp1_e = (vp1_enabled ? 1 : 2); + return (void*) c; +} + +void *composite_clone( void *compiz ) +{ + composite_t *c = (composite_t*) compiz; + if(!c) return NULL; + void *v = viewport_clone(c->vp1,c->img_width,c->img_height); + viewport_reconfigure(v); + + return v; +} + +void composite_set_backing( void *compiz, void *vp ) +{ + composite_t *c = (composite_t*) compiz; + c->back1 = vp; +} + +void composite_destroy( void *compiz ) +{ + composite_t *c = (composite_t*) compiz; + if(c) + { + if(c->proj_plane[0]) free(c->proj_plane[0]); + if(c->vp1) viewport_destroy( c->vp1 ); + //if(c->back1) viewport_destroy(c->back1); + if(c->scaler) yuv_free_swscaler( c->scaler ); + if(c->back_scaler) yuv_free_swscaler(c->back_scaler); + if(c->frame1) free(c->frame1); + if(c->frame2) free(c->frame2); + if(c->frame3) free(c->frame3); + if(c->frame4) free(c->frame4); + if(c->sampler) subsample_free(c->sampler); + free(c); + } + c = NULL; +} + +int composite_get_status(void *compiz ) +{ + composite_t *c = (composite_t*) compiz; + return viewport_get_initial_active( c->vp1 ); +} + +void composite_set_status(void *compiz, int mode) +{ + composite_t *c = (composite_t*) compiz; + viewport_set_initial_active( c->vp1, mode ); +} + +void composite_set_ui(void *compiz, int status ) +{ + composite_t *c = (composite_t*) compiz; + + viewport_set_ui( c->vp1, status ); +} + +void composite_add_to_config( void *compiz, void *vc, int which_vp ) +{ + composite_t *c = (composite_t*) compiz; + viewport_set_composite( vc, which_vp, c->Y_only ); +} + +void *composite_load_config( void *compiz, void *vc, int *result ) +{ + if( vc == NULL ) { + *result = -1; + return NULL; + } + + composite_t *c = (composite_t*) compiz; + int cm = viewport_get_color_mode_from_config(vc); + int m = viewport_get_composite_mode_from_config(vc); + + void *view = NULL; + int res = viewport_reconfigure_from_config( c->vp1, vc ); + //@ push to back1 too! + if(res) { + if( c->back1 == NULL ) { + c->back1 = composite_clone(c ); + } +#ifdef STRICT_CHECKING + assert(c->back1 != NULL ); +#endif + viewport_update_from(c->vp1, c->back1 ); + c->Y_only = cm; + *result = m; + return (void*)c->back1; + } + return NULL; +} + +int composite_event( void *compiz, uint8_t *in[3], int mouse_x, int mouse_y, int mouse_button, int w_x, int w_y ) +{ + composite_t *c = (composite_t*) compiz; + if(viewport_external_mouse( c->vp1, c->proj_plane, mouse_x, mouse_y, mouse_button, 1,w_x,w_y )) { + if(c->back1) + viewport_update_from(c->vp1, c->back1 ); + return 1; + } + return 0; +} + +static struct { + int i; + char *s; +} pixstr[] = { + {PIX_FMT_YUV420P, "YUVPIX_FMT_YUV420P"}, +{ PIX_FMT_YUV422P, "4:2:2 planar, Y-Cb-Cr ( 422P )"}, +{ PIX_FMT_YUVJ420P, "4:2:0 planar, Y-U-V (420P JPEG)"}, +{ PIX_FMT_YUVJ422P, "4:2:2 planar, Y-U-V (422P JPEG)"}, +{ PIX_FMT_RGB24, "RGB 24 bit"}, +{ PIX_FMT_BGR24, "BGR 24 bit"}, +{ PIX_FMT_YUV444P, "YUV 4:4:4 planar, Y-Cb-Cr (444P)"}, +{ PIX_FMT_YUVJ444P, "YUV 4:4:4 planar, Y-U-V (444P JPEG)"}, +{ PIX_FMT_RGB32, "RGB 32 bit"}, +{ PIX_FMT_BGR32, "BGR 32 bit"}, +{ PIX_FMT_GRAY8, "Greyscale"}, +{ PIX_FMT_RGB32_1, "RGB 32 bit LE"}, +{ 0 , NULL} + +}; + + +static const char *unicap_pf_str(int i) +{ + int j; + for( j = 0; pixstr[j].s != NULL ; j ++ ) { + if( i == pixstr[j].i ) + return pixstr[j].s; + } + return NULL; +} + +static void composite_scale( composite_t *c, VJFrame *input, VJFrame *output ) +{ +#ifdef STRICT_CHECKING + assert( unicap_pf_str(input->format) != NULL ); + assert( c->scaler != NULL ); +#endif + yuv_convert_and_scale(c->scaler,input,output); +} + +int composite_get_top(void *compiz, uint8_t *current_in[3], uint8_t *out[3], int which_vp ) +{ + composite_t *c = (composite_t*) compiz; + int vp1_active = viewport_active(c->vp1); + if( vp1_active ) + { + out[0] = c->proj_plane[0]; + out[1] = c->proj_plane[1]; + out[2] = c->proj_plane[2]; + return c->frame2->format; + } + + if (c->proj_width != c->img_width && + c->proj_height != c->img_height && which_vp == 2 ) + { + out[0] = c->proj_plane[0]; + out[1] = c->proj_plane[1]; + out[2] = c->proj_plane[2]; + return c->frame3->format; + } else if( which_vp == 1) { + out[0] = c->proj_plane[0]; + out[1] = c->proj_plane[1]; + out[2] = c->proj_plane[2]; + return c->frame2->format; + } else if ( which_vp == 2 ) { + out[0] = current_in[0]; + out[1] = current_in[1]; + out[2] = current_in[2]; + return c->frame1->format; + } + return c->frame1->format; +} + +/* Top frame, blit */ +void composite_blit_yuyv( void *compiz, uint8_t *in[3], uint8_t *yuyv, int which_vp ) +{ + composite_t *c = (composite_t*) compiz; + int vp1_active = viewport_active(c->vp1); + + int blit_back = c->has_back; + + c->has_back = 0; + + if( which_vp == 2 && vp1_active ) { + yuv422_to_yuyv(c->proj_plane,yuyv,c->proj_width,c->proj_height ); + return; + } else if (which_vp == 2 ) { + if (c->proj_width != c->img_width && + c->proj_height != c->img_height && which_vp == 2 ) + { + yuv422_to_yuyv(c->proj_plane,yuyv,c->proj_width,c->proj_height); + } + else { + yuv422_to_yuyv(in,yuyv,c->proj_width,c->proj_height ); + } + return; + } + + if( which_vp == 1 && !vp1_active ) { + viewport_produce_full_img_yuyv( c->vp1,c->proj_plane,yuyv); + if( yuv_use_auto_ccir_jpeg() && c->pf == FMT_422 ) { + yuy2_scale_pixels_from_ycbcr( yuyv,c->proj_width * c->proj_height ); + } + return; + } + + if( yuv_use_auto_ccir_jpeg() && c->pf == FMT_422 ) { + //@scale to full range yuv + yuv422_to_yuyv(c->proj_plane,yuyv,c->proj_width,c->proj_height); + yuy2_scale_pixels_from_ycbcr( yuyv,c->proj_width * c->proj_height ); + } else { + yuv422_to_yuyv(c->proj_plane,yuyv,c->proj_width,c->proj_height ); + } + +} + +//@OBSOLETE +void composite_blit_ycbcr( void *compiz, + uint8_t *in[3], + int which_vp, + void *gl ) +{ + composite_t *c = (composite_t*) compiz; + int vp1_active = viewport_active(c->vp1); + + int blit_back = c->has_back; +#ifdef HAVE_GL + uint8_t *gl_buffer = x_display_get_buffer(gl); + + c->has_back = 0; + +//@ frame in 444 + + if( which_vp == 2 && vp1_active ) { + yuv444_yvu444_1plane(c->proj_plane,c->proj_width,c->proj_height, gl_buffer); + return; + } else if (which_vp == 2 ) { + if (c->proj_width != c->img_width && + c->proj_height != c->img_height && which_vp == 2 ) + { + yuv444_yvu444_1plane(c->proj_plane,c->proj_width,c->proj_height, gl_buffer); + } + else { + yuv444_yvu444_1plane(in,c->proj_width,c->proj_height, gl_buffer); + } + return; + } + + if( which_vp == 1 && !vp1_active ) { + viewport_produce_full_img_packed( c->vp1,c->proj_plane,gl_buffer); + //if( yuv_use_auto_ccir_jpeg() && c->pf == FMT_422 ) { + // yuy2_scale_pixels_from_ycbcr( yuyv,c->proj_width * c->proj_height ); + //} + return; + } + + yuv444_yvu444_1plane(c->proj_plane,c->proj_width,c->proj_height, gl_buffer); + +/* if( yuv_use_auto_ccir_jpeg() && c->pf == FMT_422 ) { + //@scale to full range yuv + yuv422_to_yuyv(c->proj_plane,yuyv,c->proj_width,c->proj_height); + yuy2_scale_pixels_from_ycbcr( yuyv,c->proj_width * c->proj_height ); + } else { + yuv422_to_yuyv(c->proj_plane,yuyv,c->proj_width,c->proj_height ); + } + + */ + +#endif +} + + +void *composite_get_config(void *compiz, int which_vp ) +{ + composite_t *c = (composite_t*) compiz; + void *config = viewport_get_configuration( c->vp1 ); + viewport_set_composite( config, which_vp, c->Y_only ); + return config; +} + +/* Top frame */ +int composite_process(void *compiz, VJFrame *output, VJFrame *input, int which_vp, int pff ) +{ + composite_t *c = (composite_t*) compiz; + + if(c->run == 0 ) { + viewport_reconfigure(c->vp1); + c->run=1; + } + + int vp1_active = viewport_active(c->vp1); + if( which_vp == 2 && !vp1_active ) + { + if( input->width != output->width || + input->height != output->height ) { + c->frame4->data[0] = output->data[0]; + c->frame4->data[1] = output->data[1]; + c->frame4->data[2] = output->data[2]; + /* if(output->ssm || pff == PIX_FMT_YUV444P || pff == PIX_FMT_YUVJ444P) + c->frame4->format = PIX_FMT_YUV444P; + else*/ + c->frame4->format = pff; + yuv_convert_and_scale(c->back_scaler,c->frame4,c->frame3); + } + if( pff == PIX_FMT_YUV444P || pff == PIX_FMT_YUVJ444P ) + return 1; + + return output->ssm; + } + + if( which_vp && vp1_active ) /* for both modes, render ui from vp1 */ + { + viewport_push_frame( /* push frame to preview in setup */ + c->vp1, + input->width, + input->height, + input->data[0], + input->data[1], + input->data[2] + ); + veejay_memset( c->proj_plane[0], 125, c->proj_width * c->proj_height ); + veejay_memset( c->proj_plane[1], 128, c->proj_width* c->proj_height ); + veejay_memset( c->proj_plane[2], 128, c->proj_width* c->proj_height ); + viewport_draw_interface_color( c->vp1, c->proj_plane ); + } + else if ( which_vp == 1 ) + { + composite_scale( c, input, c->frame2 ); + } + return 1; +} + + +/* Chained Frame */ +int composite_processX( void *compiz, void *back1, uint8_t *out_data[3], VJFrame *input ) +{ + composite_t *c = (composite_t*) compiz; +#ifdef STRICT_CHECKING + assert( input->width == c->frame1->width ); + assert( input->height == c->frame1->height ); +#endif + + if(!input->ssm) /* supersample to YUV 4:4:4 */ + { + chroma_supersample( c->sample_mode, c->sampler, input->data, input->width, input->height ); + input->ssm = 1; + } +#ifdef STRICT_CHECKING + assert( input->data[0] != out_data[0] ); + assert( input->data[1] != out_data[1] ); + assert( input->data[2] != out_data[2] ); + assert( back1 != NULL ); +#endif + viewport_produce_bw_img( back1,input->data,out_data,c->Y_only); + + c->has_back = 1; + + return 1; //* supersampled */ +} + +int composite_get_colormode(void *compiz) +{ + composite_t *c = (composite_t*) compiz; + return c->Y_only; +} + +void composite_set_colormode( void *compiz, int mode ) +{ + composite_t *c = (composite_t*) compiz; + if( mode == 0 ) + c->Y_only = 0; + else if( mode == 1 ) + c->Y_only = 1; +} + + + +void *composite_get_draw_buffer( void *compiz ) +{ + composite_t *c = (composite_t*) compiz; + VJFrame *frame = (VJFrame*) vj_malloc(sizeof(VJFrame)); + vj_get_yuv444_template( frame, c->proj_width,c->proj_height); + frame->data[0] = c->proj_plane[0]; + frame->data[1] = c->proj_plane[1]; + frame->data[2] = c->proj_plane[2]; + return (void*)frame; +} + diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-composite.h b/branches/V-1.5.3/veejay-server/veejay/vj-composite.h new file mode 100644 index 00000000..8a1f22b8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-composite.h @@ -0,0 +1,59 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#ifndef COMPOSITEHVJ +#define COMPOSITEHVJ + +void *composite_get_draw_buffer( void *compiz ); + +void composite_set_colormode( void *compiz, int mode ); + +int composite_get_colormode(void *compiz); + +int composite_get_top(void *compiz, uint8_t *current_in[3], uint8_t *out[3], int mode ); + +int composite_processX( void *compiz, void *back1,uint8_t *tmp_data[3], VJFrame *input ); + +int composite_process(void *compiz, VJFrame *output, VJFrame *input, int which_vp, int pixfmt ); + +void composite_blit_ycbcr( void *compiz,uint8_t *in[3], int which_vp, void *gl ); + + +void composite_blit_yuyv( void *compiz,uint8_t *in[3], uint8_t *yuyv, int which_vp ); + +int composite_event( void *compiz, uint8_t *in[3], int mouse_x, int mouse_y, int mouse_button, int w_x, int w_y ); + +void composite_destroy( void *compiz ); + +void *composite_init( int pw, int ph, int iw, int ih, const char *homedir, int sample_mode, int zoom_type, int pf, int *vp1_enabled ); + +void composite_set_backing( void *compiz, void *vp ); + +void *composite_clone( void *compiz ); + +void *composite_get_vp( void *data ); +void composite_set_ui(void *compiz, int status ); +int composite_get_ui(void *compiz ); +//@ load config after loading to activate viewport setup +//@ add to config before saving +void *composite_load_config( void *compiz, void *vc, int *result ); +void composite_add_to_config( void *compiz, void *vc, int which_vp ); +int composite_get_status(void *compiz ); +void composite_set_status(void *compiz, int mode); +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-dfb.c b/branches/V-1.5.3/veejay-server/veejay/vj-dfb.c new file mode 100644 index 00000000..afaa051d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-dfb.c @@ -0,0 +1,341 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +/* DirectFB support, this file is part of veejay + code inspired by mplayer and dfbtv + + */ + +#include +#include +#include +#include +#include +#ifdef HAVE_DIRECTFB +#include "vj-dfb.h" +void *vj_dfb_allocate(int width, int height, int norm) +{ + vj_dfb *dfb = (vj_dfb *) malloc(sizeof(vj_dfb)); + if (!dfb) + return NULL; + dfb->buffer = NULL; + dfb->screen_width = 0; + dfb->screen_height = 0; + dfb->screen_framebuffer = 0; + dfb->screen_pitch = 0; + sprintf(dfb->dev_name, "%s", "/dev/fb0"); + fprintf(stderr, "DirectFB: using [%s]\n", dfb->dev_name); + dfb->width = width; + dfb->height = height; + dfb->norm = norm; + dfb->stretch = 0; + return (void*)dfb; +} + +int vj_dfb_init(void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + DFBDisplayLayerConfig dlc; + DFBDisplayLayerConfigFlags failed; + DFBSurfaceDescription dsc; + int n; + + DirectFBInit(0, 0); + DirectFBSetOption("fbdev", framebuffer->dev_name); + DirectFBSetOption("no-cursor", ""); + DirectFBSetOption("bg-color", "00000000"); + DirectFBSetOption("matrox-crtc2", ""); + DirectFBSetOption("matrox-tv-standard", + framebuffer->norm ? "pal" : "ntsc"); + + fprintf(stderr, "DirectFB: PAL = %s\n", + framebuffer->norm ? "pal" : "ntsc"); + + framebuffer->bufs[0] = framebuffer->bufs[1] = framebuffer->bufs[2] = + NULL; + + DirectFBCreate(&framebuffer->d); + + framebuffer->d->GetDisplayLayer(framebuffer->d, 2, + &(framebuffer->crtc2)); + + if (!framebuffer->crtc2) { + fprintf(stderr, "Unable to initialize display layern"); + return -1; + } + + framebuffer->crtc2->SetCooperativeLevel(framebuffer->crtc2, + DLSCL_EXCLUSIVE); + + framebuffer->d->GetInputDevice(framebuffer->d, DIDID_KEYBOARD, + &(framebuffer->keyboard)); + + framebuffer->keyboard->CreateEventBuffer(framebuffer->keyboard, + &(framebuffer->buffer)); + + framebuffer->buffer->Reset(framebuffer->buffer); + + dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; + dlc.buffermode = DLBM_BACKVIDEO; + dlc.pixelformat = DSPF_I420; + + + dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; + dsc.width = framebuffer->width; + dsc.height = framebuffer->height; + dsc.pixelformat = dlc.pixelformat; + + if (framebuffer->d->CreateSurface(framebuffer->d, &dsc, + &framebuffer->frame) != DFB_OK) + return -1; + + if (framebuffer->crtc2->TestConfiguration(framebuffer->crtc2, + &dlc, &failed) != DFB_OK) { + fprintf(stderr, "TestConfiguration failed\n"); + return -1; + } + + framebuffer->crtc2->SetConfiguration(framebuffer->crtc2, &dlc); + + framebuffer->crtc2->GetSurface(framebuffer->crtc2, + &(framebuffer->c2frame) + ); + + framebuffer->c2frame->GetSize(framebuffer->c2frame, + &(framebuffer->screen_width), + &(framebuffer->screen_height) + ); + + fprintf(stderr, "DirectFB: Screen is %d x %d , Video is %d x %d\n", + framebuffer->screen_width, framebuffer->screen_height, + framebuffer->width, framebuffer->height); + + if (framebuffer->width != framebuffer->screen_width || + framebuffer->height != framebuffer->screen_height) { + framebuffer->stretch = 1; + } + + framebuffer->drect.x = + (framebuffer->screen_width - framebuffer->width) / 2; + framebuffer->drect.y = + (framebuffer->screen_height - framebuffer->height) / 2; + framebuffer->drect.w = framebuffer->width; + framebuffer->drect.h = framebuffer->height; + + framebuffer->c2frame->Clear(framebuffer->c2frame, 0, 0, 0, 0xff); + framebuffer->c2frame->Flip(framebuffer->c2frame, NULL, 0); + framebuffer->c2frame->Clear(framebuffer->c2frame, 0, 0, 0, 0xff); + + + framebuffer->c2frame->GetPixelFormat(framebuffer->c2frame, + &(framebuffer->frame_format) + ); + + framebuffer->frame->GetPixelFormat(framebuffer->frame, + &(framebuffer->frame_format) + ); + + fprintf(stderr, "DirectFB: Frame format = "); + switch (framebuffer->frame_format) { + case DSPF_I420: + fprintf(stderr, "I420\n"); + break; + default: + fprintf(stderr, "Wrong pixel format!\n"); + break; + } + + framebuffer->crtc2->SetOpacity(framebuffer->crtc2, 0xff); + + return 0; +} + +int vj_dfb_lock(void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + if (!framebuffer) + return -1; + framebuffer->c2frame->Lock(framebuffer->c2frame, + DSLF_WRITE, + &(framebuffer->screen_framebuffer), + &(framebuffer->screen_pitch) + ); + return 0; +} + +int vj_dfb_unlock(void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + if (!framebuffer) + return -1; + + framebuffer->c2frame->Unlock(framebuffer->c2frame); + return 0; +} + + +int vj_dfb_free(void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*)ptr; + if (!framebuffer) + return -1; + + if (framebuffer->buffer) { + framebuffer->buffer->Release(framebuffer->buffer); + } + if (framebuffer->keyboard) { + framebuffer->keyboard->Release(framebuffer->keyboard); + } + if (framebuffer->c2frame) { + framebuffer->c2frame->Release(framebuffer->c2frame); + } + if (framebuffer->crtc2) { + framebuffer->crtc2->Release(framebuffer->crtc2); + } + if (framebuffer->d) { + framebuffer->d->Release(framebuffer->d); + } + return 0; +} + + +void vj_dfb_wait_for_sync( void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + framebuffer->d->WaitForSync(framebuffer->d); +} + +int vj_dfb_get_pitch( void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + return (int) framebuffer->screen_pitch; +} + +uint8_t *vj_dfb_get_address(void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + return (uint8_t *) framebuffer->screen_framebuffer; +} + +int vj_dfb_get_output_field( void *ptr) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + int fieldid; + framebuffer->crtc2->GetCurrentOutputField(framebuffer->crtc2, + &fieldid); + return fieldid; +} + +/* +int vj_dfb_update_yuv_overlay(void *ptr , uint8_t **frame) { + uint8_t *output; + vj_dfb *framebuffer = (vj_dfb*) ptr; + int pitch,i,p; + while(vj_dfb_get_output_field(framebuffer) != 0) { + fprintf(stderr, "resyncing...\n"); + vj_dfb_wait_for_sync(framebuffer); + } + + if(vj_dfb_lock(framebuffer)!=0) return -1; + + output = vj_dfb_get_address(framebuffer); + + pitch = vj_dfb_get_pitch(framebuffer); + + p = pitch; + if(p > framebuffer->width) p = framebuffer->width; + + for(i=0; i < framebuffer->height; i++) { + veejay_memcpy(output+i*pitch, frame[0]+i*framebuffer->width, p); + } + + output += pitch * framebuffer->height; + p = p / 2; + for(i=0; i < framebuffer->height/2; i++) { + veejay_memcpy(output+i*pitch/2, frame[1] + i * framebuffer->width/2, p); + } + + output += pitch * framebuffer->height/4; + for(i=0; i < framebuffer->height/2; i++) { + veejay_memcpy(output+i * pitch/2, frame[2] + i * framebuffer->width/2, p); + } + + if(vj_dfb_unlock(framebuffer)!=0) return -1; + + vj_dfb_wait_for_sync(framebuffer); + return 0; + +} +*/ + +int vj_dfb_update_yuv_overlay(void *ptr, uint8_t ** frame) +{ + vj_dfb *framebuffer = (vj_dfb*) ptr; + void *dst; + int i, p, pitch; + if (framebuffer->frame->Lock(framebuffer->frame, + DSLF_WRITE, &dst, &pitch) != DFB_OK) + return -1; + + p = pitch; + + if (p > framebuffer->width) + p = framebuffer->width; + + for (i = 0; i < framebuffer->height; i++) { + veejay_memcpy(dst + i * pitch, frame[0] + i * framebuffer->width, p); + } + + dst += pitch * framebuffer->height; + p = p / 2; + for (i = 0; i < framebuffer->height / 2; i++) { + veejay_memcpy(dst + i * pitch / 2, frame[1] + i * framebuffer->width / 2, + p); + } + + dst += pitch * framebuffer->height / 4; + for (i = 0; i < framebuffer->height / 2; i++) { + veejay_memcpy(dst + i * pitch / 2, frame[2] + i * framebuffer->width / 2, + p); + } + + framebuffer->frame->Unlock(framebuffer->frame); + + framebuffer->c2frame->SetBlittingFlags(framebuffer->c2frame, + DSBLIT_NOFX); + + if (framebuffer->stretch) { + framebuffer->c2frame->StretchBlit(framebuffer->c2frame, + framebuffer->frame, NULL, + //&(framebuffer->drect) + NULL); + } else { + framebuffer->c2frame->Blit(framebuffer->c2frame, + framebuffer->frame, + NULL, + framebuffer->drect.x, + framebuffer->drect.y); + + } + + framebuffer->c2frame->Flip(framebuffer->c2frame, NULL, + DSFLIP_WAITFORSYNC); + + return 0; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-dfb.h b/branches/V-1.5.3/veejay-server/veejay/vj-dfb.h new file mode 100644 index 00000000..4819f291 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-dfb.h @@ -0,0 +1,71 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#ifndef VJ_DFB_H +#define VJ_DFB_H +#include + +#ifdef HAVE_DIRECTFB +#include +#include +#include + +typedef struct vj_dfb_t { + IDirectFB *d; + IDirectFBDisplayLayer *crtc2; + IDirectFBSurface *bufs[3]; + IDirectFBSurface *c2frame; + IDirectFBSurface *frame; + DFBRectangle drect; + DFBSurfacePixelFormat frame_format; + IDirectFBInputDevice *keyboard; + IDirectFBEventBuffer *buffer; + unsigned int screen_width; + unsigned int screen_height; + void *screen_framebuffer; + int screen_pitch; + int stretch; + int width; + int height; + char dev_name[100]; + int norm; +} vj_dfb; + +void *vj_dfb_allocate(int width, int height, int norm); + +int vj_dfb_init(void *dfb); + +int vj_dfb_lock(void *dfb); + +int vj_dfb_unlock(void * dfb); + +int vj_dfb_update_yuv_overlay(void * dfb, uint8_t ** yuv420); + +int vj_dfb_free(void * dfb); + +void vj_dfb_wait_for_sync(); + +int vj_dfb_get_pitch( void *dfb); + +int vj_dfb_update_yuv_overlay(void *dfb, uint8_t ** frame); + +uint8_t *vj_dfb_get_address(void *dfb ); + +int vj_dfb_get_output_field( void *dfb ); +#endif +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-event.c b/branches/V-1.5.3/veejay-server/veejay/vj-event.c new file mode 100644 index 00000000..7b581804 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-event.c @@ -0,0 +1,10233 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg + * + * 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 + */ + + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SDL +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_GL +#include +#endif +#ifdef USE_GDK_PIXBUF +#include +#endif +#include +#include +#include +#include +#include +#include +/* Highest possible SDL Key identifier */ +#define MAX_SDL_KEY (3 * SDLK_LAST) + 1 +#define MSG_MIN_LEN 4 /* stripped ';' */ +#ifdef STRICT_CHECKING +#include +#endif +#ifdef HAVE_FREETYPE +#include +#endif + +static int use_bw_preview_ = 0; +static int _last_known_num_args = 0; +static hash_t *BundleHash = NULL; + +static int vj_event_valid_mode(int mode) { + switch(mode) { + case VJ_PLAYBACK_MODE_SAMPLE: + case VJ_PLAYBACK_MODE_TAG: + case VJ_PLAYBACK_MODE_PLAIN: + return 1; + } + + return 0; +} + +/* define the function pointer to any event */ +typedef void (*vj_event)(void *ptr, const char format[], va_list ap); + +void vj_event_create_effect_bundle(veejay_t * v,char *buf, int key_id, int key_mod ); + +/* struct for runtime initialization of event handlers */ +typedef struct { + int list_id; // VIMS id + vj_event act; // function pointer +} vj_events; + +static vj_events net_list[VIMS_MAX]; +static int override_keyboard = 0; +#ifdef HAVE_SDL +typedef struct +{ + vj_events *vims; + int key_symbol; + int key_mod; + int arg_len; + char *arguments; + int event_id; +} vj_keyboard_event; + +static hash_t *keyboard_events = NULL; + +static vj_keyboard_event *keyboard_event_map_[2048]; + +typedef struct +{ + int key_symbol; + int key_mod; + char *args; + int arg_len; + void *next; +} vims_key_list; + +#endif + +static int _recorder_format = ENCODER_MJPEG; + +#define SEND_BUF 256000 + +static char *get_print_buf(int size) { + int s = size; + if( s<= 0) + s = SEND_BUF; + char *res = (char*) vj_calloc(sizeof(char) * s ); + return res; +} + +static void *macro_bank_[12]; +static void *macro_port_ = NULL; +static int current_macro_ = 0; +static int macro_status_ = 0; +static int macro_key_ = 1; +static int macro_line_[3] = {-1 ,0,0}; +static int macro_current_age_ = 0; +static int macro_expected_age_ = 0; +#define MAX_MACROS 8 +typedef struct { + char *msg[MAX_MACROS]; + int pending[MAX_MACROS]; + int age[MAX_MACROS]; +} macro_block_t; + +int vj_event_macro_status(void) +{ + return macro_status_; +} + +static char *retrieve_macro_(veejay_t *v, long frame, int idx ); +static void store_macro_( veejay_t *v,char *str, long frame ); +static void reset_macro_(void); +static void replay_macro_(void); + +extern void veejay_pipe_write_status(veejay_t *info, int link_id ); +extern int _vj_server_del_client(vj_server * vje, int link_id); +extern int vj_event_exists( int id ); + +// forward decl +int vj_event_get_video_format(void) +{ + return _recorder_format; +} + +enum { + VJ_ERROR_NONE=0, + VJ_ERROR_MODE=1, + VJ_ERROR_EXISTS=2, + VJ_ERROR_VIMS=3, + VJ_ERROR_DIMEN=4, + VJ_ERROR_MEM=5, + VJ_ERROR_INVALID_MODE = 6, +}; + +#ifdef HAVE_SDL +#define VIMS_MOD_SHIFT 3 +#define VIMS_MOD_NONE 0 +#define VIMS_MOD_CTRL 2 +#define VIMS_MOD_ALT 1 + +static struct { /* hardcoded keyboard layout (the default keys) */ + int event_id; + int key_sym; + int key_mod; + const char *value; +} vj_event_default_sdl_keys[] = { + + { 0,0,0,NULL }, + { VIMS_PROJ_INC, SDLK_LEFT, VIMS_MOD_CTRL, "-1 0" }, + { VIMS_PROJ_INC, SDLK_RIGHT, VIMS_MOD_CTRL, "1 0" }, + { VIMS_PROJ_INC, SDLK_UP, VIMS_MOD_CTRL, "0 -1" }, + { VIMS_PROJ_INC, SDLK_DOWN, VIMS_MOD_CTRL, "0 1" }, + + + { VIMS_EFFECT_SET_BG, SDLK_b, VIMS_MOD_ALT, NULL }, + { VIMS_VIDEO_PLAY_FORWARD, SDLK_KP6, VIMS_MOD_NONE, NULL }, + { VIMS_VIDEO_PLAY_BACKWARD, SDLK_KP4, VIMS_MOD_NONE, NULL }, + { VIMS_VIDEO_PLAY_STOP, SDLK_KP5, VIMS_MOD_NONE, NULL }, + { VIMS_VIDEO_SKIP_FRAME, SDLK_KP9, VIMS_MOD_NONE, "1" }, + { VIMS_VIDEO_PREV_FRAME, SDLK_KP7, VIMS_MOD_NONE, "1" }, + { VIMS_VIDEO_SKIP_SECOND, SDLK_KP8, VIMS_MOD_NONE, NULL }, + { VIMS_VIDEO_PREV_SECOND, SDLK_KP2, VIMS_MOD_NONE, NULL }, + { VIMS_VIDEO_GOTO_START, SDLK_KP1, VIMS_MOD_NONE, NULL }, + { VIMS_VIDEO_GOTO_END, SDLK_KP3, VIMS_MOD_NONE, NULL }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_a, VIMS_MOD_NONE, "1" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_s, VIMS_MOD_NONE, "2" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_d, VIMS_MOD_NONE, "3" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_f, VIMS_MOD_NONE, "4" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_g, VIMS_MOD_NONE, "5" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_h, VIMS_MOD_NONE, "6" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_j, VIMS_MOD_NONE, "7" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_k, VIMS_MOD_NONE, "8" }, + { VIMS_VIDEO_SET_SPEEDK, SDLK_l, VIMS_MOD_NONE, "9" }, + { VIMS_VIDEO_SET_SLOW, SDLK_a, VIMS_MOD_ALT, "1" }, + { VIMS_VIDEO_SET_SLOW, SDLK_s, VIMS_MOD_ALT, "2" }, + { VIMS_VIDEO_SET_SLOW, SDLK_d, VIMS_MOD_ALT, "3" }, + { VIMS_VIDEO_SET_SLOW, SDLK_e, VIMS_MOD_ALT, "4" }, + { VIMS_VIDEO_SET_SLOW, SDLK_f, VIMS_MOD_ALT, "5" }, + { VIMS_VIDEO_SET_SLOW, SDLK_g, VIMS_MOD_ALT, "6" }, + { VIMS_VIDEO_SET_SLOW, SDLK_h, VIMS_MOD_ALT, "7" }, + { VIMS_VIDEO_SET_SLOW, SDLK_j, VIMS_MOD_ALT, "8" }, + { VIMS_VIDEO_SET_SLOW, SDLK_k, VIMS_MOD_ALT, "9" }, + { VIMS_VIDEO_SET_SLOW, SDLK_l, VIMS_MOD_ALT, "10" }, +#ifdef HAVE_SDL + { VIMS_FULLSCREEN, SDLK_f, VIMS_MOD_CTRL, NULL }, +#endif + { VIMS_CHAIN_ENTRY_DOWN, SDLK_KP_MINUS, VIMS_MOD_NONE, "1" }, + { VIMS_CHAIN_ENTRY_UP, SDLK_KP_PLUS, VIMS_MOD_NONE, "1" }, + { VIMS_CHAIN_ENTRY_CHANNEL_INC, SDLK_EQUALS, VIMS_MOD_NONE, NULL }, + { VIMS_CHAIN_ENTRY_CHANNEL_DEC, SDLK_MINUS, VIMS_MOD_NONE, NULL }, + { VIMS_CHAIN_ENTRY_SOURCE_TOGGLE, SDLK_SLASH, VIMS_MOD_NONE, NULL }, // stream/sample + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_PAGEUP, VIMS_MOD_NONE, "0 1" }, + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_KP_PERIOD, VIMS_MOD_NONE, "1 1" }, + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_PERIOD, VIMS_MOD_NONE, "2 1" }, + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_w, VIMS_MOD_NONE, "3 1" }, + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_r, VIMS_MOD_NONE, "4 1" }, + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_y, VIMS_MOD_NONE, "5 1" }, + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_i, VIMS_MOD_NONE, "6 1" }, + { VIMS_CHAIN_ENTRY_INC_ARG, SDLK_p, VIMS_MOD_NONE, "7 1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_PAGEDOWN, VIMS_MOD_NONE, "0 -1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_KP0, VIMS_MOD_NONE, "1 -1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_COMMA, VIMS_MOD_NONE, "2 -1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_q, VIMS_MOD_NONE, "3 -1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_e, VIMS_MOD_NONE, "4 -1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_t, VIMS_MOD_NONE, "5 -1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_u, VIMS_MOD_NONE, "6 -1" }, + { VIMS_CHAIN_ENTRY_DEC_ARG, SDLK_o, VIMS_MOD_NONE, "7 -1" }, + { VIMS_OSD, SDLK_o, VIMS_MOD_CTRL, NULL }, + { VIMS_COPYRIGHT, SDLK_c, VIMS_MOD_CTRL, NULL }, + { VIMS_COMPOSITE, SDLK_i, VIMS_MOD_CTRL, NULL }, + { VIMS_OSD_EXTRA, SDLK_h, VIMS_MOD_CTRL, NULL }, + { VIMS_PROJ_STACK, SDLK_v, VIMS_MOD_CTRL, "1 0" }, + { VIMS_PROJ_STACK, SDLK_p, VIMS_MOD_CTRL, "0 1" }, + { VIMS_PROJ_TOGGLE, SDLK_a, VIMS_MOD_CTRL, NULL }, + { VIMS_FRONTBACK, SDLK_s, VIMS_MOD_CTRL, NULL }, + { VIMS_RENDER_DEPTH, SDLK_d, VIMS_MOD_CTRL, "2" }, + { VIMS_SELECT_BANK, SDLK_1, VIMS_MOD_NONE, "1" }, + { VIMS_SELECT_BANK, SDLK_2, VIMS_MOD_NONE, "2" }, + { VIMS_SELECT_BANK, SDLK_3, VIMS_MOD_NONE, "3" }, + { VIMS_SELECT_BANK, SDLK_4, VIMS_MOD_NONE, "4" }, + { VIMS_SELECT_BANK, SDLK_5, VIMS_MOD_NONE, "5" }, + { VIMS_SELECT_BANK, SDLK_6, VIMS_MOD_NONE, "6" }, + { VIMS_SELECT_BANK, SDLK_7, VIMS_MOD_NONE, "7" }, + { VIMS_SELECT_BANK, SDLK_8, VIMS_MOD_NONE, "8" }, + { VIMS_SELECT_BANK, SDLK_9, VIMS_MOD_NONE, "9" }, + { VIMS_SELECT_ID, SDLK_F1, VIMS_MOD_NONE, "1" }, + { VIMS_SELECT_ID, SDLK_F2, VIMS_MOD_NONE, "2" }, + { VIMS_SELECT_ID, SDLK_F3, VIMS_MOD_NONE, "3" }, + { VIMS_SELECT_ID, SDLK_F4, VIMS_MOD_NONE, "4" }, + { VIMS_SELECT_ID, SDLK_F5, VIMS_MOD_NONE, "5" }, + { VIMS_SELECT_ID, SDLK_F6, VIMS_MOD_NONE, "6" }, + { VIMS_SELECT_ID, SDLK_F7, VIMS_MOD_NONE, "7" }, + { VIMS_SELECT_ID, SDLK_F8, VIMS_MOD_NONE, "8" }, + { VIMS_SELECT_ID, SDLK_F9, VIMS_MOD_NONE, "9" }, + { VIMS_SELECT_ID, SDLK_F10, VIMS_MOD_NONE, "10" }, + { VIMS_SELECT_ID, SDLK_F11, VIMS_MOD_NONE, "11" }, + { VIMS_SELECT_ID, SDLK_F12, VIMS_MOD_NONE, "12" }, + { VIMS_SET_PLAIN_MODE, SDLK_KP_DIVIDE, VIMS_MOD_NONE, NULL }, + { VIMS_REC_AUTO_START, SDLK_e, VIMS_MOD_CTRL, "100" }, + { VIMS_REC_STOP, SDLK_t, VIMS_MOD_CTRL, NULL }, + { VIMS_REC_START, SDLK_r, VIMS_MOD_CTRL, NULL }, + { VIMS_CHAIN_TOGGLE, SDLK_END, VIMS_MOD_NONE, NULL }, + { VIMS_CHAIN_ENTRY_SET_STATE, SDLK_END, VIMS_MOD_ALT, NULL }, + { VIMS_CHAIN_ENTRY_CLEAR, SDLK_DELETE, VIMS_MOD_NONE, NULL }, + { VIMS_FXLIST_INC, SDLK_UP, VIMS_MOD_NONE, "1" }, + { VIMS_FXLIST_DEC, SDLK_DOWN, VIMS_MOD_NONE, "1" }, + { VIMS_FXLIST_ADD, SDLK_RETURN, VIMS_MOD_NONE, NULL }, + { VIMS_SET_SAMPLE_START, SDLK_LEFTBRACKET, VIMS_MOD_NONE, NULL }, + { VIMS_SET_SAMPLE_END, SDLK_RIGHTBRACKET, VIMS_MOD_NONE, NULL }, + { VIMS_SAMPLE_SET_MARKER_START, SDLK_LEFTBRACKET, VIMS_MOD_ALT, NULL }, + { VIMS_SAMPLE_SET_MARKER_END, SDLK_RIGHTBRACKET, VIMS_MOD_ALT, NULL }, + { VIMS_SAMPLE_TOGGLE_LOOP, SDLK_KP_MULTIPLY, VIMS_MOD_NONE,NULL }, + { VIMS_SWITCH_SAMPLE_STREAM, SDLK_ESCAPE, VIMS_MOD_NONE, NULL }, + { VIMS_PRINT_INFO, SDLK_HOME, VIMS_MOD_NONE, NULL }, + { VIMS_SAMPLE_CLEAR_MARKER, SDLK_BACKSPACE, VIMS_MOD_NONE, NULL }, + { VIMS_MACRO, SDLK_SPACE, VIMS_MOD_NONE, "2 1" }, + { VIMS_MACRO, SDLK_SPACE, VIMS_MOD_SHIFT, "1 1" }, + { VIMS_MACRO, SDLK_SPACE, VIMS_MOD_CTRL, "0 0" }, + { VIMS_MACRO_SELECT, SDLK_F1, VIMS_MOD_CTRL, "0" }, + { VIMS_MACRO_SELECT, SDLK_F2, VIMS_MOD_CTRL, "1" }, + { VIMS_MACRO_SELECT, SDLK_F3, VIMS_MOD_CTRL, "2" }, + { VIMS_MACRO_SELECT, SDLK_F4, VIMS_MOD_CTRL, "3" }, + { VIMS_MACRO_SELECT, SDLK_F5, VIMS_MOD_CTRL, "4" }, + { VIMS_MACRO_SELECT, SDLK_F6, VIMS_MOD_CTRL, "5" }, + { VIMS_MACRO_SELECT, SDLK_F7, VIMS_MOD_CTRL, "6" }, + { VIMS_MACRO_SELECT, SDLK_F8, VIMS_MOD_CTRL, "7" }, + { VIMS_MACRO_SELECT, SDLK_F9, VIMS_MOD_CTRL, "8" }, + { VIMS_MACRO_SELECT, SDLK_F10, VIMS_MOD_CTRL, "9" }, + { VIMS_MACRO_SELECT, SDLK_F11, VIMS_MOD_CTRL, "10" }, + { VIMS_MACRO_SELECT, SDLK_F12, VIMS_MOD_CTRL, "11" }, + { 0,0,0,NULL }, +}; +#endif + +#define VIMS_REQUIRE_ALL_PARAMS (1<<0) /* all params needed */ +#define VIMS_DONT_PARSE_PARAMS (1<<1) /* dont parse arguments */ +#define VIMS_LONG_PARAMS (1<<3) /* long string arguments (bundle, plugin) */ +#define VIMS_ALLOW_ANY (1<<4) /* use defaults when optional arguments are not given */ + +#define FORMAT_MSG(dst,str) sprintf(dst,"%03d%s",strlen(str),str) +#define APPEND_MSG(dst,str) veejay_strncat(dst,str,strlen(str)) +#define SEND_MSG_DEBUG(v,str) \ +{\ +char *__buf = str;\ +int __len = strlen(str);\ +int __done = 0;\ +veejay_msg(VEEJAY_MSG_INFO, "--------------------------------------------------------");\ +for(__done = 0; __len > (__done + 80); __done += 80)\ +{\ + char *__tmp = strndup( str+__done, 80 );\ +veejay_msg(VEEJAY_MSG_INFO, "[%d][%s]",strlen(str),__tmp);\ + if(__tmp) free(__tmp);\ +}\ +veejay_msg(VEEJAY_MSG_INFO, "[%s]", str + __done );\ +vj_server_send(v->vjs[0], v->uc->current_link, __buf, strlen(__buf));\ +veejay_msg(VEEJAY_MSG_INFO, "--------------------------------------------------------");\ +} + +#define SEND_DATA(v,buf,buflen)\ +{\ + int res_ = vj_server_send(v->vjs[VEEJAY_PORT_CMD], v->uc->current_link, (uint8_t*) buf, buflen);\ + if(res_ <= 0) { \ + _vj_server_del_client( v->vjs[VEEJAY_PORT_CMD], v->uc->current_link); \ + _vj_server_del_client( v->vjs[VEEJAY_PORT_STA], v->uc->current_link); \ + _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], v->uc->current_link); \ + return;\ + }\ +} + +#define SEND_MSG(v,str)\ +{\ +if(vj_server_send(v->vjs[VEEJAY_PORT_CMD], v->uc->current_link, (uint8_t*) str, strlen(str)) < 0) { \ + _vj_server_del_client( v->vjs[VEEJAY_PORT_CMD], v->uc->current_link); \ + _vj_server_del_client( v->vjs[VEEJAY_PORT_STA], v->uc->current_link); \ + _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], v->uc->current_link);} \ +} + +/* some macros for commonly used checks */ + +#define SAMPLE_PLAYING(v) ( (v->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE) ) +#define STREAM_PLAYING(v) ( (v->uc->playback_mode == VJ_PLAYBACK_MODE_TAG) ) +#define PLAIN_PLAYING(v) ( (v->uc->playback_mode == VJ_PLAYBACK_MODE_PLAIN) ) + +#define p_no_sample(a) { veejay_msg(VEEJAY_MSG_ERROR, "Sample %d does not exist",a); } +#define p_no_tag(a) { veejay_msg(VEEJAY_MSG_ERROR, "Stream %d does not exist",a); } +#define p_invalid_mode() { veejay_msg(VEEJAY_MSG_DEBUG, "Invalid playback mode for this action"); } +#define v_chi(v) ( (v < 0 || v >= SAMPLE_MAX_EFFECTS ) ) + +#define P_A(a,b,c,d)\ +{\ +int __z = 0;\ +unsigned char *__tmpstr = NULL;\ +if(a!=NULL){\ +unsigned int __rp;\ +unsigned int __rplen = (sizeof(a) / sizeof(int) );\ +for(__rp = 0; __rp < __rplen; __rp++) a[__rp] = 0;\ +}\ +while(*c) { \ +if(__z > _last_known_num_args ) break; \ +switch(*c++) {\ + case 's':\ +__tmpstr = (char*)va_arg(d,char*);\ +if(__tmpstr != NULL) {\ + sprintf( b,"%s",__tmpstr);\ + }\ +__z++ ;\ + break;\ + case 'd': a[__z] = *( va_arg(d, int*)); __z++ ;\ + break; }\ + }\ +} + +/* P_A16: Parse 16 integer arguments. This macro is used in 1 function */ +#define P_A16(a,c,d)\ +{\ +int __z = 0;\ +while(*c) { \ +if(__z > 15 ) break; \ +switch(*c++) { case 'd': a[__z] = va_arg(d, int); __z++ ; break; }\ +}}\ + + +#define DUMP_ARG(a)\ +if(sizeof(a)>0){\ +int __l = sizeof(a)/sizeof(int);\ +int __i; for(__i=0; __i < __l; __i++) veejay_msg(VEEJAY_MSG_DEBUG,"[%02d]=[%06d], ",__i,a[__i]);}\ +else { veejay_msg(VEEJAY_MSG_DEBUG,"arg has size of 0x0");} + + +#define CLAMPVAL(a) { if(a<0)a=0; else if(a >255) a =255; } +//@ FIXME: implement embedded help +//@ F1 -> sample playing FX=off -> standard help +//@ F1 -> sample playing FX=on entry >= 0 <= MAX_E : show help for FX on entry N +// +// +static struct { + const char *msg; +} embedded_help[] = { + { "'[' Set starting position of sample\n" }, + { "']' Set ending position and create new sample\n"}, + { "'F1-F12' Play sample (Bank * 12) + Fx\n"}, + { "'0-9' Select Bank 0-12\n"}, + { "'KP/' Toggle between plain and sample mode\n"}, + { "'A...L' Speed\n"}, + { "'A...L' + ALT Slow motion\n"}, + { "'KP8' Forward 1 second\n"}, + { "'KP2' Back 1 second\n"}, + { "'KP5' Pause playback\n"}, + { "'KP4' Play backward\n"}, + { "'KP6' Play forward\n"}, + { "'KP7' Back one frame\n"}, + { "'KP9' Forward one frame\n"}, + { "'KP1' Goto starting position\n"}, + { "'KP3' Goto ending position\n"}, + { "'KP*' Change sample looping\n"}, + { "Cursor Up/Down Select FX from FX list\n"}, + { "ENTER Add selected FX to current FX slot\n"}, + + NULL +}; + +static struct { + const char *msg; +} fx_embedded_help[] = { + { "'PgUp/PgDn' Inc/Dec FX parameter 0 "}, + { "'KP Ins/Del' Inc/Dec FX parameter 1 "}, + { "',/.' Inc/Dec FX parameter 2 "}, + { "'q/w' Inc/Dec FX parameter 3 "}, + { "'e/r' Inc/Dec FX parameter 4 "}, + { "'t/y' Inc/Dec FX parameter 5 "}, + { "'u/i' Inc/Dec FX parameter 6 "}, + { "'o/p' Inc/Dec FX parameter 7 "}, + {"'\nEND' Toggle FX Chain\n"}, + {"'Delete' Clear current FX slot\n"}, + { "'KP-' Down 1 position in FX chain\n"}, + { "'KP+' Up 1 position in FX chain\n"}, + { "-/+ Select mix-in source" }, + { "/ Toggle between stream and sample source"}, + NULL +}; + + +static char *get_arr_embedded_help(char *ehelp[]) +{ + int i; + int len = 0; + for( i = 0; ehelp[i] != NULL ; i ++ ) { + len += strlen(ehelp[i]); + } + if( len <= 0 ) + return NULL; + char *msg = (char*) vj_malloc(sizeof(char) * len ); + if( msg == NULL ) + return NULL; + veejay_memset( msg, 0, len ); + char *p = msg; + int x = 0; + for( i = 0; ehelp[i] != NULL; i ++ ) { + x = strlen(ehelp[i]); + strncpy(p,ehelp[i],x); + p += x; + } + return msg; +} + +char *get_embedded_help( int fx_mode, int play_mode, int fx_entry, int id ) +{ + char msg[16384]; + if( play_mode == VJ_PLAYBACK_MODE_PLAIN || ( play_mode == VJ_PLAYBACK_MODE_SAMPLE && fx_mode == 0 ) ) + { + return get_arr_embedded_help( embedded_help ); + } else { + veejay_memset(msg,0,sizeof(msg)); + int fx_id = 0; + if( play_mode == VJ_PLAYBACK_MODE_TAG ) { + fx_id = vj_tag_get_effect_any(id,fx_entry); + } else if( play_mode == VJ_PLAYBACK_MODE_SAMPLE ) { + fx_id = sample_get_effect_any(id,fx_entry); + } + if( fx_id <= 0 ) + return NULL; + + int n = vj_effect_get_num_params( fx_id ); + char *fx_descr = vj_effect_get_description(fx_id); + sprintf(msg,"FX slot %d:%s\n", fx_entry, fx_descr ); + char *p = msg + strlen(msg); + int i; + for( i = 0; i < n ; i ++ ) { //@ specific FX help + char name[128]; + char *descr = vj_effect_get_param_description(fx_id,i ); + snprintf(name,sizeof(name)-1,"%s'%s'\n",fx_embedded_help[i].msg,descr ); + int len = strlen(name); + strncpy(p, name, len ); + p += len; + //free(descr); + } + for( i = 0; fx_embedded_help[8+i].msg != NULL; i ++ ) { + int len = strlen(fx_embedded_help[8+i].msg); + strncpy(p, fx_embedded_help[8+i].msg, len ); + p += len; + } + return strdup(msg); + } + return NULL; +} + +static void init_vims_for_macro(); + +static void macro_select( int slot ) +{ + if( slot >= 0 && slot < 12 ) + { + macro_bank_[ current_macro_ ] = macro_port_; + current_macro_ = slot; + macro_port_ = macro_bank_[ current_macro_ ]; + if( !macro_port_ ) + { + if( macro_status_ == 1 ) + { + veejay_msg(VEEJAY_MSG_INFO, + "Continuing recording keystrokes in slot %d", current_macro_); + macro_bank_[ current_macro_ ] = + vpn(VEVO_ANONYMOUS_PORT ); + macro_port_ = macro_bank_[ current_macro_ ]; + } + else if (macro_status_ == 2 ) + { + veejay_msg(VEEJAY_MSG_INFO, + "No keystrokes found in slot %d", current_macro_); + } + } + macro_current_age_ = 0; + macro_expected_age_ = 0; + } +} + +static void replay_macro_(void) +{ + int i,k; + char **items; + + if(!macro_port_ ) + return; + + items = vevo_list_properties( macro_port_ ); + if(items) + { + int strokes = 0; + for(k = 0; items[k] != NULL ; k ++ ) + { + void *mb = NULL; + if( vevo_property_get( macro_port_, items[k],0,&mb ) == VEVO_NO_ERROR ) + { + macro_block_t *m = (macro_block_t*) mb; + for( i = 0; i < MAX_MACROS; i ++ ) + { + if(m->msg[i]) { m->pending[i] = 1; strokes ++; } + } + } + free(items[k]); + } + veejay_msg(VEEJAY_MSG_INFO, "Replay %d keystrokes in macro slot %d!", strokes, + current_macro_ ); + free(items); + } +} + +static void reset_macro_(void) +{ + int i,k; + char **items; + + if(!macro_port_ ) + return; + + items = vevo_list_properties( macro_port_ ); + if(items) + { + int strokes = 0; + for(k = 0; items[k] != NULL ; k ++ ) + { + void *mb = NULL; + if( vevo_property_get( macro_port_, items[k],0,&mb ) == VEVO_NO_ERROR ) + { + macro_block_t *m = (macro_block_t*) mb; + for( i = 0; i < MAX_MACROS; i ++ ) + if(m->msg[i]) { free(m->msg[i]); strokes ++; } + free(m); + } + free(items[k]); + } + veejay_msg(VEEJAY_MSG_INFO, "Cleared %d keystrokes from macro slot %d", + strokes, current_macro_ ); + free(items); + } + vevo_port_free(macro_port_); + macro_bank_[ current_macro_ ] = NULL; + macro_port_ = NULL; +} + +static char *retrieve_macro_(veejay_t *v, long frame, int idx ) +{ + void *mb = NULL; + char key[16]; + + int s = 0; + if( SAMPLE_PLAYING(v)) + s = sample_get_framedups( v->uc->sample_id ); + else if ( PLAIN_PLAYING(v)) + s = v->settings->simple_frame_dup; + + snprintf(key,16,"%08ld%02d", frame,s ); + + int error = vevo_property_get( macro_port_, key, 0, &mb ); + if( error == VEVO_NO_ERROR ) + { + if( idx == MAX_MACROS ) + return NULL; + + macro_block_t *m = (macro_block_t*) mb; + if( m->msg[idx ] && m->pending[idx] == 1 && m->age[idx] == macro_expected_age_) + { + m->pending[idx] = 0; + macro_expected_age_ ++; + return m->msg[idx]; + } + } + return NULL; +} + +static void store_macro_(veejay_t *v, char *str, long frame ) +{ + void *mb = NULL; + char key[16]; + int k; + int s = 0; + if( SAMPLE_PLAYING(v)) + s = sample_get_framedups( v->uc->sample_id ); + else if ( PLAIN_PLAYING(v)) + s = v->settings->simple_frame_dup; + + + snprintf(key,16,"%08ld%02d", frame,s ); + + int error = vevo_property_get( macro_port_, key, 0, &mb ); + if( error != VEVO_NO_ERROR ) + { // first element + macro_block_t *m = vj_calloc( sizeof(macro_block_t)); + m->msg[0] = strdup(str); + m->pending[0] = 1; + m->age[0] = macro_current_age_; + macro_current_age_++; + vevo_property_set( macro_port_, key, VEVO_ATOM_TYPE_VOIDPTR,1,&m ); + } + else + { + // following elements + macro_block_t *c = (macro_block_t*) mb; + for( k = 1; k < MAX_MACROS; k ++ ) + { + if(c->msg[k] == NULL ) + { + c->msg[k] = strdup(str); + c->pending[k] = 1; + c->age[k] = macro_current_age_; + macro_current_age_ ++; + return; + } + } + veejay_msg(VEEJAY_MSG_ERROR, "Slot for frame %ld is full (keystroke recorder)",frame ); + } + + veejay_msg(0, "key = %s, '%s' %ld", key,str,frame); + +} + + + +static hash_val_t int_bundle_hash(const void *key) +{ + return (hash_val_t) key; +} + +static int int_bundle_compare(const void *key1,const void *key2) +{ + return ((int)key1 < (int) key2 ? -1 : + ((int) key1 > (int) key2 ? +1 : 0)); +} + +typedef struct { + int event_id; + int accelerator; + int modifier; + char *bundle; +} vj_msg_bundle; + + +/* forward declarations (former console sample/tag print info) */ +#ifdef HAVE_SDL +vj_keyboard_event *new_keyboard_event( int symbol, int modifier, const char *value, int event_id ); +vj_keyboard_event *get_keyboard_event( int id ); +int keyboard_event_exists(int id); +int del_keyboard_event(int id ); +char *find_keyboard_default(int id); +#endif +void vj_event_print_plain_info(void *ptr, int x); +void vj_event_print_sample_info(veejay_t *v, int id); +void vj_event_print_tag_info(veejay_t *v, int id); +int vj_event_bundle_update( vj_msg_bundle *bundle, int bundle_id ); +vj_msg_bundle *vj_event_bundle_get(int event_id); +int vj_event_bundle_exists(int event_id); +int vj_event_suggest_bundle_id(void); +int vj_event_load_bundles(char *bundle_file); +int vj_event_bundle_store( vj_msg_bundle *m ); +int vj_event_bundle_del( int event_id ); +vj_msg_bundle *vj_event_bundle_new(char *bundle_msg, int event_id); +void vj_event_trigger_function(void *ptr, vj_event f, int max_args, const char format[], ...); +void vj_event_parse_bundle(veejay_t *v, char *msg ); +int vj_has_video(veejay_t *v, editlist *el); +void vj_event_fire_net_event(veejay_t *v, int net_id, char *str_arg, int *args, int arglen, int type); +void vj_event_commit_bundle( veejay_t *v, int key_num, int key_mod); +#ifdef HAVE_SDL +static vims_key_list * vj_event_get_keys( int event_id ); +int vj_event_single_fire(void *ptr , SDL_Event event, int pressed); +int vj_event_register_keyb_event(int event_id, int key_id, int key_mod, const char *args); +void vj_event_unregister_keyb_event(int key_id, int key_mod); +#endif + +#ifdef HAVE_XML2 +void vj_event_format_xml_event( xmlNodePtr node, int event_id ); +//void vj_event_format_xml_stream( xmlNodePtr node, int stream_id ); +#endif +void vj_event_init(void); + +int vj_has_video(veejay_t *v,editlist *el) +{ + if( el->is_empty ) + return 0; + if( !el->has_video) + return 0; + if( el->video_frames > 0 ) + return 1; + return 0; +} + +int vj_event_bundle_update( vj_msg_bundle *bundle, int bundle_id ) +{ + if(bundle) { + hnode_t *n = hnode_create(bundle); + if(!n) return 0; + hnode_put( n, (void*) bundle_id); + hnode_destroy(n); + return 1; + } + return 0; +} + +static void constrain_sample( veejay_t *v,int n ) +{ +#ifdef STRICT_CHECKING + assert( v->font != NULL ); +#endif + vj_font_set_dict(v->font, sample_get_dict(n) ); + // v->current_edit_list->video_fps, + vj_font_prepare( v->font, sample_get_startFrame(n), + sample_get_endFrame(n) ); + +} + +static void constrain_stream( veejay_t *v, int n, long hi ) +{ +#ifdef STRICT_CHECKING + assert(v->font != NULL ); +#endif + vj_font_set_dict(v->font, vj_tag_get_dict(n) ); + // v->current_edit_list->video_fps, + vj_font_prepare( v->font, 0, vj_tag_get_n_frames(n) ); +} + +vj_msg_bundle *vj_event_bundle_get(int event_id) +{ + vj_msg_bundle *m; + hnode_t *n = hash_lookup(BundleHash, (void*) event_id); + if(n) + { + m = (vj_msg_bundle*) hnode_get(n); + if(m) + { + return m; + } + } + return NULL; +} +#ifdef HAVE_SDL +void del_all_keyb_events() +{ + if(!keyboard_events) + return; + + if(!hash_isempty( keyboard_events )) + { + hscan_t scan; + hash_scan_begin( &scan, keyboard_events ); + hnode_t *node; + while( ( node = hash_scan_next(&scan)) != NULL ) + { + vj_keyboard_event *ev = NULL; + ev = hnode_get( node ); + if(ev) + { + if(ev->arguments) free(ev->arguments); + if(ev->vims) free(ev->vims); + } + } + hash_free_nodes( keyboard_events ); + hash_destroy( keyboard_events ); + } + + veejay_memset( keyboard_event_map_, 0, sizeof(keyboard_event_map_)); +} + +int del_keyboard_event(int id ) +{ + hnode_t *node; + vj_keyboard_event *ev = get_keyboard_event( id ); + + keyboard_event_map_[ id ] = NULL; + + if(ev == NULL) + return 0; + node = hash_lookup( keyboard_events, (void*) id ); + if(!node) + return 0; + if(ev->arguments) + free(ev->arguments); + if(ev->vims ) + free(ev->vims ); + hash_delete( keyboard_events, node ); + + return 1; +} + +vj_keyboard_event *get_keyboard_event(int id ) +{ + hnode_t *node = hash_lookup( keyboard_events, (void*) id ); + if(node) + return ((vj_keyboard_event*) hnode_get( node )); + return NULL; +} + +int keyboard_event_exists(int id) +{ + hnode_t *node = hash_lookup( keyboard_events, (void*) id ); + if(node) + if( hnode_get(node) != NULL ) + return 1; + return 0; +} + + +vj_keyboard_event *new_keyboard_event( + int symbol, int modifier, const char *value, int event_id ) +{ +// int vims_id = event_id; +/* if(vims_id == 0) + { + if(!vj_event_bundle_exists( event_id )) + { + veejay_msg(VEEJAY_MSG_ERROR, + "VIMS %d does not exist", event_id); + return NULL; + } + }*/ + + + if( event_id <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "VIMS event %d does not exist", event_id ); + return NULL; + } + + vj_keyboard_event *ev = (vj_keyboard_event*)vj_calloc(sizeof(vj_keyboard_event)); + if(!ev) + return NULL; + ev->vims = (vj_events*) vj_calloc(sizeof(vj_events)); + if(!ev->vims) + return NULL; + + ev->event_id = event_id; + + keyboard_event_map_ [ (modifier * SDLK_LAST) + symbol ] = ev; + + if(value) + { + ev->arg_len = strlen(value); + ev->arguments = strndup( value, ev->arg_len ); + } + else + { + if(event_id < VIMS_BUNDLE_START || event_id > VIMS_BUNDLE_END) + { + ev->arguments = find_keyboard_default( event_id ); + if(ev->arguments) + ev->arg_len = strlen(ev->arguments); + else + { + ev->arguments = NULL; + ev->arg_len = 0; + } + } + } + + if( vj_event_exists( event_id ) ) + { + ev->vims->act = (vj_event) vj_event_vevo_get_event_function( event_id ); + ev->vims->list_id = event_id; + } + else if ( vj_event_bundle_exists( event_id ) ) + { + ev->vims->act = vj_event_do_bundled_msg; + ev->vims->list_id = event_id; + } + ev->key_symbol = symbol; + ev->key_mod = modifier; + + return ev; +} +#endif + +int vj_event_bundle_exists(int event_id) +{ + hnode_t *n = hash_lookup( BundleHash, (void*) event_id ); + if(!n) + return 0; + return ( vj_event_bundle_get(event_id) == NULL ? 0 : 1); +} + +int vj_event_suggest_bundle_id(void) +{ + int i; + for(i=VIMS_BUNDLE_START ; i < VIMS_BUNDLE_END; i++) + { + if ( vj_event_bundle_exists(i ) == 0 ) return i; + } + + return -1; +} + +int vj_event_bundle_store( vj_msg_bundle *m ) +{ + hnode_t *n; + if(!m) return 0; + n = hnode_create(m); + if(!n) return 0; + if(!vj_event_bundle_exists(m->event_id)) + { + hash_insert( BundleHash, n, (void*) m->event_id); + } + else + { + hnode_put( n, (void*) m->event_id); + hnode_destroy( n ); + } + + // add bundle to VIMS list + veejay_msg(VEEJAY_MSG_DEBUG, + "Added Bundle VIMS %d to net_list", m->event_id ); + + net_list[ m->event_id ].list_id = m->event_id; + net_list[ m->event_id ].act = vj_event_none; + return 1; +} + +int vj_event_bundle_del( int event_id ) +{ + hnode_t *n; + vj_msg_bundle *m = vj_event_bundle_get( event_id ); + if(!m) return -1; + + n = hash_lookup( BundleHash, (void*) event_id ); + if(!n) + return -1; + + net_list[ m->event_id ].list_id = 0; + net_list[ m->event_id ].act = vj_event_none; + +#ifdef HAVE_SDL + vj_event_unregister_keyb_event( m->accelerator, m->modifier ); +#endif + if( m->bundle ) + free(m->bundle); + if(m) + free(m); + m = NULL; + + hash_delete( BundleHash, n ); + return 0; +} + +vj_msg_bundle *vj_event_bundle_new(char *bundle_msg, int event_id) +{ + vj_msg_bundle *m; + int len = 0; + if(!bundle_msg || strlen(bundle_msg) < 1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Doesn't make sense to store empty bundles in memory"); + return NULL; + } + len = strlen(bundle_msg); + m = (vj_msg_bundle*) malloc(sizeof(vj_msg_bundle)); + if(!m) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error allocating memory for bundled message"); + return NULL; + } + memset(m, 0, sizeof(m) ); + m->bundle = (char*) vj_calloc(sizeof(char) * len+1); + m->accelerator = 0; + m->modifier = 0; + if(!m->bundle) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error allocating memory for bundled message context"); + return NULL; + } + veejay_strncpy(m->bundle, bundle_msg, len); + + m->event_id = event_id; + + veejay_msg(VEEJAY_MSG_DEBUG, + "New VIMS Bundle %d [%s] created", + event_id, m->bundle ); + + return m; +} + + +void vj_event_trigger_function(void *ptr, vj_event f, int max_args, const char *format, ...) +{ + va_list ap; + va_start(ap,format); + f(ptr, format, ap); + va_end(ap); +} + + + +/* parse a keyframe packet */ +void vj_event_parse_kf( veejay_t *v, unsigned char *msg, int len ) +{ + if(SAMPLE_PLAYING(v)) + { + if(sample_chain_set_kfs( v->uc->sample_id, len, msg )==-1) + veejay_msg(VEEJAY_MSG_ERROR,"(VIMS) Invalid key frame blob [%s]",msg); + } + else if (STREAM_PLAYING(v)) + { + if(vj_tag_chain_set_kfs(v->uc->sample_id,len,msg ) == -1) + veejay_msg(VEEJAY_MSG_ERROR, "(VIMS) Invalid key frame blob [%s]",msg); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "(VIMS) Cannot store key frame in this playback mode"); + } +} + + +/* parse a message received from network */ +void vj_event_parse_bundle(veejay_t *v, char *msg ) +{ + + int num_msg = 0; + int offset = 3; + int i = 0; + + + if ( msg[offset] == ':' ) + { + int j = 0; + offset += 1; /* skip ':' */ + if( sscanf(msg+offset, "%03d", &num_msg )<= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR,"(VIMS) Invalid number of messages. Skipping message [%s] ",msg); + } + if ( num_msg <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR,"(VIMS) Invalid number of message given to execute. Skipping message [%s]",msg); + return; + } + + offset += 3; + + if ( msg[offset] != '{' ) + { + veejay_msg(VEEJAY_MSG_ERROR, "(VIMS) 'al' expected. Skipping message [%s]",msg); + return; + } + + offset+=1; /* skip # */ + + for( i = 1; i <= num_msg ; i ++ ) /* iterate through message bundle and invoke parse_msg */ + { + char atomic_msg[256]; + int found_end_of_msg = 0; + int total_msg_len = strlen(msg); + veejay_memset( atomic_msg,0,256 ); + while( (offset+j) < total_msg_len) + { + if(msg[offset+j] == '}') + { + return; /* dont care about semicolon here */ + } + else + if(msg[offset+j] == ';') + { + found_end_of_msg = offset+j+1; + veejay_strncpy(atomic_msg, msg+offset, (found_end_of_msg-offset)); + atomic_msg[ (found_end_of_msg-offset) ] ='\0'; + offset += j + 1; + j = 0; + vj_event_parse_msg( v, atomic_msg, strlen(atomic_msg) ); + } + j++; + } + } + } +} + +void vj_event_dump() +{ + vj_event_vevo_dump(); + + vj_osc_dump(); + +} + +typedef struct { + void *value; +} vims_arg_t; + +static void dump_arguments_(int net_id,int arglen, int np, int prefixed, char *fmt) +{ + int i; + char *name = vj_event_vevo_get_event_name( net_id ); + veejay_msg(VEEJAY_MSG_ERROR, "VIMS '%03d' : '%s'", net_id, name ); + if(np < arglen) { + veejay_msg(VEEJAY_MSG_ERROR, "\tOnly %d arguments of %d seen",arglen,np); + } else { + veejay_msg(VEEJAY_MSG_ERROR, "\tToo many parameters! %d of %d",np,arglen); + } + veejay_msg(VEEJAY_MSG_ERROR, "\tFormat is '%s'", fmt ); + + for( i = prefixed; i < np; i ++ ) + { + char *help = vj_event_vevo_help_vims( net_id, i ); + veejay_msg(VEEJAY_MSG_ERROR,"\t\tArgument %d : %s", + i,help ); + if(help) free(help); + } +} + +static int vvm_[600]; + +static void init_vims_for_macro() +{ + veejay_memset( vvm_,1, sizeof(vvm_)); + vvm_[VIMS_MACRO] = 0; + vvm_[VIMS_TRACK_LIST] = 0; + vvm_[VIMS_RGB24_IMAGE] = 0; + vvm_[VIMS_SET_SAMPLE_START] =0; + vvm_[VIMS_SET_SAMPLE_END] = 0; + vvm_[VIMS_SAMPLE_NEW] = 0; + vvm_[VIMS_SAMPLE_DEL] = 0; + vvm_[VIMS_STREAM_DELETE] = 0; + vvm_[VIMS_SAMPLE_LOAD_SAMPLELIST]=0; + vvm_[VIMS_SAMPLE_SAVE_SAMPLELIST]=0; + vvm_[VIMS_SAMPLE_DEL_ALL] = 0; + vvm_[VIMS_SAMPLE_COPY] = 0; + vvm_[VIMS_SAMPLE_UPDATE] = 0; + vvm_[VIMS_SAMPLE_KF_GET]=0; + vvm_[VIMS_SAMPLE_KF_RESET]=0; + vvm_[VIMS_SAMPLE_KF_STATUS]=0; + vvm_[VIMS_STREAM_NEW_V4L] = 0; + vvm_[VIMS_STREAM_NEW_DV1394] = 0; + vvm_[VIMS_STREAM_NEW_COLOR] = 0; + vvm_[VIMS_STREAM_NEW_Y4M] = 0; + vvm_[VIMS_STREAM_NEW_UNICAST]=0; + vvm_[VIMS_STREAM_NEW_MCAST]=0; + vvm_[VIMS_STREAM_NEW_PICTURE]=0; + vvm_[VIMS_STREAM_SET_DESCRIPTION]=0; + vvm_[VIMS_SAMPLE_SET_DESCRIPTION]=0; + vvm_[VIMS_STREAM_SET_LENGTH]=0; + vvm_[VIMS_SEQUENCE_STATUS]=0; + vvm_[VIMS_SEQUENCE_ADD]=0; + vvm_[VIMS_SEQUENCE_DEL]=0; + vvm_[VIMS_CHAIN_LIST]=0; + vvm_[VIMS_OUTPUT_Y4M_START]=0; + vvm_[VIMS_OUTPUT_Y4M_STOP]=0; + vvm_[VIMS_GET_FRAME]=0; + vvm_[VIMS_VLOOPBACK_START]=0; + vvm_[VIMS_VLOOPBACK_STOP]=0; + vvm_[VIMS_VIDEO_MCAST_START]=0; + vvm_[VIMS_VIDEO_MCAST_STOP]=0; + vvm_[VIMS_SYNC_CORRECTION]=0; + vvm_[VIMS_NO_CACHING]=0; + vvm_[VIMS_SCREENSHOT]=0; + vvm_[VIMS_RGB_PARAMETER_TYPE]=0; + vvm_[VIMS_RESIZE_SDL_SCREEN] =0; + vvm_[VIMS_DEBUG_LEVEL]=0; + vvm_[VIMS_SAMPLE_MODE]=0; + vvm_[VIMS_BEZERK] = 0; + vvm_[VIMS_AUDIO_ENABLE]=0; + vvm_[VIMS_AUDIO_DISABLE]=0; + vvm_[VIMS_RECORD_DATAFORMAT]=0; + vvm_[VIMS_INIT_GUI_SCREEN]=0; + vvm_[VIMS_SUSPEND]=0; + vvm_[VIMS_VIEWPORT]=0; + vvm_[VIMS_PREVIEW_BW]=0; + vvm_[VIMS_FRONTBACK]=0; + vvm_[VIMS_RECVIEWPORT]=0; + vvm_[VIMS_PROJECTION] = 0; +} + +static int valid_for_macro(int net_id) +{ + int k; + if(net_id > 400 || net_id >= 388 || (net_id >= 80 && net_id <= 86) || (net_id >= 50 && net_id <= 59)) + return 0; + + return vvm_[net_id]; +} + +static void dump_argument_( int net_id , int i ) +{ + char *help = vj_event_vevo_help_vims( net_id, i ); + veejay_msg(VEEJAY_MSG_ERROR,"\t\tArgument %d : %s", + i,help ); + if(help) free(help); +} + +static int vj_event_verify_args( int *fx, int net_id , int arglen, int np, int prefixed, char *fmt ) +{ + if(net_id != VIMS_CHAIN_ENTRY_SET_PRESET ) + { + if( arglen != np ) + { + dump_arguments_(net_id,arglen, np, prefixed, fmt); + return 0; + } + } + else + { + if( arglen <= 3 ) + { + dump_arguments_(net_id, arglen,np,prefixed, fmt ); + return 0; + } + int fx_id = fx[2]; + if( fx_id <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid Effect ID" ); + return 0; + } + else + { + int fx_p = vj_effect_get_num_params( fx_id ); + int fx_c = vj_effect_get_extra_frame( fx_id ); + int min = fx_p + (prefixed > 0 ? 0: 3); + int max = min + ( fx_c ? 2 : 0 ) + prefixed; + int a_len = arglen -( prefixed > 0 ? prefixed - 1: 0 ); + if( a_len < min || a_len > max ) + { + if( a_len < min ) + veejay_msg(VEEJAY_MSG_ERROR,"Invalid number of parameters for Effect %d (Need %d, only have %d)", fx_id, + min, a_len ); + if( a_len > max ) + veejay_msg(VEEJAY_MSG_ERROR,"Invalid number of parameters for Effect %d (At most %d, have %d)",fx_id, + max, a_len ); + return 0; + } + if( a_len > min && a_len < max ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid mixing source given for Effect %d , use ",fx_id); + return 0; + } + } + } + return 1; +} + +void vj_event_fire_net_event(veejay_t *v, int net_id, char *str_arg, int *args, int arglen, int prefixed) +{ + int np = vj_event_vevo_get_num_args(net_id); + char *fmt = vj_event_vevo_get_event_format( net_id ); + int flags = vj_event_vevo_get_flags( net_id ); + int fmt_offset = 1; + vims_arg_t vims_arguments[16]; + memset( vims_arguments, 0, sizeof(vims_arguments) ); + + if(!vj_event_verify_args(args , net_id, arglen, np, prefixed, fmt )) + { + if(fmt) free(fmt); + return; + } + + if( np == 0 ) + { + vj_event_vevo_inline_fire_default( (void*) v, net_id, fmt ); + if(fmt) free(fmt); + return; + } + + int i=0; + while( i < arglen ) + { + if( fmt[fmt_offset] == 'd' ) + { + vims_arguments[i].value = (void*) &(args[i]); + } + if( fmt[fmt_offset] == 's' ) + { + if(str_arg == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Argument %d must be a string! (VIMS %03d)", i,net_id ); + if(fmt) free(fmt); + return; + } + vims_arguments[i].value = (void*) strdup( str_arg ); + if(flags & VIMS_REQUIRE_ALL_PARAMS ) + { + if( strlen((char*)vims_arguments[i].value) <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Argument %d is not a string!",i ); + if(fmt)free(fmt); + return; + } + } + } + fmt_offset += 3; + i++; + } + _last_known_num_args = arglen; + + while( i < np ) + { + int dv = vj_event_vevo_get_default_value( net_id, i); + if( fmt[fmt_offset] == 'd' ) + { + vims_arguments[i].value = (void*) &(dv); + } + i++; + } + + vj_event_vevo_inline_fire( (void*) v, net_id, + fmt, + vims_arguments[0].value, + vims_arguments[1].value, + vims_arguments[2].value, + vims_arguments[3].value, + vims_arguments[4].value, + vims_arguments[5].value, + vims_arguments[6].value, + vims_arguments[7].value, + vims_arguments[8].value, + vims_arguments[9].value, + vims_arguments[10].value, + vims_arguments[11].value, + vims_arguments[12].value, + vims_arguments[13].value, + vims_arguments[14].value, + vims_arguments[15].value); + fmt_offset = 1; + for ( i = 0; i < np ; i ++ ) + { + if( vims_arguments[i].value && + fmt[fmt_offset] == 's' ) + free( vims_arguments[i].value ); + fmt_offset += 3; + } + if(fmt) + free(fmt); + +} + +static int inline_str_to_int(const char *msg, int *val) +{ + char longest_num[16]; + int str_len = 0; + if( sscanf( msg , "%d", val ) <= 0 ) + return 0; + veejay_memset(longest_num,0, 16 ); + sprintf(longest_num, "%d", *val ); + + str_len = strlen( longest_num ); + return str_len; +} + +static char *inline_str_to_str(int flags, char *msg) +{ + char *res = NULL; + int len = strlen(msg); + if( len <= 0 ) + return res; + + if( (flags & VIMS_LONG_PARAMS) ) /* copy rest of message */ + { + res = (char*) vj_calloc(sizeof(char) * (len+1) ); + veejay_strncpy( res, msg, len ); + } + else + { + char str[255]; + veejay_memset(str,0, sizeof(str) ); + if(sscanf( msg, "%s", str ) <= 0 ) + return res; + res = strndup( str, 255 ); + } + return res; +} + +int vj_event_parse_msg( void *ptr, char *msg, int msg_len ) +{ + veejay_t *v = (veejay_t*)ptr; + char head[5] = { 0,0,0,0,0}; + int net_id = 0; + int np = 0; + if( msg == NULL ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Dropped empty VIMS message."); + return 0; + } + + if( msg_len < MSG_MIN_LEN ) + { + veejay_msg(VEEJAY_MSG_ERROR, "VIMS Message too small (%s), dropped!",msg); + return 0; + + } + + veejay_memcpy(head,msg,4); + + if( strncasecmp( head, "bun", 3 ) == 0 ) + { + veejay_chomp_str( msg, &msg_len ); + vj_event_parse_bundle( v, msg ); + return 1; + } + + if( strncasecmp( head, "key", 3 ) == 0 ) + { + vj_event_parse_kf( v, msg, msg_len ); + return 1; + } + + veejay_chomp_str( msg, &msg_len ); + msg_len --; + + /* try to scan VIMS id */ + if ( sscanf( head, "%03d", &net_id ) != 1 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error parsing VIMS selector"); + return 0; + } +#ifdef STRICT_CHECKING + char *dbg_msg = vj_event_vevo_get_event_name( net_id ); + if( dbg_msg == NULL ) { + veejay_msg(VEEJAY_MSG_WARNING, "No event knownn by '%d' (%s)", net_id,msg ); + } else { + veejay_msg(VEEJAY_MSG_DEBUG, "VIMS '%s' %s", + msg,dbg_msg ); + } +#endif +#ifndef STRICT_CHECKING + if( net_id != 412 && net_id != 333) +#else + + veejay_msg(VEEJAY_MSG_DEBUG, "VIMS: @%ld Parse message '%s'",v->settings->current_frame_num, msg ); + +#endif + if( net_id <= 0 || net_id >= VIMS_MAX ) + { + veejay_msg(VEEJAY_MSG_ERROR, "VIMS Selector %d invalid", net_id ); + return 0; + } + + /* verify format */ + if( msg[3] != 0x3a || msg[msg_len] != ';' ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Syntax error in VIMS message"); + if( msg[3] != 0x3a ) + { + veejay_msg(VEEJAY_MSG_ERROR, "\tExpected ':' after VIMS selector"); + return 0; + } + if( msg[msg_len] != ';' ) + { + veejay_msg(VEEJAY_MSG_ERROR, "\tExpected ';' to terminate VIMS message"); + return 0; + } + } + + if ( net_id >= VIMS_BUNDLE_START && net_id < VIMS_BUNDLE_END ) + { + vj_msg_bundle *bun = vj_event_bundle_get(net_id ); + if(!bun) + { + veejay_msg(VEEJAY_MSG_ERROR, "(VIMS) internal error: Bundle %d not registered"); + return 0; + } + vj_event_parse_bundle( v, bun->bundle ); + return 1; + } + + if( net_id >= 400 && net_id < 499 ) + vj_server_client_promote( v->vjs[VEEJAY_PORT_CMD] , v->uc->current_link ); + + np = vj_event_vevo_get_num_args( net_id ); + + if ( msg_len <= MSG_MIN_LEN ) + { + int i_args[16]; + int i = 0; + while( i < np ) + { + i_args[i] = vj_event_vevo_get_default_value( net_id, i ); + i++; + } + vj_event_fire_net_event( v, net_id, NULL, i_args, np, 0 ); + if( macro_status_ == 1 && macro_port_ != NULL) + { + if( valid_for_macro(net_id)) + store_macro_( v,msg, v->settings->current_frame_num ); + } + + } + else + { + char *arguments = NULL; + char *fmt = vj_event_vevo_get_event_format( net_id ); + int flags = vj_event_vevo_get_flags( net_id ); + int i = 0; + int i_args[16]; + char *str = NULL; + int fmt_offset = 1; + char *arg_str = NULL; + memset( i_args, 0, sizeof(i_args) ); + + arg_str = arguments = strndup( msg + 4 , msg_len - 4 ); + + if( arguments == NULL ) + { + dump_arguments_( net_id, 0, np, 0, fmt ); + if(fmt) free(fmt ); + return 0; + } + if( np <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "VIMS %d accepts no arguments", net_id ); + if(fmt) free(fmt); + return 0; + } + + while( i < np ) + { + if( fmt[fmt_offset] == 'd' ) + i_args[i] = vj_event_vevo_get_default_value(net_id, i); + i++; + } + + for( i = 0; i < np; i ++ ) + { + int failed_arg = 1; + + if( fmt[fmt_offset] == 'd' ) + { + int il = inline_str_to_int( arguments, &i_args[i] ); + if( il > 0 ) + { + failed_arg = 0; + arguments += il; + } + } + if( fmt[fmt_offset] == 's' && str == NULL) + { + str = inline_str_to_str( flags,arguments ); + if(str != NULL ) + { + failed_arg = 0; + arguments += strlen(str); + } + } + + if( failed_arg ) + { + char *name = vj_event_vevo_get_event_name( net_id ); + veejay_msg(VEEJAY_MSG_ERROR, "Invalid argument %d for VIMS '%03d' : '%s' ", + i, net_id, name ); + if(name) free(name); + dump_argument_( net_id, i ); + if(fmt) free(fmt); + return 0; + } + + if( *arguments == ';' || *arguments == 0 ) + break; + fmt_offset += 3; + + if( *arguments == 0x20 ) + *arguments ++; + } + + i ++; + + if( flags & VIMS_ALLOW_ANY ) + i = np; + + if( macro_status_ == 1 && macro_port_ != NULL) + { + if( valid_for_macro(net_id)) + store_macro_( v,msg, v->settings->current_frame_num ); + } + vj_event_fire_net_event( v, net_id, str, i_args, i, 0 ); + + + if(fmt) free(fmt); + if(arg_str) free(arg_str); + if(str) free(str); + + return 1; + + } + return 0; +} + +void vj_event_update_remote(void *ptr) +{ + veejay_t *v = (veejay_t*)ptr; + int i; + + if( vj_server_poll( v->vjs[VEEJAY_PORT_CMD] ) ) + vj_server_new_connection( v->vjs[VEEJAY_PORT_CMD] ); + if( vj_server_poll( v->vjs[VEEJAY_PORT_STA] ) ) + vj_server_new_connection( v->vjs[VEEJAY_PORT_STA] ); + + if( vj_server_poll( v->vjs[VEEJAY_PORT_DAT] ) ) + { + vj_server_new_connection( v->vjs[VEEJAY_PORT_DAT] ); + } + + if( v->settings->use_vims_mcast ) + { + int res = vj_server_update(v->vjs[VEEJAY_PORT_MAT],0 ); + if(res > 0) + { + v->uc->current_link = 0; + char *buf = NULL; + int len =0; + while( ( buf = vj_server_retrieve_msg( v->vjs[VEEJAY_PORT_MAT], 0, buf,&len )) != NULL ) + { + + vj_event_parse_msg( v, buf,len ); + } + } + + } + + v->settings->is_dat = 0; + for( i = 0; i < VJ_MAX_CONNECTIONS; i ++ ) + { + if( vj_server_link_used( v->vjs[VEEJAY_PORT_CMD], i ) ) + { + int res = 1; + while( res != 0 ) + { + res = vj_server_update( v->vjs[VEEJAY_PORT_CMD], i ); + if(res>0) + { + v->uc->current_link = i; + int n = 0; + int len = 0; + char *buf = NULL; + while( (buf= vj_server_retrieve_msg(v->vjs[VEEJAY_PORT_CMD],i,buf, &len))!= NULL ) + { + vj_event_parse_msg( v, buf,len ); + n++; + } + } + if( res == -1 ) + { + _vj_server_del_client( v->vjs[VEEJAY_PORT_CMD], i ); + _vj_server_del_client( v->vjs[VEEJAY_PORT_STA], i ); + _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], i ); + } + } + } + } + + v->settings->is_dat = 1; + for( i = 0; i < VJ_MAX_CONNECTIONS; i ++ ) + { + if( vj_server_link_used( v->vjs[VEEJAY_PORT_DAT], i ) ) + { + int res = 1; + while( res != 0 ) + { + res = vj_server_update( v->vjs[VEEJAY_PORT_DAT], i ); + if(res>0) + { + v->uc->current_link = i; + int n = 0; + int len = 0; + char *buf = NULL; + while( (buf= vj_server_retrieve_msg(v->vjs[VEEJAY_PORT_DAT],i,buf, &len))!= NULL ) + { + vj_event_parse_msg( v, buf,len ); + n++; + } + } + if( res == -1 ) + { + _vj_server_del_client( v->vjs[VEEJAY_PORT_DAT], i ); + _vj_server_del_client( v->vjs[VEEJAY_PORT_CMD], i ); + _vj_server_del_client( v->vjs[VEEJAY_PORT_STA], i ); + } + } + } + } + + //@ repeat macros + if(macro_status_ == 2 && macro_port_ != NULL) + { + int n_macro = 0; + char *macro_msg = NULL; + for( n_macro = 0; n_macro < MAX_MACROS ; n_macro ++ ) + { + macro_msg = retrieve_macro_( v, v->settings->current_frame_num, n_macro ); + if(macro_msg) + vj_event_parse_msg(v,macro_msg, strlen(macro_msg)); + } + } + + + v->settings->is_dat = 0; + + + for( i = 0; i < VJ_MAX_CONNECTIONS; i ++ ) + if( vj_server_link_used( v->vjs[VEEJAY_PORT_STA], i )) + veejay_pipe_write_status( v, i ); + + if(!veejay_keep_messages()) + veejay_reap_messages(); +} + +void vj_event_commit_bundle( veejay_t *v, int key_num, int key_mod) +{ + char bundle[4096]; + veejay_memset(bundle,0,4096); + vj_event_create_effect_bundle(v, bundle, key_num, key_mod ); +} + +#ifdef HAVE_SDL +int vj_event_single_fire(void *ptr , SDL_Event event, int pressed) +{ + + SDL_KeyboardEvent *key = &event.key; + SDLMod mod = key->keysym.mod; + veejay_t *v = (veejay_t*) ptr; + int vims_mod = 0; + + if( (mod & KMOD_LSHIFT) || (mod & KMOD_RSHIFT )) + vims_mod = VIMS_MOD_SHIFT; + if( (mod & KMOD_LALT) || (mod & KMOD_ALT) ) + vims_mod = VIMS_MOD_ALT; + if( (mod & KMOD_CTRL) || (mod & KMOD_CTRL) ) + vims_mod = VIMS_MOD_CTRL; + + int vims_key = key->keysym.sym; + int index = vims_mod * SDLK_LAST + vims_key; + + vj_keyboard_event *ev = get_keyboard_event( index ); + if(!ev ) + { + // veejay_msg(VEEJAY_MSG_ERROR,"Keyboard event %d unknown", index ); + if( event.button.button == SDL_BUTTON_WHEELUP && v->use_osd != 3 ) { + char msg[100]; + sprintf(msg,"%03d:;", VIMS_VIDEO_SKIP_SECOND ); + vj_event_parse_msg( (veejay_t*) ptr, msg, strlen(msg) ); + return 1; + } else if (event.button.button == SDL_BUTTON_WHEELDOWN && v->use_osd != 3) { + char msg[100]; + sprintf(msg,"%03d:;", VIMS_VIDEO_PREV_SECOND ); + vj_event_parse_msg( (veejay_t*) ptr, msg, strlen(msg) ); + return 1; + } + return 0; + } + + int event_id = ev->vims->list_id; + if( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END ) + { + vj_msg_bundle *bun = vj_event_bundle_get(event_id ); + if(!bun) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Requested BUNDLE %d does not exist", event_id); + return; + } + vj_event_parse_bundle( (veejay_t*) ptr, bun->bundle ); + } + else + { + char msg[100]; + if( ev->arg_len > 0 ) + { + sprintf(msg,"%03d:%s;", event_id, ev->arguments ); + } + else + sprintf(msg,"%03d:;", event_id ); + vj_event_parse_msg( (veejay_t*) ptr, msg, strlen(msg) ); + } + return 1; +} + +#endif +#ifdef HAVE_GL +void vj_event_single_gl_fire(void *ptr , int mod, int key) +{ + int vims_mod = 0; +#ifndef HAVE_SDL + return; +#else + switch( key ) + { + case 0xff0d: key = SDLK_RETURN; break; + case 0xff1b: key = SDLK_ESCAPE; break; + case 0xffbe: key = SDLK_F1; break; + case 0xffbf: key = SDLK_F2; break; + case 0xffc0: key = SDLK_F3; break; + case 0xffc1: key = SDLK_F4; break; + case 0xffc2: key = SDLK_F5; break; + case 0xffc3: key = SDLK_F6; break; + case 0xffc4: key = SDLK_F7; break; + case 0xffc5: key = SDLK_F8; break; + case 0xffc6: key = SDLK_F9; break; + case 0xffc7: key = SDLK_F10; break; + case 0xffc8: key = SDLK_F11; break; + case 0xffc9: key = SDLK_F12; break; + case 0xff63: key = SDLK_INSERT; break; + case 0xff50: key = SDLK_HOME; break; + case 0xff55: key = SDLK_PAGEUP; break; + case 0xff56: key = SDLK_PAGEDOWN; break; + case 0xff57: key = SDLK_END; break; + case 0xffff: key = SDLK_DELETE;break; + case 0xff08: key = SDLK_BACKSPACE;break; + case 0xff52: key = SDLK_UP; break; + case 0xff53: key = SDLK_RIGHT; break; + case 0xff54: key = SDLK_DOWN; break; + case 0xff51: key = SDLK_LEFT; break; + case 0xffaa: key = SDLK_KP_MULTIPLY; break; + case 0xffb0: key = SDLK_KP0; break; + case 0xffb1: case 0xff9c: key = SDLK_KP1; break; + case 0xffb2: case 0xff99: key = SDLK_KP2; break; + case 0xffb3: case 0xff9b: key = SDLK_KP3; break; + case 0xffb4: case 0xff96: key = SDLK_KP4; break; + case 0xffb5: case 0xff9d: key = SDLK_KP5; break; + case 0xffb6: case 0xff98: key = SDLK_KP6; break; + case 0xffb7: case 0xff95: key = SDLK_KP7; break; + case 0xffb8: case 0xff97: key = SDLK_KP8; break; + case 0xffb9: case 0xff9a: key = SDLK_KP9; break; + case 0xffab: key = SDLK_KP_PLUS; break; + case 0xffad: key = SDLK_KP_MINUS; break; + case 0xff8d: key = SDLK_KP_ENTER; break; + case 0xffaf: key = SDLK_KP_DIVIDE; break; + case 0xff9e: case 0xff9f: key = SDLK_KP_PERIOD; break; + case 65507: key = SDLK_s; mod = 2; break; + default: + if( key > (256+128)) + veejay_msg(VEEJAY_MSG_DEBUG, "\tUnknown key pressed %x, mod = %d", key, mod ); + break; + + } + + switch( mod ) + { + case 1: + case 17: + vims_mod = VIMS_MOD_SHIFT; break; + case 4: + case 20: + vims_mod = VIMS_MOD_CTRL; break; + case 8: + case 24: + case 144: + vims_mod = VIMS_MOD_ALT; break; + default: + veejay_msg(VEEJAY_MSG_DEBUG, "\tUnknown modifier pressed %x, mod = %d", key , mod ); + break; + + } + + + int vims_key = key; + int index = vims_mod * SDLK_LAST + vims_key; + + vj_keyboard_event *ev = get_keyboard_event( index ); + if(!ev ) + { + veejay_msg(VEEJAY_MSG_ERROR,"Keyboard event %d unknown", index ); + return; + } + + // event_id is here VIMS list entry! + int event_id = ev->vims->list_id; + + if( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END ) + { + vj_msg_bundle *bun = vj_event_bundle_get(event_id ); + if(!bun) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Requested BUNDLE %d does not exist", event_id); + return; + } + vj_event_parse_bundle( (veejay_t*) ptr, bun->bundle ); + } + else + { + char msg[100]; + if( ev->arg_len > 0 ) + { + sprintf(msg,"%03d:%s;", event_id, ev->arguments ); + } + else + sprintf(msg,"%03d:;", event_id ); + vj_event_parse_msg( (veejay_t*) ptr, msg,strlen(msg) ); + } +#endif +} + + +#endif +void vj_event_none(void *ptr, const char format[], va_list ap) +{ + veejay_msg(VEEJAY_MSG_DEBUG, "No action implemented for requested event"); +} + +#ifdef HAVE_XML2 +static int get_cstr( xmlDocPtr doc, xmlNodePtr cur, const xmlChar *what, char *dst ) +{ + xmlChar *tmp = NULL; + char *t = NULL; + if(! xmlStrcmp( cur->name, what )) + { + tmp = xmlNodeListGetString( doc, cur->xmlChildrenNode,1 ); + t = UTF8toLAT1(tmp); + if(!t) + return 0; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Load string property '%s' with value '%s'", + cur->name, t); +#endif + + veejay_strncpy( dst, t, strlen(t) ); + free(t); + xmlFree(tmp); + return 1; + } + return 0; +} +static int get_fstr( xmlDocPtr doc, xmlNodePtr cur, const xmlChar *what, float *dst ) +{ + xmlChar *tmp = NULL; + char *t = NULL; + float tmp_f = 0; + int n = 0; + if(! xmlStrcmp( cur->name, what )) + { + tmp = xmlNodeListGetString( doc, cur->xmlChildrenNode,1 ); + t = UTF8toLAT1(tmp); + if(!t) + return 0; +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Load float property '%s' with value '%s'", + cur->name, t); +#endif + + n = sscanf( t, "%f", &tmp_f ); + free(t); + xmlFree(tmp); + + if( n ) + *dst = tmp_f; + else + return 0; + + return 1; + } + return 0; +} + +static int get_istr( xmlDocPtr doc, xmlNodePtr cur, const xmlChar *what, int *dst ) +{ + xmlChar *tmp = NULL; + char *t = NULL; + int tmp_i = 0; + int n = 0; + if(! xmlStrcmp( cur->name, what )) + { + tmp = xmlNodeListGetString( doc, cur->xmlChildrenNode,1 ); + t = UTF8toLAT1(tmp); + if(!t) + { + veejay_msg(VEEJAY_MSG_ERROR, "Input not in UTF8 format!"); + return 0; + } +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "Load int property '%s' with value '%s'", + cur->name, t); +#endif + + n = sscanf( t, "%d", &tmp_i ); + free(t); + xmlFree(tmp); + + if( n ) + *dst = tmp_i; + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot convert value '%s'to number", t); + return 0; + } + return 1; + } + return 0; +} +#define XML_CONFIG_STREAM "stream" +#define XML_CONFIG_STREAM_SOURCE "source" +#define XML_CONFIG_STREAM_FILENAME "filename" +#define XML_CONFIG_STREAM_TYPE "type" +#define XML_CONFIG_STREAM_COLOR "rgb" +#define XML_CONFIG_STREAM_OPTION "option" +#define XML_CONFIG_STREAM_CHAIN "fxchain" + +#define XML_CONFIG_KEY_SYM "key_symbol" +#define XML_CONFIG_KEY_MOD "key_modifier" +#define XML_CONFIG_KEY_VIMS "vims_id" +#define XML_CONFIG_KEY_EXTRA "extra" +#define XML_CONFIG_EVENT "event" +#define XML_CONFIG_FILE "config" +#define XML_CONFIG_SETTINGS "run_settings" +#define XML_CONFIG_SETTING_PORTNUM "port_num" +#define XML_CONFIG_SETTING_HOSTNAME "hostname" +#define XML_CONFIG_SETTING_PRIOUTPUT "primary_output" +#define XML_CONFIG_SETTING_PRINAME "primary_output_destination" +#define XML_CONFIG_SETTING_SDLSIZEX "SDLwidth" +#define XML_CONFIG_SETTING_SDLSIZEY "SDLheight" +#define XML_CONFIG_SETTING_AUDIO "audio" +#define XML_CONFIG_SETTING_SYNC "sync" +#define XML_CONFIG_SETTING_TIMER "timer" +#define XML_CONFIG_SETTING_FPS "output_fps" +#define XML_CONFIG_SETTING_GEOX "Xgeom_x" +#define XML_CONFIG_SETTING_GEOY "Xgeom_y" +#define XML_CONFIG_SETTING_BEZERK "bezerk" +#define XML_CONFIG_SETTING_COLOR "nocolor" +#define XML_CONFIG_SETTING_YCBCR "chrominance_level" +#define XML_CONFIG_SETTING_WIDTH "output_width" +#define XML_CONFIG_SETTING_HEIGHT "output_height" +#define XML_CONFIG_SETTING_DFPS "dummy_fps" +#define XML_CONFIG_SETTING_DUMMY "dummy" +#define XML_CONFIG_SETTING_NORM "video_norm" +#define XML_CONFIG_SETTING_MCASTOSC "mcast_osc" +#define XML_CONFIG_SETTING_MCASTVIMS "mcast_vims" +#define XML_CONFIG_SETTING_SCALE "output_scaler" +#define XML_CONFIG_SETTING_PMODE "play_mode" +#define XML_CONFIG_SETTING_PID "play_id" +#define XML_CONFIG_SETTING_SAMPLELIST "sample_list" +#define XML_CONFIG_SETTING_FILEASSAMPLE "file_as_sample" +#define XML_CONFIG_SETTING_EDITLIST "edit_list" +#define XML_CONFIG_BACKFX "backfx" +#define XML_CONFIG_COMPOSITEMODE "composite_mode" +#define XML_CONFIG_SCALERFLAGS "scaler_flags" +#define XML_CONFIG_SETTING_OSD "use_osd" + +#define __xml_cint( buf, var , node, name )\ +{\ +veejay_msg(0,"Try i '%s', '%s'",name,buf);\ +sprintf(buf,"%d", var);\ +xmlNewChild(node, NULL, (const xmlChar*) name, (const xmlChar*) buf );\ +} + +#define __xml_cfloat( buf, var , node, name )\ +{\ +veejay_msg(0,"Try f '%s', '%s'",name,buf);\ +sprintf(buf,"%f", var);\ +xmlNewChild(node, NULL, (const xmlChar*) name, (const xmlChar*) buf );\ +} + +#define __xml_cstr( buf, var , node, name )\ +{\ +if(var != NULL){\ +veejay_msg(0,"Try s '%s', '%s'",name,buf);\ +veejay_strncpy(buf,var,strlen(var));\ +xmlNewChild(node, NULL, (const xmlChar*) name, (const xmlChar*) buf );}\ +} + + +void vj_event_format_xml_settings( veejay_t *v, xmlNodePtr node ) +{ + char *buf = (char*) vj_calloc(sizeof(char) * 4000 ); + int c = veejay_is_colored(); + + __xml_cint( buf, v->video_out,node, XML_CONFIG_SETTING_PRIOUTPUT ); + __xml_cint( buf, v->bes_width,node, XML_CONFIG_SETTING_SDLSIZEX ); + __xml_cint( buf, v->bes_height,node, XML_CONFIG_SETTING_SDLSIZEY ); + __xml_cint( buf, v->uc->geox,node, XML_CONFIG_SETTING_GEOX ); + __xml_cint( buf, v->uc->geoy,node, XML_CONFIG_SETTING_GEOY ); + __xml_cint( buf, v->video_output_width,node, XML_CONFIG_SETTING_WIDTH ); + __xml_cint( buf, v->video_output_height,node, XML_CONFIG_SETTING_HEIGHT ); + + __xml_cint( buf, v->audio,node, XML_CONFIG_SETTING_AUDIO ); + __xml_cint( buf, v->sync_correction,node, XML_CONFIG_SETTING_SYNC ); + + __xml_cint( buf, v->uc->use_timer,node, XML_CONFIG_SETTING_TIMER ); + __xml_cint( buf, v->no_bezerk,node, XML_CONFIG_SETTING_BEZERK ); + __xml_cint( buf, c,node, XML_CONFIG_SETTING_COLOR ); + __xml_cint( buf, v->pixel_format,node, XML_CONFIG_SETTING_YCBCR ); + __xml_cfloat( buf,v->dummy->fps,node, XML_CONFIG_SETTING_DFPS ); + __xml_cint( buf, v->dummy->norm,node, XML_CONFIG_SETTING_NORM ); + __xml_cint( buf, v->dummy->active,node, XML_CONFIG_SETTING_DUMMY ); + __xml_cint( buf, v->settings->use_mcast,node, XML_CONFIG_SETTING_MCASTOSC ); + __xml_cint( buf, v->settings->use_vims_mcast,node, XML_CONFIG_SETTING_MCASTVIMS ); + __xml_cint( buf, v->settings->zoom ,node, XML_CONFIG_SETTING_SCALE ); + __xml_cfloat( buf, v->settings->output_fps, node, XML_CONFIG_SETTING_FPS ); + __xml_cint( buf, v->uc->playback_mode, node, XML_CONFIG_SETTING_PMODE ); + __xml_cint( buf, v->uc->sample_id, node, XML_CONFIG_SETTING_PID ); + __xml_cint( buf, v->settings->fxdepth, node, XML_CONFIG_BACKFX); + __xml_cint( buf, v->settings->composite, node, XML_CONFIG_COMPOSITEMODE ); + __xml_cint( buf, v->settings->sws_templ.flags ,node, XML_CONFIG_SCALERFLAGS ); + __xml_cint( buf, v->uc->file_as_sample, node, XML_CONFIG_SETTING_FILEASSAMPLE ); + __xml_cint( buf, v->use_osd, node, XML_CONFIG_SETTING_OSD ); + + free(buf); +} + +void vj_event_xml_parse_config( veejay_t *v, xmlDocPtr doc, xmlNodePtr cur ) +{ + if( veejay_get_state(v) != LAVPLAY_STATE_STOP) + return; + + int c = 0; + char sample_list[1024]; + veejay_memset(sample_list,0,1024); + // todo: editlist loading ; veejay restart + + while( cur != NULL ) + { + get_cstr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_SAMPLELIST, sample_list ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_PORTNUM, &(v->uc->port) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_PRIOUTPUT, &(v->video_out) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_SDLSIZEX, &(v->bes_width) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_SDLSIZEY, &(v->bes_height) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_AUDIO, &(v->audio) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_SYNC, &(v->sync_correction) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_TIMER, &(v->uc->use_timer) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_GEOX, &(v->uc->geox) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_GEOY, &(v->uc->geoy) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_BEZERK, &(v->no_bezerk) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_COLOR, &c ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_YCBCR, &(v->pixel_format) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_WIDTH, &(v->video_output_width) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_HEIGHT,&(v->video_output_height) ); + get_fstr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_DFPS, &(v->dummy->fps ) ); + get_cstr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_NORM, &(v->dummy->norm) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_DUMMY, &(v->dummy->active) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_MCASTOSC, &(v->settings->use_mcast) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_MCASTVIMS, &(v->settings->use_vims_mcast) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_SCALE, &(v->settings->zoom) ); + get_fstr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_FPS, &(v->settings->output_fps ) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_PMODE, &(v->uc->playback_mode) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_PID, &(v->uc->sample_id ) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_BACKFX, &(v->settings->fxdepth) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_COMPOSITEMODE, &(v->settings->composite) ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SCALERFLAGS, &(v->settings->sws_templ.flags)); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_FILEASSAMPLE, &(v->uc->file_as_sample)); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_SETTING_OSD, &(v->use_osd)); + + cur = cur->next; + } + + veejay_set_colors( c ); + if(sample_list) + { + v->settings->action_scheduler.sl = strdup( sample_list ); + veejay_msg(VEEJAY_MSG_DEBUG, "Scheduled '%s' for restart", sample_list ); + + v->settings->action_scheduler.state = 1; + } +} + +void vj_event_xml_new_keyb_event( void *ptr, xmlDocPtr doc, xmlNodePtr cur ) +{ + int key = 0; + int key_mod = 0; + int event_id = 0; + + char msg[4096]; + veejay_memset(msg,0,4096); + + while( cur != NULL ) + { + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_KEY_VIMS, &event_id ); + get_cstr( doc, cur, (const xmlChar*) XML_CONFIG_KEY_EXTRA, msg ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_KEY_SYM, &key ); + get_istr( doc, cur, (const xmlChar*) XML_CONFIG_KEY_MOD, &key_mod ); + cur = cur->next; + } + + if( event_id <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid key '%s' in configuration file", XML_CONFIG_KEY_VIMS); + return; + } + + if( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END ) + { + int b_key = 0, b_mod = 0; + if( vj_event_bundle_exists(event_id)) + { + vj_msg_bundle *mm = vj_event_bundle_get( event_id ); + if( mm ) + { + b_key = mm->accelerator; + b_mod = mm->modifier; + } + if(!override_keyboard) + { + veejay_msg(VEEJAY_MSG_WARNING, + "Bundle %d already exists in VIMS system! (Bundle in configfile was ignored)",event_id); + return; + } + else + { + if(vj_event_bundle_del(event_id) != 0) + { + veejay_msg(0, "Unable to delete bundle %d", event_id); + return; + } + } + } + + vj_msg_bundle *m = vj_event_bundle_new( msg, event_id); + if(!msg) + { + veejay_msg(VEEJAY_MSG_ERROR, "Failed to create new Bundle %d - [%s]", event_id, msg ); + return; + } + + m->accelerator = b_key; + m->modifier = b_mod; + + + if(vj_event_bundle_store(m)) + veejay_msg(VEEJAY_MSG_DEBUG, "Added bundle %d , trigger with key %d (mod %d)", event_id, b_key, b_mod); + } + +#ifdef HAVE_SDL + if( key > 0 && key_mod >= 0) + { + if( override_keyboard ) + vj_event_unregister_keyb_event( key, key_mod ); + if( !vj_event_register_keyb_event( event_id, key, key_mod, NULL )) + veejay_msg(VEEJAY_MSG_ERROR, "Attaching key %d + %d to Bundle %d ", key,key_mod,event_id); + } +#endif +} + +int veejay_load_action_file( void *ptr, char *file_name ) +{ + xmlDocPtr doc; + xmlNodePtr cur; + + veejay_t *v = (veejay_t*) ptr; + if(!file_name) + return 0; + + doc = xmlParseFile( file_name ); + + if(doc==NULL) { + veejay_msg(0, "Cannot read file '%s'",file_name); + return 0; + } + + cur = xmlDocGetRootElement( doc ); + if( cur == NULL) + { + veejay_msg(0, "Cannot get document root from '%s'",file_name); + xmlFreeDoc(doc); + return 0; + } + + if( xmlStrcmp( cur->name, (const xmlChar *) XML_CONFIG_FILE)) + { + veejay_msg(0, "This is not a veejay configuration file."); + xmlFreeDoc(doc); + return 0; + } + + cur = cur->xmlChildrenNode; + override_keyboard = 1; + while( cur != NULL ) + { + if( !xmlStrcmp( cur->name, (const xmlChar*) XML_CONFIG_SETTINGS ) ) + { + vj_event_xml_parse_config( v, doc, cur->xmlChildrenNode ); + } + if( !xmlStrcmp( cur->name, (const xmlChar *) XML_CONFIG_EVENT )) + { + vj_event_xml_new_keyb_event( (void*)v, doc, cur->xmlChildrenNode ); + } + cur = cur->next; + } + override_keyboard = 0; + xmlFreeDoc(doc); + return 1; +} + +void vj_event_format_xml_event( xmlNodePtr node, int event_id ) +{ + char buffer[4096]; + int key_id=0; + int key_mod=-1; + + veejay_memset( buffer,0, 4096 ); + + if( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END) + { /* its a Bundle !*/ + vj_msg_bundle *m = vj_event_bundle_get( event_id ); + if(!m) + { + veejay_msg(VEEJAY_MSG_ERROR, "bundle %d does not exist", event_id); + return; + } + veejay_strncpy(buffer, m->bundle, strlen(m->bundle) ); + xmlNewChild(node, NULL, (const xmlChar*) XML_CONFIG_KEY_EXTRA , + (const xmlChar*) buffer); + // m->event_id and event_id should be equal + } + /* Put all known VIMS so we can detect differences in runtime + some Events will not exist if SDL, Jack, DV, Video4Linux would be missing */ + + sprintf(buffer, "%d", event_id); + xmlNewChild(node, NULL, (const xmlChar*) XML_CONFIG_KEY_VIMS , + (const xmlChar*) buffer); +#ifdef HAVE_SDL + if(key_id > 0 && key_mod >= 0 ) + { + sprintf(buffer, "%d", key_id ); + xmlNewChild(node, NULL, (const xmlChar*) XML_CONFIG_KEY_SYM , + (const xmlChar*) buffer); + sprintf(buffer, "%d", key_mod ); + xmlNewChild(node, NULL, (const xmlChar*) XML_CONFIG_KEY_MOD , + (const xmlChar*) buffer); + } +#endif +} + +static void vj_event_send_new_id(veejay_t * v, int new_id) +{ + char s_print_buf[16]; + if( vj_server_client_promoted( v->vjs[0], v->uc->current_link )) + { + char result[6]; + sprintf( result, "%05d",new_id ); + sprintf(s_print_buf, "%03d%s",5, result); + SEND_MSG( v,s_print_buf); + } +} + +void vj_event_write_actionfile(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + char file_name[512]; + char live_set[512]; + int args[2] = {0,0}; + int i; + //veejay_t *v = (veejay_t*) ptr; + xmlDocPtr doc; + xmlNodePtr rootnode,childnode; + P_A(args,file_name,format,ap); + doc = xmlNewDoc( "1.0" ); + rootnode = xmlNewDocNode( doc, NULL, (const xmlChar*) XML_CONFIG_FILE,NULL); + xmlDocSetRootElement( doc, rootnode ); + + childnode = xmlNewChild( rootnode, NULL, (const xmlChar*) XML_CONFIG_SETTINGS, NULL ); + vj_event_format_xml_settings( v, childnode ); + + for( i = 0; i < VIMS_MAX; i ++ ) + { + if( net_list[i].list_id > 0 ) + { + childnode = xmlNewChild( rootnode,NULL,(const xmlChar*) XML_CONFIG_EVENT ,NULL); + vj_event_format_xml_event( childnode, i ); + } + } + xmlSaveFormatFile( file_name, doc, 1); + + veejay_msg(VEEJAY_MSG_INFO, "Saved Action file as '%s'" , file_name ); + xmlFreeDoc(doc); +} +#endif // XML2 +void vj_event_read_file( void *ptr, const char format[], va_list ap ) +{ + char file_name[512]; + int args[1]; + + P_A(args,file_name,format,ap); + +#ifdef HAVE_XML2 + if(veejay_load_action_file( ptr, file_name )) + veejay_msg(VEEJAY_MSG_INFO, "Loaded Action file '%s'", file_name ); + else + veejay_msg(VEEJAY_MSG_ERROR,"Unable to load Action file '%s'", file_name ); +#endif +} + +#ifdef HAVE_SDL +vims_key_list *vj_event_get_keys( int event_id ) +{ + vims_key_list *list = vj_calloc( sizeof(vims_key_list)); + vims_key_list *tree = list; + vims_key_list *next = NULL; + if ( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END ) + { + if( vj_event_bundle_exists( event_id )) + { + vj_msg_bundle *bun = vj_event_bundle_get( event_id ); + if( bun ) + { + list->key_symbol = bun->accelerator; + list->key_mod = bun->modifier; + } + } + return list; + } + + if(!hash_isempty( keyboard_events )) + { + hscan_t scan; + hash_scan_begin( &scan, keyboard_events ); + hnode_t *node; + while( ( node = hash_scan_next(&scan)) != NULL ) + { + vj_keyboard_event *ev = NULL; + ev = hnode_get( node ); + if(ev && ev->event_id == event_id) + { + next = vj_calloc( sizeof(vims_key_list)); + + tree->key_symbol = ev->key_symbol; + tree->key_mod = ev->key_mod; + tree->args = ev->arguments; + tree->arg_len = ev->arg_len; + tree->next = next; + + tree = next; + } + } + } + return list; +} + +void vj_event_unregister_keyb_event( int sdl_key, int modifier ) +{ + int index = (modifier * SDLK_LAST) + sdl_key; + vj_keyboard_event *ev = get_keyboard_event( index ); + if(ev) + { + vj_msg_bundle *m = vj_event_bundle_get( ev->event_id ); + if(m) + { + m->accelerator = 0; + m->modifier = 0; + + vj_event_bundle_update( m, ev->event_id ); + veejay_msg(VEEJAY_MSG_DEBUG, "Bundle %d dropped key binding", + ev->event_id); + } + if( ev->vims ) + free(ev->vims); + if( ev->arguments) + free(ev->arguments ); + veejay_memset(ev, 0, sizeof( vj_keyboard_event )); + + del_keyboard_event( index ); + } + else + { + veejay_msg(0,"No event was attached to key %d : %d", modifier, sdl_key); + } +} + +int vj_event_register_keyb_event(int event_id, int symbol, int modifier, const char *value) +{ + int offset = SDLK_LAST * modifier; + int index = offset + symbol; + if( keyboard_event_exists( index )) + { + veejay_msg(VEEJAY_MSG_DEBUG, + "Keboard binding %d + %d already exists", modifier, symbol); + vj_keyboard_event *ff = get_keyboard_event(index); + if(ff && value) + { + if(ff->arguments) free(ff->arguments); + ff->arguments = strdup(value); + ff->arg_len = strlen(value); + veejay_msg( VEEJAY_MSG_DEBUG, + "Updated arguments of keybinding %d+%d, (VIMS %03d:%s;) ",modifier,symbol, ff->event_id, + value); + return 1; + } + return 0; + } + + if( vj_event_bundle_exists(event_id)) + { + vj_keyboard_event *ev = get_keyboard_event( index ); + if( ev ) + { + ev->key_symbol = symbol; + ev->key_mod = modifier; + veejay_msg(VEEJAY_MSG_INFO, + "Updated Bundle ID %d with keybinding %d+%d", + ev->event_id, modifier, symbol ); + return 1; + } + } + + vj_keyboard_event *ev = NULL; + + if( event_id >= VIMS_BUNDLE_START && event_id < VIMS_BUNDLE_END ) + { + char val[10]; + vj_msg_bundle *m = vj_event_bundle_get( event_id ); + sprintf(val, "%d", event_id ); + if( m ) + { + m->accelerator = symbol; + m->modifier = modifier; + + vj_event_bundle_update( m, event_id ); + + ev = new_keyboard_event( symbol, modifier, val, event_id ); + veejay_msg(VEEJAY_MSG_DEBUG, "Bundle %d triggered by key %d (mod %d)", event_id,symbol, modifier); + } + } + else + { + ev = new_keyboard_event( symbol, modifier, value, event_id ); + } + + + if(!ev) + return 0; + + hnode_t *node = hnode_create( ev ); + if(!node) + { + return 0; + } + + hash_insert( keyboard_events, node, (void*) index ); + + return 1; +} +#endif +void vj_event_init_network_events() +{ + int i; + int net_id = 0; + for( i = 0; i <= 600; i ++ ) + { + net_list[ net_id ].act = + (vj_event) vj_event_vevo_get_event_function( i ); + + if( net_list[ net_id ].act ) + { + net_list[net_id].list_id = i; + net_id ++; + } + } + veejay_msg(VEEJAY_MSG_DEBUG, "Registered %d VIMS events", net_id ); +} +#ifdef HAVE_SDL +char *find_keyboard_default(int id) +{ + char *result = NULL; + int i; + for( i = 1; vj_event_default_sdl_keys[i].event_id != 0; i ++ ) + { + if( vj_event_default_sdl_keys[i].event_id == id ) + { + if( vj_event_default_sdl_keys[i].value != NULL ) + result = strdup( vj_event_default_sdl_keys[i].value ); + break; + } + } + return result; +} + +void vj_event_init_keyboard_defaults() +{ + int i; + int keyb_events = 0; + for( i = 1; vj_event_default_sdl_keys[i].event_id != 0; i ++ ) + { + if( vj_event_register_keyb_event( + vj_event_default_sdl_keys[i].event_id, + vj_event_default_sdl_keys[i].key_sym, + vj_event_default_sdl_keys[i].key_mod, + vj_event_default_sdl_keys[i].value )) + { + keyb_events++; + } + else + { + + veejay_msg(VEEJAY_MSG_ERROR, + "VIMS event %03d does not exist ", vj_event_default_sdl_keys[i].event_id ); + } + } +} +#endif + +void vj_event_init() +{ + int i; + + veejay_memset( keyboard_event_map_, 0, sizeof(keyboard_event_map_)); + + vj_init_vevo_events(); +#ifdef HAVE_SDL + if( !(keyboard_events = hash_create( HASHCOUNT_T_MAX, int_bundle_compare, int_bundle_hash))) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot initialize hash for keyboard events"); + return; + } +#endif + for(i=0; i < VIMS_MAX; i++) + { + net_list[i].act = vj_event_none; + net_list[i].list_id = 0; + } + + if( !(BundleHash = hash_create(HASHCOUNT_T_MAX, int_bundle_compare, int_bundle_hash))) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot initialize hashtable for message bundles"); + return; + } + + vj_event_init_network_events(); +#ifdef HAVE_SDL + vj_event_init_keyboard_defaults(); +#endif + init_vims_for_macro(); + +} + +void vj_event_linkclose(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + veejay_msg(VEEJAY_MSG_INFO, "Remote requested session-end, quitting Client"); + int i = v->uc->current_link; + _vj_server_del_client( v->vjs[0], i ); + _vj_server_del_client( v->vjs[1], i ); + _vj_server_del_client( v->vjs[3], i ); +} + +void vj_event_quit(void *ptr, const char format[], va_list ap) +{ + int i; + veejay_t *v = (veejay_t*)ptr; + veejay_msg(VEEJAY_MSG_INFO, "Remote requested session-end, quitting Veejay"); +//@ hang up clients + for( i = 0; i < VJ_MAX_CONNECTIONS; i ++ ) + { + if( vj_server_link_used( v->vjs[VEEJAY_PORT_CMD], i ) ) + { + _vj_server_del_client(v->vjs[VEEJAY_PORT_CMD],i); + _vj_server_del_client(v->vjs[VEEJAY_PORT_STA],i); + _vj_server_del_client(v->vjs[VEEJAY_PORT_DAT],i); + } + } + + + veejay_change_state(v, LAVPLAY_STATE_STOP); +} + +void vj_event_sample_mode(void *ptr, const char format[], va_list ap) +{ +} + +void vj_event_set_framerate( void *ptr, const char format[] , va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *s = NULL; + + P_A(args,s,format,ap); + + float new_fps = (float) args[0] * 0.01; + + if(new_fps == 0.0 ) + new_fps = v->current_edit_list->video_fps; + else if (new_fps <= 0.25 ) { + new_fps = 0.25f; + veejay_msg(VEEJAY_MSG_WARNING, "Limited new framerate to %2.2f ", new_fps ); + } + + veejay_set_framerate( v, new_fps ); + + veejay_msg(VEEJAY_MSG_INFO, "Playback engine is now playing at %2.2f FPS", new_fps ); +} + +void vj_event_sync_correction( void *ptr,const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *s = NULL; + + P_A(args,s,format,ap); + + if(args[0] == 0 ) + { + v->sync_correction = 0; + veejay_msg(VEEJAY_MSG_INFO, "Sync correction disabled"); + } + else if( args[0] == 1 ) + { + v->sync_correction = 1; + veejay_msg(VEEJAY_MSG_INFO, "Sync correction enabled"); + } + +} + +void vj_event_bezerk(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(v->no_bezerk) v->no_bezerk = 0; else v->no_bezerk = 1; + if(v->no_bezerk==1) + veejay_msg(VEEJAY_MSG_INFO,"Bezerk On :No sample-restart when changing input channels"); + else + veejay_msg(VEEJAY_MSG_INFO,"Bezerk Off :Sample-restart when changing input channels"); +} +void vj_event_no_caching(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(v->no_caching) + v->no_caching = 0; + else + v->no_caching = 1; + + if(v->no_caching==1) + { + int i = 0; + int k = 0; + vj_el_break_cache( v->edit_list ); + for( i = 1; i < sample_size() - 1; i ++ ) { + editlist *e = sample_get_editlist(i); + if(e) { + vj_el_break_cache(e); k++; + } + } + veejay_msg(VEEJAY_MSG_INFO,"Cleared %d samples from cache.", k ); + } + else + { + vj_el_setup_cache( v->current_edit_list ); + veejay_msg(VEEJAY_MSG_INFO,"Sample FX Cache enabled : Recycling identicial samples in FX chain (default)"); + } + + vj_el_set_caching(v->no_caching); +} + +void vj_event_debug_level(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(v->verbose) v->verbose = 0; else v->verbose = 1; + veejay_set_debug_level( v->verbose ); + if(v->verbose) + veejay_msg(VEEJAY_MSG_INFO, "Displaying debug information" ); + else + veejay_msg(VEEJAY_MSG_INFO, "Not displaying debug information"); +} + +void vj_event_suspend(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + veejay_change_state(v, LAVPLAY_STATE_PAUSED); + veejay_msg(VEEJAY_MSG_WARNING, "Suspending veejay"); +} + +void vj_event_play_norestart( void *ptr, const char format[], va_list ap ) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + P_A(args,s,format,ap); + + //@ change mode so veejay does not restart samples at all + + if( args[0] == 0 ) { + //@ off + v->settings->sample_restart = 0; + } else if ( args[0] == 1 ) { + //@ on + v->settings->sample_restart = 1; + } + +} + +void vj_event_set_play_mode_go(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + + P_A(args,s,format,ap); + if(vj_event_valid_mode(args[0])) + { + if(args[0] == VJ_PLAYBACK_MODE_PLAIN) + { + if( vj_has_video(v,v->edit_list) ) + veejay_change_playback_mode(v, args[0], 0); + else + veejay_msg(VEEJAY_MSG_ERROR, + "There are no video files in the editlist"); + return; + } + + if(args[0] == VJ_PLAYBACK_MODE_SAMPLE) + { + if(args[1]==0) args[1] = v->uc->sample_id; + if(args[1]==-1) args[1] = sample_size()-1; + if(sample_exists(args[1])) + { + veejay_change_playback_mode(v,args[0] ,args[1]); + } + else + { + p_no_sample(args[1]); + } + return; + } + if(args[0] == VJ_PLAYBACK_MODE_TAG) + { + if(args[1]==0) args[1] = v->uc->sample_id; + if(args[1]==-1) args[1] = vj_tag_size()-1; + if(vj_tag_exists(args[1])) + { + veejay_change_playback_mode(v,args[0],args[1]); + } + else + { + p_no_tag(args[1]); + } + return; + } + } + else + { + p_invalid_mode(); + } +} + + + +void vj_event_set_rgb_parameter_type(void *ptr, const char format[], va_list ap) +{ + + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + if(args[0] >= 0 && args[0] <= 3 ) + { + rgb_parameter_conversion_type_ = args[0]; + if(args[0] == 0) + veejay_msg(VEEJAY_MSG_INFO,"GIMP's RGB -> YUV"); + if(args[1] == 1) + veejay_msg(VEEJAY_MSG_INFO,"CCIR601 RGB -> YUV"); + if(args[2] == 2) + veejay_msg(VEEJAY_MSG_INFO,"Broken RGB -> YUV"); + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Use: 0=GIMP , 1=CCIR601, 2=Broken"); + } +} + +void vj_event_effect_set_bg(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + v->uc->take_bg = 1; + veejay_msg(VEEJAY_MSG_INFO, "Next frame will be taken for static background\n"); +} + +void vj_event_send_keylist( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + unsigned int i,len=0; + char message[256]; + char *blob = vj_calloc( 1024 * 32 ); + char line[512]; + char header[7]; + int skip = 0; + if(!hash_isempty( keyboard_events )) + { + hscan_t scan; + hash_scan_begin( &scan, keyboard_events ); + hnode_t *node; + while( ( node = hash_scan_next(&scan)) != NULL ) + { + vj_keyboard_event *ev = NULL; + ev = hnode_get( node ); + if(ev) + { + if( ev->event_id >= VIMS_BUNDLE_START && ev->event_id < VIMS_BUNDLE_END ) + { + skip = 1; + if( vj_event_bundle_exists(ev->event_id)) + { + vj_msg_bundle *mm = vj_event_bundle_get( ev->event_id); + if( mm->bundle ) { skip = 0; snprintf(message, 256, "%s", mm->bundle ); } + } + } + else + { + if(ev->arguments) + snprintf(message,256, "%03d:%s;", ev->event_id,ev->arguments); + else + snprintf(message,256, "%03d:;", ev->event_id ); + } + + if(!skip) + { + snprintf( line, 512, "%04d%03d%03d%03d%s", + ev->event_id, ev->key_mod, ev->key_symbol, strlen(message), message ); + int line_len = strlen(line); + len += line_len; + veejay_strncat( blob, line, line_len); + } + skip = 0; + } + } + } + + sprintf( header, "%06d", len ); + + SEND_MSG( v, header ); + SEND_MSG( v, blob ); + + free( blob ); + +} + +static int min_bundles_len(veejay_t *v ) +{ + vj_msg_bundle *m; + int i; + int len = 0; + const int token_len = 20; + char tmp[1024]; + char *buf = NULL; + + for( i = 0; i <= 600 ; i ++ ) + { + if( i >= VIMS_BUNDLE_START && i < VIMS_BUNDLE_END ) + { + if(!vj_event_bundle_exists(i)) + continue; + + len += token_len; + m = vj_event_bundle_get(i); + len += strlen( m->bundle ); + + } + else + { + if( !vj_event_exists(i) || (i >= 400 && i < VIMS_BUNDLE_START)) + continue; + + char *name = vj_event_vevo_get_event_name(i); + char *form = vj_event_vevo_get_event_format(i); + + len += token_len; + len += strlen(name); + + int form_len = (form ? strlen( form ): 0); + int name_len = (name ? strlen(name) : 0); +#ifdef HAVE_SDL + vims_key_list *tree = vj_event_get_keys( i ); + while( tree != NULL ) + { + vims_key_list *this = tree; + len += tree->arg_len; + len += form_len; + len += token_len; + len += name_len; + tree = tree->next; + free(this); + } + +#endif + free(name); + if(form) free(form); + } + } + return len; +} + +void vj_event_send_bundles(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + vj_msg_bundle *m; + int i; + const int token_len = 20; + char tmp[1024]; + + int len = min_bundles_len(v); +#ifdef STRICT_CHECKING + int consumed_len = len; +#endif + + if( len <= 0 ) + { + SEND_MSG(v, "000000"); + return; + } + + char *buf = vj_calloc( len+6+64 ); + + int rc = 0; + + for( i = 0; i <= 600 ; i ++ ) + { + if( i >= VIMS_BUNDLE_START && i < VIMS_BUNDLE_END ) + { + if(!vj_event_bundle_exists(i)) + continue; + + m = vj_event_bundle_get(i); +#ifdef STRICT_CHECKING + assert( m!= NULL); +#endif + int bun_len = strlen(m->bundle); + + sprintf(tmp, "%04d%03d%03d%04d%s%03d%03d", + i, m->accelerator, m->modifier, bun_len, m->bundle, 0,0 ); + + veejay_strncat( buf, tmp, strlen(tmp) ); +#ifdef STRICT_CHECKING + consumed_len -= strlen(tmp); + assert( consumed_len > 0 ); +#endif + } + else + { + if( !vj_event_exists(i) || (i >= 400 && i < VIMS_BUNDLE_START) ) + continue; + + char *name = vj_event_vevo_get_event_name(i); + char *form = vj_event_vevo_get_event_format(i); +#ifdef STRICT_CHECKING + assert( name != NULL ); +#endif + int name_len = strlen(name); + int form_len = (form ? strlen(form) : 0); +#ifdef HAVE_SDL + vims_key_list *tree = vj_event_get_keys( i ); + while( tree != NULL ) + { + vims_key_list *this = tree; + sprintf(tmp, "%04d%03d%03d%04d%s%03d%03d", + i, tree->key_symbol, tree->key_mod, name_len, name, form_len, tree->arg_len ); + veejay_strncat( buf,tmp,strlen(tmp)); +#ifdef STRICT_CHECKING + if( tree->arg_len ) + assert( tree->args != NULL ); +#endif + if(form) + veejay_strncat( buf, form, form_len); + if(tree->arg_len) + veejay_strncat( buf, tree->args, tree->arg_len ); +#ifdef STRICT_CHECKING + consumed_len -= strlen(tmp); + consumed_len -= form_len; + consumed_len -= tree->arg_len; + assert( consumed_len > 0 ); +#endif + tree = tree->next; + free(this); + } + +#endif + free(name); + if(form) + free(form); + + } + } + +#ifdef STRICT_CHECKING + assert( consumed_len >= 0 ); +#endif + int pack_len = strlen( buf ); + char header[7]; + sprintf(header, "%06d", pack_len ); + SEND_MSG(v, header); + SEND_MSG(v,buf); + + if(buf) free(buf); + +} + +void vj_event_send_vimslist(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + char *buf = vj_event_vevo_list_serialize(); + SEND_MSG(v,buf); + if(buf) free(buf); +} + +void vj_event_send_devicelist( void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + + char *buf = vj_tag_scan_devices(); + SEND_MSG( v, buf ); + free(buf); +} + + +void vj_event_sample_select(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + P_A( args, s , format, ap); + + if(args[0] == 0 ) + { + args[0] = v->uc->sample_id; + } + if(args[0] == -1) + { + args[0] = sample_size()-1; + } + if(sample_exists(args[0])) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_SAMPLE,args[0] ); + } + else + { + p_no_sample(args[0]); + } +} + +void vj_event_tag_select(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + P_A( args, s , format, ap); + + if(args[0] == 0 ) + { + args[0] = v->uc->sample_id; + } + if(args[0]==-1) + { + args[0] = vj_tag_size()-1; + } + + if(vj_tag_exists(args[0])) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_TAG,args[0]); + } + else + { + p_no_tag(args[0]); + } +} + + +void vj_event_switch_sample_tag(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + + int last_tag = vj_tag_size()-1; + int last_sample=sample_size()-1; + + if(last_tag < 1 ) + last_tag = 1; + if(last_sample < 1 ) + last_sample = 1; + + if(!STREAM_PLAYING(v) && !SAMPLE_PLAYING(v)) + { + if(sample_exists(v->last_sample_id)) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_SAMPLE, v->last_sample_id); + return; + } + if(vj_tag_exists(v->last_tag_id)) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_TAG, v->last_tag_id); + return; + } + if(sample_size()-1 <= 0) + { + if(vj_tag_exists( last_tag )) + { + veejay_change_playback_mode( v, VJ_PLAYBACK_MODE_TAG, last_tag); + return; + } + } + } + + if(SAMPLE_PLAYING(v)) + { + if(vj_tag_exists(v->last_tag_id)) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_TAG, v->last_tag_id); + } + else if ( vj_tag_exists(last_tag)) + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_TAG, last_tag); + } + else if(STREAM_PLAYING(v)) + { + if(sample_exists(v->last_sample_id) ) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_SAMPLE, v->last_sample_id); + } + else if( sample_exists( last_sample )) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_SAMPLE,last_sample); + } + } +} + +void vj_event_set_volume(void *ptr, const char format[], va_list ap) +{ + int args[1]; + char *s = NULL; + P_A(args,s,format,ap) + if(args[0] >= 0 && args[0] <= 100) + { +#ifdef HAVE_JACK + if(vj_jack_set_volume(args[0])) + { + veejay_msg(VEEJAY_MSG_INFO, "Volume set to %d", args[0]); + } +#else + veejay_msg(VEEJAY_MSG_ERROR, "Audio support not compiled in"); +#endif + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Use a value between 0-100 for audio volume"); + } +} +void vj_event_set_play_mode(void *ptr, const char format[], va_list ap) +{ + int args[1]; + char *s = NULL; + veejay_t *v = (veejay_t*) ptr; + P_A(args,s,format,ap); + + if(vj_event_valid_mode(args[0])) + { + int mode = args[0]; + /* check if current playing ID is valid for this mode */ + if(mode == VJ_PLAYBACK_MODE_SAMPLE) + { + int last_id = sample_size()-1; + if(last_id == 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "There are no samples. Cannot switch to sample mode"); + return; + } + if(!sample_exists(v->last_sample_id)) + { + v->uc->sample_id = last_id; + } + if(sample_exists(v->uc->sample_id)) + { + veejay_change_playback_mode( v, VJ_PLAYBACK_MODE_SAMPLE, v->uc->sample_id ); + } + } + if(mode == VJ_PLAYBACK_MODE_TAG) + { + int last_id = vj_tag_size()-1; + if(last_id == 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "There are no streams. Cannot switch to stream mode"); + return; + } + + if(!vj_tag_exists(v->last_tag_id)) /* jump to last used Tag if ok */ + { + v->uc->sample_id = last_id; + } + if(vj_tag_exists(v->uc->sample_id)) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_TAG, v->uc->sample_id); + } + } + if(mode == VJ_PLAYBACK_MODE_PLAIN) + { + if(vj_has_video(v,v->edit_list) ) + veejay_change_playback_mode( v, VJ_PLAYBACK_MODE_PLAIN, 0); + else + veejay_msg(VEEJAY_MSG_ERROR, + "There are no video files in the editlist"); + } + } + else + { + p_invalid_mode(); + } + +} + +void vj_event_sample_new(void *ptr, const char format[], va_list ap) +{ + int new_id = 0; + veejay_t *v = (veejay_t*) ptr; + if(PLAIN_PLAYING(v) || SAMPLE_PLAYING(v)) + { + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + editlist *E = v->edit_list; + if( SAMPLE_PLAYING(v)) + E = v->current_edit_list; + + if(args[0] < 0) + { + args[0] = v->uc->sample_start; + } + if(args[1] == 0) + { + args[1] = E->total_frames; + } + + int num_frames = E->total_frames; + + + if(args[0] >= 0 && args[1] > 0 && args[0] <= args[1] && args[0] <= num_frames && + args[1] <= num_frames ) + { + editlist *el = veejay_edit_copy_to_new( v, E, args[0],args[1] ); + if(!el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cant copy EDL"); + return; + } + int start = 0; + int end = el->total_frames; + + sample_info *skel = sample_skeleton_new(start, end ); + if(skel) + { + skel->edit_list = el; + if(!skel->edit_list) + veejay_msg(VEEJAY_MSG_ERROR, "Failed to copy EDL !!"); + } + + if(sample_store(skel)==0) + { + veejay_msg(VEEJAY_MSG_INFO, "Created new sample [%d] with EDL", skel->sample_id); + new_id = skel->sample_id; + } + + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid frame range given : %d - %d , range is %d - %d", + args[0],args[1], 1,num_frames); + } + } + else + { + p_invalid_mode(); + } + + vj_event_send_new_id( v, new_id); + +} + +void vj_event_fullscreen(void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + // parsed display num!! -> index of SDL array + + //int id = args[0]; + int id = 0; + int status = args[0]; + + switch(v->video_out) + { + /* + case 4: +#ifdef HAVE_GL + { + int go_fs = x_display_get_fs( v->gl ) == 1 ? 0:1; + x_display_set_fullscreen( v->gl, go_fs ); + v->settings->full_screen = go_fs; + } +#endif + break; + */ + case 0: + case 2: +#ifdef HAVE_SDL + { + int go_fs = v->sdl[id]->fs == 1 ? 0:1 ; + char *caption = veejay_title(v); + + vj_sdl *tmpsdl = vj_sdl_allocate( v->video_output_width,v->video_output_height,v->pixel_format); + + if(vj_sdl_init( + v->settings->ncpu, + tmpsdl, + v->bes_width, + v->bes_height, + caption, + 1, + go_fs + ) ) { + if( v->sdl[id] ) { + vj_sdl_free(v->sdl[id]); + } + v->sdl[id] = tmpsdl; + if( go_fs) + vj_sdl_grab( v->sdl[id], 0 ); + v->settings->full_screen = go_fs; + } + else { + vj_sdl_free(tmpsdl); + } + free(caption); + } +#endif + break; + default: + break; + } + veejay_msg(VEEJAY_MSG_INFO,"Video screen is %s", + (v->settings->full_screen ? "full screen" : "windowed")); + +} + + +void vj_event_set_screen_size(void *ptr, const char format[], va_list ap) +{ + int args[5]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + + P_A(args,s,format,ap); + + int id = 0; + int w = args[0]; + int h = args[1]; + int x = args[2]; + int y = args[3]; + + if( w < 0 || w > 4096 || h < 0 || h > 4096 || x < 0 || y < 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid arguments '%d %d %d %d'", w,h,x,y ); + return; + } + + if( w == 0 && h == 0 ) + { + switch( v->video_out ) + { + case 0: + case 2: +#ifdef HAVE_SDL + if( v->sdl[id] ) + { + vj_sdl_free( v->sdl[id] ); + free(v->sdl[id]); + v->sdl[id] = NULL; + v->video_out = 5; + vj_sdl_quit(); + veejay_msg(VEEJAY_MSG_INFO, "Closed SDL window"); + return; + } +#endif + break; + default: + break; + } + } + else + { + char *title = veejay_title(v); + + switch( v->video_out ) + { + case 5: +#ifdef HAVE_SDL + if(!v->sdl[id] ) + { + v->sdl[id] = vj_sdl_allocate( + v->video_output_width, + v->video_output_height, + v->pixel_format ); + veejay_msg(VEEJAY_MSG_INFO, "Allocated SDL window"); + + if(vj_sdl_init( v->settings->ncpu, + v->sdl[id], + v->bes_width, + v->bes_height, + title, + 1, + v->settings->full_screen ) + ) { + veejay_msg(VEEJAY_MSG_INFO, "Opened SDL Video Window of size %d x %d", w, h ); + v->video_out = 0; + } + } +#endif + case 0: +#ifdef HAVE_SDL + if( x > 0 && y > 0 ) + vj_sdl_set_geometry(v->sdl[id],x,y); + + if( w > 0 && h > 0 ) + vj_sdl_resize( v->sdl[id], w, h, v->settings->full_screen ); +#endif + break; + /* + case 4: +#ifdef HAVE_GL + if( w > 0 && h > 0 ) + x_display_resize(w,h,w,h); +#endif + break; + */ + default: + break; + } + free(title); + } +} + +void vj_event_play_stop(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(!STREAM_PLAYING(v)) + { + int speed = v->settings->current_playback_speed; + veejay_set_speed(v, (speed == 0 ? 1 : 0 )); + veejay_msg(VEEJAY_MSG_INFO,"Video is %s", (speed==0 ? "paused" : "playing")); + } + else + { + p_invalid_mode(); + } +} + +void vj_event_render_depth( void *ptr, const char format[] , va_list ap ) +{ + int args[1]; + veejay_t *v = (veejay_t*)ptr; + char *s = NULL; + P_A(args,s,format,ap); + int status = 0; + int toggle = 0; + if( args[0] == 2 ) + toggle = 1; + + if( args[0] ) { + status = 1; + } + + if( toggle ) { + if( v->settings->fxdepth == 1 ) + v->settings->fxdepth = 0; + else + v->settings->fxdepth = 1; + } else { + v->settings->fxdepth = status; + } + if( v->settings->fxdepth == 1 ) { + veejay_msg(VEEJAY_MSG_INFO, "Rendering chain entries 1 - 3 of all underlying samples and streams."); + } else { + veejay_msg(VEEJAY_MSG_INFO, "Skipping all FX on all underlying samples and streams."); + } +} + +void vj_event_viewport_composition( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + if(v->composite) { + if(STREAM_PLAYING(v)) + { + if( vj_tag_get_composite_view(v->uc->sample_id) == NULL ) { + veejay_msg(VEEJAY_MSG_WARNING, "No perspective transform setup for Stream %d, play it and press CTRL-s", + v->uc->sample_id ); + return; + } + + int status = vj_tag_get_composite( v->uc->sample_id ); + if( status == 1 || status == 2 ) { + status = 0; + } else { + status = 2; + } + vj_tag_set_composite( v->composite, v->uc->sample_id, status ); + + veejay_msg(VEEJAY_MSG_INFO, "Stream #%d will %s be transformed when used as secundary input", + v->uc->sample_id, (status==2? "now" : "not")); + veejay_msg(VEEJAY_MSG_INFO, "Press CTRL+i again to toggle."); + + } else if (SAMPLE_PLAYING(v)) { + if( sample_get_composite_view(v->uc->sample_id ) == NULL ) { + veejay_msg(VEEJAY_MSG_WARNING, "No perspective transform setup for Sample %d, play it and press CTRL-s", + v->uc->sample_id ); + return; + } + int status = sample_get_composite( v->uc->sample_id ); + if( status == 1 || status == 2 ) + status = 0; + else + status = 2; + + sample_set_composite( v->composite, v->uc->sample_id, status ); + veejay_msg(VEEJAY_MSG_INFO, "Sample #%d will %s be transformed when used as secundary input", + v->uc->sample_id, (status==2? "now" : "not")); + veejay_msg(VEEJAY_MSG_INFO, "Press CTRL+i again to toggle."); + + } + } +} + +void vj_event_play_reverse(void *ptr,const char format[],va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + if(!STREAM_PLAYING(v)) + { + int speed = v->settings->current_playback_speed; + if( speed == 0 ) speed = -1; + else + if(speed > 0) speed = -(speed); + veejay_set_speed(v, + speed ); + + veejay_msg(VEEJAY_MSG_INFO, "Video is playing in reverse at speed %d.", speed); + } + else + { + p_invalid_mode(); + } +} + +void vj_event_play_forward(void *ptr, const char format[],va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + if(!STREAM_PLAYING(v)) + { + int speed = v->settings->current_playback_speed; + if(speed == 0) speed = 1; + else if(speed < 0 ) speed = -1 * speed; + + veejay_set_speed(v, + speed ); + + veejay_msg(VEEJAY_MSG_INFO, "Video is playing forward at speed %d" ,speed); + } + else + { + p_invalid_mode(); + } +} + +void vj_event_play_speed(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + if(!STREAM_PLAYING(v)) + { + char *s = NULL; + int speed = 0; + P_A(args,s,format,ap); + veejay_set_speed(v, args[0] ); + speed = v->settings->current_playback_speed; + veejay_msg(VEEJAY_MSG_INFO, "Video is playing at speed %d now (%s)", + speed, speed == 0 ? "paused" : speed < 0 ? "reverse" : "forward" ); + } + else + { + p_invalid_mode(); + } +} + +void vj_event_play_speed_kb(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + if(!STREAM_PLAYING(v)) + { + char *s = NULL; + P_A(args,s,format,ap); + + int speed = abs(args[0]); + if( v->settings->current_playback_speed < 0 ) + veejay_set_speed( v, -1 * speed ); + else + veejay_set_speed(v, speed ); + speed = v->settings->current_playback_speed; + veejay_msg(VEEJAY_MSG_INFO, "Video is playing at speed %d now (%s)", + speed, speed == 0 ? "paused" : speed < 0 ? "reverse" : "forward" ); + } + else + { + p_invalid_mode(); + } +} + + + +void vj_event_play_slow(void *ptr, const char format[],va_list ap) +{ + int args[1]; + veejay_t *v = (veejay_t*)ptr; + char *s = NULL; + P_A(args,s,format,ap); + + if(PLAIN_PLAYING(v) || SAMPLE_PLAYING(v)) + { + if(args[0] <= 0 ) + args[0] = 1; + + if(veejay_set_framedup(v, args[0])) + { + if( SAMPLE_PLAYING(v)) + sample_reset_loopcount( v->uc->sample_id ); + veejay_msg(VEEJAY_MSG_INFO,"A/V frames will be repeated %d times ",args[0]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to set frame repeat of %d", args[0]); + } + } + else + { + p_invalid_mode(); + } + +} + + +void vj_event_set_frame(void *ptr, const char format[], va_list ap) +{ + int args[1]; + veejay_t *v = (veejay_t*) ptr; + if(!STREAM_PLAYING(v)) + { + video_playback_setup *s = v->settings; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0] == -1 ) + args[0] = v->current_edit_list->total_frames; + veejay_set_frame(v, args[0]); + } + else + { + p_invalid_mode(); + } +} + + +void vj_event_projection_dec( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + float inc_x = (float) args[0]; + float inc_y = (float) args[1]; + + if(!v->composite) + { + veejay_msg(0,"No viewport active"); + return; + } + viewport_finetune_coord( composite_get_vp(v->composite),vj_perform_get_width(v), vj_perform_get_height(v), + inc_x, + inc_y); + +} +void vj_event_projection_inc( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + if(!v->composite) + { + veejay_msg(0,"No viewport active"); + return; + } + viewport_finetune_coord( composite_get_vp(v->composite),vj_perform_get_width(v), vj_perform_get_height(v), + args[0], + args[1]); +} + +void vj_event_inc_frame(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + P_A( args,s,format, ap ); + if(!STREAM_PLAYING(v)) + { + video_playback_setup *s = v->settings; + veejay_set_frame(v, (s->current_frame_num + args[0])); + veejay_msg(VEEJAY_MSG_INFO, "Skip to frame %d", s->current_frame_num); + } + else + { + p_invalid_mode(); + } +} + +void vj_event_dec_frame(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *) ptr; + int args[1]; + char *s = NULL; + P_A( args,s,format, ap ); + if(!STREAM_PLAYING(v)) + { + video_playback_setup *s = v->settings; + veejay_set_frame(v, (s->current_frame_num - args[0])); + veejay_msg(VEEJAY_MSG_INFO, "Skip to frame %d", s->current_frame_num); + } + else + { + p_invalid_mode(); + } +} + +void vj_event_prev_second(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + int args[1]; + char *s = NULL; + P_A( args,s,format, ap ); + if(!STREAM_PLAYING(v)) + { + video_playback_setup *s = v->settings; + veejay_set_frame(v, (s->current_frame_num - (int) + (args[0] * v->current_edit_list->video_fps))); + veejay_msg(VEEJAY_MSG_INFO, "Skip to frame %d", s->current_frame_num ); + } + else + { + p_invalid_mode(); + } +} + +void vj_event_next_second(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + int args[1]; + char *str = NULL; + P_A( args,str,format, ap ); + if(!STREAM_PLAYING(v)) + { + video_playback_setup *s = v->settings; + veejay_set_frame(v, (s->current_frame_num + (int) + ( args[0] * v->current_edit_list->video_fps))); + veejay_msg(VEEJAY_MSG_INFO, "Skip to frame %d", s->current_frame_num ); + } + else + { + p_invalid_mode(); + } +} + + +void vj_event_sample_start(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + video_playback_setup *s = v->settings; + if(SAMPLE_PLAYING(v) || PLAIN_PLAYING(v)) + { + v->uc->sample_start = s->current_frame_num; + veejay_msg(VEEJAY_MSG_INFO, "Change sample starting position to %ld", v->uc->sample_start); + } + else + { + p_invalid_mode(); + } +} + + + +void vj_event_sample_end(void *ptr, const char format[] , va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + video_playback_setup *s = v->settings; + + if(PLAIN_PLAYING(v) || SAMPLE_PLAYING(v)) + { + v->uc->sample_end = s->current_frame_num; + if( v->uc->sample_end > v->uc->sample_start) { + long vstart = v->uc->sample_start; + long vend = v->uc->sample_end; + + if(v->settings->current_playback_speed < 0) { + long tmp = vend; + vend = vstart; + vstart = tmp; + } + + if(vstart < 0 ) { + vstart=0; + } + if(vend > v->current_edit_list->total_frames) { + vend = v->current_edit_list->total_frames; + } + + editlist *E = v->edit_list; + if( SAMPLE_PLAYING(v)) + E = v->current_edit_list; + editlist *el = veejay_edit_copy_to_new( v, E, vstart, vend ); + if(!el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to clone current editlist!"); + return; + } + + long start = 0; + long end = el->total_frames; + + sample_info *skel = sample_skeleton_new(start,end); + if(!skel) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create new sample!"); + return; + } + + v->uc->sample_start = v->uc->sample_end; // set new starting position (repeat ']') + + skel->edit_list = el; + + if(sample_store(skel)==0) { + veejay_msg(VEEJAY_MSG_INFO,"Created new Sample %d\t [%ld] | %ld-%ld | [%ld]", + skel->sample_id, + 0, + start, + end, + el->total_frames); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR,"Unable to create new sample"); + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample ending position before starting position. Cannot create new sample"); + } + } + else + { + p_invalid_mode(); + } + +} + +void vj_event_goto_end(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + if(SAMPLE_PLAYING(v)) + { + veejay_set_frame(v, sample_get_endFrame(v->uc->sample_id)); + veejay_msg(VEEJAY_MSG_INFO, "Goto sample's endings position"); + } + if(PLAIN_PLAYING(v)) + { + veejay_set_frame(v,v->current_edit_list->total_frames); + veejay_msg(VEEJAY_MSG_INFO, "Goto frame %ld of edit decision list", + v->edit_list->total_frames); + } +} + +void vj_event_goto_start(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + if( SAMPLE_PLAYING(v)) + { + veejay_set_frame(v, sample_get_startFrame(v->uc->sample_id)); + veejay_msg(VEEJAY_MSG_INFO, "Goto sample's starting position"); + } + if ( PLAIN_PLAYING(v)) + { + veejay_set_frame(v,0); + veejay_msg(VEEJAY_MSG_INFO, "Goto first frame of edit decision list"); + } +} + +void vj_event_sample_rand_start( void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + video_playback_setup *settings = v->settings; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + if(args[0] == RANDTIMER_FRAME) + settings->randplayer.timer = RANDTIMER_FRAME; + else + settings->randplayer.timer = RANDTIMER_LENGTH; + + + settings->randplayer.mode = RANDMODE_SAMPLE; + + vj_perform_randomize(v); + veejay_msg(VEEJAY_MSG_INFO, "Started sample randomizer, %s", + (settings->randplayer.timer == RANDTIMER_FRAME ? "freestyling" : "playing full length of gambled samples")); +} + +void vj_event_sample_rand_stop( void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + video_playback_setup *settings = v->settings; + + if(settings->randplayer.mode != RANDMODE_INACTIVE) + veejay_msg(VEEJAY_MSG_INFO, "Stopped sample randomizer"); + else + veejay_msg(VEEJAY_MSG_ERROR, "Sample randomizer not started"); + settings->randplayer.mode = RANDMODE_INACTIVE; +} + +void vj_event_sample_set_loop_type(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + P_A(args,s,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0) + { + args[0] = v->uc->sample_id; + } + if(args[0] == -1) args[0] = sample_size()-1; + + if(args[1] == -1) + { + if(sample_exists(args[0])) + { + if(sample_get_looptype(args[0])==2) + { + int lp; + sample_set_looptype(args[0],1); + lp = sample_get_looptype(args[0]); + veejay_msg(VEEJAY_MSG_INFO, "Sample %d loop type is now %s",args[0], + ( lp==1 ? "Normal Looping" : (lp==2 ? "Pingpong Looping" : "No Looping" ) ) ); + return; + } + else + { + int lp; + sample_set_looptype(args[0],2); + lp = sample_get_looptype(args[0]); + veejay_msg(VEEJAY_MSG_INFO, "Sample %d loop type is now %s",args[0], + ( lp==1 ? "Normal Looping" : lp==2 ? "Pingpong Looping" : "No Looping" ) ); + return; + } + } + else + { + p_no_sample(args[0]); + return; + } + } + + if(args[1] >= 0 && args[1] <= 3) + { + if(sample_exists(args[0])) + { + int lp; + sample_set_looptype( args[0] , args[1]); + lp = sample_get_looptype(args[0]); + switch(lp) + { + case 0: veejay_msg(VEEJAY_MSG_INFO, "Play once");break; + case 1: veejay_msg(VEEJAY_MSG_INFO, "Normal looping");break; + case 2: veejay_msg(VEEJAY_MSG_INFO, "Pingpong looping");break; + case 3: veejay_msg(VEEJAY_MSG_INFO, "Random frame");break; + } + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample %d does not exist or invalid looptype %d",args[1],args[0]); + } +} + +void vj_event_sample_set_speed(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + P_A(args, s, format, ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == -1) + args[0] = sample_size() - 1; + + if( args[0] == 0) + args[0] = v->uc->sample_id; + + if( sample_set_speed(args[0], args[1]) != -1) + { + veejay_msg(VEEJAY_MSG_INFO, "Changed speed of sample %d to %d",args[0],args[1]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Speed %d it too high to set on sample %d !", + args[1],args[0]); + } + } + else + { + p_invalid_mode(); + } +} + +void vj_event_sample_set_marker_start(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*)ptr; + + char *str = NULL; + P_A(args,str,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0) + { + args[0] = v->uc->sample_id; + } + + if(args[0] == -1) args[0] = sample_size()-1; + + if( sample_exists(args[0]) ) + { + int start = 0; int end = 0; + if ( sample_get_el_position( args[0], &start, &end ) ) + { + if( sample_set_marker_start( args[0], args[1] ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Sample %d marker starting position set at %d", args[0],args[1]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot set marker position %d for sample %d (limits are %d - %d)",args[1],args[0],start,end); + } + } + } + else + { + p_no_sample( args[0] ); + } +} + + +void vj_event_sample_set_marker_end(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + + char *str = NULL; + P_A(args,str,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0 ) + args[0] = v->uc->sample_id; + + if(args[0] == -1) + args[0] = sample_size()-1; + + if( sample_exists(args[0]) ) + { + int start = 0; int end = 0; + if ( sample_get_el_position( args[0], &start, &end ) ) + { + args[1] = end - args[1]; // add sample's ending position + if( sample_set_marker_end( args[0], args[1] ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Sample %d marker ending position set at position %d", args[0],args[1]); + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Marker position out side of sample boundaries"); + } + } + } + else + { + p_no_sample(args[0]); + } +} + + +void vj_event_sample_set_marker(void *ptr, const char format[], va_list ap) +{ + int args[3]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + P_A(args,s,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0) + { + args[0] = v->uc->sample_id; + } + if(args[0] == -1) args[0] = sample_size()-1; + + if( sample_exists(args[0]) ) + { + int start = 0; + int end = 0; + if( sample_get_el_position( args[0], &start, &end ) ) + { + if( sample_set_marker( args[0], args[1],args[2] ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Sample %d marker starting position at %d, ending position at %d", args[0],args[1],args[2]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot set marker %d-%d for sample %d",args[1],args[2],args[0]); + } + } + } + else + { + p_no_sample( args[0] ); + } +} + + +void vj_event_sample_set_marker_clear(void *ptr, const char format[],va_list ap) +{ + int args[1]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + P_A(args,s,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0) + args[0] = v->uc->sample_id; + + if(args[0] == -1) args[0] = sample_size()-1; + + if( sample_exists(args[0]) ) + { + if( sample_marker_clear( args[0] ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Sample %d marker cleared", args[0]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot set marker %d-%d for sample %d",args[1],args[2],args[0]); + } + } + else + { + p_no_sample(args[0]); + } +} + +void vj_event_sample_set_dup(void *ptr, const char format[], va_list ap) +{ + int args[2]; + veejay_t *v = (veejay_t*) ptr; + char *s = NULL; + P_A(args,s,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0) + args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = sample_size()-1; + + if( sample_exists(args[0])) + { + if( args[1] <= 0 ) + args[1] = 1; + if( sample_set_framedup( args[0], args[1] ) != -1) + { + veejay_msg(VEEJAY_MSG_INFO, "Sample %d frame repeat set to %d", args[0],args[1]); + if( args[0] == v->uc->sample_id) + { + if(veejay_set_framedup(v, args[1])) + { + veejay_msg(VEEJAY_MSG_INFO, + "Video frame will be duplicated %d to output",args[1]); + } + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR,"Cannot set frame repeat to %d for sample %d",args[0],args[1]); + } + sample_reset_loopcount( args[0] ); + } + else + { + p_no_sample(args[0]); + } +} + +void vj_event_tag_set_descr( void *ptr, const char format[], va_list ap) +{ + char str[TAG_MAX_DESCR_LEN]; + int args[2]; + veejay_t *v = (veejay_t*) ptr; + P_A(args,str,format,ap); + + if(!STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0 ) + args[0] = v->uc->sample_id; + + if(args[0] == -1) + args[0] = vj_tag_size()-1; + + if( vj_tag_set_description(args[0],str) == 1) + veejay_msg(VEEJAY_MSG_INFO, "Changed stream title to '%s'", str ); + else + veejay_msg(VEEJAY_MSG_ERROR, "Cannot change title of stream %d to '%s'", args[0], str ); +} + +void vj_event_sample_set_descr(void *ptr, const char format[], va_list ap) +{ + char str[SAMPLE_MAX_DESCR_LEN]; + int args[5]; + veejay_t *v = (veejay_t*) ptr; + P_A(args,str,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0 ) + args[0] = v->uc->sample_id; + + if(args[0] == -1) args[0] = sample_size()-1; + + if(sample_set_description(args[0],str) == 0) + veejay_msg(VEEJAY_MSG_INFO, "Changed sample title to %s",str); + else + veejay_msg(VEEJAY_MSG_ERROR, "Cannot change title of sample %d to '%s'", args[0],str ); +} + +#ifdef HAVE_XML2 +void vj_event_sample_save_list(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + char str[1024]; + int *args = NULL; + P_A(args,str,format,ap); + if(sample_writeToFile( str, v->composite,v->seq,v->font, v->uc->sample_id, v->uc->playback_mode) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Saved %d samples to file '%s'", sample_size()-1, str); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Error saving samples to file %s", str); + } +} + +void vj_event_sample_load_list(void *ptr, const char format[], va_list ap) +{ + char str[1024]; + int *args = NULL; + veejay_t *v = (veejay_t*) ptr; + P_A( args, str, format, ap); + + int id = 0; + int mode = 0; + + if( sample_readFromFile( str, v->composite,v->seq, v->font, v->edit_list, &id, &mode ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Loaded sample list from file '%s'", str); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to load samples from file '%s", str); + } +} +#endif + +void vj_event_sample_rec_start( void *ptr, const char format[], va_list ap) +{ + char tmp[255]; + veejay_t *v = (veejay_t *)ptr; + int args[2]; + int result = 0; + char *str = NULL; + char prefix[150]; + P_A(args,str,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + veejay_memset(tmp,0,255); + veejay_memset(prefix,0,150); + + if( !v->seq->active ) + { + sample_get_description(v->uc->sample_id, prefix ); + } + else + { + if( v->seq->rec_id ) + { + veejay_msg(0, "Already recording the sequence!"); + return; + } + else + { + v->seq->rec_id = v->uc->sample_id; + sprintf( prefix, "sequence_"); + } + } + + if(!veejay_create_temp_file(prefix, tmp)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create temporary file, Record aborted." ); + if(v->seq->rec_id && v->seq->active) + v->seq->rec_id = 0; + return; + } + + if( args[0] == 0 ) + { + if(!v->seq->active ) + { + args[0] = sample_get_longest(v->uc->sample_id); + } + else + { + int i; + for( i = 0; i < MAX_SEQUENCES; i ++ ) + { + args[0] += sample_get_longest( v->seq->samples[i] ); + } + } + veejay_msg(VEEJAY_MSG_DEBUG, "\tRecording %d frames", args[0]); + } + + int format_ = _recorder_format; + if(format_==-1) + { + veejay_msg(VEEJAY_MSG_ERROR,"Select a video codec first"); + if(v->seq->active && v->seq->rec_id ) + v->seq->rec_id = 0; + return; + } + + if(args[0] <= 1 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cowardly refusing to record less then 2 frames"); + if(v->seq->active && v->seq->rec_id ) + v->seq->rec_id = 0; + + return; + } + + if( sample_init_encoder( v->uc->sample_id, tmp, format_, v->current_edit_list, args[0]) == 1) + { + video_playback_setup *s = v->settings; + s->sample_record_id = v->uc->sample_id; + s->sample_record_switch = args[1]; + result = 1; + if(v->use_osd) + { + veejay_msg(VEEJAY_MSG_INFO,"Turned off OSD, recording now"); + v->use_osd = 0; + } + veejay_msg(VEEJAY_MSG_INFO, "Sample recording started , record %d frames from sample %d and %s", + args[0],s->sample_record_id, (args[1] == 1 ? "play new sample" : "dont play new sample" )); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR,"Unable to start sample recorder"); + sample_stop_encoder( v->uc->sample_id ); + result = 0; + v->settings->sample_record = 0; + return; + } + + if(result == 1) + { + v->settings->sample_record = 1; + v->settings->sample_record_switch = args[1]; + } + + if( v->seq->active ) + { + int i; + int start_at = 0; + for( i = 0; i < MAX_SEQUENCES; i ++ ) + { + if ( sample_exists( v->seq->samples[i] )) + { + start_at = v->seq->samples[i]; + break; + } + } + if( start_at == v->uc->sample_id ) + veejay_set_frame(v,sample_get_startFrame(v->uc->sample_id)); + else + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_SAMPLE, start_at ); + } + else + { + veejay_set_frame(v, sample_get_startFrame(v->uc->sample_id)); + } +} + +void vj_event_sample_rec_stop(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + + if( SAMPLE_PLAYING(v)) + { + video_playback_setup *s = v->settings; + int stop_sample = v->uc->sample_id; + + if(v->seq->active && v->seq->rec_id ) + stop_sample = v->seq->rec_id; + + if( sample_stop_encoder( stop_sample ) == 1 ) + { + char avi_file[255]; + v->settings->sample_record = 0; + if( sample_get_encoded_file( stop_sample, avi_file) <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to append file '%s' to sample %d", avi_file, stop_sample); + } + else + { + // add to new sample + int ns = veejay_edit_addmovie_sample(v,avi_file,0 ); + if(ns > 0) + veejay_msg(VEEJAY_MSG_INFO, "Loaded file '%s' to new sample %d",avi_file, ns); + if(ns <= 0 ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to append file %s to EditList!",avi_file); + + + sample_reset_encoder( stop_sample ); + s->sample_record = 0; + s->sample_record_id = 0; + if(v->seq->active && v->seq->rec_id ) + v->seq->rec_id = 0; + if(s->sample_record_switch) + { + s->sample_record_switch = 0; + if( ns > 0 ) + veejay_change_playback_mode( v,VJ_PLAYBACK_MODE_SAMPLE, ns ); + } + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample recorder was never started for sample %d",stop_sample); + } + } + else + { + p_invalid_mode(); + } +} + + +void vj_event_sample_set_num_loops(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = sample_size()-1; + + if(sample_exists(args[0])) + { + + if( sample_set_loops(v->uc->sample_id, args[1])) + { veejay_msg(VEEJAY_MSG_INFO, "Setted %d no. of loops for sample %d", + sample_get_loops(v->uc->sample_id),args[0]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR,"Cannot set %d loops for sample %d",args[1],args[0]); + } + + } + else + { + p_no_sample(args[0]); + } +} + + +void vj_event_sample_rel_start(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + int args[4]; + //video_playback_setup *s = v->settings; + char *str = NULL; + int s_start; + int s_end; + + P_A(args,str,format,ap); + if(SAMPLE_PLAYING(v)) + { + + if(args[0] == 0) + args[0] = v->uc->sample_id; + + if(args[0] == -1) args[0] = sample_size()-1; + + if(!sample_exists(args[0])) + { + p_no_sample(args[0]); + return; + } + + s_start = sample_get_startFrame(args[0]) + args[1]; + s_end = sample_get_endFrame(args[0]) + args[2]; + + if (sample_set_startframe(args[0],s_start) && + sample_set_endframe(args[0],s_end)) + { + constrain_sample( v, args[0] ); + veejay_msg(VEEJAY_MSG_INFO, "Sample update start %d end %d", + s_start,s_end); + } + } + else + { + p_invalid_mode(); + } + +} + +void vj_event_sample_set_start(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + int args[2]; + int mf; + video_playback_setup *s = v->settings; + char *str = NULL; + P_A(args,str,format,ap); + + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if(args[0] == 0) + args[0] = v->uc->sample_id; + if(args[0] == -1) + args[0] = sample_size()-1; + + if( args[0] <= 0 ) + return; + + if( args[1] < sample_get_endFrame(args[0])) { + if( sample_set_startframe(args[0],args[1] ) ) { + veejay_msg(VEEJAY_MSG_INFO, "Sample starting frame updated to frame %d", + sample_get_startFrame(args[0])); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to update sample %d 's starting position to %d",args[0],args[1]); + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample %d 's starting position %d must be greater than ending position %d.", + args[0],args[1], sample_get_endFrame(args[0])); + } +} + +void vj_event_sample_set_end(void *ptr, const char format[] , va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + int args[2]; + int mf; + video_playback_setup *s = v->settings; + char *str = NULL; + P_A(args,str,format,ap); + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if(args[0] == 0) + args[0] = v->uc->sample_id; + if(args[1] == -1) + args[1] = sample_video_length( args[0] ); + if(args[1] <= 0 ) + { + veejay_msg(0, "Impossible to set ending position %d for sample %d", args[1],args[0] ); + return; + } + if( args[1] >= sample_get_startFrame(v->uc->sample_id)) + { + if(sample_set_endframe(args[0],args[1])) + { + constrain_sample( v, args[0] ); + veejay_msg(VEEJAY_MSG_INFO,"Sample ending frame updated to frame %d", + sample_get_endFrame(args[0])); + } + else + { + veejay_msg(0, "Impossible to set ending position %d for sample %d", args[1],args[0] ); + } + } + else + { + veejay_msg(0, "Ending position must be greater then start position"); + } +} + +void vj_event_sample_del(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + P_A(args,s,format,ap); + int deleted_sample = 0; + + if(SAMPLE_PLAYING(v) && v->uc->sample_id == args[0]) + { + veejay_msg(VEEJAY_MSG_INFO,"Cannot delete sample while playing"); + return; + } + + if(sample_del(args[0])) + { + veejay_msg(VEEJAY_MSG_INFO, "Deleted sample %d", args[0]); + deleted_sample = args[0]; + int i; + for( i = 0; i < MAX_SEQUENCES ; i ++ ) + if( v->seq->samples[i] == deleted_sample ) + v->seq->samples[i] = 0; + + sample_verify_delete( args[0] , 0 ); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to delete sample %d",args[0]); + } + vj_event_send_new_id( v, deleted_sample ); +} + +void vj_event_sample_copy(void *ptr, const char format[] , va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + int new_sample =0; + P_A(args,s,format,ap); + + if( sample_exists(args[0] )) + { + new_sample = sample_copy(args[0]); + if(!new_sample) + veejay_msg(VEEJAY_MSG_ERROR, "Failed to copy sample %d.",args[0]); + } + vj_event_send_new_id( v, new_sample ); +} + +void vj_event_sample_clear_all(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if( !SAMPLE_PLAYING(v)) + { + sample_del_all(); + veejay_msg(VEEJAY_MSG_INFO,"Deleted all samples"); + } + else + { + p_invalid_mode(); + } +} + + + +void vj_event_chain_enable(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + if(SAMPLE_PLAYING(v)) + { + sample_set_effect_status(v->uc->sample_id, 1); + } + else + { + if(STREAM_PLAYING(v)) + { + vj_tag_set_effect_status(v->uc->sample_id, 1); + } + else + p_invalid_mode(); + } + veejay_msg(VEEJAY_MSG_INFO, "Enabled effect chain"); + +} + +void vj_event_stream_set_length( void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + if(STREAM_PLAYING(v)) + { + if(args[0] > 0 && args[0] < 999999 ) + { + vj_tag_set_n_frames(v->uc->sample_id, args[0]); + v->settings->max_frame_num = args[0]; + constrain_stream( v, v->uc->sample_id, (long) args[0]); + } + else + veejay_msg(VEEJAY_MSG_ERROR, "Ficticious length must be 0 - 999999"); + } + else + p_invalid_mode(); +} + +void vj_event_chain_disable(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + if(SAMPLE_PLAYING(v) ) + { + sample_set_effect_status(v->uc->sample_id, 0); + veejay_msg(VEEJAY_MSG_INFO, "Effect chain on Sample %d is disabled",v->uc->sample_id); + } + else + { + if(STREAM_PLAYING(v) ) + { + vj_tag_set_effect_status(v->uc->sample_id, 0); + veejay_msg(VEEJAY_MSG_INFO, "Effect chain on Stream %d is enabled",v->uc->sample_id); + } + else + p_invalid_mode(); + } +} + +void vj_event_sample_chain_enable(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[4]; + char *s = NULL; + P_A(args,s,format,ap); + if(!SAMPLE_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if(args[0] == 0) + { + args[0] = v->uc->sample_id; + } + + if(sample_exists(args[0])) + { + sample_set_effect_status(args[0], 1); + veejay_msg(VEEJAY_MSG_INFO, "Effect chain on Sample %d is enabled",args[0]); + } + else + p_no_sample(args[0]); + +} + +void vj_event_all_samples_chain_toggle(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + P_A(args,s,format,ap); + if(SAMPLE_PLAYING(v)) + { + int i; + for(i=0; i < sample_size()-1; i++) + sample_set_effect_status( i, args[0] ); + veejay_msg(VEEJAY_MSG_INFO, "Effect Chain on all samples %s", (args[0]==0 ? "Disabled" : "Enabled")); + } + else + { + if(STREAM_PLAYING(v)) + { + int i; + for(i=0; i < vj_tag_size()-1; i++) + vj_tag_set_effect_status(i,args[0]); + veejay_msg(VEEJAY_MSG_INFO, "Effect Chain on all streams %s", (args[0]==0 ? "Disabled" : "Enabled")); + } + else + p_invalid_mode(); + } +} + + +void vj_event_tag_chain_enable(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[4]; + char *s = NULL; + P_A(args,s,format,ap); + + if(!STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0 ) + args[0] = v->uc->sample_id; + + if(vj_tag_exists(args[0])) + { + vj_tag_set_effect_status(args[0], 1); + veejay_msg(VEEJAY_MSG_INFO, "Effect chain on stream %d is enabled",args[0]); + } + else + p_no_tag(args[0]); + +} +void vj_event_tag_chain_disable(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + if(!STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + if( args[0] == 0 ) + args[0] = v->uc->sample_id; + if(vj_tag_exists(args[0])) + { + vj_tag_set_effect_status(args[0], 0); + veejay_msg(VEEJAY_MSG_INFO, "Effect chain on stream %d is disabled",args[0]); + } + else + { + p_no_tag(args[0]); + } + +} + +void vj_event_sample_chain_disable(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + if(args[0] == 0) + { + args[0] = v->uc->sample_id; + } + + if(SAMPLE_PLAYING(v) && sample_exists(args[0])) + { + sample_set_effect_status(args[0], 0); + veejay_msg(VEEJAY_MSG_INFO, "Effect chain on stream %d is disabled",args[0]); + } + if(STREAM_PLAYING(v) && vj_tag_exists(args[0])) + { + vj_tag_set_effect_status(args[0], 0); + veejay_msg(VEEJAY_MSG_INFO, "Effect chain on stream %d is disabled",args[0]); + } + +} + + +void vj_event_chain_toggle(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + if(SAMPLE_PLAYING(v)) + { + int flag = sample_get_effect_status(v->uc->sample_id); + if(flag == 0) + { + sample_set_effect_status(v->uc->sample_id,1); + } + else + { + sample_set_effect_status(v->uc->sample_id,0); + } + veejay_msg(VEEJAY_MSG_INFO, "Effect chain is %s.", (sample_get_effect_status(v->uc->sample_id) ? "enabled" : "disabled")); + } + if(STREAM_PLAYING(v)) + { + int flag = vj_tag_get_effect_status(v->uc->sample_id); + if(flag == 0) + { + vj_tag_set_effect_status(v->uc->sample_id,1); + } + else + { + vj_tag_set_effect_status(v->uc->sample_id,0); + } + veejay_msg(VEEJAY_MSG_INFO, "Effect chain is %s.", (vj_tag_get_effect_status(v->uc->sample_id) ? "enabled" : "disabled")); + } +} + +void vj_event_chain_entry_video_toggle(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + if(SAMPLE_PLAYING(v)) + { + int c = sample_get_selected_entry(v->uc->sample_id); + int flag = sample_get_chain_status(v->uc->sample_id,c); + if(flag == 0) + { + sample_set_chain_status(v->uc->sample_id, c,1); + } + else + { + sample_set_chain_status(v->uc->sample_id, c,0); + } + veejay_msg(VEEJAY_MSG_INFO, "Video on chain entry %d is %s", c, + (flag==0 ? "Disabled" : "Enabled")); + } + if(STREAM_PLAYING(v)) + { + int c = vj_tag_get_selected_entry(v->uc->sample_id); + int flag = vj_tag_get_chain_status( v->uc->sample_id,c); + if(flag == 0) + { + vj_tag_set_chain_status(v->uc->sample_id, c,1); + } + else + { + vj_tag_set_chain_status(v->uc->sample_id, c,0); + } + veejay_msg(VEEJAY_MSG_INFO, "Video on chain entry %d is %s", c, + (flag==0 ? "Disabled" : "Enabled")); + + } +} + +void vj_event_chain_entry_enable_video(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *s = NULL; + P_A(args,s,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + if(sample_exists(args[0])) + { + if(sample_set_chain_status(args[0],args[1],1) != -1) + { + veejay_msg(VEEJAY_MSG_INFO, "Sample %d: Video on chain entry %d is %s",args[0],args[1], + ( sample_get_chain_status(args[0],args[1]) == 1 ? "Enabled" : "Disabled")); + } + } + else + p_no_sample(args[0]); + } + if(STREAM_PLAYING(v)) + { + if(args[0] == 0)args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + if(vj_tag_exists(args[0])) + { + if(vj_tag_set_chain_status(args[0],args[1],1)!=-1) + { + veejay_msg(VEEJAY_MSG_INFO, "Stream %d: Video on chain entry %d is %s",args[0],args[1], + vj_tag_get_chain_status(args[0],args[1]) == 1 ? "Enabled" : "Disabled" ); + } + } + else + p_no_tag(args[0]); + } +} +void vj_event_chain_entry_disable_video(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + if(sample_set_chain_status(args[0],args[1],0)!=-1) + { + veejay_msg(VEEJAY_MSG_INFO, "Sample %d: Video on chain entry %d is %s",args[0],args[1], + ( sample_get_chain_status(args[0],args[1])==1 ? "Enabled" : "Disabled")); + } + } + else + p_no_sample(args[0]); + } + if(STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(args[0])) + { + if(vj_tag_set_chain_status(args[0],args[1],0)!=-1) + { + veejay_msg(VEEJAY_MSG_INFO, "Stream %d: Video on chain entry %d is %s",args[0],args[1], + vj_tag_get_chain_status(args[0],args[1]) == 1 ? "Enabled" : "Disabled" ); + } + } + else + p_no_tag(args[0]); + } + +} + +void vj_event_chain_fade_follow(void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + if( args[0] == 0 || args[0] == 1 ) { + vj_perform_follow_fade( args[0] ); + } +} + +void vj_event_manual_chain_fade(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + if(args[0] == 0 && (SAMPLE_PLAYING(v) || STREAM_PLAYING(v)) ) + { + args[0] = v->uc->sample_id; + } + + if( args[1] < 0 || args[1] > 255) + { + veejay_msg(VEEJAY_MSG_ERROR,"Invalid opacity range %d use [0-255] ", args[1]); + return; + } + args[1] = 255 - args[1]; + + if( SAMPLE_PLAYING(v) && sample_exists(args[0])) + { + if( sample_set_manual_fader( args[0], args[1] ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Set chain opacity to %f", + sample_get_fader_val( args[0] )); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Error setting chain opacity of sample %d to %d", args[0],args[1]); + } + } + if (STREAM_PLAYING(v) && vj_tag_exists(args[0])) + { + if( vj_tag_set_manual_fader( args[0], args[1] ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Set chain opacity to %f", + vj_tag_get_fader_val(args[0])); + } + } + +} + +void vj_event_chain_fade_in(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; P_A(args,str,format,ap); + + if(args[0] == 0 && (SAMPLE_PLAYING(v) || STREAM_PLAYING(v)) ) + { + args[0] = v->uc->sample_id; + } + + if( args[1] == 0 ) + args[1] = 1; //@forward + + if( SAMPLE_PLAYING(v) && sample_exists(args[0])) + { + if( sample_set_fader_active( args[0], args[1],-1 ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Chain Fade In from sample to full effect chain in %d frames. Per frame %2.4f", + args[1], sample_get_fader_inc(args[0])); + if(sample_get_effect_status(args[0]==0)) + { + sample_set_effect_status(args[0], -1); + } + } + } + if (STREAM_PLAYING(v) && vj_tag_exists(args[0])) + { + if( vj_tag_set_fader_active( args[0], args[1],-1 ) ) + { + veejay_msg(VEEJAY_MSG_INFO,"Chain Fade In from stream to full effect chain in %d frames. Per frame %2.4f", + args[1], sample_get_fader_inc(args[0])); + if(vj_tag_get_effect_status(args[0]==0)) + { + vj_tag_set_effect_status(args[0],-1); + } + } + } + +} + +void vj_event_chain_fade_out(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; P_A(args,str,format,ap); + + if(args[0] == 0 && (SAMPLE_PLAYING(v) || STREAM_PLAYING(v)) ) + { + args[0] = v->uc->sample_id; + } + + if( args[1] == 0 ) + args[1] = -1; + + if( SAMPLE_PLAYING(v) && sample_exists(args[0])) + { + if( sample_set_fader_active( args[0], args[1],1 ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Chain Fade Out from sample to full effect chain in %d frames. Per frame %2.2f", + args[1], sample_get_fader_inc(args[0])); + } + } + if (STREAM_PLAYING(v) && vj_tag_exists(args[0])) + { + if( vj_tag_set_fader_active( args[0], args[1],1 ) ) + { + veejay_msg(VEEJAY_MSG_INFO,"Chain Fade Out from stream to full effect chain in %d frames. Per frame %2.2f", + args[1], sample_get_fader_inc(args[0])); + } + } +} + + + +void vj_event_chain_clear(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[1]; + char *str = NULL; + P_A(args,str,format,ap); + + if(args[0] == 0 && (SAMPLE_PLAYING(v) || STREAM_PLAYING(v)) ) + { + args[0] = v->uc->sample_id; + } + + if( SAMPLE_PLAYING(v) && sample_exists(args[0])) + { + int i; + for(i=0; i < SAMPLE_MAX_EFFECTS;i++) + { + int effect = sample_get_effect_any(args[0],i); + if(vj_effect_is_valid(effect)) + { + sample_chain_remove(args[0],i); + veejay_msg(VEEJAY_MSG_INFO,"Sample %d: Deleted effect %s from entry %d", + args[0],vj_effect_get_description(effect), i); + } + } + v->uc->chain_changed = 1; + } + if (STREAM_PLAYING(v) && vj_tag_exists(args[0])) + { + int i; + for(i=0; i < SAMPLE_MAX_EFFECTS;i++) + { + int effect = vj_tag_get_effect_any(args[0],i); + if(vj_effect_is_valid(effect)) + { + vj_tag_chain_remove(args[0],i); + veejay_msg(VEEJAY_MSG_INFO,"Stream %d: Deleted effect %s from entry %d", + args[0],vj_effect_get_description(effect), i); + } + } + v->uc->chain_changed = 1; + } + + +} + +void vj_event_chain_entry_del(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + int effect = sample_get_effect_any(args[0],args[1]); + if( vj_effect_is_valid(effect)) + { + sample_chain_remove(args[0],args[1]); + v->uc->chain_changed = 1; + veejay_msg(VEEJAY_MSG_INFO,"Sample %d: Deleted effect %s from entry %d", + args[0],vj_effect_get_description(effect), args[1]); + } + } + } + + if (STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(args[0])) + { + int effect = vj_tag_get_effect_any(args[0],args[1]); + if(vj_effect_is_valid(effect)) + { + vj_tag_chain_remove(args[0],args[1]); + v->uc->chain_changed = 1; + veejay_msg(VEEJAY_MSG_INFO,"Stream %d: Deleted effect %s from entry %d", + args[0],vj_effect_get_description(effect), args[1]); + } + } + } +} + +void vj_event_chain_entry_set_defaults(void *ptr, const char format[], va_list ap) +{ + +} + +void vj_event_chain_entry_set(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[3]; + char *str = NULL; P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = sample_size()-1; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + //int real_id = vj_effect_real_to_sequence(args[2]); + if(sample_chain_add(args[0],args[1],args[2]) != -1) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Sample %d chain entry %d has effect %s", + args[0],args[1],vj_effect_get_description(args[2])); + v->uc->chain_changed = 1; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot set effect %d on sample %d chain %d",args[2],args[0],args[1]); + } + } + } + if( STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = vj_tag_size()-1; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(args[0])) + { + if(vj_tag_set_effect(args[0],args[1], args[2]) != -1) + { + // veejay_msg(VEEJAY_MSG_INFO, "Stream %d chain entry %d has effect %s", + // args[0],args[1],vj_effect_get_description(real_id)); + v->uc->chain_changed = 1; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot set effect %d on stream %d chain %d",args[2],args[0],args[1]); + } + } + } +} + +void vj_event_chain_entry_select(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *str = NULL; P_A(args,str,format,ap); + + if( SAMPLE_PLAYING(v) ) + { + if(args[0] >= 0 && args[0] < SAMPLE_MAX_EFFECTS) + { + if( sample_set_selected_entry( v->uc->sample_id, args[0])) + { + veejay_msg(VEEJAY_MSG_INFO,"Selected entry %d [%s]", + sample_get_selected_entry(v->uc->sample_id), + vj_effect_get_description( + sample_get_effect_any(v->uc->sample_id,sample_get_selected_entry(v->uc->sample_id)))); + } + } + } + if ( STREAM_PLAYING(v)) + { + if(args[0] >= 0 && args[0] < SAMPLE_MAX_EFFECTS) + { + if( vj_tag_set_selected_entry(v->uc->sample_id,args[0])) + { + veejay_msg(VEEJAY_MSG_INFO, "Selected entry %d [%s]", + vj_tag_get_selected_entry(v->uc->sample_id), + vj_effect_get_description( + vj_tag_get_effect_any(v->uc->sample_id,vj_tag_get_selected_entry(v->uc->sample_id)))); + } + } + } +} + +void vj_event_entry_up(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + P_A(args,s,format,ap); + if(SAMPLE_PLAYING(v) || STREAM_PLAYING(v)) + { + int effect_id=-1; + int c=-1; + if(SAMPLE_PLAYING(v)) + { + c = sample_get_selected_entry(v->uc->sample_id) + args[0]; + if(c >= SAMPLE_MAX_EFFECTS) c = 0; + sample_set_selected_entry( v->uc->sample_id, c); + effect_id = sample_get_effect_any(v->uc->sample_id, c ); + } + if(STREAM_PLAYING(v)) + { + c = vj_tag_get_selected_entry(v->uc->sample_id)+args[0]; + if( c>= SAMPLE_MAX_EFFECTS) c = 0; + vj_tag_set_selected_entry(v->uc->sample_id,c); + effect_id = vj_tag_get_effect_any(v->uc->sample_id,c); + } + + veejay_msg(VEEJAY_MSG_INFO, "Entry %d has effect %s", + c, vj_effect_get_description(effect_id)); + + } +} +void vj_event_entry_down(void *ptr, const char format[] ,va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *s = NULL; + P_A(args,s,format,ap); + if(SAMPLE_PLAYING(v) || STREAM_PLAYING(v)) + { + int effect_id=-1; + int c = -1; + + if(SAMPLE_PLAYING(v)) + { + c = sample_get_selected_entry( v->uc->sample_id ) - args[0]; + if(c < 0) c = SAMPLE_MAX_EFFECTS-1; + sample_set_selected_entry( v->uc->sample_id, c); + effect_id = sample_get_effect_any(v->uc->sample_id, c ); + } + if(STREAM_PLAYING(v)) + { + c = vj_tag_get_selected_entry(v->uc->sample_id) - args[0]; + if(c<0) c= SAMPLE_MAX_EFFECTS-1; + vj_tag_set_selected_entry(v->uc->sample_id,c); + effect_id = vj_tag_get_effect_any(v->uc->sample_id,c); + } + veejay_msg(VEEJAY_MSG_INFO , "Entry %d has effect %s", + c, vj_effect_get_description(effect_id)); + } +} + +void vj_event_chain_entry_preset(void *ptr,const char format[], va_list ap) +{ + int args[16]; + veejay_t *v = (veejay_t*)ptr; + veejay_memset(args,0,sizeof(int) * 16); + //P_A16(args,format,ap); + char *str = NULL; + P_A(args,str,format,ap); + if(SAMPLE_PLAYING(v)) + { + int num_p = 0; + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + int real_id = args[2]; + int i; + num_p = vj_effect_get_num_params(real_id); + + if(sample_chain_add( args[0],args[1],args[2])!=-1) + { + int args_offset = 3; + + for(i=0; i < num_p; i++) + { + if(vj_effect_valid_value(real_id,i,args[(i+args_offset)]) ) + { + + if(sample_set_effect_arg(args[0],args[1],i,args[(i+args_offset)] )==-1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error setting argument %d value %d for %s", + i, + args[(i+args_offset)], + vj_effect_get_description(real_id)); + } + } + } + + /* if ( vj_effect_get_extra_frame( real_id )) + { + int source = args[num_p+3]; + int channel_id = args[num_p+4]; + int err = 1; + if( (source != VJ_TAG_TYPE_NONE && vj_tag_exists(channel_id))|| (source == VJ_TAG_TYPE_NONE && sample_exists(channel_id)) ) + { + err = 0; + } + if( err == 0 && sample_set_chain_source( args[0],args[1], source ) && + sample_set_chain_channel( args[0],args[1], channel_id )) + { + veejay_msg(VEEJAY_MSG_INFO, "Updated mixing channel to %s %d", + (source == VJ_TAG_TYPE_NONE ? "sample" : "stream" ), + channel_id); + } + }*/ + } + } + } + if( STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(v->uc->sample_id)) + { + int real_id = args[2]; + int num_p = vj_effect_get_num_params(real_id); + int i; + + if(vj_tag_set_effect(args[0],args[1], args[2]) != -1) + { + for(i=0; i < num_p; i++) + { + if(vj_effect_valid_value(real_id, i, args[i+3]) ) + { + if(vj_tag_set_effect_arg(args[0],args[1],i,args[i+3]) == -1) + { + veejay_msg(VEEJAY_MSG_ERROR, "setting argument %d value %d for %s", + i, + args[i+3], + vj_effect_get_description(real_id)); + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Parameter %d value %d is invalid for effect %d (%d-%d)", + i,args[(i+3)], real_id, + vj_effect_get_min_limit(real_id,i), + vj_effect_get_max_limit(real_id,i)); + } + } + v->uc->chain_changed = 1; + } +/* + if( vj_effect_get_extra_frame(real_id) ) + { + int channel_id = args[num_p + 4]; + int source = args[ num_p + 3]; + int err = 1; + + if( (source != VJ_TAG_TYPE_NONE && vj_tag_exists(channel_id))|| (source == VJ_TAG_TYPE_NONE && sample_exists(channel_id)) ) + { + err = 0; + } + + if( err == 0 && vj_tag_set_chain_source( args[0],args[1], source ) && + vj_tag_set_chain_channel( args[0],args[1], channel_id )) + { + veejay_msg(VEEJAY_MSG_INFO,"Updated mixing channel to %s %d", + (source == VJ_TAG_TYPE_NONE ? "sample" : "stream"), channel_id ); + } + }*/ + } + } + +} + +void vj_event_chain_entry_src_toggle(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + if(SAMPLE_PLAYING(v)) + { + int entry = sample_get_selected_entry(v->uc->sample_id); + int src = sample_get_chain_source(v->uc->sample_id, entry); + int cha = sample_get_chain_channel( v->uc->sample_id, entry ); + if(src == 0 ) // source is sample, toggle to stream + { + if(!vj_tag_exists(cha)) + { + cha =vj_tag_size()-1; + if(cha <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "No streams to mix with"); + return; + } + } + veejay_msg(VEEJAY_MSG_DEBUG, "Switched from source Sample to Stream"); + //src = vj_tag_get_type(cha); + src = 1; + } + else + { + if(!sample_exists(cha)) + { + cha = sample_size()-1; + if(cha<=0) + { + veejay_msg(VEEJAY_MSG_ERROR, "No samples to mix with"); + return; + } + } + veejay_msg(VEEJAY_MSG_DEBUG, "Switched from source Stream to Sample"); + src = 0; + } + sample_set_chain_source( v->uc->sample_id, entry, src ); + sample_set_chain_channel(v->uc->sample_id,entry,cha); + veejay_msg(VEEJAY_MSG_INFO, "Chain entry %d uses %s %d", entry,(src==VJ_TAG_TYPE_NONE ? "Sample":"Stream"), cha); + if(v->no_bezerk) + { + veejay_set_frame(v, sample_get_startFrame(v->uc->sample_id)); + } + + } + + if(STREAM_PLAYING(v)) + { + int entry = vj_tag_get_selected_entry(v->uc->sample_id); + int src = vj_tag_get_chain_source(v->uc->sample_id, entry); + int cha = vj_tag_get_chain_channel( v->uc->sample_id, entry ); + char description[100]; + + if(src == VJ_TAG_TYPE_NONE ) // mix sample, change to stream + { + if(!vj_tag_exists(cha)) + { + cha = vj_tag_size()-1; + if(cha <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "No streams to mix with"); + return; + } + } + src = 1; + } + else + { + if(!sample_exists(cha)) + { + cha = sample_size()-1; + if(cha<=0) + { + veejay_msg(VEEJAY_MSG_ERROR, "No samples to mix with"); + return; + } + } + src = 0; + } + vj_tag_set_chain_source( v->uc->sample_id, entry, src ); + vj_tag_set_chain_channel(v->uc->sample_id,entry,cha); + + vj_tag_get_descriptive(cha, description); + veejay_msg(VEEJAY_MSG_INFO, "Chain entry %d uses %s %d (%s)", entry,( src == 0 ? "Sample" : "Stream" ), cha,description); + } +} + +void vj_event_chain_entry_source(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[3]; + char *str = NULL; + P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + int src = args[2]; + int c = sample_get_chain_channel(args[0],args[1]); + if(src == VJ_TAG_TYPE_NONE) + { + if(!sample_exists(c)) + { + c = sample_size()-1; + if(c<=0) + { + veejay_msg(VEEJAY_MSG_ERROR, "You should create a sample first\n"); + return; + } + } + } + else + { + if(!vj_tag_exists(c) ) + { + c = vj_tag_size() - 1; + if(c<=0) + { + veejay_msg(VEEJAY_MSG_ERROR, "You should create a stream first (there are none)"); + return; + } + src = vj_tag_get_type(c); + } + } + + if(c > 0) + { + sample_set_chain_channel(args[0],args[1], c); + sample_set_chain_source (args[0],args[1],src); + + veejay_msg(VEEJAY_MSG_INFO, "Mixing with source (%s %d)", + src == VJ_TAG_TYPE_NONE ? "sample" : "stream",c); + // if(v->no_bezerk) veejay_set_sample(v, v->uc->sample_id); + if(v->no_bezerk) + { + veejay_set_frame(v, + sample_get_startFrame(v->uc->sample_id)); + } + } + + } + } + if(STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(args[0])) + { + int src = args[2]; + int c = vj_tag_get_chain_channel(args[0],args[1]); + + if(src == VJ_TAG_TYPE_NONE) + { + if(!sample_exists(c)) + { + c = sample_size()-1; + if(c<=0) + { + veejay_msg(VEEJAY_MSG_ERROR, "You should create a sample first\n"); + return; + } + } + } + else + { + if(!vj_tag_exists(c) ) + { + c = vj_tag_size() - 1; + if(c<=0) + { + veejay_msg(VEEJAY_MSG_ERROR, "You should create a stream first (there are none)"); + return; + } + src = vj_tag_get_type(c); + } + } + + if(c > 0) + { + vj_tag_set_chain_channel(args[0],args[1], c); + vj_tag_set_chain_source (args[0],args[1],src); + veejay_msg(VEEJAY_MSG_INFO, "Mixing with source (%s %d)", + src==VJ_TAG_TYPE_NONE ? "sample" : "stream",c); + // if(v->no_bezerk) veejay_set_sample(v, v->uc->sample_id); + + } + } + } +} + +#define clamp_channel( a, b, c ) ( ( a < b ? c : (a >= c ? b : a ))) + +void vj_event_chain_entry_channel_dec(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[1]; + char *str = NULL; P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + int entry = sample_get_selected_entry(v->uc->sample_id); + int cha = sample_get_chain_channel(v->uc->sample_id,entry); + int src = sample_get_chain_source(v->uc->sample_id,entry); + int old = cha; + if(src==VJ_TAG_TYPE_NONE) + { //decrease sample id + cha = cha - args[0]; + if( sample_size()-1 <= 0 ) + { + veejay_msg(0, "No samples to mix with"); + return; + } + clamp_channel( + cha, + 1, + sample_size()-1 ); + + if( !sample_exists( cha ) ) + cha = old; + } + else + { + cha = cha - args[0]; + if( vj_tag_size()-1 <= 0 ) + { + veejay_msg(0, "No streams to mix with"); + return; + } + clamp_channel( + cha, + 1, + vj_tag_size()-1 ); + + if( !vj_tag_exists( cha )) + cha = old; + } + sample_set_chain_channel( v->uc->sample_id, entry, cha ); + veejay_msg(VEEJAY_MSG_INFO, "Chain entry %d uses %s %d",entry, + (src==VJ_TAG_TYPE_NONE ? "Sample" : "Stream"),cha); + + if(v->no_bezerk) + veejay_set_frame(v , sample_get_startFrame(v->uc->sample_id)); + } + if(STREAM_PLAYING(v)) + { + int entry = vj_tag_get_selected_entry(v->uc->sample_id); + int cha = vj_tag_get_chain_channel(v->uc->sample_id,entry); + int src = vj_tag_get_chain_source(v->uc->sample_id,entry); + int old = cha; + char description[100]; + + if(src==VJ_TAG_TYPE_NONE) + { //decrease sample id + cha = cha - args[0]; + if( sample_size()-1 <= 0 ) + { + veejay_msg(0, "No samples to mix with"); + return; + } + clamp_channel( + cha, + 1, + sample_size()-1 ); + if( !sample_exists(cha ) ) + cha = old; + } + else + { + cha = cha - args[0]; + if( vj_tag_size()-1 <= 0 ) + { + veejay_msg(0, "No streams to mix with"); + return; + } + clamp_channel( + cha, + 1, + vj_tag_size()-1 ); + if(! vj_tag_exists( cha )) + cha = old; + } + + vj_tag_set_chain_channel( v->uc->sample_id, entry, cha ); + vj_tag_get_descriptive( cha, description); + + veejay_msg(VEEJAY_MSG_INFO, "Chain entry %d uses Stream %d (%s)",entry,cha,description); +// if(v->no_bezerk) veejay_set_sample(v, v->uc->sample_id); + + } + +} + +void vj_event_chain_entry_channel_inc(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[1]; + char *str = NULL; P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + int entry = sample_get_selected_entry(v->uc->sample_id); + int cha = sample_get_chain_channel(v->uc->sample_id,entry); + int src = sample_get_chain_source(v->uc->sample_id,entry); + int old = cha; + if(src==VJ_TAG_TYPE_NONE) + { //decrease sample id + cha = cha + args[0]; + if( sample_size()-1 <= 0 ) + { + veejay_msg(0, "No samples to mix with"); + return; + } + clamp_channel( + cha, + 1, + sample_size()-1 ); + if( !sample_exists( cha ) ) + cha = old; + } + else + { + cha = cha + args[0]; + if( vj_tag_size()-1 <= 0 ) + { + veejay_msg(0, "No streams to mix with"); + return; + } + clamp_channel( + cha, + 1, + vj_tag_size()-1 ); + if( !vj_tag_exists(cha) ) + cha = old; + } + + sample_set_chain_channel( v->uc->sample_id, entry, cha ); + veejay_msg(VEEJAY_MSG_INFO, "Chain entry %d uses %s %d",entry, + (src==VJ_TAG_TYPE_NONE ? "Sample" : "Stream"),cha); +// if(v->no_bezerk) veejay_set_sample(v, v->uc->sample_id); + if(v->no_bezerk) veejay_set_frame(v,sample_get_startFrame(v->uc->sample_id)); + + } + if(STREAM_PLAYING(v)) + { + int entry = vj_tag_get_selected_entry(v->uc->sample_id); + int cha = vj_tag_get_chain_channel(v->uc->sample_id,entry); + int src = vj_tag_get_chain_source(v->uc->sample_id,entry); + int old = cha; + char description[100]; + + if(src==0) + { //decrease sample id + cha = cha + args[0]; + if( sample_size()-1 <= 0 ) + { + veejay_msg(0, "No samples to mix with"); + return; + } + clamp_channel( + cha, + 1, + sample_size()-1 ); + if( !sample_exists( cha ) ) + cha = old; + } + else + { + cha = cha + args[0]; + if( vj_tag_size()-1 <= 0 ) + { + veejay_msg(0, "No streams to mix with"); + return; + } + clamp_channel( + cha, + 1, + vj_tag_size()-1 ); + if( !vj_tag_exists( cha )) + cha = old; + } + + vj_tag_set_chain_channel( v->uc->sample_id, entry, cha ); + vj_tag_get_descriptive( cha, description); +// if(v->no_bezerk) veejay_set_sample(v, v->uc->sample_id); + + veejay_msg(VEEJAY_MSG_INFO, "Chain entry %d uses Stream %d (%s)",entry, + vj_tag_get_chain_channel(v->uc->sample_id,entry),description); + } +} + +void vj_event_chain_entry_channel(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[3]; + char *str = NULL; P_A(args,str,format,ap); + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of bounds: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + int src = sample_get_chain_source( args[0],args[1]); + int err = 1; + if(src == VJ_TAG_TYPE_NONE && sample_exists(args[2])) + { + err = 0; + } + if(src != VJ_TAG_TYPE_NONE && vj_tag_exists(args[2])) + { + err = 0; + } + if(err == 0 && sample_set_chain_channel(args[0],args[1], args[2])>= 0) + { + veejay_msg(VEEJAY_MSG_INFO, "Selected input channel (%s %d)", + (src == VJ_TAG_TYPE_NONE ? "sample" : "stream"),args[2]); + // if(v->no_bezerk) veejay_set_sample(v, v->uc->sample_id); + if(v->no_bezerk) veejay_set_frame(v,sample_get_startFrame(v->uc->sample_id)); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid channel (%s %d) given", + (src ==VJ_TAG_TYPE_NONE ? "sample" : "stream") , args[2]); + } + } + } + if(STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(args[0])) + { + int src = vj_tag_get_chain_source(args[0],args[1]); + int err = 1; + if( src == VJ_TAG_TYPE_NONE && sample_exists( args[2])) + err = 0; + if( src != VJ_TAG_TYPE_NONE && vj_tag_exists( args[2] )) + err = 0; + + if( err == 0 && vj_tag_set_chain_channel(args[0],args[1],args[2])>=0) + { + veejay_msg(VEEJAY_MSG_INFO, "Selected input channel (%s %d)", + (src==VJ_TAG_TYPE_NONE ? "sample" : "stream"), args[2]); +// if(v->no_bezerk) veejay_set_sample(v, v->uc->sample_id); + + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid channel (%s %d) given", + (src ==VJ_TAG_TYPE_NONE ? "sample" : "stream") , args[2]); + } + } + } +} + +void vj_event_chain_entry_srccha(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[4]; + char *str = NULL; P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = sample_size()-1; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + int source = args[2]; + int channel_id = args[3]; + int err = 1; + if( source == VJ_TAG_TYPE_NONE && sample_exists(channel_id)) + err = 0; + if( source != VJ_TAG_TYPE_NONE && vj_tag_exists(channel_id)) + err = 0; + + + if( err == 0 && + sample_set_chain_source(args[0],args[1],source)!=-1 && + sample_set_chain_channel(args[0],args[1],channel_id) != -1) + { + veejay_msg(VEEJAY_MSG_INFO, "Selected input channel (%s %d) to mix in", + (source == VJ_TAG_TYPE_NONE ? "sample" : "stream") , channel_id); + if( source != VJ_TAG_TYPE_NONE ) { + int slot = sample_has_cali_fx( args[0]);//@sample + if( slot >= 0 ) { + sample_cali_prepare( args[0],slot,channel_id); + veejay_msg(VEEJAY_MSG_DEBUG, "Using calibration data of stream %d",channel_id); + } + } + if(v->no_bezerk) veejay_set_frame(v,sample_get_startFrame(v->uc->sample_id)); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid channel (%s %d) given", + (source ==VJ_TAG_TYPE_NONE ? "sample" : "stream") , args[2]); + } + } + } + if(STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = sample_size()-1; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(args[0])) + { + int source = args[2]; + int channel_id = args[3]; + int err = 1; + if( source == VJ_TAG_TYPE_NONE && sample_exists(channel_id)) + err = 0; + if( source != VJ_TAG_TYPE_NONE && vj_tag_exists(channel_id)) + err = 0; + + //@ if there is CALI in FX chain, + //@ call cali_prepare and pass channel id + + + if( err == 0 && + vj_tag_set_chain_source(args[0],args[1],source)!=-1 && + vj_tag_set_chain_channel(args[0],args[1],channel_id) != -1) + { + veejay_msg(VEEJAY_MSG_INFO, "Selected input channel (%s %d) to mix in", + (source == VJ_TAG_TYPE_NONE ? "sample" : "stream") , channel_id); + + if( source != VJ_TAG_TYPE_NONE ) { + int slot = vj_tag_has_cali_fx( args[0]); + if( slot >= 0 ) { + vj_tag_cali_prepare( args[0],slot, channel_id); + } + + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid channel (%s %d) given", + (source ==VJ_TAG_TYPE_NONE ? "sample" : "stream") , args[2]); + } + } + } + +} + + +void vj_event_chain_arg_inc(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + int c = sample_get_selected_entry(v->uc->sample_id); + int effect = sample_get_effect_any(v->uc->sample_id, c); + int val = sample_get_effect_arg(v->uc->sample_id,c,args[0]); + if ( vj_effect_is_valid( effect ) ) + { + + int tval = val + args[1]; + if( tval > vj_effect_get_max_limit( effect,args[0] ) ) + tval = vj_effect_get_min_limit( effect,args[0]); + else + if( tval < vj_effect_get_min_limit( effect,args[0] ) ) + tval = vj_effect_get_max_limit( effect,args[0] ); + if(sample_set_effect_arg( v->uc->sample_id, c,args[0],tval)!=-1 ) + { + veejay_msg(VEEJAY_MSG_INFO,"Set parameter %d value %d",args[0],tval); + } + } + } + + if(STREAM_PLAYING(v)) + { + int c = vj_tag_get_selected_entry(v->uc->sample_id); + int effect = vj_tag_get_effect_any(v->uc->sample_id, c); + int val = vj_tag_get_effect_arg(v->uc->sample_id, c, args[0]); + + int tval = val + args[1]; + + if( tval > vj_effect_get_max_limit( effect,args[0] )) + tval = vj_effect_get_min_limit( effect,args[0] ); + else + if( tval < vj_effect_get_min_limit( effect,args[0] )) + tval = vj_effect_get_max_limit( effect,args[0] ); + + + if(vj_tag_set_effect_arg(v->uc->sample_id, c, args[0], tval) ) + { + veejay_msg(VEEJAY_MSG_INFO,"Set parameter %d value %d",args[0], tval ); + } + } +} + +void vj_event_chain_entry_set_arg_val(void *ptr, const char format[], va_list ap) +{ + int args[4]; + veejay_t *v = (veejay_t*)ptr; + char *str = NULL; P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = sample_size()-1; + if(args[1] == -1) args[1] = sample_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(sample_exists(args[0])) + { + int effect = sample_get_effect_any( args[0], args[1] ); + if( vj_effect_valid_value(effect,args[2],args[3]) ) + { + if(sample_set_effect_arg( args[0], args[1], args[2], args[3])) { + veejay_msg(VEEJAY_MSG_INFO, "Set parameter %d to %d on Entry %d of Sample %d", args[2], args[3],args[1],args[0]); + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Parameter %d with value %d invalid for Chain Entry %d of Sample %d", + args[2], args[3], args[1], args[0] ); + } + } else { veejay_msg(VEEJAY_MSG_ERROR, "Sample %d does not exist", args[0]); } + } + if(STREAM_PLAYING(v)) + { + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[1] == -1) args[1] = vj_tag_get_selected_entry(v->uc->sample_id); + if(v_chi(args[1])) + { + veejay_msg(VEEJAY_MSG_ERROR, "Chain index out of boundaries: %d", args[1]); + return; + } + + if(vj_tag_exists(args[0])) + { + int effect = vj_tag_get_effect_any(args[0],args[1] ); + if ( vj_effect_valid_value( effect,args[2],args[3] ) ) + { + if(vj_tag_set_effect_arg(args[0],args[1],args[2],args[3])) { + veejay_msg(VEEJAY_MSG_INFO,"Set parameter %d to %d on Entry %d of Stream %d", args[2],args[3],args[2],args[1]); + } + } + else { + veejay_msg(VEEJAY_MSG_ERROR, "Parameter %d with value %d for Chain Entry %d invalid for Stream %d", + args[2],args[3], args[1],args[0]); + } + } + else { + veejay_msg(VEEJAY_MSG_ERROR,"Stream %d does not exist", args[0]); + } + } +} + +void vj_event_el_cut(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + if( SAMPLE_PLAYING(v)) + { + if( !sample_usable_edl( v->uc->sample_id )) + { + veejay_msg(VEEJAY_MSG_ERROR, "This sample type has no EDL (all frames are identical)"); + return; + } + + editlist *el = sample_get_editlist( v->uc->sample_id ); + if(!el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample has no EDL (is this possible?)"); + return; + } + if( args[0] < 0 || args[0] > el->total_frames || args[1] < 0 || args[1] > el->total_frames) + { + veejay_msg(VEEJAY_MSG_ERROR, "Frame number out of bounds"); + return; + } + + if(veejay_edit_cut( v,el, args[0], args[1] )) + { + veejay_msg(VEEJAY_MSG_INFO, "Cut frames %d-%d from sample %d into buffer",args[0],args[1], + v->uc->sample_id); + } + + sample_set_startframe( v->uc->sample_id, 0 ); + sample_set_endframe( v->uc->sample_id, sample_video_length(v->uc->sample_id) ); + + constrain_sample( v, v->uc->sample_id ); + } + + if ( STREAM_PLAYING(v) || PLAIN_PLAYING(v)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot cut frames in this playback mode"); + return; + } + +} + +void vj_event_el_copy(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; P_A(args,str,format,ap); + + if ( SAMPLE_PLAYING(v)) + { + if( !sample_usable_edl( v->uc->sample_id )) + { + veejay_msg(VEEJAY_MSG_ERROR, "This sample type has no EDL (all frames are identical)"); + return; + } + + editlist *el = sample_get_editlist( v->uc->sample_id ); + if(!el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample has no EDL (is this possible?)"); + return; + } + if( args[0] < 0 || args[0] > el->total_frames || args[1] < 0 || args[1] > el->total_frames) + { + veejay_msg(VEEJAY_MSG_ERROR, "Frame number out of bounds"); + return; + } + + if(veejay_edit_copy( v,el, args[0], args[1] )) + { + veejay_msg(VEEJAY_MSG_INFO, "Copy frames %d-%d from sample %d into buffer",args[0],args[1], + v->uc->sample_id); + } + + sample_set_startframe( v->uc->sample_id, 0 ); + sample_set_endframe( v->uc->sample_id,sample_video_length(v->uc->sample_id)); + + constrain_sample( v, v->uc->sample_id ); + } + if ( STREAM_PLAYING(v) || PLAIN_PLAYING(v)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot copy frames in this playback mode"); + return; + } + +} + +void vj_event_el_del(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; P_A(args,str,format,ap); + + if ( SAMPLE_PLAYING(v)) + { + if( !sample_usable_edl( v->uc->sample_id )) + { + veejay_msg(VEEJAY_MSG_ERROR, "This sample type has no EDL (all frames are identical)"); + return; + } + + editlist *el = sample_get_editlist( v->uc->sample_id ); + + if(!el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample has no EDL (is this possible?)"); + return; + } + if( args[0] < 0 || args[0] > el->total_frames || args[1] < 0 || args[1] > el->total_frames) + { + veejay_msg(VEEJAY_MSG_ERROR, "Frame number out of bounds"); + return; + } + + if(veejay_edit_delete( v,el, args[0], args[1] )) + { + veejay_msg(VEEJAY_MSG_INFO, "Deleted frames %d-%d from EDL of sample %d", + v->uc->sample_id,args[0],args[1]); + } + sample_set_startframe( v->uc->sample_id, 0 ); + sample_set_endframe( v->uc->sample_id, sample_video_length(v->uc->sample_id)); + + constrain_sample( v, v->uc->sample_id ); + + } + + if ( STREAM_PLAYING(v) || PLAIN_PLAYING(v)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot delete frames in this playback mode"); + return; + } + +} + +void vj_event_el_crop(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; P_A(args,str,format,ap); + + if ( STREAM_PLAYING(v) || PLAIN_PLAYING(v)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot delete frames in this playback mode"); + return; + } + + if(SAMPLE_PLAYING(v)) + { + if( !sample_usable_edl( v->uc->sample_id )) + { + veejay_msg(VEEJAY_MSG_ERROR, "This sample type has no EDL (all frames are identical)"); + return; + } + + editlist *el = sample_get_editlist( v->uc->sample_id); + if(!el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample has no EDL"); + return; + } + + if( args[0] < 0 || args[0] > el->total_frames || args[1] < 0 || args[1] > el->total_frames) + { + veejay_msg(VEEJAY_MSG_ERROR, "Frame number out of bounds"); + return; + } + + if( args[1] <= args[0] ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Crop: start - end (start must be smaller then end)"); + return; + } + int s2 =0; + int s1 = veejay_edit_delete(v,el, 0, args[0]); + int res = 0; + if(s1) + { + args[1] -= args[0]; // after deleting the first part, move arg[1] + s2 = veejay_edit_delete(v, el,args[1], el->total_frames); + if(s2) + { + veejay_set_frame(v,0); + veejay_msg(VEEJAY_MSG_INFO, "Delete frames 0- %d , %d - %d from sample %d", 0,args[0],args[1], + el->total_frames, v->uc->sample_id); + res = 1; + sample_set_startframe( v->uc->sample_id, 0 ); + sample_set_endframe( v->uc->sample_id, sample_video_length(v->uc->sample_id) ); + constrain_sample( v, v->uc->sample_id ); + } + + } + if(!res) + veejay_msg(VEEJAY_MSG_ERROR, "Invalid range given to crop ! %d - %d", args[0],args[1] ); + + } +} + +void vj_event_el_paste_at(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *str = NULL; P_A(args,str,format,ap); + + if ( STREAM_PLAYING(v) || PLAIN_PLAYING(v)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot paste frames in this playback mode"); + return; + } + + if( SAMPLE_PLAYING(v)) + { + if( !sample_usable_edl( v->uc->sample_id )) + { + veejay_msg(VEEJAY_MSG_ERROR, "This sample type has no EDL (all frames are identical)"); + return; + } + + editlist *el = sample_get_editlist( v->uc->sample_id ); + long length = el->total_frames; + if(!el) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample has no EDL"); + return; + } + if( args[0] >= 0 && args[0] <= el->total_frames) + { + if( veejay_edit_paste( v, el, args[0] ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Pasted buffer at frame %d",args[0]); + } + sample_set_startframe( v->uc->sample_id, 0 ); + sample_set_endframe( v->uc->sample_id, sample_video_length(v->uc->sample_id)); + constrain_sample( v, v->uc->sample_id ); + } + + } +} + +void vj_event_el_save_editlist(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + char str[1024]; + veejay_memset(str,0,1024); + int args[2] = {0,0}; + P_A(args,str,format,ap); + if( STREAM_PLAYING(v) || PLAIN_PLAYING(v) ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Wrong playback mode for saving EDL of sample"); + return; + } + + if( veejay_save_all(v, str,args[0],args[1]) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Saved EditList as %s",str); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR,"Unable to save EditList as %s",str); + } +} + +void vj_event_el_load_editlist(void *ptr, const char format[], va_list ap) +{ + veejay_msg(VEEJAY_MSG_ERROR, "EditList: Load not implemented"); +} + + +void vj_event_el_add_video(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int start = -1; + int destination = v->current_edit_list->total_frames; + char str[1024]; + int *args = NULL; + P_A(args,str,format,ap); + + if(SAMPLE_PLAYING(v)) + { + if( !sample_usable_edl( v->uc->sample_id )) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot append video to a picture sample"); + return; + } + } + + if ( veejay_edit_addmovie(v,v->current_edit_list,str,start,destination)) + veejay_msg(VEEJAY_MSG_INFO, "Added video file %s to EditList",str); + else + veejay_msg(VEEJAY_MSG_INFO, "Unable to add file %s to EditList",str); +} + +void vj_event_el_add_video_sample(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + char str[1024]; + int args[2]; + P_A(args,str,format,ap); + + int new_sample_id = args[0]; + if(new_sample_id == 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "Trying to create new sample from %s", + str ); + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Trying to append %s to current sample", + str ); + } + new_sample_id = veejay_edit_addmovie_sample(v,str,new_sample_id ); + if(new_sample_id <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to open %s", str ); + new_sample_id = 0; + } + vj_event_send_new_id( v,new_sample_id ); +} + +void vj_event_tag_del(void *ptr, const char format[] , va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char *str = NULL; P_A(args,str,format,ap); + + + if(STREAM_PLAYING(v) && v->uc->sample_id == args[0]) + { + veejay_msg(VEEJAY_MSG_INFO,"Cannot delete stream while playing"); + } + else + { + if(vj_tag_exists(args[0])) + { + if(vj_tag_del(args[0])) + { + veejay_msg(VEEJAY_MSG_INFO, "Deleted stream %d", args[0]); + vj_tag_verify_delete( args[0], 1 ); + } + } + } + vj_event_send_new_id( v, args[0] ); +} + +void vj_event_tag_toggle(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[1]; + char *str = NULL; P_A(args,str,format,ap); + if(STREAM_PLAYING(v)) + { + int active = vj_tag_get_active(v->uc->sample_id); + vj_tag_set_active( v->uc->sample_id, !active); + veejay_msg(VEEJAY_MSG_INFO, "Stream is %s", (vj_tag_get_active(v->uc->sample_id) ? "active" : "disabled")); + } +} + +#ifdef USE_GDK_PIXBUF +void vj_event_tag_new_picture(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + char str[255]; + int *args = NULL; + P_A(args,str,format,ap); + + int id = veejay_create_tag(v, VJ_TAG_TYPE_PICTURE, str, v->nstreams,0,0); + + vj_event_send_new_id( v, id ); + if(id <= 0 ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create new Picture stream"); +} +#endif + +#ifdef SUPPORT_READ_DV2 +void vj_event_tag_new_dv1394(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + if(args[0] == -1) args[0] = 63; + veejay_msg(VEEJAY_MSG_DEBUG, "Try channel %d", args[0]); + int id = veejay_create_tag(v, VJ_TAG_TYPE_DV1394, "/dev/dv1394", v->nstreams,0, args[0]); + vj_event_send_new_id( v, id ); + if( id <= 0) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create new DV1394 stream"); +} +#endif + +void vj_event_v4l_blackframe( void *ptr, const char format[] , va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + + char *str = NULL; + int args[3]; + + P_A(args,str,format,ap); + + int id = args[0]; + if( id == 0 ) { + if( STREAM_PLAYING(v) ) + id = v->uc->sample_id; + } + + if( id == 0 ) { + return; + } + + if( args[1] == 0 ) { + vj_tag_drop_blackframe(id); + } else { + vj_tag_grab_blackframe(id, args[1], args[2],args[3]); + } +} + +void vj_event_cali_write_file( void *ptr, const char format[], va_list ap) +{ + char str[1024]; + int args[2]; + veejay_t *v = (veejay_t*) ptr; + + P_A(args,str,format,ap); + + int id = args[0]; + if( id == 0 ) { + if(STREAM_PLAYING(v)) + id = v->uc->sample_id; + } + if( vj_tag_exists( id ) ){ + if(vj_tag_cali_write_file( id, str, v->current_edit_list )) { + veejay_msg(VEEJAY_MSG_INFO, "Saved calibration file to %s", str ); + } + } + else { + p_no_tag(id); + } +} + +void vj_event_stream_new_cali( void *ptr, const char format[], va_list ap) +{ + char str[1024]; + int args[2]; + veejay_t *v = (veejay_t*) ptr; + + P_A(args,str,format,ap); + + + int id = veejay_create_tag( + v, VJ_TAG_TYPE_CALI, + str, + v->nstreams, + 0,0); + if(id > 0 ) + v->nstreams++; + + vj_event_send_new_id( v, id ); + + if( id <= 0 ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create load calibration file '%s'",str); + else + veejay_msg(VEEJAY_MSG_INFO, "Loaded calibration file to Stream %d",id ); + + +} + +void vj_event_tag_new_v4l(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + char *str = NULL; + int args[2]; + char filename[255]; + P_A(args,str,format,ap); + + sprintf(filename, "video%d", args[0]); + + int id = vj_tag_new(VJ_TAG_TYPE_V4L, + filename, + v->nstreams, + v->edit_list, + v->pixel_format, + args[1], + args[0], + v->settings->composite ); + + if(id > 0 ) + v->nstreams++; + + vj_event_send_new_id( v, id ); + if( id <= 0 ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create new Video4Linux stream "); +} + +void vj_event_tag_new_net(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + + char str[255]; + int args[2]; + + P_A(args,str,format,ap); + + if( strncasecmp( str, "localhost",9 ) == 0 || strncasecmp( str, "127.0.0.1",9 ) == 0 ) + { + if( args[0] == v->uc->port ) + { + veejay_msg(0, "Try another port number, I am listening on this one."); + vj_event_send_new_id(v, 0 ); + return; + } + } + + int id = veejay_create_tag(v, VJ_TAG_TYPE_NET, str, v->nstreams, args[0],0); + vj_event_send_new_id( v, id); + + if(id <= 0) + veejay_msg(VEEJAY_MSG_ERROR, "Failed to create unicast stream"); +} + +void vj_event_tag_new_mcast(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + + char str[255]; + int args[3]; + + P_A(args,str,format,ap); + + int id = veejay_create_tag(v, VJ_TAG_TYPE_MCAST, str, v->nstreams, args[0],0); + + vj_event_send_new_id( v, id ); + + if( id <= 0) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create new multicast stream"); + +} + + + +void vj_event_tag_new_color(void *ptr, const char format[], va_list ap) +{ + veejay_t *v= (veejay_t*) ptr; + char *str=NULL; + int args[4]; + P_A(args,str,format,ap); + + int i; + for(i = 0 ; i < 3; i ++ ) + CLAMPVAL( args[i] ); + + + int id = vj_tag_new( VJ_TAG_TYPE_COLOR, NULL, -1, v->edit_list,v->pixel_format, -1,0 , v->settings->composite); + if(id > 0) + { + vj_tag_set_stream_color( id, args[0],args[1],args[2] ); + } + + vj_event_send_new_id( v , id ); + if( id <= 0 ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create new solid color stream"); + +} + +void vj_event_tag_new_y4m(void *ptr, const char format[], va_list ap) +{ + veejay_t *v= (veejay_t*) ptr; + char str[255]; + int *args = NULL; + P_A(args,str,format,ap); + int id = veejay_create_tag(v, VJ_TAG_TYPE_YUV4MPEG, str, v->nstreams,0,0); + + vj_event_send_new_id( v, id ); + if( id <= 0 ) + veejay_msg(VEEJAY_MSG_INFO, "Unable to create new Yuv4mpeg stream"); +} +void vj_event_v4l_set_brightness(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0]==0) args[0] = v->uc->sample_id; + if(args[0]==-1) args[0] = vj_tag_size()-1; + if(vj_tag_exists(args[0]) && STREAM_PLAYING(v)) + { + if(vj_tag_set_brightness(args[0],args[1])) + { + veejay_msg(VEEJAY_MSG_INFO,"Set brightness to %d",args[1]); + } + } + +} + +void vj_event_vp_proj_toggle(void *ptr, const char format[],va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + + if(!v->composite ) { + veejay_msg(0, "No viewport active."); + return; + } + + int mode = !composite_get_status(v->composite); + composite_set_status( v->composite, mode ); + + veejay_msg(VEEJAY_MSG_INFO, "Projection transform is now %s", + (mode==0? "inactive" : "active")); +} + +void vj_event_vp_stack( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + if(!v->composite ) { + veejay_msg(0, "No viewport active."); + return; + } + + if( args[0] == 1 ) + { + /* int cs = composite_get_colormode(v->composite); + if(cs == 0 ) + cs = 1; + else + cs = 0; + composite_set_colormode( v->composite, cs ); + veejay_msg(VEEJAY_MSG_INFO ,"Secundary Input renders in %s", (cs == 1 ?"Grayscale" : "Color" ) ); + return;*/ + } + + if ( args[1] == 1 ) { + if(v->settings->composite == 1 ) + v->settings->composite = 2; + else if (v->settings->composite == 2 ) + v->settings->composite = 1; + veejay_msg(VEEJAY_MSG_INFO, "Focus on %s, press CTRL-h for more help.", (v->settings->composite == 1 ? "Projection" : "Secundary Input")); + if( SAMPLE_PLAYING(v) ) { + + /* sample_reload_config( v->composite, v->uc->sample_id,v->settings->composite ); + + if(v->settings->composite == 2 && sample_get_composite(v->uc->sample_id ) == 0 ) + { + sample_set_composite( v->composite, v->uc->sample_id, 2 ); + void *cur = sample_get_composite_view(v->uc->sample_id); + if(cur==NULL) { + cur = composite_clone( v->composite ); + } + composite_set_backing(v->composite,cur ); + veejay_msg(0, "Saved calibration to current sample"); + }*/ + sample_set_composite( v->composite, v->uc->sample_id, v->settings->composite ); + + veejay_msg(VEEJAY_MSG_INFO, + "Secundary input sample %d will %s.", v->uc->sample_id, + (v->settings->composite == 2 ? "be transformed" : "not be transformed" ) ); + } else if (STREAM_PLAYING(v)) { + + /* vj_tag_reload_config( v->composite, v->uc->sample_id,v->settings->composite ); + + if(v->settings->composite == 2 && vj_tag_get_composite(v->uc->sample_id) == 0 ) + { + vj_tag_set_composite( v->composite, v->uc->sample_id, 2 ); + void *cur = vj_tag_get_composite_view(v->uc->sample_id); + if(cur==NULL) { + cur = composite_clone( v->composite ); + } + composite_set_backing(v->composite,cur ); + + veejay_msg(0, "Saved calibration to current sample"); + }*/ + + vj_tag_set_composite( v->composite, v->uc->sample_id, v->settings->composite ); + + veejay_msg(VEEJAY_MSG_INFO, + "Secundary input stream %d will %s.", v->uc->sample_id, + (v->settings->composite == 2 ? "be transformed" : "not be transformed" ) ); + + } + } + +} +void vj_event_vp_get_points( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + char msg[280]; + char message[256]; + + if( args[0] == 0 || !v->composite) { + snprintf(message,256,"%d %d %d %d %d %d %d %d", + 0,0,0,0,0,0,0,0); + FORMAT_MSG(msg,message); + SEND_MSG(v,msg); + return; + } +//FIXME +// int *r = viewport_event_get_projection( composite_get_vp( v->composite ),args[0] ); + int r[8]; + memset(r,0,sizeof(r)); + snprintf(message,256, "%d %d %d %d %d %d %d %d", + r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7] ); + + char *err = "0 0 0 0 0 0 0 0"; + FORMAT_MSG(msg,err); + SEND_MSG(v,err); +} + +void vj_event_vp_set_points( void *ptr, const char format[], va_list ap ) +{ + int args[4]; + veejay_t *v = (veejay_t*)ptr; + veejay_memset(args,0,sizeof(args)); + char *str = NULL; + P_A(args,str,format,ap); + + if(!v->composite ) { + veejay_msg(0, "No viewport active."); + return; + } + + if( args[0] <= 0 || args[0] > 4 ) { + veejay_msg(0, "Invalid point number. Use 1 - 4"); + return; + } + if( args[1] < 0 ) { + veejay_msg(0, "Scale must be a positive number."); + return; + } + float point_x = ( (float) args[2] / (float) args[1] ); + float point_y = ( (float) args[3] / (float) args[1] ); + + video_playback_setup *settings = v->settings; + v->settings->cx = point_x; + v->settings->cy = point_y; + v->settings->cn = args[0]; + v->settings->ca = 1; + +} + +// 159, 164 for white +void vj_event_v4l_get_info(void *ptr, const char format[] , va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0]==0) args[0] = v->uc->sample_id; + if(args[0]==-1) args[0] = vj_tag_size()-1; + + char send_msg[33]; + char message[30]; + veejay_memset(send_msg, 0,sizeof(send_msg)); + + sprintf( send_msg, "000" ); + + if(vj_tag_exists(args[0])) + { + int values[6]; + memset(values,0,6*sizeof(int)); + if(vj_tag_get_v4l_properties( args[0], &values[0], &values[1], &values[2], &values[3], &values[4])) + { + sprintf(message, "%05d%05d%05d%05d%05d%05d", + values[0],values[1],values[2],values[3],values[4],values[5] ); + FORMAT_MSG(send_msg, message); + } + } + + SEND_MSG( v,send_msg ); +} + +void vj_event_v4l_set_contrast(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0]==0) args[0] = v->uc->sample_id; + if(args[0]==-1)args[0] = vj_tag_size()-1; + if(vj_tag_exists(args[0]) && STREAM_PLAYING(v)) + { + if(vj_tag_set_contrast(args[0],args[1])) + { + veejay_msg(VEEJAY_MSG_INFO,"Set contrast to %d",args[1]); + } + } +} + +void vj_event_v4l_set_white(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0]==0) args[0] = v->uc->sample_id; + if(args[0]==-1)args[0] = vj_tag_size()-1; + if(vj_tag_exists(args[0]) && STREAM_PLAYING(v)) + { + if(vj_tag_set_white(args[0],args[1])) + { + veejay_msg(VEEJAY_MSG_INFO,"Set whiteness to %d",args[1]); + } + } + +} +void vj_event_v4l_set_saturation(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0]==0) args[0] = v->uc->sample_id; + if(args[0]==-1)args[0] = vj_tag_size()-1; + if(vj_tag_exists(args[0]) && STREAM_PLAYING(v)) + { +veejay_msg(0, "broken"); + } + +} +void vj_event_v4l_set_color(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = vj_tag_size()-1; + if(vj_tag_exists(args[0]) && STREAM_PLAYING(v)) + { + if(vj_tag_set_color(args[0],args[1])) + { + veejay_msg(VEEJAY_MSG_INFO,"Set color to %d",args[1]); + } + } + +} +void vj_event_v4l_set_hue(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + unsigned char *str = NULL; + P_A(args,str,format,ap); + if(args[0] == 0) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = vj_tag_size()-1; + if(vj_tag_exists(args[0]) && STREAM_PLAYING(v)) + { + if(vj_tag_set_hue(args[0],args[1])) + { + veejay_msg(VEEJAY_MSG_INFO,"Set hue to %d",args[1]); + } + } + +} +void vj_event_viewport_frontback(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(!v->composite) { + veejay_msg(VEEJAY_MSG_ERROR, "No viewport active."); + return; + } + + if( v->settings->composite && composite_get_ui( v->composite ) ) { + if(v->use_osd==3) + v->use_osd = 0; + v->settings->composite = 2; + if(STREAM_PLAYING(v)) { + void *cur = vj_tag_get_composite_view(v->uc->sample_id); + if(cur == NULL ) { + cur = (void*)composite_clone(v->composite); + vj_tag_set_composite_view(v->uc->sample_id,cur); + } + vj_tag_reload_config(v->composite,v->uc->sample_id,v->settings->composite ); + veejay_msg(VEEJAY_MSG_INFO, "Saved calibration to stream %d",v->uc->sample_id); + } else if (SAMPLE_PLAYING(v)) { + void *cur = sample_get_composite_view( v->uc->sample_id ); + if( cur == NULL ) { + cur = composite_clone(v->composite); + sample_set_composite_view(v->uc->sample_id, cur ); + } + sample_reload_config( v->composite,v->uc->sample_id, v->settings->composite); + veejay_msg(VEEJAY_MSG_INFO, "Saved calibration to sample %d",v->uc->sample_id ); + } + composite_set_ui(v->composite, 0 ); + if(v->video_out==0 || v->video_out == 2) + vj_sdl_grab( v->sdl[0], 0 ); + } + else { + composite_set_ui( v->composite, 1 ); + v->settings->composite = 1; + v->use_osd=3; + if(v->video_out==0 || v->video_out == 2) + vj_sdl_grab( v->sdl[0], 1 ); + + veejay_msg(VEEJAY_MSG_INFO, "You can now calibrate your projection/camera, press CTRL-s again to exit."); + } +} + +void vj_event_toggle_osd( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + if(v->use_osd == 0 ) + { + v->use_osd = 1; + veejay_msg(VEEJAY_MSG_INFO, "OSD on"); + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "OSD off"); + v->use_osd = 0; + } +} +void vj_event_toggle_copyright( void *ptr, const char format[], va_list ap ) +{ + static int old_osd = -1; + veejay_t *v = (veejay_t*) ptr; + if( old_osd == -1 ) + old_osd = v->use_osd; + if(v->use_osd == 0 || v->use_osd == 1) + v->use_osd = 2; + else + v->use_osd = (old_osd==-1?0: old_osd); +} +void vj_event_toggle_osd_extra( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + if(v->use_osd == 3 ) + v->use_osd = 0; + else + { + v->use_osd = 3; + veejay_msg(VEEJAY_MSG_INFO, "Not displaying viewport help"); + } +} + +static struct { + char *name; + int id; +} recorder_formats[] = { + { "mlzo", ENCODER_LZO }, + { "y4m422", ENCODER_YUV4MPEG }, + { "y4m420", ENCODER_YUV4MPEG420 }, + { "yv16", ENCODER_YUV422 }, + { "y422", ENCODER_YUV422 }, + { "i420", ENCODER_YUV420 }, + { "y420", ENCODER_YUV420 }, + { "div3", ENCODER_DIVX }, + { "mpeg4", ENCODER_MPEG4 }, +#ifdef SUPPORT_READ_DV2 + { "dvvideo", ENCODER_DVVIDEO }, +#endif + { "dvsd", ENCODER_DVVIDEO }, + { "mjpeg", ENCODER_MJPEG }, + { "mjpeg-b", ENCODER_MJPEGB }, + { "mjpegb", ENCODER_MJPEGB }, + { "ljpeg", ENCODER_LJPEG }, +#ifdef HAVE_LIBQUICKTIME + { "quicktime-mjpeg", ENCODER_QUICKTIME_MJPEG }, +#ifdef SUPPORT_READ_DV2 + { "quicktime-dv", ENCODER_QUICKTIME_DV }, +#endif +#endif + { "vj20", ENCODER_YUV420F }, + { "vj22", ENCODER_YUV422F }, + { NULL , -1 } +}; + +void vj_event_tag_set_format(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char str[255]; + veejay_memset(str,0,255); + P_A(args,str,format,ap); + + if(v->settings->tag_record || v->settings->offline_record) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot change data format while recording to disk"); + return; + } + + int i; + if( strncasecmp(str, "list", 4 ) == 0 || strncasecmp( str, "help",4) == 0 ) { + for(i = 0; recorder_formats[i].name != NULL ; i ++ ) { + veejay_msg(VEEJAY_MSG_INFO,"%s", recorder_formats[i].name ); + } + return; + } + + + for( i = 0; recorder_formats[i].name != NULL ; i ++ ) { + if(strncasecmp( str, recorder_formats[i].name, strlen(recorder_formats[i].name) ) == 0 ) { + _recorder_format = recorder_formats[i].id; + } + } + + + if( strncasecmp(str, "yuv", 3 ) == 0 || strncasecmp(str, "intern", 6 ) == 0) { + switch(v->pixel_format) { + case FMT_422F: _recorder_format = ENCODER_YUV422F; break; + case FMT_422 : _recorder_format = ENCODER_YUV422; break; + } + } + + if(strncasecmp(str,"dvvideo",7)==0||strncasecmp(str,"dvsd",4)==0) + { + if(vj_el_is_dv(v->current_edit_list)) { + _recorder_format = ENCODER_DVVIDEO; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Not working in a valid DV resolution"); + } + return; + } + +#ifdef HAVE_LIBQUICKTIME + if(strncasecmp(str,"quicktime-dv", 12 ) == 0 ) + { + if( vj_el_is_dv( v->current_edit_list )) + { + _recorder_format = ENCODER_QUICKTIME_DV; + veejay_msg(VEEJAY_MSG_INFO, "Recorder writes in QT DV format"); + } + else + veejay_msg(VEEJAY_MSG_ERROR, "Not working in valid DV resolution"); + } +#endif + + veejay_msg(VEEJAY_MSG_INFO, + "Recording in %s" , vj_avcodec_get_encoder_name( _recorder_format ) ); +} + +static void _vj_event_tag_record( veejay_t *v , int *args, char *str ) +{ + if(!STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + char tmp[255]; + char prefix[255]; + if(args[0] <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Number of frames to record must be > 0"); + return; + } + + if(args[1] < 0 || args[1] > 1) + { + veejay_msg(VEEJAY_MSG_ERROR,"Auto play is either on or off"); + return; + } + + char sourcename[255]; + vj_tag_get_description( v->uc->sample_id, sourcename ); + sprintf(prefix,"%s-%02d-", sourcename, v->uc->sample_id); + if(! veejay_create_temp_file(prefix, tmp )) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot create temporary file %s", tmp); + return; + } + + int format = _recorder_format; + if(_recorder_format == -1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Set a destination format first"); + return; + } + + if(args[0] <= 1 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cowardly refusing to record less then 2 frames"); + return; + } + + if( vj_tag_init_encoder( v->uc->sample_id, tmp, format, + args[0]) <= 0 ) + { + veejay_msg(VEEJAY_MSG_INFO, "Error trying to start recording from stream %d", v->uc->sample_id); + vj_tag_stop_encoder(v->uc->sample_id); + v->settings->tag_record = 0; + return; + } + + if(v->use_osd) + { + veejay_msg(VEEJAY_MSG_INFO,"Turned off OSD, recording now"); + v->use_osd = 0; + } + + if(args[1]==0) + v->settings->tag_record_switch = 0; + else + v->settings->tag_record_switch = 1; + + v->settings->tag_record = 1; +} + +void vj_event_tag_rec_start(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + _vj_event_tag_record( v, args, str ); +} + +void vj_event_tag_rec_stop(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; + video_playback_setup *s = v->settings; + + if( STREAM_PLAYING(v) && v->settings->tag_record) + { + int play_now = s->tag_record_switch; + if(!vj_tag_stop_encoder( v->uc->sample_id)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Wasnt recording anyway"); + return; + } + + char avi_file[255]; + if( !vj_tag_get_encoded_file(v->uc->sample_id, avi_file)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Dont know where I put the file?!"); + return; + } + + // create new sample + int ns = veejay_edit_addmovie_sample( v,avi_file, 0 ); + if(ns > 0) + { + int len = vj_tag_get_encoded_frames(v->uc->sample_id) - 1; + veejay_msg(VEEJAY_MSG_INFO,"Added file %s (%d frames) to EditList as sample %d", + avi_file, len ,ns); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot add videofile %s to EditList!",avi_file); + } + + veejay_msg(VEEJAY_MSG_ERROR, "Stopped recording from stream %d", v->uc->sample_id); + vj_tag_reset_encoder( v->uc->sample_id); + s->tag_record = 0; + s->tag_record_switch = 0; + + if(play_now) + { + veejay_msg(VEEJAY_MSG_INFO, "Playing sample %d now", sample_size()-1); + veejay_change_playback_mode( v, VJ_PLAYBACK_MODE_SAMPLE, sample_size()-1 ); + } + } + else + { + if(v->settings->offline_record) + { + veejay_msg(VEEJAY_MSG_ERROR, "Perhaps you want to stop recording from a non visible stream ? See VIMS id %d", + VIMS_STREAM_OFFLINE_REC_STOP); + } + veejay_msg(VEEJAY_MSG_ERROR, "Not recording from visible stream"); + } +} + +void vj_event_tag_rec_offline_start(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[3]; + char *str = NULL; P_A(args,str,format,ap); + + if( v->settings->offline_record ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Already recording from stream %d", v->settings->offline_tag_id); + return; + } + if( v->settings->tag_record) + { + veejay_msg(VEEJAY_MSG_ERROR ,"Please stop the stream recorder first"); + return; + } + + if( STREAM_PLAYING(v) && (args[0] == v->uc->sample_id) ) + { + veejay_msg(VEEJAY_MSG_INFO,"Using stream recorder for stream %d (is playing)",args[0]); + _vj_event_tag_record(v, args+1, str); + return; + } + + + if( vj_tag_exists(args[0])) + { + char tmp[255]; + + int format = _recorder_format; + char prefix[40]; + sprintf(prefix, "stream-%02d", args[0]); + + if(!veejay_create_temp_file(prefix, tmp )) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error creating temporary file %s", tmp); + return; + } + + if(format==-1) + { + veejay_msg(VEEJAY_MSG_ERROR, "Set a destination format first"); + return; + } + + if( vj_tag_init_encoder( args[0], tmp, format, + args[1]) ) + { + video_playback_setup *s = v->settings; + veejay_msg(VEEJAY_MSG_INFO, "(Offline) recording from stream %d", args[0]); + s->offline_record = 1; + s->offline_tag_id = args[0]; + s->offline_created_sample = args[2]; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "(Offline) error starting recording stream %d",args[0]); + } + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Stream %d does not exist",args[0]); + } +} + +void vj_event_tag_rec_offline_stop(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + video_playback_setup *s = v->settings; + if(s->offline_record) + { + if( vj_tag_stop_encoder( s->offline_tag_id ) == 0 ) + { + char avi_file[255]; + + if( vj_tag_get_encoded_file(v->uc->sample_id, avi_file)!=0) return; + + // create new sample + int ns = veejay_edit_addmovie_sample(v,avi_file,0); + + if(ns) + { + if( vj_tag_get_encoded_frames(v->uc->sample_id) > 0) + veejay_msg(VEEJAY_MSG_INFO, "Created new sample %d from file %s", + ns,avi_file); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot add videofile %s to EditList!",avi_file); + } + + vj_tag_reset_encoder( v->uc->sample_id); + + if(s->offline_created_sample) + { + veejay_msg(VEEJAY_MSG_INFO, "Playing new sample %d now ", sample_size()-1); + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_SAMPLE , sample_size()-1); + } + } + s->offline_record = 0; + s->offline_tag_id = 0; + s->offline_created_sample = 0; + } +} + + +void vj_event_output_y4m_start(void *ptr, const char format[], va_list ap) +{ + veejay_msg(0, "Y4M out stream: obsolete - use recorder."); +} + +void vj_event_output_y4m_stop(void *ptr, const char format[], va_list ap) +{ + veejay_msg(0, "Y4M out stream: obsolete - use recorder."); +} + +void vj_event_enable_audio(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; +#ifdef HAVE_JACK + if (!v->audio_running ) + { + veejay_msg(0,"Veejay was started without audio."); + return; + } + + if( v->audio == NO_AUDIO ) + { + vj_jack_enable(); + v->audio = AUDIO_PLAY; + } +#endif +} + +void vj_event_disable_audio(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t *)ptr; +#ifdef HAVE_JACK + if (!v->audio_running ) + { + veejay_msg(0,"Veejay was started without audio."); + return; + } + + if( v->audio != NO_AUDIO ) + { + vj_jack_disable(); + v->audio = NO_AUDIO; + vj_jack_reset(); + } +#endif +} + + +void vj_event_effect_inc(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int real_id; + int args[1]; + char *s = NULL; + P_A(args,s,format,ap); + if(!SAMPLE_PLAYING(v) && !STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + v->uc->key_effect += args[0]; + if(v->uc->key_effect >= vj_effect_max_effects()) v->uc->key_effect = 1; + + real_id = vj_effect_get_real_id(v->uc->key_effect); + + veejay_msg(VEEJAY_MSG_INFO, "Selected %s Effect %s (%d)", + (vj_effect_get_extra_frame(real_id)==1 ? "Video" : "Image"), + vj_effect_get_description(real_id), + real_id); +} + +void vj_event_effect_dec(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int real_id; + int args[1]; + char *s = NULL; + P_A(args,s,format,ap); + if(!SAMPLE_PLAYING(v) && !STREAM_PLAYING(v)) + { + p_invalid_mode(); + return; + } + + v->uc->key_effect -= args[0]; + if(v->uc->key_effect <= 0) v->uc->key_effect = vj_effect_max_effects()-1; + + real_id = vj_effect_get_real_id(v->uc->key_effect); + veejay_msg(VEEJAY_MSG_INFO, "Selected %s Effect %s (%d)", + (vj_effect_get_extra_frame(real_id) == 1 ? "Video" : "Image"), + vj_effect_get_description(real_id), + real_id); +} +void vj_event_effect_add(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + if(SAMPLE_PLAYING(v)) + { + int c = sample_get_selected_entry(v->uc->sample_id); + if ( sample_chain_add( v->uc->sample_id, c, + vj_effect_get_real_id(v->uc->key_effect)) != 1) + { + int real_id = vj_effect_get_real_id(v->uc->key_effect); + veejay_msg(VEEJAY_MSG_INFO,"Added Effect %s on chain entry %d", + vj_effect_get_description(real_id), + c + ); + if(v->no_bezerk && vj_effect_get_extra_frame(real_id) ) + { + //veejay_set_sample(v,v->uc->sample_id); + // + int nf = sample_get_startFrame( v->uc->sample_id ); + veejay_set_frame(v,nf ); + } + v->uc->chain_changed = 1; + } + } + if(STREAM_PLAYING(v)) + { + int c = vj_tag_get_selected_entry(v->uc->sample_id); + if ( vj_tag_set_effect( v->uc->sample_id, c, + vj_effect_get_real_id( v->uc->key_effect) ) != -1) + { + int real_id = vj_effect_get_real_id(v->uc->key_effect); + veejay_msg(VEEJAY_MSG_INFO,"Added Effect %s on chain entry %d", + vj_effect_get_description(real_id), + c + ); +// if(v->no_bezerk && vj_effect_get_extra_frame(real_id)) veejay_set_sample(v,v->uc->sample_id); + v->uc->chain_changed = 1; + } + } + +} + +void vj_event_misc_start_rec_auto(void *ptr, const char format[], va_list ap) +{ + +} +void vj_event_misc_start_rec(void *ptr, const char format[], va_list ap) +{ + +} +void vj_event_misc_stop_rec(void *ptr, const char format[], va_list ap) +{ + +} + +void vj_event_select_id(void *ptr, const char format[], va_list ap) +{ + veejay_t *v= (veejay_t*)ptr; + int args[2]; + char *str = NULL; + P_A(args,str, format, ap); + if(!STREAM_PLAYING(v)) + { + int sample_id = (v->uc->sample_key*12)-12 + args[0]; + if(sample_exists(sample_id)) + { + veejay_change_playback_mode( v, VJ_PLAYBACK_MODE_SAMPLE, sample_id); + vj_event_print_sample_info(v,sample_id); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR,"Selected sample %d does not exist",sample_id); + } + } + else + { + int sample_id = (v->uc->sample_key*12)-12 + args[0]; + if(vj_tag_exists(sample_id )) + { + veejay_change_playback_mode(v, VJ_PLAYBACK_MODE_TAG ,sample_id); + + } + else + { + veejay_msg(VEEJAY_MSG_INFO,"Selected stream %d does not exist",sample_id); + } + } + +} + +void vj_event_select_macro( void *ptr, const char format[], va_list ap ) +{ + int args[2]; + char *str = NULL; + P_A( args, str, format, ap ); + macro_select( args[0] ); + veejay_msg(VEEJAY_MSG_INFO, "Changed macro slot to %d", current_macro_ ); +} + +void vj_event_select_bank(void *ptr, const char format[], va_list ap) +{ + veejay_t *v =(veejay_t*) ptr; + int args[1]; + + char *str = NULL; P_A(args,str,format,ap); + if(args[0] >= 1 && args[0] <= 9) + { + veejay_msg(VEEJAY_MSG_INFO,"Selected bank %d (active sample range is now %d-%d)",args[0], + (12 * args[0]) - 12 , (12 * args[0])); + v->uc->sample_key = args[0]; + } +} + +void vj_event_print_tag_info(veejay_t *v, int id) +{ + int i, y, j, value; + char description[100]; + char source[150]; + char title[150]; + vj_tag_get_descriptive(id,description); + vj_tag_get_description(id, title); + vj_tag_get_source_name(id, source); + + if(v->settings->tag_record) + veejay_msg(VEEJAY_MSG_INFO, "Stream '%s' [%d]/[%d] [%s] %s recorded: %06ld frames ", + title,id,vj_tag_size()-1,description, + (vj_tag_get_active(id) ? "is active" : "is not active"), + vj_tag_get_encoded_frames(id)); + else + veejay_msg(VEEJAY_MSG_INFO, + "Stream [%d]/[%d] [%s] %s ", + id, vj_tag_size()-1, description, + (vj_tag_get_active(id) == 1 ? "is active" : "is not active")); + + if( vj_tag_get_composite( id ) ) + veejay_msg(VEEJAY_MSG_INFO, "This tag is transformed when used as secundary input."); + + veejay_msg(VEEJAY_MSG_INFO, "|-----------------------------------|"); + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + { + y = vj_tag_get_effect_any(id, i); + if (y != -1) + { + veejay_msg(VEEJAY_MSG_INFO, "%02d [%d] [%s] %s (%s)", + i, + y, + vj_tag_get_chain_status(id,i) ? "on" : "off", vj_effect_get_description(y), + (vj_effect_get_subformat(y) == 1 ? "2x2" : "1x1") + ); + + for (j = 0; j < vj_effect_get_num_params(y); j++) + { + value = vj_tag_get_effect_arg(id, i, j); + if (j == 0) + { + veejay_msg(VEEJAY_MSG_PRINT, " [%04d]", value); + } + else + { + veejay_msg(VEEJAY_MSG_PRINT, " [%04d]",value); + } + + } + veejay_msg(VEEJAY_MSG_PRINT, "\n"); + + if (vj_effect_get_extra_frame(y) == 1) + { + int source = vj_tag_get_chain_source(id, i); + veejay_msg(VEEJAY_MSG_INFO, " V %s [%d]",(source == VJ_TAG_TYPE_NONE ? "Sample" : "Stream"), + vj_tag_get_chain_channel(id,i) + ); + //veejay_msg(VEEJAY_MSG_INFO, " A: %s", vj_tag_get_chain_audio(id, i) ? "yes" : "no"); + } + + veejay_msg(VEEJAY_MSG_PRINT, "\n"); + } + } +} + +void vj_event_create_effect_bundle(veejay_t * v, char *buf, int key_id, int key_mod ) +{ + char blob[50 * SAMPLE_MAX_EFFECTS]; + char prefix[20]; + int i ,y,j; + int num_cmd = 0; + int id = v->uc->sample_id; + int event_id = 0; + int bunlen=0; + veejay_memset(prefix,0,20); + veejay_memset(blob,0,50*SAMPLE_MAX_EFFECTS ); + + if(!SAMPLE_PLAYING(v) && !STREAM_PLAYING(v)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot take snapshot of Effect Chain"); + return; + } + + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + { + y = (SAMPLE_PLAYING(v) ? sample_get_effect_any(id, i) : vj_tag_get_effect_any(id,i) ); + if (y != -1) + { + num_cmd++; + } + } + if(num_cmd < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Effect Chain is empty." ); + return; + } + + for (i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + y = (SAMPLE_PLAYING(v) ? sample_get_effect_any(id, i) : vj_tag_get_effect_any(id,i) ); + if( y != -1) + { + //int entry = i; + int effect_id = y; + if(effect_id != -1) + { + char bundle[200]; + int np = vj_effect_get_num_params(y); + sprintf(bundle, "%03d:0 %d %d", VIMS_CHAIN_ENTRY_SET_PRESET,i, effect_id ); + for (j = 0; j < np; j++) + { + char svalue[10]; + int value = (SAMPLE_PLAYING(v) ? sample_get_effect_arg(id, i, j) : vj_tag_get_effect_arg(id,i,j)); + if(value != -1) + { + if(j == (np-1)) + sprintf(svalue, " %d;", value); + else + sprintf(svalue, " %d", value); + veejay_strncat( bundle, svalue, strlen(svalue)); + } + } + veejay_strncpy( blob+bunlen, bundle,strlen(bundle)); + bunlen += strlen(bundle); + } + } + } + sprintf(prefix, "BUN:%03d{", num_cmd); + sprintf(buf, "%s%s}",prefix,blob); + event_id = vj_event_suggest_bundle_id(); + + if(event_id <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot add more bundles"); + return; + } + + vj_msg_bundle *m = vj_event_bundle_new( buf, event_id); + if(!m) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to create new Bundle"); + return; + } + if(!vj_event_bundle_store(m)) + veejay_msg(VEEJAY_MSG_ERROR, "Error storing Bundle %d", event_id); +} + + +void vj_event_print_sample_info(veejay_t *v, int id) +{ + video_playback_setup *s = v->settings; + int y, i, j; + long value; + char timecode[15]; + char curtime[15]; + char sampletitle[200]; + MPEG_timecode_t tc; + y4m_ratio_t ratio = mpeg_conform_framerate( (double)v->current_edit_list->video_fps ); + long start = sample_get_startFrame( id ); + long end = sample_get_endFrame( id ); + long speed = sample_get_speed(id); + long len = end - start; + +// if(start == 0) len ++; + veejay_memset( &tc,0,sizeof(MPEG_timecode_t)); + mpeg_timecode(&tc, len, mpeg_framerate_code( ratio ),v->current_edit_list->video_fps); + sprintf(timecode, "%2d:%2.2d:%2.2d:%2.2d", tc.h, tc.m, tc.s, tc.f); + + mpeg_timecode(&tc, s->current_frame_num, mpeg_framerate_code(ratio),v->current_edit_list->video_fps); + sprintf(curtime, "%2d:%2.2d:%2.2d:%2.2d", tc.h, tc.m, tc.s, tc.f); + sample_get_description( id, sampletitle ); + + veejay_msg(VEEJAY_MSG_PRINT, "\n"); + veejay_msg(VEEJAY_MSG_INFO, + "Sample '%s'[%4d]/[%4d]\t[duration: %s | %8ld]", + sampletitle,id,sample_size()-1,timecode,len); + + if( sample_get_composite( id ) ) + veejay_msg(VEEJAY_MSG_INFO, "This sample will be transformed when used as secundary input."); + + if(sample_encoder_active(v->uc->sample_id)) + { + veejay_msg(VEEJAY_MSG_INFO, "REC %09d\t[timecode: %s | %8ld ]", + sample_get_frames_left(v->uc->sample_id), + curtime,(long)v->settings->current_frame_num); + + } + else + { + veejay_msg(VEEJAY_MSG_INFO, " \t[timecode: %s | %8ld ]", + curtime,(long)v->settings->current_frame_num); + } + veejay_msg(VEEJAY_MSG_INFO, + "[%09ld] - [%09ld] @ %4.2f (speed %d)", + start,end, (float)speed * v->current_edit_list->video_fps,speed); + veejay_msg(VEEJAY_MSG_INFO, + "[%s looping]", + (sample_get_looptype(id) == + 2 ? "pingpong" : (sample_get_looptype(id)==1 ? "normal" : (sample_get_looptype(id)==3 ? "random" : "none")) ) + ); + + int first = 0; + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) + { + y = sample_get_effect_any(id, i); + if (y != -1) + { + if(!first) + { + veejay_msg(VEEJAY_MSG_INFO, "\nI: E F F E C T C H A I N\nI:"); + veejay_msg(VEEJAY_MSG_INFO,"Entry|Effect ID|SW | Name"); + first = 1; + } + veejay_msg(VEEJAY_MSG_INFO, "%02d |%03d |%s| %s %s", + i, + y, + sample_get_chain_status(id,i) ? "on " : "off", vj_effect_get_description(y), + (vj_effect_get_subformat(y) == 1 ? "2x2" : "1x1") + ); + + for (j = 0; j < vj_effect_get_num_params(y); j++) + { + value = sample_get_effect_arg(id, i, j); + if (j == 0) + { + veejay_msg(VEEJAY_MSG_PRINT, "I:\t\t\tP%d=[%d]",j, value); + } + else + { + veejay_msg(VEEJAY_MSG_PRINT, " P%d=[%d] ",j,value); + } + } + veejay_msg(VEEJAY_MSG_PRINT, "\n"); + if (vj_effect_get_extra_frame(y) == 1) + { + int source = sample_get_chain_source(id, i); + + veejay_msg(VEEJAY_MSG_PRINT, "I:\t\t\t Mixing with %s %d\n",(source == VJ_TAG_TYPE_NONE ? "sample" : "stream"), + sample_get_chain_channel(id,i) + ); + } + } + } + + //vj_el_print( sample_get_editlist( id ) ); + + veejay_msg(VEEJAY_MSG_DEBUG, + "Sample has EDL %p, Plain at %p", sample_get_editlist( id ), v->current_edit_list ); + + veejay_msg(VEEJAY_MSG_PRINT, "\n"); + +} + +void vj_event_print_plain_info(void *ptr, int x) +{ + veejay_t *v = (veejay_t*) ptr; + if( PLAIN_PLAYING(v)) vj_el_print( v->edit_list ); +} + +void vj_event_print_info(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[1]; + char *str = NULL; P_A(args,str,format,ap); + if(args[0]==0) + { + args[0] = v->uc->sample_id; + } + + veejay_msg(VEEJAY_MSG_INFO, "%d / %d Mb used in cache", + get_total_mem(), + vj_el_cache_size() ); + + vj_event_print_plain_info(v,args[0]); + + if( SAMPLE_PLAYING(v) && sample_exists(args[0]) ) + { + vj_event_print_sample_info( v, args[0] ); + } + if( STREAM_PLAYING(v) && vj_tag_exists(args[0]) ) + { + vj_event_print_tag_info(v, args[0]) ; + } +} + +void vj_event_send_track_list ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + char *s_print_buf = get_print_buf(0); + sprintf(s_print_buf, "%05d",0); + int n = vj_tag_size()-1; + if (n >= 1 ) + { + char line[300]; + char *print_buf = get_print_buf(SEND_BUF); + int i; + for(i=0; i <= n; i++) + { + if(vj_tag_exists(i) && !vj_tag_is_deleted(i)) + { + vj_tag *tag = vj_tag_get(i); + if(tag->source_type == VJ_TAG_TYPE_NET ) + { + char cmd[275]; + char space[275]; + sprintf(space, "%s %d", tag->descr, tag->id ); + sprintf(cmd, "%03d%s",strlen(space),space); + APPEND_MSG(print_buf,cmd); + } + } + } + sprintf(s_print_buf, "%05d%s",strlen(print_buf),print_buf); + free(print_buf); + } + + SEND_MSG(v,s_print_buf); + free(s_print_buf); +} + +void vj_event_send_tag_list ( void *ptr, const char format[], va_list ap ) +{ + int args[1]; + + veejay_t *v = (veejay_t*)ptr; + char *str = NULL; + P_A(args,str,format,ap); + int i,n; + char *s_print_buf = get_print_buf(0); + sprintf(s_print_buf, "%05d",0); + + //if(args[0]>0) start_from_tag = args[0]; + + n = vj_tag_size()-1; + if (n >= 1 ) + { + char line[300]; + char *print_buf = get_print_buf(SEND_BUF); + + for(i=0; i <= n; i++) + { + if(vj_tag_exists(i) &&!vj_tag_is_deleted(i)) + { + vj_tag *tag = vj_tag_get(i); + char source_name[255]; + char cmd[300]; + veejay_memset(source_name,0,200);veejay_memset(cmd,0,255); + veejay_memset(line,0,300); + //vj_tag_get_description( i, source_name ); + vj_tag_get_source_name( i, source_name ); + sprintf(line,"%05d%02d%03d%03d%03d%03d%03d%s", + i, + vj_tag_get_type(i), + tag->color_r, + tag->color_g, + tag->color_b, + tag->opacity, + strlen(source_name), + source_name + ); + sprintf(cmd, "%03d%s",strlen(line),line); + APPEND_MSG(print_buf,cmd); + } + } + sprintf(s_print_buf, "%05d%s",strlen(print_buf),print_buf); + free(print_buf); + } + + SEND_MSG(v,s_print_buf); + free(s_print_buf); +} + +static char *_vj_event_gatter_sample_info( veejay_t *v, int id ) +{ + char description[SAMPLE_MAX_DESCR_LEN]; + int end_frame = sample_get_endFrame( id ); + int start_frame = sample_get_startFrame( id ); + char timecode[20]; + MPEG_timecode_t tc; + y4m_ratio_t ratio = mpeg_conform_framerate( (double) v->current_edit_list->video_fps ); + mpeg_timecode( &tc, (end_frame - start_frame),mpeg_framerate_code(ratio),v->current_edit_list->video_fps ); + + sprintf( timecode, "%2d:%2.2d:%2.2d:%2.2d", tc.h,tc.m,tc.s,tc.f ); + sample_get_description( id, description ); + + int dlen = strlen(description); + int tlen = strlen(timecode); + char *s_print_buf = get_print_buf(512); + snprintf( s_print_buf, 512, + "%08d%03d%s%03d%s%02d%02d", + ( 3 + dlen + 3+ tlen + 2 +2), + dlen, + description, + tlen, + timecode, + 0, + id + ); + return s_print_buf; +} +static char * _vj_event_gatter_stream_info( veejay_t *v, int id ) +{ + char description[SAMPLE_MAX_DESCR_LEN]; + char source[255]; + int stream_type = vj_tag_get_type( id ); + vj_tag_get_source_name( id, source ); + vj_tag_get_description( id, description ); + + int dlen = strlen( description ); + int tlen = strlen( source ); + char *s_print_buf = get_print_buf( 512 ); + snprintf( s_print_buf,512, + "%08d%03d%s%03d%s%02d%02d", + ( 3 + dlen + 3 + tlen + 2 + 2), + dlen, + description, + tlen, + source, + stream_type, + id + ); + return s_print_buf; +} + +void vj_event_send_sample_info ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + int failed = 1; + char *str = NULL; + P_A(args,str,format,ap); + if(args[0] == 0 ) + args[0] = v->uc->sample_id; + + + char *s_print_buf = NULL; + + switch( args[1] ) + { + case 0: + if(args[0] == -1) + args[0] = sample_size() - 1; + + if(sample_exists(args[0])) + { + s_print_buf = _vj_event_gatter_sample_info(v,args[0]); + failed = 0; + } + break; + case 1: + if(args[0] == -1) + args[0] = vj_tag_size() - 1; + + if(vj_tag_exists(args[0])) + { + s_print_buf = _vj_event_gatter_stream_info(v,args[0]); + failed = 0; + } + break; + default: + break; + } + + if(failed) { + s_print_buf = get_print_buf( 8 ); + snprintf( s_print_buf,8, "%08d", 0 ); + } + SEND_MSG(v , s_print_buf ); + free(s_print_buf); +} + +void vj_event_get_scaled_image ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + int w=0,h=0; + w = args[0]; + h = args[1]; + + if( w <= 0 || h <= 0 || w >= 2000 || h >= 2000 ) + { + veejay_msg(0, "Invalid image dimension %dx%d requested",w,h ); + SEND_MSG(v, "0000000" ); + return; + } + + veejay_image_t *img = NULL; + int pixel_format = get_ffmpeg_pixfmt(v->pixel_format); + VJFrame frame; + veejay_memcpy(&frame, v->effect_frame1, sizeof(VJFrame)); + vj_perform_get_primary_frame( v, frame.data ); + if( v->settings->composite ) { + pixel_format = composite_get_top( v->composite, frame.data, + frame.data, + v->settings->composite ); + frame.width = v->video_output_width; + frame.height = v->video_output_height; + switch(pixel_format) { + case PIX_FMT_YUV444P: + case PIX_FMT_YUVJ444P: + frame.uv_width = frame.width; + frame.uv_height= frame.height; + frame.ssm = 1; + frame.shift_v = 0; + frame.shift_h = 0; + frame.len = frame.width * frame.height; + frame.uv_len = frame.len; + break; + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUV422P: + frame.uv_width = frame.width; + frame.uv_height= frame.height / 2; + frame.ssm = 0; + frame.shift_v = 1; + frame.shift_h = 0; + frame.len = frame.width * frame.height; + frame.uv_len = frame.uv_width * frame.uv_height; + break; + } + + } + //@ fast*_picture delivers always 4:2:0 data to reduce bandwidth + if( use_bw_preview_ ) + vj_fastbw_picture_save_to_mem( + &frame, + w, + h, + pixel_format ); + else + vj_fast_picture_save_to_mem( + &frame, + w, + h, + pixel_format ); + + int dstlen = (use_bw_preview_ ? ( w * h ) : (( w * h ) + ((w * h)/2)) ); + + char header[8]; + sprintf( header, "%06d%1d", dstlen, use_bw_preview_ ); + SEND_DATA(v, header, 7 ); + SEND_DATA(v, vj_perform_get_preview_buffer(), dstlen ); +} + +void vj_event_get_cali_image ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char *str = NULL; + P_A(args,str,format,ap); + + int id = args[0]; + int type = args[1]; + + if( !vj_tag_exists(id) || vj_tag_get_type(id) != VJ_TAG_TYPE_V4L || type < 0 || type > 2) + { + SEND_MSG(v, "000000000" ); + return; + } + + vj_tag *tag = vj_tag_get(id); + + int total_len = 0; + int uv_len = 0; + int len = 0; + + uint8_t *buf = vj_tag_get_cali_buffer( id , type, &total_len, &len, &uv_len ); + + if( buf == NULL ) { + SEND_MSG(v, "00000000" ); + } + else { + char header[128];//FIXME + sprintf( header, "%03d%08d%06d%06d%06d%06d",8+6+6+6+6,len, len, 0, v->current_edit_list->video_width, v->current_edit_list->video_height ); + SEND_MSG( v, header ); + + int res = vj_server_send(v->vjs[VEEJAY_PORT_CMD], v->uc->current_link, buf,len); + } +} + + + +void vj_event_toggle_bw( void *ptr, const char format[], va_list ap ) +{ + if( use_bw_preview_ ) + use_bw_preview_ = 0; + else + use_bw_preview_ = 1; +} + +void vj_event_send_working_dir(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + char str[2048]; + P_A(args,str,format,ap); + + + filelist_t *list = (filelist_t*)find_media_files(v); + char *s_print_buf = NULL; + if(!list) { + veejay_msg(VEEJAY_MSG_ERROR, "No usable files found."); + s_print_buf = get_print_buf( 8 ); + snprintf(s_print_buf,8,"%08d",0); + }else { + + int len = 1; + int i; + for( i = 0; i < list->num_files; i ++ ) { + len += ( list->files[i] == NULL ? 0 : strlen( list->files[i] ) ); + } + + int msg_len = (list->num_files*4) + len - 1; + s_print_buf = get_print_buf ( msg_len + 32 ); + sprintf(s_print_buf, "%08d", msg_len ); + + int tlen=0; + for( i = 0; i num_files; i ++ ) { + char tmp[1024]; + if(list->files[i]==NULL) + continue; + tlen = strlen(list->files[i]); +#ifdef STRICT_CHECKING + assert( tlen <= sizeof(tmp)); +#endif + snprintf(tmp,sizeof(tmp), "%04d%s",tlen,list->files[i]); + + strcat( s_print_buf,tmp); + } + SEND_MSG(v,s_print_buf); + free_media_files(v,list); + } + free( s_print_buf ); +} + +void vj_event_send_sample_list ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + int start_from_sample = 1; + char cmd[512]; + char *str = NULL; + int i,n; + P_A(args,str,format,ap); + if(args[0] > 0 ) + start_from_sample = args[0]; + char *s_print_buf = get_print_buf(0); + + sprintf(s_print_buf, "00000000"); + + n = sample_size(); + if( n > 1 ) + { + char line[400]; + char *print_buf = get_print_buf(SEND_BUF); + for(i=start_from_sample; i <= n; i++) + { + if(sample_exists(i)) + { + char description[SAMPLE_MAX_DESCR_LEN]; + int end_frame = sample_get_endFrame(i); + int start_frame = sample_get_startFrame(i); + veejay_memset(cmd,0, sizeof(cmd)); + + /* format of sample: + 00000 : id + 000000000 : start + 000000000 : end + xxx: str : description + */ + sample_get_description( i, description ); + + sprintf(cmd,"%05d%09d%09d%03d%s", + i, + start_frame, + end_frame, + strlen(description), + description + ); + FORMAT_MSG(line,cmd); + APPEND_MSG(print_buf,line); + } + + } + sprintf(s_print_buf, "%08d%s", strlen(print_buf),print_buf); + free(print_buf); + } + SEND_MSG(v, s_print_buf); + free(s_print_buf); +} + +void vj_event_send_log ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int num_lines = 0; + int str_len = 0; + char *messages = NULL; + + char *s_print_buf = get_print_buf(0); + + messages = veejay_pop_messages( &num_lines, &str_len ); + + if(str_len == 0 || num_lines == 0 ) + sprintf(s_print_buf, "%06d", 0); + else + sprintf(s_print_buf, "%06d%s", str_len, messages ); + if(messages) + free(messages); + + veejay_msg(VEEJAY_MSG_DEBUG, "\tDebug: send log %s", s_print_buf); + + SEND_MSG( v, s_print_buf ); + free(s_print_buf); +} + +void vj_event_send_sample_stack ( void *ptr, const char format[], va_list ap ) +{ + char line[32]; + int args[4]; + char *str = NULL; + int error = 1; + + char buffer[1024]; + char message[1024]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,str,format,ap); + + buffer[0] = '\0'; + message[0] = '\0'; + + int channel, source,fx_id,i, offset,sample_len; + + if( SAMPLE_PLAYING(v) ) { + if(args[0] == 0) + args[0] = v->uc->sample_id; + + for( i = 0; i < SAMPLE_MAX_EFFECTS ;i ++ ) { + fx_id = sample_get_effect_any( args[0], i ); + if( fx_id <= 0 ) + continue; + channel = sample_get_chain_channel( args[0], i ); + source = sample_get_chain_source( args[0], i ); + offset = sample_get_offset( args[0], i ); + if( source == 0 ) + sample_len= sample_video_length( channel ); + else + sample_len = 50; //@TODO, implement stream handling + snprintf( line, sizeof(line), "%02d%04d%02d%08d%08d", i, channel, source, offset, sample_len ); + strncat( buffer, line, strlen(line)); + } + } else if(STREAM_PLAYING(v)) + { + if(args[0] == 0) + args[0] = v->uc->sample_id; + + for(i = 0; i < SAMPLE_MAX_EFFECTS ; i ++ ) { + fx_id = vj_tag_get_effect_any( args[0], i ); + if( fx_id <= 0 ) + continue; + channel = vj_tag_get_chain_channel( args[0], i ); + source = vj_tag_get_chain_source( args[0], i ); + offset = vj_tag_get_offset( args[0], i ); + if( source == 0 ) + sample_len= sample_video_length( channel ); + else + sample_len = 50; //@TODO, implement stream handling + + snprintf( line, sizeof(line), "%02d%04d%02d%08d%08d",i,channel,source, offset, sample_len ); + strncat( buffer, line, strlen(line)); + } + } + + + + FORMAT_MSG( message, buffer ); + SEND_MSG( v, message ); + +} + +void vj_event_send_chain_entry ( void *ptr, const char format[], va_list ap ) +{ + char fline[255]; + char line[255]; + int args[4]; + char *str = NULL; + int error = 1; + veejay_t *v = (veejay_t*)ptr; + P_A(args,str,format,ap); + veejay_memset(fline,0,255); + sprintf(line, "%03d", 0); + + if( SAMPLE_PLAYING(v) ) + { + if(args[0] == 0) + args[0] = v->uc->sample_id; + + if(args[1]==-1) + args[1] = sample_get_selected_entry(args[0]); + + int effect_id = sample_get_effect_any(args[0], args[1]); + + if(effect_id > 0) + { + int is_video = vj_effect_get_extra_frame(effect_id); + int params[SAMPLE_MAX_PARAMETERS]; + int p; + int video_on = sample_get_chain_status(args[0],args[1]); + int audio_on = 0; + //int audio_on = sample_get_chain_audio(args[0],args[1]); + int num_params = vj_effect_get_num_params(effect_id); + for(p = 0 ; p < num_params; p++) + params[p] = sample_get_effect_arg(args[0],args[1],p); +#ifdef STRICT_CHECKING + assert( args[2] >= 0 && args[2] <= num_params ); +#endif + for(p = num_params; p < SAMPLE_MAX_PARAMETERS; p++) + params[p] = 0; + + int kf_start = 0, kf_end = 0, kf_type = 0; + int kf_status = sample_get_kf_status( args[0],args[1] ); + sample_get_kf_tokens( args[0],args[1],args[2],&kf_start,&kf_end,&kf_type ); + sprintf(line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + effect_id, + is_video, + num_params, + params[0], + params[1], + params[2], + params[3], + params[4], + params[5], + params[6], + params[7], + params[8], + video_on, + audio_on, + sample_get_chain_source(args[0],args[1]), + sample_get_chain_channel(args[0],args[1]), + kf_status, kf_start,kf_end,kf_type + ); + error = 0; + } + } + + if(STREAM_PLAYING(v)) + { + if(args[0] == 0) + args[0] = v->uc->sample_id; + + if(args[1] == -1) + args[1] = vj_tag_get_selected_entry(args[0]); + + int effect_id = vj_tag_get_effect_any(args[0], args[1]); + + if(effect_id > 0) + { + int is_video = vj_effect_get_extra_frame(effect_id); + int params[SAMPLE_MAX_PARAMETERS]; + int p; + int num_params = vj_effect_get_num_params(effect_id); + int video_on = vj_tag_get_chain_status(args[0], args[1]); + for(p = 0 ; p < num_params; p++) + { + params[p] = vj_tag_get_effect_arg(args[0],args[1],p); + } + for(p = num_params; p < SAMPLE_MAX_PARAMETERS;p++) + { + params[p] = 0; + } + int kf_start = 0, kf_end = 0, kf_type = 0; + int kf_status = vj_tag_get_kf_status(args[0],args[1]); + vj_tag_get_kf_tokens( args[0],args[1],args[2],&kf_start,&kf_end,&kf_type ); + sprintf(line, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + effect_id, + is_video, + num_params, + params[0], + params[1], + params[2], + params[3], + params[4], + params[5], + params[6], + params[7], + params[8], + video_on, + 0, + vj_tag_get_chain_source(args[0],args[1]), + vj_tag_get_chain_channel(args[0],args[1]), + kf_status,kf_start,kf_end, kf_type + ); + error = 0; + } + } + + if(!error) + { + FORMAT_MSG(fline,line); + SEND_MSG(v, fline); + } + else + SEND_MSG(v,line); +} + +void vj_event_send_chain_list ( void *ptr, const char format[], va_list ap ) +{ + int i; + char line[18]; + int args[1]; + char *str = NULL; + veejay_t *v = (veejay_t*)ptr; + P_A(args,str,format,ap); + + if(args[0] == 0) + args[0] = v->uc->sample_id; + + char *s_print_buf = get_print_buf(0); + + sprintf( s_print_buf, "%03d",0 ); + + if(SAMPLE_PLAYING(v)) + { + if(args[0] == -1) args[0] = sample_size()-1; + char *print_buf = get_print_buf(16*SAMPLE_MAX_EFFECTS); + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + int effect_id = sample_get_effect_any(args[0], i); + if(effect_id > 0) + { + int is_video = vj_effect_get_extra_frame(effect_id); + int using_effect = sample_get_chain_status(args[0], i); + int using_audio = 0; + //int using_audio = sample_get_chain_audio(args[0],i); + sprintf(line,"%02d%03d%1d%1d%1d", + i, + effect_id, + is_video, + (using_effect <= 0 ? 0 : 1 ), + (using_audio <= 0 ? 0 : 1 ) + ); + + APPEND_MSG(print_buf,line); + } + } + sprintf(s_print_buf, "%03d%s",strlen(print_buf), print_buf); + free(print_buf); + + } else if(STREAM_PLAYING(v)) + { + if(args[0] == -1) args[0] = vj_tag_size()-1; + char *print_buf = get_print_buf(16*SAMPLE_MAX_EFFECTS); + + for(i=0; i < SAMPLE_MAX_EFFECTS; i++) + { + int effect_id = vj_tag_get_effect_any(args[0], i); + if(effect_id > 0) + { + int is_video = vj_effect_get_extra_frame(effect_id); + int using_effect = vj_tag_get_chain_status(args[0],i); + sprintf(line, "%02d%03d%1d%1d%1d", + i, + effect_id, + is_video, + (using_effect <= 0 ? 0 : 1 ), + 0 + ); + APPEND_MSG(print_buf, line); + } + } + sprintf(s_print_buf, "%03d%s",strlen( print_buf ), print_buf); + free(print_buf); + } else { + sprintf(s_print_buf, "000"); + } + SEND_MSG(v, s_print_buf); + free(s_print_buf); +} + +void vj_event_send_video_information ( void *ptr, const char format[], va_list ap ) +{ + /* send video properties */ + char info_msg[150]; + veejay_t *v = (veejay_t*)ptr; + + editlist *el = v->current_edit_list; +/* + editlist *el = ( SAMPLE_PLAYING(v) ? sample_get_editlist( v->uc->sample_id ) : + v->current_edit_list ); +*/ + long n_frames = el->total_frames; + if( SAMPLE_PLAYING(v)) + n_frames = sample_max_video_length( v->uc->sample_id ); + char *s_print_buf = get_print_buf(200); + snprintf(info_msg,sizeof(info_msg)-1, "%04d %04d %01d %c %02.3f %1d %04d %06ld %02d %03ld %08ld %1d", + el->video_width, + el->video_height, + el->video_inter, + el->video_norm, + el->video_fps, + el->has_audio, + el->audio_bits, + el->audio_rate, + el->audio_chans, + el->num_video_files, + n_frames, + v->audio + ); + sprintf(s_print_buf, "%03d%s",strlen(info_msg), info_msg); + SEND_MSG(v,s_print_buf); + free(s_print_buf); +} + +void vj_event_send_editlist ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int b = 0; + editlist *el = v->current_edit_list; +/* ( SAMPLE_PLAYING(v) ? sample_get_editlist( v->uc->sample_id ) : + v->current_edit_list );*/ + + if( el->num_video_files <= 0 ) + { + SEND_MSG( v, "000000"); + return; + } + + + char *msg = (char*) vj_el_write_line_ascii( el, &b ); + + + char *s_print_buf = get_print_buf( b + 8 ); + snprintf( s_print_buf, (b+8),"%06d%s", b, msg ); + if(msg)free(msg); + SEND_MSG( v, s_print_buf ); + free(s_print_buf); +} + +void vj_event_send_devices ( void *ptr, const char format[], va_list ap ) +{ + char str[255]; + struct dirent **namelist; + int n_dev = 0; + int n; + char device_list[512]; + char useable_devices[2]; + int *args = NULL; + veejay_t *v = (veejay_t*)ptr; + P_A(args,str,format,ap); + veejay_memset(device_list,0,512); + + n = scandir(str,&namelist,0,alphasort); + if( n<= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "No device information in [%s]",str); + SEND_MSG(v,"0000"); + return; + } + + + while(n--) + { + if( strncmp(namelist[n]->d_name, "video", 4)==0) + { + FILE *fd; + char filename[300]; + sprintf(filename,"%s%s",str,namelist[n]->d_name); + fd = fopen( filename, "r"); + if(fd) + { + fclose(fd); + } + } + } + sprintf(useable_devices,"%02d", n_dev); + + APPEND_MSG( device_list, useable_devices ); + SEND_MSG(v,device_list); + +} + +void vj_event_send_frame ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + + int i = 0; + int ok = 0; + for( i = 0; i < 8; i ++ ) { + if( v->uc->current_link == v->rlinks[i] ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Some one grabbed two beers at once!"); + } + if( v->rlinks[i] == -1 ) { + v->rlinks[i] = v->uc->current_link; + ok = 1; + break; + } + } + + if( !ok ) { + veejay_msg(0, "No more video stream connections allowed, limited to 8"); + SEND_MSG(v,"00000000000000000000"); + return; + } + + if (!v->settings->is_dat ) + { + veejay_msg(0, "Wrong control port for retrieving frames!"); + SEND_MSG(v, "00000000000000000000"); //@ send empty header only (20 bytes) + return; + } + + v->settings->unicast_frame_sender = 1; +} + + +void vj_event_mcast_start ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + int args[2]; + char s[255]; + P_A( args, s , format, ap); + + if(!v->settings->use_vims_mcast) + veejay_msg(VEEJAY_MSG_ERROR, "start veejay in multicast mode (see -T commandline option)"); + else + { + v->settings->mcast_frame_sender = 1; + v->settings->mcast_mode = args[0]; + vj_server_set_mcast_mode( v->vjs[2],args[0] ); + veejay_msg(VEEJAY_MSG_INFO, "Veejay started mcast frame sender"); + } +} + + +void vj_event_mcast_stop ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + if(!v->settings->use_vims_mcast) + veejay_msg(VEEJAY_MSG_ERROR, "start veejay in multicast mode (see -V commandline option)"); + else + { + v->settings->mcast_frame_sender = 0; + veejay_msg(VEEJAY_MSG_INFO, "Veejay stopped mcast frame sender"); + } +} + +void vj_event_send_effect_list ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int i; + char *priv_msg = NULL; + int len = 0; + + for( i = 1; i < vj_effect_max_effects(); i ++ ) + len += vj_effect_get_summary_len( i ); + + priv_msg = (char*) malloc(sizeof(char) * (5 + len + 1000)); + memset(priv_msg, 0, (5+len+100)); + sprintf(priv_msg, "%05d", len ); + char line[1025]; + char fline[1025]; + for(i=1; i < vj_effect_max_effects(); i++) + { + int effect_id = vj_effect_get_real_id(i); + if(vj_effect_get_summary(i,line)) + { + sprintf(fline, "%03d%s", strlen(line), line ); + veejay_strncat( priv_msg, fline, strlen(fline) ); + } + } + SEND_MSG(v,priv_msg); + free(priv_msg); +} + + + +int vj_event_load_bundles(char *bundle_file) +{ + FILE *fd; + char *event_name, *event_msg; + char buf[65535]; + int event_id=0; + if(!bundle_file) return -1; + fd = fopen(bundle_file, "r"); + veejay_memset(buf,0,65535); + if(!fd) return -1; + while(fgets(buf,4096,fd)) + { + buf[strlen(buf)-1] = 0; + event_name = strtok(buf, "|"); + event_msg = strtok(NULL, "|"); + if(event_msg!=NULL && event_name!=NULL) { + //veejay_msg(VEEJAY_MSG_INFO, "Event: %s , Msg [%s]",event_name,event_msg); + event_id = atoi( event_name ); + if(event_id && event_msg) + { + vj_msg_bundle *m = vj_event_bundle_new( event_msg, event_id ); + if(m != NULL) + { + if( vj_event_bundle_store(m) ) + { + veejay_msg(VEEJAY_MSG_INFO, "(VIMS) Registered a bundle as event %03d",event_id); + } + } + } + } + } + fclose(fd); + return 1; +} + +void vj_event_do_bundled_msg(void *ptr, const char format[], va_list ap) +{ + veejay_t *v = (veejay_t*) ptr; + int args[1]; + char s[1024]; + vj_msg_bundle *m; + P_A( args, s , format, ap); + //veejay_msg(VEEJAY_MSG_INFO, "Parsing message bundle as event"); + m = vj_event_bundle_get(args[0]); + if(m) + { + vj_event_parse_bundle( v, m->bundle ); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Requested event %d does not exist. ",args[0]); + } +} + +#ifdef HAVE_SDL +void vj_event_attach_detach_key(void *ptr, const char format[], va_list ap) +{ + int args[4] = { 0,0,0,0 }; + char value[100]; + int mode = 0; + + + P_A( args, value, format ,ap ); + + if( args[1] <= 0 || args[1] >= SDLK_LAST) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid key identifier %d (range is 1 - %d)", args[1], SDLK_LAST); + return; + } + if( args[2] < 0 || args[2] > VIMS_MOD_SHIFT ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid key modifier (3=shift,2=ctrl,1=alt, 0=none)"); + return; + } + + char *clone = NULL; + mode = args[0]; + + switch(mode) + { + case 1: + vj_event_unregister_keyb_event( args[1],args[2] ); + break; + default: + + if( strncmp(value, "dummy",5 ) != 0 ) + clone = value; + vj_event_register_keyb_event( args[0], args[1], args[2], clone ); + break; + } +} +#endif + +void vj_event_bundled_msg_del(void *ptr, const char format[], va_list ap) +{ + + int args[1]; + char *s = NULL; + P_A(args,s,format,ap); + if ( vj_event_bundle_del( args[0] ) == 0) + { + veejay_msg(VEEJAY_MSG_INFO,"Bundle %d deleted from event system",args[0]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Bundle is %d is not known",args[0]); + } +} + + + + +void vj_event_bundled_msg_add(void *ptr, const char format[], va_list ap) +{ + + int args[2] = {0,0}; + char s[1024]; + veejay_memset(s,0, 1024); + P_A(args,s,format,ap); + + if(args[0] == 0) + { + args[0] = vj_event_suggest_bundle_id(); + veejay_msg(VEEJAY_MSG_DEBUG, "(VIMS) suggested new Event id %d", args[0]); + } + else + { + veejay_msg(VEEJAY_MSG_DEBUG, "(VIMS) requested to add/replace %d", args[0]); + } + + if(args[0] < VIMS_BUNDLE_START|| args[0] > VIMS_BUNDLE_END ) + { + // invalid bundle + veejay_msg(VEEJAY_MSG_ERROR, "Customized events range from %d-%d", VIMS_BUNDLE_START, VIMS_BUNDLE_END); + return; + } + // allocate new + veejay_strrep( s, '_', ' '); + vj_msg_bundle *m = vj_event_bundle_new(s, args[0]); + if(!m) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error adding bundle ?!"); + return; + } + + // bye existing bundle + if( vj_event_bundle_exists(args[0])) + { + veejay_msg(VEEJAY_MSG_DEBUG,"(VIMS) Bundle exists - replacing contents "); + vj_msg_bundle *mm = vj_event_bundle_get( args[0] ); + if(mm) + { + m->modifier = mm->modifier; + m->accelerator = mm->accelerator; + } + + vj_event_bundle_del( args[0] ); + } + + if( vj_event_bundle_store(m)) + { + veejay_msg(VEEJAY_MSG_INFO, "(VIMS) Registered Bundle %d in VIMS",args[0]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "(VIMS) Error in Bundle %d '%s'",args[0],s ); + } +} + +void vj_event_set_stream_color(void *ptr, const char format[], va_list ap) +{ + int args[4]; + char *s = NULL; + P_A(args,s,format,ap); + veejay_t *v = (veejay_t*) ptr; + + if(STREAM_PLAYING(v)) + { + if(args[0] == 0 ) args[0] = v->uc->sample_id; + if(args[0] == -1) args[0] = vj_tag_size()-1; + } + // allow changing of color while playing plain/sample + if(vj_tag_exists(args[0]) && + vj_tag_get_type(args[0]) == VJ_TAG_TYPE_COLOR ) + { + CLAMPVAL( args[1] ); + CLAMPVAL( args[2] ); + CLAMPVAL( args[3] ); + vj_tag_set_stream_color(args[0],args[1],args[2],args[3]); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Stream %d does not exist", + args[0]); + } +} + +#ifdef USE_GDK_PIXBUF +void vj_event_screenshot(void *ptr, const char format[], va_list ap) +{ + int args[4]; + char filename[1024]; + veejay_memset(filename,0,1024); + P_A(args, filename, format, ap ); + veejay_t *v = (veejay_t*) ptr; + + char type[5]; + veejay_memset(type,0,5); + + + veejay_get_file_ext( filename, type, sizeof(type)); + + if(args[0] == 0 ) + args[0] = v->video_output_width; + if(args[1] == 0 ) + args[1] = v->video_output_height; + + v->settings->export_image = + vj_picture_prepare_save( filename , type, args[0], args[1] ); + if(v->settings->export_image) + v->uc->hackme = 1; +} +#else +#ifdef HAVE_JPEG +void vj_event_screenshot(void *ptr, const char format[], va_list ap) +{ + int args[4]; + char filename[1024]; + veejay_memset(filename,0,1024); + P_A(args, filename, format, ap ); + veejay_t *v = (veejay_t*) ptr; + + v->uc->hackme = 1; + v->uc->filename = strdup( filename ); +} +#endif +#endif + +void vj_event_quick_bundle( void *ptr, const char format[], va_list ap) +{ + vj_event_commit_bundle( (veejay_t*) ptr,0,0); +} + + +void vj_event_vloopback_start(void *ptr, const char format[], va_list ap) +{ + int args[2]; + char *s = NULL; + char device_name[100]; + + P_A(args,s,format,ap); + + veejay_t *v = (veejay_t*)ptr; + + sprintf(device_name, "/dev/video%d", args[0] ); + + veejay_msg(VEEJAY_MSG_INFO, "Open vloopback %s", device_name ); + + v->vloopback = vj_vloopback_open( device_name, + (v->current_edit_list->video_norm == 'p' ? 1 : 0), + 1, // pipe, 0 = mmap + v->video_output_width, + v->video_output_height, + v->pixel_format ); + if(v->vloopback == NULL) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Cannot open vloopback %s", device_name ); + + return; + } + + int ret = 0; + + veejay_msg(VEEJAY_MSG_DEBUG, "Vloopback pipe"); + ret = vj_vloopback_start_pipe( v->vloopback ); + /* + veejay_msg(VEEJAY_MSG_DEBUG, "Vloopback mmap"); + ret = vj_vloopback_start_mmap( v->vloopback ); + */ + + if(ret) + { + veejay_msg(VEEJAY_MSG_DEBUG, + "Setup vloopback!"); + } + + if(!ret) + { + veejay_msg(VEEJAY_MSG_ERROR, + "closing vloopback"); + if(v->vloopback) + vj_vloopback_close( v->vloopback ); + v->vloopback = NULL; + } + + if( v->vloopback == NULL ) + veejay_msg(VEEJAY_MSG_ERROR, "Failed to setup vloopback pusher"); + +} + +void vj_event_vloopback_stop( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*) ptr; + vj_vloopback_close( v->vloopback ); +} + +/* + * Function that returns the options for a special sample (markers, looptype, speed ...) or + * for a special stream ... + * + * Needs two Parameters, first on: -1 last created sample, 0 == current playing sample, >=1 id of sample + * second parameter is the playmode of this sample to decide if its a video sample or any kind of stream + * (for this see comment on void vj_event_send_sample_info(..) + */ +void vj_event_send_sample_options ( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2]; + int id=0; + char *str = NULL; + int failed = 1; + + P_A(args,str,format,ap); + if(args[0] == 0 ) + args[0] = v->uc->sample_id; + if(args[0] == -1) + args[0] = sample_size() - 1; + + id = args[0]; + char options[100]; + char prefix[4]; + veejay_memset(prefix,0, 4 ); + veejay_memset(options, 0,100); + + + char *s_print_buf = get_print_buf(128); + + switch(args[1]) + { + case VJ_PLAYBACK_MODE_SAMPLE: + if(sample_exists(id)) + { + /* For gathering sample-infos use the sample_info_t-structure that is defined in /libsample/sampleadm.h */ + sample_info *si = sample_get(id); + if (si) + { + int start = si->first_frame; + int end = si->last_frame; + int speed = si->speed; + int loop = si->looptype; + int marker_start = si->marker_start; + int marker_end = si->marker_end; + int effects_on = si->effect_toggle; + + sprintf( options, + "%06d%06d%03d%02d%06d%06d%01d", + start, + end, + speed, + loop, + marker_start, + marker_end, + effects_on); + failed = 0; + + sprintf(prefix, "%02d", 0 ); + + } + } + break; + case VJ_PLAYBACK_MODE_TAG: + if(vj_tag_exists(id)) + { + /* For gathering further informations of the stream first decide which type of stream it is + the types are definded in libstream/vj-tag.h and uses then the structure that is definded in + libstream/vj-tag.h as well as some functions that are defined there */ + vj_tag *si = vj_tag_get(id); + int stream_type = si->source_type; + + sprintf(prefix, "%02d", stream_type ); + + if (stream_type == VJ_TAG_TYPE_COLOR) + { + int col[3] = {0,0,0}; + col[0] = si->color_r; + col[1] = si->color_g; + col[2] = si->color_b; + + sprintf( options, + "%03d%03d%03d", + col[0], + col[1], + col[2] + ); + failed = 0; + } + /* this part of returning v4l-properties is here implemented again ('cause there is + * actually a VIMS-command to get these values) to get all necessary stream-infos at + * once so only ONE VIMS-command is needed */ + else if (stream_type == VJ_TAG_TYPE_V4L) + { + int brightness=0; + int hue = 0; + int contrast = 0; + int color = 0; + int white = 0; + int sat = 0; + int effects_on = 0; + + vj_tag_get_v4l_properties(id,&brightness,&hue,&contrast, &color, &white ); + effects_on = si->effect_toggle; + + sprintf( options, + "%05d%05d%05d%05d%05d%05d%01d", + brightness, + hue, + sat, + contrast, + color, + white, + effects_on); + failed = 0; + } + else + { + int effects_on = si->effect_toggle; + sprintf( options, + "%01d", + effects_on); + failed = 0; + } + } + break; + default: + break; + } + + if(failed) + sprintf( s_print_buf, "%05d", 0 ); + else + sprintf( s_print_buf, "%05d%s%s",strlen(prefix) + strlen(options), prefix,options ); + + SEND_MSG(v , s_print_buf ); + free(s_print_buf); +} +#ifdef HAVE_FREETYPE +void vj_event_get_srt_list( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + char *str = NULL; + int len = 0; + + if(!v->font) + { + SEND_MSG(v, "000000" ); + return; + } + + char **list = vj_font_get_sequences( v->font ); + int i; + + if(!list) + { + SEND_MSG(v, "000000" ); + return; + } + + for(i = 0; list[i] != NULL ; i ++ ) + { + int k = strlen(list[i]); + if(k>0) + len += (k+1); + } + if(len <= 0) + { + SEND_MSG(v, "000000" ); + return; + } + + str = vj_calloc( len + 20 ); + char *p = str; + sprintf(p, "%06d", len ); + p += 6; + for(i = 0; list[i] != NULL ; i ++ ) + { + sprintf(p, "%s ", list[i]); + p += strlen(list[i]) + 1; + free(list[i]); + } + free(list); + + SEND_MSG(v , str ); + free(str); +} + +void vj_event_get_font_list( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + char *str = NULL; + int len = 0; + + if(!v->font) + { + SEND_MSG(v, "000000" ); + return; + } + + char **list = vj_font_get_all_fonts( v->font ); + int i; + + if(!list) + { + SEND_MSG(v, "000000" ); + return; + } + + for(i = 0; list[i] != NULL ; i ++ ) + { + int k = strlen(list[i]); + if(k>0) + len += (k+3); + } + if(len <= 0) + { + SEND_MSG(v, "000000" ); + return; + } + + str = vj_calloc( len + 20 ); + char *p = str; + sprintf(p, "%06d", len ); + p += 6; + for(i = 0; list[i] != NULL ; i ++ ) + { + int k = strlen(list[i]); + sprintf(p, "%03d%s", k,list[i]); + p += (k + 3); + free(list[i]); + } + free(list); + + SEND_MSG(v , str ); + free(str); + +} +void vj_event_get_srt_info( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2] = {0,0}; + char *str = NULL; + P_A(args,str,format,ap); + + if(!v->font) + { + SEND_MSG(v, "000000"); + return; + } + + char *sequence = vj_font_get_sequence( v->font,args[0] ); + + if(!sequence) + { + SEND_MSG(v, "000000"); + return; + + } + + int len = strlen( sequence ); + str = vj_calloc( len+20 ); + sprintf(str,"%06d%s",len,sequence); + free(sequence); + + SEND_MSG(v , str ); +} + +void vj_event_save_srt( void *ptr, const char format[], va_list ap ) +{ + char file_name[512]; + int args[1]; + veejay_t *v = (veejay_t*)ptr; + + P_A(args,file_name,format,ap); + + if(!v->font) + { + veejay_msg(0, "No font renderer active"); + return; + } + + if( vj_font_save_srt( v->font, file_name ) ) + veejay_msg(VEEJAY_MSG_INFO, "Saved SRT file '%s'", file_name ); + else + veejay_msg(VEEJAY_MSG_ERROR, "Unable to save SRT file '%s'", file_name ); +} +void vj_event_load_srt( void *ptr, const char format[], va_list ap ) +{ + char file_name[512]; + int args[1]; + veejay_t *v = (veejay_t*)ptr; + + P_A(args,file_name,format,ap); + + if(!v->font) + { + veejay_msg(0, "No font renderer active"); + return; + } + + if( vj_font_load_srt( v->font, file_name ) ) + veejay_msg(VEEJAY_MSG_INFO, "Loaded SRT file '%s'", file_name ); + else + veejay_msg(VEEJAY_MSG_ERROR, "Unable to open SRT file '%s'", file_name ); +} + +void vj_event_select_subtitle( void *ptr, const char format[], va_list ap ) +{ + int args[6]; + veejay_t *v = (veejay_t*)ptr; + + if(!v->font) + { + veejay_msg(VEEJAY_MSG_ERROR, "No font renderer active"); + return; + } + + P_A(args,NULL,format,ap); + + vj_font_set_current( v->font, args[0] ); +} + + +void vj_event_get_keyframes( void *ptr, const char format[], va_list ap ) +{ + int args[3]; + veejay_t *v = (veejay_t*)ptr; + + P_A(args,NULL,format,ap); + + if(SAMPLE_PLAYING(v)) + { + int data_len = 0; + unsigned char *data = sample_chain_get_kfs( v->uc->sample_id, args[0],args[1], &data_len ); + if( data_len > 0 && data ) + { + char header[32]; + sprintf(header, "%08d",data_len ); + SEND_DATA( v, header,8); + SEND_DATA( v, data, data_len ); + free(data); + return; + } + } else if (STREAM_PLAYING(v)) + { + int data_len = 0; + unsigned char *data = vj_tag_chain_get_kfs( v->uc->sample_id, args[0],args[1], &data_len ); + if( data_len > 0 && data ) + { + char header[32]; + sprintf(header, "%08d",data_len ); + SEND_DATA( v, header,8); + SEND_DATA( v, data, data_len ); + free(data); + return; + } + + } + SEND_MSG( v, "00000000" ); +} + +void vj_event_set_kf_status( void *ptr, const char format[], va_list ap ) +{ + int args[3]; + veejay_t *v = (veejay_t*)ptr; + + P_A(args,NULL,format,ap); + + if(SAMPLE_PLAYING(v)) + { + sample_chain_set_kf_status( v->uc->sample_id, args[0],args[1] ); + veejay_msg(VEEJAY_MSG_INFO, "Sample %d is using animated parameter values", v->uc->sample_id); + } else if (STREAM_PLAYING(v)) + { + vj_tag_chain_set_kf_status(v->uc->sample_id,args[0],args[1] ); + veejay_msg(VEEJAY_MSG_INFO, "Stream %d is using animated parameter values", v->uc->sample_id); + + } +} +void vj_event_reset_kf( void *ptr, const char format[], va_list ap ) +{ + int args[3]; + veejay_t *v = (veejay_t*)ptr; + + P_A(args,NULL,format,ap); + + if(SAMPLE_PLAYING(v)) + { + sample_chain_reset_kf( v->uc->sample_id, args[0] ); + } else if (STREAM_PLAYING(v)) + { + vj_tag_chain_reset_kf( v->uc->sample_id, args[0] ); + } + +} + +static void *select_dict( veejay_t *v , int n ) +{ + void *dict = NULL; + if( SAMPLE_PLAYING(v) ) + return sample_get_dict( n ); + else if(STREAM_PLAYING(v)) + return vj_tag_get_dict( n ); + return NULL; +} + +void vj_event_add_subtitle( void *ptr, const char format[], va_list ap ) +{ + unsigned char text[2048]; + int args[6]; + int k; + veejay_t *v = (veejay_t*)ptr; + + if(!v->font) + { + veejay_msg(VEEJAY_MSG_ERROR, "No font renderer active"); + return; + } + + veejay_memset(text,0,2048); + P_A(args,text,format,ap); + + void *dict = select_dict( v, v->uc->sample_id ); + if(!dict) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid playback mode for subtitles"); + return; + } + + int len = strlen( text ); + if ( len <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "No text given"); + return; + } + for( k = 0; k < len ; k ++ ) { + if( !isprint( text[k] ) ) + text[k] == 0x20; + } + + + + if( args[3] < 0 || args[4] < 0 || + args[3] >= v->current_edit_list->video_width || + args[4] >= v->current_edit_list->video_height ) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Invalid XY position"); + return; + } + + vj_font_set_dict( v->font, dict ); + + int id = vj_font_new_text( v->font, text, (long) args[1], (long)args[2], args[0] ); + + vj_font_set_position( v->font, args[3] ,args[4] ); + + char newslot[50]; + sprintf(newslot, "%05d%05d",5, id ); + SEND_MSG(v,newslot); +} +void vj_event_upd_subtitle( void *ptr, const char format[], va_list ap ) +{ + int args[5]; + char text[2048]; + + veejay_t *v = (veejay_t*)ptr; + P_A(args,text,format,ap); + + if(!v->font ) + { + veejay_msg(0, "No font renderer active"); + return; + } + + void *dict = select_dict( v, v->uc->sample_id ); + if(!dict) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid playback mode for subtitles"); + return; + } + + vj_font_set_dict( v->font, dict ); + vj_font_update_text( v->font, (long) args[1], (long) args[2], args[0], text ); +} + +void vj_event_del_subtitle( void *ptr, const char format[], va_list ap ) +{ + int args[5]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,NULL,format,ap); + + if(!v->font) + { + veejay_msg(0, "No font renderer active"); + return; + } + + + void *dict = select_dict( v, v->uc->sample_id ); + if(!dict) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid playback mode for subtitles"); + return; + } + + vj_font_set_dict( v->font, dict ); + + vj_font_del_text( v->font, args[0] ); + +} + +void vj_event_font_set_position( void *ptr, const char format[], va_list ap ) +{ + int args[5]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,NULL,format,ap); + + if(!v->font) + { + veejay_msg(0, "No font renderer active"); + return; + } + + void *dict = select_dict( v, v->uc->sample_id ); + if(!dict) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid playback mode for subtitles"); + return; + } + vj_font_set_dict( v->font, dict ); + + vj_font_set_position( v->font, args[0] ,args[1] ); +} +void vj_event_font_set_color( void *ptr, const char format[], va_list ap ) +{ + int args[6]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,NULL,format,ap); + + if(!v->font) + { + veejay_msg(0, "No font renderer active"); + return; + } + + void *dict = select_dict( v, v->uc->sample_id ); + if(!dict) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid playback mode for subtitles"); + return; + } + vj_font_set_dict( v->font, dict ); + + + switch( args[4] ) + { + case 0: + vj_font_set_outline_and_border( + v->font, args[0],args[1] ); + //outline, //use_bg + break; + case 1: + vj_font_set_fgcolor( v->font, + args[0],args[1],args[2],args[3] ); + break; + case 2: + vj_font_set_bgcolor( v->font, + args[0],args[1],args[2],args[3] ); + break; + case 3: + vj_font_set_lncolor( v->font, + args[0],args[1],args[2],args[3] ); + break; + default: + veejay_msg(0, "Invalid mode. Use 0=outline/border 1=FG,2=BG,3=LN" ); + break; + } +} +void vj_event_font_set_size_and_font( void *ptr, const char format[], va_list ap ) +{ + int args[5]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,NULL,format,ap); + + if(!v->font) + { + veejay_msg(0, "No font renderer active"); + return; + } + + void *dict = select_dict( v, v->uc->sample_id ); + if(!dict) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid playback mode for subtitles"); + return; + } + vj_font_set_dict( v->font, dict ); + + vj_font_set_size_and_font(v->font, args[0],args[1]); +} +#endif + +void vj_event_sequencer_add_sample( void *ptr, const char format[], va_list ap ) +{ + int args[5]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,NULL,format,ap); + + int seq = args[0]; + int id = args[1]; + + if( seq < 0 || seq >= MAX_SEQUENCES ) + { + veejay_msg( VEEJAY_MSG_ERROR,"Slot not within bounds"); + return; + } + + if( sample_exists(id )) + { + v->seq->samples[ seq ] = id; + if( v->seq->size < MAX_SEQUENCES ) + { + v->seq->size ++; + } + veejay_msg(VEEJAY_MSG_INFO, "Added sample %d to slot %d/%d", + id, seq,MAX_SEQUENCES ); + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Sample %d does not exist. It cannot be added to the sequencer",id); + } + +} + +void vj_event_sequencer_del_sample( void *ptr, const char format[], va_list ap ) +{ + int args[5]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,NULL,format,ap); + + int seq_it = args[0]; + + if( seq_it < 0 || seq_it >= MAX_SEQUENCES ) + { + veejay_msg( VEEJAY_MSG_ERROR, "Sequence slot %d is not used, nothing deleted",seq_it ); + return; + } + + if( v->seq->samples[ seq_it ] ) + { + veejay_msg(VEEJAY_MSG_INFO, "Deleted sequence %d (Sample %d)", seq_it, + v->seq->samples[ seq_it ] ); + v->seq->samples[ seq_it ] = 0; + } + else + { + veejay_msg(VEEJAY_MSG_ERROR, "Sequence slot %d already empty", seq_it ); + } + +} + +void vj_event_get_sample_sequences( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int i; + + if( v->seq->size <= 0 ) + { + SEND_MSG(v,"000000"); + return; + } + + char *s_print_buf = get_print_buf( 32 + (MAX_SEQUENCES*4)); + + sprintf(s_print_buf, "%06d%04d%04d%04d", + ( 12 + (4*MAX_SEQUENCES)), + v->seq->current,MAX_SEQUENCES, v->seq->active ); + + for( i =0; i < MAX_SEQUENCES ;i ++ ) + { + char tmp[32]; + sprintf(tmp, "%04d", v->seq->samples[i]); + veejay_strncat(s_print_buf, tmp, 4 ); + } + + SEND_MSG(v, s_print_buf ); + free(s_print_buf); +} + +void vj_event_sample_sequencer_active( void *ptr, const char format[], va_list ap ) +{ + int args[5]; + veejay_t *v = (veejay_t*)ptr; + P_A(args,NULL,format,ap); + + if( v->seq->size == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Sequencer list is empty. Please add samples first"); + return; + } + + if( args[0] == 0 ) + { + v->seq->active = 0; + v->seq->current = 0; + veejay_msg(VEEJAY_MSG_INFO, "Sample sequencer disabled"); + } + else + { + v->seq->active = 1; + veejay_msg(VEEJAY_MSG_INFO, "Sample sequencer enabled"); + } +} + +void vj_event_set_macro_status( void *ptr, const char format[], va_list ap ) +{ + veejay_t *v = (veejay_t*)ptr; + int args[2] = {0,0}; + int k,i; + char *str = NULL; + P_A(args,str,format,ap); + + if( args[1] == 0 ) + { + reset_macro_(); + macro_status_ = 0; + macro_current_age_ = 0; + macro_expected_age_ = 0; + args[0] = 0; + macro_line_[0] = -1; + macro_line_[1] = 0; + macro_line_[2] = 0; + veejay_msg(VEEJAY_MSG_INFO, "Cleared all recorded keystrokes"); + } + if( args[0] == 0 ) + { + if( macro_port_ ) + { + macro_status_ = 0; //@ stop + veejay_msg(VEEJAY_MSG_INFO, "Stopped macro recorder"); + } + } else if (args[0] == 1 ) + { + reset_macro_(); + macro_port_ = vpn(VEVO_ANONYMOUS_PORT); + macro_bank_[ current_macro_ ] = macro_port_; + veejay_msg(VEEJAY_MSG_INFO , "Recording keystrokes!"); + macro_status_ = 1; + macro_line_[0] = v->settings->current_frame_num; + macro_line_[1] = v->uc->playback_mode; + macro_line_[2] = v->uc->sample_id; + macro_current_age_ =0; + } + else if (args[0] == 2) + { + if( macro_status_ == 0 && macro_port_ ) + { + macro_status_ = 2; + veejay_msg(VEEJAY_MSG_INFO, "Resume playing keystrokes"); + } else if( macro_line_[0] >= 0 && macro_port_ != NULL) + { + /* if( macro_status_ == 1 ) + { //@ store current speed and direction + char last[100]; + snprintf(last,100, "%03d:%d;", + VIMS_VIDEO_SET_SPEED, v->settings->current_playback_speed ); + store_macro_( v, last, v->settings->current_frame_num ); + }*/ + macro_status_ = 2; + veejay_msg(VEEJAY_MSG_INFO, "Replay all keystrokes!"); + veejay_change_playback_mode( v, macro_line_[1],macro_line_[2] ); + veejay_set_frame( v, macro_line_[0] ); + macro_expected_age_ = 0; + replay_macro_(); + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "No keystrokes to playback!"); + } + } +} + +void vj_event_stop() +{ + // destroy bundlehash, destroy keyboard_events +#ifdef HAVE_SDL + del_all_keyb_events(); +#endif + + vj_picture_free(); + + vj_event_vevo_free(); + + int i; + for( i = 0; i < 12; i ++ ) + { + macro_port_ = macro_bank_[i]; + if(macro_port_) + reset_macro_(); + } +} + diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-event.h b/branches/V-1.5.3/veejay-server/veejay/vj-event.h new file mode 100644 index 00000000..5e0c05fb --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-event.h @@ -0,0 +1,293 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ + +#ifndef VJ_EVENT_H +#define VJ_EVENT_H +#include +#ifdef HAVE_XML2 +#include +#include +#endif + +void vj_event_fmt_arg ( int *args, char *str, const char format[], va_list ap); +void vj_event_init (); +void vj_event_print_range ( int n1, int n2); +int veejay_finish_action_file(void *ptr, char *filename ); +int veejay_load_action_file( void *ptr, char *filename ); +int vj_event_macro_status(void); +void vj_event_select_macro( void *ptr, + const char format[], va_list ap); +void vj_event_stop(); +int vj_event_parse_msg( void *v, char *msg, int msg_len ); +void vj_event_push_coords(void *ptr); + void vj_event_viewport_frontback(void *ptr, const char format[], va_list ap); + +#ifdef HAVE_SDL +#ifdef HAVE_XML2 +void vj_event_xml_new_keyb_event ( void *v, xmlDocPtr doc, xmlNodePtr cur ); +#endif +#endif +int vj_event_get_video_format(void); +int vj_event_get_num_args(int net_id); +void vj_event_update_remote(void *ptr); +void vj_event_dump(void); +void vj_event_set_stream_color ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_arg_inc ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_arg_set ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_disable ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_enable ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_audio_toggle ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_audio_vol_inc ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_channel ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_channel_inc ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_del ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_inc ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_channel_dec ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_preset ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_select ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_set_arg_val ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_set ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_src_toggle ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_source ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_srccha ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_video_toggle ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_disable_video ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_enable_video ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_entry_set_defaults ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_fade_follow ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_fade_in ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_fade_out ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_toggle ( void *ptr, const char format[], va_list ap ); +void vj_event_chain_clear ( void *ptr, const char format[], va_list ap ); +void vj_event_dec_frame ( void *ptr, const char format[], va_list ap ); +void vj_event_effect_add ( void *ptr, const char format[], va_list ap ); +void vj_event_effect_dec ( void *ptr, const char format[], va_list ap ); +void vj_event_effect_inc ( void *ptr, const char format[], va_list ap ); +void vj_event_el_copy ( void *ptr, const char format[], va_list ap ); +void vj_event_el_crop ( void *ptr, const char format[], va_list ap ); +void vj_event_el_cut ( void *ptr, const char format[], va_list ap ); +void vj_event_el_del ( void *ptr, const char format[], va_list ap ); +void vj_event_el_paste_at ( void *ptr, const char format[], va_list ap ); +void vj_event_el_load_editlist ( void *ptr, const char format[], va_list ap ); +void vj_event_el_save_editlist ( void *ptr, const char format[], va_list ap ); +void vj_event_el_add_video_his ( void *ptr, const char format[], va_list ap ); +void vj_event_el_add_video_sample ( void *ptr, const char format[], va_list ap ); +void vj_event_el_add_video ( void *ptr, const char format[], va_list ap ); +void vj_event_entry_down ( void *ptr, const char format[], va_list ap ); +void vj_event_entry_up ( void *ptr, const char format[], va_list ap ); +void vj_event_goto_end ( void *ptr, const char format[], va_list ap ); +void vj_event_goto_start ( void *ptr, const char format[], va_list ap ); +void vj_event_inc_frame ( void *ptr, const char format[], va_list ap ); +void vj_event_misc_start_rec ( void *ptr, const char format[], va_list ap ); +void vj_event_misc_start_rec_auto ( void *ptr, const char format[], va_list ap ); +void vj_event_misc_stop_rec ( void *ptr, const char format[], va_list ap ); +void vj_event_next_second ( void *ptr, const char format[], va_list ap ); +void vj_event_none ( void *ptr, const char format[], va_list ap ); +void vj_event_output_y4m_start ( void *ptr, const char format[], va_list ap ); +void vj_event_output_y4m_stop ( void *ptr, const char format[], va_list ap ); +void vj_event_output_raw_start ( void *ptr, const char format[], va_list ap ); +void vj_event_output_raw_stop ( void *ptr, const char format[], va_list ap ); +void vj_event_play_forward ( void *ptr, const char format[], va_list ap ); +void vj_event_play_reverse ( void *ptr, const char format[], va_list ap ); +void vj_event_play_speed ( void *ptr, const char format[], va_list ap ); +void vj_event_play_speed_kb ( void *ptr, const char format[], va_list ap ); +void vj_event_play_slow ( void *ptr, const char format[], va_list ap ); +void vj_event_play_stop ( void *ptr, const char format[], va_list ap ); +void vj_event_prev_second ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_clear_all ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_copy ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_del ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_end ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_load_list ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_rec_start ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_rec_stop ( void *ptr, const char format[], va_list ap ); +#ifdef HAVE_XML2 +void vj_event_sample_save_list ( void *ptr, const char format[], va_list ap ); +#endif +void vj_event_sample_select ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_descr ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_end ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_freeze_play ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_loop_type ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_speed ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_nl ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_no ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_num_loops ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_pp ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_start ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_start ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_marker_start ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_marker_end ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_marker_clear ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_set_marker ( void *ptr, const char format[], va_list ap ); +void vj_event_set_frame ( void *ptr, const char format[], va_list ap ); +void vj_event_set_play_mode ( void *ptr, const char format[], va_list ap ); +void vj_event_set_play_mode_go ( void *ptr, const char format[], va_list ap ); +void vj_event_switch_sample_tag ( void *ptr, const char format[], va_list ap ); +#ifdef HAVE_SDL +void vj_event_set_screen_size ( void *ptr, const char format[], va_list ap ); +#endif +void vj_event_sample_set_dup ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_del ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_new_raw ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_new_avformat ( void *ptr, const char format[], va_list ap ); +#ifdef USE_GDK_PIXBUF +void vj_event_tag_new_picture ( void *ptr, const char format[], va_list ap ); +#endif +void vj_event_tag_new_v4l ( void *ptr, const char format[], va_list ap ); +#ifdef SUPPORT_READ_DV2 +void vj_event_tag_new_dv1394 ( void *ptr, const char format[], va_list ap ); +#endif +void vj_event_tag_new_color ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_new_y4m ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_new_net ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_new_mcast ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_rec_offline_start ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_rec_offline_stop ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_rec_start ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_rec_stop ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_select ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_toggle ( void *ptr, const char format[], va_list ap ); +void vj_event_select_id ( void *ptr, const char format[], va_list ap ); +void vj_event_select_bank ( void *ptr, const char format[], va_list ap ); +void vj_event_enable_audio ( void *ptr, const char format[], va_list ap ); +void vj_event_disable_audio ( void *ptr, const char format[], va_list ap ); +void vj_event_print_info ( void *ptr, const char format[], va_list ap ); +void vj_event_send_keylist( void *ptr, const char format[], va_list ap ); +void vj_event_send_tag_list ( void *ptr, const char format[], va_list ap ); +void vj_event_send_working_dir(void *ptr, const char format[], va_list ap); +void vj_event_send_sample_list ( void *ptr, const char format[], va_list ap ); +void vj_event_send_log ( void *ptr, const char format[], va_list ap ); +void vj_event_send_chain_list ( void *ptr, const char format[], va_list ap ); +void vj_event_send_chain_entry ( void *ptr, const char format[], va_list ap ); +void vj_event_send_sample_history_list ( void *ptr, const char format[], va_list ap ); +void vj_event_send_video_information ( void *ptr, const char format[], va_list ap ); +void vj_event_send_editlist ( void *ptr, const char format[], va_list ap ); +void vj_event_send_devices ( void *ptr, const char format[], va_list ap ); +void vj_event_send_frame ( void *ptr, const char fomrat[], va_list ap ); +void vj_event_send_effect_list ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_new ( void *ptr, const char format[], va_list ap ); +void vj_event_do_bundled_msg ( void *ptr, const char format[], va_list ap ); +void vj_event_bundled_msg_del ( void *ptr, const char format[], va_list ap ); +void vj_event_bundled_msg_add ( void *ptr, const char format[], va_list ap ); +void vj_event_read_file ( void *ptr, const char format[], va_list ap ); +#ifdef HAVE_SDL +void vj_event_attach_detach_key ( void *ptr, const char format[], va_list ap ); +#endif +void vj_event_write_actionfile ( void *ptr, const char format[], va_list ap ); +void vj_event_screenshot ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_chain_enable ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_chain_disable ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_chain_enable ( void *ptr, const char format[], va_list ap ); +void vj_event_v4l_set_brightness ( void *ptr, const char format[], va_list ap ); +void vj_event_v4l_set_contrast ( void *ptr, const char format[], va_list ap ); +void vj_event_v4l_set_color ( void *ptr, const char format[], va_list ap ); +void vj_event_v4l_set_hue ( void *ptr, const char format[], va_list ap ); +void vj_event_v4l_set_white ( void *ptr, const char format[], va_list ap ); +void vj_event_v4l_set_saturation ( void *ptr, const char format[], va_list ap ); +void vj_event_v4l_get_info ( void *ptr, const char format[], va_list ap ); +void vj_event_manual_chain_fade(void *ptr, const char format[], va_list ap); +void vj_event_tag_chain_disable ( void *ptr, const char format[], va_list ap ); +void vj_event_all_samples_chain_toggle ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_rel_start ( void *ptr, const char format[], va_list ap ); +void vj_event_effect_set_bg ( void *ptr, const char format[], va_list ap ); +void vj_event_quit ( void *ptr, const char format[], va_list ap ); +void vj_event_suspend ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_set_format ( void *ptr, const char format[], va_list ap ); +void vj_event_set_volume ( void *ptr, const char format[], va_list ap ); +void vj_event_tag_new_shm ( void *ptr, const char format[], va_list ap ); +void vj_event_debug_level ( void *ptr, const char format[], va_list ap ); +void vj_event_bezerk ( void *ptr, const char format[], va_list ap ); +void vj_event_plugin_command ( void *ptr, const char format[], va_list ap ); +void vj_event_load_plugin ( void *ptr, const char format[], va_list ap ); +void vj_event_unload_plugin ( void *ptr, const char format[], va_list ap ); +void vj_event_fullscreen ( void *ptr, const char format[], va_list ap ); +void vj_event_sample_mode ( void *ptr, const char format[], va_list ap ); +void vj_event_set_rgb_parameter_type ( void *ptr,const char format[], va_list ap ); +void vj_event_tag_set_descr ( void *ptr, const char format[], va_list ap ); +void vj_event_send_vimslist ( void *ptr, const char format[], va_list ap ); +void vj_event_send_devicelist ( void *ptr, const char format[], va_list ap ); +void vj_event_send_bundles (void *ptr, const char format[], va_list ap); + +void vj_event_mcast_start( void *ptr, const char format[], va_list ap); + +void vj_event_mcast_stop( void *ptr, const char format[], va_list ap); +void vj_event_vloopback_start ( void *ptr, const char format[], va_list ap ); +void vj_event_vloopback_stop ( void *ptr, const char format[], va_list ap ); + +void vj_event_play_norestart( void *ptr, const char format[], va_list ap ); +void vj_event_quick_bundle (void *ptr, const char format[], va_list ap); + +void vj_event_sample_rand_start( void *ptr, const char format[], va_list ap); +void vj_event_sample_rand_stop( void *ptr, const char format[], va_list ap); +void vj_event_send_sample_info ( void *ptr, const char format[], va_list ap ); +void vj_event_get_scaled_image( void *ptr, const char format[], va_list ap); +void vj_event_send_sample_options( void *ptr, const char format[], va_list ap); +void vj_event_stream_set_length( void *ptr, const char format[], va_list ap); +void vj_event_linkclose(void *ptr, const char format[], va_list ap); +void vj_event_send_track_list( void *ptr, const char format[], va_list ap); + +void vj_event_toggle_bw( void *ptr, const char format[], va_list ap ); +void vj_event_no_caching(void *ptr, const char format[], va_list ap); +void vj_event_render_depth( void *ptr, const char format[] , va_list ap ); +void vj_event_send_sample_stack( void *ptr, const char format[], va_list ap ); + +#ifdef HAVE_FREETYPE +void vj_event_get_srt_list( void *ptr, const char format[], va_list ap ); +void vj_event_get_font_list( void *ptr, const char format[], va_list ap ); +void vj_event_get_srt_info( void *ptr, const char format[], va_list ap ); +void vj_event_save_srt( void *ptr, const char format[], va_list ap ); +void vj_event_load_srt( void *ptr, const char format[], va_list ap ); +void vj_event_add_subtitle( void *ptr, const char format[], va_list ap ); +void vj_event_upd_subtitle( void *ptr, const char format[], va_list ap ); +void vj_event_del_subtitle( void *ptr, const char format[], va_list ap ); +void vj_event_font_set_position(void *ptr, const char format[], va_list ap ); +void vj_event_font_set_color(void *ptr, const char format[], va_list ap ); +void vj_event_font_set_size_and_font(void *ptr,const char format[], va_list ap ); +void vj_event_select_subtitle( void *ptr, const char format[], va_list ap ); +void vj_event_toggle_osd( void *ptr, const char format[], va_list ap ); +void vj_event_toggle_copyright( void *ptr, const char format[], va_list ap ); +void vj_event_toggle_osd_extra(void *ptr, const char format[], va_list ap); +void vj_event_set_macro_status( void *ptr, const char format[], va_list ap ); +#endif +void vj_event_set_framerate( void *ptr, const char format[], va_list ap ); +void vj_event_sync_correction( void *ptr,const char format[], va_list ap ); +void vj_event_get_keyframes( void *ptr, const char format[], va_list ap ); +void vj_event_set_kf_status( void *ptr, const char format[], va_list ap ); +void vj_event_reset_kf( void *ptr, const char format[], va_list ap); +void vj_event_sample_sequencer_active( void *ptr, const char format[], va_list ap ); +void vj_event_get_sample_sequences( void *ptr, const char format[], va_list ap ); +void vj_event_sequencer_del_sample( void *ptr, const char format[], va_list ap ); +void vj_event_sequencer_add_sample( void *ptr, const char format[], va_list ap ); +void vj_event_projection_inc( void *ptr, const char format[], va_list ap); +void vj_event_projection_dec( void *ptr, const char format[], va_list ap); + +void vj_event_viewport_composition( void *ptr, const char format[], va_list ap ); + +void vj_event_vp_set_points( void *ptr, const char format[], va_list ap ); +void vj_event_vp_stack(void *ptr, const char format[], va_list ap ); +void vj_event_vp_get_points( void *ptr, const char format[], va_list ap ); +void vj_event_vp_proj_toggle(void *ptr, const char format[],va_list ap ); + +void vj_event_v4l_blackframe( void *ptr, const char format[], va_list ap ); + +void vj_event_cali_write_file( void *ptr, const char format[], va_list ap ); +void vj_event_stream_new_cali( void *ptr, const char format[], va_list ap ); +void vj_event_get_cali_image ( void *ptr, const char format[], va_list ap ); +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-eventman.c b/branches/V-1.5.3/veejay-server/veejay/vj-eventman.c new file mode 100644 index 00000000..79cb03b4 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-eventman.c @@ -0,0 +1,2758 @@ +/* veejay - Linux VeeJay + * (C) 2002-2005 Niels Elburg + * + * + * 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 +#ifdef STRICT_CHECKING +#include +#endif + +#define MAX_INDEX 1024 + +#define VIMS_REQUIRE_ALL_PARAMS (1<<0) /* all params needed */ +#define VIMS_DONT_PARSE_PARAMS (1<<1) /* dont parse arguments */ +#define VIMS_LONG_PARAMS (1<<3) /* long string arguments (bundle, plugin) */ +#define VIMS_ALLOW_ANY (1<<4) /* use defaults when optional arguments are not given */ +#define livido_port_t vevo_port_t + +#define SAMPLE_ID_HELP "Sample ID (0=current playing, -1=last created, > 0 = Sample ID)" +#define STREAM_ID_HELP "Stream ID (-1=last created, > 0 = Stream ID)" +#define SAMPLE_STREAM_ID_HELP "Sample or Stream ID (0=current playing, -1=last created, > 0 = ID)" +static vevo_port_t **index_map_ = NULL; +/* define the function pointer to any event */ +typedef void (*vevo_event)(void *ptr, const char format[], va_list ap); + +static void dump_event_stderr(vevo_port_t *event) +{ + char *fmt = NULL; + char *name = NULL; + int n_arg = 0; + int vims_id = 0; + char *param = NULL; + int i; + char key[10]; + + size_t len = vevo_property_element_size(event, "format", 0 ); + if(len > 0 ) + { + fmt = malloc(sizeof(char) * len); + vevo_property_get( event, "format", 0, &fmt ); + } + name = malloc(sizeof(char) * vevo_property_element_size( event, "description", 0 )); + vevo_property_get( event, "description", 0, &name ); + + vevo_property_get( event, "arguments", 0, &n_arg ); + vevo_property_get( event, "vims_id", 0, &vims_id ); + + veejay_msg(VEEJAY_MSG_INFO, "VIMS selector %03d\t'%s'", vims_id, name ); + if(fmt) + veejay_msg(VEEJAY_MSG_INFO, "\tFORMAT: '%s', where:", fmt ); + + for( i = 0; i < n_arg; i ++ ) + { + sprintf(key, "help_%d", i ); + size_t len2 = vevo_property_element_size( event, key, 0 ); + if(len2 > 0 ) + { + param = malloc(sizeof(char) * len2 ); + vevo_property_get( event, key, 0, ¶m ); + veejay_msg(VEEJAY_MSG_INFO,"\t\tArgument %d is %s", i, param ); + free(param); + } + } + + if(fmt) free(fmt); + free(name); + +} + +int vj_event_vevo_list_size(void) +{ + int i; + int len =0; + for ( i = 0; i < MAX_INDEX ;i ++ ) + { + if( index_map_[i] != NULL ) + { + char *name = vj_event_vevo_get_event_name( i ); + char *format= vj_event_vevo_get_event_format( i ); + len += (name == NULL ? 0: strlen( name )); + len += (format == NULL ? 0: strlen( format )); + len += 12; + if(name) free(name); + if(format)free(format); + } + } + return len; +} + +char *vj_event_vevo_help_vims( int id, int n ) +{ + char *help = NULL; + char key[10]; + sprintf(key, "help_%d", n); + size_t len = vevo_property_element_size( index_map_[id], key, 0 ); + if(len > 0 ) + { + help = (char*) malloc(sizeof(char) * len ); + vevo_property_get( index_map_[id], key, 0, &help ); + } + return help; +} + +char *vj_event_vevo_list_serialize(void) +{ + int len = vj_event_vevo_list_size() + 5; + char *res = (char*) malloc(sizeof(char) * len + 100 ); + int i; + memset( res, 0, len ); + sprintf(res, "%05d", len - 5); + for ( i = 0; i < MAX_INDEX ;i ++ ) + { + if ( index_map_[i] != NULL ) + { + char *name = vj_event_vevo_get_event_name( i ); + char *format= vj_event_vevo_get_event_format( i ); + int name_len = (name == NULL ? 0: strlen( name )); + int fmt_len = (format == NULL? 0: strlen( format )); + char tmp[13]; + sprintf( tmp, "%04d%02d%03d%03d", + i, vj_event_vevo_get_num_args(i), fmt_len, name_len ); + veejay_strncat( res, tmp, 12 ); + if( format != NULL ) + veejay_strncat( res, format, fmt_len ); + if( name != NULL ) + veejay_strncat( res, name, name_len ); + if(name) free(name); + if(format) free(format); + + } + } + return res; +} + +void vj_event_vevo_inline_fire(void *super, int vims_id, const char *format, ... ) +{ + va_list ap; + va_start( ap, format ); + void *func = NULL; + vevo_property_get( index_map_[vims_id], "function", 0, &func ); + vevo_event f = (vevo_event) func; + f( super, format, ap ); + va_end( ap ); +} + +void vj_event_vevo_inline_fire_default( void *super, int vims_id, const char *format ) +{ + char key[10]; + int i = 0; + int n = 0; + int dval[4] = {0,0,0,0}; + if(!index_map_[vims_id]) + { + veejay_msg(0, "No such event: %d", vims_id); + return; + } + vevo_property_get( index_map_[vims_id] , "arguments", 0, &n ); + // dangerous, dval != atom_type, i != n defaults + while( i < n ) + { + sprintf(key, "argument_%d", i ); + vevo_property_get( index_map_[vims_id], key, 0, &dval[i] ); + i++; + } + vj_event_vevo_inline_fire( super, vims_id, format, &dval[0],&dval[1],&dval[2],&dval[3]); +} + +static vevo_port_t *_new_event( + const char *format, + int vims_id, + const char *name, + void *function, + int n_arg, + int flags, + ... ) +{ + int n = 0; + int it = 1; + char param_name[16]; + char descr_name[255]; + +#ifdef STRICT_CHECKING + assert( name != NULL ); + assert( function != NULL ); + assert( vims_id > 0 ); +#endif + + vevo_port_t *p = (void*) vpn( VEVO_EVENT_PORT ); +#ifdef STRICT_CHECKING + assert( p != NULL ); +#endif + if( format ) + vevo_property_set( p, "format", VEVO_ATOM_TYPE_STRING, 1, &format ); + else + vevo_property_set( p, "format", VEVO_ATOM_TYPE_STRING, 0, NULL ); + + vevo_property_set( p, "description", VEVO_ATOM_TYPE_STRING, 1, &name ); + vevo_property_set( p, "function", VEVO_ATOM_TYPE_VOIDPTR, 1,&function ); + vevo_property_set( p, "arguments", VEVO_ATOM_TYPE_INT, 1, &n_arg ); + vevo_property_set( p, "flags", VEVO_ATOM_TYPE_INT, 1, &flags ); + vevo_property_set( p, "vims_id", VEVO_ATOM_TYPE_INT, 1, &vims_id ); + + va_list ap; + va_start(ap, flags); + + for( n = 0; n < n_arg ; n ++) + { + int dd = 0; + char *ds = NULL; + + sprintf(param_name, "argument_%d", n ); + const char *arg = va_arg( ap, const char*); +#ifdef STRICT_CHECKING + if(!arg) veejay_msg(VEEJAY_MSG_DEBUG, "\t'%s' %s - %d = '%s' of format %c (%s)",name,param_name, n, arg, format[it],format ); + assert( arg != NULL ); +#endif + char *descr = (char*) strdup( arg ); + sprintf(descr_name, "help_%d", n ); + + if (format[it] == 'd') + { + dd = va_arg( ap, int ); + vevo_property_set( p, param_name, VEVO_ATOM_TYPE_INT,1, &dd ); + } + else + { + ds = va_arg( ap, char*); + if(!ds) + vevo_property_set( p, param_name, VEVO_ATOM_TYPE_STRING, 0, NULL ); + else + vevo_property_set( p, param_name, VEVO_ATOM_TYPE_STRING,1, &ds ); + } + + vevo_property_set( p, descr_name, VEVO_ATOM_TYPE_STRING, 1,&descr ); + + it += 3; + + if( ds ) + free( ds); + if( descr ) + free( descr ); + } + + va_end(ap); + + return p; +} + +void * vj_event_vevo_get_event_function( int id ) +{ + void *func = NULL; + if( index_map_[id] ) + vevo_property_get( index_map_[id] , "function", 0, &func ); + return func; +} + +char *vj_event_vevo_get_event_name( int id ) +{ + char *descr = NULL; + if( index_map_[id] == NULL ) + return NULL; + + size_t len = vevo_property_element_size( index_map_[id], "description", 0 ); + if(len > 0 ) + { + descr = (char*) malloc(sizeof(char) * len ); + vevo_property_get( index_map_[id], "description", 0, &descr ); + } + return descr; +} +char *vj_event_vevo_get_event_format( int id ) +{ + char *fmt = NULL; + if(!index_map_[id]) + return NULL; + size_t len = vevo_property_element_size( index_map_[id], "format", 0 ); + if(len > 0 ) + { + fmt = (char*) malloc(sizeof(char) * len ); + vevo_property_get( index_map_[id], "format", 0, &fmt ); + } + return fmt; +} + +int vj_event_exists( int id ) +{ + if( index_map_[id]) + return 1; + return 0; +} + + +int vj_event_vevo_get_default_value(int id, int p) +{ + int n =0; + if(!index_map_[id]) + return 0; + char key[15]; + sprintf(key, "argument_%d",p); + vevo_property_get(index_map_[id], key, 0, &n ); + return n; +} +int vj_event_vevo_get_num_args(int id) +{ + if(!index_map_[id]) + return 0; + int n =0; + vevo_property_get(index_map_[id], "arguments", 0, &n ); + return n; +} +int vj_event_vevo_get_flags( int id ) +{ + if(!index_map_[id]) + return 0; + int flags = 0; + vevo_property_get( index_map_[id], "flags", 0, &flags ); + return flags; +} + +int vj_event_vevo_get_vims_id( int id ) +{ + if(!index_map_[id]) + return 0; + int vims_id = 0; + vevo_property_get( index_map_[id], "vims_id", 0, &vims_id ); + return vims_id; +} + +void vj_event_vevo_dump(void) +{ + int i; + veejay_msg(VEEJAY_MSG_INFO, "VIMS Syntax: ':;'"); + veejay_msg(VEEJAY_MSG_INFO, "Use arguments according to FORMAT"); + veejay_msg(VEEJAY_MSG_INFO, "FORMAT controls the arguments as in C printf. Interpreted sequences are:"); + veejay_msg(VEEJAY_MSG_INFO, "\t%%d\tinteger"); + veejay_msg(VEEJAY_MSG_INFO, "\t%%s\tstring"); + + for( i = 0; i < MAX_INDEX; i ++ ) + { + if( index_map_[i] ) + { + dump_event_stderr( index_map_[i] ); + } + } +} + +void vj_event_vevo_free(void) +{ + int i; + + veejay_msg(VEEJAY_MSG_DEBUG, "Closing VIMS event system"); + + if( !index_map_) + return; + + for( i = 0 ; i < MAX_INDEX ; i ++ ) + if( index_map_[i] ) vevo_port_free( index_map_[i] ); + + free(index_map_); +} + +void vj_init_vevo_events(void) +{ + index_map_ = (vevo_port_t*) vj_malloc(sizeof(vevo_port_t*) * MAX_INDEX ); + veejay_memset( index_map_, 0, sizeof( vevo_port_t *) * MAX_INDEX ); + + index_map_[VIMS_MACRO] = _new_event( + "%d %d", + VIMS_MACRO, + "Macro keystroke recorder/playback", + vj_event_set_macro_status, + 2, + VIMS_ALLOW_ANY, + "Keep or reset (1=reset)", + 1, + "Macro status (0=disabled,1=record,2=playing)", + 0, + NULL ); + + index_map_[VIMS_MACRO_SELECT] = _new_event( + "%d", + VIMS_MACRO_SELECT, + "Select a bank to store macro keystrokes", + vj_event_select_macro, + 1, + VIMS_ALLOW_ANY, + "Bank ID", + 0, + NULL ); + + index_map_[VIMS_VIDEO_PLAY_FORWARD] = _new_event( + NULL, + VIMS_VIDEO_PLAY_FORWARD, + "Play forward", + vj_event_play_forward, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_VIDEO_PLAY_BACKWARD] = _new_event( + NULL, + VIMS_VIDEO_PLAY_BACKWARD, + "Play backward", + vj_event_play_reverse, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_VIDEO_PLAY_STOP] = _new_event( + NULL, + VIMS_VIDEO_PLAY_STOP, + "Play stop", + vj_event_play_stop, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_VIDEO_SKIP_FRAME] = _new_event( + "%d", + VIMS_VIDEO_SKIP_FRAME, + "Skip N frames forward", + vj_event_inc_frame, + 1, + VIMS_ALLOW_ANY, + "Number of frames", // param label + 1, // default + NULL ); + + index_map_[VIMS_VIDEO_PREV_FRAME] = _new_event( + "%d", + VIMS_VIDEO_PREV_FRAME, + "Skip N frames backward", + vj_event_dec_frame, + 1, + VIMS_ALLOW_ANY, + "Number of frames", + 1, + NULL ); + + index_map_[VIMS_VIDEO_SKIP_SECOND] = _new_event( + "%d", + VIMS_VIDEO_SKIP_SECOND, + "Skip N seconds forward", + vj_event_next_second, + 1, + VIMS_ALLOW_ANY, + "Number of seconds", + 1, + NULL ); + + index_map_[VIMS_VIDEO_PREV_SECOND] = _new_event( + "%d", + VIMS_VIDEO_PREV_SECOND, + "Skip N seconds backward", + vj_event_prev_second, + 1, + VIMS_ALLOW_ANY, + "Number of seconds", + 1, + NULL ); + + index_map_[VIMS_VIDEO_GOTO_START] = _new_event( + NULL, + VIMS_VIDEO_GOTO_START, + "Go to starting position", + vj_event_goto_start, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_VIDEO_GOTO_END] = _new_event( + NULL, + VIMS_VIDEO_GOTO_END, + "Go to ending position", + vj_event_goto_end, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_VIDEO_SET_SPEEDK] = _new_event( + "%d", + VIMS_VIDEO_SET_SPEED, + "Change trickplay speed depending on play direction", + vj_event_play_speed_kb, + 1, + VIMS_ALLOW_ANY, + "Frame step", + 1, + NULL ); + + index_map_[VIMS_VIDEO_SET_SPEED] = _new_event( + "%d", + VIMS_VIDEO_SET_SPEED, + "Change trickplay speed", + vj_event_play_speed, + 1, + VIMS_ALLOW_ANY, + "Frame step", + 1, + NULL ); + + index_map_[VIMS_VIDEO_SET_SLOW] = _new_event( + "%d", + VIMS_VIDEO_SET_SLOW, + "Change frameduplication", + vj_event_play_slow, + 1, + VIMS_ALLOW_ANY, + "Frame repeat", + 0, + NULL ); + + index_map_[VIMS_VIDEO_SET_FRAME] = _new_event( + "%d", + VIMS_VIDEO_SET_FRAME, + "Set current frame number", + vj_event_set_frame, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Frame number", + 0, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_UP] = _new_event( + "%d", + VIMS_CHAIN_ENTRY_UP, + "Increment current FX chain entry", + vj_event_entry_up, + 1, + VIMS_ALLOW_ANY, + "Increment value", + 1, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_DOWN] = _new_event( + "%d", + VIMS_CHAIN_ENTRY_DOWN, + "Decrement current FX chain entry", + vj_event_entry_down, + 1, + VIMS_ALLOW_ANY, + "Decrement value", + -1, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_CHANNEL_INC] = _new_event( + "%d", + VIMS_CHAIN_ENTRY_CHANNEL_INC, + "Increment current Channel ID on selected chain entry", + vj_event_chain_entry_channel_inc, + 1, + VIMS_ALLOW_ANY, + "Increment vale", + 1, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_CHANNEL_DEC] = _new_event( + "%d", + VIMS_CHAIN_ENTRY_CHANNEL_DEC, + "Decrement current Channel ID on selected chain entry", + vj_event_chain_entry_channel_dec, + 1, + VIMS_ALLOW_ANY, + "Decrement value", + 1, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_SOURCE_TOGGLE] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_SOURCE_TOGGLE, + "Change source type of a chain entry", + vj_event_chain_entry_src_toggle, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Chain entry", + 1, + "Source type (0=Sample, 1=Stream)", + 0, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_INC_ARG] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_INC_ARG, + "Increment current value of a parameter", + vj_event_chain_arg_inc, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Parameter number", + 0, + "Step size", + 0, + NULL ); + + + + index_map_[VIMS_CHAIN_ENTRY_DEC_ARG] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_DEC_ARG, + "Decrement current value of a parameter", + vj_event_chain_arg_inc, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Parameter number", + 0, + "Step size", + 0, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_SET_STATE] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_SET_STATE, + "Enable / disable effect on current entry", + vj_event_chain_entry_video_toggle, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_CHAIN_TOGGLE] = _new_event( + NULL, + VIMS_CHAIN_TOGGLE, + "Enable / disable Effect Chain", + vj_event_chain_toggle, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SET_SAMPLE_START] = _new_event( + NULL, + VIMS_SET_SAMPLE_START, + "Store current frame as starting position of new sample", + vj_event_sample_start, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SAMPLE_KF_STATUS] = _new_event( + "%d %d", + VIMS_SAMPLE_KF_STATUS, + "Change KF play status for entry X", + vj_event_set_kf_status, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Entry ID", + 0, + "Status value", + 0, + NULL ); + index_map_[VIMS_SAMPLE_KF_RESET] = _new_event( + "%d", + VIMS_SAMPLE_KF_STATUS, + "Clear KF series on entry X", + vj_event_reset_kf, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Entry ID", + 0, + NULL ); + index_map_[VIMS_SAMPLE_KF_GET] = _new_event( + "%d %d", + VIMS_SAMPLE_KF_GET, + "Get keyframes for parameter Y on entry X", + vj_event_get_keyframes, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Entry ID", + 0, + "Parameter ID", + 0, + NULL ); + + index_map_[VIMS_SET_SAMPLE_END] = _new_event( + NULL, + VIMS_SET_SAMPLE_END, + "Store current frame as ending position of a new sample ( and commit )", + vj_event_sample_end, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SAMPLE_SET_MARKER_START] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_MARKER_START, + "Set in point on sample", + vj_event_sample_set_marker_start, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Position", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_SET_MARKER_END] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_MARKER_END, + "Set out point on sample", + vj_event_sample_set_marker_end, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Position", + 0, + NULL ); + + + index_map_[VIMS_FXLIST_INC] = _new_event( + "%d", + VIMS_FXLIST_INC, + "Increment index of Effect List", + vj_event_effect_inc, + 1, + VIMS_ALLOW_ANY, + "Step size", + 1, + NULL ); + + index_map_[VIMS_FXLIST_DEC] = _new_event( + "%d", + VIMS_FXLIST_DEC, + "Decrement index of Effect List", + vj_event_effect_dec, + 1, + VIMS_ALLOW_ANY, + "Step size", + 1, + NULL ); + index_map_[VIMS_FXLIST_ADD] = _new_event( + NULL, + VIMS_FXLIST_ADD, + "Put selected effect in Effect List to current sample and current entry", + vj_event_effect_add, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SELECT_BANK] = _new_event( + "%d", + VIMS_SELECT_BANK, + "Set current sample bank", + vj_event_select_bank, + 1, + VIMS_ALLOW_ANY, + "Bank number", + 0, + NULL ); + index_map_[VIMS_SELECT_ID] = _new_event( + "%d", + VIMS_SELECT_ID, + "Play stream or sample slot (depends on current playmode)", + vj_event_select_id, + 1, + VIMS_ALLOW_ANY, + "Slot number", + 1, + NULL ); + + index_map_[VIMS_SAMPLE_RAND_START] = _new_event( + "%d", + VIMS_SAMPLE_RAND_START, + "Start sample randomizer", + vj_event_sample_rand_start, + 1, + VIMS_ALLOW_ANY, + "Mode (0=Random duration, 1=Sample duration)", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_RAND_STOP] = _new_event( + NULL, + VIMS_SAMPLE_RAND_STOP, + "Stop sample randomizer", + vj_event_sample_rand_stop, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SAMPLE_TOGGLE_LOOP] = _new_event( + "%d %d", + VIMS_SAMPLE_TOGGLE_LOOP, + "Switch between loop types", + vj_event_sample_set_loop_type, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Looptype (0=None, 1=Normal, 2=Pingpong)", + -1, + NULL); + + index_map_[VIMS_PREVIEW_BW] = _new_event( + NULL, + VIMS_PREVIEW_BW, + "Toggle grayscale preview on/off (default=off)", + vj_event_toggle_bw, + 0, + VIMS_ALLOW_ANY, + NULL, + NULL ); + index_map_[VIMS_RECORD_DATAFORMAT] = _new_event( + "%s", + VIMS_RECORD_DATAFORMAT, + "Set codec to use for recording (global setting)", + vj_event_tag_set_format, + 1, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + "Codec name (use 'x' to see list)", + NULL, + NULL ); + + index_map_[VIMS_REC_AUTO_START] = _new_event( + NULL, + VIMS_REC_AUTO_START, + "Start recording now and play when finished", + vj_event_misc_start_rec_auto, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_REC_START] = _new_event( + NULL, + VIMS_REC_START, + "Start recording", + vj_event_misc_start_rec, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_REC_STOP] = _new_event( + NULL, + VIMS_REC_STOP, + "Stop recording", + vj_event_misc_stop_rec, + 0, + VIMS_ALLOW_ANY , + NULL ); + + index_map_[VIMS_SAMPLE_NEW] = _new_event( + "%d %d", + VIMS_SAMPLE_NEW, + "Create a new sample", + vj_event_sample_new, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Starting position", + 0, + "Ending position", + -1, + NULL ); + + index_map_[VIMS_PRINT_INFO] = _new_event( + "%d", + VIMS_PRINT_INFO, + "Print current settings", + vj_event_print_info, + 1, + VIMS_ALLOW_ANY, + "Sample or Stream ID (depends on playmode, 0=current playing)", + 0, + NULL ); + + index_map_[VIMS_SET_PLAIN_MODE] = _new_event( + "%d", + VIMS_SET_PLAIN_MODE, + "Change playback mode", + vj_event_set_play_mode, + 1, + VIMS_ALLOW_ANY, + "Playback (2=plain,1=stream,0=sample)", + 2, + NULL ); + + index_map_[VIMS_SAMPLE_SET_LOOPTYPE] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_LOOPTYPE, + "Change looptype of sample", + vj_event_sample_set_loop_type, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Looptype (0=None,1=Normal,2=Pingpong)", + 1, + NULL ); + + index_map_[VIMS_SAMPLE_SET_SPEED] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_SPEED, + "Change playback speed of sample", + vj_event_sample_set_speed, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Speed (0=pause, > 0 and < (end-start)", + 1, + NULL ); + + index_map_[VIMS_SAMPLE_SET_DESCRIPTION] = _new_event( + "%d %s", + VIMS_SAMPLE_SET_DESCRIPTION, + "Change title of sample", + vj_event_sample_set_descr, + 2, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + SAMPLE_ID_HELP, + 0, + "Title", + NULL, + NULL ); + + index_map_[VIMS_SAMPLE_SET_END] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_END, + "Change end position of sample", + vj_event_sample_set_end, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Frame number", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_SET_START] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_START, + "Change start position of sample", + vj_event_sample_set_start, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Frame number", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_SET_DUP] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_DUP, + "Change frame repeat for this sample", + vj_event_sample_set_dup, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Frame repeat", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_SET_MARKER_START] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_MARKER_START, + "Set in point in sample", + vj_event_sample_set_marker_start, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Position", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_SET_MARKER_END] = _new_event( + "%d %d", + VIMS_SAMPLE_SET_MARKER_END, + "Set out point in sample", + vj_event_sample_set_marker_end, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Position", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_SET_MARKER] = _new_event( + "%d %d %d", + VIMS_SAMPLE_SET_MARKER, + "Set in and out points in sample", + vj_event_sample_set_marker, + 3, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Starting position", + 0, + "Ending position", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_CLEAR_MARKER] = _new_event( + "%d", + VIMS_SAMPLE_CLEAR_MARKER, + "Clear in and out points", + vj_event_sample_set_marker_clear, + 1, + VIMS_ALLOW_ANY, + SAMPLE_ID_HELP, + 0, + NULL ); +#ifdef HAVE_XML2 + index_map_[VIMS_SAMPLE_LOAD_SAMPLELIST] = _new_event( + "%s", + VIMS_SAMPLE_LOAD_SAMPLELIST, + "Load samples from file", + vj_event_sample_load_list, + 1, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + "Filename", + NULL, + NULL ); + index_map_[VIMS_SAMPLE_SAVE_SAMPLELIST] = _new_event( + "%s", + VIMS_SAMPLE_SAVE_SAMPLELIST, + "Save samples to file", + vj_event_sample_save_list, + 1, + VIMS_REQUIRE_ALL_PARAMS|VIMS_LONG_PARAMS, + "Filename", + NULL, + NULL ); +#endif + + + index_map_[VIMS_SAMPLE_CHAIN_ENABLE] = _new_event( + "%d", + VIMS_SAMPLE_CHAIN_ENABLE, + "Enable effect chain of sample", + vj_event_sample_chain_enable, + 1, + VIMS_ALLOW_ANY, + SAMPLE_ID_HELP, + 0, + NULL ); + + index_map_[VIMS_SAMPLE_CHAIN_DISABLE] = _new_event( + "%d", + VIMS_SAMPLE_CHAIN_DISABLE, + "Disable effect chain of sample", + vj_event_sample_chain_disable, + 1, + VIMS_ALLOW_ANY, + SAMPLE_ID_HELP, + 0, + NULL ); + + index_map_[VIMS_SAMPLE_REC_START] = _new_event( + "%d %d", + VIMS_SAMPLE_REC_START, + "Start recording from sample", + vj_event_sample_rec_start, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Number of frames (0=sample duration)", + 0, + "Auto Play (0=disable, 1=enable)", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_REC_STOP] = _new_event( + NULL, + VIMS_SAMPLE_REC_STOP, + "Stop recording from this sample", + vj_event_sample_rec_stop, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SAMPLE_DEL] = _new_event( + "%d", + VIMS_SAMPLE_DEL, + "Delete sample", + vj_event_sample_del, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Sample ID >= 1", + 0, + NULL ); + + index_map_[VIMS_SAMPLE_DEL_ALL] = _new_event( + NULL, + VIMS_SAMPLE_DEL_ALL, + "Delete all samples (caution!)", + vj_event_sample_clear_all, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SAMPLE_COPY] = _new_event( + "%d", + VIMS_SAMPLE_COPY, + "Copy sample to new", + vj_event_sample_copy, + 1, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + NULL ); + + index_map_[VIMS_SAMPLE_SELECT] = _new_event( + "%d", + VIMS_SAMPLE_SELECT, + "Select and play sample", + vj_event_sample_select, + 1, + VIMS_ALLOW_ANY, + SAMPLE_ID_HELP, + 0, + NULL ); + + index_map_[VIMS_STREAM_SELECT] = _new_event( + "%d", + VIMS_STREAM_SELECT, + "Select and play stream", + vj_event_tag_select, + 1, + VIMS_ALLOW_ANY, + "Stream ID >= 1", + 0, + NULL ); + + index_map_[VIMS_STREAM_DELETE] = _new_event( + "%d", + VIMS_STREAM_DELETE, + "Delete stream", + vj_event_tag_del, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Stream ID >= 1", + 0, + NULL ); + index_map_[VIMS_V4L_CALI] = _new_event( + "%s", + VIMS_V4L_CALI, + "Write calibration data to file", + vj_event_cali_write_file, + 1, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + "Filename", + NULL, + NULL ); + index_map_[VIMS_STREAM_NEW_CALI] = _new_event( + "%s", + VIMS_STREAM_NEW_CALI, + "Load calibration data", + vj_event_stream_new_cali, + 1, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + "Filename", + NULL, + NULL ); + index_map_[VIMS_V4L_BLACKFRAME] = _new_event( + "%d %d %d %d", + VIMS_V4L_BLACKFRAME, + "Capture a black/light frame and subtract it from the video stream", + vj_event_v4l_blackframe, + 4, + VIMS_REQUIRE_ALL_PARAMS, + "Tag ID", + 0, + "Frame Duration (Use 0 to drop blackframe)", + 5, + "Median Radius (0=Average, N=NxN square)", + 0, + "Blackframe=0,Lightframe=1", + 0, + NULL); + + index_map_[VIMS_STREAM_NEW_V4L] = _new_event( + "%d %d", + VIMS_STREAM_NEW_V4L, + "Open video4linux device as new input stream", + vj_event_tag_new_v4l, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Device Number (0=/dev/video0,1=/dev/video1, ... )", + 0, + "Channel Number (0=TV,1=composite,2=svideo)", + 0, + NULL ); +#ifdef SUPPORT_READ_DV2 + index_map_[VIMS_STREAM_NEW_DV1394] = _new_event( + "%d", + VIMS_STREAM_NEW_DV1394, + "Open dv1394 device as new input stream", + vj_event_tag_new_dv1394, + 1, + VIMS_ALLOW_ANY, + "Channel number", + 63, + NULL ); +#endif + index_map_[VIMS_STREAM_NEW_Y4M] = _new_event( + "%s", + VIMS_STREAM_NEW_Y4M, + "Open yuv4mpeg (special) file as new input stream", + vj_event_tag_new_y4m, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Filename", + NULL, + NULL ); + index_map_[VIMS_STREAM_NEW_COLOR] = _new_event( + "%d %d %d", + VIMS_STREAM_NEW_COLOR, + "Solid RGB color fill as new input stream", + vj_event_tag_new_color, + 3, + VIMS_REQUIRE_ALL_PARAMS, + "Red", + 0, + "Green", + 0, + "Blue", + 0, + NULL ); + index_map_[VIMS_RGB_PARAMETER_TYPE] = _new_event( + "%d", + VIMS_RGB_PARAMETER_TYPE, + "Change YUV <-> RGB conversion (unadvised)", + vj_event_set_rgb_parameter_type, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Mode (0=GIMP,1=CCIR701,2=broken)", + 0, + NULL ); + index_map_[VIMS_STREAM_COLOR] = _new_event( + "%d %d %d %d", + VIMS_STREAM_COLOR, + "Change RGB color of solid stream", + vj_event_set_stream_color, + 4, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Red", + 0, + "Green", + 0, + "Blue", + 0, + NULL ); + index_map_[VIMS_STREAM_NEW_UNICAST] = _new_event( + "%d %s", + VIMS_STREAM_NEW_UNICAST, + "Open TCP veejay connection (peer to peer, raw data) as new input stream", + vj_event_tag_new_net, + 2, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Port number", + 0, + "Hostname or IP address", + NULL, + NULL ); + index_map_[VIMS_STREAM_NEW_MCAST] = _new_event( + "%d %s", + VIMS_STREAM_NEW_MCAST, + "Open UDP multicast as new input stream", + vj_event_tag_new_mcast, + 2, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Port Number", + 0, + "Multicast Address", + NULL, + NULL ); +#ifdef USE_GDK_PIXBUF + index_map_[VIMS_STREAM_NEW_PICTURE] = _new_event( + "%s", + VIMS_STREAM_NEW_PICTURE, + "Open image from file as new input stream", + vj_event_tag_new_picture, + 1, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Filename", + NULL, + NULL ); +#endif + + index_map_[VIMS_STREAM_OFFLINE_REC_START] = _new_event( + "%d %d %d", + VIMS_STREAM_OFFLINE_REC_START, + "Start offline recording from stream", + vj_event_tag_rec_offline_start, + 3, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Number of frames", + 0, + "Auto Play (0=disable,1=enable)", + 0, + NULL ); + index_map_[VIMS_STREAM_OFFLINE_REC_STOP] = _new_event( + NULL, + VIMS_STREAM_OFFLINE_REC_STOP, + "Stop offline recording from this stream", + vj_event_tag_rec_offline_stop, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_STREAM_SET_DESCRIPTION] = _new_event( + "%d %s", + VIMS_STREAM_SET_DESCRIPTION, + "Change title of stream", + vj_event_tag_set_descr, + 2, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Title", + NULL, + NULL ); + index_map_[VIMS_STREAM_REC_START] = _new_event( + "%d %d", + VIMS_STREAM_REC_START, + "Start recording from stream", + vj_event_tag_rec_start, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Number of frames", + 0, + "Auto Play (0=disable,1=enable)", + 0, + NULL ); + index_map_[VIMS_STREAM_REC_STOP] = _new_event( + "%d %d", + VIMS_STREAM_REC_STOP, + "Stop recording from this stream", + vj_event_tag_rec_stop, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_STREAM_CHAIN_ENABLE] = _new_event( + "%d", + VIMS_STREAM_CHAIN_ENABLE, + "Enable effect chain of stream", + vj_event_tag_chain_enable, + 1, + VIMS_ALLOW_ANY, + STREAM_ID_HELP, + 0, + NULL ); + index_map_[VIMS_STREAM_CHAIN_DISABLE] = _new_event( + "%d", + VIMS_STREAM_CHAIN_DISABLE, + "Disable effect chain of stream", + vj_event_tag_chain_disable, + 1, + VIMS_ALLOW_ANY, + STREAM_ID_HELP, + 0, + NULL ); + index_map_[VIMS_CHAIN_ENTRY_SET_EFFECT] = _new_event( + "%d %d %d", + VIMS_CHAIN_ENTRY_SET_EFFECT, + "Add effect to chain entry with default values", + vj_event_chain_entry_set, + 3, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + "Effect ID", + 0, + NULL ); + index_map_[VIMS_CHAIN_ENTRY_SET_PRESET] = _new_event( + "%d %d %d %d %d %d %d %d %d %d %d", + VIMS_CHAIN_ENTRY_SET_PRESET, + "Preset effect on chain entry", + vj_event_chain_entry_preset, + 11, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current", + -1, + "Effect ID", + 0, + "Parameter 0", + 0, + "Parameter 1", + 0, + "Parameter 2", + 0, + "Parameter 3", + 0, + "Parameter 4", + 0, + "Parameter 5", + 0, + "Parameter 6", + 0, + "Parameter 7", + 0, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_SET_ARG_VAL] = _new_event( + "%d %d %d %d", + VIMS_CHAIN_ENTRY_SET_ARG_VAL, + "Set a parameter value", + vj_event_chain_entry_set_arg_val, + 4, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + "Parameter number", + 0, + "Value", + 0, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_SET_VIDEO_ON] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_SET_VIDEO_ON, + "Enable effect on chain index", + vj_event_chain_entry_enable_video, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_SET_VIDEO_OFF] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_SET_VIDEO_OFF, + "Disable effect on chain index", + vj_event_chain_entry_disable_video, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_SET_DEFAULTS] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_SET_DEFAULTS, + "Reset effect to default", + vj_event_chain_entry_set_defaults, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + NULL ); + index_map_[VIMS_CHAIN_ENTRY_SET_CHANNEL] = _new_event( + "%d %d %d", + VIMS_CHAIN_ENTRY_SET_CHANNEL, + "Set mixing channel", + vj_event_chain_entry_channel, + 3, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + "Sample ID", + 1, + NULL ); + index_map_[VIMS_CHAIN_ENTRY_SET_SOURCE] = _new_event( + "%d %d %d", + VIMS_CHAIN_ENTRY_SET_SOURCE, + "Set mixing source type", + vj_event_chain_entry_source, + 3, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + "Source Type (0=sample,1=stream)", + 0, + NULL ); + + index_map_[VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL] = _new_event( + "%d %d %d %d", + VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL, + "Set mixing channel and source type", + vj_event_chain_entry_srccha, + 4, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + "Source Type (0=sample,1=stream)", + 0, + "Sample or Stream ID", + 0, + NULL ); + index_map_[VIMS_CHAIN_ENTRY_CLEAR] = _new_event( + "%d %d", + VIMS_CHAIN_ENTRY_CLEAR, + "Reset chain index", + vj_event_chain_entry_del, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index (-1=current)", + -1, + NULL ); + index_map_[VIMS_CHAIN_ENABLE] = _new_event( + NULL, + VIMS_CHAIN_ENABLE, + "Enable Effect Chain", + vj_event_chain_enable, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_CHAIN_DISABLE] = _new_event( + NULL, + VIMS_CHAIN_DISABLE, + "Disable Effect Chain", + vj_event_chain_disable, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_CHAIN_CLEAR] = _new_event( + "%d", + VIMS_CHAIN_CLEAR, + "Reset Effect Chain", + vj_event_chain_clear, + 1, + VIMS_ALLOW_ANY, + SAMPLE_STREAM_ID_HELP, + 0, + NULL ); + index_map_[VIMS_CHAIN_FADE_IN] = _new_event( + "%d %d", + VIMS_CHAIN_FADE_IN, + "Fade in effect chain", + vj_event_chain_fade_in, + 2, + VIMS_ALLOW_ANY, + SAMPLE_STREAM_ID_HELP, + 0, + "Duration in frames", + 100, + NULL ); + index_map_[VIMS_CHAIN_FADE_OUT] = _new_event( + "%d %d", + VIMS_CHAIN_FADE_OUT, + "Fade out effet chain", + vj_event_chain_fade_out, + 2, + VIMS_ALLOW_ANY, + SAMPLE_STREAM_ID_HELP, + 0, + "Duration in frames", + 100, + NULL ); + + index_map_[VIMS_CHAIN_FOLLOW_FADE] = _new_event( + "%d", + VIMS_CHAIN_FOLLOW_FADE, + "Follow to sample #B after finishing fade from sample #A", + vj_event_chain_fade_follow, + 1, + VIMS_ALLOW_ANY, + "0=On, 1=Off", + 0, + NULL ); + + + index_map_[VIMS_CHAIN_MANUAL_FADE] = _new_event( + "%d %d", + VIMS_CHAIN_MANUAL_FADE, + "Set opacity of Effect Chain", + vj_event_manual_chain_fade, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Opacity value [0-255]", + 0, + NULL ); + index_map_[VIMS_CHAIN_SET_ENTRY] = _new_event( + "%d", + VIMS_CHAIN_SET_ENTRY, + "Set Chain Index", + vj_event_chain_entry_select, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Index value", + 0, + NULL ); + + index_map_[VIMS_OUTPUT_Y4M_START] = _new_event( + "%s", + VIMS_OUTPUT_Y4M_START, + "(OUT) Write video output to (special) file in yuv4mpeg format", + vj_event_output_y4m_start, + 1, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS , + "Filename", + NULL, + NULL ); + index_map_[VIMS_OUTPUT_Y4M_STOP] = _new_event( + NULL, + VIMS_OUTPUT_Y4M_STOP, + "(OUT) Stop writing video output to yuv4mpeg file", + vj_event_output_y4m_stop, + 0, + VIMS_ALLOW_ANY, + NULL ); +#ifdef HAVE_SDL + index_map_[VIMS_RESIZE_SDL_SCREEN] = _new_event( + "%d %d %d %d", + VIMS_RESIZE_SDL_SCREEN, + "(OUT) Resize SDL video window", + vj_event_set_screen_size, + 4, + VIMS_REQUIRE_ALL_PARAMS, + "Width", + 0, + "Height", + 0, + "X offset", + 0, + "Y offset", + 0, + NULL ); +#endif + index_map_[VIMS_SET_PLAY_MODE] = _new_event( + "%d", + VIMS_SET_PLAY_MODE, + "Change playback mode", + vj_event_set_play_mode, + 1, + VIMS_ALLOW_ANY, + "Playback mode (0=sample,1=stream,2=plain)", + 0 ); + index_map_[VIMS_SET_MODE_AND_GO] = _new_event( + "%d %d", + VIMS_SET_MODE_AND_GO, + "Play sample / stream", + vj_event_set_play_mode_go, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Source type (0=sample,1=stream)", + 0, + NULL ); + index_map_[VIMS_SWITCH_SAMPLE_STREAM] = _new_event( + NULL, + VIMS_SWITCH_SAMPLE_STREAM, + "Switch between sample and stream playback", + vj_event_switch_sample_tag, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_AUDIO_DISABLE] = _new_event( + NULL, + VIMS_AUDIO_DISABLE, + "Disable audio playback", + vj_event_disable_audio, + 0, + VIMS_ALLOW_ANY , + NULL ); + + index_map_[VIMS_AUDIO_ENABLE] = _new_event( + NULL, + VIMS_AUDIO_DISABLE, + "Enable audio playback", + vj_event_enable_audio, + 0, + VIMS_ALLOW_ANY , + NULL ); + + + index_map_[VIMS_EDITLIST_PASTE_AT] = _new_event( + "%d", + VIMS_EDITLIST_PASTE_AT, + "Paste frames from buffer at frame into edit descision list", + vj_event_el_paste_at, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "EDL position", + 0, + NULL ); + index_map_[VIMS_EDITLIST_CUT] = _new_event( + "%d %d", + VIMS_EDITLIST_CUT, + "Cut frames from edit descision list to buffer", + vj_event_el_cut, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "EDL start position", + 0, + "EDL end position", + 0, + NULL ); + index_map_[VIMS_EDITLIST_COPY] = _new_event( + "%d %d", + VIMS_EDITLIST_COPY, + "Copy frames from edit descision list to buffer", + vj_event_el_copy, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "EDL start position", + 0, + "EDL end position", + 0, + NULL ); + index_map_[VIMS_EDITLIST_CROP] = _new_event( + "%d %d", + VIMS_EDITLIST_CROP, + "Crop frames from edit descision list to buffer", + vj_event_el_crop, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "EDL start position", + 0, + "EDL end position", + 0, + NULL ); + index_map_[VIMS_EDITLIST_DEL] = _new_event( + "%d %d", + VIMS_EDITLIST_DEL, + "Delete frames from editlist (no undo!)", + vj_event_el_del, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "EDL start position", + 0, + "EDL end position", + 0, + NULL ); + index_map_[VIMS_EDITLIST_SAVE] = _new_event( + "%d %d %s", + VIMS_EDITLIST_SAVE, + "Save (selection of) edit descision list to new file", + vj_event_el_save_editlist, + 3, + VIMS_LONG_PARAMS | VIMS_ALLOW_ANY, + "EDL start position (0=start position)", + 0, + "EDL end position (0=end position)", + 0, + "Filename", + NULL, + NULL ); + index_map_[VIMS_EDITLIST_LOAD] = _new_event( + "%s", + VIMS_EDITLIST_LOAD, + "Load edit descision list from file", + vj_event_el_load_editlist, + 1, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Filename", + NULL, + NULL ); + index_map_[VIMS_EDITLIST_ADD] = _new_event( + "%s", + VIMS_EDITLIST_ADD, + "Add video file to edit descision list", + vj_event_el_add_video, + 1, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Filename", + NULL, + NULL ); + index_map_[VIMS_EDITLIST_ADD_SAMPLE] = _new_event( + "%d %s", + VIMS_EDITLIST_ADD_SAMPLE, + "GUI: Append a file to the plain EDL and create a new sample (unadvised!)", + vj_event_el_add_video_sample, + 2, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "existing or new ID", + 0, + "Filename", + NULL, + NULL ); + index_map_[VIMS_STREAM_LIST] = _new_event( + "%d", + VIMS_STREAM_LIST, + "GUI: Get a list of all streams (unadvised!)", + vj_event_send_tag_list, + 1, + VIMS_ALLOW_ANY, + "stream offset", + 0, + NULL ); + + index_map_[VIMS_TRACK_LIST] = _new_event( + NULL, + VIMS_TRACK_LIST, + "GUI: Get a list of all tracks (unadvised!)", + vj_event_send_track_list, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_WORKINGDIR] = _new_event( + "%d", + VIMS_WORKINGDIR, + "GUI: Get all video files starting in cwd", + vj_event_send_working_dir, + 1, + VIMS_ALLOW_ANY, + "(unused)", + 0, + NULL ); + + + index_map_[VIMS_SAMPLE_LIST] = _new_event( + "%d", + VIMS_SAMPLE_LIST, + "GUI: Get a list of all samples", + vj_event_send_sample_list, + 1, + VIMS_ALLOW_ANY, + "sample offset", + 0, + NULL ); + index_map_[VIMS_SAMPLE_INFO] = _new_event( + "%d %d", + VIMS_SAMPLE_INFO, + "GUI: Get sample or stream information (unadivsed!)", + vj_event_send_sample_info, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Source Type (0=sample,1=stream)", + 0, + NULL ); + index_map_[VIMS_SAMPLE_OPTIONS] = _new_event( + "%d %d", + VIMS_SAMPLE_OPTIONS, + "GUI: Get sample options", + vj_event_send_sample_options, + 2, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_STREAM_ID_HELP, + 0, + "Source Type (0=sample,1=stream)", + 0, + NULL ); + index_map_[VIMS_EDITLIST_LIST] = _new_event( + NULL, + VIMS_EDITLIST_LIST, + "GUI: Get EDL", + vj_event_send_editlist, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_BUNDLE] = _new_event( + "%d", + VIMS_BUNDLE, + "Execute VIMS bundle", + vj_event_do_bundled_msg, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Bundle ID", + 0, + NULL ); +#ifdef HAVE_XML2 + index_map_[VIMS_BUNDLE_FILE] = _new_event( + "%s", + VIMS_BUNDLE_FILE, + "Veejay load action file", + vj_event_read_file, + 1, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Filename", + NULL , + NULL ); + index_map_[VIMS_BUNDLE_SAVE] = _new_event( + "%d %s", + VIMS_BUNDLE_SAVE, + "Veejay save action file", + vj_event_write_actionfile, + 2, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Mode (0=only Bundles,1=save edl/sample list)", + 0, + "Filename", + NULL, + NULL ); +#endif + index_map_[VIMS_BUNDLE_DEL] = _new_event( + "%d", + VIMS_BUNDLE_DEL, + "Delete a VIMS bundle", + vj_event_bundled_msg_del, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Bundle ID", + 0, + NULL ); + index_map_[VIMS_BUNDLE_LIST] = _new_event( + NULL, + VIMS_BUNDLE_LIST, + "GUI: Get all bundles", + vj_event_send_bundles, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[ VIMS_KEYLIST ] = _new_event( + NULL, + VIMS_KEYLIST, + "GUI: Get all keys", + vj_event_send_keylist, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_DEVICE_LIST] = _new_event( + NULL, + VIMS_DEVICE_LIST, + "GUI: Get all devices and their locations", + vj_event_send_devicelist, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_VIMS_LIST] = _new_event( + NULL, + VIMS_VIMS_LIST, + "GUI: Get all VIMS events", + vj_event_send_vimslist, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_BUNDLE_ADD] = _new_event( + "%d %s", + VIMS_BUNDLE_ADD, + "Add a new bundle to the event list", + vj_event_bundled_msg_add, + 2, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Bundle ID (0=new, 1=overwrite existing)", + 0, + "VIMS text", + 0, + NULL ); + + index_map_[VIMS_CALI_IMAGE] = _new_event( + "%d %d", + VIMS_REQUIRE_ALL_PARAMS, + "GUI: Get Calibrated image (raw)", + vj_event_get_cali_image, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "ID", + 0, + "Type", + 0, + NULL ); + + index_map_[VIMS_BUNDLE_CAPTURE] = _new_event( + NULL, + VIMS_BUNDLE_CAPTURE, + "Capture Effect Chain to a new Bundle", + vj_event_quick_bundle, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_LOG] = _new_event( + NULL, + VIMS_LOG, + "GUI: Get console output", + vj_event_send_log, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_CHAIN_LIST] = _new_event( + "%d", + VIMS_CHAIN_LIST, + "GUI: Get effect chain", + vj_event_send_chain_list, + 1, + VIMS_ALLOW_ANY, + SAMPLE_STREAM_ID_HELP, + 0, + NULL ); + + index_map_[VIMS_SAMPLE_STACK] = _new_event( + "%d", + VIMS_SAMPLE_STACK, + "Get sample stack details", + vj_event_send_sample_stack, + 1, + VIMS_ALLOW_ANY, + SAMPLE_STREAM_ID_HELP, + NULL ); + + index_map_[VIMS_CHAIN_GET_ENTRY] = _new_event( + "%d %d", + VIMS_CHAIN_GET_ENTRY, + "GUI: Get effect chain index details", + vj_event_send_chain_entry, + 2, + VIMS_ALLOW_ANY, + SAMPLE_STREAM_ID_HELP, + 0, + "Chain Index", + -1, + NULL ); + index_map_[VIMS_EFFECT_LIST] = _new_event( + NULL, + VIMS_EFFECT_LIST, + "GUI: Get all effects", + vj_event_send_effect_list, + 0, + VIMS_ALLOW_ANY ); + index_map_[VIMS_VIDEO_INFORMATION] = _new_event( + NULL, + VIMS_VIDEO_INFORMATION, + "GUI: Get video information details", + vj_event_send_video_information, + 0, + VIMS_ALLOW_ANY ); +#ifdef HAVE_SDL + index_map_[VIMS_BUNDLE_ATTACH_KEY] = _new_event( + "%d %d %d %s", + VIMS_BUNDLE_ATTACH_KEY, + "Attach/Detach a Key to VIMS Event", + vj_event_attach_detach_key, + 4, + VIMS_ALLOW_ANY, + "VIMS ID", + 0, + "SDL Key symbol", + 0, + "SDL Key modifier (0=none,1=alt,2=ctrl,3=shift)", + 0, + "VIMS message", + NULL, + NULL ); + +#endif +#ifdef USE_SWSCALER + index_map_[VIMS_RGB24_IMAGE] = _new_event( + "%d %d", + VIMS_REQUIRE_ALL_PARAMS, + "GUI: Get preview image (raw RGB24)", + vj_event_get_scaled_image, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Width", + 0, + "Height", + 0, + NULL ); + +#else +#ifdef USE_GDK_PIXBUF + index_map_[VIMS_RGB24_IMAGE] = _new_event( + "%d %d", + VIMS_REQUIRE_ALL_PARAMS, + "GUI: Get preview image (raw RGB24)", + vj_event_get_scaled_image, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Width", + 0, + "Height", + 0, + NULL ); +#endif +#endif +#ifdef USE_GDK_PIXBUF + index_map_[VIMS_SCREENSHOT] = _new_event( + "%d %d %s", + VIMS_SCREENSHOT, + "Save output frame to file", + vj_event_screenshot, + 3, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Width", + 0, + "Height", + 0, + "Filename", + NULL, + NULL ); +#else +#ifdef HAVE_JPEG + index_map_[VIMS_SCREENSHOT] = _new_event( + "%d %d %s", + VIMS_SCREENSHOT, + "Save output frame to file", + vj_event_screenshot, + 3, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Width", + 0, + "Height", + 0, + "Filename", + NULL, + NULL ); +#endif +#endif + index_map_[VIMS_CHAIN_TOGGLE_ALL] = _new_event( + "%d", + VIMS_CHAIN_TOGGLE_ALL, + "Enable or disable Effect Chain for ALL samples or streams", + vj_event_all_samples_chain_toggle, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "On = 1, Off= 0", + 0, + NULL ); + index_map_[VIMS_SAMPLE_UPDATE] = _new_event( + "%d %d %d", + VIMS_SAMPLE_UPDATE, + "Set sample's starting and ending position", + vj_event_sample_rel_start, + 3, + VIMS_REQUIRE_ALL_PARAMS, + SAMPLE_ID_HELP, + 0, + "Starting position", + 0, + "Ending position", + 0, + NULL ); + index_map_[VIMS_STREAM_SET_LENGTH] = _new_event( + "%d", + VIMS_STREAM_SET_LENGTH, + "Set ficticious stream length", + vj_event_stream_set_length, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Number of frames", + 0, + NULL); + index_map_[VIMS_STREAM_SET_BRIGHTNESS] = _new_event( + "%d %d", + VIMS_STREAM_SET_BRIGHTNESS, + "Set brightness value for Video4linux stream", + vj_event_v4l_set_brightness, + 2, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Value 0-65535", + 0, + NULL ); + index_map_[VIMS_STREAM_SET_CONTRAST] = _new_event( + "%d %d", + VIMS_STREAM_SET_CONTRAST, + "Set constrast value for Video4linux stream", + vj_event_v4l_set_contrast, + 2, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Value 0-65535", + 0, + NULL ); + + index_map_[VIMS_STREAM_SET_HUE] = _new_event( + "%d %d", + VIMS_STREAM_SET_BRIGHTNESS, + "Set hue value for Video4linux stream", + vj_event_v4l_set_hue, + 2, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Value 0-65535", + 0, + NULL ); + + index_map_[VIMS_STREAM_SET_COLOR] = _new_event( + "%d %d", + VIMS_STREAM_SET_COLOR, + "Set color value for Video4linux stream", + vj_event_v4l_set_color, + 2, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Value 0-65535", + 0, + NULL ); + index_map_[VIMS_STREAM_SET_SATURATION] = _new_event( + "%d %d", + VIMS_STREAM_SET_WHITE, + "Set saturation value for Video4linux stream", + vj_event_v4l_set_saturation, + 2, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Value 0-65535", + 0, + NULL ); + index_map_[VIMS_STREAM_SET_WHITE] = _new_event( + "%d %d", + VIMS_STREAM_SET_WHITE, + "Set white balance value for Video4linux stream", + vj_event_v4l_set_white, + 2, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + "Value 0-65535", + 0, + NULL ); + index_map_[VIMS_STREAM_GET_V4L] = _new_event( + "%d", + VIMS_STREAM_GET_V4L, + "GUI: Get video4linux properties", + vj_event_v4l_get_info, + 1, + VIMS_REQUIRE_ALL_PARAMS, + STREAM_ID_HELP, + 0, + NULL ); + index_map_[VIMS_VLOOPBACK_START] = _new_event( + "%d", + VIMS_VLOOPBACK_START, + "OUT: Start writing video output to a vloopback device", + vj_event_vloopback_start, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Vloopback pipe number", + 0, + NULL ); + index_map_[VIMS_VLOOPBACK_STOP] = _new_event( + NULL, + VIMS_VLOOPBACK_STOP, + "OUT: Stop writing to vloopback device", + vj_event_vloopback_stop, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_EFFECT_SET_BG] = _new_event( + NULL, + VIMS_EFFECT_SET_BG, + "Take current frame as Mask for this Effect", + vj_event_effect_set_bg, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_QUIT] = _new_event( + NULL, + VIMS_QUIT, + "Quit Veejay (caution!)", + vj_event_quit, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_CLOSE] = _new_event( + NULL, + VIMS_QUIT, + "End sessions with veejay", + vj_event_linkclose, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_SET_VOLUME] = _new_event( + "%d", + VIMS_SET_VOLUME, + "Set audio volume", + vj_event_set_volume, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Volume 0-100", + 0, + NULL ); + index_map_[VIMS_SUSPEND] = _new_event( + NULL, + VIMS_SUSPEND, + "Suspend Veejay (caution!)", + vj_event_suspend, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_DEBUG_LEVEL] = _new_event( + NULL, + VIMS_DEBUG_LEVEL, + "More/Less verbosive console output", + vj_event_debug_level, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_SYNC_CORRECTION] = _new_event( + "%d", + VIMS_SYNC_CORRECTION, + "Enable/Disable sync correction", + vj_event_sync_correction, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "0=off,1=on", + 0, + NULL ); + index_map_[VIMS_FRAMERATE] = _new_event( + "%d", + VIMS_FRAMERATE, + "Change playback engine framerate", + vj_event_set_framerate, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Multiple by 100 (ie. for 25fps, use 2500)", + 0, + NULL ); + index_map_[VIMS_BEZERK] = _new_event( + NULL, + VIMS_BEZERK, + "Bezerk mode toggle ", + vj_event_bezerk, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_NO_CACHING] = _new_event( + NULL, + VIMS_NO_CACHING, + "Editlist cache mode toggle", + vj_event_no_caching, + 0, + VIMS_ALLOW_ANY, + NULL ); + + + index_map_[VIMS_SAMPLE_MODE] = _new_event( + NULL, + VIMS_SAMPLE_MODE, + "Change between box or triangle filter for sampling purposes", + vj_event_sample_mode, + 0, + VIMS_ALLOW_ANY, + NULL ); + index_map_[VIMS_VIDEO_MCAST_START] = _new_event( + "%d", + VIMS_VIDEO_MCAST_START, + "Start built-in UDP mcast server (YUV planar)", + vj_event_mcast_start, + 1, + VIMS_ALLOW_ANY, + "0=Color,1=Grayscale (default)", + 1, + NULL ); + index_map_[VIMS_VIDEO_MCAST_STOP] = _new_event( + NULL, + VIMS_VIDEO_MCAST_STOP, + "Stop built-in UDP mcast server", + vj_event_mcast_stop, + 0, + VIMS_ALLOW_ANY , + NULL ); + index_map_[VIMS_GET_FRAME] = _new_event( + NULL, + VIMS_GET_FRAME, + "TCP: Send a frame to a connected veejay client", + vj_event_send_frame, + 0, + VIMS_ALLOW_ANY, + NULL ); + + + index_map_[ VIMS_CONTINUOUS_PLAY ] = _new_event( + "%d", + VIMS_PROJ_INC, + "Continuous sample play, do not restart samples", + vj_event_play_norestart, + 1, + VIMS_ALLOW_ANY, + "0=off (default),1=on", + 0, + NULL ); + + index_map_[ VIMS_PROJ_INC ] = _new_event( + "%d %d", + VIMS_PROJ_INC, + "Increase projection/camera point", + vj_event_projection_inc, + 2, + VIMS_ALLOW_ANY, + "X increment", + 0, + "Y increment", + 0, + NULL ); + + index_map_[ VIMS_PROJ_DEC ] = _new_event( + "%d %d", + VIMS_PROJ_DEC, + "Decrease projection/camera point", + vj_event_projection_dec, + 2, + VIMS_ALLOW_ANY, + "X increment", + 0, + "Y increment", + 0, + NULL ); + + index_map_[ VIMS_PROJ_GET_POINT ] = _new_event( + "%d", + VIMS_PROJ_GET_POINT, + "Get viewport points using scale", + vj_event_vp_get_points, + 1, + VIMS_ALLOW_ANY, + "Grid size", + 1000, + NULL ); + + index_map_[ VIMS_FRONTBACK ] = _new_event( + NULL, + VIMS_FRONTBACK, + "Camera/Projection calibration setup", + vj_event_viewport_frontback, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[ VIMS_RENDER_DEPTH ] = _new_event( + "%d", + VIMS_RENDER_DEPTH, + "Set render depth, use 1 to render chain entries 0,1 and 2 of underlying sample, use 2 to toggle on/off", + vj_event_render_depth, + 1, + VIMS_ALLOW_ANY, + "Depth switch", + "2", + NULL ); + + index_map_[ VIMS_COMPOSITE ] = _new_event( + NULL, + VIMS_COMPOSITE, + "Push current playing sample or stream as viewport input", + vj_event_viewport_composition, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[ VIMS_PROJ_TOGGLE ] = _new_event( + NULL, + VIMS_PROJ_TOGGLE, + "Enable/disable viewport rendering", + vj_event_vp_proj_toggle, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[ VIMS_PROJ_STACK ] = _new_event( + "%d %d", + VIMS_PROJ_STACK, + "Push viewport to secundary input", + vj_event_vp_stack, + 2, + VIMS_ALLOW_ANY, + "On/Off", + 1, + "Color=0, Grayscale=1", + 1, + NULL ); + + index_map_[ VIMS_PROJ_SET_POINT ] = _new_event( + "%d %d %d %d", + VIMS_PROJ_SET_POINT, + "Set a viewport point using scale", + vj_event_vp_set_points, + 4, + VIMS_REQUIRE_ALL_PARAMS, + "Point number", + 0, + "Scale factor", + 0, + "X", + 0, + "Y", + 0, + NULL ); + + +#ifdef HAVE_SDL + index_map_[VIMS_FULLSCREEN] = _new_event( + "%d", + VIMS_FULLSCREEN, + "Enable / Disable Fullscreen video output", + vj_event_fullscreen, + 1, + VIMS_ALLOW_ANY, + "On = 1, Off=0", + 1, + NULL ); +#endif + +#ifdef HAVE_FREETYPE + + index_map_[ VIMS_FONT_COL ] = _new_event( + "%d %d %d %d %d", + VIMS_FONT_COL, + "Set font color", + vj_event_font_set_color, + 5, + VIMS_REQUIRE_ALL_PARAMS, + "Red", + 0, + "Green", + 0, + "Blue", + 0, + "Alpha", + 0, + "0=Transparent 1=BG 2=FG", + 0, + NULL ); + + index_map_[ VIMS_FONT_POS ] = _new_event( + "%d %d", + VIMS_FONT_POS, + "Set font position", + vj_event_font_set_position, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "X position", + 0, + "Y position", + 0, + NULL ); + + index_map_[ VIMS_FONT_SIZE_FONT ] = _new_event( + "%d %d", + VIMS_FONT_SIZE_FONT, + "Set font type and font size", + vj_event_font_set_size_and_font, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Font type", + 0, + "Font size", + 0, + NULL ); + + index_map_[ VIMS_OSD_EXTRA ] = _new_event( + NULL, + VIMS_OSD_EXTRA, + "Print help in OSD (if available)", + vj_event_toggle_osd_extra, + 0, + VIMS_ALLOW_ANY, + NULL + ); + + index_map_[ VIMS_COPYRIGHT ] = _new_event( + NULL, + VIMS_OSD, + "Print copyright", + vj_event_toggle_copyright, + 0, + VIMS_ALLOW_ANY, + NULL + ); + + index_map_[ VIMS_OSD ] = _new_event( + NULL, + VIMS_OSD, + "Toggle OSD status", + vj_event_toggle_osd, + 0, + VIMS_ALLOW_ANY, + NULL + ); + + index_map_[ VIMS_SRT_ADD ] = _new_event( + "%d %d %d %d %d %s", + VIMS_SRT_ADD, + "Add a subtitle sequence", + vj_event_add_subtitle, + 6, + VIMS_LONG_PARAMS | VIMS_REQUIRE_ALL_PARAMS, + "Subtitle sequence (0=new)", + 0, + "Start position", + 0, + "End position", + 0, + "X position", + 0, + "Y position", + 0, + "Text", + NULL, + NULL ); + + index_map_[ VIMS_SRT_SELECT ] = _new_event( + "%d", + VIMS_SRT_SELECT, + "Select a subtitle sequence", + vj_event_select_subtitle, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Subtitle sequence", + 0, + NULL ); + + index_map_[ VIMS_SRT_DEL ] = _new_event( + "%d", + VIMS_SRT_DEL, + "Delete a subtitle sequence", + vj_event_del_subtitle, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Subtitle sequence", + 0, + NULL ); + + index_map_[ VIMS_SRT_UPDATE ] = _new_event( + "%d %d %d %s", + VIMS_SRT_UPDATE, + "Update a subtitle sequence", + vj_event_upd_subtitle, + 4, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + "Subtitle sequence", + 0, + "Start position", + 0, + "End position", + 0, + "Text", + NULL, + NULL ); + + index_map_[ VIMS_SRT_SAVE ] = _new_event( + "%s", + VIMS_SRT_SAVE, + "Export subtitles to SRT", + vj_event_save_srt, + 1, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + "Filename", + NULL, + NULL ); + index_map_[ VIMS_SRT_LOAD ] = _new_event( + "%s", + VIMS_SRT_LOAD, + "Import subtitles from SRT", + vj_event_load_srt, + 1, + VIMS_REQUIRE_ALL_PARAMS | VIMS_LONG_PARAMS, + "Filename", + NULL, + NULL ); + + index_map_[VIMS_FONT_LIST] = _new_event( + NULL, + VIMS_FONT_LIST, + "GUI: Get list of loaded fonts", + vj_event_get_font_list, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SRT_LIST] = _new_event( + NULL, + VIMS_SRT_LIST, + "GUI: Get list of loaded subtitle sequences", + vj_event_get_srt_list, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[VIMS_SRT_INFO] = _new_event( + "%d", + VIMS_SRT_INFO, + "GUI: Get subtitle sequence", + vj_event_get_srt_info, + 1, + VIMS_ALLOW_ANY, + "Subtitle sequence", + 1, + NULL ); + + + index_map_[ VIMS_SEQUENCE_LIST ] = _new_event( + NULL, + VIMS_SRT_INFO, + "GUI: Get list of sample sequences", + vj_event_get_sample_sequences, + 0, + VIMS_ALLOW_ANY, + NULL ); + + index_map_[ VIMS_SEQUENCE_STATUS ] = _new_event( + "%d", + VIMS_SEQUENCE_STATUS, + "Set sequence play on or off", + vj_event_sample_sequencer_active, + 1, + VIMS_ALLOW_ANY, + "Status 0=off,1=on", + 0, + NULL ); + + index_map_[ VIMS_SEQUENCE_ADD ] = _new_event( + "%d %d", + VIMS_SEQUENCE_ADD, + "Add a sample to the sequence", + vj_event_sequencer_add_sample, + 2, + VIMS_REQUIRE_ALL_PARAMS, + "Seq ID", + 0, + "Sample ID", + 0, + NULL ); + + index_map_[ VIMS_SEQUENCE_DEL ] = _new_event( + "%d", + VIMS_SEQUENCE_DEL, + "Del sample from sequence slot", + vj_event_sequencer_del_sample, + 1, + VIMS_REQUIRE_ALL_PARAMS, + "Seq ID", + 0, + NULL ); + + +#endif +} + + + diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-font.c b/branches/V-1.5.3/veejay-server/veejay/vj-font.c new file mode 100644 index 00000000..c0692db8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-font.c @@ -0,0 +1,2472 @@ +/* + * drawtext.c: print text over the screen + * heavily modified to serve as font renderer in veejay + ****************************************************************************** + * Author: Gustavo Sverzut Barbieri + * Niels Elburg (Nov. 2006-2008) + * + * 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 +#include +#include +#include +#include +#ifdef HAVE_XML2 +#include +#include +#endif + +extern int vj_tag_size(); + +#ifdef STRICT_CHECKING +#include +#endif + +#ifdef HAVE_FREETYPE +#include +#include +#include +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#define BSIZE 256 + +typedef struct +{ + int id; + char *text; + long start; + long end; + unsigned int x; + unsigned int y; + int size; + int font; + char *key; + int time; + uint8_t bg[3]; + uint8_t fg[3]; + uint8_t ln[3]; + uint8_t alpha[3]; + int use_bg; + int outline; +} srt_seq_t; + + +typedef struct +{ + int id[16]; +} srt_cycle_t; + +typedef struct { + unsigned char *text; + unsigned char *font; + uint8_t *fd_buf; + unsigned int w; + unsigned int h; + unsigned int x; + unsigned int y; + int bg; + int outline; + uint8_t alpha[3]; + + uint8_t bgcolor[3]; + uint8_t fgcolor[3]; + uint8_t lncolor[3]; + + FT_Library library; + FT_Face face; + FT_Glyph glyphs[ BSIZE ]; + FT_Bitmap bitmaps[ BSIZE ]; + int advance[ BSIZE ]; + int bitmap_left[ BSIZE ]; + int bitmap_top[ BSIZE ]; + unsigned int glyphs_index[ BSIZE ]; + int text_height; + int text_width; + int current_font; + int baseline; + int use_kerning; + int current_size; + char **font_table; + char **font_list; + int auto_number; + int font_index; + long index_len; + srt_seq_t **index; + float fps; + void *dictionary; + void *plain; + char *add; + char *prev; + pthread_mutex_t mutex; + srt_cycle_t *text_buffer; + uint32_t text_max_size; +} vj_font_t; + +static int configure(vj_font_t *f, int size, int font); +static char *make_key(int id); +static char *vj_font_pos_to_timecode( vj_font_t *font, long pos ); +static long vj_font_timecode_to_pos( vj_font_t *font, const char *tc ); +static srt_seq_t *vj_font_new_srt_sequence(vj_font_t *font, int id,char *text, long lo, long hi ); +static void vj_font_del_srt_sequence( vj_font_t *f, int seq_id ); +static void vj_font_store_srt_sequence( vj_font_t *f, srt_seq_t *s ); +static int font_selector( const struct dirent *dir ); +static int find_fonts(vj_font_t *ec, char *path); +static void print_fonts(vj_font_t *ec); +static char *select_font( vj_font_t *ec, int id ); +static void vj_font_substract_timecodes( vj_font_t *font, const char *tc_srt, long *lo, long *hi ); +static char *vj_font_split_strd( const char *str ); +static char *vj_font_split_str( const char *str ); + +static char *get_font_name( vj_font_t *f,const char *font, int id ); +static int get_default_font( vj_font_t *f ); + +static int test_font( vj_font_t *f , const char *font, int id); + +static void font_lock(vj_font_t *f) +{ + pthread_mutex_lock( &(f->mutex) ); +} +static void font_unlock( vj_font_t *f ) +{ + pthread_mutex_unlock( &(f->mutex) ); +} + +static char *make_key(int id) +{ + char key[32]; + sprintf(key,"s%d",id); + return strdup(key); +} + + +int vj_font_prepare( void *font, long s1, long s2 ) +{ + vj_font_t *f = (vj_font_t*) font; + char **list = vevo_list_properties( f->dictionary ); + int i; + int N = 0; + + if(f->index) + free(f->index); + f->index = NULL; + f->index_len = 0; + + if( list == NULL ) + return 0; + + for( i = 0; list[i] != NULL ; i ++ ) + N++; +/* + long min = s1; + long max = s2; + for( i = 0; list[i] != NULL ; i ++ ) { + void *srt = NULL; + int error = vevo_property_get( f->dictionary, list[i], 0, &srt ); + if( error != VEVO_NO_ERROR ) + continue; + + srt_seq_t *s = (srt_seq_t*) srt; + if( s->start < min ) + min = start; + if( s->end > max ) + max = s->end; + } + + s1 = min; + s2 = max;*/ + + + if( N == 0 ) + return 0; + + f->index = (srt_seq_t**) vj_calloc(sizeof(srt_seq_t*) * N ); + f->index_len = N; + for( i = 0; list[i] != NULL ; i ++ ) { + void *srt = NULL; + int error = vevo_property_get( f->dictionary, list[i], 0, &srt ); + if( error == VEVO_NO_ERROR ) + { + srt_seq_t *s = (srt_seq_t*) srt; + if( s->start > s1 ) + s->start = s1; + if( s->end > s2 ) + s->end = s2; + f->index[i] = s; + } else { + f->index[i] = NULL; + } + free(list[i]); + } + + free(list); + return N; +} + +int vj_font_srt_sequence_exists( void *font, int id ) +{ + if(!font) + return 0; + vj_font_t *f = (vj_font_t*) font; + if(!f->dictionary ) + return 0; + +#ifdef STRICT_CHECKING + assert( f->dictionary != NULL ); +#endif + char *key = make_key(id); + void *srt = NULL; + int error = vevo_property_get( f->dictionary, key,0,&srt ); + free(key); + if( error == VEVO_NO_ERROR ) + return 1; + return 0; +} + +static char *vj_font_pos_to_timecode( vj_font_t *font, long pos ) +{ + vj_font_t *ff = (vj_font_t*) font; + MPEG_timecode_t tc; + veejay_memset(&tc, 0,sizeof(MPEG_timecode_t)); + char tmp[20]; + + y4m_ratio_t ratio = mpeg_conform_framerate( ff->fps ); + int n = mpeg_framerate_code( ratio ); + + mpeg_timecode(&tc, pos, n, ff->fps ); + + snprintf(tmp, 20, "%2d:%2.2d:%2.2d:%2.2d", + tc.h, tc.m, tc.s, tc.f ); + + return strdup(tmp); +} + +static long vj_font_timecode_to_pos( vj_font_t *font, const char *tc ) +{ + int t[4]; + + sscanf( tc, "%1d:%02d:%02d:%02d", &t[0],&t[1],&t[2],&t[3] ); + + long res = 0; + + res = (long) t[3]; + res += (long) t[2] * font->fps; + res += (long) t[1] * font->fps * 60.0; + res += (long) t[0] * font->fps * 3600.0; + + return res; +} + +static void vj_font_substract_timecodes( vj_font_t *font, const char *tc_srt, long *lo, long *hi ) +{ + char tc1[20]; + char tc2[20]; + veejay_memset(tc1,0,sizeof(tc1)); + veejay_memset(tc2,0,sizeof(tc2)); + + sscanf( tc_srt, "%s %*s %s", tc1,tc2 ); + + *lo = vj_font_timecode_to_pos( font, tc1 ); + *hi = vj_font_timecode_to_pos( font, tc2 ); +} + +static char *vj_font_split_strd( const char *str ) +{ + const char *p = str; + char *res = NULL; + int i = 0; + while( *p != '\0' && *p != '\n' ) + { + *p ++; + i++; + } + if(*p == '\n') + { + *p ++; + i ++; + } + if(*p == '\n' ) + { + *p ++; + i ++; + } + else + { + return NULL; + } + + if( i <= 0 ) + return NULL; + + res = strndup( str, i ); + return res; +} + +static char *vj_font_split_str( const char *str ) +{ + const char *p = str; + char *res = NULL; + int i = 0; + while( *p != '\0' && *p != '\n' ) + { + *p ++; + i++; + } + if(*p == '\n') + { + *p ++; + i ++; + } + if( i <= 0 ) + return NULL; + + res = strndup( str, i ); + return res; +} + +static srt_seq_t *vj_font_new_srt_sequence( vj_font_t *f,int id,char *text, long lo, long hi ) +{ + char tmp_key[16]; + srt_seq_t *s = (srt_seq_t*) vj_calloc(sizeof( srt_seq_t )); + s->id = id; + s->text = strdup( text ); + s->start = lo; + s->end = hi; + sprintf(tmp_key, "s%d", id ); + s->bg[0] = 0; + s->bg[1] = 0; + s->bg[2] = 0; + s->fg[0] = 255; + s->fg[1] = 255; + s->fg[2] = 255; + s->ln[0] = 200; + s->ln[1] = 255; + s->ln[2] = 255; + s->alpha[0] = 0; + s->alpha[1] = 0; + s->alpha[2] = 0; + s->use_bg = 0; + s->outline = 0; + s->size = 40; + s->font = get_default_font(f); + s->key = strdup(tmp_key); + + veejay_msg(VEEJAY_MSG_DEBUG, + "New SRT sequence: '%s' starts at position %ld , ends at position %ld", + text,lo,hi ); + + return s; +} + +void vj_font_set_current( void *font , int cur ) +{ + vj_font_t *f = (vj_font_t*) font; + if(vj_font_srt_sequence_exists( font, cur )) + { + f->auto_number = cur; + } + +} + +static void vj_font_del_srt_sequence( vj_font_t *f, int seq_id ) +{ +#ifdef STRICT_CHECKING + assert( f->dictionary != NULL ); +#endif + if(seq_id == 0 ) + seq_id = f->auto_number; + + char *key = make_key(seq_id ); + void *srt = NULL; + + + int error = vevo_property_get( f->dictionary, key, 0, &srt ) ; + if( error == VEVO_NO_ERROR ) + { + srt_seq_t *s = (srt_seq_t*) srt; + free(s->text); + free(s->key); + free(s); + vevo_property_set( f->dictionary, key, VEVO_ATOM_TYPE_VOIDPTR, 0,NULL ); + + } + free(key); +} + +static void vj_font_store_srt_sequence( vj_font_t *f, srt_seq_t *s ) +{ +#ifdef STRICT_CHECKING + assert( f->dictionary != NULL ); +#endif + void *srt = NULL; + int error = vevo_property_get( f->dictionary, s->key, 0, &srt ); + if( error == VEVO_NO_ERROR ) + { + srt_seq_t *old = (srt_seq_t*) srt; + + veejay_msg(VEEJAY_MSG_DEBUG, "replacing subtitle %d, '%s', %ld -> %ld", + old->id, old->text,old->start,old->end ); + free(old->text); + free(old->key); + free(old); + } + + error = vevo_property_set( f->dictionary, s->key, VEVO_ATOM_TYPE_VOIDPTR, 1,&s ); + if( error != VEVO_NO_ERROR ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to store SRT sequence '%s'", s->key ); + } +} + +int vj_font_load_srt( void *font, const char *filename ) +{ + vj_font_t *ff = (vj_font_t*) font; + FILE *f = fopen( filename, "r" ); + unsigned int len = 0; + unsigned int i; + if(!f) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to load SRT file '%s'",filename ); + return 0; + } + fseek( f, 0, SEEK_END ); + len = ftell( f ); + + if( len <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "SRT file '%s' is empty", filename ); + return 0; + } + rewind( f ); + + ff->fd_buf = (uint8_t*) vj_calloc( len ); + fread( ff->fd_buf, len,1, f ); + + fclose( f ); + + //parse the file + uint8_t *str = ff->fd_buf; + int offset = 0; + + + font_lock( ff ); + while( offset < len ) + { + char *line = vj_font_split_str( str ); + if(!line) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to parse sequence ID in srt file"); + font_unlock( ff ); + return 0; + } + int n = strlen( line ); + + offset += n; + str += n; + + char *timecode = vj_font_split_str( str ); + if(!timecode) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to parse timecode in srt file"); + font_unlock(ff); + return 0; + } + n = strlen( timecode ); + + offset += n; + str += n; + + char *text = vj_font_split_strd ( str ); + if(!text) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to parse subtitle text in srt file"); + font_unlock(ff); + return 0; + } + n = strlen ( text ); + + offset += n; + str += n; + + long lo=0,hi=0; + int seq_id = atoi( line ); + + vj_font_substract_timecodes( ff, timecode, &lo, &hi ); + + if( lo == hi ) + { + veejay_msg(VEEJAY_MSG_ERROR, "It makes no sense to create a subtitle sequence with length 0"); + font_unlock(ff); + return 0; + } + + srt_seq_t *s = vj_font_new_srt_sequence(ff, seq_id, text, lo,hi ); + + vj_font_store_srt_sequence( ff, s ); + + free(line); + free(timecode); + free(text); + } + font_unlock( ff ); + + free( ff->fd_buf ); + + return 1; +} +static int get_xml_int( xmlDocPtr doc, xmlNodePtr node ) +{ + xmlChar *tmp = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 ); + char *ch = UTF8toLAT1( tmp ); + int res = 0; + if( ch ) + { + res = atoi( ch ); + free(ch); + } + if(tmp) + free(tmp); + return res; +} + +static void get_xml_3int( xmlDocPtr doc, xmlNodePtr node, int *first , int *second, int *third ) +{ + xmlChar *tmp = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 ); + char *ch = UTF8toLAT1( tmp ); + if( ch ) + { + sscanf( ch, "%d %d %d" , first, second, third ); + free(ch); + } + if(tmp) + free(tmp); +} + + +void vj_font_xml_unpack( xmlDocPtr doc, xmlNodePtr node, void *font ) +{ + if(!node) + return; + vj_font_t *f = (vj_font_t*) font; + + int x=0,y=0,id=0,size=0,type=0, use_bg=0, outline=0; + int bg[3] = {0,0,0}; + int fg[3] = {0,0,0}; + int alpha[3] = {0,0,0}; + int ln[3] = {0,0,0}; + + while( node != NULL ) + { + if( !xmlStrcmp( node->name, (const xmlChar*) "srt_id" )) + id = get_xml_int( doc, node ); + if( !xmlStrcmp( node->name, (const xmlChar*) "x_pos" )) + x = get_xml_int( doc,node ); + if( !xmlStrcmp( node->name, (const xmlChar*) "y_pos" )) + y = get_xml_int( doc, node ); + if( !xmlStrcmp( node->name, (const xmlChar*) "font_size" )) + size = get_xml_int(doc,node); + if( !xmlStrcmp( node->name, (const xmlChar*) "font_family" )) + type = get_xml_int( doc, node ); + if( !xmlStrcmp( node->name, (const xmlChar*) "bg" )) + get_xml_3int( doc, node, &bg[0], &bg[1], &bg[2] ); + if( !xmlStrcmp( node->name, (const xmlChar*) "fg" )) + get_xml_3int( doc, node, &fg[0], &fg[1], &fg[2] ); + if( !xmlStrcmp( node->name, (const xmlChar*) "ln" )) + get_xml_3int( doc, node, &ln[0], &ln[1], &ln[2] ); + if( !xmlStrcmp( node->name, (const xmlChar*) "alpha" )) + get_xml_3int( doc, node, &alpha[0], &alpha[1], &alpha[2] ); + if( !xmlStrcmp( node->name, (const xmlChar*) "use_bg" )) + use_bg = get_xml_int( doc, node ); + if( !xmlStrcmp( node->name, (const xmlChar*) "use_outline" )) + outline = get_xml_int(doc,node); + + node = node->next; + } + + char *key = make_key( id ); + srt_seq_t *s = NULL; + if( vevo_property_get( f->dictionary, key, 0, &s ) == VEVO_NO_ERROR ) + { + s->x = x; s->y = y; s->size = size; s->font = type; + s->use_bg = use_bg; s->outline = outline; + s->bg[0] = bg[0]; s->bg[1] = bg[1]; s->bg[2] = bg[2]; + s->fg[0] = fg[0]; s->fg[1] = fg[1]; s->fg[2] = fg[2]; + s->ln[0] = ln[0]; s->ln[1] = ln[1]; s->ln[2] = ln[2]; + s->alpha[0] = alpha[0]; + s->alpha[1] = alpha[1]; + s->alpha[2] = alpha[2]; + } + else + { + veejay_msg(VEEJAY_MSG_DEBUG, "Sequence %d (%s) not in .srt file (tried dictionary %p)", id,key, f->dictionary ); + } + free(key); + +} + +void vj_font_xml_pack( xmlNodePtr node, void *font ) +{ + vj_font_t *ff = (vj_font_t*) font; + if(ff == NULL ) + return; + + char **items = vevo_list_properties ( ff->dictionary ); + if(!items) + return; +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + + char buf[100]; + int i; + for( i = 0; items[i] != NULL ; i ++ ) + { + void *srt = NULL; + if ( vevo_property_get( ff->dictionary, items[i], 0, &srt ) == VEVO_NO_ERROR ) + { + srt_seq_t *s = (srt_seq_t*) srt; + + xmlNodePtr childnode = xmlNewChild( node, NULL, (const xmlChar*) "SUBTITLES" , NULL ); + + sprintf(buf, "%d", s->id ); + xmlNewChild(childnode, NULL, (const xmlChar*) "srt_id", (const xmlChar*) buf ); + + sprintf(buf, "%d",s->x ); + xmlNewChild(childnode, NULL, (const xmlChar*) "x_pos", (const xmlChar*) buf ); + + sprintf(buf, "%d", s->y ); + xmlNewChild(childnode, NULL, (const xmlChar*) "y_pos", (const xmlChar*) buf ); + + sprintf(buf, "%d", s->size ); + xmlNewChild(childnode, NULL, (const xmlChar*) "font_size", (const xmlChar*) buf ); + + sprintf(buf, "%d", s->font ); + xmlNewChild(childnode, NULL, (const xmlChar*) "font_family", (const xmlChar*) buf ); + + sprintf(buf, "%d %d %d", s->bg[0],s->bg[1],s->bg[2] ); + xmlNewChild(childnode, NULL, (const xmlChar*) "bg" , (const xmlChar*) buf ); + + sprintf(buf, "%d %d %d", s->fg[0], s->fg[1], s->fg[2] ); + xmlNewChild(childnode, NULL, (const xmlChar*) "fg", (const xmlChar*) buf ); + + sprintf(buf, "%d %d %d", s->ln[0], s->ln[1], s->ln[2] ); + xmlNewChild(childnode,NULL, (const xmlChar*) "ln", (const xmlChar*) buf ); + + sprintf(buf, "%d %d %d", s->alpha[0], s->alpha[1],s->alpha[2] ); + xmlNewChild(childnode, NULL, (const xmlChar*) "alpha", (const xmlChar*) buf ); + + sprintf(buf, "%d", s->use_bg ); + xmlNewChild(childnode, NULL, (const xmlChar*) "use_bg", (const xmlChar*) buf ); + + sprintf(buf, "%d", s->outline ); + xmlNewChild(childnode, NULL, (const xmlChar*) "use_outline", (const xmlChar*) buf ); + + + } + free(items[i]); + } + free(items); +} + + +int vj_font_save_srt( void *font , const char *filename ) +{ + vj_font_t *ff = (vj_font_t*) font; + if( ff == NULL ) + return 0; + + char **items = vevo_list_properties ( ff->dictionary ); + if(!items) + { + veejay_msg(0, "No subtitle sequences present, nothing to save"); + return 0; + } + int i; + FILE *f = fopen( filename , "w" ); + if(!f) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot open file '%s' for writing", filename ); + return 0; + } +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + for( i = 0; items[i] != NULL ; i ++ ) + { + void *srt = NULL; + if ( vevo_property_get( ff->dictionary, items[i], 0, &srt ) == VEVO_NO_ERROR ) + { + srt_seq_t *s = (srt_seq_t*) srt; + int n = strlen(s->text); + if( n > 0 ) + { + char *tc1 = vj_font_pos_to_timecode( ff, s->start ); + char *tc2 = vj_font_pos_to_timecode( ff, s->end ); + fprintf( f, "%d\n%s --> %s\n%s\n\n", + s->id, + tc1, + tc2, + s->text ); + free(tc1); + free(tc2); + } + } + free(items[i]); + } + free(items); + fclose( f ); + + veejay_msg(VEEJAY_MSG_DEBUG, "Saved %d subtitles to %s", i, filename ); + + return 1; +} + +char *vj_font_get_sequence( void *font, int seq ) +{ + vj_font_t *ff = (vj_font_t*) font; + char tmp[1024]; + srt_seq_t *s = NULL; + void *srt = NULL; + + if( seq == 0 ) + seq = ff->auto_number; + char *key = make_key( seq ); + +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + if( vevo_property_get( ff->dictionary, key, 0, &srt ) != VEVO_NO_ERROR ) + return NULL; + + s = (srt_seq_t*) srt; + + int tcl1, tcl2; + char *tc1 = vj_font_pos_to_timecode( ff, s->start ); + char *tc2 = vj_font_pos_to_timecode( ff, s->end ); + int len = strlen(s->text); + tcl1 = strlen(tc1); + tcl2 = strlen(tc2); + + uint8_t bg[3]; + uint8_t fg[3]; + + + sprintf( tmp, "%05d%09d%09d%02d%s%02d%s%03d%s%04d%04d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d%03d", + s->id, + (int)s->start, + (int)s->end, + tcl1, + tc1, + tcl2, + tc2, + len, + s->text, + s->x, + s->y, + s->font, + s->size, + s->bg[0], + s->bg[1], + s->bg[2], + s->fg[0], + s->fg[1], + s->fg[2], + s->use_bg, + s->outline, + s->ln[0], + s->ln[1], + s->ln[2], + s->alpha[0], + s->alpha[1], + s->alpha[2]); + + free(tc1); + free(tc2); + free(key); + return strdup(tmp); +} + +int vj_font_new_text( void *font, char *text, long lo,long hi, int seq) +{ + vj_font_t *ff = (vj_font_t*) font; + if( lo == hi ) + { + veejay_msg(VEEJAY_MSG_ERROR, "It makes no sense to make a subtitle of length 0" ); + return 0; + } + + if(seq == 0 ) + { + int an = ff->auto_number; + while( vj_font_srt_sequence_exists( font, an ) ) + an++; + ff->auto_number = an; + veejay_msg(VEEJAY_MSG_DEBUG, "New subtitle sequence %d", an ); + seq = ff->auto_number; + } + + font_lock( ff ); + + srt_seq_t *s = vj_font_new_srt_sequence(ff, seq, text, lo,hi ); + + vj_font_store_srt_sequence( ff, s ); + + font_unlock(ff); + + return seq; +} +void vj_font_del_text( void *font, int seq ) +{ + vj_font_t *ff = (vj_font_t*) font; + ff->auto_number = seq; + font_lock( ff ); + vj_font_del_srt_sequence( ff, seq); + font_unlock( ff ); +} + +void vj_font_set_position( void *font, int x, int y ) +{ + vj_font_t *ff = (vj_font_t*) font; + int seq = ff->auto_number; + + char *key = make_key( seq ); + +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + srt_seq_t *s = NULL; + if( vevo_property_get( ff->dictionary, key, 0, &s ) != VEVO_NO_ERROR ) + { + free(key); + return; + } + font_lock( ff ); + + s->x = x; + s->y = y; + + font_unlock( ff ); + free(key); +} + +void vj_font_set_size_and_font( void *font, int f_id, int size ) +{ + vj_font_t *ff = (vj_font_t*) font; + if( f_id < 0 || f_id >= ff->font_index || size < 6 || size > 400 ) + return ; + int seq = ff->auto_number; + + char *key = make_key( seq ); + +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + srt_seq_t *s = NULL; + if( vevo_property_get( ff->dictionary, key, 0, &s ) != VEVO_NO_ERROR ) + { + free(key); + return; + } + + font_lock( ff ); + + s->font = f_id; + s->size = size; + + veejay_msg(VEEJAY_MSG_DEBUG, "Selected font '%s', size %d", + ff->font_list[s->font], s->size ); + + font_unlock( ff ); + + free(key); +} + +void vj_font_update_text( void *font, long s1, long s2, int seq, char *text) +{ + vj_font_t *ff = (vj_font_t*) font; + srt_seq_t *s = NULL; + void *srt = NULL; + if(seq == 0 ) + seq = ff->auto_number; + char *key = make_key( seq ); +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + int error = vevo_property_get( ff->dictionary, key, 0, &srt ); + if( error != VEVO_NO_ERROR ) + { + veejay_msg(0, "No such subtitle '%s'",key); + free(key); + return; + } + else { + veejay_msg(0, "Update subtitle %s to '%s' , play from %ld to %ld", + key,text,s1,s2); + } + + if(s1 < 0 ) s1 = 0; + if(s2 < 0 ) s2 = 0; + + if( (s2-s1) > ff->index_len || ff->index_len <= 0 ) { + if(!vj_font_prepare( ff,s1,s2 ) ) { + while(s2<=s1) + s2++; + if(!vj_font_prepare(ff,s1,s2)) { + veejay_msg(0, "Error updating subtitle %s",key); + free(key); + return; + } + } + } + + + s = (srt_seq_t*) srt; + font_lock( ff ); + if( s->text ) + free(s->text); + s->text = strdup( text ); + s->start = s1; + s->end = s2; + + ff->auto_number = seq; + + font_unlock( ff ); + free(key); +} + +char **vj_font_get_sequences( void *font ) +{ + vj_font_t *f = (vj_font_t*) font; + char **items = vevo_list_properties( f->dictionary ); + if(!items) + return NULL; + int i; + int j=0; + int len=0; + + for( i = 0; items[i] != NULL ; i ++ ) + len ++; + + if( len <= 0 ) + return NULL; + + char **res = (char**) vj_calloc(sizeof(char*) * (len+1)); + for( i = 0; items[i] != NULL ; i ++ ) + { + srt_seq_t *s = NULL; + if( vevo_property_get( f->dictionary, items[i], 0,&s ) == VEVO_NO_ERROR ) + { + char tmp[16]; + sprintf(tmp, "%d", s->id ); + res[j] = strdup(tmp); + j++; + } + free(items[i]); + + } + free(items); + if( j == 0 ) + { + free(res); + return NULL; + } + + return res; +} + +#define MAX_FONTS 250 + +char **vj_font_get_all_fonts( void *font ) +{ + vj_font_t *f = (vj_font_t*) font; + int i; + if( f->font_index <= 0 ) + return NULL; + + char **res = (char**) vj_calloc(sizeof(char*) * (f->font_index +1) ); + for( i =0; i < f->font_index ;i ++ ) + res[i] = strdup( f->font_list[i] ); + return res; +} + +static int font_selector( const struct dirent *dir ) +{ + if(strstr(dir->d_name, ".ttf" )) return 1; + if(strstr(dir->d_name, ".TTF" )) return 1; +// if(strstr(dir->d_name, ".pfa" )) return 1; +// if(strstr(dir->d_name, ".pcf.gz" )) return 1; + return 0; +} + +static int dir_selector( const struct dirent *dir ) +{ + return 1; +} + +static int is_ttf( const char *file ) +{ + if(strstr( file, ".ttf" ) || strstr( file, ".TTF" ) || strstr( file, "PFA" ) || + strstr(file, "pfa" ) || strstr( file, "pcf" ) || strstr( file, "PCF" ) ) + return 1; + return 0; +} + +static int try_deepen( vj_font_t *f , char *path ) +{ + int n = 0; + if(!path) return 0; + + struct stat l; + memset( &l, 0, sizeof(struct stat) ); + if( lstat( path, &l ) < 0 ) + return 0; + + if( S_ISLNK( l.st_mode ) ) + { + memset(&l,0,sizeof(struct stat)); + stat( path, &l ); + } + + if( S_ISDIR( l.st_mode )) + { + return 1; + } + + if( S_ISREG( l.st_mode )) + { + if( is_ttf( path ) ) + { + if( f->font_index < MAX_FONTS ) + { + char *try_font = strdup(path); + if( get_font_name( f,try_font, f->font_index ) ) { + f->font_table[f->font_index] = try_font; + f->font_index ++; + } else { + free(try_font); + } + /* + if( fnname ) { + veejay_msg(VEEJAY_MSG_INFO, "FontName ='%s'",fnname ); + + }else { + veejay_msg(0, "Error '%s'",try_font); + } + + + if( test_font (f, try_font, f->font_index) ) + { + f->font_table[ f->font_index ] = try_font; + f->font_index ++; + } + else + { + free(try_font); + }*/ + } + } + } + return 0; +} + +static int find_fonts(vj_font_t *ec, char *path) +{ + struct dirent **files; + int n = scandir(path, &files, dir_selector,alphasort); + + if(n < 0) + return 0; + + while( n -- ) + { + char tmp[1024]; + snprintf( tmp, 1024, "%s/%s", path, files[n]->d_name ); + if( strcmp( files[n]->d_name , "." ) != 0 && + strcmp( files[n]->d_name, ".." ) != 0 ) + { + if(try_deepen( ec, tmp )) + find_fonts( ec, tmp ); + } + free( files[n] ); + } + free(files); + return 1; +} + +static char *select_font( vj_font_t *ec, int id ) +{ + if( id < 0 || id >= ec->font_index ) + return NULL; + + return ec->font_table[id]; +} + + +static char *get_font_name( vj_font_t *f,const char *font, int id ) +{ + int len = 0; + char *string; + int platform,encoding,lang; + int error; + + static char *fontName = NULL; + static int fontLen = 256; + + if( fontName == NULL ) { + fontName = (char*) vj_malloc(sizeof(char) * fontLen ); + } + if( fontName == NULL ) { + return NULL; + } + + FT_SfntName sn,qn,zn; + FT_SfntName sname; + FT_UInt snamei,snamec; + + FT_Face face; + if ( (error = FT_New_Face( f->library, font, 0, &face )) != 0) + { + return 0; + } + + memset( &qn, 0,sizeof( FT_SfntName ) ); + memset( &zn, 0, sizeof( FT_SfntName )); + memset( &sn, 0, sizeof( FT_SfntName )); + + snamec = FT_Get_Sfnt_Name_Count(face); + + int found = 0; + int tlen = 0; + for(snamei=0;snamei fontLen ) { + fontLen *= 2; + fontName = (char*) realloc( fontName, fontLen ); + if( fontName == NULL ) { + return NULL; + } + } + + int i,k; + + for( i=0; i < tlen; i +=2 ) { + fontName[i/2] = string[i+1]; + } + fontName[tlen/2] = '\0'; + + f->font_list[id] = strdup( fontName ); + + return fontName; +} + +static int test_font( vj_font_t *f , const char *font, int id) +{ + char name[1024]; + FT_Face face; + int error; + FT_SfntName sn,qn,zn; + FT_SfntName sname; + FT_UInt snamei,snamec; + char *name1 = NULL; + char *name2 = NULL; + + if ( (error = FT_New_Face( f->library, font, 0, &face )) != 0) + { + return 0; + } + + memset( &qn, 0,sizeof( FT_SfntName ) ); + memset( &zn, 0, sizeof( FT_SfntName )); + memset( &sn, 0, sizeof( FT_SfntName )); + +// FT_Get_Sfnt_Name( face, TT_NAME_ID_FONT_FAMILY, &qn ); + + snamec = FT_Get_Sfnt_Name_Count(face); + + for(snamei=0;snamei 150) + { + FT_Done_Face(face); + free(name1); + free(name2); + return 0; + } + + snprintf( name,1024,"%s (%s)", name1, name2); + + f->font_list[id] = strdup( name ); + + free(name1); + free(name2); + + FT_Done_Face( face ); + return 1; +} + + + +static void print_fonts(vj_font_t *ec) +{ + int i; + for(i =0 ; i < ec->font_index ; i ++ ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "[%03d] : [%s]", + i, ec->font_list[i] ); + } +} + + +void vj_font_set_outline_and_border( void *font, int outline, int border) +{ + vj_font_t *ff = (vj_font_t*) font; + + int seq = ff->auto_number; + char *key = make_key( seq ); + +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + srt_seq_t *s = NULL; + if( vevo_property_get( ff->dictionary, key, 0, &s ) != VEVO_NO_ERROR ) + { + free(key); + return; + } + font_lock( ff ); + + s->use_bg = border; + s->outline = outline; + + font_unlock( ff ); + + free(key); +} + +void vj_font_set_lncolor( void *font, int r, int g, int b, int a) +{ + vj_font_t *f = (vj_font_t*) font; + + int seq = f->auto_number; + + char *key = make_key( seq ); + +#ifdef STRICT_CHECKING + assert( f->dictionary != NULL ); +#endif + srt_seq_t *s = NULL; + if( vevo_property_get( f->dictionary, key, 0, &s ) != VEVO_NO_ERROR ) + { + free(key); + return; + } + font_lock( f ); + + s->ln[0] = r; + s->ln[1] = g; + s->ln[2] = b; + s->alpha[2] = a; + + font_unlock( f ); + + free(key); +} + +void vj_font_set_bgcolor( void *font, int r, int g, int b,int a) +{ + vj_font_t *f = (vj_font_t*) font; + + int seq = f->auto_number; + + char *key = make_key( seq ); + +#ifdef STRICT_CHECKING + assert( f->dictionary != NULL ); +#endif + srt_seq_t *s = NULL; + if( vevo_property_get( f->dictionary, key, 0, &s ) != VEVO_NO_ERROR ) + { + free(key); + return; + } + font_lock( f ); + + s->bg[0] = r; + s->bg[1] = g; + s->bg[2] = b; + s->alpha[1] = a; + + font_unlock( f ); + + free(key); +} + + +void vj_font_set_fgcolor( void *font, int r, int g, int b, int a) +{ + vj_font_t *ff = (vj_font_t*) font; + int seq = ff->auto_number; + + char *key = make_key( seq ); + +#ifdef STRICT_CHECKING + assert( ff->dictionary != NULL ); +#endif + srt_seq_t *s = NULL; + if( vevo_property_get( ff->dictionary, key, 0, &s ) != VEVO_NO_ERROR ) + { + free(key); + return; + } + font_lock( ff ); + + s->fg[0] = r; + s->fg[1] = g; + s->fg[2] = b; + s->alpha[0] = a; + + font_unlock( ff ); + + free(key); +} + +void vj_font_dictionary_destroy( void *font, void *dict ) +{ + char **items = vevo_list_properties(dict ); + if(!items) { + vevo_port_free(dict); + return; + } + + vj_font_t *f = (vj_font_t*) font; + + int i; + for( i = 0; items[i] != NULL ; i ++ ) + { + srt_seq_t *s = NULL; + if( vevo_property_get( dict, items[i], 0,&s ) == VEVO_NO_ERROR ) + { + free(s->text); + free(s); + } + free(items[i]); + } + free(items); + vevo_port_free( dict ); +} + + +void vj_font_destroy(void *ctx) +{ + if(!ctx) + return; + + vj_font_t *f = (vj_font_t*) ctx; + + if( f->face ) + { + int c; + for( c = 0; c < 256 ; c ++) + { + if( f->glyphs[c] ) + FT_Done_Glyph( f->glyphs[c] ); + f->glyphs[c] = NULL; + } + FT_Done_Face( f->face ); + } + + if(f->plain) + vj_font_dictionary_destroy( f,f->plain ); + + FT_Done_FreeType( f->library ); + + int i; + for( i = 0 ; i < MAX_FONTS ;i ++ ) + { + if( f->font_list[i] ) + free(f->font_list[i]); + if( f->font_table[i] ) + free(f->font_table[i]); + } + free( f->text_buffer ); + free( f->font_table ); + free( f->font_list ); + free( f ); +} + +static void fallback_font(vj_font_t *f) +{ + f->current_font = get_default_font( f ); + + while( (f->font = select_font(f, f->current_font )) == NULL ) + { + f->current_font ++; + if( f->current_font >= f->font_index ) + { + veejay_msg(0, "No more fonts to try"); + vj_font_destroy( f ); + } + } + +} + +static int configure(vj_font_t *f, int size, int font) +{ + int c,error; + FT_BBox bbox; + int yMax,yMin,xMax,xMin; + + f->current_font = font; + f->font = select_font( f , font ); + if(f->font == NULL ) + { + fallback_font( f ); + } + + veejay_msg(VEEJAY_MSG_DEBUG, "Using font %s, size %d (#%d)", f->font, size, font ); + + if( f->face ) + { + for( c = 0; c < 256 ; c ++) + { + if( f->glyphs[c] ) + FT_Done_Glyph( f->glyphs[c] ); + f->glyphs[c] = NULL; + } + FT_Done_Face( f->face ); + } + + if ( (error = FT_New_Face( f->library, f->font, 0, &(f->face) )) != 0) + { + veejay_msg(VEEJAY_MSG_ERROR,"Cannot load face: %s (error #%d)\n ", f->font, error); + return 0; + } + + f->current_size = size; + if ( (error = FT_Set_Pixel_Sizes( f->face, 0, f->current_size)) != 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot set font size to %d pixels (error #%d)\n", + f->current_size, error ); + return 0; + } + + f->use_kerning = FT_HAS_KERNING(f->face); + + yMax = -32000; + yMin = 32000; + xMax = -32000; + xMin = 32000; + + for( c = 0; c < 256 ; c ++) + { + // load char + error = FT_Load_Char( f->face, (unsigned char) c , FT_LOAD_RENDER | FT_LOAD_MONOCHROME ); + if(!error) + { + f->bitmaps[c] = f->face->glyph->bitmap; + f->bitmap_left[c] = f->face->glyph->bitmap_left; + f->bitmap_top[c] = f->face->glyph->bitmap_top; + f->advance[c] = f->face->glyph->advance.x >> 6; + + + FT_Get_Glyph( f->face->glyph, &(f->glyphs[c]) ); + } + + f->glyphs_index[c] = FT_Get_Char_Index( f->face, (unsigned char) c ); + if( f->glyphs_index[c] ) + { + FT_Glyph_Get_CBox( f->glyphs[ c ] , ft_glyph_bbox_pixels, &bbox); + if( bbox.yMax > yMax ) + yMax = bbox.yMax; + if( bbox.yMin < yMin ) + yMin = bbox.yMin; + if( bbox.xMax > xMax ) + xMax = bbox.xMax; + if( bbox.xMin < xMin ) + xMin = bbox.xMin; + } + } + + f->text_height = yMax - yMin; + f->text_width = xMax - xMin; + f->baseline = yMax; + + return 1; +} + +void *vj_font_get_plain_dict( void *font ) +{ + vj_font_t *f = (vj_font_t*) font; + return f->plain; +} + +void vj_font_set_osd_text(void *font, char *text ) +{ + vj_font_t *f = (vj_font_t*) font; + if(f->add) + free(f->add); + f->add = strdup( text ); +} + +void vj_font_set_dict( void *font, void *dict ) +{ + vj_font_t *f = (vj_font_t*) font; + if( f == NULL ) + return; + f->dictionary = dict; +} + +void *vj_font_get_dict(void *font) +{ + vj_font_t *f = (vj_font_t*) font; + if(f == NULL ) + return; + return f->dictionary; +} + +static int compare_strings( const void *p1, const void *p2 ) +{ + + return strcoll( (const char *) p1, (const char *) p2 ); +} + +static int get_default_font( vj_font_t *f ) +{ + static struct + { + char *name; + } default_fonts[] = { + { "Arab (Regular)"}, + { "Mashq (Regular)" }, + { "DejaVu Sans (Bold)" }, + { NULL }, + }; + int i,j; + for( i = 0; i < f->font_index; i ++ ) + { + for( j = 0; default_fonts[j].name != NULL ; j ++ ) + { + if( f->font_list[i]) + { + if( strcasecmp( default_fonts[j].name, f->font_list[i] ) == 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG,"Using default font '%s'", default_fonts[j].name ); + return i; + } + } + } + } + return 0; +} + +void *vj_font_init( int w, int h, float fps, int is_osd ) +{ + int error=0; + vj_font_t *f = (vj_font_t*) vj_calloc(sizeof(vj_font_t)); + f->text = NULL; + f->x = 0; + f->y = 0; + f->w = w; + f->h = h; + f->auto_number = 1; + f->index_len = 0; + f->fgcolor[0] = 235; + f->fgcolor[1] = 128; + f->fgcolor[2] = 128; + f->bgcolor[0] = 16; + f->bgcolor[1] = 128; + f->bgcolor[2] = 128; + f->lncolor[0] = 200; + f->lncolor[1] = 128; + f->lncolor[2] = 128; + f->alpha[0] = 0; + f->alpha[1] = 0; + f->alpha[2] = 0; + f->bg = 0; + f->outline = 0; + f->text_height = 0; + int tmp = ((w / 100) * 3) -1; + if(tmp>15) tmp = 14; + if(tmp<9) tmp = 9; + f->current_size = (is_osd ? (tmp): 40); + + f->fps = fps; + f->index = NULL; + f->font_table = (char**) vj_calloc(sizeof(char*) * MAX_FONTS ); + f->font_list = (char**) vj_calloc(sizeof(char*) * MAX_FONTS); + f->font_index =0; + f->plain = vpn( VEVO_ANONYMOUS_PORT ); + + if ( (error = FT_Init_FreeType(&(f->library))) != 0 ) + { + free(f->font_table); + free(f->font_list); + free(f); + veejay_msg(VEEJAY_MSG_ERROR,"Cannot load FreeType (error #%d) \n",error); + return NULL; + } + + find_fonts(f,"/usr/X11R6/lib/X11/fonts/TTF"); + find_fonts(f,"/usr/X11R6/lib/X11/fonts/Type1"); + find_fonts(f,"/usr/X11R6/lib/X11/truetype"); + find_fonts(f,"/usr/X11R6/lib/X11/TrueType"); + find_fonts(f,"/usr/share/fonts/truetype"); + + if( f->font_index <= 0 ) + { + char *home = getenv("HOME"); + char path[1024]; + snprintf(path,1024,"%s/.veejay/fonts",home); + veejay_msg(VEEJAY_MSG_ERROR, "No TrueType fonts found"); + + find_fonts(f,path); + if( f->font_index <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Please put some TrueType font files in %s",path); + return NULL; + } + } + + veejay_msg(VEEJAY_MSG_INFO, "Loaded %d TrueType fonts", f->font_index ); + + qsort( f->font_table, f->font_index, sizeof(char*), compare_strings ); + qsort( f->font_list, f->font_index, sizeof(char*), compare_strings ); + + int df = get_default_font( f ); + + while(!configure( f, f->current_size, df )) + { + f->current_font ++; + if( f->current_font >= f->font_index ) + { + veejay_msg(0, "It seems that all loaded fonts are not working. Bye"); + vj_font_destroy( f ); + return NULL; + } + } + + f->text_buffer = (srt_cycle_t*) + vj_calloc(sizeof(srt_cycle_t) * (sizeof(srt_cycle_t)*22500)); + f->text_max_size = 22500; + //print_fonts(f); + + pthread_mutex_init( &(f->mutex), NULL ); + + return f; +} +void *vj_font_single_init( int w, int h, float fps,char *path ) +{ + int error=0; + vj_font_t *f = (vj_font_t*) vj_calloc(sizeof(vj_font_t)); + f->text = NULL; + f->x = 0; + f->y = 0; + f->w = w; + f->h = h; + f->auto_number = 1; + f->index_len = 0; + f->fgcolor[0] = 235; + f->fgcolor[1] = 128; + f->fgcolor[2] = 128; + f->bgcolor[0] = 16; + f->bgcolor[1] = 128; + f->bgcolor[2] = 128; + f->lncolor[0] = 200; + f->lncolor[1] = 128; + f->lncolor[2] = 128; + f->alpha[0] = 0; + f->alpha[1] = 0; + f->alpha[2] = 0; + f->bg = 0; + f->outline = 0; + f->text_height = 0; + + int tmp = (w / 100) * 3; + if(tmp>15) tmp = 14; + if(tmp<11) tmp = 11; + f->current_size = tmp; + + f->fps = fps; + f->index = NULL; + f->font_table = (char**) vj_calloc(sizeof(char*) * MAX_FONTS ); + f->font_list = (char**) vj_calloc(sizeof(char*) * MAX_FONTS); + f->font_index =0; + f->plain = vpn( VEVO_ANONYMOUS_PORT ); + + if ( (error = FT_Init_FreeType(&(f->library))) != 0 ) + { + free(f->font_table); + free(f->font_list); + free(f); + veejay_msg(VEEJAY_MSG_ERROR,"Cannot load FreeType (error #%d) \n",error); + return NULL; + } + + char fontpath[1024]; + snprintf(fontpath,1024,"%s/fonts",path); + + find_fonts(f,fontpath); + if( f->font_index <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Please put some TrueType font files in %s",fontpath); + return NULL; + } + + veejay_msg(VEEJAY_MSG_INFO, "Loaded %d TrueType fonts", f->font_index ); + qsort( f->font_table, f->font_index, sizeof(char*), compare_strings ); + qsort( f->font_list, f->font_index, sizeof(char*), compare_strings ); + + int df = get_default_font( f ); + + while(!configure( f, f->current_size, df )) + { + f->current_font ++; + if( f->current_font >= f->font_index ) + { + veejay_msg(0, "It seems that all loaded fonts are not working. Bye"); + vj_font_destroy( f ); + return NULL; + } + } + + f->text_buffer = (srt_cycle_t*) + vj_calloc(sizeof(srt_cycle_t) * (sizeof(srt_cycle_t)*22500)); + f->text_max_size = 22500; + //print_fonts(f); + + pthread_mutex_init( &(f->mutex), NULL ); + + return f; +} + +static void draw_glyph( + vj_font_t *f, + VJFrame *picture, + FT_Bitmap *bitmap, + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + uint8_t *yuv_fgcolor, + uint8_t *yuv_lncolor, + int outline) +{ + int r, c; + int spixel, dpixel[3], in_glyph=0; + dpixel[2] = 128; dpixel[1] = 128; + + if( x < 0 ) x = 0; else if ( x > width ) x = width; + if( y < 0 ) y = 0; else if ( y > height ) y = height; + + uint8_t *Y = picture->data[0]; + uint8_t *U = picture->data[1]; + uint8_t *V = picture->data[2]; + + uint8_t *bitbuffer = bitmap->buffer; + uint32_t bitmap_rows = bitmap->rows; + uint32_t bitmap_wid = bitmap->width; + uint32_t bitmap_pitch = bitmap->pitch; + + int p,left,top,bot,pos; + + if (bitmap->pixel_mode == ft_pixel_mode_mono) + { + in_glyph = 0; + for (r=0; (r < bitmap_rows) && (r+y < height); r++) + { + for (c=0; (c < bitmap_wid) && (c+x < width); c++) + { + p = (c+x) + ((y+r)*width); + left = (c+x-1) + ((y+r)*width); + top = (c+x) + ((y+r-1)*width); + bot = (c+x) + ((y+r+1)*width); + + dpixel[0] = Y[ p ]; + dpixel[1] = U[ p ]; + dpixel[2] = V[ p ]; + + pos = r * bitmap_pitch + (c >> 3 ); + + // spixel = bitmap->buffer[r*bitmap->pitch +c/8] & (0x80>>(c%8)); + + spixel = bitbuffer[ pos ] & ( 0x80 >> ( c % 8 )); + + if (spixel) + { + dpixel[0] = yuv_fgcolor[0]; + dpixel[1] = yuv_fgcolor[1]; + dpixel[2] = yuv_fgcolor[2]; + } + if (outline) + { + if ( (!in_glyph) && (spixel) ) + { + in_glyph = 1; + if (c-1 >= 0) + { + Y[ left ] = yuv_lncolor[0]; + U[ left ] = yuv_lncolor[1]; + V[ left ] = yuv_lncolor[2]; + } + } + else if ( (in_glyph) && (!spixel) ) + { + in_glyph = 0; + dpixel[0] = yuv_lncolor[0]; + dpixel[1] = yuv_lncolor[1]; + dpixel[2] = yuv_lncolor[2]; + } + + if (in_glyph) + { + if ( (r-1 >= 0) && (! bitbuffer[(r-1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) + { + Y[ top ] = yuv_lncolor[0]; + U[ top ] = yuv_lncolor[1]; + V[ top ] = yuv_lncolor[2]; + } + + if ( (r+1 < height) && (! bitbuffer[(r+1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) + { + Y[ bot ] = yuv_lncolor[0]; + U[ bot ] = yuv_lncolor[1]; + V[ bot ] = yuv_lncolor[2]; + } + } + } + Y[ p ] = dpixel[0]; + U[ p ] = dpixel[1]; + V[ p ] = dpixel[2]; + } + } + } +} + +// in struct: line color [3] , alpha fg, bg and line color +// extras in sequence: alpha (3x), linecolor( 3x ) +static void draw_transparent_glyph( + vj_font_t *f, + VJFrame *picture, + FT_Bitmap *bitmap, + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + uint8_t *yuv_fgcolor, + uint8_t *yuv_lncolor, + int outline, + int fgop, + int bgop) +{ + int r, c; + int spixel, dpixel[3], in_glyph=0; + dpixel[2] = 128; dpixel[1] = 128; + + + uint8_t *Y = picture->data[0]; + uint8_t *U = picture->data[1]; + uint8_t *V = picture->data[2]; + + const uint8_t fop1 = fgop; + const uint8_t fop0 = 255 - fop1; + const uint8_t bop1 = bgop; + const uint8_t bop0 = 255 - bop1; + + // opacity for line color , fgcolor and bgcolor. is bg color needed here? + if (bitmap->pixel_mode == ft_pixel_mode_mono) + { + + in_glyph = 0; + for (r=0; (r < bitmap->rows) && (r+y < height); r++) + { + for (c=0; (c < bitmap->width) && (c+x < width); c++) + { + int p = (c+x) + ((y+r)*width); + int left = (c+x-1) + ((y+r)*width); + int top = (c+x) + ((y+r-1)*width); + int bot = (c+x) + ((y+r+1)*width); + + dpixel[0] = Y[ p ]; + dpixel[1] = U[ p ]; + dpixel[2] = V[ p ]; + + spixel = bitmap->buffer[r*bitmap->pitch +c/8] & (0x80>>(c%8)); + + if (spixel) + { + dpixel[0] = (Y[p] * fop0 + yuv_fgcolor[0] * fop1 ) >> 8; + dpixel[1] = (U[p] * fop0 + yuv_fgcolor[1] * fop1 ) >> 8; + dpixel[2] = (V[p] * fop0 + yuv_fgcolor[2] * fop1 ) >> 8; + } + if (outline) + { + if ( (!in_glyph) && (spixel) ) + { + in_glyph = 1; + if (c-1 >= 0) + { + Y[ left ] = (Y[p] * bop0 + yuv_lncolor[0] * bop1)>>8; + U[ left ] = (U[p] * bop0 + yuv_lncolor[1] * bop1)>>8; + V[ left ] = (V[p] * bop0 + yuv_lncolor[2] * bop1)>>8; + } + } + else if ( (in_glyph) && (!spixel) ) + { + in_glyph = 0; + dpixel[0] = (Y[p] * bop0 + yuv_lncolor[0] * bop1) >> 8; + dpixel[1] = (U[p] * bop0 + yuv_lncolor[1] * bop1) >> 8; + dpixel[2] = (V[p] * bop0 + yuv_lncolor[2] * bop1) >> 8; + } + + if (in_glyph) + { + if ( (r-1 >= 0) && (! bitmap->buffer[(r-1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) + { + Y[ top ] = (Y[p] * bop0 + yuv_lncolor[0] * bop1)>>8; + U[ top ] = (U[p] * bop0 + yuv_lncolor[1] * bop1)>>8; + V[ top ] = (V[p] * bop0 + yuv_lncolor[2] * bop1)>>8; + } + + if ( (r+1 < height) && (! bitmap->buffer[(r+1)*bitmap->pitch +c/8] & (0x80>>(c%8))) ) + { + Y[ bot ] = (Y[p] * bop0 + yuv_lncolor[0] * bop1)>>8; + U[ bot ] = (U[p] * bop0 + yuv_lncolor[1] * bop1)>>8; + V[ bot ] = (V[p] * bop0 + yuv_lncolor[2] * bop1)>>8; + } + } + } + Y[ p ] = dpixel[0]; + U[ p ] = dpixel[1]; + V[ p ] = dpixel[2]; + } + } + } +} + +static inline void draw_transparent_box( + VJFrame *picture, + unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height, + uint8_t *yuv_color, + uint8_t opacity) +{ + const int op1 = opacity; + const int op0 = 255 - op1; + const int w = picture->width; + int i, j; + + uint8_t *A[3] = { + picture->data[0], + picture->data[1], + picture->data[2] + }; + + int p; + + for (j = y; j < height; j++) + for (i = x; i < width; i++) + { + p = (i + (j * w)); + A[0][p] = (op0 * A[0][ p ] + op1 * yuv_color[0]) >> 8; + A[1][p] = (op0 * A[1][ p ] + op1 * yuv_color[1]) >> 8; + A[2][p] = (op0 * A[2][ p ] + op1 * yuv_color[2]) >> 8; + } + +} + +static inline void draw_box(VJFrame *picture, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uint8_t *yuv_color) +{ + int i, j; + + for (j = y; j < height; j++) + for (i = x; i < width; i++) + { + picture->data[0][ i + (j * picture->width ) ] = yuv_color[0]; + picture->data[1][ i + (j * picture->width ) ] = yuv_color[1]; + picture->data[2][ i + (j * picture->width ) ] = yuv_color[2]; + } + +} + +#define MAXSIZE_TEXT 1024 + +static void vj_font_text_render(vj_font_t *f, srt_seq_t *seq, void *_picture ) +{ + int size = strlen(seq->text); + FT_Face face = f->face; + FT_GlyphSlot slot = face->glyph; + FT_Vector pos[MAXSIZE_TEXT]; + FT_Vector delta; + + unsigned char c; + int x = 0, y = 0, i=0; + int str_w, str_w_max; + + VJFrame *picture = (VJFrame*) _picture; + int width = picture->width; + int height = picture->height; + + int x1 = f->x; + int y1 = f->y; + + str_w = str_w_max = 0; + + x = f->x; + y = f->y; + + char *text = seq->text; + + for (i=0; i < size; i++) + { + c = text[i]; + if ( (f->use_kerning) && (i > 0) && (f->glyphs_index[c]) ) + { + FT_Get_Kerning( + f->face, + f->glyphs_index[c], + // f->glyphs_index[ text[i-1] ], + f->glyphs_index[c], + ft_kerning_default, + &delta + ); + + x += delta.x >> 6; + } + + if( isblank( c ) || c == 20 ) + { + f->advance[c] = f->current_size; + if( (x + f->current_size) >= width ) + { + str_w = width = f->x - 1; + y += f->text_height; + x = f->x; + } + } + else + if (( (x + f->advance[ c ]) >= width ) || ( c == '\n' )) + { + str_w = width - f->x - 1; + y += f->text_height; + x = f->x; + } + + pos[i].x = x + f->bitmap_left[c]; + pos[i].y = y - f->bitmap_top[c] + f->baseline; + x += f->advance[c]; + + if (str_w > str_w_max) + str_w_max = str_w; + } + + if (f->bg) + { + if ( str_w_max + f->x >= width ) + str_w_max = width - f->x - 1; + if ( y >= height ) + y = height - 1 - 2*f->y; + + if( str_w_max == 0 ) + str_w_max = x1 + (x - x1); + + int bw = str_w_max; + int bh = y - y1; + if(bh <= 0 ) + bh = y1 + f->current_size; + + if( f->alpha[1] == 0 ) + { + draw_box( + picture, + x1, + y1, + bw, + bh, + f->bgcolor + ); + } + else + { + draw_transparent_box( + picture, + x1, + y1, + bw, + bh, + f->bgcolor, + f->alpha[1] ); + } + } + + for (i=0; i < size; i++) + { + c = text[i]; + if ( ((c == '_') && ((char*)text == (char*)f->text) ) || /* skip '_' (consider as space) + IF text was specified in cmd line + (which doesn't like neasted quotes) */ + ( c == '\n' )) /* Skip new line char, just go to new line */ + continue; + + if( f->alpha[0] || f->alpha[2] ) + { + draw_transparent_glyph( f, picture, &(f->bitmaps[c]), + pos[i].x,pos[i].y,width,height, + f->fgcolor,f->lncolor, f->outline, + f->alpha[0],f->alpha[2] ); + } + else + { + draw_glyph( f,picture, &(f->bitmaps[ c ]), + pos[i].x,pos[i].y,width, height, + f->fgcolor,f->lncolor,f->outline ); + } + x += slot->advance.x >> 6; + } + +} + +static int num_nl( char *str , int len ) { + int i; + int sum = 0; + for( i = 0; i < len ; i ++ ) + if( str[i] == '\n' ) + sum ++; + return sum; +} + +static void vj_font_text_osd_render(vj_font_t *f, void *_picture, int x, int y ) +{ + FT_Face face = f->face; + FT_GlyphSlot slot = face->glyph; + FT_Vector pos[MAXSIZE_TEXT]; + FT_Vector delta; + unsigned char c; + int i=0; + int str_w, str_w_max; + VJFrame *picture = (VJFrame*) _picture; + int width = picture->width; + int height = picture->height; + int x1,y1; + str_w = str_w_max = 0; + + if(!f->add) + return; + + int size = strlen( f->add ); + if( size <= 0 ) + return; + + if( y == -1 ) + { + int n = num_nl(f->add,size); + if( n > 4 ) + y = 0; + else + y = picture->height - (f->current_size * n ) - f->current_size - 8; + if( width < 512 ) + y -= (f->current_size * n ) - f->current_size - 8; + if ( y < 0 ) + y = 0; + } + + + x1 = x; + y1 = y; + + unsigned int str_wi = 0; + unsigned char *text = f->add; + + for (i=0; i < size; i++) + { + c = text[i]; + if ( (f->use_kerning) && (i > 0) && (f->glyphs_index[c]) ) + { + FT_Get_Kerning( + f->face, + f->glyphs_index[c], + f->glyphs_index[c], + ft_kerning_default, + &delta + ); + + x += delta.x >> 6; + } + + if( isblank( c ) || c == 20 ) + { + f->advance[c] = f->current_size; + if( (x + f->current_size) >= width ) + { + str_w = width = f->x - 1; + y += f->text_height; + x = f->x; + } + } + else + if (( (x + f->advance[ c ]) >= width ) || ( c == '\n' )) + { + str_w = width - f->x - 1; + y += f->text_height; + if( str_wi < x ) + str_wi = x; + x = f->x; + } + + pos[i].x = x + f->bitmap_left[c]; + pos[i].y = y - f->bitmap_top[c] + f->baseline; + x += f->advance[c]; + + if (str_w > str_w_max) + str_w_max = str_w; + } + +// if ( str_w_max + f->x >= width ) +// str_w_max = width - f->x - 1; + + if ( y >= height ) + y = height - 1 - 2*f->y; + +// if( str_w_max == 0 ) + str_w_max = (x - x1); + + int bw = str_w_max; + int bh = y - y1; + if(bh <= 0 ) + bh = y1 + f->current_size + 4; + + draw_transparent_box( + picture, + x1, + y1, + str_wi,//picture->width, + bh, + f->bgcolor, + 80 ); + + for (i=0; i < size; i++) + { + c = text[i]; + if ( ((c == (unsigned char) '_') && (text == f->text) ) || /* skip '_' (consider as space) + IF text was specified in cmd line + (which doesn't like neasted quotes) */ + ( c == '\n' )) /* Skip new line char, just go to new line */ + continue; + draw_glyph( f,picture, &(f->bitmaps[ c ]), + pos[i].x,pos[i].y,width, height, + f->fgcolor,f->lncolor,f->outline ); + + x += slot->advance.x >> 6; + } +} + + +int vj_font_norender(void *ctx, long position) +{ + if(!ctx) + return 0; + vj_font_t *f = (vj_font_t *) ctx; + + if(!f->dictionary ) + return 0; + + int i; + int jobs = 0; + for( i = 0; i < f->index_len; i ++ ) { + srt_seq_t *s = f->index[i]; + if(!s) + continue; + if(s->start <= position && s->end >= position ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Subtitle %p, Render %s on %ld",s, s->text, position); + jobs ++; + } + } + + return jobs; +} + +void vj_font_render_osd_status( void *ctx, void *_picture, char *status_str, int placement ) +{ + vj_font_t *f = (vj_font_t*) ctx; + vj_font_set_osd_text(ctx,status_str); + if(placement == 1) { + vj_font_text_osd_render( ctx, _picture, 5, 5 ); + } + else + { + vj_font_text_osd_render( ctx, _picture, 5, -1 ); + } + +} + +void vj_font_render(void *ctx, void *_picture, long position) +{ + vj_font_t *f = (vj_font_t *) ctx; +#ifdef STRICT_CHECKING + assert( f->dictionary != NULL ); +#endif + font_lock( f ); + int i; + for( i = 0; i < f->index_len; i ++ ) { + srt_seq_t *s = f->index[i]; + if(!s) + continue; + if(s->start <= position && s->end >= position ) + { + int old_font = f->current_font; + int old_size = f->current_size; + + if( old_font != s->font || old_size != s->size ) + if(!configure( f, s->size, s->font )) + if(!configure( f, old_size, old_font )) + break; + + f->x = s->x; + f->y = s->y; + f->bg = s->use_bg; + f->outline = s->outline; + + if(f->outline) + _rgb2yuv( s->ln[0],s->ln[1],s->ln[2], f->lncolor[0],f->lncolor[1],f->lncolor[2]); + + _rgb2yuv( s->fg[0],s->fg[1],s->fg[2], f->fgcolor[0],f->fgcolor[1],f->fgcolor[2] ); + if(f->bg) + _rgb2yuv( s->bg[0],s->bg[1],s->bg[2], f->bgcolor[0],f->bgcolor[1],f->bgcolor[2] ); + + memcpy( f->alpha, s->alpha, sizeof(s->alpha) ); + + vj_font_text_render( f,s, _picture ); + + } + } + + font_unlock(f); +} + + + +#endif + diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-font.h b/branches/V-1.5.3/veejay-server/veejay/vj-font.h new file mode 100644 index 00000000..1017871d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-font.h @@ -0,0 +1,56 @@ +#ifndef VJFONT_H +#define VJFONT_H +/* + * Linux VeeJay + * + * Copyright(C)2002-2006 Niels Elburg < nwelburg@gmail.com > + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + * + * + */ +void *vj_font_single_init(int s_w, int s_h, float fps, char *home); + +void *vj_font_init(int s_w, int s_h, float fps, int osd); +int vj_font_srt_sequence_exists( void *font, int id ); +void vj_font_render(void *ctx, void *_picture, long nframe); +void vj_font_destroy(void *ctx); +int vj_font_load_srt( void *font, const char *filename ); +int vj_font_save_srt( void *font , const char *filename ); +char *vj_font_get_sequence( void *font, int seq ); +void *vj_font_get_plain_dict( void *font ); +int vj_font_prepare( void *font, long s1, long s2 ); +void vj_font_dictionary_destroy(void *font,void *dict); +int vj_font_clear_text( void *font ); +int vj_font_new_text( void *font, char *text, long s1,long s2, int seq); +void vj_font_del_text( void *font, int seq ); +char **vj_font_get_all_fonts( void *font ); +void vj_font_set_lncolor( void *font, int r, int g, int b, int a ); +void vj_font_set_fgcolor( void *font, int r, int g, int b, int a ); +void vj_font_set_bgcolor( void *font, int r, int g, int b, int a ); +void vj_font_set_outline_and_border( void *font, int outline, int border); +void vj_font_set_position( void *font, int x, int y ); +void vj_font_set_size_and_font( void *font, int f_id, int size ); +void vj_font_set_dict( void *font, void *dict ); +void vj_font_set_osd_text(void *font, char *text ); +void *vj_font_get_dict(void *font); +void vj_font_update_text( void *font, long s1,long s2, int seq, char *text); +char **vj_font_get_sequences( void *font ); +char *vj_font_get_sequence( void *font , int id ); +void vj_font_set_current( void *font , int cur ); +void vj_font_xml_pack( xmlNodePtr node, void *font ); +void vj_font_xml_unpack( xmlDocPtr doc, xmlNodePtr node, void *font ); +int vj_font_norender(void *ctx, long position); +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-jack.h b/branches/V-1.5.3/veejay-server/veejay/vj-jack.h new file mode 100644 index 00000000..a69b99a5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-jack.h @@ -0,0 +1,63 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_JACK_H +#define VJ_JACK_H + +#include +#ifdef HAVE_JACK +#include + +int vj_jack_init(editlist *el); + +int vj_jack_update_buffer( uint8_t *buff, int bps, int num_channels, int buf_len); + +int vj_jack_stop(); + +int vj_jack_start(); + +int vj_jack_pause(); + +int vj_jack_resume(); + +void vj_jack_reset(); + +int vj_jack_play(void *data, int len); + +int vj_jack_set_volume(int volume); + +int vj_jack_pause(); + +int vj_jack_resume(); + +long vj_jack_get_status(long int *sec, long int *usec); + +void vj_jack_enable(); + +void vj_jack_disable(); + +int vj_jack_get_space(); + +int vj_jack_continue(int speed); + +int vj_jack_initialize(); + +int vj_jack_rate(); + +#endif +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-lib.h b/branches/V-1.5.3/veejay-server/veejay/vj-lib.h new file mode 100644 index 00000000..969d932d --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-lib.h @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2002 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef VJ_LIB_H +#define VJ_LIB_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + NO_AUDIO = 0, + AUDIO_PLAY = 1, + AUDIO_RENDER = 2, +}; + + + + +enum { + LAVPLAY_STATE_STOP = 0, /* uninitialized state */ + LAVPLAY_STATE_PAUSED = 1, /* also known as: speed = 0 */ + LAVPLAY_STATE_PLAYING = 2, /* speed != 0 */ + LAVPLAY_STATE_RENDER_READY = 3, /* render mode */ +}; + +/* nmacro recorder, 5 lines code for play back of what you changed at navigation */ +enum { + VJ_MACRO_PLAIN_RECORD = 0, + VJ_MACRO_PLAIN_PLAY = 1, +}; + +#define MJPEG_MAX_BUF 64 +#define VJ_AUDIO_BUF_SIZE 16384 + + + +#define DUMMY_DEFAULT_WIDTH 352 +#define DUMMY_DEFAULT_HEIGHT 288 +#define DUMMY_DEFAULT_FPS 25 + +/* Video Playback Setup, necessary items for reading and playing video */ +struct mjpeg_sync +{ + unsigned long frame; /* Frame (0 - n) for double buffer */ + unsigned long length; /* number of code bytes in buffer (capture only) */ + unsigned long seq; /* frame sequence number */ + struct timeval timestamp; /* timestamp */ +}; +#define VJ_SCHED_NONE (1<<0) +#define VJ_SCHED_SL (1<<1) +#define VJ_SCHED_EL (1<<2) + +typedef struct { + int state; + char *sl; +} vj_schedule_t; + +#define RANDMODE_INACTIVE 0 +#define RANDMODE_SAMPLE 1 +#define RANDTYPE_NOFX 0 +#define RANDTYPE_PIXEL 1 +#define RANDTYPE_GEO 2 +#define RANDTYPE_MIXED 3 +#define RANDTIMER_FRAME 1 +#define RANDTIMER_LENGTH 0 + +typedef struct +{ + int mode; + int type; + int timer; + int min_delay; + int max_delay; +} vj_rand_player; + +typedef struct +{ + int chroma; + char norm; + int width; + int height; + float fps; + int active; + long arate; +} dummy_t; + +typedef struct +{ + int active; + int current; + int size; + int *samples; + int rec_id; +} sequencer_t; + + +typedef struct { + pthread_t software_playback_thread; + pthread_t playback_thread; + pthread_attr_t playback_attr; + pthread_t geo_stat; + pthread_mutex_t valid_mutex; + pthread_cond_t buffer_filled[MJPEG_MAX_BUF]; + pthread_cond_t buffer_done[MJPEG_MAX_BUF]; + pthread_mutex_t syncinfo_mutex; + pthread_t signal_thread; + sigset_t signal_set; + struct timeval lastframe_completion; /* software sync variable */ + + long old_field_len; + uint64_t save_list_len; /* for editing purposes */ + + double spvf; /* seconds per video frame */ + int usec_per_frame; /* milliseconds per frame */ + int msec_per_frame; + int min_frame_num; /* the lowest frame to be played back - normally 0 */ + int max_frame_num; /* the latest frame to be played back - normally num_frames - 1 */ + int current_frame_num; /* the current frame */ + int previous_frame_num; /* previous frame num */ + int current_playback_speed; /* current playback speed */ + int currently_processed_frame; /* changes constantly */ + int currently_synced_frame; /* changes constantly */ + int first_frame; /* software sync variable */ + int valid[MJPEG_MAX_BUF]; /* num of frames to be played */ + long buffer_entry[MJPEG_MAX_BUF]; + int render_entry; + int render_list; + int last_rendered_frame; + long rendered_frames; + long currently_processed_entry; + struct mjpeg_sync syncinfo[MJPEG_MAX_BUF]; /* synchronization info */ + uint64_t *save_list; /* for editing purposes */ + int abuf_len; + double spas; /* seconds per audio sample */ + int audio_mute; /* controls whether to currently play audio or not */ + int state; /* playing, paused or stoppped */ + int effect; /* realtime effect during play */ + int video_fd; + // pthread_t playback_thread; /* the thread for the whole playback-library */ + int offline_ready; + int offline_record; + int offline_tag_id; + int offline_created_sample; + int sample_record; + int sample_record_id; + int sample_record_switch; + int full_screen; + int tag_record_switch; + int tag_record; + int dct_method; + subsample_mode_t sample_mode; + int unicast_link_id; + int unicast_frame_sender; + int is_dat; + int mcast_mode; + int mcast_frame_sender; + int use_mcast; + char *group_name; + int use_vims_mcast; + char *vims_group_name; + int zoom; + int composite; + int composite2; + sws_template sws_templ; + vj_schedule_t action_scheduler; + float output_fps; + int crop; + VJRectangle viewport; + vj_rand_player randplayer; + void *export_image; + int links[16]; + int ncpu; + int vp_rec; + int late[2]; + int cy; + int cx; + int cn; + int ca; + int fxrow[3]; + int fxdepth; + int repeat_delay; + int repeat_interval; + int simple_frame_dup; + uint32_t cycle_count[2]; //@ required for veejay-radar + int sample_restart; +} video_playback_setup; + +typedef struct { + int stats_changed; /* has anything bad happened? */ + unsigned int frame; /* current frame which is being played back */ + unsigned int num_corrs_a; /* Number of corrections because video ahead audio */ + unsigned int num_corrs_b; /* Number of corrections because video behind audio */ + unsigned int num_aerr; /* Number of audio buffers in error */ + unsigned int num_asamps; + unsigned int nsync; /* Number of syncs */ + unsigned int nqueue; /* Number of frames queued */ + int play_speed; /* current playback speed */ + int audio; /* whether audio is currently turned on */ + int norm; /* [0-2] playback norm: 0 = PAL, 1 = NTSC, 2 = SECAM */ + double tdiff; /* video/audio time difference (sync debug purposes) */ +} video_playback_stats; + +/* User Control , it keeps track of user's actions */ +typedef struct { + int playback_mode; /* playing plain,sample,tag or pattern */ + int sample_id; /* which sample or tag is beeing played */ + char *filename; + int hackme; + int take_bg; + int direction; /* forward, reverse or pause */ + int looptype; /* loop setting depending on playmode */ + long sample_end; /* end of sample */ + long sample_start; /* start of sample */ + int play_sample; /* playing sample or not */ + int key_effect; /* selected effect */ + int effect_id; /* current effect id */ + int loops; + int next; + int sample_key; /* sample by key */ + int sample_select; /* selected sample */ + int sample_pressed; /* which sample key was pressed */ + int chain_changed; + int use_timer; + int rtc_fd; + int current_link; + int port; + float rtc_delay; + int is_server; + int render_changed; + int input_device; + int geox; + int geoy; + int file_as_sample; + int mouse[4]; + char *osd_extra; +} user_control; + +typedef struct { + int video_output_width; /* width of the SDL playback window in case of software playback */ + int video_output_height; /* height of the SDL playback window in case of software playback */ + int double_factor; /* while playing, duplicate each frame double_factor times */ + int preserve_pathnames; + int audio; /* [0-1] Whether to play audio, 0 = no, 1 = yes */ + int continuous; /* [0-1] 0 = quit when the video has been played, 1 = continue cycle */ + int sync_correction; /* [0-1] Whether to enable sync correction, 0 = no, 1 = yes */ + int sync_skip_frames; /* [0-1] If video is behind audio: 1 = skip video, 0 = insert audio */ + int sync_ins_frames; /* [0-1] If video is ahead of audio: 1 = insert video, 0 = skip audio */ + int auto_deinterlace; + int load_action_file; + editlist *current_edit_list; + editlist *edit_list; /* the playing editlist */ + user_control *uc; /* user control */ + +// v4l_video *vj[4]; /* v4l input */ + void *osc; + VJFrame *plugin_frame; + VJFrameInfo *plugin_frame_info; + VJFrame *effect_frame1; + VJFrame *effect_frame2; + VJFrameInfo *effect_frame_info; + vjp_kf *effect_info; /* effect dependent variables */ +#ifdef HAVE_DIRECTFB + void *dfb; +#endif + //vj_ladspa_instance *vli; + //int vli_enabled; + int video_out; +#ifdef HAVE_GL + void *gl; +#endif + void *y4m; +#ifdef HAVE_SDL + vj_sdl **sdl; /* array of SDL windows */ +#endif + vj_yuv *output_stream; /* output stream for dumping video */ + vj_yuv *render_stream; + void *vloopback; // vloopback output + void *video_out_scaler; + int render_now; /* write RGB */ + int render_continous; + char action_file[2][1024]; + char y4m_file[1024]; + int stream_outformat; + int stream_enabled; + int last_sample_id; + int last_tag_id; + int nstreams; + int sfd; + vj_server *vjs[4]; /* 0=cmd, 1 = sta, 2 = mcast, 3 = msg */ + int net; + int render_entry; + int render_continue; + video_playback_setup *settings; /* private info - don't touch :-) (type UNKNOWN) */ + int real_fps; + int dump; + int verbose; + int no_bezerk; + int pixel_format; + dummy_t *dummy; + int seek_cache; + int bes_width; + int bes_height; + char *status_what; + char *status_msg; + char *homedir; + void *font; + void *osd; + int use_osd; + sequencer_t *seq; + int no_caching; + void *viewport; + void *composite; + void *composite2; + int use_vp; + int use_proj; + int frontback; + int out_buf; + unsigned long *mask; + unsigned long *cpumask; + int ncpus; + int sz; + int audio_running; + int *rlinks; +} veejay_t; + +typedef struct { + int arg; + int val; + int press; + int increment; + int lock; + int minterpolate; + int interpolate; +} vj_key; + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-misc.c b/branches/V-1.5.3/veejay-server/veejay/vj-misc.c new file mode 100644 index 00000000..416fcd91 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-misc.c @@ -0,0 +1,656 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_JPEG +#include +#endif +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +static unsigned int vj_relative_time = 0; +static unsigned int vj_stamp_ = 0; +static unsigned int vj_get_timer() +{ + struct timeval tv; + gettimeofday(&tv, 0); + return ((tv.tv_sec & 1000000) + tv.tv_usec); +} + +unsigned int vj_stamp() +{ + vj_stamp_ ++; + return vj_stamp_; +} + +void vj_stamp_clear() +{ + vj_stamp_ = 0; +} + +unsigned int vj_get_relative_time() +{ + unsigned int time, relative; + time = vj_get_timer(); + relative = time - vj_relative_time; + vj_relative_time = time; + return relative; +} + +static struct +{ + const char *ext; +} filefilters[] = { + { ".avi" }, + { ".mov" }, + { ".dv" }, + { ".edl" }, + { ".y4m" }, + { NULL} +}; + +static int is_it_usable(const char *file) +{ + int i = 0; + while ( filefilters[i].ext != NULL ) { + if(strcasestr( file, filefilters[i].ext ) ) + return 1; + i++; + } + return 0; +} + +static char *relative_path(filelist_t *filelist, const char *node) +{ + int len = strlen(filelist->working_dir); + if( node + len + 1 ) { + char *tmp = strdup( node + len + 1); + return tmp; + } + return strdup(node); +} + +static int is_usable_file( filelist_t *filelist, const char *node, const char *filename ) +{ + if(!node) + return 0; + + struct stat l; + veejay_memset(&l,0,sizeof(struct stat)); +#ifdef STRICT_CHECKING + assert( filelist != NULL ); + assert( filelist->num_files >= 0 || filelist->num_files < 1024 ); +#endif + if( lstat( node, &l) < 0 ) + return 0; + if( S_ISLNK( l.st_mode )) { + veejay_memset(&l,0,sizeof(struct stat)); + stat(node, &l); + return 1; + } + if( S_ISDIR( l.st_mode ) ) { + return 1; + } + + if( S_ISREG( l.st_mode ) ) { + if( is_it_usable(node)) { + if( filelist->num_files < filelist->max_files-1 ) { + filelist->files[ filelist->num_files ] = + relative_path(filelist,node); + filelist->num_files ++; + } + } + } + return 0; +} + +static int dir_selector( const struct dirent *dir ) +{ + return 1; +} + +static int find_files( filelist_t *filelist, const char *path ) +{ + struct dirent **files; + int N = scandir ( path, &files, dir_selector,alphasort ); + int n; + if( N < 0 ) { + return 0; + } + + for( n = 0; n < N; n ++ ) + { + char tmp[2048]; + if( strcmp( files[n]->d_name, "." ) == 0 || + strcmp( files[n]->d_name, ".." ) == 0 ) { + continue; + } + + snprintf(tmp,sizeof(tmp), "%s/%s", path,files[n]->d_name ); + if(is_usable_file( filelist, tmp, files[n]->d_name ) ) { //@recurse + find_files( filelist, tmp ); + } + } + + for( n = 0; n < N; n ++ ) { + if( files[n]) + free(files[n]); + } + free(files); + return 1; +} +void free_media_files( veejay_t *info, filelist_t *fl ) +{ + int n; + for( n = 0; n < fl->num_files ; n ++ ) { + if(fl->files[n] != NULL ) { + free(fl->files[n]); + } + } + free(fl->files); + free(fl->working_dir); + free(fl); + fl = NULL; +} + +filelist_t *find_media_files( veejay_t *info ) +{ + char working_dir[2048]; + + char *wd = getcwd( working_dir, sizeof(working_dir)); + + if( wd == NULL ) { +#ifdef STRICT_CHECKING + veejay_msg(0, "Strange, current working directory seems to be invalid?"); +#endif + return NULL; + } + + filelist_t *fl = (filelist_t*) vj_malloc(sizeof(filelist_t)); + fl->files = (char**) vj_malloc(sizeof(char*) * 1024 ); //@ 1024 files + fl->max_files = 1024; + fl->num_files = 0; + fl->working_dir = strdup(working_dir); + + int res = find_files( fl, wd ); + + if( res == 0 ) { + veejay_msg(VEEJAY_MSG_DEBUG, "No files found in %s", wd ); + free( fl->files ); + free( fl ); + return NULL; + } + + return fl; +} + + +int vj_perform_take_bg(veejay_t *info, VJFrame *frame, int pass) +{ + int n = 0; + static void *bg_sampler = NULL; + if( pass == 0 ) { + if(frame->ssm = 1 ) { + n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_CHAMBLEND ); + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CHAMELEON ); + return 1; + } + if(frame->ssm == 0) { + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_BGSUBTRACT ); + n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_DIFF ); + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_MOTIONMAP ); + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CONTOUR ); + n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_TEXMAP); + } + + if( frame->ssm == 0 ) + { + //@ supersample + if(!bg_sampler) + bg_sampler = subsample_init( frame->width ); + chroma_supersample( info->settings->sample_mode,bg_sampler,frame->data,frame->width,frame->height); + n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_CHAMBLEND ); + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CHAMELEON ); + frame->ssm = 1; + return 1; + } + return 0; + } else { + + if(frame->ssm == 0) { + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_BGSUBTRACT ); + n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_DIFF ); + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_MOTIONMAP ); + n += vj_effect_prepare( frame, VJ_IMAGE_EFFECT_CONTOUR ); + n += vj_effect_prepare( frame, VJ_VIDEO_EFFECT_TEXMAP); + return 0; + } + } + return 0; +} + +#ifdef HAVE_JPEG +int vj_perform_screenshot2(veejay_t * info, uint8_t ** src) +{ + FILE *frame; + int res = 0; + uint8_t *jpeg_buff; + VJFrame tmp; + int jpeg_size; + + video_playback_setup *settings = info->settings; + + jpeg_buff = (uint8_t *) malloc( 65535 * 10); + if (!jpeg_buff) + return -1; + + vj_get_yuv_template( &tmp, + info->video_output_width, + info->video_output_height, + info->pixel_format ); + + if( tmp.shift_v == 0 ) + { + tmp.data[0] = (uint8_t*) vj_malloc(sizeof(uint8_t) * tmp.len * 3); + tmp.data[1] = tmp.data[0] + tmp.len; + tmp.data[2] = tmp.data[1] + tmp.len + tmp.uv_len; + + tmp.format = PIX_FMT_YUVJ420P; + + VJFrame *srci = yuv_yuv_template( src[0],src[1],src[2], info->video_output_width, + info->video_output_height , PIX_FMT_YUVJ422P); + + yuv_convert_any_ac( srci,&tmp, srci->format, tmp.format ); + + free(srci); + } + else + { + tmp.data[0] = src[0]; + tmp.data[1] = src[1]; + tmp.data[2] = src[2]; + } + + if(info->uc->filename == NULL) + { + info->uc->filename = (char*) malloc(sizeof(char) * 12); + sprintf(info->uc->filename, "%06d.jpg", info->settings->current_frame_num ); + } + frame = fopen(info->uc->filename, "wb"); + + if (frame) + { + jpeg_size = encode_jpeg_raw(jpeg_buff, (65535*10), 100, + settings->dct_method, + info->current_edit_list->video_inter,0, + info->video_output_width, + info->video_output_height, + tmp.data[0], + tmp.data[1], tmp.data[2]); + + res = fwrite(jpeg_buff, jpeg_size, 1, frame); + fclose(frame); + if(res) + veejay_msg(VEEJAY_MSG_INFO, "Dumped frame to %s", info->uc->filename); + } + + if (jpeg_buff) + free(jpeg_buff); + + if( tmp.shift_v == 0 ) + { + free(tmp.data[0]); + } + + return res; +} + +#endif + +int veejay_create_temp_file(const char *prefix, char *dst) +{ + time_t today_time_; + struct tm *today; + + today_time_ = time(NULL); + today = localtime( &today_time_ ); + /* time: + prefix_01-01-04-hh:mm:ss + put time in filename, on cp a.o. the creation date + will be set to localtime (annoying for users who + copy arround files) + */ + + sprintf(dst, + "%s_%02d%02d%02d_%02d%02d%02d", + prefix, + today->tm_mday, + today->tm_mon, + (today->tm_year%100), + today->tm_hour, + today->tm_min, + today->tm_sec); + + return 1; +} + +void vj_get_rgb_template(VJFrame *src, int w, int h ) +{ + src->width = w; + src->height = h; + src->uv_width = 0; + src->uv_height = 0; + src->format = PIX_FMT_RGB24; + src->len = w * h * 3; + src->uv_len = 0; + src->data[0] = NULL; + src->data[1] = NULL; + src->data[2] = NULL; +} + +void vj_get_yuvgrey_template(VJFrame *src, int w, int h) +{ + src->width = w; + src->uv_width = 0; + src->height = h; + src->format = PIX_FMT_GRAY8; + src->uv_height = 0; + src->shift_v = 0; + src->len = w * h; + src->uv_len = 0; + src->shift_h = 0; + src->data[0] = NULL; + src->data[1] = NULL; + src->data[2] = NULL; +} + +void vj_get_yuv_template(VJFrame *src, int w, int h, int fmt) +{ + src->width = w; + src->height = h; + + src->format = get_ffmpeg_pixfmt( fmt ); + + if(fmt == FMT_420||fmt == FMT_420F) + { + src->uv_height = h >> 1; + src->uv_width = w >> 1; + src->shift_v = 1; + src->uv_len = (w*h)/4; + } + if(fmt == FMT_422||fmt==FMT_422F) + { + src->uv_height = h >> 1; + src->uv_width = w; + src->shift_v = 0; + src->uv_len = src->uv_width * src->uv_height; + + } + src->len = w * h; + src->shift_h = 1; + src->data[0] = NULL; + src->data[1] = NULL; + src->data[2] = NULL; + +} + +void vj_get_yuv444_template(VJFrame *src, int w, int h) +{ + src->width = w; + src->uv_width = w; + src->height = h; + src->format = PIX_FMT_YUV444P; + src->uv_height = h; + src->shift_v = 0; + src->len = w * h; + src->uv_len = src->uv_width * src->uv_height; + src->shift_h = 0; + src->data[0] = NULL; + src->data[1] = NULL; + src->data[2] = NULL; +} +int available_diskspace(void) +{ + return 1; +} + +static int possible_veejay_file( const char *file ) +{ + if( strstr( file , ".edl" ) || strstr( file, ".EDL" ) || + strstr( file, ".sl" ) || strstr(file, ".SL" ) || + strstr( file, ".cfg" ) || strstr(file, ".CFG" ) || + strstr( file, ".avi" ) || strstr(file, ".mov" ) ) + return 1; + return 0; +} + +static int try_file( char *path ) +{ + struct stat l; + memset( &l, 0, sizeof( struct stat ) ); + if( lstat(path, &l ) < 0 ) + return 0; + if( S_ISREG(l.st_mode )) + { + if( possible_veejay_file( path ) ) + return 1; + } + return 0; +} + +int verify_working_dir() +{ + char path[1024]; + if(getcwd( path, sizeof(path))== NULL ) + return 0; + struct dirent **files; + int n = scandir( path, &files, NULL, alphasort ); + if( n <= 0 ) + return 0; + + int c = 0; + while( n -- ) { + char tmp[1024]; + snprintf( tmp, sizeof(tmp), "%s/%s", path, files[n]->d_name ); + if( try_file( tmp ) ) + c++; + free( files[n] ); + } + + free(files); + return c; +} + + +int sufficient_space(int max_size, int nframes) +{ +//bogus + return available_diskspace(); +} +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + + +/* the sprintf functions below was stolen and stripped from linux 2.4.33 + * from files: + * linux/lib/vsprintf.c + * asm-i386/div64.h + */ +#ifdef ARCH_X86 +#define do_div(n,base) ({ \ + unsigned long __upper, __low, __high, __mod; \ + asm("":"=a" (__low), "=d" (__high):"A" (n)); \ + __upper = __high; \ + if (__high) { \ + __upper = __high % (base); \ + __high = __high / (base); \ + } \ + asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (base), "0" (__low), "1" (__upper)); \ + asm("":"=A" (n):"a" (__low),"d" (__high)); \ + __mod; \ +}) +#endif +#ifdef ARCH_X86_64 +#define do_div(n,base) \ +({ \ + int _res; \ + _res = ((unsigned long) (n)) % (unsigned) (base); \ + (n) = ((unsigned long) (n)) / (unsigned) (base); \ + _res; \ +}) +#endif + +#if defined(ARCH_X86) || defined(ARCH_X86_64) +static char * kern_number(char * buf, char * end, long long num, int base, int type) +{ + char c,sign=0,tmp[66]; + static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + int i=0; + const char *digits = small_digits; + + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + } + } + + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + + return buf; +} + +static int kern_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ +#ifdef STRICT_CHECKING + assert( size > 0 ); +#endif + int num,flags,base; + char *str, *end, c; + const char *s; + str = buf; + end = buf + size - 1; + + if( end < buf - 1 ) { + end = ((void*)-1); + size = end - buf + 1; + } + + for( ; *fmt; ++fmt ) { + if( *fmt != '%' ) { + if( str <= end ) + *str = *fmt; + ++str; + continue; + } + + flags = 0; + repeat: + ++ fmt; + switch( *fmt ) { + case ' ': flags |= SPACE; goto repeat; + } + + base = 10; + + switch( *fmt ) { + case 'd': + flags |= SIGN; + break; + } + + num = va_arg(args, unsigned int); + if (flags & SIGN) + num = (signed int) num; + + str = kern_number(str, end, num, base, flags); + } + if( str <= end ) + *str = '\0'; + else if ( size > 0 ) + *end = '\0'; + + return str-buf; +} + +/* + * veejay_sprintf can only deal with format 'd' ... it is used to produce + * status lines. + * + * + */ + +int veejay_sprintf( char *s, size_t size, const char *format, ... ) +{ + va_list arg; + int done; + va_start( arg, format ); + done = kern_vsnprintf( s, size, format, arg ); + va_end(arg); + return done; +} +#else +int veejay_sprintf( char *s, size_t size, const char *format, ... ) +{ + va_list arg; + int done; + va_start(arg,format); + done = vsnprintf( s,size, format, arg ); + return done; +} +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-misc.h b/branches/V-1.5.3/veejay-server/veejay/vj-misc.h new file mode 100644 index 00000000..6fff20a1 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-misc.h @@ -0,0 +1,63 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_MISC_H +#define VJ_MISC_H +#include +#include +#include "vj-lib.h" + +typedef struct +{ + char **files; + char *working_dir; + int num_files; + int max_files; +} filelist_t; + +#define VEEJAY_FILE_LIMIT (1048576 * 16000) +int available_diskspace(void); +int vj_perform_screenshot2(veejay_t * info, uint8_t ** src); + +#ifdef ARCH_X86 +int veejay_sprintf( char *s, size_t size, const char *format, ... ); +#define veejay_snprintf veejay_sprintf +#else +#define veejay_snprintf snprintf +#endif + +unsigned int vj_get_relative_time(void); + +void vj_stamp_clear(); +unsigned int vj_stamp(); + +int vj_perform_take_bg( veejay_t *info, VJFrame *src, int pass); + +int veejay_create_temp_file(const char *prefix, char *dst); + +void vj_get_yuv_template(VJFrame *src, int w, int h, int fmt); + +void vj_get_rgb_template(VJFrame *src, int w, int h ); + +void vj_get_yuvgrey_template(VJFrame *src, int w, int h); + +void vj_get_yuv444_template(VJFrame *src, int w, int h); + +int verify_working_dir(); + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-osc.c b/branches/V-1.5.3/veejay-server/veejay/vj-osc.c new file mode 100644 index 00000000..7aa1acc5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-osc.c @@ -0,0 +1,918 @@ +/* + * Copyright (C) 2002-2010 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +/* libOSC + + use ./sendOSC from ${veejay_package_dir}/libOMC/test + to send OSC messages to port VJ_PORT + 4 (usually 3496) + + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +static veejay_t *osc_info; + +#ifdef HAVE_LIBLO +#include +static vevo_port_t **osc_clients = NULL; +#endif + +#include +#include +#include +#include +#include +#include + +typedef struct osc_arg_t { + int a; + int b; + int c; +} osc_arg; + +typedef struct vj_osc_t { + struct OSCAddressSpaceMemoryTuner t; + struct OSCReceiveMemoryTuner rt; + struct OSCContainerQueryResponseInfoStruct cqinfo; + struct OSCMethodQueryResponseInfoStruct ris; + struct sockaddr_in cl_addr; + int sockfd; + int clilen; + fd_set readfds; + OSCcontainer container; + OSCcontainer *leaves; + OSCPacketBuffer packet; + osc_arg *osc_args; + void *index; + void *clients; +} vj_osc; + + +/* VIMS does the job */ +extern void vj_event_fire_net_event(veejay_t *v, int net_id, char *str_arg, int *args, int arglen, int type); + + +#define OSC_STRING_SIZE 255 +#define OPUSH(p) { _old_p_mode = osc_info->uc->playback_mode; osc_info->uc->playback_mode = p; } +#define OPOP() { osc_info->uc->playback_mode = _old_p_mode; } + + +void vj_osc_set_veejay_t(veejay_t *t); + +void *_vj_osc_time_malloc(int num_bytes) ; +void *_vj_osc_rt_malloc(int num_bytes); +int vj_osc_attach_methods( vj_osc *o ); +int vj_osc_build_cont( vj_osc *o ); + +#ifdef ARCH_X86 +/* convert a big endian 32 bit string to an int for internal use */ +static int toInt(const char* b) { + return (( (int) b[3] ) & 0xff ) + ((((int) b[2]) & 0xff) << 8) + ((((int) b[1]) & 0xff) << 16) + + ((((int) b[0] ) & 0xff) << 24); +} +#else +static int toInt(const char *b) +{ + return (( (int) b[0] ) & 0xff ) + (( (int) b[1] & 0xff ) << 8) + ((( (int) b[2])&0xff) << 16 ) + + ((( (int) b[3] ) & 0xff ) << 24); +} +#endif + +/* parse int arguments */ +static int vj_osc_count_int_arguments(int arglen, const void *vargs) +{ + unsigned int num_args = 0; + // type tags indicated with 0x2c + const char *args = (const char*) vargs; + if(args[0] == 0x2c) + { + int i; + // count occurences of 'i' (0x69) + for ( i = 1; i < arglen ; i ++ ) + { + if( args[i] == 0x69 ) num_args ++; + if( (i+1) < arglen && args[i+1] == 0 ) break; + } + } + else + { + // for non typed tags its much simpler, every integer is stored 32 bits + if(arglen < 4) return 0; + num_args = arglen / 4; + } + return num_args; +} + +static int vj_osc_parse_char_arguments(int arglen, const void *vargs, char *dst) +{ + const char *args = (const char*)vargs; + if(arglen <= 4) return 0; + if(args[1] == 0x73) + { + int b = 0; + for(b = 0; b < arglen; b++) + { + dst[b] = args[b+4]; + if(args[b+4] == 0) + break; + } + return arglen; + } + return 0; +} +/* parse int arguments */ +static int vj_osc_parse_int_arguments(int arglen, const void *vargs, int *arguments) +{ + int num_args = vj_osc_count_int_arguments(arglen,vargs); + int i=0; + int offset = 0; + const char *args = (const char*)vargs; + + if(num_args <= 0) + return 0; + + if( args[0] == 0x2c ) + { // type tag + // figure out padding length of typed tag + unsigned int pad = 4 + ( num_args + 1 ) / 4 * 4; + for ( i = 0; i < num_args ; i ++ ) + { + arguments[i] = toInt( args + pad + offset ); + offset += 4; + } + } + else + { + for(i = 0; i < num_args; i ++) + { + arguments[i] = toInt( args + offset); + offset += 4; + } + + } + + return num_args; /* success */ +} + +/* memory allocation functions of libOMC_dirty (OSC) */ + +void *_vj_osc_time_malloc(int num_bytes) { + return vj_malloc( num_bytes ); +} + +void *_vj_osc_rt_malloc(int num_bytes) { + return vj_malloc( num_bytes ); +} + + +/* initialize the pointer to veejay_t */ + +void vj_osc_set_veejay_t(veejay_t *info) { + osc_info = info; +} + +void vj_osc_free(void *d) +{ + if(!d) return; + vj_osc *c = (vj_osc*) d; + void *addr = OSCPacketBufferGetClientAddr(c->packet ); + if(addr) + free(addr); + //if(c->osc_args) free(c->osc_args); + if(c->leaves) free(c->leaves); + if(c->index) vevo_port_free(c->index); + if(c) free(c); + + c = NULL; +} + +#ifdef HAVE_LIBLO +static int osc_has_connection( char *name ) { + + int i; + for( i = 0; i < 32; i ++ ){ + + vevo_port_t *port = osc_clients[i]; + if( port == NULL ) + continue; + + size_t len = vevo_property_element_size( port, "connection", 0 ); +#ifdef STRICT_CHECKING + assert( len > 0 ); +#endif + + char *con = malloc( sizeof(char) * len ); + int err = vevo_property_get(port, "connection", 0,&con ); + if( err == VEVO_NO_ERROR ) { + if( strncasecmp(con,name, strlen(con)) == 0 ) + return 1; + } + } + return 0; +} + +static void osc_add_client(void *context, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) +{ + int client_id = *( (int*) context ); + char str[OSC_STRING_SIZE]; + int args[16]; + int __a = vj_osc_count_int_arguments(arglen,vargs); + int __n = vj_osc_parse_char_arguments(arglen,vargs,str); + memset( args,0,16 ); + str[__n] = '\0'; + + vj_osc_parse_int_arguments( arglen , vargs , args ); + + if( __n > 0 ) __a ++; + + + int free_id = -1; + int i; + for( i = 0; i < 31; i ++ ) { + if(osc_clients[i] == NULL ) { + free_id = i; + break; + } + } + + if( free_id == -1 ) { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to add more OSC senders."); + return; + } + + if( __a != 2 || __n <= 0) { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid arguments, use HOSTNAME PORT"); + return; + } + char port[6]; + snprintf( port, sizeof(port-1), "%d", args[0] ); + char name[1024]; + snprintf(name, sizeof(name)-1, "%s:%s", str,port ); + char *cmd = "/status"; + char *nptr = name; + if( osc_has_connection( name ) ) { + veejay_msg(0, "There already exists a status sender for %s",name); + return; + } + + osc_clients[ free_id ] = vpn(VEVO_ANONYMOUS_PORT ); + lo_address t = lo_address_new( str, port ); + + if(vevo_property_set( osc_clients[free_id], "lo", VEVO_ATOM_TYPE_VOIDPTR,1, &t ) != VEVO_NO_ERROR ) { + veejay_msg(0, "Unable to add lo_address to vevo port."); + vevo_port_free( osc_clients[free_id] ); + osc_clients[free_id] = NULL; + return; + } + + if(vevo_property_set( osc_clients[free_id], "cmd", VEVO_ATOM_TYPE_STRING, 1, &cmd ) != VEVO_NO_ERROR ) { + veejay_msg(0, "Unable to store command '%s'", cmd ); + vevo_port_free(osc_clients[free_id]); + osc_clients[free_id]=NULL; + return; + } + + if( vevo_property_set( osc_clients[free_id], "connection", VEVO_ATOM_TYPE_STRING,1,&nptr ) != VEVO_NO_ERROR ) { + veejay_msg(0, "Unable to store connection string."); + vevo_port_free(osc_clients[free_id]); + osc_clients[free_id] = NULL; + return; + } + + veejay_msg(VEEJAY_MSG_INFO, "Configured OSC sender to %s:%s, send /status [ArgList] every cycle.", + str,port ); +} + +static int osc_client_status_send( lo_address t, char *cmd ) +{ + sample_info *s; + vj_tag *tag; + int err = 0; + + switch( osc_info->uc->playback_mode ) { + case VJ_PLAYBACK_MODE_SAMPLE: + s = sample_get( osc_info->uc->sample_id ); + + err = lo_send( t, + cmd, + "iiiiiiiiiiiiiiii", + osc_info->uc->playback_mode, + osc_info->real_fps, + osc_info->settings->current_frame_num, + osc_info->uc->sample_id, + s->effect_toggle, + s->first_frame, + s->last_frame, + s->speed, + s->dup, + s->looptype, + s->marker_start, + s->marker_end, + (sample_size()-1), + (int)( 100.0f/osc_info->settings->spvf ), + osc_info->settings->cycle_count[0], + osc_info->settings->cycle_count[1], + vj_event_macro_status() ); + + + + break; + case VJ_PLAYBACK_MODE_TAG: + tag = vj_tag_get( osc_info->uc->sample_id ); + + err = lo_send( t, + cmd, + "iiiiiiiiiiiiiiiii", + osc_info->uc->playback_mode, + osc_info->real_fps, + osc_info->settings->current_frame_num, + osc_info->uc->sample_id, + tag->effect_toggle, + 0, + tag->n_frames, + 1,1,1,0,0, + (vj_tag_size()-1), + (int) ( 100.0f/osc_info->settings->spvf ), + osc_info->settings->cycle_count[0], + osc_info->settings->cycle_count[1], + vj_event_macro_status() ); + break; + case VJ_PLAYBACK_MODE_PLAIN: + err = lo_send( t, + cmd, + "iiiiiiiiiiiiiiiiii", + osc_info->uc->playback_mode, + osc_info->real_fps, + osc_info->settings->current_frame_num, + 0, + 0, + osc_info->settings->min_frame_num, + osc_info->settings->max_frame_num, + osc_info->settings->current_playback_speed, + 0,0,0,0,0, + (sample_size()-1 + vj_tag_true_size() - 1), + (int) ( 100.0f / osc_info->settings->spvf ), + osc_info->settings->cycle_count[0], + osc_info->settings->cycle_count[1], + vj_event_macro_status()); + + break; + } + + if( err == -1 ) { + lo_address_free( t ); + return 0; + } + return 1; +} + +static void osc_iterate_clients() +{ + int i; + for( i = 0; i < 32; i ++ ){ + + vevo_port_t *port = osc_clients[i]; + if( port == NULL ) + continue; + lo_address clnt; + int err = vevo_property_get( port, "lo", 0, &clnt ); + if( err == VEVO_NO_ERROR ) { + size_t len = vevo_property_element_size( port, "cmd", 0 ); +#ifdef STRICT_CHECKING + assert( len > 0 ); +#endif + + + char *cmd = malloc( sizeof(char) * len ); + err = vevo_property_get( port, "cmd", 0, &cmd ); + + int res = osc_client_status_send( clnt, cmd ); + if( res == 0 ) { + vevo_port_free( port ); + osc_clients[i] = NULL; + veejay_msg(VEEJAY_MSG_WARNING,"Failed to send %s",cmd); + } + free(cmd); + } + } +} +#endif + +static void osc_vims_method(void *context, int arglen, const void *vargs, OSCTimeTag when, NetworkReturnAddressPtr ra) +{ + int vims_id = *( (int*) context ); + char str[OSC_STRING_SIZE]; + int args[16]; + int __a = vj_osc_count_int_arguments(arglen,vargs); + int __n = vj_osc_parse_char_arguments(arglen,vargs,str); + memset( args,0,16 ); + str[__n] = '\0'; + + vj_osc_parse_int_arguments( arglen , vargs , args ); + + if( __n > 0 ) __a ++; + + vj_event_fire_net_event(osc_info, vims_id, str,args, __a ,0); +} + + +//@ setup osc<-> vims mapping +static struct +{ + const char *name; + const int vims_id; +} osc_method_layout[] = +{ + { "fxlist/inc" , VIMS_FXLIST_INC }, + { "fxlist/dec" , VIMS_FXLIST_DEC }, + { "fxlist/enter" , VIMS_FXLIST_ADD }, + { "fxlist/setbg" , VIMS_EFFECT_SET_BG }, + { "ui/preview" , VIMS_PREVIEW_BW }, + { "macro/macro" , VIMS_MACRO }, + { "macro/select" , VIMS_MACRO_SELECT }, + + { "composite/select" , VIMS_COMPOSITE }, +#ifdef USE_GDK_PIXBUF + { "console/screenshot" , VIMS_SCREENSHOT }, +#else +#ifdef HAVE_JPEG + { "console/screenshot", VIMS_SCREENSHOT }, +#endif +#endif + { "console/framerate" , VIMS_FRAMERATE }, + { "console/bezerk" , VIMS_BEZERK }, +#ifdef HAVE_SDL + { "console/resize" , VIMS_RESIZE_SDL_SCREEN }, +#endif + { "console/renderdepth" , VIMS_RENDER_DEPTH }, + { "console/continuous" , VIMS_CONTINUOUS_PLAY }, +//@ NO VIMS callback! { "console/recviewport" , VIMS_RECVIEWPORT }, + { "console/volume" , VIMS_SET_VOLUME }, + { "console/fullscreen" , VIMS_FULLSCREEN }, + { "console/suspsend" , VIMS_SUSPEND }, + { "console/quit" , VIMS_QUIT }, + { "console/close" , VIMS_CLOSE }, +//@ NO VIMS callback { "console/load" , VIMS_LOAD_PLUGIN }, +//@ NO VIMS callback { "console/unload" , VIMS_UNLOAD_PLUGIN }, +//@ NO VIMS callback { "console/plugcmd" , VIMS_CMD_PLUGIN }, + { "console/dataformat" , VIMS_RECORD_DATAFORMAT }, + { "console/playmode" , VIMS_SET_PLAIN_MODE }, + { "console/load", VIMS_SAMPLE_LOAD_SAMPLELIST }, + { "console/save", VIMS_SAMPLE_SAVE_SAMPLELIST }, +//@ NO VIMS callback { "console/display" VIMS_INIT_GUI_SCREEN }, + { "console/switch" , VIMS_SWITCH_SAMPLE_STREAM }, + { "audio/enable" , VIMS_AUDIO_ENABLE }, + { "audio/disable" , VIMS_AUDIO_DISABLE }, + { "bank/select" , VIMS_SELECT_BANK }, + { "bank/slot" , VIMS_SELECT_ID }, + + { "record/autostart" , VIMS_REC_AUTO_START }, + { "record/stop" , VIMS_REC_STOP }, + { "record/start" , VIMS_REC_START }, + { "sample/mode" , VIMS_SAMPLE_MODE }, + { "sample/play" , VIMS_SET_MODE_AND_GO }, + { "sample/rand/start" , VIMS_SAMPLE_RAND_START }, + { "sample/rand/stop" , VIMS_SAMPLE_RAND_STOP }, + { "sample/rec/start", VIMS_SAMPLE_REC_START }, + { "sample/start", VIMS_SET_SAMPLE_START }, + { "sample/end", VIMS_SET_SAMPLE_END }, + { "sample/new", VIMS_SAMPLE_NEW }, + { "sample/select", VIMS_SAMPLE_SELECT }, + { "sample/delete", VIMS_SAMPLE_DEL }, + { "sample/looptype", VIMS_SAMPLE_SET_LOOPTYPE }, + { "sample/description", VIMS_SAMPLE_SET_DESCRIPTION }, + { "sample/speed", VIMS_SAMPLE_SET_SPEED }, + { "sample/startposition", VIMS_SAMPLE_SET_START }, + { "sample/endposition", VIMS_SAMPLE_SET_END }, + { "sample/slow", VIMS_SAMPLE_SET_DUP }, + { "sample/inpoint", VIMS_SAMPLE_SET_MARKER_START }, + { "sample/outpoint", VIMS_SAMPLE_SET_MARKER_END }, + { "sample/clearpoints", VIMS_SAMPLE_CLEAR_MARKER }, + { "sample/edladd", VIMS_EDITLIST_ADD_SAMPLE }, + { "sample/killall", VIMS_SAMPLE_DEL_ALL }, + { "sample/copy", VIMS_SAMPLE_COPY }, + { "sample/recstart", VIMS_SAMPLE_REC_START }, + { "sample/recstop", VIMS_SAMPLE_REC_STOP }, + { "sample/fx/on", VIMS_SAMPLE_CHAIN_ENABLE }, + { "sample/fx/off", VIMS_SAMPLE_CHAIN_DISABLE }, + { "sample/looptoggle", VIMS_SAMPLE_TOGGLE_LOOP }, + { "stream/play" , VIMS_SET_MODE_AND_GO }, + { "stream/delete", VIMS_STREAM_DELETE }, + { "stream/new/v4l", VIMS_STREAM_NEW_V4L }, +#ifdef SUPPORT_READ_DV2 + { "stream/new/dv1394", VIMS_STREAM_NEW_DV1394 }, +#endif + { "stream/new/solid", VIMS_STREAM_NEW_COLOR }, + { "stream/new/y4m", VIMS_STREAM_NEW_Y4M }, + { "stream/new/cali", VIMS_STREAM_NEW_CALI }, + { "stream/startcali", VIMS_V4L_BLACKFRAME }, + { "stream/savecali", VIMS_V4L_CALI }, + { "stream/unicast", VIMS_STREAM_NEW_UNICAST }, + { "stream/mcast", VIMS_STREAM_NEW_MCAST }, + { "stream/new/picture", VIMS_STREAM_NEW_PICTURE }, + { "stream/offline/recstart", VIMS_STREAM_OFFLINE_REC_START }, + { "stream/offline/recstop", VIMS_STREAM_OFFLINE_REC_STOP }, + { "stream/fx/on", VIMS_STREAM_CHAIN_ENABLE }, + { "stream/fx/off", VIMS_STREAM_CHAIN_DISABLE }, + { "stream/rec/start", VIMS_STREAM_REC_START }, + { "stream/rec/stop", VIMS_STREAM_REC_STOP }, + { "stream/v4l/brightness", VIMS_STREAM_SET_BRIGHTNESS }, + { "stream/v4l/contrast", VIMS_STREAM_SET_CONTRAST }, + { "stream/v4l/hue", VIMS_STREAM_SET_HUE }, + { "stream/v4l/color", VIMS_STREAM_SET_COLOR }, + { "stream/v4l/whitebalance", VIMS_STREAM_SET_WHITE }, + { "stream/v4l/saturation", VIMS_STREAM_SET_SATURATION }, + { "stream/length", VIMS_STREAM_SET_LENGTH }, + { "stream/color", VIMS_STREAM_COLOR }, + + { "video/forward" , VIMS_VIDEO_PLAY_FORWARD }, + { "video/play" , VIMS_VIDEO_PLAY_FORWARD }, +//@FIXME { "video/reverse" , VIMS_VIDEO_PLAY_REVERSE }, + { "video/pause" , VIMS_VIDEO_PLAY_STOP }, + { "video/nextframe" , VIMS_VIDEO_SKIP_FRAME }, + { "video/prevframe" , VIMS_VIDEO_PREV_FRAME }, + { "video/nextsecond" , VIMS_VIDEO_SKIP_SECOND }, + { "video/prevsecond" , VIMS_VIDEO_PREV_SECOND }, + { "video/gotostart" , VIMS_VIDEO_GOTO_START }, + { "video/gotoend" , VIMS_VIDEO_GOTO_END }, + { "video/frame" , VIMS_VIDEO_SET_FRAME }, + { "video/speed" , VIMS_VIDEO_SET_SPEED }, + { "video/slow" , VIMS_VIDEO_SET_SLOW }, + { "mcast/start", VIMS_VIDEO_MCAST_START }, + { "mcast/end", VIMS_VIDEO_MCAST_STOP }, + { "video/speedk", VIMS_VIDEO_SET_SPEEDK }, + + { "editlist/paste", VIMS_EDITLIST_PASTE_AT }, + { "editlist/copy", VIMS_EDITLIST_COPY }, + { "editlist/cut", VIMS_EDITLIST_CUT }, + { "editlist/crop", VIMS_EDITLIST_CROP }, + { "editlist/add", VIMS_EDITLIST_ADD }, + { "editlist/save", VIMS_EDITLIST_SAVE }, + { "editlist/load", VIMS_EDITLIST_LOAD }, + +//@ NO VIMS callback! { "stream/activate", VIMS_STREAM_ACTIVATE }, +//@ NO VIMS callback! { "stream/deactivate", VIMS_STREAM_DEACTIVATE }, + { "sequence/status", VIMS_SEQUENCE_STATUS }, + { "sequence/set", VIMS_SEQUENCE_ADD }, + { "sequence/del", VIMS_SEQUENCE_DEL }, + { "projection/inc", VIMS_PROJ_INC }, + { "projection/dec", VIMS_PROJ_DEC }, + { "projection/set", VIMS_PROJ_SET_POINT }, + { "projection/stack", VIMS_PROJ_STACK }, + { "projection/toggle", VIMS_PROJ_TOGGLE }, + { "chain/enable", VIMS_CHAIN_ENABLE }, + { "chain/disable", VIMS_CHAIN_DISABLE }, + { "chain/fadein", VIMS_CHAIN_FADE_IN }, + { "chain/fadeout", VIMS_CHAIN_FADE_OUT }, + { "chain/clear", VIMS_CHAIN_CLEAR }, +// { "chain/entry/preset", VIMS_CHAIN_ENTRY_PRESET }, + { "chain/opacity", VIMS_CHAIN_MANUAL_FADE }, + { "chain/entry/setarg", VIMS_CHAIN_ENTRY_SET_ARG_VAL }, + { "chain/entry/defaults", VIMS_CHAIN_ENTRY_SET_DEFAULTS }, + { "chain/entry/channel", VIMS_CHAIN_ENTRY_SET_CHANNEL }, + { "chain/entry/source", VIMS_CHAIN_ENTRY_SET_SOURCE }, + { "chain/entry/srccha", VIMS_CHAIN_ENTRY_SET_SOURCE_CHANNEL }, + { "chain/entry/clear", VIMS_CHAIN_ENTRY_CLEAR }, + { "chain/entry/up", VIMS_CHAIN_ENTRY_UP }, + { "chain/entry/down", VIMS_CHAIN_ENTRY_DOWN }, + { "chain/entry/srctoggle", VIMS_CHAIN_ENTRY_SOURCE_TOGGLE }, + { "chain/entry/incarg", VIMS_CHAIN_ENTRY_INC_ARG }, + { "chain/entry/decarg", VIMS_CHAIN_ENTRY_DEC_ARG }, +// { "chain/entry/toggle", VIMS_CHAIN_ENTRY_TOGGLE }, + { "chain/entry/state", VIMS_CHAIN_ENTRY_SET_STATE} , + { "chain/channel/inc", VIMS_CHAIN_ENTRY_CHANNEL_INC }, + { "chain/channel/dec", VIMS_CHAIN_ENTRY_CHANNEL_DEC }, +// { "chain/entry/channel/up", VIMS_CHAIN_ENTRY_CHANNEL_UP }, +// { "chain/entry/channel/down", VIMS_CHAIN_ENTRY_CHANNEL_DOWN }, +#ifdef HAVE_FREETYPE + { "display/copyright", VIMS_COPYRIGHT }, +#endif + { "vloopback/start", VIMS_VLOOPBACK_START }, + { "vloopback/stop", VIMS_VLOOPBACK_STOP }, + { "y4m/start", VIMS_OUTPUT_Y4M_START }, + { "y4m/stop", VIMS_OUTPUT_Y4M_STOP }, +#ifdef HAVE_LIBLO + { "osc/sender", -2 }, +#endif + { NULL, -1 } +}; + +static char **string_tokenize( const char delim, const char *name, int *ntokens ) { + int n = strlen(name); + int i; + int n_tokens = 0; + for( i = 0; i < n; i ++ ) + if( name[i] == delim ) + n_tokens ++; + + if( n_tokens == 0 ) + return NULL; + + n_tokens ++; + + char **arr = (char**) malloc(sizeof(char*) * (n_tokens+1)); + int end = 0; + int p = 0; + char *ptr = (char*) name; + int last = 0; + for( i = 0; i < n ; i ++ ){ + if( name[i] == delim ) { + if( *ptr == delim ) + { *ptr ++; last ++; } + + arr[p] = strndup( ptr , end ); + ptr += end; + last += end; + end = 0; + p++; + } else { + end ++; + } + + } + + arr[p] = strdup( name + last + 1 ); + arr[p+1] = NULL; + *ntokens = n_tokens+1; + + return arr; +} + +static void free_token( char **arr ) { + int i = 0; + for( i = 0; arr[i] != NULL ; i ++ ) { + free(arr[i]); + arr[i] = NULL; + } + free(arr); + arr = NULL; +} + + +int vj_osc_build_cont( vj_osc *o ) +{ + int i; + + o->index = vpn( VEVO_ANONYMOUS_PORT ); + int leave_id = 0; + int next_id = 0; + int err = 0; + int t = 0; + + for( i = 0; osc_method_layout[i].name != NULL ; i ++ ) { + int ntokens = 0; + char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens); + if( arr == NULL || ntokens == 0 ) { + continue; + } + + err = vevo_property_get(o->index, arr[0] , 0, &leave_id ); + if( err == VEVO_NO_ERROR ) { + free_token(arr); + continue; + } + o->leaves[next_id] = OSCNewContainer( arr[0], o->container, &(o->cqinfo) ); + err = vevo_property_set(o->index, arr[0], VEVO_ATOM_TYPE_INT , 1, &next_id); + next_id ++; + } + + for( i = 0; osc_method_layout[i].name != NULL ; i ++ ) { + int ntokens = 0; + int exists = 0; + int attach_id = 0; + char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens); + if( arr == NULL || ntokens == 0 ) { + continue; + } + int containers = ntokens - 1; + + for( t = 1; t < containers; t ++ ) { + int is_method = (t == (containers-1)) ? 1: 0; + if( is_method ) + continue; + + err = vevo_property_get( o->index, arr[t-1], 0, &attach_id ); +#ifdef STRICT_CHECKING + assert( err == VEVO_NO_ERROR ); +#endif + + err = vevo_property_get( o->index, arr[t], 0, &exists ); + if( err == VEVO_NO_ERROR ) { + continue; + } + + o->leaves[next_id] = OSCNewContainer( arr[t], o->leaves[attach_id], &(o->cqinfo )); + + err = vevo_property_set( o->index, arr[t], VEVO_ATOM_TYPE_INT, 1, &next_id ); +#ifdef STRICT_CHECKING + assert(err==VEVO_NO_ERROR); +#endif + + next_id ++; + + //veejay_msg(0, "Added leave '%s'%d to container '%s'%d", arr[t],next_id-1,arr[t-1],attach_id); + } + } + + + for( i = 0; osc_method_layout[i].name != NULL ; i ++ ) { + int ntokens = 0; + char **arr = string_tokenize( '/', osc_method_layout[i].name, &ntokens); + if( arr == NULL || ntokens == 0 ) + continue; + int containers = ntokens - 1; + if( containers == 0 ) { + free_token(arr); + continue; + } + + int method = containers - 1; + + err = vevo_property_get( o->index, arr[method-1], 0, &leave_id ); +#ifdef STRICT_CHECKING + assert( err == VEVO_NO_ERROR ); +#endif + +#ifdef HAVE_LIBLO + if( osc_method_layout[i].vims_id == -2 ) { + o->ris.description = strdup( "Setup a OSC sender (Arg 0=host, 1=port)"); + OSCNewMethod( arr[method], + o->leaves[leave_id], + osc_add_client, + &(osc_method_layout[i].vims_id), + &(o->ris)); + } else { + o->ris.description = vj_event_vevo_get_event_name( osc_method_layout[i].vims_id ); + OSCNewMethod( arr[ method ], o->leaves[ leave_id ], osc_vims_method, &(osc_method_layout[i].vims_id),&(o->ris)); + + } +#else + o->ris.description = vj_event_vevo_get_event_name( osc_method_layout[i].vims_id ); + OSCNewMethod( arr[ method ], o->leaves[ leave_id ], osc_vims_method, &(osc_method_layout[i].vims_id),&(o->ris)); + +#endif + } + + return 1; +} + + +/* initialization, setup a UDP socket and invoke OSC magic */ +void* vj_osc_allocate(int port_id) { + void *res; + char tmp[200]; + int i; + vj_osc *o = (vj_osc*)vj_malloc(sizeof(vj_osc)); +#ifdef HAVE_LIBLO + osc_clients = (vevo_port_t*) vj_malloc(sizeof(vevo_port_t*) * 32); + for( i = 0; i < 32 ;i ++ ) + osc_clients[i] = NULL; +#endif + //o->osc_args = (osc_arg*)vj_malloc(50 * sizeof(*o->osc_args)); + o->rt.InitTimeMemoryAllocator = _vj_osc_time_malloc; + o->rt.RealTimeMemoryAllocator = _vj_osc_rt_malloc; + o->rt.receiveBufferSize = 1024; + o->rt.numReceiveBuffers = 100; + o->rt.numQueuedObjects = 100; + o->rt.numCallbackListNodes = 300; + o->leaves = (OSCcontainer*) vj_malloc(sizeof(OSCcontainer) * 300); + o->t.initNumContainers = 300; + o->t.initNumMethods = 300; + o->t.InitTimeMemoryAllocator = _vj_osc_time_malloc; + o->t.RealTimeMemoryAllocator = _vj_osc_rt_malloc; + + if(OSCInitReceive( &(o->rt))==FALSE) { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot initialize OSC receiver"); + return NULL; + } + o->packet = OSCAllocPacketBuffer(); + + if(NetworkStartUDPServer( o->packet, port_id) != TRUE) { + veejay_msg(VEEJAY_MSG_ERROR, "(VIMS) Cannot start OSC/UDP server at port %d ", + port_id); + } + + if( IsMultiCast( tmp ) ) + { + veejay_msg(VEEJAY_MSG_INFO, "Multicast address %s, port %d", + tmp, port_id ); + } + + /* Top level container / */ + o->container = OSCInitAddressSpace(&(o->t)); + + OSCInitContainerQueryResponseInfo( &(o->cqinfo) ); + o->cqinfo.comment = "Video commands"; + + if( !vj_osc_build_cont( o )) + return NULL; + + OSCInitMethodQueryResponseInfo( &(o->ris)); +// if( !vj_osc_attach_methods( o )) +// return NULL; + + res =(void*) o; + return res; +} + + +void vj_osc_dump() +{ + + OSCPrintWholeAddressSpace(); +#ifdef HAVE_LIBLO + veejay_msg(VEEJAY_MSG_INFO, "The OSC command /osc/sender will setup an OSC client"); + veejay_msg(VEEJAY_MSG_INFO, "which periodically sends veejay's status information. Format below:"); + + veejay_msg(VEEJAY_MSG_INFO, + "/status ( [playback mode], [real fps], [frame num], [sample_id], [fx on/off], [first frame],"); + veejay_msg(VEEJAY_MSG_INFO, + " [last_frame],[speed],[slow],[looptype],[in point],[out point],[num samples],"); + veejay_msg(VEEJAY_MSG_INFO, + " [second per video frame],[cycle count low],[cycle count high],[macro status]) "); + veejay_msg(VEEJAY_MSG_INFO,"\n"); +#endif + +} + +/* dump the OSC address space to screen */ +int vj_osc_setup_addr_space(void *d) { + char addr[100]; + vj_osc *o = (vj_osc*) d; + //struct OSCMethodQueryResponseInfoStruct qri; + + if(OSCGetAddressString( addr, 100, o->container ) == FALSE) { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot get address space of OSC"); + return -1; + } + veejay_msg(VEEJAY_MSG_DEBUG, "Address of top level container [%s]",addr); + return 0; +} + + +/* get a packet */ +int vj_osc_get_packet(void *d) { + //OSCTimeTag tag; + struct timeval tv; + tv.tv_sec=0; + tv.tv_usec = 0; + vj_osc *o = (vj_osc*) d; +#ifdef HAVE_LIBLO + osc_iterate_clients(); +#endif + /* see if there is something to read , this is effectivly NetworkPacketWaiting */ + // if(ioctl( o->sockfd, FIONREAD, &bytes,0 ) == -1) return 0; + // if(bytes==0) return 0; + if(NetworkPacketWaiting(o->packet)==TRUE) { + /* yes, receive packet from UDP */ + if(NetworkReceivePacket(o->packet) == TRUE) { + /* OSC must accept this packet (OSC will auto-invoke it, see source !) */ + OSCAcceptPacket(o->packet); + /* Is this really productive ? */ + OSCBeProductiveWhileWaiting(); + /* tell caller we had 1 packet */ + return 1; + } + } + return 0; +} + + diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-perform.c b/branches/V-1.5.3/veejay-server/veejay/vj-perform.c new file mode 100644 index 00000000..c6e711fd --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-perform.c @@ -0,0 +1,3697 @@ +/* + * veejay + * + * Copyright (C) 2000-2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_FREETYPE +#include +#endif +#define RECORDERS 1 +#ifdef HAVE_JACK +#include +#endif +#include +#include +#include +#ifdef STRICT_CHECKING +#include +#endif + +#define PERFORM_AUDIO_SIZE 16384 + +typedef struct { + uint8_t *Y; + uint8_t *Cb; + uint8_t *Cr; + uint8_t *alpha; + uint8_t *P0; + uint8_t *P1; + int ssm; + char padding[12]; +} ycbcr_frame; + +typedef struct { + int fader_active; + int follow_fade; + int follow_now[2]; + int follow_run; + int fx_status; + int enc_active; + int type; + int active; + char padding[12]; +} varcache_t; + +#define RUP8(num)(((num)+8)&~8) + +static varcache_t pvar_; +static void *lzo_; +static void *effect_sampler = NULL; +static void *crop_sampler = NULL; +static VJFrame *crop_frame = NULL; +static ycbcr_frame **video_output_buffer = NULL; /* scaled video output */ +static int video_output_buffer_convert = 0; +static ycbcr_frame **frame_buffer; /* chain */ +static ycbcr_frame **primary_buffer; /* normal */ +#define CACHE_TOP 0 +#define CACHE 1 +#define CACHE_SIZE (SAMPLE_MAX_EFFECTS+CACHE) +static int cached_tag_frames[CACHE_SIZE]; /* cache a frame into the buffer only once */ +static int cached_sample_frames[CACHE_SIZE]; +static int frame_info[64][SAMPLE_MAX_EFFECTS]; /* array holding frame lengths */ +static uint8_t *audio_buffer[SAMPLE_MAX_EFFECTS]; /* the audio buffer */ +static uint8_t *lin_audio_buffer_ = NULL; +static uint8_t *top_audio_buffer = NULL; +static uint8_t *resample_audio_buffer = NULL; +static uint8_t *audio_render_buffer = NULL; +static uint8_t *down_sample_buffer = NULL; +static uint8_t *temp_buffer[4]; +static ycbcr_frame *record_buffer = NULL; // needed for recording invisible streams +static VJFrame *helper_frame = NULL; +static int vj_perform_record_buffer_init(); +static void vj_perform_record_buffer_free(); +#ifdef HAVE_JACK +static ReSampleContext *resample_context[(MAX_SPEED+1)]; +static ReSampleContext *downsample_context[(MAX_SPEED+1)]; +static ReSampleContext *resample_jack = NULL; +#endif +static const char *intro = + "A visual instrument for GNU/Linux\n"; +static const char *license = + "This program is licensed as\nFree Software (GNU/GPL version 2)\n\nFor more information see:\nhttp://veejayhq.net\nhttp://veejay.dyne.org\nhttp://www.sourceforge.net/projects/veejay\nhttp://www.gnu.org"; +static const char *copyr = + "(C) 2002-2008 Copyright N.Elburg et all (nwelburg@gmail.com)\n"; + +#define MLIMIT(var, low, high) \ +if((var) < (low)) { var = (low); } \ +if((var) > (high)) { var = (high); } + +//forward +static int vj_perform_preprocess_secundary( veejay_t *info, int id, int mode,int current_ssm,int chain_entry, VJFrame **frames, VJFrameInfo *frameinfo ); +static int vj_perform_preprocess_has_ssm( veejay_t *info, int id, int mode); +static int vj_perform_get_frame_fx(veejay_t *info, int s1, long nframe, uint8_t *frame[3], uint8_t *p0plane, uint8_t *p1plane); +static void vj_perform_pre_chain(veejay_t *info, VJFrame *frame); +static int vj_perform_post_chain_sample(veejay_t *info, VJFrame *frame); +static int vj_perform_post_chain_tag(veejay_t *info, VJFrame *frame); +static void seq_play_sample( veejay_t *info, int n); +static void vj_perform_plain_fill_buffer(veejay_t * info); +static int vj_perform_tag_fill_buffer(veejay_t * info); +static void vj_perform_clear_cache(void); +static int vj_perform_increase_tag_frame(veejay_t * info, long num); +static int vj_perform_increase_plain_frame(veejay_t * info, long num); +static void vj_perform_apply_secundary_tag(veejay_t * info, int sample_id,int type, int chain_entry); +static void vj_perform_apply_secundary(veejay_t * info, int sample_id,int type, int chain_entry); +static int vj_perform_tag_complete_buffers(veejay_t * info, int *h); +static int vj_perform_increase_sample_frame(veejay_t * info, long num); +static int vj_perform_sample_complete_buffers(veejay_t * info, int *h); +static void vj_perform_use_cached_ycbcr_frame(veejay_t *info, int centry, int chain_entry, int width, int height); +static int vj_perform_apply_first(veejay_t *info, vjp_kf *todo_info, VJFrame **frames, VJFrameInfo *frameinfo, int e, int c, int n_frames ); +static int vj_perform_render_sample_frame(veejay_t *info, uint8_t *frame[4], int sample); +static int vj_perform_render_tag_frame(veejay_t *info, uint8_t *frame[4]); +static int vj_perform_record_commit_single(veejay_t *info); +static int vj_perform_get_subframe(veejay_t * info, int sub_sample,int chain_entyr ); +static int vj_perform_get_subframe_tag(veejay_t * info, int sub_sample, int chain_entry ); +static void vj_perform_reverse_audio_frame(veejay_t * info, int len, uint8_t *buf ); + +static int vj_perform_tag_is_cached(int chain_entry, int tag_id) +{ + int c; + int res = -1; + for(c=0; c < CACHE_SIZE; c++) + { + if(chain_entry != c && cached_tag_frames[c] == tag_id) + { + res = c; + break; + } + } + + return res; +} +static int vj_perform_sample_is_cached(int nframe, int chain_entry) +{ + int c; + int res = -1; + for(c=0; c < CACHE_SIZE ; c++) + { + if(chain_entry != c && cached_sample_frames[c] == nframe) + { + res = c; + break; + } + } + return res; +} + +void vj_perform_clear_frame_info() +{ + int c = 0; + for (c = 0; c < SAMPLE_MAX_EFFECTS; c++) { + frame_info[0][c] = 0; + } +} + + +static void vj_perform_clear_cache() +{ + veejay_memset(cached_tag_frames, 0 , sizeof(cached_tag_frames)); + veejay_memset(cached_sample_frames, 0, sizeof(cached_sample_frames)); +} + +static int vj_perform_increase_tag_frame(veejay_t * info, long num) +{ + video_playback_setup *settings = info->settings; + settings->current_frame_num += num; + + if (settings->current_frame_num < settings->min_frame_num) { + settings->current_frame_num = settings->min_frame_num; + if (settings->current_playback_speed < 0) { + settings->current_playback_speed = + +(settings->current_playback_speed); + } + return -1; + } + if (settings->current_frame_num >= settings->max_frame_num) { + settings->current_frame_num = settings->min_frame_num; + return -1; + } + return 0; +} + + +static int vj_perform_increase_plain_frame(veejay_t * info, long num) +{ + video_playback_setup *settings = info->settings; + + settings->simple_frame_dup ++; + if (settings->simple_frame_dup >= info->sfd) { + settings->current_frame_num += num; + settings->simple_frame_dup = 0; + } + +// auto loop plain mode + if (settings->current_frame_num < settings->min_frame_num) { + settings->current_frame_num = settings->max_frame_num; + + return 0; + } + if (settings->current_frame_num > settings->max_frame_num) { + if(!info->continuous) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Reached end of video - Ending veejay session ... "); + veejay_change_state(info, LAVPLAY_STATE_STOP); + } + settings->current_frame_num = settings->min_frame_num; + return 0; + } + return 0; +} + + +static int vj_perform_valid_sequence( veejay_t *info ) +{ + int cur = info->seq->current + 1; + int cycle = 0; + while( info->seq->samples[ cur ] == 0 ) + { + cur ++; + if( cur >= MAX_SEQUENCES && !cycle) + { + cur = 0; + cycle = 1; + } + else if ( cur >= MAX_SEQUENCES && cycle ) + { + veejay_msg(VEEJAY_MSG_ERROR, "No valid sequence to play. Sequence Play disabled"); + info->seq->active = 0; + return -1; + } + } + return cur; +} + +static int vj_perform_try_sequence( veejay_t *info ) +{ + if(! info->seq->active ) + return 0; + + if( sample_get_loop_dec( info->uc->sample_id ) >= 1 ) + { + int n = vj_perform_valid_sequence( info ); + if( n >= 0 ) + { + sample_set_loop_dec( info->uc->sample_id, 0 ); //reset loop + + veejay_msg(0, "Sequence play selects sample %d", info->seq->samples[info->seq->current]); + + seq_play_sample(info, n ); + return 1; + } + return 0; + } + + return 0; +} + +static void seq_play_sample( veejay_t *info, int n) +{ + + info->seq->current = n; + + int id = info->seq->samples[n]; + + if(id) + { + sample_chain_free( info->uc->sample_id ); + sample_chain_malloc( id ); + } + + int which_sample = 0; + int offset = sample_get_first_mix_offset( info->uc->sample_id, &which_sample, info->seq->samples[info->seq->current] ); + + veejay_set_sample_f( info, info->seq->samples[ info->seq->current ] , offset ); +} + +static int vj_perform_increase_sample_frame(veejay_t * info, long num) +{ + video_playback_setup *settings = + (video_playback_setup *) info->settings; + int start,end,looptype,speed; + int ret_val = 1; + + if(num == 0 ) return 1; + + if(sample_get_short_info(info->uc->sample_id,&start,&end,&looptype,&speed)!=0) return -1; + + settings->current_playback_speed = speed; + + int cur_sfd = sample_get_framedups( info->uc->sample_id ); + int max_sfd = sample_get_framedup( info->uc->sample_id ); + cur_sfd ++; + + if( max_sfd > 0 ) { + if( cur_sfd >= max_sfd ) + { + // settings->current_frame_num += num; + cur_sfd = 0; + } + sample_set_framedups( info->uc->sample_id , cur_sfd); + if( cur_sfd != 0 ) + return 1; + } + settings->current_frame_num += num; + + if (speed >= 0) { /* forward play */ + + if(looptype==3) + { + int range = end - start; + int num = start + ((int) ( (double)range * rand()/(RAND_MAX))); + settings->current_frame_num = num; + } + + if (settings->current_frame_num > end || settings->current_frame_num < start) { + switch (looptype) { + case 2: + sample_loopcount( info->uc->sample_id); + info->uc->direction = -1; + if(!vj_perform_try_sequence( info ) ) + { + editlist *E = sample_get_editlist(info->uc->sample_id); + sample_apply_loop_dec( info->uc->sample_id,E->video_fps); + veejay_set_frame(info, end); + veejay_set_speed(info, (-1 * speed)); + } + sample_loopcount( info->uc->sample_id); + break; + case 1: + sample_loopcount( info->uc->sample_id); + if(! info->seq->active ) + veejay_set_frame(info, start); + else + { + int n = vj_perform_valid_sequence( info ); + if( n >= 0 ) + { + seq_play_sample( info, n ); + } + else + veejay_set_frame(info,start); + } + break; + case 3: + sample_loopcount( info->uc->sample_id); + veejay_set_frame(info, start); + break; + default: + veejay_set_frame(info, end); + veejay_set_speed(info, 0); + } + } + } else { /* reverse play */ + if( looptype == 3 ) + { + int range = end - start; + int num = end - ((int) ( (double)range*rand()/(RAND_MAX))); + settings->current_frame_num = num; + } + + if (settings->current_frame_num < start || settings->current_frame_num >= end ) { + switch (looptype) { + case 2: + sample_loopcount( info->uc->sample_id); + + info->uc->direction = 1; + if(!vj_perform_try_sequence(info) ) + { + editlist *E = sample_get_editlist(info->uc->sample_id); + sample_apply_loop_dec( info->uc->sample_id, E->video_fps); + veejay_set_frame(info, start); + veejay_set_speed(info, (-1 * speed)); + } + break; + case 1: + sample_loopcount( info->uc->sample_id); + + if(!info->seq->active) + veejay_set_frame(info, end); + else + { + int n = vj_perform_valid_sequence( info ); + if( n >= 0 ) + { + seq_play_sample(info, n ); + } + else + veejay_set_frame(info,end); + } + break; + case 3: + sample_loopcount( info->uc->sample_id); + + veejay_set_frame(info,end); + break; + default: + veejay_set_frame(info, start); + veejay_set_speed(info, 0); + } + } + } + sample_update_offset( info->uc->sample_id, settings->current_frame_num ); + vj_perform_rand_update( info ); + + return ret_val; +} + +static long vj_perform_alloc_row(veejay_t *info, int c, int frame_len) +{ + uint8_t *buf = vj_malloc(sizeof(uint8_t) * RUP8(helper_frame->len * 3 * 3)); +#ifdef STRICT_CHECKING + assert ( buf != NULL ); +#endif + if(!buf) + return 0; + + frame_buffer[c]->Y = buf; + frame_buffer[c]->Cb = frame_buffer[c]->Y + RUP8(frame_len); + frame_buffer[c]->Cr = frame_buffer[c]->Cb + RUP8(frame_len); + + frame_buffer[c]->ssm = info->effect_frame1->ssm; + frame_buffer[c]->P0 = buf + RUP8(helper_frame->len*3); + frame_buffer[c]->P1 = frame_buffer[c]->P0 + RUP8(helper_frame->len*3); + return (long) (RUP8(helper_frame->len*3*3)); +} + +static void vj_perform_free_row(int c) +{ + if(frame_buffer[c]->Y) + free( frame_buffer[c]->Y ); + frame_buffer[c]->Y = NULL; + frame_buffer[c]->Cb = NULL; + frame_buffer[c]->Cr = NULL; + frame_buffer[c]->ssm = 0; + frame_buffer[c]->P0 = NULL; + frame_buffer[c]->P1 = NULL; + cached_sample_frames[c+1] = 0; + cached_tag_frames[c+1] = 0; +} + +#define vj_perform_row_used(c) ( frame_buffer[c]->Y == NULL ? 0 : 1 ) + +static int vj_perform_verify_rows(veejay_t *info ) +{ + if( pvar_.fx_status == 0 ) + return 0; + + int c,v,has_rows = 0; + const int w = info->current_edit_list->video_width; + const int h = info->current_edit_list->video_height; + long total_size = 0; + for(c=0; c < SAMPLE_MAX_EFFECTS; c++) + { + v = (info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ? + sample_get_effect_any(info->uc->sample_id,c) : vj_tag_get_effect_any(info->uc->sample_id,c)); + if( v > 0) + { + if(!vj_perform_row_used(c)) + { + long size = vj_perform_alloc_row( info, c, w*h); + if( size <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to allocate memory for FX entry %d",c); + veejay_change_state( info, LAVPLAY_STATE_STOP ); + return -1; + } + else { + total_size += size; + } + } + has_rows ++; + } + else + { + if(vj_perform_row_used(c)) + vj_perform_free_row(c); + } + } +#ifdef STRICT_CHECKING + if(total_size > 0) { + veejay_msg(VEEJAY_MSG_DEBUG, "Total Mb used in FX Chain: %2.2f", (float) (total_size / 1048576.0f ) ); + } +#endif + return has_rows; +} + + +static int vj_perform_record_buffer_init() +{ + if(record_buffer->Cb==NULL) + record_buffer->Cb = (uint8_t*)vj_malloc(sizeof(uint8_t) * RUP8(helper_frame->uv_len) ); + if(!record_buffer->Cb) return 0; + if(record_buffer->Cr==NULL) + record_buffer->Cr = (uint8_t*)vj_malloc(sizeof(uint8_t) * RUP8(helper_frame->uv_len) ); + if(!record_buffer->Cr) return 0; + + if(record_buffer->Y == NULL) + record_buffer->Y = (uint8_t*)vj_malloc(sizeof(uint8_t) * RUP8(helper_frame->len)); + if(!record_buffer->Y) return 0; + + veejay_memset( record_buffer->Y , 16, helper_frame->len ); + veejay_memset( record_buffer->Cb, 128, helper_frame->uv_len ); + veejay_memset( record_buffer->Cr, 128, helper_frame->uv_len ); + + return 1; +} + +static void vj_perform_record_buffer_free() +{ + + if(record_buffer->Y) free(record_buffer->Y); + record_buffer->Y = NULL; + if(record_buffer->Cb) free(record_buffer->Cb); + record_buffer->Cb = NULL; + if(record_buffer->Cr) free(record_buffer->Cr); + record_buffer->Cr = NULL; + if(record_buffer) + free(record_buffer); +} +static char ppm_path[1024]; + +static long CYCLE_CAP = 0; //@ saturate cycle counter at this boundary value + +int vj_perform_init(veejay_t * info) +{ + const int w = info->edit_list->video_width; + const int h = info->edit_list->video_height; + const int frame_len = ((w * h)/7) * 8; + int c; + // buffer used to store encoded frames (for plain and sample mode) + frame_buffer = (ycbcr_frame **) vj_malloc(sizeof(ycbcr_frame*) * SAMPLE_MAX_EFFECTS); + if(!frame_buffer) return 0; + + record_buffer = (ycbcr_frame*) vj_malloc(sizeof(ycbcr_frame) ); + if(!record_buffer) return 0; + record_buffer->Y = NULL; + record_buffer->Cb = NULL; + record_buffer->Cr = NULL; + + primary_buffer = + (ycbcr_frame **) vj_malloc(sizeof(ycbcr_frame **) * 8); + if(!primary_buffer) return 0; + for( c = 0; c < 6; c ++ ) + { + primary_buffer[c] = (ycbcr_frame*) vj_calloc(sizeof(ycbcr_frame)); + primary_buffer[c]->Y = (uint8_t*) vj_malloc( sizeof(uint8_t) * RUP8((frame_len+w) * 3) ); +#ifdef STRICT_CHECKING + assert( primary_buffer[c] != NULL ); + assert( primary_buffer[c]->Y != NULL ); +#endif + primary_buffer[c]->Cb = primary_buffer[c]->Y + (frame_len + w); + primary_buffer[c]->Cr = primary_buffer[c]->Cb + (frame_len +w); + + veejay_memset( primary_buffer[c]->Y, 0, (frame_len+w)); + veejay_memset( primary_buffer[c]->Cb,128, (frame_len+w)); + veejay_memset( primary_buffer[c]->Cr,128, (frame_len+w)); + } + + + primary_buffer[6] = (ycbcr_frame*) vj_calloc(sizeof(ycbcr_frame)); + primary_buffer[6]->Y = (uint8_t*) vj_calloc( sizeof(uint8_t) * RUP8(512 * 512 * 3)); + //@ layout of primary_buffer[6] is flat, only Y + + + + primary_buffer[7] = (ycbcr_frame*) vj_calloc(sizeof(ycbcr_frame)); + primary_buffer[7]->Y = (uint8_t*) vj_calloc( sizeof(uint8_t) * RUP8(w * h * 3)); + primary_buffer[7]->Cb = primary_buffer[7]->Y + ( RUP8(w*h)); + primary_buffer[7]->Cr = primary_buffer[7]->Cb + ( RUP8(w*h)); + + + video_output_buffer_convert = 0; + video_output_buffer = + (ycbcr_frame**) vj_malloc(sizeof(ycbcr_frame*) * 2 ); + if(!video_output_buffer) + return 0; + + veejay_memset( ppm_path,0,sizeof(ppm_path)); + + for(c=0; c < 2; c ++ ) + { + video_output_buffer[c] = (ycbcr_frame*) vj_malloc(sizeof(ycbcr_frame)); + video_output_buffer[c]->Y = NULL; + video_output_buffer[c]->Cb = NULL; + video_output_buffer[c]->Cr = NULL; + } + + sample_record_init(frame_len); + vj_tag_record_init(w,h); + // to render fading of effect chain: + temp_buffer[0] = (uint8_t*)vj_malloc(sizeof(uint8_t) * RUP8(frame_len+16) * 2 ); + if(!temp_buffer[0]) return 0; + veejay_memset( temp_buffer[0], 16, RUP8(frame_len+16) * 2 ); + temp_buffer[1] = (uint8_t*)vj_malloc(sizeof(uint8_t) * RUP8(frame_len+16) * 2); + if(!temp_buffer[1]) return 0; + veejay_memset( temp_buffer[1],128, (sizeof(uint8_t) * RUP8(frame_len+16) * 2) ); + temp_buffer[2] = (uint8_t*)vj_malloc(sizeof(uint8_t) * RUP8(frame_len+16) * 2 ); + if(!temp_buffer[2]) return 0; + veejay_memset( temp_buffer[2], 128,sizeof(uint8_t) * RUP8(frame_len+16) * 2 ); + // to render fading of effect chain: + + /* allocate space for frame_buffer, the place we render effects in */ + for (c = 0; c < SAMPLE_MAX_EFFECTS; c++) { + frame_buffer[c] = (ycbcr_frame *) vj_calloc(sizeof(ycbcr_frame)); + if(!frame_buffer[c]) return 0; + } + // clear the cache information + vj_perform_clear_cache(); + veejay_memset( frame_info[0],0,SAMPLE_MAX_EFFECTS); + + helper_frame = (VJFrame*) vj_malloc(sizeof(VJFrame)); + veejay_memcpy(helper_frame, info->effect_frame1, sizeof(VJFrame)); + + vj_perform_record_buffer_init(); + + effect_sampler = subsample_init( w ); + + lzo_ = lzo_new(); + + int vp = 0; int frontback = 0; + int pvp = 0; + + veejay_memset( &pvar_, 0, sizeof( varcache_t)); + + //@ undocumented + char *cc = getenv( "VEEJAY_CYCLE_SATURATE" ); + if( cc ) { + CYCLE_CAP = atol(cc); + veejay_msg(VEEJAY_MSG_INFO, + "Saturating Cycle Count at %ld", CYCLE_CAP); + } + + return 1; +} + + +static void vj_perform_close_audio() { + int i; + + if( lin_audio_buffer_ ) + free(lin_audio_buffer_ ); + veejay_memset( audio_buffer, 0, sizeof(uint8_t*) * SAMPLE_MAX_EFFECTS ); + + if(top_audio_buffer) free(top_audio_buffer); + if(resample_audio_buffer) free(resample_audio_buffer); + if(audio_render_buffer) free( audio_render_buffer ); + if(down_sample_buffer) free( down_sample_buffer ); +#ifdef HAVE_JACK + for(i=0; i <= MAX_SPEED; i ++) + { + if(resample_context[i]) + audio_resample_close( resample_context[i] ); + if(downsample_context[i]) + audio_resample_close( downsample_context[i]); + } + + if(resample_jack) + audio_resample_close(resample_jack); +#endif + veejay_msg(VEEJAY_MSG_INFO, "Stopped Audio playback task"); +} + +int vj_perform_init_audio(veejay_t * info) +{ + // video_playback_setup *settings = info->settings; +#ifndef HAVE_JACK + return 0; +#else + int i; + + if(!info->audio ) + { + veejay_msg(0,"No audio found"); + return 0; + } + top_audio_buffer = + (uint8_t *) vj_calloc(sizeof(uint8_t) * 8 * PERFORM_AUDIO_SIZE); + if(!top_audio_buffer) + return 0; + + down_sample_buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * PERFORM_AUDIO_SIZE * MAX_SPEED *4 ); + if(!down_sample_buffer) + return 0; + audio_render_buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * PERFORM_AUDIO_SIZE * MAX_SPEED * 4 ); + if(!audio_render_buffer) + return 0; + + resample_audio_buffer = (uint8_t*) vj_calloc(sizeof(uint8_t) * PERFORM_AUDIO_SIZE * 2); + if(!resample_audio_buffer) + return 0; + + lin_audio_buffer_ = (uint8_t*) vj_calloc( sizeof(uint8_t) * PERFORM_AUDIO_SIZE * SAMPLE_MAX_EFFECTS ); + if(!lin_audio_buffer_) + return 0; + + for (i = 0; i < SAMPLE_MAX_EFFECTS; i++) { + audio_buffer[i] = lin_audio_buffer_ + (PERFORM_AUDIO_SIZE * i); + } + + for( i = 0; i <= MAX_SPEED; i ++ ) + { + int out_rate = (info->edit_list->audio_rate * (i+2)); + int down_rate = (info->edit_list->audio_rate / (i+2)); + + resample_context[i] = av_audio_resample_init( + info->edit_list->audio_chans, + info->edit_list->audio_chans, + info->edit_list->audio_rate, + out_rate, + SAMPLE_FMT_S16, + SAMPLE_FMT_S16, + 16, + 10, + 0, + 1.0 + ); + if(!resample_context[i]) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot initialize audio upsampler for speed %d", i); + return 0; + } + downsample_context[i] = av_audio_resample_init( + info->edit_list->audio_chans, + info->edit_list->audio_chans, + info->edit_list->audio_rate, + down_rate, + SAMPLE_FMT_S16, + SAMPLE_FMT_S16, + 16, + 10, + 0, + 1.0 ); + + if(!downsample_context[i]) + { + veejay_msg(VEEJAY_MSG_WARNING, "Cannot initialize audio downsampler for dup %d",i); + return 0; + } + + /*veejay_msg(VEEJAY_MSG_DEBUG, "Resampler %d: Speed %d resamples audio to %d Hz, Slow %d to %d Hz ", i,i+2,out_rate, + i+2, down_rate );*/ + } + + return 1; +#endif +} + +void vj_perform_free(veejay_t * info) +{ + int fblen = SAMPLE_MAX_EFFECTS; // mjpg buf + int c; + + sample_record_free(); + + if(info->edit_list->has_audio) + vj_perform_close_audio(); + + for (c = 0; c < fblen; c++) { + if(vj_perform_row_used(c)) + vj_perform_free_row(c); + if(frame_buffer[c]) + { + if(frame_buffer[c]->Y) free(frame_buffer[c]->Y); + if(frame_buffer[c]->Cb) free(frame_buffer[c]->Cb); + if(frame_buffer[c]->Cr) free(frame_buffer[c]->Cr); + free(frame_buffer[c]); + } + } + + if(frame_buffer) free(frame_buffer); + + for( c = 0;c < 8; c++ ) + { + if(primary_buffer[c]->Y) free(primary_buffer[c]->Y ); + free(primary_buffer[c] ); + } + if(primary_buffer) free(primary_buffer); + + if(crop_frame) + { + if(crop_frame->data[0]) free(crop_frame->data[0]); + if(crop_frame->data[1]) free(crop_frame->data[1]); + if(crop_frame->data[2]) free(crop_frame->data[2]); + } + if(crop_sampler) + subsample_free(crop_sampler); + if(effect_sampler) + subsample_free(effect_sampler); + + +// if( info->viewport ) +// viewport_destroy( info->viewport ); + + for(c=0; c < 3; c ++) + { + if(temp_buffer[c]) free(temp_buffer[c]); + } + vj_perform_record_buffer_free(); + + for( c = 0 ; c < 2 ; c ++ ) + { + if(video_output_buffer[c]->Y ) + free(video_output_buffer[c]->Y); + if(video_output_buffer[c]->Cb ) + free(video_output_buffer[c]->Cb ); + if(video_output_buffer[c]->Cr ) + free(video_output_buffer[c]->Cr ); + free(video_output_buffer[c]); + } + free(video_output_buffer); + free(helper_frame); + + if(lzo_) + lzo_free(lzo_); +} + +int vj_perform_audio_start(veejay_t * info) +{ + int res; + editlist *el = info->edit_list; + + if (el->has_audio) + { +#ifdef HAVE_JACK + vj_jack_initialize(); + res = vj_jack_init(el); + if( res <= 0 ) { + veejay_msg(0, "Audio playback disabled"); + info->audio = NO_AUDIO; + return 0; + } + + if ( res == 2 ) + { + vj_jack_stop(); + info->audio = NO_AUDIO; + veejay_msg(VEEJAY_MSG_WARNING,"Please run jackd with a sample rate of %ld", + el->audio_rate ); + return 0; + } + + return 1; +#else + veejay_msg(VEEJAY_MSG_WARNING, "Jack support not compiled in (no audio)"); + return 0; +#endif + } + return 0; +} + +void vj_perform_audio_stop(veejay_t * info) +{ + if (info->edit_list->has_audio) { +#ifdef HAVE_JACK + vj_jack_stop(); + if(resample_jack) + { + audio_resample_close(resample_jack); + resample_jack = NULL; + } +#endif + info->audio = NO_AUDIO; + } +} + +void vj_perform_get_primary_frame(veejay_t * info, uint8_t ** frame) +{ + frame[0] = primary_buffer[info->out_buf]->Y; + frame[1] = primary_buffer[info->out_buf]->Cb; + frame[2] = primary_buffer[info->out_buf]->Cr; +} + +uint8_t *vj_perform_get_a_work_buffer( ) +{ + return primary_buffer[4]->Y; +} +void vj_perform_get_space_buffer( uint8_t *d[4] ) +{ + d[0] = primary_buffer[5]->Y; + d[1] = primary_buffer[5]->Cb; + d[2] = primary_buffer[5]->Cr; +} +uint8_t *vj_perform_get_preview_buffer() +{ + return primary_buffer[6]->Y; +} + +void vj_perform_get_output_frame( uint8_t **frame ) +{ + frame[0] = video_output_buffer[0]->Y; + frame[1] = video_output_buffer[0]->Cb; + frame[2] = video_output_buffer[0]->Cr; +} +void vj_perform_get_crop_dimensions(veejay_t *info, int *w, int *h) +{ + *w = info->current_edit_list->video_width - info->settings->viewport.left - info->settings->viewport.right; + *h = info->current_edit_list->video_height - info->settings->viewport.top - info->settings->viewport.bottom; + +} +int vj_perform_get_cropped_frame( veejay_t *info, uint8_t **frame, int crop ) +{ + if(crop) + { + VJFrame src; + veejay_memset( &src, 0, sizeof(VJFrame)); + + vj_get_yuv_template( &src, + info->current_edit_list->video_width, + info->current_edit_list->video_height, + info->pixel_format ); + + src.data[0] = primary_buffer[0]->Y; + src.data[1] = primary_buffer[0]->Cb; + src.data[2] = primary_buffer[0]->Cr; + + // yuv crop needs supersampled data + chroma_supersample( info->settings->sample_mode,effect_sampler, src.data, src.width,src.height ); + yuv_crop( &src, crop_frame, &(info->settings->viewport)); + chroma_subsample( info->settings->sample_mode,crop_sampler, crop_frame->data, crop_frame->width, crop_frame->height ); + } + + frame[0] = crop_frame->data[0]; + frame[1] = crop_frame->data[1]; + frame[2] = crop_frame->data[2]; + + return 1; +} + +int vj_perform_init_cropped_output_frame(veejay_t *info, VJFrame *src, int *dw, int *dh ) +{ + video_playback_setup *settings = info->settings; + if( crop_frame ) + free(crop_frame); + crop_frame = yuv_allocate_crop_image( src, &(settings->viewport) ); + if(!crop_frame) + return 0; + + *dw = crop_frame->width; + *dh = crop_frame->height; + + crop_sampler = subsample_init( *dw ); + + /* enough space to supersample*/ + int i; + for( i = 0; i < 3; i ++ ) + { + crop_frame->data[i] = (uint8_t*) vj_malloc(sizeof(uint8_t) * RUP8(crop_frame->len) ); + if(!crop_frame->data[i]) + return 0; + } + return 1; +} +void vj_perform_init_output_frame( veejay_t *info, uint8_t **frame, + int dst_w, int dst_h ) +{ + int i; + for(i = 0; i < 2; i ++ ) + { + if( video_output_buffer[i]->Y != NULL ) + free(video_output_buffer[i]->Y ); + if( video_output_buffer[i]->Cb != NULL ) + free(video_output_buffer[i]->Cb ); + if( video_output_buffer[i]->Cr != NULL ) + free(video_output_buffer[i]->Cr ); + + video_output_buffer[i]->Y = (uint8_t*) + vj_malloc(sizeof(uint8_t) * RUP8( dst_w * dst_h) ); + veejay_memset( video_output_buffer[i]->Y, 16, dst_w * dst_h ); + video_output_buffer[i]->Cb = (uint8_t*) + vj_malloc(sizeof(uint8_t) * RUP8( dst_w * dst_h) ); + veejay_memset( video_output_buffer[i]->Cb, 128, dst_w * dst_h ); + video_output_buffer[i]->Cr = (uint8_t*) + vj_malloc(sizeof(uint8_t) * RUP8(dst_w * dst_h) ); + veejay_memset( video_output_buffer[i]->Cr, 128, dst_w * dst_h ); + + } + frame[0] = video_output_buffer[0]->Y; + frame[1] = video_output_buffer[0]->Cb; + frame[2] = video_output_buffer[0]->Cr; + +} + +static void long2str(unsigned char *dst, int32_t n) +{ + dst[0] = (n )&0xff; + dst[1] = (n>> 8)&0xff; + dst[2] = (n>>16)&0xff; + dst[3] = (n>>24)&0xff; +} + +static int vj_perform_compress_frame( veejay_t *info, uint8_t *dst, uint32_t *p1_len, uint32_t *p2_len, uint32_t *p3_len) +{ + const int len = info->effect_frame1->width * info->effect_frame1->height; + const int uv_len = info->effect_frame1->uv_len; + uint8_t *dstI = dst + (sizeof(uint8_t) * 16); + unsigned int size1=0,size2=0,size3=0; + int i = lzo_compress( lzo_ , primary_buffer[info->out_buf]->Y, dstI, &size1, len ); + if( i == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to compress Y plane"); +#ifdef STRICT_CHECKING + assert(0); +#endif + return 0; + } + dstI += size1; + *p1_len = size1; + + if( info->settings->mcast_mode == 1 ) { + //@ only compress Y plane, set mode in header + /* long2str( dst,size1); + long2str( dst+4,0); + long2str( dst+8,0); + long2str( dst+12, info->settings->mcast_mode );*/ + return size1; + } + + i = lzo_compress( lzo_, primary_buffer[info->out_buf]->Cb, dstI, &size2, uv_len ); + if( i == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to compress U plane"); +#ifdef STRICT_CHECKING + assert(0); +#endif + return 0; + } + dstI += size2; + *p2_len = size2; + + i = lzo_compress( lzo_, primary_buffer[info->out_buf]->Cr, dstI, &size3, uv_len ); + if( i == 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to compress V plane"); +#ifdef STRICT_CHECKING + assert(0); +#endif + return 0; + } + + *p3_len = size3; + + long2str( dst,size1); + long2str( dst+4, size2 ); + long2str( dst+8, size3 ); + long2str( dst+12,info->settings->mcast_mode ); + + return (size1+size2+size3+16); +} + +int vj_perform_send_primary_frame_s2(veejay_t *info, int mcast, int to_link_id) +{ + int hlen =0; + unsigned char info_line[48]; + + uint8_t *socket_buffer = (uint8_t*) vj_malloc(sizeof(uint8_t) * info->effect_frame1->width * + info->effect_frame1->height * 3 ); + + int compr_len = 0; + uint32_t planes[3]; + + if( !mcast ) + { + uint8_t *sbuf = socket_buffer + (sizeof(uint8_t) * 41 ); + compr_len = vj_perform_compress_frame(info,sbuf, &planes[0], &planes[1], &planes[2]); +#ifdef STRICT_CHECKING + assert( compr_len > 0 ); +#endif + /* peer to peer connection */ + sprintf(info_line, "%04d%04d%1d%08d%08d%08d%08d", info->effect_frame1->width, + info->effect_frame1->height, info->effect_frame1->format, + compr_len, + planes[0], + planes[1], + planes[2] ); + hlen = strlen(info_line ); +#ifdef STRICT_CHECKING + assert( hlen == 41 ); +#endif + veejay_memcpy( socket_buffer, info_line, sizeof(uint8_t) * hlen ); + } + else + { + uint8_t *sbuf = socket_buffer + (sizeof(uint8_t) * 41 ); + + compr_len = vj_perform_compress_frame(info,sbuf, &planes[0], &planes[1], &planes[2] ); +#ifdef STRICT_CHECKING + assert(compr_len > 0 ); +#endif + sprintf(info_line, "%04d%04d%1d%08d%08d%08d%08d", info->effect_frame1->width, + info->effect_frame1->height, info->effect_frame1->format, + compr_len, + planes[0], + planes[1], + planes[2] ); + hlen = strlen(info_line ); +#ifdef STRICT_CHECKING + assert( hlen == 41 ); +#endif + veejay_memcpy( socket_buffer, info_line, sizeof(uint8_t) * hlen ); + + } + + int id = (mcast ? 2: 3); + int __socket_len = hlen + compr_len; + + if(!mcast) + { + int i; + for( i = 0; i < 8 ; i++ ) { + if( info->rlinks[i] != -1 ) { + if(vj_server_send_frame( info->vjs[id], info->rlinks[i], socket_buffer, __socket_len, + info->effect_frame1, info->real_fps )<=0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error sending frame to remote"); + _vj_server_del_client( info->vjs[id], info->rlinks[i] ); + } + info->rlinks[i] = -1; + } + } + + } + else + { + if(vj_server_send_frame( info->vjs[id], to_link_id, socket_buffer, __socket_len, + info->effect_frame1, info->real_fps )<=0) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Error sending multicast frame."); + } + } + + + free(socket_buffer); + + return 1; +} + +void vj_perform_get_output_frame_420p( veejay_t *info, uint8_t **frame, int w, int h ) +{ +//FIXME + if(info->pixel_format == FMT_422 || info->pixel_format == FMT_422F) + { + frame[0] = video_output_buffer[1]->Y; + frame[1] = video_output_buffer[1]->Cb; + frame[2] = video_output_buffer[1]->Cr; + + if( video_output_buffer_convert == 0 ) + { + uint8_t *src_frame[3]; + src_frame[0] = video_output_buffer[0]->Y; + src_frame[1] = video_output_buffer[0]->Cb; + src_frame[2] = video_output_buffer[0]->Cr; + + VJFrame *srci = yuv_yuv_template( video_output_buffer[0]->Y, video_output_buffer[0]->Cb, + video_output_buffer[0]->Cr, w, h, + get_ffmpeg_pixfmt(info->pixel_format)); + VJFrame *dsti = yuv_yuv_template( video_output_buffer[1]->Y, video_output_buffer[1]->Cb, + video_output_buffer[1]->Cr, w, h, + PIX_FMT_YUV420P ); + + yuv_convert_any_ac( srci,dsti, srci->format, dsti->format ); + free(srci); + free(dsti); + + video_output_buffer_convert = 1; + return; + } + } + else + { + frame[0] = video_output_buffer[0]->Y; + frame[1] = video_output_buffer[0]->Cb; + frame[2] = video_output_buffer[0]->Cr; + } +} + +int vj_perform_is_ready(veejay_t *info) +{ + if( info->settings->zoom ) + { + if( video_output_buffer[0]->Y == NULL ) return 0; + if( video_output_buffer[0]->Cb == NULL ) return 0; + if( video_output_buffer[0]->Cr == NULL ) return 0; + } + return 1; +} + +void vj_perform_get_primary_frame_420p(veejay_t *info, uint8_t **frame ) +{ + editlist *el = info->current_edit_list; + uint8_t *pframe[3]; + pframe[0] = primary_buffer[info->out_buf]->Y; + pframe[1] = primary_buffer[info->out_buf]->Cb; + pframe[2] = primary_buffer[info->out_buf]->Cr; + yuv422to420planar( pframe, temp_buffer, el->video_width,el->video_height ); + veejay_memcpy( pframe[0],frame[0], el->video_width * el->video_height ); + frame[0] = temp_buffer[0]; + frame[1] = temp_buffer[1]; + frame[2] = temp_buffer[2]; +} + +static int vj_perform_apply_first(veejay_t *info, vjp_kf *todo_info, + VJFrame **frames, VJFrameInfo *frameinfo, int e , int c, int n_frame) +{ + int n_a = vj_effect_get_num_params(e); + int entry = e; + int err = 0; + int args[16]; + + veejay_memset( args, 0 , sizeof(args) ); + + if( info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) + { + if(!vj_tag_get_all_effect_args(todo_info->ref, c, args, n_a, n_frame )) + return 1; + } + else + { + if(!sample_get_all_effect_arg( todo_info->ref, c, args, n_a, n_frame)) + return 1; + } + + err = vj_effect_apply( frames, frameinfo, todo_info,entry, args ); + return err; +} + +static void vj_perform_reverse_audio_frame(veejay_t * info, int len, + uint8_t * buf) +{ + int i; + int bps = info->current_edit_list->audio_bps; + uint8_t sample[bps]; + int x=len*bps; + for( i = 0; i < x/2 ; i += bps ) { + veejay_memcpy(sample,buf+i,bps); + veejay_memcpy(buf+i ,buf+(x-i-bps),bps); + veejay_memcpy(buf+(x-i-bps), sample,bps); + } +} + + +static void vj_perform_use_cached_ycbcr_frame(veejay_t *info, int centry, int chain_entry, int width, int height) +{ + int len1 = (width*height); + + if( centry == 0 ) + { + int len2 = ( info->effect_frame1->ssm == 1 ? len1 : + info->effect_frame1->uv_len ); + + veejay_memcpy(frame_buffer[chain_entry]->Y,primary_buffer[0]->Y, len1 ); + veejay_memcpy(frame_buffer[chain_entry]->Cb,primary_buffer[0]->Cb,len2 ); + veejay_memcpy(frame_buffer[chain_entry]->Cr,primary_buffer[0]->Cr,len2); + + frame_buffer[chain_entry]->ssm = info->effect_frame1->ssm; + } + else + { + int c = centry - 1; + int len2 = ( frame_buffer[c]->ssm == 1 ? len1 : info->effect_frame2->uv_len ); + + veejay_memcpy( frame_buffer[chain_entry]->Y,frame_buffer[c]->Y, len1); + veejay_memcpy( frame_buffer[chain_entry]->Cb,frame_buffer[c]->Cb, len2); + veejay_memcpy( frame_buffer[chain_entry]->Cr,frame_buffer[c]->Cr, len2); + + frame_buffer[chain_entry]->ssm = frame_buffer[c]->ssm; + } +} + + + +static int vj_perform_get_subframe(veejay_t * info, int sub_sample, + int chain_entry) + +{ + video_playback_setup *settings = (video_playback_setup*) info->settings; + int a = info->uc->sample_id; + int b = sub_sample; + //int trim_val = sample_get_trimmer(a, chain_entry); + + int sample_a[4]; + int sample_b[4]; + + int offset = sample_get_offset(a, chain_entry); + int len_a, len_b; + if(sample_get_short_info(b,&sample_b[0],&sample_b[1],&sample_b[2],&sample_b[3])!=0) return -1; + + if(sample_get_short_info(a,&sample_a[0],&sample_a[1],&sample_a[2],&sample_a[3])!=0) return -1; + + len_a = sample_a[1] - sample_a[0]; + len_b = sample_b[1] - sample_b[0]; + + int max_sfd = sample_get_framedup( b ); + int cur_sfd = sample_get_framedups( b ); + + cur_sfd ++; + + if( max_sfd > 0 ) { + if( cur_sfd >= max_sfd ) + { + cur_sfd = 0; + } + sample_set_framedups( b , cur_sfd); + if( cur_sfd != 0 ) + return 1; + } + + /* offset + start >= end */ + if(sample_b[3] >= 0) /* sub sample plays forward */ + { + if( settings->current_playback_speed != 0) + offset += sample_b[3]; /* speed */ + + if( sample_b[2] == 3 ) + offset = sample_b[0] + ( (int) ( (double) len_b * rand()/RAND_MAX) ); + + /* offset reached sample end */ + if( offset > len_b ) + { + if(sample_b[2] == 2) /* sample is in pingpong loop */ + { + /* then set speed in reverse and set offset to sample end */ + //offset = sample_b[1] - sample_b[0]; + offset = 0; + sample_set_speed( b, (-1 * sample_b[3]) ); + sample_set_offset(a,chain_entry,offset); + return sample_b[1]; + } + if(sample_b[2] == 1) + { + offset = 0; + } + if(sample_b[2] == 0) + { + offset = 0; + sample_set_speed(b,0); + } + if(sample_b[2] == 3 ) + offset = 0; + } + sample_set_offset(a,chain_entry,offset); + return (sample_b[0] + offset); + } + else + { /* sub sample plays reverse */ + if(settings->current_playback_speed != 0) + offset += sample_b[3]; /* speed */ + + if( sample_b[2] == 3 ) + offset = sample_b[0] + ( (int) ( (double) len_b * rand()/RAND_MAX)); + + if ( offset < -(len_b) ) + { + /* reached start position */ + if(sample_b[2] == 2) + { + //offset = sample_b[1] - sample_b[0]; + offset = 0; + sample_set_speed( b, (-1 * sample_b[3])); + sample_set_offset(a,chain_entry,offset); + return sample_b[0]; + } + if(sample_b[2] == 1) + { + //offset = sample_b[1] - sample_b[0]; + offset = 0; + } + if(sample_b[2]== 0) + { + sample_set_speed(b , 0); + offset = 0; + } + if(sample_b[2] == 3 ) + offset = 0; + } + sample_set_offset(a, chain_entry, offset); + + return (sample_b[1] + offset); + } + return 0; +} + + +static int vj_perform_get_subframe_tag(veejay_t * info, int sub_sample, + int chain_entry) + +{ + video_playback_setup *settings = (video_playback_setup*) info->settings; + //int trim_val = sample_get_trimmer(a, chain_entry); + + int sample[4]; + + int offset = sample_get_offset(sub_sample, chain_entry); + int nset = offset; + int len; + + if(sample_get_short_info(sub_sample,&sample[0],&sample[1],&sample[2],&sample[3])!=0) return -1; + + len = sample[1] - sample[0]; + int max_sfd = sample_get_framedup( sub_sample ); + int cur_sfd = sample_get_framedups( sub_sample ); + + cur_sfd ++; + + if( max_sfd > 0 ) { + if( cur_sfd >= max_sfd ) + { + cur_sfd = 0; + } + sample_set_framedups( sub_sample, cur_sfd); + if( cur_sfd != 0 ) + return 1; + } + + /* offset + start >= end */ + if(sample[3] >= 0) /* sub sample plays forward */ + { + if( settings->current_playback_speed != 0) + offset += sample[3]; /* speed */ + + if( sample[2] == 3 ) + offset = sample[0] + ( (int) ( (double) len * rand()/RAND_MAX)); + + /* offset reached sample end */ + if( offset > len ) + { + if(sample[2] == 2) /* sample is in pingpong loop */ + { + /* then set speed in reverse and set offset to sample end */ + //offset = sample_b[1] - sample_b[0]; + offset = 0; + sample_set_speed( sub_sample, (-1 * sample[3]) ); + sample_set_offset( sub_sample,chain_entry,offset); + return sample[1]; + } + if(sample[2] == 1) + { + offset = 0; + } + if(sample[2] == 0) + { + offset = 0; + sample_set_speed( sub_sample,0); + } + if(sample[2] == 3 ) + offset = 0; + } + + sample_set_offset(sub_sample,chain_entry,offset); + return (sample[0] + nset); + } + else + { /* sub sample plays reverse */ + if(settings->current_playback_speed != 0) + offset += sample[3]; /* speed */ + if( sample[2] == 3 ) + offset = sample[0] + ( (int) ( (double) len * rand()/RAND_MAX)); + + if ( offset < -(len) ) + { + /* reached start position */ + if(sample[2] == 2) + { + //offset = sample_b[1] - sample_b[0]; + offset = 0; + sample_set_speed( sub_sample, (-1 * sample[3])); + sample_set_offset( sub_sample,chain_entry,offset); + return sample[0]; + } + if(sample[2] == 1) + { + //offset = sample_b[1] - sample_b[0]; + offset = 0; + } + if(sample[2]== 0) + { + sample_set_speed( sub_sample , 0); + offset = 0; + } + if(sample[2] == 3 ) + offset = 0; + } + sample_set_offset(sub_sample, chain_entry, offset); + + return (sample[1] + nset); + } + return 0; +} + +#define ARRAY_LEN(x) ((int)(sizeof(x)/sizeof((x)[0]))) +int vj_perform_fill_audio_buffers(veejay_t * info, uint8_t *audio_buf, uint8_t *temporary_buffer, int *sampled_down) +{ +#ifdef HAVE_JACK + video_playback_setup *settings = info->settings; + int len = 0; + int speed = sample_get_speed(info->uc->sample_id); + int bps = info->current_edit_list->audio_bps; + int pred_len = (info->current_edit_list->audio_rate / info->current_edit_list->video_fps ); + int rs = 0; + int n_samples = 0; + + int cur_sfd = sample_get_framedups( info->uc->sample_id ); + int max_sfd = sample_get_framedup( info->uc->sample_id ); + + + if( cur_sfd <= 0 ) + { + if (speed > 1 || speed < -1) + { + int a_len = 0; + int n_frames = abs(speed); + uint8_t *tmp = temporary_buffer; + uint8_t *sambuf = tmp; + long i,start,end; + + if( n_frames >= MAX_SPEED ) + n_frames = MAX_SPEED - 1; + + if( speed < 0 ) + { + start = settings->current_frame_num - n_frames; + end = settings->current_frame_num; + } + else + { + start = settings->current_frame_num; + end = settings->current_frame_num + n_frames; + } + + for ( i = start; i < end; i ++ ) + { + a_len = vj_el_get_audio_frame(info->current_edit_list,i, tmp); + if( a_len <= 0 ) + { + n_samples += pred_len; + veejay_memset( tmp, 0, pred_len * bps ); + tmp += (pred_len*bps); + } + else + { + n_samples += a_len; + tmp += (a_len* bps ); + rs = 1; + } + } +#ifdef STRICT_CHECKING + assert( resample_context[ n_frames ] != NULL ); +#endif + if( rs ) + { + if( speed < 0 ) + vj_perform_reverse_audio_frame(info, n_samples, sambuf ); + n_samples = audio_resample( resample_context[n_frames-2],audio_buf, sambuf, n_samples ); + } + } else if( speed == 0 ) { + n_samples = len = pred_len; + veejay_memset( audio_buf, 0, pred_len * bps ); + } else { + n_samples = vj_el_get_audio_frame( info->current_edit_list, settings->current_frame_num, audio_buf ); + if(n_samples <= 0 ) + { + veejay_memset( audio_buf,0, pred_len * bps ); + n_samples = pred_len; + } + else + { + rs = 1; + } + if( speed < 0 && rs) + vj_perform_reverse_audio_frame(info,n_samples,audio_buf); + } + + if( n_samples < pred_len ) + { + veejay_memset( audio_buf + (n_samples * bps ) , 0, (pred_len- n_samples) * bps ); + n_samples = pred_len; + } + + } + + if( cur_sfd <= max_sfd && max_sfd > 1) + { + int val = *sampled_down; + if( cur_sfd == 0 ) + { + // @ resample buffer + n_samples = audio_resample( downsample_context[ max_sfd-2 ], + down_sample_buffer,audio_buf, n_samples ); + *sampled_down = n_samples / max_sfd; + val = n_samples / max_sfd; + n_samples = pred_len; + } + else + { + n_samples = pred_len; + } + veejay_memcpy( audio_buf, down_sample_buffer + (cur_sfd * val *bps ), val * bps ); + } + + return n_samples; +#else + return 0; +#endif +} + +static void vj_perform_apply_secundary_tag(veejay_t * info, int sample_id, + int type, int chain_entry ) +{ /* second sample */ + int width = info->current_edit_list->video_width; + int height = info->current_edit_list->video_height; + int error = 1; + int nframe; + int len = 0; + int centry = -1; +#ifdef STRICT_CHECKING + assert( frame_buffer[chain_entry]->Cb != frame_buffer[chain_entry]->Cr ); +#endif + uint8_t *fb[3] = { + frame_buffer[chain_entry]->Y, + frame_buffer[chain_entry]->Cb, + frame_buffer[chain_entry]->Cr }; + + uint8_t *backing_fb[3] = { + temp_buffer[0] + info->effect_frame1->len, + temp_buffer[1] + info->effect_frame1->len, + temp_buffer[2] + info->effect_frame1->len}; + video_playback_setup *settings = info->settings; +#ifdef STRICT_CHECKING + assert( info->effect_frame1->len > 0 ); +#endif + switch (type) + { + case VJ_TAG_TYPE_YUV4MPEG: /* playing from stream */ + case VJ_TAG_TYPE_V4L: + case VJ_TAG_TYPE_VLOOPBACK: + case VJ_TAG_TYPE_AVFORMAT: + case VJ_TAG_TYPE_NET: + case VJ_TAG_TYPE_MCAST: + case VJ_TAG_TYPE_PICTURE: + case VJ_TAG_TYPE_COLOR: + + centry = vj_perform_tag_is_cached(chain_entry, sample_id); + int dovp = vj_tag_get_composite( sample_id ); + + void *vp = NULL; + + if (centry == -1) + { + if(! vj_tag_get_active( sample_id ) ) + { + // active stream if neccesaary + vj_tag_set_active(sample_id, 1 ); + } + + if (vj_tag_get_active(sample_id) == 1 ) + { + int res = 0; + //@ Capture frame into backing buffer + vp = vj_tag_get_composite_view(sample_id); + if( vp == NULL ) //dovp == 2 + dovp = 0; + + if( dovp == 2) { + res = vj_tag_get_frame(sample_id,backing_fb, audio_buffer[chain_entry]); + } else { + res = vj_tag_get_frame(sample_id, fb, audio_buffer[chain_entry]); + } + + if(res==1) + error = 0; + else + vj_tag_set_active(sample_id, 0); + frame_buffer[chain_entry]->ssm = 0; + + if( dovp == 2) + { +#ifdef STRICT_CHECKING + assert( vp != NULL ); +#endif + + VJFrame *tmp = yuv_yuv_template( backing_fb[0],backing_fb[1],backing_fb[2], + width,height, get_ffmpeg_pixfmt(info->pixel_format) ); + frame_buffer[chain_entry]->ssm = composite_processX(info->composite,vp,fb,tmp); + free(tmp); + } + + } + } + else + { + vj_perform_use_cached_ycbcr_frame(info, centry, chain_entry, width,height); + error = 0; + } + if(!error) + cached_tag_frames[1 + chain_entry ] = sample_id; + break; + + case VJ_TAG_TYPE_NONE: + nframe = vj_perform_get_subframe_tag(info, sample_id, chain_entry); // get exact frame number to decode + centry = vj_perform_sample_is_cached(sample_id, chain_entry); + if(centry == -1 || info->no_caching) + { + dovp = sample_get_composite( sample_id ); + vp = sample_get_composite_view(sample_id); + if( vp == NULL ) // dovp == 2 + dovp = 0; + +#ifdef STRICT_CHECKING + if(dovp==2) + assert( vp != NULL ); +#endif + if(dovp==2) { + len = vj_perform_get_frame_fx(info,sample_id,nframe,backing_fb, frame_buffer[chain_entry]->P0, frame_buffer[chain_entry]->P1 ); + } else { + len = vj_perform_get_frame_fx( info, sample_id, nframe, fb, frame_buffer[chain_entry]->P0, frame_buffer[chain_entry]->P1 ); + } + + if(len > 0 ) + error = 0; + frame_buffer[chain_entry]->ssm = 0; + + if(dovp==2) { + VJFrame *tmp = yuv_yuv_template( backing_fb[0],backing_fb[1],backing_fb[2], width,height, get_ffmpeg_pixfmt(info->pixel_format) ); + frame_buffer[chain_entry]->ssm = composite_processX(info->composite,vp,fb,tmp); + free(tmp); + } + } + else + { + vj_perform_use_cached_ycbcr_frame( info, centry, chain_entry, width,height ); + cached_sample_frames[ 1 + chain_entry ] = sample_id; + error = 0; + } + if(!error) + cached_sample_frames[chain_entry+1] = sample_id; + + break; + + } +} + + +static int vj_perform_get_frame_( veejay_t *info, int s1, long nframe, uint8_t *img[3], uint8_t *p0_buffer[3], uint8_t *p1_buffer[3], int check_sample ) +{ + int max_sfd = (s1 ? sample_get_framedup( s1 ) : info->sfd ); + + if(check_sample) { + if(info->uc->sample_id == s1 && info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) { + + uint8_t *source[3]; + if( max_sfd <= 1 ) { + veejay_memcpy(img[0], primary_buffer[0]->Y, info->effect_frame1->len ); + veejay_memcpy(img[1], primary_buffer[0]->Cb, + (info->effect_frame1->ssm ? info->effect_frame1->len : info->effect_frame1->uv_len ) ); + veejay_memcpy(img[2], primary_buffer[0]->Cr, + (info->effect_frame1->ssm ? info->effect_frame1->len : info->effect_frame1->uv_len ) ); + return 1; + } + + veejay_memcpy(img[0], primary_buffer[7]->Y, info->effect_frame1->len ); + veejay_memcpy(img[1], primary_buffer[7]->Cb, + (info->effect_frame1->ssm ? info->effect_frame1->len : info->effect_frame1->uv_len ) ); + veejay_memcpy(img[2], primary_buffer[7]->Cr, + (info->effect_frame1->ssm ? info->effect_frame1->len : info->effect_frame1->uv_len ) ); + + return 1; + } + } + + + editlist *el = ( s1 ? sample_get_editlist(s1) : info->edit_list); +#ifdef STRICT_CHECKING + assert( el != NULL ); +#endif + int cur_sfd = (s1 ? sample_get_framedups(s1 ) : info->settings->simple_frame_dup ); + + if( max_sfd <= 1 ) + return vj_el_get_video_frame( el, nframe, img ); + + int speed = info->settings->current_playback_speed; + int loops = (s1 ? sample_get_loopcount(s1) : 0 ); + int uv_len = (info->effect_frame1->ssm ? info->effect_frame1->len : info->effect_frame1->uv_len ); + + long p0_frame = 0; + long p1_frame = 0; + int p0 = 0; + int p1 = 0; + + long start = ( s1 ? sample_get_startFrame(s1) : info->settings->min_frame_num); + long end = ( s1 ? sample_get_endFrame(s1) : info->settings->max_frame_num ); + + if( cur_sfd == 0 ) { + if( speed > 0 && nframe == end ){ //@ p0 = last frame + p0_frame = end; + p0 = vj_el_get_video_frame( el, p0_frame, p0_buffer ); + p1_frame = start; + p1 = vj_el_get_video_frame( el, p1_frame, p1_buffer ); + } else if( speed < 0 && nframe == start) { //@ p0 = first frame + p0_frame = start; + p0 = vj_el_get_video_frame( el, p0_frame, p0_buffer ); + p1_frame = end; + p1 = vj_el_get_video_frame( el, p1_frame, p1_buffer ); + } else { + p0_frame = nframe; + p0 = vj_el_get_video_frame( el, p0_frame, p0_buffer ); + p1_frame = nframe + speed; + p1 = vj_el_get_video_frame( el, p1_frame, p1_buffer ); + } + veejay_memcpy( img[0], p0_buffer[0], info->effect_frame1->len ); + veejay_memcpy( img[1], p0_buffer[1], uv_len); + veejay_memcpy( img[2], p0_buffer[2], uv_len ); + + } else { + uint32_t i; + const uint32_t N = max_sfd; + const uint32_t n1 = cur_sfd; + const float frac = 1.0f / (float) N * n1; + const uint32_t len = el->video_width * el->video_height; + +//@ SSE optimize this, takes about 10ms for 1024x768x3 + if(!info->effect_frame1->ssm ) { + for( i = 0; i < len ; i ++ ) + img[0][i] = p0_buffer[0][i] + ( frac * (p1_buffer[0][i] - p0_buffer[0][i])); + for( i = 0; i < uv_len ; i ++ ) { + img[1][i] = p0_buffer[1][i] + ( frac * (p1_buffer[1][i] - p0_buffer[1][i])); + img[2][i] = p0_buffer[2][i] + ( frac * (p1_buffer[2][i] - p0_buffer[2][i])); + } + } else { + for( i = 0; i < len ; i ++ ) { + img[0][i] = p0_buffer[0][i] + ( frac * (p1_buffer[0][i] - p0_buffer[0][i])); + img[1][i] = p0_buffer[1][i] + ( frac * (p1_buffer[1][i] - p0_buffer[1][i])); + img[2][i] = p0_buffer[2][i] + ( frac * (p1_buffer[2][i] - p0_buffer[2][i])); + } + + } + //@ copy p0 buffer + if( (n1 + 1 ) == N ) { + veejay_memcpy( p0_buffer[0], img[0], info->effect_frame1->len ); + veejay_memcpy( p0_buffer[1], img[1], uv_len ); + veejay_memcpy( p0_buffer[2], img[2], uv_len ); + } + + } + return 1; +} + + +static int vj_perform_get_frame_fx(veejay_t *info, int s1, long nframe, uint8_t *frame[3], uint8_t *p0plane, uint8_t *p1plane) +{ + uint8_t *p0_buffer[3] = { + p0plane, + p0plane + info->effect_frame1->len, + p0plane + info->effect_frame1->len + info->effect_frame1->len + }; + uint8_t *p1_buffer[3] = { + p1plane, + p1plane + info->effect_frame1->len, + p1plane + info->effect_frame1->len + info->effect_frame1->len + }; + + return vj_perform_get_frame_(info, s1, nframe,frame, p0_buffer, p1_buffer,1 ); +} + + +static void vj_perform_apply_secundary(veejay_t * info, int sample_id, int type, + int chain_entry) +{ /* second sample */ + + + int width = info->current_edit_list->video_width; + int height = info->current_edit_list->video_height; + int error = 1; + int nframe; + int len; + + int res = 1; + int centry = -1; + int dovp = 0; + void *vp = NULL; + + uint8_t *fb[3] = { + frame_buffer[chain_entry]->Y, + frame_buffer[chain_entry]->Cb, + frame_buffer[chain_entry]->Cr }; + uint8_t *backing_fb[3] = { + temp_buffer[0] + info->effect_frame1->len, + temp_buffer[1] + info->effect_frame1->len, + temp_buffer[2] + info->effect_frame1->len}; +#ifdef STRICT_CHECKING + assert( info->effect_frame1->len > 0 ); +#endif + video_playback_setup *settings = info->settings; + + switch (type) + { + case VJ_TAG_TYPE_YUV4MPEG: + case VJ_TAG_TYPE_V4L: + case VJ_TAG_TYPE_VLOOPBACK: + case VJ_TAG_TYPE_AVFORMAT: + case VJ_TAG_TYPE_NET: + case VJ_TAG_TYPE_MCAST: + case VJ_TAG_TYPE_COLOR: + case VJ_TAG_TYPE_PICTURE: + + centry = vj_perform_tag_is_cached(chain_entry, sample_id); // is it cached? + //@ not cached + if (centry == -1 ) + { + if(! vj_tag_get_active( sample_id ) ) + { + // active stream if neccesaary + vj_tag_set_active(sample_id, 1 ); + } + + if (vj_tag_get_active(sample_id) == 1) + { + dovp = vj_tag_get_composite( sample_id); + vp = vj_tag_get_composite_view(sample_id ); + if( vp == NULL ) //dovp == 2 + dovp = 0; + + if(dovp==2) { + res = vj_tag_get_frame(sample_id,backing_fb,audio_buffer[chain_entry] ); + } else { + res = vj_tag_get_frame(sample_id, fb, audio_buffer[chain_entry]); + } + if(res) + error = 0; + else + vj_tag_set_active(sample_id, 0); // stop stream + + frame_buffer[chain_entry]->ssm = 0; + video_playback_setup *settings = info->settings; + if( dovp==2) + { + void *vp = vj_tag_get_composite_view( sample_id ); +#ifdef STRICT_CHECKING + assert( vp != NULL ); +#endif + VJFrame *tmp = yuv_yuv_template( backing_fb[0],backing_fb[1],backing_fb[2], + width,height, get_ffmpeg_pixfmt(info->pixel_format) ); + frame_buffer[chain_entry]->ssm = composite_processX(info->composite,vp,fb,tmp); + free(tmp); + } + + } + } + else + { + vj_perform_use_cached_ycbcr_frame(info,centry, chain_entry, width, height); + error = 0; + } + if(!error ) + cached_tag_frames[1 + chain_entry ] = sample_id; + break; + case VJ_TAG_TYPE_NONE: + nframe = vj_perform_get_subframe(info, sample_id, chain_entry); // get exact frame number to decode + centry = vj_perform_sample_is_cached(sample_id, chain_entry); + if(centry == -1 || info->no_caching) + { + dovp = sample_get_composite(sample_id); + vp = sample_get_composite_view(sample_id); + if( vp == NULL ) //dovp == 2 + dovp = 0; + +#ifdef STRICT_CHECKING + if(dovp==2) + assert( vp != NULL ); +#endif + if(dovp==2) { + len = vj_perform_get_frame_fx(info,sample_id,nframe,backing_fb, frame_buffer[chain_entry]->P0, frame_buffer[chain_entry]->P1 ); + } else { + len = vj_perform_get_frame_fx( info, sample_id, nframe, fb, frame_buffer[chain_entry]->P0, frame_buffer[chain_entry]->P1 ); + } + + if(len > 0 ) + error = 0; + frame_buffer[chain_entry]->ssm = 0; + if(dovp) + { + VJFrame *tmp = yuv_yuv_template( backing_fb[0],backing_fb[1],backing_fb[2], + width,height, get_ffmpeg_pixfmt(info->pixel_format)); + + frame_buffer[chain_entry]->ssm = composite_processX(info->composite,vp,fb,tmp); + free(tmp); + } + } + else + { + vj_perform_use_cached_ycbcr_frame(info,centry, chain_entry,width,height); + cached_sample_frames[ 1 + chain_entry ] = sample_id; + error = 0; + } + if(!error) + cached_sample_frames[chain_entry+1] = sample_id; + break; + + } +} +//@ FIXME: Render all image effects in subchain +// +static int vj_perform_tag_render_chain_entry(veejay_t *info, int chain_entry) +{ + VJFrame *frames[2]; + VJFrameInfo *frameinfo; + video_playback_setup *settings = info->settings; + frames[0] = info->effect_frame1; + frames[1] = info->effect_frame2; + frameinfo = info->effect_frame_info; + // setup pointers to ycbcr 4:2:0 or 4:2:2 data + frames[0]->data[0] = primary_buffer[0]->Y; + frames[0]->data[1] = primary_buffer[0]->Cb; + frames[0]->data[2] = primary_buffer[0]->Cr; + frames[0]->format = info->pixel_format; + vjp_kf *setup; + setup = info->effect_info; + setup->ref = info->uc->sample_id; + + if (vj_tag_get_chain_status(info->uc->sample_id, chain_entry)) + { + int effect_id = vj_tag_get_effect_any(info->uc->sample_id, chain_entry); // what effect is enabled + if (effect_id > 0) + { + int sub_mode = vj_effect_get_subformat(effect_id); + int ef = vj_effect_get_extra_frame(effect_id); + if(ef) + { + int sub_id = + vj_tag_get_chain_channel(info->uc->sample_id, + chain_entry); // what id + int source = + vj_tag_get_chain_source(info->uc->sample_id, // what source type + chain_entry); + + vj_perform_apply_secundary_tag(info,sub_id,source,chain_entry ); // get it + frames[1]->data[0] = frame_buffer[chain_entry]->Y; + frames[1]->data[1] = frame_buffer[chain_entry]->Cb; + frames[1]->data[2] = frame_buffer[chain_entry]->Cr; + frames[1]->format = info->pixel_format; + frames[1]->ssm = frame_buffer[chain_entry]->ssm; + + int done = 0; + int do_ssm = vj_perform_preprocess_has_ssm( info, sub_id, source); + if(do_ssm >= 0 ) { + if( (frames[1]->ssm == 0 && do_ssm == 0) || (frames[1]->ssm == 1 && do_ssm == 1 ) + || (frames[1]->ssm == 0 && do_ssm == 1 )) { + //@ call render now + frames[1]->ssm = vj_perform_preprocess_secundary( info, sub_id,source,sub_mode,chain_entry, frames, frameinfo ); + done = 1; + } + } + + // sample B + if(sub_mode && frames[1]->ssm == 0) + { + chroma_supersample( + settings->sample_mode, + effect_sampler, + frames[1]->data, + frameinfo->width, + frameinfo->height ); + frames[1]->ssm = 1; + frame_buffer[chain_entry]->ssm = 1; + } + else if (!sub_mode && frames[1]->ssm == 1 ) + { + chroma_subsample( + settings->sample_mode, + effect_sampler, + frames[1]->data, + frameinfo->width, + frameinfo->height + ); + frames[1]->ssm = 0; + frame_buffer[chain_entry]->ssm = 0; + } + + if(!done && do_ssm >= 0) { + if( (do_ssm == 1 && frames[1]->ssm == 1) || (do_ssm == 0 && frames[1]->ssm == 0) ) { + vj_perform_preprocess_secundary( info, sub_id,source,sub_mode,chain_entry, frames, frameinfo ); + + } + } + + + } + + if( sub_mode && frames[0]->ssm == 0 ) + { + chroma_supersample( + settings->sample_mode, + effect_sampler, + frames[0]->data, + frameinfo->width, + frameinfo->height ); + frames[0]->ssm = 1; + } + else if(!sub_mode && frames[0]->ssm == 1) + { + chroma_subsample( + settings->sample_mode, + effect_sampler, + frames[0]->data,frameinfo->width, + frameinfo->height + ); + frames[0]->ssm = 0; + } + vj_perform_apply_first(info,setup,frames,frameinfo,effect_id,chain_entry, + (int) settings->current_frame_num ); + } // if + } // for + return 0; +} + +static int vj_perform_preprocess_has_ssm( veejay_t *info, int id, int mode) +{ + int n; + + if(info->settings->fxdepth==0) + return -1; + + switch( mode ) { + case VJ_PLAYBACK_MODE_SAMPLE: + for( n=0; n < 3; n ++ ) { + if( sample_get_chain_status(id, n ) ) { + int fx_id = sample_get_effect_any(id,n ); + if( fx_id > 0 ) + return vj_effect_get_subformat(fx_id); + } + } + break; + case VJ_PLAYBACK_MODE_TAG: + for( n=0; n < 3; n ++ ) { + if( vj_tag_get_chain_status(id, n ) ) { + int fx_id = vj_tag_get_effect_any(id,n ); + if( fx_id > 0 ) + return vj_effect_get_subformat(fx_id); + } + } + break; + } + return -1; +} + +static int vj_perform_preprocess_secundary( veejay_t *info, int id, int mode,int current_ssm,int chain_entry, VJFrame **frames, VJFrameInfo *frameinfo ) +{ + int n; + int cur_id = info->effect_info->ref; + int ssm = current_ssm; + video_playback_setup *settings = info->settings; + vjp_kf *setup = NULL; + VJFrame **f = frames; + VJFrameInfo *i = frameinfo; + + VJFrame a,b; + veejay_memcpy(&a, frames[1], sizeof(VJFrame)); + veejay_memcpy(&b, frames[0], sizeof(VJFrame)); + + VJFrame *F[2]; + F[0] = &a; + F[1] = &b; + + switch( mode ) { + case VJ_PLAYBACK_MODE_SAMPLE: + setup = info->effect_info; + setup->ref = id; + for( n=0; n < 3; n ++ ) { + if( sample_get_chain_status(id, n ) ) { + int fx_id = sample_get_effect_any(id,n ); + if( fx_id > 0 ) { + int sm = vj_effect_get_subformat(fx_id); + int ef = vj_effect_get_extra_frame(fx_id); + if( ef ) continue; + if( sm ) { + if( !ssm ) { + chroma_supersample( settings->sample_mode,effect_sampler,F[0]->data,i->width,i->height ); + F[0]->ssm = 1; + frame_buffer[chain_entry]->ssm = 1; + ssm = 1; + } + } else if ( ssm ) { + chroma_subsample( settings->sample_mode, effect_sampler,F[0]->data,i->width,i->height); + F[0]->ssm = 0; + frame_buffer[chain_entry]->ssm = 1; + ssm = 0; + } + + if(vj_perform_apply_first(info,setup,F,frameinfo,fx_id,n,(int) settings->current_frame_num )==-2) { + if( vj_effect_activate(fx_id) ) { + settings->fxrow[n] = fx_id; + vj_perform_apply_first(info,setup,F,frameinfo,fx_id,n,(int) settings->current_frame_num ); + } + + } + // FX needs init! + + } + } + } + break; + case VJ_PLAYBACK_MODE_TAG: + setup = info->effect_info; + setup->ref = id; + for( n=0; n < 3; n ++ ) { + if( vj_tag_get_chain_status(id, n ) ) { + int fx_id = vj_tag_get_effect_any(id,n ); + if( fx_id > 0 ) { + int sm = vj_effect_get_subformat(fx_id); + int ef = vj_effect_get_extra_frame(fx_id); + if( ef ) continue; + if( sm ) { + if( !ssm ) { + chroma_supersample( settings->sample_mode,effect_sampler,F[0]->data,i->width,i->height ); + F[0]->ssm = 1; + frame_buffer[chain_entry]->ssm = 1; + ssm = 1; + } + } else if ( ssm ) { + chroma_subsample( settings->sample_mode, effect_sampler,F[0]->data,i->width,i->height); + F[0]->ssm = 0; + frame_buffer[chain_entry]->ssm = 1; + ssm = 0; + } + + // logic to super/sub sample + } + if(vj_perform_apply_first(info,setup,F,frameinfo,fx_id,n,(int) settings->current_frame_num ) == -2 ) { + if( vj_effect_activate(fx_id) ) { + settings->fxrow[n] = fx_id; + vj_perform_apply_first(info,setup,F,frameinfo,fx_id,n,(int) settings->current_frame_num ); + } + } + + } + } + break; + } + info->effect_info->ref = cur_id; + + return ssm; +} + +static int vj_perform_render_chain_entry(veejay_t *info, int chain_entry) +{ + VJFrame *frames[2]; + VJFrameInfo *frameinfo; + video_playback_setup *settings = info->settings; + frames[0] = info->effect_frame1; + frames[1] = info->effect_frame2; + frames[1]->format = info->pixel_format; + frameinfo = info->effect_frame_info; + frames[0]->data[0] = primary_buffer[0]->Y; + frames[0]->data[1] = primary_buffer[0]->Cb; + frames[0]->data[2] = primary_buffer[0]->Cr; + frames[0]->format = info->pixel_format; + + vjp_kf *setup; + setup = info->effect_info; + setup->ref = info->uc->sample_id; + + if (sample_get_chain_status(info->uc->sample_id, chain_entry)) + { + int effect_id = + sample_get_effect_any(info->uc->sample_id, chain_entry); // what effect is enabled + + if (effect_id > 0) + { + int sub_mode = vj_effect_get_subformat(effect_id); + int ef = vj_effect_get_extra_frame(effect_id); + if(ef) + { + int sub_id = + sample_get_chain_channel(info->uc->sample_id, + chain_entry); // what id + int source = + sample_get_chain_source(info->uc->sample_id, // what source type + chain_entry); + vj_perform_apply_secundary(info,sub_id,source,chain_entry); // get it + + frames[1]->data[0] = frame_buffer[chain_entry]->Y; + frames[1]->data[1] = frame_buffer[chain_entry]->Cb; + frames[1]->data[2] = frame_buffer[chain_entry]->Cr; + frames[1]->ssm = frame_buffer[chain_entry]->ssm; + int done = 0; + int do_ssm = vj_perform_preprocess_has_ssm( info, sub_id, source); + if(do_ssm >= 0 ) { + if( (frames[1]->ssm == 0 && do_ssm == 0) || (frames[1]->ssm == 1 && do_ssm == 1 ) + || (frames[1]->ssm == 0 && do_ssm == 1 )) { + //@ call render now + frames[1]->ssm = vj_perform_preprocess_secundary( info, sub_id,source,sub_mode,chain_entry, frames, frameinfo ); + done = 1; + } + } + + + if(frames[1]->ssm == 0 && sub_mode) + { + chroma_supersample( + settings->sample_mode, + effect_sampler, + frames[1]->data, + frameinfo->width, + frameinfo->height ); + frames[1]->ssm = 1; // HUH FIXME was 0 + frame_buffer[chain_entry]->ssm = 1; + } + else if(frames[1]->ssm == 1 && !sub_mode ) + { + frames[1]->ssm = 0; + frame_buffer[chain_entry]->ssm = 0; + chroma_subsample( + settings->sample_mode, + effect_sampler, + frames[1]->data, + frameinfo->width, + frameinfo->height + ); + } + + if(!done && do_ssm >= 0) { + if( (do_ssm == 1 && frames[1]->ssm == 1) || (do_ssm == 0 && frames[1]->ssm == 0) ) { + vj_perform_preprocess_secundary( info, sub_id,source,sub_mode,chain_entry, frames, frameinfo ); + + } + } + } + + if( sub_mode && frames[0]->ssm == 0) + { + chroma_supersample( + settings->sample_mode, + effect_sampler, + frames[0]->data, + frameinfo->width, + frameinfo->height ); + + frames[0]->ssm = 1; + } + else if(!sub_mode && frames[0]->ssm == 1) + { + chroma_subsample( + settings->sample_mode, + effect_sampler, + frames[0]->data, + frameinfo->width, + frameinfo->height + ); + frames[0]->ssm = 0; + } + + vj_perform_apply_first(info,setup,frames,frameinfo,effect_id,chain_entry, + (int) settings->current_frame_num ); + + } // if + } // status + return 0; +} + +static int vj_perform_sample_complete_buffers(veejay_t * info, int *hint444) +{ + int chain_entry; + vjp_kf *setup; + VJFrame *frames[2]; + VJFrameInfo *frameinfo; + setup = info->effect_info; + + frames[0] = info->effect_frame1; + frames[1] = info->effect_frame2; + frameinfo = info->effect_frame_info; + setup->ref = info->uc->sample_id; + frames[0]->data[0] = primary_buffer[0]->Y; + frames[0]->data[1] = primary_buffer[0]->Cb; + frames[0]->data[2] = primary_buffer[0]->Cr; + if(pvar_.fader_active) + vj_perform_pre_chain( info, frames[0] ); + + for(chain_entry = 0; chain_entry < SAMPLE_MAX_EFFECTS; chain_entry++) + { + vj_perform_render_chain_entry(info, chain_entry); + } + *hint444 = frames[0]->ssm; + return 1; +} + + +static int vj_perform_tag_complete_buffers(veejay_t * info,int *hint444 ) +{ + int chain_entry; + VJFrame *frames[2]; + + frames[0] = info->effect_frame1; + frames[1] = info->effect_frame2; + frames[0]->data[0] = primary_buffer[0]->Y; + frames[0]->data[1] = primary_buffer[0]->Cb; + frames[0]->data[2] = primary_buffer[0]->Cr; + + if( pvar_.fader_active ) + vj_perform_pre_chain( info, frames[0] ); + + + for(chain_entry = 0; chain_entry < SAMPLE_MAX_EFFECTS; chain_entry++) + vj_perform_tag_render_chain_entry( info, chain_entry); + + *hint444 = frames[0]->ssm; + return 1; +} + + +static void vj_perform_plain_fill_buffer(veejay_t * info) +{ + video_playback_setup *settings = (video_playback_setup*) info->settings; + uint8_t *frame[3]; + int ret = 0; + frame[0] = primary_buffer[0]->Y; + frame[1] = primary_buffer[0]->Cb; + frame[2] = primary_buffer[0]->Cr; + + uint8_t *p0_buffer[3] = { + primary_buffer[7]->Y, + primary_buffer[7]->Cb, + primary_buffer[7]->Cr }; + + uint8_t *p1_buffer[3]= { + primary_buffer[4]->Y, + primary_buffer[4]->Cb, + primary_buffer[4]->Cr }; + + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE) + { + ret = vj_perform_get_frame_(info, info->uc->sample_id, settings->current_frame_num,frame, p0_buffer, p1_buffer,0 ); + } else if ( info->uc->playback_mode == VJ_PLAYBACK_MODE_PLAIN ) { + ret = vj_perform_get_frame_(info, 0, settings->current_frame_num,frame, p0_buffer, p1_buffer,0 ); + + } + + if(ret <= 0) + { + veejay_msg(0, "Unable to queue video frame %d", + settings->current_frame_num ); + // veejay_change_state_save(info, LAVPLAY_STATE_STOP); + } +} +static uint32_t rec_audio_sample_ = 0; +static int vj_perform_render_sample_frame(veejay_t *info, uint8_t *frame[3], int sample) +{ + int audio_len = 0; + long nframe = info->settings->current_frame_num; + uint8_t *buf = NULL; + + if( info->current_edit_list->has_audio ) + { + buf = (uint8_t*) vj_malloc(sizeof(uint8_t) * PERFORM_AUDIO_SIZE ); + audio_len = vj_perform_fill_audio_buffers(info, buf, audio_render_buffer, &rec_audio_sample_ ); + } + int res = sample_record_frame( sample,frame,buf,audio_len,info->pixel_format ); + + if( buf ) + free(buf); + + return res; +} + + +static int vj_perform_render_tag_frame(veejay_t *info, uint8_t *frame[3]) +{ + long nframe = info->settings->current_frame_num; + int sample_id = info->uc->sample_id; + + if(info->settings->offline_record) + sample_id = info->settings->offline_tag_id; + + if(info->settings->offline_record) + { + if (!vj_tag_get_frame(sample_id, frame, NULL)) + { + return 0;//skip and dont care + } + } + + return vj_tag_record_frame( sample_id, frame, NULL, 0, info->pixel_format); +} + +static int vj_perform_record_commit_single(veejay_t *info) +{ + + char filename[512]; + //int n_files = 0; + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE) + { + if(sample_get_encoded_file(info->uc->sample_id, filename)) + { + int df = vj_event_get_video_format(); + int id = 0; + if ( df == ENCODER_YUV4MPEG || df == ENCODER_YUV4MPEG420 ) { + id = veejay_create_tag( info, VJ_TAG_TYPE_YUV4MPEG,filename,info->nstreams,0,0 ); + } + else + { + id = veejay_edit_addmovie_sample(info,filename, 0 ); + } + if(id <= 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "Error trying to add %s as sample or stream", filename); + return 0; + } + return id; + } + } + + if(info->uc->playback_mode==VJ_PLAYBACK_MODE_TAG) + { + int stream_id = (info->settings->offline_record ? info->settings->offline_tag_id : info->uc->sample_id); + if(vj_tag_get_encoded_file(stream_id, filename)) + { + int df = vj_event_get_video_format(); + int id = 0; + if( df == ENCODER_YUV4MPEG || df == ENCODER_YUV4MPEG420 ) { + id = veejay_create_tag( info, VJ_TAG_TYPE_YUV4MPEG,filename,info->nstreams,0,0 ); + } else { + id = veejay_edit_addmovie_sample(info, filename, 0); + } + if( id <= 0 ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Adding file %s to new sample", filename); + return 0; + } + return id; + } + } + return 0; +} + +void vj_perform_record_stop(veejay_t *info) +{ + video_playback_setup *settings = info->settings; + int df = vj_event_get_video_format(); + + if(info->uc->playback_mode==VJ_PLAYBACK_MODE_SAMPLE) + { + sample_reset_encoder(info->uc->sample_id); + sample_reset_autosplit(info->uc->sample_id); + if( settings->sample_record && settings->sample_record_switch) + { + settings->sample_record_switch = 0; + if( df != ENCODER_YUV4MPEG && df != ENCODER_YUV4MPEG420 ) { + veejay_set_sample( info,sample_size()-1); + veejay_msg(VEEJAY_MSG_INFO, "Autoplaying new sample %d", sample_size()-1); + } else { + veejay_msg(VEEJAY_MSG_WARNING, "Not autoplaying new streams."); + } + } + settings->sample_record = 0; + settings->sample_record_id = 0; + settings->sample_record_switch =0; + settings->render_list = 0; + } + + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG) + { + int stream_id = (settings->offline_record ? settings->offline_tag_id : info->uc->sample_id); + int play = settings->tag_record_switch; + vj_tag_reset_encoder(stream_id); + vj_tag_reset_autosplit(stream_id); + if(settings->offline_record) + { + play = settings->offline_created_sample; + settings->offline_record = 0; + settings->offline_created_sample = 0; + settings->offline_tag_id = 0; + } + else + { + settings->tag_record = 0; + settings->tag_record_switch = 0; + } + + if(play) + { + if(df != ENCODER_YUV4MPEG && df != ENCODER_YUV4MPEG420) + { + info->uc->playback_mode = VJ_PLAYBACK_MODE_SAMPLE; + veejay_set_sample(info ,sample_size()-1); + veejay_msg(VEEJAY_MSG_INFO, "Autoplaying new sample %d", sample_size()-1); + } + else { + + veejay_msg(VEEJAY_MSG_WARNING, "Not autoplaying new streams."); + } + + } + } + +} + + +void vj_perform_record_sample_frame(veejay_t *info, int sample) { + video_playback_setup *settings = info->settings; + uint8_t *frame[3]; + int res = 1; + int n = 0; + frame[0] = primary_buffer[0]->Y; + frame[1] = primary_buffer[0]->Cb; + frame[2] = primary_buffer[0]->Cr; + + if( available_diskspace() ) + res = vj_perform_render_sample_frame(info, frame, sample); + + if( res == 2) + { + int df = vj_event_get_video_format(); + int len = sample_get_total_frames(sample); + long frames_left = sample_get_frames_left(sample) ; + sample_stop_encoder( sample ); + n = vj_perform_record_commit_single( info ); + sample_reset_encoder( sample ); + if(frames_left > 0 ) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Continue, %d frames left to record", frames_left); + if( sample_init_encoder( sample, NULL, + df, info->current_edit_list, frames_left)==-1) + { + veejay_msg(VEEJAY_MSG_ERROR, + "Error while auto splitting "); + report_bug(); + } + } + else + { + veejay_msg(VEEJAY_MSG_DEBUG, "Added new sample %d of %d frames",n,len); + } + } + + + if( res == 1) + { + if( info->seq->active && info->seq->rec_id ) + info->seq->rec_id = 0; + sample_stop_encoder(sample); + vj_perform_record_commit_single( info ); + vj_perform_record_stop(info); + } + + if( res == -1) + { + if( info->seq->active && info->seq->rec_id ) + info->seq->rec_id = 0; + + sample_stop_encoder(sample); + vj_perform_record_stop(info); + } +} + + +void vj_perform_record_tag_frame(veejay_t *info) { + video_playback_setup *settings = info->settings; + uint8_t *frame[3]; + int res = 1; + int stream_id = info->uc->sample_id; + if( settings->offline_record ) + stream_id = settings->offline_tag_id; + + if(settings->offline_record) + { + frame[0] = record_buffer->Y; + frame[1] = record_buffer->Cb; + frame[2] = record_buffer->Cr; + } + else + { + frame[0] = primary_buffer[0]->Y; + frame[1] = primary_buffer[0]->Cb; + frame[2] = primary_buffer[0]->Cr; + } + + if(available_diskspace()) + res = vj_perform_render_tag_frame(info, frame); + + if( res == 2) + { + int df = vj_event_get_video_format(); + long frames_left = vj_tag_get_frames_left(stream_id) ; + vj_tag_stop_encoder( stream_id ); + vj_perform_record_commit_single( info ); + vj_tag_reset_encoder( stream_id ); + if(frames_left > 0 ) + { + if( vj_tag_init_encoder( stream_id, NULL, + df, frames_left)==-1) + { + veejay_msg(VEEJAY_MSG_WARNING, + "Error while auto splitting."); + report_bug(); + } + } + } + + + if( res == 1) + { + vj_tag_stop_encoder(stream_id); + vj_perform_record_commit_single( info ); + vj_perform_record_stop(info); + } + + if( res == -1) + { + vj_tag_stop_encoder(stream_id); + vj_perform_record_stop(info); + } + +} + + +static int vj_perform_tag_fill_buffer(veejay_t * info) +{ + int error = 1; + uint8_t *frame[3]; + int type = pvar_.type; + int active = pvar_.active; + frame[0] = primary_buffer[0]->Y; + frame[1] = primary_buffer[0]->Cb; + frame[2] = primary_buffer[0]->Cr; + + + + if(!active) + { + if (type == VJ_TAG_TYPE_V4L || type == VJ_TAG_TYPE_NET || type == VJ_TAG_TYPE_MCAST || type == VJ_TAG_TYPE_PICTURE ) + vj_tag_enable( info->uc->sample_id ); + } + else + { + + + if (vj_tag_get_frame(info->uc->sample_id, frame, NULL)) + { + error = 0; + cached_tag_frames[0] = info->uc->sample_id; + } + + } + + + if (error == 1) + { + VJFrame dumb; + vj_el_init_422_frame( info->current_edit_list, &dumb ); + + dumb.data[0] = frame[0]; + dumb.data[1] = frame[1]; + dumb.data[2] = frame[2]; + + dummy_apply(&dumb, + info->current_edit_list->video_width, + info->current_edit_list->video_height, VJ_EFFECT_COLOR_BLACK); + } + return 1; +} + +static void vj_perform_pre_chain(veejay_t *info, VJFrame *frame) +{ + veejay_memcpy( temp_buffer[0] ,frame->data[0], frame->len ); + veejay_memcpy( temp_buffer[1], frame->data[1], frame->uv_len); + veejay_memcpy( temp_buffer[2], frame->data[2], frame->uv_len ); /* /4 */ +} + +static inline void vj_perform_supersample_chain( veejay_t *info, VJFrame *frame ) +{ + chroma_supersample( + info->settings->sample_mode, + effect_sampler, + temp_buffer, + frame->width, + frame->height + ); + frame->ssm = 1; +} + + +void vj_perform_follow_fade(int status) { + pvar_.follow_fade = status; +} + +static int vj_perform_post_chain_sample(veejay_t *info, VJFrame *frame) +{ + unsigned int opacity; + int mode = pvar_.fader_active; + int follow = 0; + + if( frame->ssm ) + vj_perform_supersample_chain( info, frame ); + + if(mode == 2 ) // manual fade + opacity = (int) sample_get_fader_val(info->uc->sample_id); + else // fade in/fade out + opacity = (int) sample_apply_fader_inc(info->uc->sample_id); + + if(mode != 2) + { + int dir =sample_get_fader_direction(info->uc->sample_id); + + if((dir<0) &&(opacity == 0)) + { + sample_set_effect_status(info->uc->sample_id, 1); + sample_reset_fader(info->uc->sample_id); + if( pvar_.follow_fade ) { + follow = 1; + } + + veejay_msg(VEEJAY_MSG_DEBUG, "Sample Chain Auto Fade Out done"); + } + if((dir>0) && (opacity==255)) + { + sample_set_effect_status(info->uc->sample_id,0); + sample_reset_fader(info->uc->sample_id); + veejay_msg(VEEJAY_MSG_DEBUG, "Sample Chain Auto fade In done"); + if( pvar_.follow_fade ) { + follow = 1; + } + } + } else if(mode) { + if( pvar_.follow_fade ) { + follow = 1; + } + } + + int len2 = ( frame->ssm == 1 ? helper_frame->len : helper_frame->uv_len ); + + + opacity_blend_apply( frame->data ,temp_buffer,frame->len, len2, opacity ); + + if( follow ) { + //@ find something to jump to, start with last on chain + int i; + + for( i = SAMPLE_MAX_EFFECTS - 1; i > 0; i -- ) { + if( sample_get_chain_channel( info->uc->sample_id, i ) > 0 ) { + pvar_.follow_now[0] = sample_get_chain_channel(info->uc->sample_id, i ); + pvar_.follow_now[1] = sample_get_chain_source( info->uc->sample_id, i ); + } + } + } + + return follow; +} + + +static int vj_perform_post_chain_tag(veejay_t *info, VJFrame *frame) +{ + unsigned int opacity; + int mode = pvar_.fader_active; + int follow = 0; + + if( !frame->ssm ) + vj_perform_supersample_chain( info, frame ); + + if(mode == 2) + opacity = (int) vj_tag_get_fader_val(info->uc->sample_id); + else + opacity = (int) vj_tag_apply_fader_inc(info->uc->sample_id); + + if( opacity == 0 ) { + if( pvar_.follow_fade ) { + follow = 1; + } + } + + if(mode != 2) + { + int dir = vj_tag_get_fader_direction(info->uc->sample_id); + if((dir < 0) && (opacity == 0)) + { + vj_tag_set_effect_status(info->uc->sample_id,1); + vj_tag_reset_fader(info->uc->sample_id); + if( pvar_.follow_fade ) { + follow = 1; + } + + veejay_msg(VEEJAY_MSG_DEBUG, "Stream Chain Auto Fade done"); + } + if((dir > 0) && (opacity == 255)) + { + vj_tag_set_effect_status(info->uc->sample_id,0); + vj_tag_reset_fader(info->uc->sample_id); + if( pvar_.follow_fade ) { + follow = 1; + } + veejay_msg(VEEJAY_MSG_DEBUG, "Stream Chain Auto Fade done"); + } + } else if(mode){ + if( pvar_.follow_fade ) { + follow = 1; + } + } + + int len2 = ( frame->ssm == 1 ? helper_frame->len : helper_frame->uv_len ); + opacity_blend_apply( frame->data ,temp_buffer,frame->len, len2, opacity ); + + if( follow ) { + //@ find something to jump to, start with last on chain + int i; + + for( i = SAMPLE_MAX_EFFECTS - 1; i > 0; i -- ) { + if( sample_get_chain_channel( info->uc->sample_id, i ) > 0 ) { + pvar_.follow_now[0] = vj_tag_get_chain_channel(info->uc->sample_id, i ); + pvar_.follow_now[1] = vj_tag_get_chain_source( info->uc->sample_id, i ); + } + } + } + + + return follow; +} +static uint32_t play_audio_sample_ = 0; +int vj_perform_queue_audio_frame(veejay_t *info) +{ + if( info->audio == NO_AUDIO || !info->current_edit_list->has_audio) + return 1; + +#ifdef HAVE_JACK + editlist *el = info->current_edit_list; + video_playback_setup *settings = info->settings; + long this_frame = settings->current_frame_num; + int num_samples = (el->audio_rate/el->video_fps); + int pred_len = num_samples; + int bps = el->audio_bps; + uint8_t *a_buf = top_audio_buffer; + int rs = 0; + if (info->audio == AUDIO_PLAY) + { + if(settings->audio_mute || settings->current_playback_speed == 0 ) + { + veejay_memset( a_buf, 0, num_samples * bps); + vj_jack_play( a_buf, (num_samples * bps )); + return 1; + } + + switch (info->uc->playback_mode) + { + case VJ_PLAYBACK_MODE_SAMPLE: + if( el->has_audio ) + num_samples = vj_perform_fill_audio_buffers(info,a_buf, audio_render_buffer + (2* PERFORM_AUDIO_SIZE * MAX_SPEED), &play_audio_sample_); + if(num_samples <= 0 ) + { + num_samples = pred_len; + veejay_memset( a_buf, 0, num_samples * bps ); + } + else + rs = 1; + break; + case VJ_PLAYBACK_MODE_PLAIN: + if( el->has_audio ) + { + if (settings->current_frame_num <= settings->max_frame_num) + num_samples = vj_el_get_audio_frame(el, this_frame,a_buf ); + else + num_samples = 0; + if( num_samples <= 0 ) + { + num_samples = pred_len; + veejay_memset( a_buf, 0, num_samples * bps ); + } + else + rs = 1; + if( settings->current_playback_speed < 0 && rs ) + vj_perform_reverse_audio_frame(info,num_samples,a_buf); + } + break; + //@ pfffff there is no stream that delivers audio anyway yet + case VJ_PLAYBACK_MODE_TAG: + if(el->has_audio) + { + num_samples = vj_tag_get_audio_frame(info->uc->sample_id, a_buf); + if(num_samples <= 0 ) + { + num_samples = pred_len; + veejay_memset(a_buf, 0, num_samples * bps ); + } + else + rs = 1; + } + break; + } + + vj_jack_play( a_buf, (num_samples * bps )); + } +#endif + return 1; +} + +int vj_perform_get_width( veejay_t *info ) +{ +#ifdef HAVE_GL + if(info->video_out == 3 ) + return x_display_width(info->gl); +#endif +#ifdef HAVE_SDL + if(info->video_out <= 1 ) + return vj_sdl_screen_w(info->sdl[0]); +#endif + return info->video_output_width; +} + +int vj_perform_get_height( veejay_t *info ) +{ +#ifdef HAVE_GL + if(info->video_out == 3 ) + return x_display_height(info->gl); +#endif +#ifdef HAVE_SDL + if(info->video_out <= 1 ) + return vj_sdl_screen_h(info->sdl[0]); +#endif + return info->video_output_height; +} + +static char *vj_perform_print_credits( veejay_t *info ) +{ + char text[1024]; + veejay_memset(text,0,sizeof(text)); + snprintf(text, 1024,"This is Veejay version %s\n%s\n%s\n%s\n",VERSION,intro,copyr,license); + + return strdup(text); +} + +static char *vj_perform_osd_status( veejay_t *info ) +{ + video_playback_setup *settings = info->settings; + char *more = NULL; + if(info->composite ) { + void *vp = composite_get_vp( info->composite ); + if(viewport_get_mode(vp)==1 ) { + more = viewport_get_my_status( vp ); + } + } + + MPEG_timecode_t tc; + char timecode[20]; + char tmp[32]; + char buf[256]; + veejay_memset(&tc,0,sizeof(MPEG_timecode_t)); + veejay_memset(&tmp,0,sizeof(tmp)); + veejay_memset(&buf,0,sizeof(buf)); + y4m_ratio_t ratio = mpeg_conform_framerate( (double)info->current_edit_list->video_fps ); + int n = mpeg_framerate_code( ratio ); + + mpeg_timecode(&tc, settings->current_frame_num, n, info->current_edit_list->video_fps ); + + snprintf(timecode, 20, "%2d:%2.2d:%2.2d:%2.2d", + tc.h, tc.m, tc.s, tc.f ); + + + char *extra = NULL; + + if( info->composite ) { + int status = -1; + if( info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) { + status = sample_get_composite( info->uc->sample_id ); + } else if (info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) { + status = vj_tag_get_composite( info->uc->sample_id ); + } + if( status == 0 ) { + snprintf(tmp,sizeof(tmp), "Proj"); + extra = strdup(tmp); + } + else if(status == 1 ) { + snprintf(tmp,sizeof(tmp), "Cam"); + extra = strdup(tmp); + } + } + + switch(info->uc->playback_mode) { + case VJ_PLAYBACK_MODE_SAMPLE: + snprintf(buf,256, "(S) %s %d of %d Cache=%dMb Cost=%dms", + timecode, + info->uc->sample_id, + sample_size()-1, + sample_cache_used(0), + info->real_fps ); + break; + case VJ_PLAYBACK_MODE_TAG: + snprintf(buf,256, "(T) %s %d of %d Cost=%dms", + timecode, + info->uc->sample_id, + vj_tag_size(), + info->real_fps ); + break; + default: + snprintf(buf,256, "(P) %s", timecode ); + break; + } + + int total_len = strlen(buf) + ( extra == NULL ? 0 : strlen(extra)) + 1; + if( more ) + total_len += strlen(more); + char *status_str = (char*) malloc(sizeof(char) * total_len); + if( extra && more ) + snprintf(status_str,total_len,"%s %s %s",more, buf,extra); + else if ( more ) + snprintf(status_str, total_len, "%s %s", more,buf ); + else + strncpy( status_str, buf, total_len ); + + if(extra) + free(extra); + if(more) + free(more); + + return status_str; +} + + +static void vj_perform_render_osd( veejay_t *info, video_playback_setup *settings, int destination ) +{ + if(info->use_osd <= 0 || info->settings->composite ) + return; + + VJFrame *frame = info->effect_frame1; + frame->data[0] = primary_buffer[destination]->Y; + frame->data[1] = primary_buffer[destination]->Cb; + frame->data[2] = primary_buffer[destination]->Cr; + + if( !frame->ssm) + { + chroma_supersample( + settings->sample_mode, + effect_sampler, + frame->data, + frame->width, + frame->height + ); + frame->ssm = 1; + } + + + char *osd_text = NULL; + int placement = 0; + if( info->use_osd == 2 ) { + placement = 1; + osd_text = vj_perform_print_credits(info); + } else if (info->use_osd == 1 ) { + osd_text = vj_perform_osd_status(info); + } else if (info->use_osd == 3 && info->composite ) { + placement = 1; + osd_text = viewport_get_my_help( composite_get_vp(info->composite ) ); + } + if(osd_text) { + vj_font_render_osd_status(info->osd,frame,osd_text,placement); + free(osd_text); + } +} + +static void vj_perform_finish_chain( veejay_t *info ) +{ + VJFrame *frame = info->effect_frame1; + frame->data[0] = primary_buffer[0]->Y; + frame->data[1] = primary_buffer[0]->Cb; + frame->data[2] = primary_buffer[0]->Cr; + + int result = 0; + + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) + { + if( pvar_.fader_active ) + result = vj_perform_post_chain_tag(info,frame); + } + else if( info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) + { + if( pvar_.fader_active) + result = vj_perform_post_chain_sample(info,frame); + } + + if( result ) { + pvar_.follow_run = result; + } +} + +static void vj_perform_finish_render( veejay_t *info, video_playback_setup *settings, int destination ) +{ + VJFrame *frame = info->effect_frame1; + VJFrame *frame2= info->effect_frame2; + uint8_t *pri[3]; + uint8_t *buf[3]; + char *osd_text = NULL; + char *more_text = NULL; + int placement= 0; + + pri[0] = primary_buffer[destination]->Y; + pri[1] = primary_buffer[destination]->Cb; + pri[2] = primary_buffer[destination]->Cr; + if( settings->composite ) + { //@ scales in software + if( settings->ca ) { + settings->ca = 0; + } + + //@ focus on projection screen + if(composite_event( info->composite, pri, info->uc->mouse[0],info->uc->mouse[1],info->uc->mouse[2], + vj_perform_get_width(info), vj_perform_get_height(info)) ) { + //@ save config to playing sample/stream + if( info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) { + void *cur = vj_tag_get_composite_view(info->uc->sample_id); + if(cur == NULL ) + { + cur = composite_clone(info->composite); + vj_tag_set_composite_view(info->uc->sample_id, cur ); + } + composite_set_backing(info->composite,cur); + vj_tag_reload_config( info->composite,info->uc->sample_id, 1); + +// settings->composite); + } else if ( info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE) { + void *cur = sample_get_composite_view(info->uc->sample_id); + if(cur==NULL) { + cur = composite_clone(info->composite); + sample_set_composite_view(info->uc->sample_id,cur); + } + composite_set_backing(info->composite,cur); + sample_reload_config( info->composite,info->uc->sample_id, 1 ); + // settings->composite); + } + if( info->video_out == 0 ) { + //@ release focus + vj_sdl_grab( info->sdl[0], 0 ); + } + } + + if( info->use_osd == 2 ) { + osd_text = vj_perform_print_credits(info); + placement= 1; + } else if (info->use_osd == 1 ) { + osd_text = vj_perform_osd_status(info); + placement= 0; + } else if (info->use_osd == 3 && info->composite ) { + placement = 1; + osd_text = viewport_get_my_help( composite_get_vp(info->composite ) ); + more_text = vj_perform_osd_status(info); + } + } + + if( settings->composite ) { + VJFrame *out = yuv_yuv_template( pri[0],pri[1],pri[2],info->video_output_width,info->video_output_height, + get_ffmpeg_pixfmt( info->pixel_format)); + + int pff = get_ffmpeg_pixfmt(info->pixel_format); + if( frame->ssm == 1 ) + pff = (info->pixel_format == FMT_422F ? PIX_FMT_YUVJ444P : PIX_FMT_YUV444P ); + VJFrame *in = yuv_yuv_template( frame->data[0],frame->data[1],frame->data[2], + frame->width,frame->height, pff); + frame->ssm = composite_process(info->composite,out,in,settings->composite,pff); + + if(osd_text == NULL && info->use_osd == 3 ) { + int fx_mode=0; + int cur_e = 0; + int fx_id = 0; + if( info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) { + cur_e = vj_tag_get_selected_entry(info->uc->sample_id); + fx_mode = vj_tag_get_chain_status( info->uc->sample_id,cur_e ); + } else if ( info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) { + cur_e = sample_get_selected_entry(info->uc->sample_id); + fx_mode = sample_get_chain_status(info->uc->sample_id,cur_e); + } + osd_text = get_embedded_help(fx_mode,info->uc->playback_mode,cur_e,info->uc->sample_id ); + } + + if(osd_text) { + void *vp = composite_get_vp( info->composite ); + int on_proj = viewport_get_mode(vp); + + // if( settings->composite == 1 ) + // on_proj = 1; + if(!frame->ssm) { + chroma_supersample( + settings->sample_mode, + effect_sampler, + frame->data, + frame->width, + frame->height + ); + frame->ssm = 1; + } + // if( on_proj == 1 ) + // { + VJFrame *tst = composite_get_draw_buffer( info->composite ); + if(tst) { + vj_font_render_osd_status(info->osd,tst,osd_text,placement); + if(more_text) + vj_font_render_osd_status(info->osd,tst,more_text,0); + free(tst); + } + /* } else { + if(more_text) + vj_font_render_osd_status(info->osd,out,more_text,0); + vj_font_render_osd_status(info->osd, out, osd_text,placement ); + }*/ + } + free(out); + free(in); + } + if( osd_text) + free(osd_text); + if( more_text) + free(more_text); + + + if (info->uc->take_bg==1) + { + info->uc->take_bg = vj_perform_take_bg(info,frame,0); + } + + if( frame->ssm == 1 ) + { + chroma_subsample( + settings->sample_mode, + effect_sampler, + pri, + frame->width, + frame->height + ); + frame->ssm = 0; + } + + if( frame2->ssm == 1 ) + { + frame2->ssm=0; + } + + if (info->uc->take_bg==1) + { + int d = vj_perform_take_bg(info,frame,1); + info->uc->take_bg = 0; + } + + +} + +static void vj_perform_font_render2(veejay_t *info, uint8_t *frame[3],video_playback_setup *settings ) +{ +#ifdef STRICT_CHECKING +// assert( info->effect_frame1->ssm == 1 ); +#endif +#ifdef HAVE_FREETYPE + int n = vj_font_norender( info->font, settings->current_frame_num ); + if( n > 0 ) + vj_font_render( info->font, frame , settings->current_frame_num ); +#endif +} + +static void vj_perform_render_font( veejay_t *info, video_playback_setup *settings ) +{ +// VJFrame *frame = font_frame; + VJFrame *frame = info->effect_frame1; + + frame->data[0] = primary_buffer[0]->Y; + frame->data[1] = primary_buffer[0]->Cb; + frame->data[2] = primary_buffer[0]->Cr; + +#ifdef HAVE_FREETYPE + int n = vj_font_norender( info->font, settings->current_frame_num ); + if( n > 0 ) + { + if( !frame->ssm ) + { + chroma_supersample( + settings->sample_mode, + effect_sampler, + frame->data, + frame->width, + frame->height + ); + frame->ssm = 1; + } + + vj_font_render( info->font, frame , settings->current_frame_num ); + } +#endif +} + +static void vj_perform_record_frame( veejay_t *info ) +{ + VJFrame *frame = info->effect_frame1; + int which_sample = info->uc->sample_id; + if( info->seq->active && info->seq->rec_id && info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) + which_sample = info->seq->rec_id; + + if(frame->ssm == 1) + { + video_playback_setup *settings = info->settings; + uint8_t *dst[3] = { NULL, primary_buffer[3]->Cb, + primary_buffer[3]->Cr }; + chroma_subsample_cp( settings->sample_mode, effect_sampler, + frame->data,dst, frame->width,frame->height ); + uint8_t *chroma[2] = { primary_buffer[0]->Cb, primary_buffer[0]->Cr }; + primary_buffer[0]->Cb = dst[1]; + primary_buffer[0]->Cr = dst[2]; + + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) + vj_perform_record_tag_frame(info); + else if (info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) + vj_perform_record_sample_frame(info, which_sample ); + + primary_buffer[0]->Cb = chroma[0]; + primary_buffer[0]->Cr = chroma[1]; + } + else + { + if(info->uc->playback_mode == VJ_PLAYBACK_MODE_TAG ) + vj_perform_record_tag_frame(info); + else if (info->uc->playback_mode == VJ_PLAYBACK_MODE_SAMPLE ) + vj_perform_record_sample_frame(info, which_sample ); + } +} + +static int vj_perform_render_magic( veejay_t *info, video_playback_setup *settings ) +{ + int deep = 0; + + VJFrame *frame = info->effect_frame1; + VJFrame *frame2= info->effect_frame2; + uint8_t *pri[3]; + pri[0] = primary_buffer[0]->Y; + pri[1] = primary_buffer[0]->Cb; + pri[2] = primary_buffer[0]->Cr; + if( frame->ssm == 1 ) + { + chroma_subsample( + settings->sample_mode, + effect_sampler, + pri, + frame->width, + frame->height + ); + frame->ssm = 0; + } + + + vj_perform_finish_chain( info ); + + vj_perform_render_font( info, settings); + //@ record frame + if( pvar_.enc_active ) + vj_perform_record_frame(info); + //@ Render OSD menu + if(!settings->composite) + vj_perform_render_osd( info, settings, deep ); + + //@ Do the subsampling + vj_perform_finish_render( info, settings,deep ); + + return deep; +} + + +int vj_perform_queue_video_frame(veejay_t *info, const int skip_incr) +{ + video_playback_setup *settings = info->settings; + if(skip_incr) + return 1; + + int is444 = 0; + int res = 0; + + int safe_ff = pvar_.follow_fade; + veejay_memset( &pvar_, 0, sizeof(varcache_t)); + pvar_.follow_fade = safe_ff; + + if(settings->offline_record) + vj_perform_record_tag_frame(info); + + int cur_out = info->out_buf; + + switch (info->uc->playback_mode) + { + case VJ_PLAYBACK_MODE_SAMPLE: + + sample_var( info->uc->sample_id, &(pvar_.type), + &(pvar_.fader_active), + &(pvar_.fx_status), + &(pvar_.enc_active), + &(pvar_.active) + ); + + if( info->seq->active && info->seq->rec_id ) + pvar_.enc_active = 1; + + vj_perform_plain_fill_buffer(info); + + cached_sample_frames[0] = info->uc->sample_id; + + if(vj_perform_verify_rows(info)) + vj_perform_sample_complete_buffers(info, &is444); + + + cur_out = vj_perform_render_magic( info, info->settings ); + res = 1; + + break; + + case VJ_PLAYBACK_MODE_PLAIN: + + vj_perform_plain_fill_buffer(info); + + cur_out = vj_perform_render_magic( info, info->settings ); + res = 1; + break; + case VJ_PLAYBACK_MODE_TAG: + + vj_tag_var( info->uc->sample_id, + &(pvar_.type), + &(pvar_.fader_active), + &(pvar_.fx_status), + &(pvar_.enc_active), + &(pvar_.active) + + ); + + if (vj_perform_tag_fill_buffer(info)) + { + if(vj_perform_verify_rows(info)) + vj_perform_tag_complete_buffers(info, &is444); + cur_out = vj_perform_render_magic( info, info->settings ); + } + res = 1; + break; + default: + return 0; + } + + info->out_buf = cur_out; + + return res; +} + + +int vj_perform_queue_frame(veejay_t * info, int skip ) +{ + video_playback_setup *settings = (video_playback_setup*) info->settings; + + if( pvar_.follow_run ) { + veejay_msg(VEEJAY_MSG_DEBUG, "Following to [%d,%d]", pvar_.follow_now[0], pvar_.follow_now[1] ); + + if( pvar_.follow_now[1] == 0 ) { + info->uc->playback_mode = VJ_PLAYBACK_MODE_SAMPLE; + veejay_set_sample( info, pvar_.follow_now[1] ); + } else { + info->uc->playback_mode = VJ_PLAYBACK_MODE_TAG; + veejay_set_sample( info, pvar_.follow_now[1] ); + } + + pvar_.follow_run = 0; + pvar_.follow_now[0] = 0; + pvar_.follow_now[1] = 0; + } + + + if(!skip) + { + switch(info->uc->playback_mode) + { + case VJ_PLAYBACK_MODE_TAG: + vj_perform_increase_tag_frame(info, settings->current_playback_speed); + break; + case VJ_PLAYBACK_MODE_SAMPLE: + vj_perform_increase_sample_frame(info,settings->current_playback_speed); + break; + case VJ_PLAYBACK_MODE_PLAIN: + vj_perform_increase_plain_frame(info,settings->current_playback_speed); + break; + default: + break; + } + } + + //@ increase tick + + vj_perform_clear_cache(); + //__global_frame = 0; + + settings->cycle_count[0] ++; + if( settings->cycle_count[0] == 0 ) + settings->cycle_count[1] ++; + + return 0; +} + + +static int track_dup = 0; +void vj_perform_randomize(veejay_t *info) +{ + video_playback_setup *settings = info->settings; + if(settings->randplayer.mode == RANDMODE_INACTIVE) + return; + + double n_sample = (double) (sample_size()-1); + + if( settings->randplayer.mode == RANDMODE_SAMPLE ) + track_dup = info->uc->sample_id; + + if( n_sample == 1.0 ) + track_dup = 0; + + int take_n = 1 + (int) (n_sample * rand() / (RAND_MAX+1.0)); + int min_delay = 1; + int max_delay = 0; + char timecode[15]; + + int use = ( take_n == track_dup ? 0: 1 ); + + while(!sample_exists(take_n) || !use) + { + veejay_msg(VEEJAY_MSG_DEBUG, + "Sample to play (at random) %d does not exist", + take_n); + take_n = 1 + (int) ( n_sample * rand()/(RAND_MAX+1.0)); + use = (track_dup == take_n ? 0:1 ); + } + + int start,end; + start = sample_get_startFrame( take_n); + end = sample_get_endFrame( take_n ); + + if( settings->randplayer.timer == RANDTIMER_FRAME ) + { + max_delay = (end-start) + 1; + max_delay = min_delay + (int) ((double)max_delay * rand() / (RAND_MAX+1.0)); + } + else + { + max_delay = (end-start); + } + + settings->randplayer.max_delay = max_delay; + settings->randplayer.min_delay = min_delay; + + + MPEG_timecode_t tc; + y4m_ratio_t ratio = mpeg_conform_framerate( (double)info->current_edit_list->video_fps ); + mpeg_timecode(&tc,max_delay,mpeg_framerate_code(ratio),info->current_edit_list->video_fps ); + sprintf(timecode, "%2d:%2.2d:%2.2d:%2.2d", tc.h, tc.m, tc.s, tc.f); + veejay_msg(VEEJAY_MSG_DEBUG, "Sample randomizer trigger in %s", timecode ); + + veejay_set_sample( info, take_n ); +} + +int vj_perform_rand_update(veejay_t *info) +{ + video_playback_setup *settings = info->settings; + if(settings->randplayer.mode == RANDMODE_INACTIVE) + return 0; + if(settings->randplayer.mode == RANDMODE_SAMPLE) + { + settings->randplayer.max_delay --; + if(settings->randplayer.max_delay <= 0 ) + vj_perform_randomize(info); + return 1; + } + return 0; +} + diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-perform.h b/branches/V-1.5.3/veejay-server/veejay/vj-perform.h new file mode 100644 index 00000000..0ea9b8c2 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-perform.h @@ -0,0 +1,73 @@ +#ifndef VJ_PERFORM_H +#define VJ_PERFORM_H + +#include "vj-lib.h" + +/* multithreaded code, what starts in queue belongs to playback_thread */ +uint8_t *vj_perform_get_preview_buffer(); + +void vj_perform_init_output_frame( veejay_t *info, uint8_t **frame, + int dst_w, int dst_h ); + +void vj_perform_update_plugin_frame(VJFrame *frame); + +VJFrame *vj_perform_init_plugin_frame(veejay_t *info); +VJFrameInfo *vj_perform_init_plugin_frame_info(veejay_t *info); + +int vj_perform_init(veejay_t * info); + +int vj_perform_init_audio(veejay_t * info); + +void vj_perform_free(veejay_t *info); + +int vj_perform_audio_start(veejay_t * info); + +void vj_perform_audio_status(struct timeval tmpstmp, unsigned int nb_out, + unsigned int nb_err); + +void vj_perform_audio_stop(veejay_t * info); + +void vj_perform_get_primary_frame(veejay_t * info, uint8_t ** frame ); + +void vj_perform_get_primary_frame_420p(veejay_t *info, uint8_t **frame ); + +int vj_perform_fill_audio_buffers(veejay_t *info, uint8_t *audio_buf, uint8_t *temporary_buffer, int *temporary_sum); + +int vj_perform_tag_decode_buffers(veejay_t * info, int entry); + +int vj_perform_queue_frame(veejay_t * info, int skip); + +int vj_perform_queue_audio_frame(veejay_t * info); + +int vj_perform_queue_video_frame(veejay_t * info, int skip); + +void vj_perform_clear_frame_info(); + +void vj_perform_record_stop(veejay_t *info); + +void vj_perform_record_sample_frame(veejay_t *info, int sample); + +void vj_perform_record_tag_frame(veejay_t *info ); +void vj_perform_get_output_frame_420p( veejay_t *info, uint8_t **frame, int w, int h ); +void vj_perform_get_output_frame( uint8_t **frame ); + +int vj_perform_get_cropped_frame( veejay_t *info, uint8_t **frame, int crop ); +int vj_perform_init_cropped_output_frame(veejay_t *info, VJFrame *src, int *dw, int *dh ); +void vj_perform_get_crop_dimensions(veejay_t *info, int *w, int *h); +int vj_perform_rand_update(veejay_t *info); +void vj_perform_randomize(veejay_t *info); + +void vj_perform_free_plugin_frame(VJFrameInfo *f ); + +uint8_t *vj_perform_get_a_work_buffer( ); + +int vj_perform_send_primary_frame_s2(veejay_t *info, int mcast, int dst_link); +void vj_perform_get_backstore( uint8_t **frame ); +int vj_perform_get_sampling(); + +int vj_perform_get_width( veejay_t *info ); +int vj_perform_get_height( veejay_t *info ); + +void vj_perform_follow_fade(int status); + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-pjack.c b/branches/V-1.5.3/veejay-server/veejay/vj-pjack.c new file mode 100644 index 00000000..e1f12655 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-pjack.c @@ -0,0 +1,200 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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 +#ifdef HAVE_JACK +#include +#include +static int driver = 0; +static int bits_per_sample = 0; +static unsigned long audio_rate = 0; +static int audio_channels = 0; +static int audio_bps = 0; +static unsigned long v_rate = 0; +extern void veejay_msg(int type, const char format[], ...); + +int vj_jack_initialize() +{ + JACK_Init(); + return 0; +} +static int _vj_jack_start(int *dri) +{ + int err = JACK_Open(dri, bits_per_sample,&audio_rate,audio_channels); + if(err == ERR_RATE_MISMATCH) + { + veejay_msg(1, + "(Jackd) Sample rate mismatch (Retrying)"); + + err = JACK_Open(dri, bits_per_sample,&audio_rate, + audio_channels); + + } + + if(err != ERR_SUCCESS) + { + switch(err) + { + case ERR_OPENING_JACK: + veejay_msg(0, "Unable to open Jackd (is jackd running?"); + break; + case ERR_RATE_MISMATCH: + veejay_msg(0, "Jackd cannot handle samplerate of %d Hz", audio_rate); + break; + case ERR_TOO_MANY_OUTPUT_CHANNELS: + veejay_msg(0, "Cannot connect to jackd, Too many output channels: %d", + audio_channels ); + break; + case ERR_PORT_NOT_FOUND: + veejay_msg(0, "Unable to find jack port"); + break; + } +// veejay_msg(0, "To run veejay without audio, use -a0"); + return 0; + } + + return 1; +} + +int vj_jack_init(editlist *el) +{ + int err; + int v_rate = el->audio_rate; + int i = 0; + int ret = 0; + + JACK_Init(); + + bits_per_sample = 16; + audio_channels = el->audio_chans; + + if( !_vj_jack_start(&driver) ) + return ret; + + long jack_rate = JACK_GetSampleRate(driver ); + + audio_bps = v_rate;// audio_rate * audio_channels; + + ret = 1; + + if( jack_rate != el->audio_rate ) { + veejay_msg(1,"Jack is running with a different sample rate (%ld)! Really should use a rate of %d", jack_rate,el->audio_rate ); + ret = 2; + } + + JACK_SetState(driver, PAUSED ); + + return ret; +} + +int vj_jack_rate() +{ + return JACK_GetSampleRate(driver); +} + + +int vj_jack_continue(int speed) +{ + if(speed==0) + { + if(JACK_GetState(driver) == PAUSED) + return 1; + + JACK_SetState(driver, PAUSED ); + return 1; + } + + if( JACK_GetState(driver) == PAUSED ) + { + JACK_SetState(driver, PLAYING); + return 1; + } + return 0; +} + + +int vj_jack_stop() +{ + + JACK_Reset( driver ); + + if(JACK_Close(driver)) + { + veejay_msg(2, + "(Jack) Error closing device"); + } + return 1; +} + +void vj_jack_enable() +{ + if( JACK_GetState(driver) == STOPPED ) + JACK_SetState(driver, PLAYING ); +} + +void vj_jack_disable() +{ + JACK_SetState( driver, STOPPED ); +} + + +void vj_jack_reset() +{ + JACK_Reset(driver); +} + +int vj_jack_c_play(void *data, int len, int entry) +{ + return 0; +} + +int vj_jack_play(void *data, int len) +{ + return JACK_Write(driver,data,len); +} + +int vj_jack_set_volume(int volume) +{ + if(JACK_SetAllVolume( driver, volume)==0) + return 1; + return 0; +} + +int vj_jack_pause() +{ + JACK_SetState(driver,PAUSED); + return 1; +} + +int vj_jack_resume() +{ + JACK_SetState(driver,PLAYING); + return 1; +} + +int vj_jack_get_space() +{ + return JACK_GetBytesFreeSpace(driver); +} + +long vj_jack_get_status(long int *sec, long int *usec) +{ + return JACK_OutputStatus( driver, sec, usec); +} +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-plug.h b/branches/V-1.5.3/veejay-server/veejay/vj-plug.h new file mode 100644 index 00000000..0cdeb756 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-plug.h @@ -0,0 +1,49 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + + +*/ + +#ifndef _VEEJAY_PLUG_H +#define _VEEJAY_PLUG_H +#include +#define VJPLUG_VIDO_DRIVER 1 +#define VJPLUG_NORMAL 0 +#define VJPLUG_VIDI_DRIVER 2 + +#define VJ_EFFECT_ERROR -1024 +#define VJ_EFFECT_DESCR_LEN 200; + +#define ARRAY_SIZE(buf) (\ + (int) ( sizeof(buf[0]) / sizeof(uint8_t) ) + \ + (int) ( sizeof(buf[1]) / sizeof(uint8_t) ) +\ + (int) ( sizeof(buf[2]) / sizeof(uint8_t) ) ) + +/* VJPluginInfo + this struct describeds the plugin and its events +*/ +typedef struct +{ + char *name; // name of plugin + char *help; // help to display + int is_sink; + int is_src; + int plugin_type; +} VJPluginInfo; + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-sdl.c b/branches/V-1.5.3/veejay-server/veejay/vj-sdl.c new file mode 100644 index 00000000..bcee2205 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-sdl.c @@ -0,0 +1,592 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2004 Niels Elburg + * + * 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 + */ + +/* + * Output in YUY2 always + * Seems that YUV 4:2:0 (YV12) overlays have problems with multiple SDL video window + */ +#include +#ifdef HAVE_SDL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//extern void *(* veejay_memcpy)(void *to, const void *from, size_t len) ; +#ifdef STRICT_CHECKING +#include +#endif +/* +static int wm_fullscreen(int action, Display *disp, Window *win) { +#ifdef STRICT_CHECKING + assert(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD || + action == _NET_WM_STATE_TOGGLE ); +#endif + XEvent xev; + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.message_type = XInternAtom( disp, + "_NET_WM_STATE", False ); + xev.xclient.window = win; + xev.xclient.format = 32; + xev.xclient.data.1[0] = action; + xev.xclient.data.1[1] = XInternAtom( disp, + "_NET_WM_STATE_FULLSCREEN",False ); + xev.xclient.data.1[2] = 0; + xev.xclient.data.1[3] = 0; + xev.xclient.data.1[4] = 0; + + if( !XSendEvent( disp, DefaultRootWindow( disp ), False, + SubstructureRedirectMask | + SubstructureNotifyMask, &xev ) ) + { + veejay_msg(0, "WM Fullscreen state failed"); + return 0; + } + return 1; +} +*/ +static void vj_sdl_move( vj_sdl *vjsdl , int scaled_width, int scaled_height, int x, int y ) +{ + //@ sw_scale_width is misleading ; it lets SDL use the BES + if (scaled_width) + vjsdl->sw_scale_width = scaled_width; + if (scaled_height) + vjsdl->sw_scale_height = scaled_height; + + int my_bpp = SDL_VideoModeOK( vjsdl->sw_scale_width, vjsdl->sw_scale_height,24, + vjsdl->flags[1] ); + if(!my_bpp) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Requested depth not supported"); + return; + } + + vjsdl->screen = SDL_SetVideoMode( vjsdl->sw_scale_width, vjsdl->sw_scale_height,my_bpp, + vjsdl->flags[1]); + + vjsdl->rectangle.x = 0; + vjsdl->rectangle.y = 0; + vjsdl->rectangle.w = scaled_width; + vjsdl->rectangle.h = scaled_height; + + + veejay_msg(VEEJAY_MSG_INFO, "Changed video window to size %d x %d", + vjsdl->sw_scale_width,vjsdl->sw_scale_height); +} +vj_sdl *vj_sdl_allocate(int width, int height, int fmt) +{ + vj_sdl *vjsdl = (vj_sdl *) vj_malloc(sizeof(vj_sdl)); + if (!vjsdl) + return NULL; + + veejay_memset( vjsdl,0,sizeof(vj_sdl)); + + vjsdl->flags[0] = 0; + vjsdl->flags[1] = 0; + vjsdl->mouse_motion = 1; + vjsdl->use_keyboard = 1; + vjsdl->pix_format = SDL_YUY2_OVERLAY; + vjsdl->pix_fmt = fmt; + vjsdl->width = width; + vjsdl->height = height; + vjsdl->frame_size = width * height; + vjsdl->sw_scale_width = 0; + vjsdl->sw_scale_height = 0; + vjsdl->custom_geo[0] = -1; + vjsdl->custom_geo[1] = -1; + vjsdl->show_cursor = 0; + vjsdl->display = NULL; + switch(fmt) { + //@ dont use YUVJ here - on blitting it to SDL it will be converted to YUV clamped for YUYJ422 + //FIXME + case FMT_422F:vjsdl->ffmpeg_pixfmt = PIX_FMT_YUV422P;break; + case FMT_422:vjsdl->ffmpeg_pixfmt = PIX_FMT_YUV422P;break; + } + sws_template templ; + memset(&templ,0,sizeof(sws_template)); + templ.flags = yuv_which_scaler(); + VJFrame *src = yuv_yuv_template( NULL,NULL,NULL,vjsdl->width,vjsdl->height, vjsdl->ffmpeg_pixfmt ); + VJFrame *dst = yuv_yuv_template( NULL,NULL,NULL,vjsdl->width,vjsdl->height,PIX_FMT_YUYV422); + vjsdl->scaler = yuv_init_swscaler( src,dst, &templ, yuv_sws_get_cpu_flags() ); + free(src); + free(dst); + return vjsdl; +} + +void vj_sdl_set_geometry(vj_sdl* sdl, int w, int h) +{ + sdl->custom_geo[0] = w; + sdl->custom_geo[1] = h; + if (sdl->custom_geo[0] != -1 && sdl->custom_geo[1]!=-1) + { + char exp_str[100]; + sprintf(exp_str, "SDL_VIDEO_WINDOW_POS=%d,%d",sdl->custom_geo[0], + sdl->custom_geo[1]); + if(putenv(exp_str)==0) + veejay_msg(VEEJAY_MSG_DEBUG,"SDL geometry %d , %d", + sdl->custom_geo[0],sdl->custom_geo[1]); + } + +} + +void vj_sdl_resize( vj_sdl *vjsdl , int scaled_width, int scaled_height, int fs ) +{ + //@ sw_scale_width is misleading ; it lets SDL use the BES + if (scaled_width) + vjsdl->sw_scale_width = scaled_width; + if (scaled_height) + vjsdl->sw_scale_height = scaled_height; + + int my_bpp = SDL_VideoModeOK( vjsdl->sw_scale_width, vjsdl->sw_scale_height,24, + vjsdl->flags[fs] ); + if(!my_bpp) + { + veejay_msg(VEEJAY_MSG_DEBUG, "Requested depth not supported"); + return; + } + + vjsdl->screen = SDL_SetVideoMode( vjsdl->sw_scale_width, vjsdl->sw_scale_height,my_bpp, + vjsdl->flags[fs]); + + vjsdl->rectangle.x = 0; + vjsdl->rectangle.y = 0; + vjsdl->rectangle.w = scaled_width; + vjsdl->rectangle.h = scaled_height; + + + veejay_msg(VEEJAY_MSG_INFO, "Changed video window to size %d x %d", + vjsdl->sw_scale_width,vjsdl->sw_scale_height); +} + + +int vj_sdl_init(int ncpu, vj_sdl * vjsdl, int scaled_width, int scaled_height, const char *caption, int show, int fs) +{ + uint8_t *sbuffer; + char name[100]; + int i = 0; + const int bpp = 24; + const SDL_VideoInfo *info = NULL; + SDL_SysWMinfo wminfo; + + if (!vjsdl) + return 0; + + veejay_memset( &wminfo, 0, sizeof(SDL_SysWMinfo)); + + + /* dont overwrite environment settings, but export if they are not set already */ + + setenv( "SDL_VIDEO_YUV_DIRECT", "1", 0 ); + setenv( "SDL_VIDEO_HWACCEL", "1", 0 ); + + char *hw_env = getenv("SDL_VIDEO_HWACCEL"); + int hw_on = 1; + if(hw_env) + { + hw_on = atoi(hw_env); + } + int extra_flags = (ncpu > 1 ? SDL_ASYNCBLIT : 0 ); + int extra_fs_flags = 0; + int manual_positioning = 0; + /* setup with no window, scale to some wxh+0x0 on fs + */ + char *veejay_screen_geom = getenv( "VEEJAY_SCREEN_GEOMETRY" ); + char *veejay_screen_size = getenv( "VEEJAY_SCREEN_SIZE" ); + if( veejay_screen_geom && veejay_screen_size ) { + extra_flags = extra_flags | SDL_NOFRAME; + manual_positioning = 1; + } else { + extra_fs_flags = SDL_FULLSCREEN; + } + + if (SDL_Init(SDL_INIT_VIDEO) < 0) + { + veejay_msg(VEEJAY_MSG_ERROR, "%s", SDL_GetError()); + veejay_msg(VEEJAY_MSG_INFO, "\tHint: 'export SDL_VIDEODRIVER=x11'"); + return 0; + } + +#ifdef STRICT_CHECKING + veejay_msg(VEEJAY_MSG_DEBUG, "%s" , (fs == 1 ? "Fullscreen": "Windowed")); +#endif +//FIXME + if( hw_on == 0 ) + { + veejay_msg(VEEJAY_MSG_WARNING, "Setting up for software emulation"); + vjsdl->flags[0] = SDL_SWSURFACE | SDL_ANYFORMAT | extra_flags; + vjsdl->flags[1] = SDL_SWSURFACE | SDL_ANYFORMAT | extra_flags | extra_fs_flags; + // vjsdl->flags[1] = SDL_SWSURFACE | SDL_FULLSCREEN | SDL_ANYFORMAT | extra_flags; + } + else + { + veejay_msg(VEEJAY_MSG_INFO, "Setting up SDL with Hardware Acceleration"); + vjsdl->flags[0] = SDL_HWSURFACE | SDL_DOUBLEBUF | extra_flags; + vjsdl->flags[1] = SDL_HWSURFACE | SDL_DOUBLEBUF | extra_flags | extra_fs_flags; + // vjsdl->flags[1] = SDL_HWSURFACE | SDL_FULLSCREEN | SDL_DOUBLEBUF | extra_flags; + } + + if (vjsdl->custom_geo[0] != -1 && vjsdl->custom_geo[1]!=-1) + { + char exp_str[100]; + sprintf(exp_str, "SDL_VIDEO_WINDOW_POS=%d,%d",vjsdl->custom_geo[0], + vjsdl->custom_geo[1]); + if(putenv(exp_str)==0) + veejay_msg(VEEJAY_MSG_DEBUG,"SDL geometry %d , %d", + vjsdl->custom_geo[0],vjsdl->custom_geo[1]); + } + + if (scaled_width) + vjsdl->sw_scale_width = scaled_width; + if (scaled_height) + vjsdl->sw_scale_height = scaled_height; + + + SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, 100 ); + + info = SDL_GetVideoInfo(); + + + veejay_msg(VEEJAY_MSG_DEBUG, "Video output driver: SDL"); + veejay_msg( (info->hw_available ? VEEJAY_MSG_DEBUG : VEEJAY_MSG_WARNING), " hw_surface = %s", + (info->hw_available ? "Yes" : "No")); + veejay_msg(VEEJAY_MSG_DEBUG, " window manager = %s", + (info->wm_available ? "Yes" : "No" )); + veejay_msg((info->blit_hw ? VEEJAY_MSG_DEBUG : VEEJAY_MSG_WARNING), " BLIT acceleration: %s ", + ( info->blit_hw ? "Yes" : "No" ) ); + veejay_msg(VEEJAY_MSG_DEBUG, " Software surface: %s", + ( info->blit_sw ? "Yes" : "No" ) ); + veejay_msg(VEEJAY_MSG_DEBUG, " Preferred depth: %d bits/pixel", info->vfmt->BitsPerPixel); + + int my_bpp = SDL_VideoModeOK( vjsdl->sw_scale_width, vjsdl->sw_scale_height,bpp, + vjsdl->flags[fs] ); + if(!my_bpp) + { + veejay_msg(VEEJAY_MSG_ERROR, "Requested depth of %d bits/pixel not supported for %dx%d",bpp,vjsdl->sw_scale_width,vjsdl->sw_scale_height); + return 0; + } + + vjsdl->screen = SDL_SetVideoMode( vjsdl->sw_scale_width, vjsdl->sw_scale_height,my_bpp, + vjsdl->flags[fs]); + + if (!vjsdl->screen) + { + veejay_msg(VEEJAY_MSG_WARNING, "%s", SDL_GetError()); + return 0; + } + + veejay_msg(VEEJAY_MSG_DEBUG, " Output dimensions: %d x %d", + vjsdl->sw_scale_width, vjsdl->sw_scale_height ); + + if (vjsdl->use_keyboard == 1) + SDL_EventState(SDL_KEYDOWN, SDL_ENABLE); + else + SDL_EventState(SDL_KEYDOWN, SDL_DISABLE); + + if (vjsdl->mouse_motion == 1) + SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE); + else + SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); + + + if (vjsdl->show_cursor == 1) + SDL_ShowCursor(SDL_ENABLE); + else + SDL_ShowCursor(SDL_DISABLE); + + SDL_WM_GrabInput( SDL_GRAB_OFF ); + + vjsdl->yuv_overlay = SDL_CreateYUVOverlay(vjsdl->width, + vjsdl->height, + vjsdl->pix_format, + vjsdl->screen); + + if (!vjsdl->yuv_overlay) + { + veejay_msg(VEEJAY_MSG_ERROR, "%s", SDL_GetError()); + return 0; + } + + SDL_VideoDriverName( name, 100 ); + +#ifndef X_DISPLAY_MISSING + if( vjsdl->display ) + x11_disable_screensaver( vjsdl->display ); +#endif + veejay_msg(VEEJAY_MSG_DEBUG, "Using Video Driver %s", name ); + + veejay_msg(VEEJAY_MSG_INFO, "Initialized %s SDL video overlay (%dx%d), %s", + ( vjsdl->pix_format == SDL_YV12_OVERLAY ? "YV12" : "YUYV"), + scaled_width, scaled_height, + ( vjsdl->yuv_overlay->hw_overlay ? "using Hardware Acceleration" : "not using Hardware Acceleration")); + + vjsdl->rectangle.x = 0; + vjsdl->rectangle.y = 0; + vjsdl->rectangle.w = scaled_width; + vjsdl->rectangle.h = scaled_height; + + if (!vj_sdl_lock(vjsdl)) + { + veejay_msg(VEEJAY_MSG_ERROR, "Cant lock SDL Surface"); + return 0; + } + + sbuffer = (uint8_t *) vjsdl->screen->pixels; + for (i = 0; i < vjsdl->screen->h; ++i) + { + memset(sbuffer, (i * 255) / vjsdl->screen->h, + vjsdl->screen->w * vjsdl->screen->format->BytesPerPixel); + sbuffer += vjsdl->screen->pitch; + } + vjsdl->display = NULL; + if(SDL_GetWMInfo(&wminfo)) + { + if( wminfo.subsystem == SDL_SYSWM_X11 ) + { + vjsdl->display = wminfo.info.x11.display; + + } + /* XWindowAttributes attr; + Display *disp; + Window win,dum; + int x=0,y=0,w=0,h=0,gravity=0; + disp = wminfo.info.x11.display; + win = wminfo.info.x11.window; + XSync(disp,0); + XGetWindowAttributes(disp,win, &attr); + XTranslateCoordinates(disp,win,attr.root,&w,&h,&x,&y, &dum); + gravity = attr.win_gravity;*/ + + int screen = DefaultScreen( vjsdl->display ); + + if( manual_positioning ) { + int new_w,new_h,new_x=0,new_y=0; + int vid_w=0,vid_h=0; + int use_geom = 0; + int use_size = 0; + int offset_x=0,offset_y=0; + if( veejay_screen_geom ) + if( sscanf( veejay_screen_geom, "%dx%d+%dx%d",&new_w,&new_h,&new_x,&new_y) == 4 ) + use_geom = 1; + + if( veejay_screen_size ) + if( sscanf( veejay_screen_size,"%dx%d",&vid_w,&vid_h) == 2 ) + use_size = 1; + + if( veejay_screen_size && !use_size ) { + veejay_msg(VEEJAY_MSG_ERROR, + "Invalid syntax for VEEJAY_SCREEN_SIZE, use \"x\""); + veejay_msg(VEEJAY_MSG_ERROR, + " for example: VEEJAY_SCREEN_SIZE=1024x768"); + } + + if(!use_size) { + veejay_msg(VEEJAY_MSG_WARNING, + "Warning, will use %dx%d for Fullscreen mode", DisplayWidth( vjsdl->display,screen), + DisplayHeight( vjsdl->display,screen) ); + + } + if( veejay_screen_geom && !use_geom) { + veejay_msg(VEEJAY_MSG_ERROR, + "Invalid syntax for VEEJAY_SCREEN_GEOMETRY, use\"x+x\""); + veejay_msg(VEEJAY_MSG_ERROR, + " for example: VEEJAY_SCREEN_GEOMETRY=2624x1024+1600+0 for TwinView/One Big Desktop"); + veejay_msg(VEEJAY_MSG_ERROR, + " VEEJAY_SCREEN_GEOMETRY=0x0+0+0 for Single Screen Desktops"); + } + + + if( fs == 1 ) { + scaled_width = DisplayWidth( vjsdl->display,screen); + scaled_height= DisplayHeight( vjsdl->display,screen); + /* if( use_geom ) { + scaled_width = new_w; + scaled_height = new_h; + }*/ + } + if( use_geom ) { + offset_x = new_x; + offset_y = new_y; + veejay_msg(VEEJAY_MSG_DEBUG, "VEEJAY_SCREEN_GEOMETRY: %dx%d+%dx%d", new_w,new_h,new_x,new_y); + } + + if( use_size ) { + scaled_width = vid_w; + scaled_height = vid_h; + veejay_msg(VEEJAY_MSG_DEBUG, "VEEJAY_SCREEN_SIZE: %dx%d", vid_w,vid_h); + } + + veejay_msg(VEEJAY_MSG_INFO, "Size of video window: %dx%d", scaled_width,scaled_height); + veejay_msg(VEEJAY_MSG_INFO, "Position : %dx%d", new_x, new_y ); + veejay_msg(VEEJAY_MSG_INFO, "Display size : %dx%d", DisplayWidth(vjsdl->display,screen), + DisplayHeight(vjsdl->display,screen)); + + if( wminfo.subsystem == SDL_SYSWM_X11 ) + { + Window rootwin; + Window parentwin; + Window *children; + unsigned int children_count; + XQueryTree( wminfo.info.x11.display, + wminfo.info.x11.window, + &rootwin, + &parentwin, + &children, + &children_count ); + wminfo.info.x11.lock_func(); + XMoveWindow( wminfo.info.x11.display, parentwin, offset_x,offset_y ); + XResizeWindow( wminfo.info.x11.display, parentwin, scaled_width,scaled_height); + wminfo.info.x11.unlock_func(); + if(children) free(children); + } + vj_sdl_move( vjsdl, scaled_width,scaled_height,new_x,new_y ); + } + } + + SDL_WM_SetCaption(caption, NULL); + + if (!vj_sdl_unlock(vjsdl)) + return 0; + + + /* + we can draw something on the raw surface. + */ + + if(show) + { + SDL_UpdateRect(vjsdl->screen, 0, 0, vjsdl->rectangle.w, + vjsdl->rectangle.h); + } + + + vjsdl->fs = fs; + + SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL ); + + return 1; +} + +int vj_sdl_screen_w( vj_sdl *vjsdl ) +{ + return vjsdl->screen->w; +} +int vj_sdl_screen_h( vj_sdl *vjsdl ) +{ + return vjsdl->screen->h; +} + +void vj_sdl_grab(vj_sdl *vjsdl, int status) +{ + SDL_WM_GrabInput( (status==1? SDL_GRAB_ON : SDL_GRAB_OFF) ); + veejay_msg(VEEJAY_MSG_DEBUG, "%s", status == 1 ? "Released mouse focus": + "Grabbed mouse focus"); +} + + +void vj_sdl_show(vj_sdl *vjsdl) { + SDL_UpdateRect(vjsdl->screen,0,0,vjsdl->rectangle.w, vjsdl->rectangle.h); +} + +int vj_sdl_lock(vj_sdl * vjsdl) +{ + if (SDL_MUSTLOCK(vjsdl->screen)) { + if (SDL_LockSurface(vjsdl->screen) < 0) { + sprintf(vjsdl->last_error, "%s", SDL_GetError()); + return 0; + } + } + if (SDL_LockYUVOverlay(vjsdl->yuv_overlay) < 0) { + sprintf(vjsdl->last_error, "%s", SDL_GetError()); + return 0; + } + return 1; +} + +int vj_sdl_unlock(vj_sdl * vjsdl) +{ + if (SDL_MUSTLOCK(vjsdl->screen)) { + SDL_UnlockSurface(vjsdl->screen); + } + SDL_UnlockYUVOverlay(vjsdl->yuv_overlay); + return 1; +} + +uint8_t *vj_sdl_get_yuv_overlay(vj_sdl *vjsdl ) +{ + return vjsdl->yuv_overlay->pixels[0]; +} + +void vj_sdl_flip( vj_sdl *vjsdl ) +{ + SDL_DisplayYUVOverlay( vjsdl->yuv_overlay, &(vjsdl->rectangle)); +} + +int vj_sdl_update_yuv_overlay(vj_sdl * vjsdl, uint8_t ** yuv420) +{ + if (!vj_sdl_lock(vjsdl)) + return 0; +#ifdef STRICT_CHECKING + assert( yuv420[0] != NULL ); + assert( yuv420[1] != NULL ); + assert( yuv420[2] != NULL ); +#endif + VJFrame *src = yuv_yuv_template( yuv420[0],yuv420[1],yuv420[2],vjsdl->width,vjsdl->height, vjsdl->ffmpeg_pixfmt ); + VJFrame *dst = yuv_yuv_template( vjsdl->yuv_overlay->pixels[0],NULL,NULL,vjsdl->width,vjsdl->height,PIX_FMT_YUYV422); + + yuv_convert_and_scale_packed( vjsdl->scaler, src,dst ); + + /*if(vjsdl->pix_fmt == FMT_420 || vjsdl->pix_fmt == FMT_420F) + yuv420p_to_yuv422( yuv420, vjsdl->yuv_overlay->pixels[0],vjsdl->width,vjsdl->height); + else + yuv422_to_yuyv( yuv420, vjsdl->yuv_overlay->pixels[0], vjsdl->width,vjsdl->height); + */ + if (!vj_sdl_unlock(vjsdl)) + return 0; + + SDL_DisplayYUVOverlay(vjsdl->yuv_overlay, &(vjsdl->rectangle)); + + free(src); + free(dst); + + return 1; +} + +void vj_sdl_quit() +{ + SDL_Quit(); +} + +void vj_sdl_free(vj_sdl * vjsdl) +{ + if( vjsdl->yuv_overlay) + SDL_FreeYUVOverlay(vjsdl->yuv_overlay); + if( vjsdl->scaler ) + yuv_free_swscaler(vjsdl->scaler); + free(vjsdl); +// SDL_Quit(); +} +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-sdl.h b/branches/V-1.5.3/veejay-server/veejay/vj-sdl.h new file mode 100644 index 00000000..a4f2ead8 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-sdl.h @@ -0,0 +1,72 @@ +/* veejay - Linux VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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. + */ +#ifndef VJ_SDL_H +#define VJ_SDL_H + +#include +#ifdef HAVE_SDL +#include +#include +#include + +typedef struct vj_sdl_t { + SDL_Surface *screen; + SDL_Overlay *yuv_overlay; + SDL_Rect rectangle; + SDL_Event event; + uint32_t flags[2]; + int show_cursor; + int mouse_motion; + int use_keyboard; + int pix_format; + int width; + int height; + int sw_scale_width; + int sw_scale_height; + int frame_size; + char last_error[255]; + int custom_geo[2]; + int fs; + int pix_fmt; + void *display; + void *scaler; + int ffmpeg_pixfmt; +} vj_sdl; + +vj_sdl *vj_sdl_allocate(int width, int height, int pixel_format); +void vj_sdl_set_geometry(vj_sdl *sdl, int w, int h); +void vj_sdl_show(vj_sdl *vjsdl); +int vj_sdl_init(int ncpu, vj_sdl * vjsdl, int scaled_width, int scaled_height,const char *caption, int show, int fs); +int vj_sdl_lock(vj_sdl * vjsdl); +int vj_sdl_unlock(vj_sdl * vjsdl); +int vj_sdl_update_yuv_overlay(vj_sdl * vjsdl, uint8_t ** yuv420); +int vj_sdl_direct_yuv_overlay(vj_sdl * vjsdl, uint8_t * buffer, int buflen, + int dataformat); +void vj_sdl_free(vj_sdl * vjsdl); +void vj_sdl_quit(); +uint8_t *vj_sdl_get_yuv_overlay(vj_sdl *vjsdl ); + +void vj_sdl_resize( vj_sdl *vjsdl , int scaled_width, int scaled_height, int fs ); +int vj_sdl_screen_w( vj_sdl *vjsdl ); +int vj_sdl_screen_h( vj_sdl *vjsdl ); +void vj_sdl_flip( vj_sdl *vjsdl ); + + +#endif +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-viewport-xml.h b/branches/V-1.5.3/veejay-server/veejay/vj-viewport-xml.h new file mode 100644 index 00000000..edc6f011 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-viewport-xml.h @@ -0,0 +1,54 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ + +#ifndef VIEWPORTXML +#define VIEWPORTXML +typedef struct +{ + int saved_w; + int saved_h; + int reverse; + int grid_resolution; + int grid_color; + int frontback; + int x0,y0,w0,h0; + float x1; + float x2; + float x3; + float x4; + float y1; + float y2; + float y3; + float y4; + float scale; + int composite_mode; + int colormode; + int grid_mode; + int marker_size; + int initial_active; +} viewport_config_t; + +void viewport_save_xml(xmlNodePtr parent,void *vv); +void *viewport_load_xml(xmlDocPtr doc, xmlNodePtr cur, void *vv ); +extern void composite_add_to_config( void *compiz, void *vc, int which_vp ); +extern void *composite_load_config( void *compiz, void *vc, int *result ); + +void *composite_get_config(void *compiz, int which_vp ); +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-viewport.c b/branches/V-1.5.3/veejay-server/veejay/vj-viewport.c new file mode 100644 index 00000000..ce46f8a5 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-viewport.c @@ -0,0 +1,3562 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + * + * Viewport with Perspective Transform Estimation for Veejay + * + * Resources: + * Gimp 1.0,2.0 (Perspective transformation (C) Spencer Kimball & Peter Mattis) + * Cinelerra (Motion plugin, no author in any file present. GPL2). + * Xine (bresenham line drawing routine) + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define X0 0 +#define Y0 1 +#define X1 2 +#define Y1 3 +#define X2 4 +#define Y2 5 +#define X3 6 +#define Y3 7 +#ifndef MIN +#define MIN(a,b) ( (a)>(b) ? (b) : (a) ) +#endif +#ifndef MAX +#define MAX(a,b) ( (a)>(b) ? (a) : (b) ) +#endif + +#define RUP8(num)(((num)+8)&~8) + +#define clamp1(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x)))) +#define distance1(x1,y1,x2,y2) ( sqrt( (x1 - x2) * (x1 - x2) + ( y1 - y2 ) * (y1 -y2 ) ) ) + +#define round1(x) ( (int32_t)( (x>0) ? (x) + 0.5 : (x) - 0.5 )) +#define min4(a,b,c,d) MIN(MIN(MIN(a,b),c),d) +#define max4(a,b,c,d) MAX(MAX(MAX(a,b),c),d) + +#undef _PREFETCH +#undef _PREFETCHW +#ifdef HAVE_ASM_DNOW +#define _PREFETCH "prefetch" +#define _PREFETCHW "prefetchw" +#elif defined ( HAVE_ASM_MMX2 ) +#define _PREFETCH "prefetchnta" +#define _PREFETCHW "prefetcht0" +#else +#define _PREFETCH "/nop" +#define _PREFETCHW "/nop" +#endif + +#define GRID_STEP 1 +#define GRID_START 44 +typedef struct +{ + float m[4][4]; +} matrix_t; + +typedef struct +{ + void *scaler; + uint8_t *buf[3]; + float scale; + float sx; + float sy; + int sw; + int sh; +} ui_t; + +typedef struct +{ + int x; + int y; +} grid_t; + + +typedef struct +{ + int32_t x,y; + int32_t h,w; + int32_t x0,y0,w0,h0; + float points[9]; + int users[4]; + float usermouse[6]; + int userm; + int user; + int save; + int user_ui; + int user_reverse; + int user_mode; + int grid_resolution; + int grid_width; + int grid_height; + int renew; + int disable; + int snap_marker; + int marker_size; + float x1; + float x2; + float x3; + float x4; + float y1; + float y2; + float y3; + float y4; + int32_t *map; + uint8_t *img[4]; + matrix_t *M; + matrix_t *m; + matrix_t *T; + char *help; + uint8_t grid_val; + int parameters[8]; + char *homedir; + int32_t tx1,tx2,ty1,ty2; + int32_t ttx1,ttx2,tty1,tty2; + int mode; + int32_t *buf; + void *sender; + uint32_t seq_id; + ui_t *ui; + int saved_w; + int saved_h; + grid_t *grid; + int grid_mode; + int initial_active; +} viewport_t; + + +static float msx(viewport_t *v, float x); +static float msy(viewport_t *v, float y); + +static float vsx(viewport_t *v, float x); +static float vsy(viewport_t *v, float y); + +static void viewport_draw_col( void *data, uint8_t *img, uint8_t *u, uint8_t *v ); +static void viewport_draw( void *data, uint8_t *img ); +static inline int grab_pixel( uint8_t *plane, int x, int y, int w ); +static int viewport_update_perspective( viewport_t *v, float *values ); +static void viewport_process( viewport_t *p ); +static int viewport_configure( + viewport_t *v, + float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4, + int32_t x0, int32_t y0, + int32_t w0, int32_t h0, + int32_t w, int32_t h, + uint32_t reverse, + uint8_t color, + int size); + +static matrix_t *viewport_transform(float x1,float y1,float x2,float y2,float *coord ); +static inline void point_map( matrix_t *M, float x, float y, float *nx, float *ny); +static matrix_t * viewport_invert_matrix( matrix_t *M, matrix_t *D ); +static matrix_t *viewport_adjoint_matrix(matrix_t *M); +static double viewport_matrix_determinant( matrix_t *M ); +static matrix_t *viewport_multiply_matrix( matrix_t *A, matrix_t *B ); +static void viewport_copy_from( matrix_t *A, matrix_t *B ); +static void viewport_scale_matrix( matrix_t *M, float sx, float sy ); +static void viewport_translate_matrix( matrix_t *M, float x, float y ); +static matrix_t *viewport_identity_matrix(void); +static matrix_t *viewport_matrix(void); +static void viewport_find_transform( float *coord, matrix_t *M ); +static void viewport_print_matrix( matrix_t *M ); +void viewport_line (uint8_t *plane,int x1, int y1, int x2, int y2, int w, int h, uint8_t col); +static void draw_point( uint8_t *plane, int x, int y, int w, int h, int size, int col ); +static viewport_config_t *viewport_load_settings( const char *dir, int mode ); +static void viewport_save_settings( viewport_t *v , int frontback); +static void viewport_prepare_process( viewport_t *v ); +static void viewport_compute_grid( viewport_t *v ); + +#ifdef HAVE_X86CPU +static inline int int_max( int a, int b ) +{ + b = a-b; + a -= b & (b>>31); + return a; +} +static inline int int_min( int a, int b ) +{ + b = b- a; + a += b & (b>>31); // if(a < b) then a = b + return a; +} +#else +static inline int int_max(int a, int b ) +{ + return MAX(a,b); +} +static inline int int_min(int a, int b ) +{ + return MIN(a,b); +} +#endif + +static void viewport_print_matrix( matrix_t *M ) +{ + veejay_msg(0, "|%f\t%f\t%f", M->m[0][0], M->m[0][1], M->m[0][2] ); + veejay_msg(0, "|%f\t%f\t%f", M->m[1][0], M->m[1][1], M->m[1][2] ); + veejay_msg(0, "|%f\t%f\t%f", M->m[2][0], M->m[2][1], M->m[2][2] ); +} +/* + * Bresenham line implementation from Xine + */ + +void viewport_line (uint8_t *plane, + int x1, int y1, int x2, int y2, int w, int h, uint8_t col) { + + uint8_t *c; + int dx, dy, t, inc, d, inc1, inc2; + int swap_x = 0; + int swap_y = 0; + + if( x1 < 0 ) x1 = 0; else if (x1 > w ) x1 = w; + if( y1 < 0 ) y1 = 0; else if (y1 > h ) y1 = h; + if( x2 < 0 ) x2 = 0; else if (x2 > w ) x2 = w; + if( y2 < 0 ) y2 = 0; else if (y2 > h ) y2 = h; + + /* sort line */ + if (x2 < x1) { + t = x1; + x1 = x2; + x2 = t; + swap_x = 1; + } + if (y2 < y1) { + t = y1; + y1 = y2; + y2 = t; + swap_y = 1; + } + + /* clip line */ + if (x1 < 0) { + y1 = y1 + (y2-y1) * -x1 / (x2-x1); + x1 = 0; + } + if (y1 < 0) { + x1 = x1 + (x2-x1) * -y1 / (y2-y1); + y1 = 0; + } + if (x2 > w) { + y2 = y1 + (y2-y1) * (w-x1) / (x2-x1); + x2 = w; + } + if (y2 > h) { + x2 = x1 + (x2-x1) * (h-y1) / (y2-y1); + y2 = h; + } + + if (x1 >= w || y1 >= h) + return; + + dx = x2 - x1; + dy = y2 - y1; + + /* unsort line */ + if (swap_x) { + t = x1; + x1 = x2; + x2 = t; + } + if (swap_y) { + t = y1; + y1 = y2; + y2 = t; + } + + if( dx>=dy ) { + if( x1>x2 ) + { + t = x2; x2 = x1; x1 = t; + t = y2; y2 = y1; y1 = t; + } + + if( y2 > y1 ) inc = 1; else inc = -1; + + inc1 = 2*dy; + d = inc1 - dx; + inc2 = 2*(dy-dx); + + c = plane + y1 * w + x1; + + while(x1y2 ) { + t = x2; x2 = x1; x1 = t; + t = y2; y2 = y1; y1 = t; + } + + if( x2 > x1 ) inc = 1; else inc = -1; + + inc1 = 2*dx; + d = inc1-dy; + inc2 = 2*(dx-dy); + + c = plane + y1 * w + x1; + + while(y1 w ) x1 = w; + if( y1 < 0 ) y1 = 0; else if ( y1 > h ) y1 = h; + if( x2 < 0 ) x2 = 0; else if ( x2 > w ) x2 = w; + if( y2 < 0 ) y2 = 0; else if ( y2 > h ) y2 = h; + + unsigned int i,j; + for( i = y; i < y2; i ++ ) + { + for( j = x1; j < x2 ; j ++ ) + plane[ y * w + x ] = col; + } +} +static void draw_point( uint8_t *plane, int x, int y, int w, int h, int size, int col ) +{ + int x1 = x - size *2; + int y1 = y - size*2; + int x2 = x + size*2; + int y2 = y + size*2; + + if( x1 < 0 ) x1 = 0; else if ( x1 > w ) x1 = w; + if( y1 < 0 ) y1 = 0; else if ( y1 > h ) y1 = h; + if( x2 < 0 ) x2 = 0; else if ( x2 > w ) x2 = w; + if( y2 < 0 ) y2 = 0; else if ( y2 > h ) y2 = h; + + unsigned int i,j; + for( i = y1; i < y2; i ++ ) + { + for( j = x1; j < x2 ; j ++ ) + plane[ i * w + j ] = col; + } +} + +static void viewport_find_transform( float *coord, matrix_t *M ) +{ + double dx1,dx2,dx3,dy1,dy2,dy3; + double det1,det2; + + dx1 = coord[X1] - coord[X3]; + dx2 = coord[X2] - coord[X3]; + dx3 = coord[X0] - coord[X1] + coord[X3] - coord[X2]; + + dy1 = coord[Y1] - coord[Y3]; + dy2 = coord[Y2] - coord[Y3]; + dy3 = coord[Y0] - coord[Y1] + coord[Y3] - coord[Y2]; + + /* is the mapping affine? */ + if( ((dx3 == 0.0) && (dy3==0.0)) ) + { + M->m[0][0] = coord[X1] - coord[X0]; + M->m[0][1] = coord[X3] - coord[X1]; + M->m[0][2] = coord[X0]; + + M->m[1][0] = coord[Y1] - coord[Y0]; + M->m[1][1] = coord[Y3] - coord[Y1]; + M->m[1][2] = coord[Y0]; + + M->m[2][0] = 0.0; + M->m[2][1] = 0.0; + } + else + { + det1 = dx3 * dy2 - dy3 * dx2; + det2 = dx1 * dy2 - dy1 * dx2; + M->m[2][0] = det1/det2; + + det1 = dx1 * dy3 - dy1 * dx3; + det2 = dx1 * dy2 - dy1 * dx2; + M->m[2][1] = det1/det2; + + M->m[0][0] = coord[X1] - coord[X0] + M->m[2][0] * coord[X1]; + M->m[0][1] = coord[X2] - coord[X0] + M->m[2][1] * coord[X2]; + M->m[0][2] = coord[X0]; + + M->m[1][0] = coord[Y1] - coord[Y0] + M->m[2][0] * coord[Y1]; + M->m[1][1] = coord[Y2] - coord[Y0] + M->m[2][1] * coord[Y2]; + M->m[1][2] = coord[Y0]; + } + + M->m[2][2] = 1.0; +} + +void viewport_set_ui(void *vv, int i) +{ + viewport_t *v = (viewport_t*) vv; + v->user_ui = i; +} + + +char *viewport_get_my_help(void *vv) +{ + viewport_t *v = (viewport_t*) vv; + if(!v->user_ui ) + return NULL; + + char reverse_mode[32]; + veejay_memset(reverse_mode,0,sizeof(reverse_mode)); + sprintf(reverse_mode, "%s", ( v->user_reverse ? "Forward" : "Reverse" ) ); + + char scroll_mode[64]; + + switch(v->grid_mode) { + case 0: + snprintf(scroll_mode,sizeof(scroll_mode), + "CTRL + Mousewheel: Marker %2dx%2d up=Grid down=Dots",v->marker_size,v->marker_size); + break; + case 1: + snprintf(scroll_mode,sizeof(scroll_mode), + "CTRL + Mousewheel: Dots %2dx%2d up=Marker down=Grid",v->grid_resolution,v->grid_resolution); + break; + case 2: + snprintf(scroll_mode,sizeof(scroll_mode), + "CTRL + Mousewheel: Grid %2dx%2d up=Grid down=Marker",v->grid_resolution,v->grid_resolution); + break; + } + + + char tmp[1500]; + char startup_mode[16]; + sprintf(startup_mode, "%s", (v->initial_active==1 ? "Active" :"Inactive" )); + int gw = v->grid_width; + int gh = v->grid_height; + sprintf(tmp, "Interactive Input/Projection calibration\nMouse Left: Set point\nCTRL + Cursor Keys: Finetune point\nMouse Left + RSHIFT: Set projection quad \nMouse Right: %s\nMouse Middle: Setup/Run\nMouse Middle + LSHIFT: Line Color\nCTRL + h:Hide/Show this Help\nCTRL + p:Focus projection/secundary input\nCTRL + i: Transform secundary input\nCTRL + v: Transform sec. input in grayscale/color \nCTRL + a: %s on startup.\nCTRL + s: Exit this screen.\n%s\n\n", + reverse_mode, + startup_mode, + scroll_mode + ); + + + return strdup( tmp ); +} +char *viewport_get_my_status(void *vv) +{ + viewport_t *v = (viewport_t*) vv; + if(!v->user_ui ) + return NULL; + + float x = v->usermouse[2] / ( v->w / 100.0f ); + float y = v->usermouse[3] / ( v->h / 100.0f ); + + float tx = vsx(v,v->usermouse[4]); + float ty = vsy(v,v->usermouse[5]); + + char status[1024]; + snprintf(status,1024, "Projection Quad: %dx%d + %dx%d\nPoints: 1=%2.2fx%2.2f 2=%2.2fx%2.2f 3=%2.2fx%2.2f 4=%2.2fx%2.2f\nCurrent Position: %2.1fx%2.1f\n", + v->x0,v->y0, + v->w0,v->h0, + v->x1,v->y1, + v->x2,v->y2, + v->x3,v->y3, + v->x4,v->y4, + tx,ty + ); + + return strdup( status ); +} + + +static matrix_t *viewport_matrix(void) +{ + matrix_t *M = (matrix_t*) vj_malloc(sizeof(matrix_t)); + uint32_t i,j; + for( i = 0;i < 3 ; i ++ ) + { + for( j = 0; j < 3 ; j++ ) + M->m[i][j] = 0.0; + } + return M; +} + +static matrix_t *viewport_identity_matrix(void) +{ + matrix_t *M = viewport_matrix(); + M->m[0][0] = 1.0; + M->m[1][1] = 1.0; + M->m[2][2] = 1.0; + return M; +} + +static void viewport_translate_matrix( matrix_t *M, float x, float y ) +{ + float g = M->m[2][0]; + float h = M->m[2][1]; + float i = M->m[2][2]; + + M->m[0][0] += x * g; + M->m[0][1] += x * h; + M->m[0][2] += x * i; + + M->m[1][0] += y * g; + M->m[1][1] += y * h; + M->m[1][2] += y * i; +} + +static void viewport_scale_matrix( matrix_t *M, float sx, float sy ) +{ + M->m[0][0] *= sx; + M->m[0][1] *= sx; + M->m[0][2] *= sx; + + M->m[1][0] *= sy; + M->m[1][1] *= sy; + M->m[1][2] *= sy; +} + +static void viewport_copy_from( matrix_t *A, matrix_t *B ) +{ + uint32_t i,j; + for( i =0 ; i < 3; i ++ ) + for( j = 0; j < 3 ; j ++ ) + A->m[i][j] = B->m[i][j]; +} + +static matrix_t *viewport_multiply_matrix( matrix_t *A, matrix_t *B ) +{ + matrix_t *R = viewport_matrix(); + + R->m[0][0] = A->m[0][0] * B->m[0][0] + A->m[0][1] * B->m[1][0] + A->m[0][2] * B->m[2][0]; + R->m[0][1] = A->m[0][0] * B->m[0][1] + A->m[0][1] * B->m[1][1] + A->m[0][2] * B->m[2][1]; + R->m[0][2] = A->m[0][0] * B->m[0][2] + A->m[0][1] * B->m[1][2] + A->m[0][2] * B->m[2][2]; + + R->m[1][0] = A->m[1][0] * B->m[0][0] + A->m[1][1] * B->m[1][0] + A->m[1][2] * B->m[2][0]; + R->m[1][1] = A->m[1][0] * B->m[0][1] + A->m[1][1] * B->m[1][1] + A->m[1][2] * B->m[2][1]; + R->m[1][2] = A->m[1][0] * B->m[0][2] + A->m[1][1] * B->m[1][2] + A->m[1][2] * B->m[2][2]; + + R->m[2][0] = A->m[2][0] * B->m[0][0] + A->m[2][1] * B->m[0][1] + A->m[2][2] * B->m[2][0]; + R->m[2][1] = A->m[2][0] * B->m[0][1] + A->m[2][1] * B->m[1][1] + A->m[2][2] * B->m[2][1]; + R->m[2][2] = A->m[2][0] * B->m[0][2] + A->m[2][1] * B->m[1][2] + A->m[2][2] * B->m[2][2]; + + + return R; +} + +static double viewport_matrix_determinant( matrix_t *M ) +{ + double D = M->m[0][0] * M->m[1][1] * M->m[2][2] + + M->m[0][1] * M->m[1][2] * M->m[2][0] + + M->m[2][0] * M->m[1][1] * M->m[0][2] - + M->m[1][0] * M->m[0][1] * M->m[2][2] - + M->m[2][1] * M->m[1][2] * M->m[0][0]; + + return D; +} + +static matrix_t *viewport_adjoint_matrix(matrix_t *M) +{ + matrix_t *A = viewport_matrix(); + A->m[0][0] = M->m[0][0]; + A->m[0][1] = -M->m[0][1]; + A->m[0][2] = M->m[0][2]; + A->m[1][0] = -M->m[1][0]; + A->m[1][1] = M->m[1][1]; + A->m[1][2] = -M->m[1][2]; + A->m[2][0] = M->m[2][0]; + A->m[2][1] = -M->m[2][1]; + A->m[2][2] = M->m[2][2]; + return A; +} + +static matrix_t * viewport_invert_matrix( matrix_t *M, matrix_t *D ) +{ + double det = viewport_matrix_determinant( M ); + if( det == 0.0 ) + { + veejay_msg(0, "det = %f, inverse of matrix not possible"); + return NULL; + } + det = 1.0 / det; + + D->m[0][0] = (M->m[1][1] * M->m[2][2] - M->m[1][2] * M->m[2][1] ) * det; + D->m[1][0] = (M->m[1][0] * M->m[2][2] - M->m[1][2] * M->m[2][0] ) * det; + D->m[2][0] = (M->m[1][0] * M->m[2][1] - M->m[1][1] * M->m[2][0] ) * det; + D->m[0][1] = (M->m[0][1] * M->m[2][2] - M->m[0][2] * M->m[2][1] ) * det; + D->m[1][1] = (M->m[0][0] * M->m[2][2] - M->m[0][2] * M->m[2][0] ) * det; + D->m[2][1] = (M->m[0][0] * M->m[2][1] - M->m[0][1] * M->m[2][0] ) * det; + D->m[0][2] = (M->m[0][1] * M->m[1][2] - M->m[0][2] * M->m[1][1] ) * det; + D->m[1][2] = (M->m[0][0] * M->m[1][2] - M->m[0][2] * M->m[1][0] ) * det; + D->m[2][2] = (M->m[0][0] * M->m[1][1] - M->m[0][1] * M->m[1][0] ) * det; + + matrix_t *A = viewport_adjoint_matrix( D ); + + return A; +} + +static inline void point_map( matrix_t *M, float x, float y, float *nx, float *ny) +{ + float w = M->m[2][0] * x + M->m[2][1] * y + M->m[2][2]; + + if( w == 0.0 ) + w = 1.0; + else + w = 1.0 / w; + + *nx = (M->m[0][0] * x + M->m[0][1] * y + M->m[0][2] ) * w; + *ny = (M->m[1][0] * x + M->m[1][1] * y + M->m[1][2] ) * w; + +} + +static inline void point_map_int( matrix_t *M, float x, float y, int *nx, int *ny) +{ + float w = M->m[2][0] * x + M->m[2][1] * y + M->m[2][2]; + + if( w == 0.0 ) + w = 1.0; + else + w = 1.0 / w; + + *nx = ceilf( (M->m[0][0] * x + M->m[0][1] * y + M->m[0][2] ) * w); + *ny = ceilf( (M->m[1][0] * x + M->m[1][1] * y + M->m[1][2] ) * w); + +} + + + + +static matrix_t *viewport_transform( + float x1, + float y1, + float x2, + float y2, + float *coord ) +{ + float sx=1.0,sy=1.0; + + if( (x2-x1) > 0.0 ) + sx = 1.0 / (x2-x1); + if( (y2-y1) > 0.0 ) + sy = 1.0 / (y2-y1); + + matrix_t *H = viewport_matrix(); + viewport_find_transform( coord, H ); + + matrix_t *I = viewport_identity_matrix(); + viewport_translate_matrix( I, -x1, -y1 ); + viewport_scale_matrix( I, sx,sy ); + matrix_t *R = viewport_multiply_matrix( H,I ); + free(I); + free(H); + return R; +} + + +/* +void viewport_get_projection_coords( + void *data, int32_t *x0, int32_t *y0, int32_t *w0, int32_t *h0 ) +{ + viewport_t *v = (viewport_t*) data; + + *x0 = v->x0; + *y0 = v->y0; + *w0 = v->w0; + *h0 = v->h0; +} + +float *viewport_get_projection_points( void *data ) +{ + viewport_t *v = (viewport_t*) data; + float *res = vj_malloc( sizeof(float) * 8 ); + + res[0] = v->x0; + res[1] = v->y0; + res[2] = v->x0 + v->w0; + res[3] = v->y0; + res[4] = v->x0; + res[5] = v->y0 + v->h0; + res[6] = v->x0 + v->w0; + res[7] = v->y0 + v->h0; + + return res; +} + +void viewport_set_projection( void *data, float *res ) +{ + viewport_t *v = (viewport_t*) data; + v->x1 = res[0]; + v->y1 = res[1]; + v->x2 = res[2]; + v->y2 = res[3]; + v->x3 = res[4]; + v->y3 = res[5]; + v->x4 = res[6]; + v->y4 = res[7]; + +}*/ +static float msy(viewport_t *v, float y) +{ + if( v->ui->scale == 1.0f ) { + return y; + } + ui_t *u = v->ui; + int cx = v->w / 2; + int cy = v->h / 2; + int dx = cx - ( u->sw / 2 ); + int dy = cy - ( u->sh / 2 ); + + float a = (float) dy / ( v->h / 100.0f ); + float s = (float) v->h / (float) v->ui->sh; +#ifdef STRICT_CHECKING + assert( (v->w > 0) ); + assert( (v->h > 0 )); + assert( (v->ui->sw > 0)); + assert( (v->ui->sh > 0 )); +#endif + + return (y/s) + a; +} + +static float msx(viewport_t *v, float x) +{ + if( v->ui->scale == 1.0f ) { + return x; + } + ui_t *u = v->ui; + int cx = v->w / 2; + int cy = v->h / 2; + int dx = cx - ( u->sw / 2 ); + int dy = cy - ( u->sh / 2 ); + + float a = (float) dx / ( v->w / 100.0f ); + float s = (float) v->w / (float) v->ui->sw; +#ifdef STRICT_CHECKING + assert( (v->w > 0) ); + assert( (v->h > 0 )); + assert( (v->ui->sw > 0)); + assert( (v->ui->sh > 0 )); +#endif + + return (x/s) + a; +} + +static float vsx(viewport_t *v, float x) +{ + if( v->ui->scale == 1.0f ) { + return x; + } + ui_t *u = v->ui; + int cx = v->w / 2; + int cy = v->h / 2; + int dx = cx - ( u->sw / 2 ); + int dy = cy - ( u->sh / 2 ); + + float a = (float) dx / ( v->w / 100.0f ); + float s = (float) v->w / (float) v->ui->sw; +#ifdef STRICT_CHECKING + assert( (v->w > 0) ); + assert( (v->h > 0 )); + assert( (v->ui->sw > 0)); + assert( (v->ui->sh > 0 )); +#endif + return (x-a)*s; +} +static float vsy(viewport_t *v, float x) +{ + if( v->ui->scale == 1.0f ) + return x; + + ui_t *u = v->ui; + int cx = v->w / 2; + int cy = v->h / 2; + int dx = cx - ( u->sw / 2 ); + int dy = cy - ( u->sh / 2 ); + + float a = (float) dy / ( v->h / 100.0f ); + + float s = (float) v->h / (float) v->ui->sh; +#ifdef STRICT_CHECKING + assert( (v->w > 0) ); + assert( (v->h > 0 )); + assert( (v->ui->sw > 0)); + assert( (v->ui->sh > 0 )); +#endif + return (x-a)*s; +} + + + +static int viewport_configure( + viewport_t *v, + float x1, float y1, /* output */ + float x2, float y2, + float x3, float y3, + float x4, float y4, + int32_t x0, int32_t y0, /* input */ + int32_t w0, int32_t h0, + int32_t wid, int32_t hei, + uint32_t reverse, + uint8_t color, + int grid_resolution) +{ + int w = wid, h = hei; + if( grid_resolution <= 8 ) + grid_resolution = GRID_START; + float rat = (h/(float)w); + + v->grid_width = grid_resolution; + v->grid_height = grid_resolution * rat; + float scale = 1.0f;//v->ui->scale; + v->points[X0] = (float) x1 * (float) w / 100.0; + v->points[Y0] = (float) y1 * (float) h / 100.0; + + v->points[X1] = (float) x2 * (float) w / 100.0; + v->points[Y1] = (float) y2 * (float) h / 100.0; + + v->points[X2] = (float) x3 * (float) w / 100.0; + v->points[Y2] = (float) y3 * (float) h / 100.0; + + v->points[X3] = (float) x4 * (float) w / 100.0; + v->points[Y3] = (float) y4 * (float) h / 100.0; + + + v->w = wid; /* image plane boundaries */ + v->x = 0; + v->h = hei; + v->y = 0; + + v->x0 = x0; + v->y0 = y0; + v->w0 = w0; + v->h0 = h0; + + v->grid_val = color; + + v->x1 = x1; + v->x2 = x2; + v->x3 = x3; + v->x4 = x4; + v->y1 = y1; + v->y2 = y2; + v->y3 = y3; + v->y4 = y4; + v->user_reverse = reverse; + + float tmp = v->points[X3]; + v->points[X3] = v->points[X2]; + v->points[X2] = tmp; + tmp = v->points[Y3]; + v->points[Y3] = v->points[Y2]; + v->points[Y2] = tmp; + + matrix_t *m = viewport_transform( x0, y0, x0 + w0, y0 + h0, v->points ); + + if(v->m) { + free(v->m); + v->m = NULL; + } + if(v->M) { + free(v->M); + v->M = NULL; + } + + if ( reverse ) + { + v->m = viewport_matrix(); + viewport_copy_from( v->m, m ); + matrix_t *im = viewport_matrix(); + v->M = viewport_invert_matrix( v->m, im ); + if(!v->M) + { + free(m); + free(im); + free(v->m); + v->m = NULL; + return 0; + } + free(im); + free(m); + viewport_prepare_process( v ); + return 1; + + } + else + { + matrix_t *tmp = viewport_matrix(); + matrix_t *im = viewport_invert_matrix( m, tmp ); + free(tmp); + if(!im) + { + free(m); + return 0; + } + v->M = m; + v->m = im; + viewport_prepare_process( v ); + return 1; + } + + return 0; +} + +static void viewport_process( viewport_t *p ) +{ + const int32_t w = p->w; + const int32_t h = p->h; + const int32_t X = p->x0; + const int32_t Y = p->y0; + const int32_t W0 = p->w0; + const int32_t H0 = p->h0; + + matrix_t *M = p->M; + matrix_t *m = p->m; + + const int len = w * h; + const float xinc = m->m[0][0]; + const float yinc = m->m[1][0]; + const float winc = m->m[2][0]; + + const int32_t tx1 = p->ttx1; + const int32_t tx2 = p->ttx2; + const int32_t ty1 = p->tty1; + const int32_t ty2 = p->tty2; + + const float m01 = m->m[0][1]; + const float m11 = m->m[1][1]; + const float m21 = m->m[2][1]; + const float m02 = m->m[0][2]; + const float m12 = m->m[1][2]; + const float m22 = m->m[2][2]; + + float tx,ty,tw; + float ttx,tty; + int32_t x,y; + int32_t itx,ity; + + int32_t *map = p->map; + register int32_t pos = 0; + + for( y = ty1; y < ty2; y ++ ) + { + tx = xinc * ( tx1 + 0.5 ) + m01 * ( y + 0.5) + m02; + ty = yinc * ( tx1 + 0.5 ) + m11 * ( y + 0.5) + m12; + tw = winc * ( tx1 + 0.5 ) + m21 * ( y + 0.5) + m22; + + for( x = tx1; x < tx2 ; x ++ ) + { + if( tw == 0.0 ) { + ttx = 0.0; + tty = 0.0; + } else if ( tw != 1.0 ) { + ttx = tx / tw; + tty = ty / tw; + } else { + ttx = tx; + tty = ty; + } + + itx = (int32_t) ttx; + ity = (int32_t) tty; + + if( itx >= X && itx <= w && ity >= Y && ity < h ) + map[ (y * w + x) ] = (ity * w + itx); + else + map[ (y * w + x) ] = (len+1); + + tx += xinc; + ty += yinc; + tw += winc; + } + } + + +} + +static void viewport_prepare_process( viewport_t *v ) +{ + const int32_t w = v->w; + const int32_t h = v->h; + + const int32_t X = v->x0; + const int32_t Y = v->y0; + + float dx1,dx2,dx3,dx4,dy1,dy2,dy3,dy4; + matrix_t *M = v->M; + + point_map( M, v->x, v->y, &dx1, &dy1); + point_map( M, v->x + v->w, v->y, &dx2, &dy2 ); + point_map( M, v->x, v->y + v->h, &dx4, &dy4 ); + point_map( M, v->x + v->w, v->y + v->h, &dx3, &dy3 ); + + v->tx1 = round1( min4( dx1, dx2, dx3, dx4 ) ); + v->ty1 = round1( min4( dy1, dy2, dy3, dy4 ) ); + v->tx2 = round1( max4( dx1, dx2, dx3, dx4 ) ); + v->ty2 = round1( max4( dy1, dy2, dy3, dy4 ) ); + + clamp1( v->ty1 , Y, Y + v->h0 ); + clamp1( v->ty2 ,Y,Y + v->h0 ); + clamp1( v->tx1, X, X + v->w0 ); + clamp1( v->tx2, X, X + v->w0 ); + + v->ttx2 = v->tx2; + v->tty2 = v->ty2; + v->ttx1 = v->tx1; + v->tty1 = v->ty1; + + clamp1( v->ttx2,0, v->w ); + clamp1( v->tty2,0, v->h ); + clamp1( v->ttx1,0, v->w ); + clamp1( v->tty1,0, v->h ); + +} + + +void viewport_process_dynamic_map( void *data, uint8_t *in[3], uint8_t *out[3], uint32_t *map, int feather ) +{ + viewport_t *v = (viewport_t*) data; + const int32_t w = v->w; + const int32_t h = v->h; + const int32_t X = v->x0; + const int32_t Y = v->y0; + const int32_t W0 = v->w0; + const int32_t H0 = v->h0; + matrix_t *M = v->M; + matrix_t *m = v->m; + + const float xinc = m->m[0][0]; + const float yinc = m->m[1][0]; + const float winc = m->m[2][0]; + const int32_t tx1 = v->ttx1; + const int32_t tx2 = v->ttx2; + const int32_t ty1 = v->tty1; + const int32_t ty2 = v->tty2; + + const float m01 = m->m[0][1]; + const float m11 = m->m[1][1]; + const float m21 = m->m[2][1]; + const float m02 = m->m[0][2]; + const float m12 = m->m[1][2]; + const float m22 = m->m[2][2]; + + const uint8_t *inY = in[0]; + const uint8_t *inU = in[1]; + const uint8_t *inV = in[2]; + + uint8_t *outY = out[0]; + uint8_t *outU = out[1]; + uint8_t *outV = out[2]; + + float tx,ty,tw; + float ttx,tty; + int32_t x,y; + int32_t itx,ity; +/* +#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE ) + + fast_memset_dirty( outY , 0, ty1 * v->w ); + fast_memset_dirty( outU , 128, ty1 * v->w ); + fast_memset_dirty( outV , 128, ty1 * v->w ); + fast_memset_finish(); +#else + + for( y =0 ; y < ty1; y ++ ) + { + for( x = 0 ; x < w ; x ++ ) + { + outY[ (y * w +x ) ] = 0; + outU[ (y * w +x ) ] = 128; + outV[ (y * w +x ) ] = 128; + } + } +#endif +*/ + for( y = ty1; y < ty2; y ++ ) + { + tx = xinc * ( tx1 + 0.5 ) + m01 * ( y + 0.5) + m02; + ty = yinc * ( tx1 + 0.5 ) + m11 * ( y + 0.5) + m12; + tw = winc * ( tx1 + 0.5 ) + m21 * ( y + 0.5) + m22; + /* for( x = 0; x < tx1; x ++ ) + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + }*/ + + for( x = tx1; x < tx2 ; x ++ ) + { + if( tw == 0.0 ) { + ttx = 0.0; + tty = 0.0; + } else if ( tw != 1.0 ) { + ttx = tx / tw; + tty = ty / tw; + } else { + ttx = tx; + tty = ty; + } + + itx = (int32_t) ttx; + ity = (int32_t) tty; + + if( itx >= X && itx <= w && ity >= Y && ity < h + && + map[( y * w + x)] >= feather ) + { + outY[(y*w+x)] = inY[(ity*w+itx)]; + outU[(y*w+x)] = inU[(ity*w+itx)]; + outV[(y*w+x)] = inV[(ity*w+itx)]; + } + /*else + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + + }*/ + + tx += xinc; + ty += yinc; + tw += winc; + } + /* + for( x = tx2; x < w; x ++ ) + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + }*/ + + } +/* +#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE ) + int rest = h - ty2; + fast_memset_dirty( outY + (ty2 * v->w),0, rest * v->w ); + fast_memset_dirty( outU + (ty2 * v->w), 128, rest * v->w ); + fast_memset_dirty( outV + (ty2 * v->w), 128, rest * v->w ); + fast_memset_finish(); +#else + for( y = ty2 ; y < h; y ++ ) + { + for( x = 0; x < w; x ++ ) + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + } + } +#endif +*/ + +} +void viewport_process_dynamic( void *data, uint8_t *in[3], uint8_t *out[3] ) +{ + viewport_t *v = (viewport_t*) data; + const int32_t w = v->w; + const int32_t h = v->h; + const int32_t X = v->x0; + const int32_t Y = v->y0; + matrix_t *M = v->M; + matrix_t *m = v->m; + + const float xinc = m->m[0][0]; + const float yinc = m->m[1][0]; + const float winc = m->m[2][0]; + const int32_t tx1 = v->ttx1; + const int32_t tx2 = v->ttx2; + const int32_t ty1 = v->tty1; + const int32_t ty2 = v->tty2; + + const float m01 = m->m[0][1]; + const float m11 = m->m[1][1]; + const float m21 = m->m[2][1]; + const float m02 = m->m[0][2]; + const float m12 = m->m[1][2]; + const float m22 = m->m[2][2]; + + const uint8_t *inY = in[0]; + const uint8_t *inU = in[1]; + const uint8_t *inV = in[2]; + + uint8_t *outY = out[0]; + uint8_t *outU = out[1]; + uint8_t *outV = out[2]; + + float tx,ty,tw; + float ttx,tty; + int32_t x,y; + int32_t itx,ity; + +#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE ) + + fast_memset_dirty( outY , 0, ty1 * v->w ); + fast_memset_dirty( outU , 128, ty1 * v->w ); + fast_memset_dirty( outV , 128, ty1 * v->w ); + fast_memset_finish(); +#else + + for( y =0 ; y < ty1; y ++ ) + { + for( x = 0 ; x < w ; x ++ ) + { + outY[ (y * w +x ) ] = 0; + outU[ (y * w +x ) ] = 128; + outV[ (y * w +x ) ] = 128; + } + } +#endif + + for( y = ty1; y < ty2; y ++ ) + { + tx = xinc * ( tx1 + 0.5 ) + m01 * ( y + 0.5) + m02; + ty = yinc * ( tx1 + 0.5 ) + m11 * ( y + 0.5) + m12; + tw = winc * ( tx1 + 0.5 ) + m21 * ( y + 0.5) + m22; + for( x = 0; x < tx1; x ++ ) + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + } + + for( x = tx1; x < tx2 ; x ++ ) + { + if( tw == 0.0 ) { + ttx = 0.0; + tty = 0.0; + } else if ( tw != 1.0 ) { + ttx = tx / tw; + tty = ty / tw; + } else { + ttx = tx; + tty = ty; + } + + itx = (int32_t) ttx; + ity = (int32_t) tty; + + if( itx >= X && itx <= w && ity >= Y && ity < h ) + { + outY[(y*w+x)] = inY[(ity*w+itx)]; + outU[(y*w+x)] = inU[(ity*w+itx)]; + outV[(y*w+x)] = inV[(ity*w+itx)]; + } + else + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + + } + + tx += xinc; + ty += yinc; + tw += winc; + } + for( x = tx2; x < w; x ++ ) + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + } + + } + +#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE ) + int rest = h - ty2; + fast_memset_dirty( outY + (ty2 * v->w),0, rest * v->w ); + fast_memset_dirty( outU + (ty2 * v->w), 128, rest * v->w ); + fast_memset_dirty( outV + (ty2 * v->w), 128, rest * v->w ); + fast_memset_finish(); +#else + for( y = ty2 ; y < h; y ++ ) + { + for( x = 0; x < w; x ++ ) + { + outY[(y*w+x)] = 0; + outU[(y*w+x)] = 128; + outV[(y*w+x)] = 128; + } + } +#endif +} + + +void viewport_destroy( void *data ) +{ + viewport_t *v = (viewport_t*)data; + if( v ) + { + if( v->M ) free( v->M ); + if( v->m ) free( v->m ); + if( v->T ) free( v->T ); + if( v->map ) free( v->map ); + if( v->help ) free( v->help ); + if( v->homedir) free(v->homedir); + if( v->buf ) free(v->buf); + if( v->ui ) { + if( v->ui->scaler ) + yuv_free_swscaler(v->ui->scaler); + if( v->ui->buf ) + free(v->ui->buf[0]); + free(v->ui); + } + if(v->grid) free(v->grid); + free(v); + } + v = NULL; +} + +static int viewport_update_perspective( viewport_t *v, float *values ) +{ + int res = viewport_configure (v, v->x1, v->y1, + v->x2, v->y2, + v->x3, v->y3, + v->x4, v->y4, + v->x0, v->y0, + v->w0, v->h0, + v->w, v->h, + v->user_reverse, + v->grid_val, + v->grid_resolution ); + + + if(! res ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Viewport: Invalid quadrilateral. Trying to fallback"); + + v->x1 = values[0]; v->x2 = values[2]; v->x3 = values[4]; v->x4 = values[6]; + v->y1 = values[1]; v->y2 = values[3]; v->y3 = values[5]; v->y4 = values[7]; + + if(!viewport_configure( v, v->x1, v->y1, v->x2, v->y2, v->x3, v->y3,v->x4,v->y4, + v->x0, v->y0, v->w0, v->h0,v->w,v->h, v->user_reverse, v->grid_val,v->grid_resolution )); + { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to configure the viewport"); + veejay_msg(VEEJAY_MSG_ERROR, "If you are using a preset-configuration, see ~/.veejay/viewport.cfg"); + v->disable = 1; + return res; + } + } + + + // Clear map + const int len = v->w * v->h; + int k; + for( k = 0 ; k < len ; k ++ ) + v->map[k] = len+1; + + v->disable = 0; + + // Update map + viewport_process( v ); + + return res; +} +static int nearest_div(int val ) +{ + int r = val % 8; + while(r--) + val--; + return val; +} +static int nearest_div4(int val ) +{ + int r = val % 4; + while(r--) + val--; + return val; +} +static int nearest_div16(int val ) +{ + int r = val % 16; + while(r--) + val--; + return val; +} + +static void *viewport_init_swscaler(ui_t *u, int w, int h) +{ + uint8_t *dummy[3] = { NULL,NULL,NULL }; + int nw = w * u->scale; + int nh = h * u->scale; + u->sw = nearest_div(nw); + u->sh = nearest_div(nh); + VJFrame *srci = yuv_yuv_template( dummy[0],dummy[1],dummy[2],w,h,PIX_FMT_GRAY8); + VJFrame *dsti = yuv_yuv_template( dummy[0],dummy[1],dummy[2],u->sw,u->sh,PIX_FMT_GRAY8); + sws_template t; + memset(&t,0,sizeof(sws_template)); + t.flags = yuv_which_scaler(); + u->sx = (float)w / (float) u->sw; + u->sy = (float)h / (float) u->sh; + void *scaler = yuv_init_swscaler( srci,dsti,&t,yuv_sws_get_cpu_flags()); + + veejay_msg(VEEJAY_MSG_INFO, + "Scaling from %dx%d to %dx%d with a scale of %f", + w,h,u->sw,u->sh,u->scale ); + + free(srci); + free(dsti); + + return scaler; +} + + +void viewport_reconfigure(void *vv) +{ + viewport_t *v = (viewport_t*) vv; + float p[9]; + + p[0] = v->x1; + p[2] = v->x2; + p[4] = v->x3; + p[6] = v->x4; + p[1] = v->y1; + p[3] = v->y2; + p[5] = v->y3; + p[7] = v->y4; + + viewport_update_perspective(v,p); + +} + +void viewport_set_composite(void *vc, int mode, int colormode) +{ + viewport_config_t *c = (viewport_config_t*) vc; + c->composite_mode = mode; + c->colormode = colormode; +} +int viewport_get_color_mode_from_config(void *vc) +{ + viewport_config_t *c = (viewport_config_t*) vc; + return c->colormode; +} + +int viewport_get_composite_mode_from_config(void *vc) +{ + viewport_config_t *c = (viewport_config_t*) vc; + return c->composite_mode; +} + +int viewport_get_initial_active( void *vv ) +{ + viewport_t *v = (viewport_t*) vv; + return v->initial_active; +} + +void viewport_set_initial_active( void *vv, int status ) +{ + viewport_t *v = (viewport_t*) vv; + v->initial_active = status; +} + +void *viewport_get_configuration(void *vv ) +{ + + viewport_t *v = (viewport_t*) vv; + viewport_config_t *o = (viewport_config_t*) vj_calloc(sizeof(viewport_config_t)); + + + o->saved_w = v->saved_w; + o->saved_h = v->saved_h; + o->reverse = v->user_reverse; + o->grid_resolution = v->grid_resolution; + o->grid_color = v->grid_val; + o->frontback = 0; + o->x0 = v->x0; + o->y0 = v->y0; + o->w0 = v->w0; + o->h0 = v->h0; + o->x1 = v->x1; + o->x2 = v->x2; + o->x3 = v->x3; + o->x4 = v->x4; + o->y1 = v->y1; + o->y2 = v->y2; + o->y3 = v->y3; + o->y4 = v->y4; + o->scale = v->ui->scale; + o->initial_active = v->initial_active; + + return o; +} + +int viewport_reconfigure_from_config(void *vv, void *vc) +{ + viewport_t *v = (viewport_t*) vv; + viewport_config_t *c = (viewport_config_t*) vc; + viewport_config_t *o = viewport_get_configuration(vv ); + + if( c->saved_w != v->saved_w || c->saved_h != v->saved_h ) { + float sx=1.0f; + float sy=1.0f; + if( c->saved_w > 0 && c->saved_h > 0 ) { + sx = (float) c->saved_w / (float) v->saved_w; + sy = (float) c->saved_h / (float) v->saved_h; + } + o->x0 = c->x0 * sx; + o->y0 = c->y0 * sy; + o->w0 = c->w0 * sx; + o->h0 = c->h0 * sy; + } + + + // Clear map + const int len = v->w * v->h; + int k; + for( k = 0 ; k < len ; k ++ ) + v->map[k] = len+1; + + v->disable = 0; + + // try to initialize the new settings + int res = viewport_configure( v, c->x1,c->y1, + c->x2,c->y2, + c->x3,c->y3, + c->x4,c->y4, + c->x0,c->y0, + c->w0,c->h0, + v->w,v->h, + c->reverse, + c->grid_color, + c->grid_resolution ); + + if(!res) { + veejay_msg(VEEJAY_MSG_ERROR, "Cannot load calibration settings, restoring defaults."); + res = viewport_configure( v, o->x1,o->y1, + o->x2,o->y2, + o->x3,o->y3, + o->x4,o->y4, + o->x0,o->y0, + o->w0,o->h0, + v->w,v->h, + o->reverse, + o->grid_color, + o->grid_resolution ); + + + } + + if(!res) { + veejay_msg(VEEJAY_MSG_ERROR, "Unable to revert to old configuration."); + v->disable = 1; + free(o); + return 0; + } + + + if( res ) { + v->user_ui = 0; + viewport_process( v ); + veejay_msg(VEEJAY_MSG_DEBUG, + "Reconfigured calibration for %dx%d to (1)=%fx%f\t(2)=%fx%f\t(3)=%fx%f\t(4)=%fx%f\t%dx%d+%dx%d", + v->w,v->h,v->x1,v->y1,v->x2,v->y2,v->x3,v->y3,v->x4,v->y4,v->x0,v->y0,v->w0,v->h0); + + } + free(o); + return 1; +} +void viewport_update_from(void *vv, void *bb) +{ + viewport_t *v = (viewport_t*) vv; + viewport_t *b = (viewport_t*) bb; + + if(!v || !b) return; + float p[9]; + + p[0] = b->x1; + p[2] = b->x2; + p[4] = b->x3; + p[6] = b->x4; + p[1] = b->y1; + p[3] = b->y2; + p[5] = b->y3; + p[7] = b->y4; + + + float sx = (float) b->w / (float) v->w; + float sy = (float) b->h / (float) v->h; + + b->x0 = v->x0 * sx; + b->y0 = v->y0 * sy; + b->w0 = v->w0 * sx; + b->h0 = v->h0 * sy; + b->x = v->x * sx; + b->y = v->y * sy; + + b->x1 = v->x1; + b->y1 = v->y1; + b->x2 = v->x2; + b->y2 = v->y2; + b->x3 = v->x3; + b->y3 = v->y3; + b->x4 = v->x4; + b->y4 = v->y4; + + b->user_reverse = v->user_reverse; + + + if(viewport_update_perspective(b,p)) { + veejay_msg(VEEJAY_MSG_DEBUG, "Configured input %dx%d to (1)=%fx%f\t(2)=%fx%f\t(3)=%fx%f\t(4)=%fx%f\t%dx%d+%dx%d", + b->w,b->h,b->x1,b->y1,b->x2,b->y2,b->x3,b->y3,b->x4,b->y4,b->x0,b->y0,b->w0,b->h0); + } + else + veejay_msg(VEEJAY_MSG_DEBUG,"Failed to configure input."); + + +} + +void *viewport_init(int x0, int y0, int w0, int h0, int w, int h, int iw, int ih,const char *homedir, int *enable, int *frontback, int mode ) +{ +#ifdef STRICT_CHECKING + assert( w > 0 ); + assert( h > 0 ); + assert( w0 > 0 ); + assert( h0 > 0 ); +#endif + //@ try to load last saved settings + viewport_config_t *vc = viewport_load_settings( homedir,mode ); + if(vc) { + float sx = (float) w / (float) vc->saved_w; + float sy = (float) h / (float) vc->saved_h; + + vc->x0 = vc->x0 * sx; + vc->y0 = vc->y0 * sy; + vc->w0 = vc->w0 * sx; + vc->h0 = vc->h0 * sy; + veejay_msg(VEEJAY_MSG_INFO,"\tQuad : %dx%d+%dx%d",vc->x0,vc->y0,vc->w0,vc->h0 ); + } else { + veejay_msg(VEEJAY_MSG_WARNING, "No or invalid viewport configuration file in %s", homedir ); + veejay_msg(VEEJAY_MSG_WARNING, "Using default values"); + veejay_msg(VEEJAY_MSG_INFO,"\tBacking : %dx%d",w,h); + veejay_msg(VEEJAY_MSG_INFO,"\tRectangle: %dx%d+%dx%d",x0,y0,w0,h0); + } + + viewport_t *v = (viewport_t*) vj_calloc(sizeof(viewport_t)); + v->usermouse[0] = 0.0; + v->usermouse[1] = 0.0; + v->usermouse[2] = 0.0; + v->usermouse[3] = 0.0; + v->M = NULL; + v->m = NULL; + v->grid = NULL; + v->ui = vj_calloc( sizeof(ui_t)); + v->ui->buf[0] = vj_calloc(sizeof(uint8_t) * RUP8(w * h) ); + v->ui->scale = 0.5f; + v->ui->scaler = viewport_init_swscaler(v->ui,iw,ih); + v->saved_w = w; + v->saved_h = h; + v->w = w; + v->h = h; + v->marker_size = 4; + v->homedir = strdup(homedir); + int res; + + if( vc == NULL ) + { + res = viewport_configure (v, 29.0, 28.0, + 70.0, 30.0, + 70.0, 66.0, + 30.0, 69.0, + + x0,y0,w0,h0, + w,h, + 1, + 0xff, + w/32 ); + + *enable = 0; + *frontback = 1; + v->user_ui = 0; + + } + else + { + v->marker_size = vc->marker_size; + v->grid_resolution = vc->grid_resolution; + v->grid_mode = vc->grid_mode; + v->initial_active = vc->initial_active; + + res = viewport_configure( v, vc->x1, vc->y1, + vc->x2, vc->y2, + vc->x3, vc->y3, + vc->x4, vc->y4, + vc->x0, vc->y0, + vc->w0, vc->h0, + w,h, + vc->reverse, + vc->grid_color, + vc->grid_resolution ); + + *enable = vc->initial_active; + *frontback = vc->frontback; + v->user_ui = 0; + + } + + + if(! res ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations"); + free(v->homedir); + free(v->ui->buf[0]); + free(v->ui); + free(v); + free(vc); + return NULL; + } + + // Allocate memory for map + v->map = (int32_t*) vj_calloc(sizeof(int32_t) * RUP8(v->w * v->h + (v->w*2)) ); + + const int len = v->w * v->h; + const int eln = len + ( v->w * 2 ); + int k; + for( k = len ; k < eln ; k ++ ) + v->map[k] = len+1; + + // calculate initial view + viewport_process( v ); + + v->buf = vj_calloc( sizeof(int32_t) * 50000 ); + free(vc); + + if(v->grid_resolution > 0) + viewport_compute_grid(v); + + return (void*)v; +} + +void *viewport_clone(void *vv, int new_w, int new_h ) +{ + viewport_t *v = (viewport_t*) vv; + if(!v) return NULL; +#ifdef STRICT_CHECKING + assert( new_w > 0 ); + assert( new_h > 0 ); +#endif + viewport_t *q = (viewport_t*) vj_malloc(sizeof(viewport_t)); + veejay_memcpy(q,v,sizeof(viewport_t)); + + float sx = (float) new_w / (float) v->w; + float sy = (float) new_h / (float) v->h; + q->M = NULL; + q->m = NULL; + q->grid = NULL; + q->initial_active = v->initial_active; + q->x0 = v->x0 * sx; + q->y0 = v->y0 * sy; + q->w0 = v->w0 * sx; + q->h0 = v->h0 * sy; + q->x = v->x * sx; + q->y = v->y * sy; + q->w = new_w; + q->h = new_h; + q->usermouse[0] = 0.0; + q->usermouse[1] = 0.0; + q->usermouse[2] = 0.0; + q->usermouse[3] = 0.0; + q->ui = vj_calloc( sizeof(ui_t)); + q->ui->buf[0] = vj_calloc(sizeof(uint8_t) * RUP8(new_w * new_h) ); + q->ui->scale = 1.0f; + q->ui->scaler = viewport_init_swscaler(q->ui,new_w,new_h); + q->homedir = strdup(v->homedir); + + int res = viewport_configure( q, q->x1, q->y1, + q->x2, q->y2, + q->x3, q->y3, + q->x4, q->y4, + q->x0, q->y0, + q->w0, q->h0, + new_w,new_h, + q->user_reverse, + q->grid_val, + q->grid_resolution ); + + q->user_ui = 0; + + if(! res ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations"); + free(q->homedir); + free(q->ui->buf[0]); + free(q->ui); + free(q); + return NULL; + } + + // Allocate memory for map + q->map = (int32_t*) vj_calloc(sizeof(int32_t) * RUP8(q->w * q->h + (q->w*2)) ); + + const int len = q->w * q->h; + const int eln = len + ( q->w * 2 ); + int k; + for( k = len ; k < eln ; k ++ ) + q->map[k] = len+1; + + viewport_process( q ); + + q->buf = vj_calloc( sizeof(int32_t) * 50000 ); + veejay_msg(VEEJAY_MSG_INFO,"\tConfiguring input:"); + veejay_msg(VEEJAY_MSG_INFO, "\tPoints :\t(1) %fx%f (2) %fx%f", q->x1,q->y1,q->x2,q->y2); + veejay_msg(VEEJAY_MSG_INFO, "\t :\t(3) %fx%f (4) %fx%f", q->x2,q->y2,q->x3,q->y3); + veejay_msg(VEEJAY_MSG_INFO, "\tQuad :\t%dx%d+%dx%d", q->x0,q->y0,q->w0,q->h0 ); + veejay_msg(VEEJAY_MSG_INFO, "\tDimension:\t%dx%d",q->w,q->h); + return (void*) q; +} + + +int viewport_active( void *data ) +{ + viewport_t *v = (viewport_t*) data; + return v->user_ui; +} + +char *viewport_get_help(void *data) +{ + viewport_t *v = (viewport_t*)data; + return v->help; +} + +static viewport_config_t *viewport_load_settings( const char *dir, int mode ) +{ + viewport_config_t *vc = vj_calloc(sizeof(viewport_config_t)); + + char path[1024]; + sprintf(path, "%s/viewport.cfg", dir); + FILE *fd = fopen( path, "r" ); + if(!fd) + { + veejay_msg(0, "Unable to open file %s",path); + free(vc); + return NULL; + } + fseek(fd,0,SEEK_END ); + unsigned int len = ftell( fd ); + + if( len <= 0 ) + { + veejay_msg(0, "%s is empty", path); + free(vc); + return NULL; + } + + char *buf = vj_calloc( (len+1) ); + + rewind( fd ); + fread( buf, len, 1 , fd); + + fclose(fd ); + + int n = sscanf(buf, "%f %f %f %f %f %f %f %f %d %d %d %d %d %d %d %d %d %d %d %d %d", + &vc->x1, &vc->y1, + &vc->x2, &vc->y2, + &vc->x3, &vc->y3, + &vc->x4, &vc->y4, + &vc->reverse, + &vc->grid_resolution, + &vc->grid_color, + &vc->x0, + &vc->y0, + &vc->w0, + &vc->h0, + &vc->frontback, + &vc->saved_w, + &vc->saved_h, + &vc->marker_size, + &vc->grid_mode, + &vc->initial_active); + + //@ pre 1.4.10 + if( n == 20 ) { + vc->initial_active = 1; + n++; + } + + if( n != 21 ) + { + veejay_msg(0, "Unable to read %s (file is %d bytes)",path, len ); + free(vc); + free(buf); + return NULL; + } + + free(buf); + veejay_msg(VEEJAY_MSG_INFO, "Projection configuration:"); + veejay_msg(VEEJAY_MSG_INFO, "\tBehaviour:\t%s", (vc->reverse ? "Forward" : "Projection") ); + veejay_msg(VEEJAY_MSG_INFO, "\tPoints :\t(1) %fx%f (2) %fx%f", vc->x1,vc->y1,vc->x2,vc->y2); + veejay_msg(VEEJAY_MSG_INFO, "\t :\t(3) %fx%f (4) %fx%f", vc->x2,vc->y2,vc->x3,vc->y3); + veejay_msg(VEEJAY_MSG_INFO, "\tPencil :\t%s", (vc->grid_color == 0xff ? "white" : "black" ) ); + veejay_msg(VEEJAY_MSG_INFO, "\tEnabled :\t%s", + (vc->initial_active == 0 ? "No" : "Yes")); + + return vc; +} + +static void viewport_save_settings( viewport_t *v, int frontback ) +{ + char path[1024]; + sprintf(path, "%s/viewport.cfg", v->homedir ); + + FILE *fd = fopen( path, "wb" ); + + if(!fd) + { + veejay_msg(0, "Unable to open '%s' for writing. Cannot save viewport settings", + path ); + return; + } + + char content[512]; + + sprintf( content, "%f %f %f %f %f %f %f %f %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + v->x1,v->y1,v->x2,v->y2, + v->x3,v->y3,v->x4,v->y4, + v->user_reverse, + 0, + v->grid_val, + v->x0, + v->y0, + v->w0, + v->h0, + frontback, + v->saved_w, + v->saved_h, + v->marker_size, + v->grid_mode, + v->initial_active ); + + int res = fwrite( content, strlen(content), 1, fd ); + + if( res <= 0 ) + veejay_msg(VEEJAY_MSG_ERROR, "Unable to save viewport settings to %s", path ); + + fclose( fd ); + + veejay_msg(VEEJAY_MSG_DEBUG, "Saved viewport settings to %s", path); +} +/* +static int viewport_locate_marker( viewport_t *v, uint8_t *img, float fx, float fy , float *dx, float *dy ) +{ + uint32_t x = fx / 100.0f * v->w; + uint32_t y = fy / 100.0f * v->h; + + uint32_t x1 = x - v->marker_size; + uint32_t y1 = y - v->marker_size; + uint32_t x2 = x + v->marker_size; + uint32_t y2 = y + v->marker_size; + + if( x1 < 0 ) x1 = 0; else if ( x1 > v->w ) x1 = v->w; + if( y1 < 0 ) y1 = 0; else if ( y1 > v->h ) y1 = v->h; + if( x2 < 0 ) x2 = 0; else if ( x2 > v->w ) x2 = v->w; + if( y2 < 0 ) y2 = 0; else if ( y2 > v->h ) y2 = v->h; + + unsigned int i,j; + uint32_t product_row = 0; + uint32_t pixels_row = 0; + uint32_t product_col = 0; + uint32_t pixels_col = 0; + uint32_t pixels_row_c = 0; + uint32_t product_col_c = 0; + + unsigned long nc = 0, it =0; + uint8_t hist[256]; + uint8_t p0 = 0; + int32_t ii=0,ji=0; + veejay_memset(hist,0,sizeof(hist)); + + // find average and most occuring pixel + for( i = y1; i < y2; i ++ ) + { + for( j = x1; j < x2 ; j ++ ) + { + p0 = (img[i*v->w+j] >= 255 ? 0: img[i * v->w + j]); + nc += p0; + hist[ p0 ] ++; + it ++; + } + } + + for( i =0 ;i < 256; i ++ ) + { + if( hist[i] > ji ) + { + ii = i; + ji = hist[i]; + } + } + + unsigned int avg = 0; + if( nc > 0 ) + avg = (nc / it); + + int diff = abs( ii - avg ); + for( i = y1; i < y2; i ++ ) + { + pixels_row = 0; + for( j = x1; j < x2 ; j ++ ) + { + if (abs(img[i * v->w + j] - diff)>= avg) + { + pixels_row++; + } + } + product_row += (i * pixels_row); + pixels_row_c += pixels_row; + } + + for( i = x1; i < x2; i ++ ) + { + pixels_col = 0; + for( j = y1; j < y2; j ++ ) + { + if (abs(img[i * v->w + j] - diff)>= avg) + { + pixels_col ++; + } + } + product_col += (i * pixels_col); + product_col_c += pixels_col; + } + + if( pixels_row_c == 0 || product_col_c == 0 ) + return 0; + + + uint32_t cy = ( product_row / pixels_row_c ); + uint32_t cx = ( product_col / product_col_c ); + + *dx = (float) cx / (v->w / 100.0f); + *dy = (float) cy / (v->h / 100.0f); + + return 1; +}*/ + +void viewport_projection_inc( void *data, int incr, int screen_width, int screen_height ) +{ +} +/* +#define ANIMAX + +#ifdef ANIMAX +#include +#define GROUP "227.0.0.17" +#define PORT_NUM 1234 +#endif + +typedef struct +{ + int x; + int y; +} point_t; + +inline int is_left( point_t *p0, point_t *p1, point_t *p2 ) +{ + return ( + (p1->x - p0->x) * (p2->y - p0->y) - + (p2->x - p0->x) * (p1->y - p0->y) + ); +} + +//@ chainhull 2D (C) 2001 softSurfer (www.softsurfer.com) +//@ http://geometryalgorithms.com/Archive/algorithm_0109/algorithm_0109.htm +point_t **chainhull_2d( point_t **p , int n, int *res ) +{ + point_t **H = (point_t**) vj_malloc( n * sizeof(point_t)); + int i; + + int bot=0, top=-1; + + int xmin = p[0]->x; + for( i = 1; i < n; i++) + if( p[i]->x != xmin ) break; + int minmax = i-1; + int minmin = 0; + if( minmax == (n-1)) { + H[++top] = p[minmin]; + if( p[minmax]->y != p[minmin]->y ) + H[++top] = p[minmax]; + H[++top] = p[minmin]; + *res = top + 1; + } + + int maxmin,maxmax = n-1; + int xmax = p[n-1]->x; + for( i = n-2; i >= 0; i -- ) + if( p[i]->x != xmax ) break; + maxmin = i+1; + + H[++top] = p[minmin]; + i= minmax; + while( ++i <= maxmin ) + { + if ( is_left( p[minmin], p[maxmin], p[i]) >= 0 && i < maxmin ) + continue; + while( top > 0 ) + { + if ( is_left( H[top-1], H[top], p[i] ) > 0 ) + break; + else + top--; + } + H[++top] = p[i]; + } + + + if( maxmax != maxmin ) + H[++top] = p[maxmax]; + bot = top; + i = maxmin; + while( --i >= minmax ) + { + if( is_left( p[maxmax], p[minmax], p[i] ) >= 0 && i > minmax ) + continue; + while( top > bot ) + { + if( is_left( H[top-1], H[top], p[i] ) > 0 ) + break; + else + top--; + } + H[++top] = p[i]; + } + if( minmax != minmin ) + H[++top] = p[minmin]; + + *res = top + 1; + + return H; +} + +static void shell_sort_points_by_degree( double *a , point_t **p, int n ) +{ + int i,j,increment=3; + double temp; + int dx,dy; + while( increment > 0 ) + { + for( i = 0; i < n; i ++ ) + { + j=i; + temp = a[i]; + dx = p[i]->x; + dy = p[i]->y; + while(( j>= increment) && (a[j-increment] > temp )) + { + a[j] = a[j-increment]; + p[j]->x = p[j-increment]->x; + p[j]->y = p[j-increment]->y; + j = j - increment; + } + a[j] = temp; + p[j]->x = dx; + p[j]->y = dy; + } + if( increment / 2 != 0 ) + increment = increment / 2; + else if (increment ==1 ) + increment = 0; + else + increment = 1; + } + +} + +static void sort_points_by_degree( double *a, point_t **p, int n ) +{ + int i; + for( i = 2; i <= n; i ++ ) + { + float sentinel = a[i]; + point_t point; + point.x = p[i]->x; + point.y = p[i]->y; + int k = i; + while( sentinel < a[k-1] && k > 0) + { + int j = k; + a[k] = a[--k]; + p[j]->x = p[k]->x; + p[j]->y = p[k]->y; + } + a[k] = sentinel; + p[k]->x = point.x; + p[k]->y = point.y; + } +} + +#define VEEJAY_PACKET_SIZE 16384 + +void viewport_dummy_send( void *data ) +{ + viewport_t *v = (viewport_t*) data; +#ifdef ANIMAX + unsigned char empty_buf[VEEJAY_PACKET_SIZE]; + veejay_memset( empty_buf, 0, VEEJAY_PACKET_SIZE ); + + if(! v->sender ) + { + v->sender = mcast_new_sender( GROUP ); + v->seq_id = 0; + } + if(!v->sender) + return; + + int result = mcast_send( v->sender, empty_buf,VEEJAY_PACKET_SIZE, PORT_NUM ); + if(result<=0) + { + veejay_msg(0, "Cannot send empty packet over mcast %s:%d", GROUP,PORT_NUM ); + mcast_close_sender( v->sender ); + v->sender = NULL; + } +#endif +} + +void viewport_transform_coords( + void *data, + void *input, + int n, + int blob_id, + int center_x, + int center_y, + int wid, + int hei, + int num_objects, + uint8_t *plane ) +{ + int i, res = 0; + viewport_t *v = (viewport_t*) data; +#ifdef ANIMAX + if(! v->sender ) + { + v->sender = mcast_new_sender( GROUP ); + v->seq_id = 0; + veejay_memset( v->buf, 0, VEEJAY_PACKET_SIZE ); + } + if(!v->sender) + return; +#endif + + if( n <= 0 ) + { + viewport_dummy_send( data ); + return; + } + + if( !v->T ) + { + matrix_t *tmp = viewport_matrix(); + v->T = viewport_invert_matrix( v->M, tmp ); + free(tmp); + } + + point_t **points = (point_t**) input; + double *array = (double*) vj_malloc( (n+3) * sizeof(double)); + + for( i = 0; i < n; i ++ ) + array[i] = atan2( (points[i]->x - center_x), (points[i]->y - center_y) ) * (180.0/M_PI ); + + //@ convex hull + point_t **contour = chainhull_2d( points, n, &res ); + + if( res > 256 ) + { + veejay_msg(1, "Convex Hull has %d points, Maximum allowed is 256", res ); + res = 256; + } + + if ( plane ) + { + for( i = 0; i < (res-1); i ++ ) + { + //@ draw polygon + viewport_line( plane, + contour[i]->x, + contour[i]->y, + contour[i+1]->x, + contour[i+1]->y, + wid, + hei, + 200 ); + } + + plane[ center_y * wid + center_x ] = 0xff; //@ display centroid + } + + shell_sort_points_by_degree( array, points, n ); + + //@ Protocol: + //@ bytes 0 ... 4 : blob id + // 4 ... 8 : number of points in convex hull + // 8 ... 12 : header symbol + // 12 ... 16 : sequence number + // 16 ... 20 : total number of blobs + // 20 ... 24 : number of points in contour + // 24 ... N1 : convex hull points + // N1 ... N2 : contour hull points + // + // packet size: 16 Kbytes + + v->buf[0] = blob_id; + v->buf[1] = res*2; + v->buf[2] = -1; + v->buf[3] = v->seq_id ++; + v->buf[4] = num_objects; + v->buf[5] = n*2; + int j = 6; + for( i = 0; i < res; i ++ ) + { + float dx1,dy1; + point_map( v->T, contour[i]->x, contour[i]->y, &dx1, &dy1 ); + v->buf[j + 0] = (int)((dx1/ (float) v->w) * 1000.0f ); + v->buf[j + 1] = (int)((dy1/ (float) v->h) * 1000.0f ); + j+=2; + } + + for( i = 0; i < n; i ++ ) + { + float dx1,dy1; + point_map( v->T, points[i]->x, points[i]->y, &dx1,&dy1 ); + v->buf[j + 0] = (int) ( ( dx1/(float) v->w) * 1000.0f ); + v->buf[j + 1] = (int) ( ( dy1/(float) v->h) * 1000.0f ); + j += 2; + } + int payload = ((n*2)+(res * 2) + 6) * sizeof(int); + int left = VEEJAY_PACKET_SIZE - payload; + + int *ptr = &(v->buf[j]); + + if(left > 0) + veejay_memset( ptr,0, left ); + + if( payload > VEEJAY_PACKET_SIZE ) + veejay_msg(1, "Contours and convex hull too large for packet"); + +#ifdef ANIMAX + int result = mcast_send( v->sender, v->buf,VEEJAY_PACKET_SIZE, PORT_NUM ); + if(result<=0) + { + veejay_msg(0, "Cannot send contour/convex hull over mcast %s:%d", GROUP,PORT_NUM ); + mcast_close_sender( v->sender ); + v->sender = NULL; + } +#endif + + free(contour); + free(array); + +} + +int *viewport_event_get_projection(void *data, int scale) { + viewport_t *v = (viewport_t*) data; + float fscale = 1.0f; + float set[9]; + if( scale == 100 ) { + set[0] = v->x1;// * sw; + set[1] = v->y1;// * sh; + set[2] = v->x2;// * sw; + set[3] = v->y2;// * sh; + set[4] = v->x3;// * sw; + set[5] = v->y3;// * sh; + set[6] = v->x4;// * sw; + set[7] = v->y4;// * sh; + } else { + float sw = (float) scale / 100.0; + float sh = (float) scale / 100.0; + fscale = sw; + set[0] = v->x1 * sw; + set[1] = v->y1 * sh; + set[2] = v->x2 * sw; + set[3] = v->y2 * sh; + set[4] = v->x3 * sw; + set[5] = v->y3 * sh; + set[6] = v->x4 * sw; + set[7] = v->y4 * sh; + } + + int *res = (int*) vj_malloc(sizeof(int) * 8 ); + int i; + + for( i = 0; i < 8 ; i ++ ) { + res[i] = (int) ( set[i]); + } + return res; +} + +int viewport_event_set_projection(void *data, float x, float y, int num, int frontback) { + + + viewport_t *v = (viewport_t*) data; + switch(num) { + case 1: + v->x1 = x; + v->y1 = y; + break; + case 2: + v->x2 = x; + v->y2 = y; + break; + case 3: + v->x3 = x; + v->y3 = y; + break; + case 4: + v->x4 = x; + v->y4 = y; + break; + } + float p[8]; + p[0] = v->x1; + p[2] = v->x2; + p[4] = v->x3; + p[6] = v->x4; + p[1] = v->y1; + p[3] = v->y2; + p[5] = v->y3; + p[7] = v->y4; + + if( viewport_update_perspective( v, p ) ) { + veejay_msg(VEEJAY_MSG_INFO, "Accepted viewport configuration from remote."); + } else { + veejay_msg(0, "Error updating points"); + } + + return 1; +}*/ + + +int viewport_finetune_coord(void *data, int screen_width, int screen_height,int inc_x, int inc_y) +{ + viewport_t *v = (viewport_t*) data; + if(!v->user_ui) + return 0; + + int width = v->w; + int height = v->h; + int point = -1; + int i; + + //@ use screen width/height + double dist = 100.0; + int cx = v->w / 2; + int cy = v->h / 2; + int dx = cx - ( v->ui->sw / 2 ); + int dy = cy - ( v->ui->sh / 2 ); + float scx = (float) v->w / (float) v->ui->sw; + float scy = (float) v->h / (float) v->ui->sh; + int x = v->usermouse[4]; + int y = v->usermouse[5]; + float p_cpy[9]; + float p[9]; + + p[0] = v->x1; + p[2] = v->x2; + p[4] = v->x3; + p[6] = v->x4; + p[1] = v->y1; + p[3] = v->y2; + p[5] = v->y3; + p[7] = v->y4; + + int j; + + float ix = (float) inc_x * 0.1f; + float iy = (float) inc_y * 0.1f; + + for ( j = 0 ; j < 8 ; j += 2 ) { + p_cpy[j] = p[j]; + p_cpy[j+1]=p[j+1]; + p[j] = msx(v, p[j] ); + p[j+1]= msy(v, p[j+1] ); + } + + if( v->user_ui ) + { + double dt[4]; + dt[0] = sqrt( (p[0] - x) * (p[0] - x) + ( p[1] - y ) * (p[1] -y ) ); + dt[1] = sqrt( (p[2] - x) * (p[2] - x) + ( p[3] - y ) * (p[3] -y ) ); + dt[2] = sqrt( (p[4] - x) * (p[4] - x) + ( p[5] - y ) * (p[5] -y ) ); + dt[3] = sqrt( (p[6] - x) * (p[6] - x) + ( p[7] - y ) * (p[7] -y ) ); + + for ( i = 0; i < 4; i ++ ) + { + if( dt[i] < dist ) + { + dist = dt[i]; + point = i; + } + } + } + + if( point < 0 ) + return 0; + + switch( point ) + { + case 0: + v->x1 = vsx(v, p[0] + ix); + v->y1 = vsy(v, p[1] + iy); + break; + case 1: + v->x2 = vsx(v, p[2] + ix); + v->y2 = vsy(v, p[3] + iy); + break; + case 2: + v->x3 = vsx(v,p[4] + ix); + v->y3 = vsy(v,p[5] + iy); + break; + case 3: + v->x4 = vsx(v,p[6] + ix); + v->y4 = vsy(v,p[7] + iy); + break; + } + viewport_update_perspective( v, p_cpy ); + if(v->grid) + viewport_compute_grid(v); + return 1; +} + +int viewport_external_mouse( void *data, uint8_t *img[3], int sx, int sy, int button, int frontback, int screen_width, int screen_height ) +{ + viewport_t *v = (viewport_t*) data; + if( sx == 0 && sy == 0 && button == 0 ) + return 0; + + int ch = 0; + int width = v->w; + int height = v->h; + int point = -1; + int i; + + //@ use screen width/height + float x = (float)sx / ( screen_width / 100.0f ); + float y = (float)sy / ( screen_height / 100.0f ); + double dist = 100.0; + int cx = v->w / 2; + int cy = v->h / 2; + int dx = cx - ( v->ui->sw / 2 ); + int dy = cy - ( v->ui->sh / 2 ); + float scx = (float) v->w / (float) v->ui->sw; + float scy = (float) v->h / (float) v->ui->sh; + int nsx = (sx - dx) * scx; + int nsy = (sy - dy) * scy; + + v->usermouse[2] = (float) nsx; + v->usermouse[3] = (float) nsy; + v->usermouse[4] = x; + v->usermouse[5] = y; + + float p_cpy[9]; + float p[9]; + // make a copy of the parameters + + p[0] = v->x1; + p[2] = v->x2; + p[4] = v->x3; + p[6] = v->x4; + p[1] = v->y1; + p[3] = v->y2; + p[5] = v->y3; + p[7] = v->y4; + + int j; + for ( j = 0 ; j < 8 ; j += 2 ) { + p_cpy[j] = p[j]; + p_cpy[j+1]=p[j+1]; + p[j] = msx(v, p[j] ); + p[j+1]= msy(v, p[j+1] ); + } + + float tx = vsx(v,v->usermouse[4]); + float ty = vsy(v,v->usermouse[5]); + + + float bx = msx(v,tx); + float by = msy(v,ty); + + + for( i = 0; i < 4 ; i ++ ) + v->users[ i ] = 1; + + if( v->user_ui ) + { + double dt[4]; + dt[0] = sqrt( (p[0] - x) * (p[0] - x) + ( p[1] - y ) * (p[1] -y ) ); + dt[1] = sqrt( (p[2] - x) * (p[2] - x) + ( p[3] - y ) * (p[3] -y ) ); + dt[2] = sqrt( (p[4] - x) * (p[4] - x) + ( p[5] - y ) * (p[5] -y ) ); + dt[3] = sqrt( (p[6] - x) * (p[6] - x) + ( p[7] - y ) * (p[7] -y ) ); + + for ( i = 0; i < 4; i ++ ) + { + if( dt[i] < dist ) + { + dist = dt[i]; + point = i; + } + } + } + + v->save = 0; + + if( ( button == 6 || button == 1 || button == 12) && point >= 0 ) + v->save = 1; + + if( button == 0 && point >= 0) + v->users[ point ] = 2; + + if( button == 0 ) + { + v->usermouse[0] = x; + v->usermouse[1] = y; + } + + if( button == 2 ) + { + if(v->user_reverse) v->user_reverse = 0; else v->user_reverse = 1; + ch = 1; + } + + if( button == 3 ) + { + if(v->user_ui) v->user_ui = 0; else v->user_ui = 1; + + if( v->user_ui == 0 ) + { + viewport_save_settings(v, frontback); + } + } + + + if( button == 6 && point >= 0) + { + switch( point ) + { + case 0: + v->x0 = (int32_t)nsx; + v->y0 = (int32_t)nsy; + clamp1(v->x0, 0, v->w ); + clamp1(v->y0, 0, v->h ); + break; + case 1: + v->w0 = nsx - v->x0; + v->y0 = nsy; + clamp1(v->w0, 0,v->w ); + clamp1(v->y0, 0,v->h ); + break; + case 2: + v->w0 = nsx - v->x0; + v->h0 = nsy - v->y0; + clamp1(v->w0, 0,v->w ); + clamp1(v->h0, 0,v->h ); + break; + case 3: + v->w0 = ( v->x0 - nsx ) + v->w0; + v->x0 = nsx; + v->h0 = nsy - v->y0; + clamp1(v->x0, 0,v->w ); + clamp1(v->h0, 0,v->h ); + clamp1(v->w0, 0,v->w ); + break; + } + ch = 1; + } + + float rat = (v->h/(float)v->w); + if( button == 15 ) { + v->grid_mode --; + if(v->grid_mode < 0 ) + v->grid_mode = 2; + } + + if( button == 5 ) // wheel up + { + if(v->grid_mode == 0 ) { + v->marker_size --; + if(v->marker_size < 2 ) + v->marker_size = 4; + } else { + v->grid_resolution -= GRID_STEP; + if(v->grid_resolution < 2 ) + v->grid_resolution = 2; + viewport_compute_grid(v); + } + } + + if( button == 16 ) + { + v->grid_mode ++; + if(v->grid_mode > 2 ) + v->grid_mode = 0; + } + + if (button == 4 ) // wheel down + { + if(v->grid_mode == 0 ) { + v->marker_size ++; + if(v->marker_size > v->w/16) + v->marker_size = 4; + } else { + v->grid_resolution += GRID_STEP; + if(v->grid_resolution > v->w ) + v->grid_resolution = v->w; + viewport_compute_grid(v); + } + } + if( button == 7 ) + { + if( v->grid_val == 0xff ) + v->grid_val = 0; + else + v->grid_val = 0xff; + } + + + if(v->save) + { + if( button == 12 ) + { + } + else if( button == 1 ) + { + switch( point ) + { + case 0: + v->x1 = tx; + v->y1 = ty; + break; + case 1: + v->x2 = tx; + v->y2 = ty; + break; + case 2: + v->x3 = tx; + v->y3 = ty; + break; + case 3: + v->x4 = tx; + v->y4 = ty; + break; + + } + } + ch = 1; + + } + + if( ch ) + { + viewport_update_perspective( v, p_cpy ); + if(v->grid) + viewport_compute_grid(v); + + return 1; + } + return 0; +} + + +void viewport_push_frame(void *data, int w, int h, uint8_t *Y, uint8_t *U, uint8_t *V ) +{ + viewport_t *v = (viewport_t*) data; + ui_t *u = v->ui; + + float s = u->scale; + + int nw = w * s; + int nh = h * s; + + VJFrame *srci = yuv_yuv_template( Y, U,V, w,h, PIX_FMT_GRAY8 ); + VJFrame *dsti = yuv_yuv_template( u->buf[0],NULL,NULL,u->sw, u->sh, PIX_FMT_GRAY8); + + yuv_convert_and_scale( u->scaler, srci,dsti ); + free(srci); + free(dsti); +} + +static void viewport_translate_frame(void *data, uint8_t *plane ) +{ + viewport_t *v = (viewport_t*) data; + ui_t *u = v->ui; + int cx = v->w / 2; + int cy = v->h / 2; + int w = v->w; + int h = v->h; + int dx = cx - ( u->sw / 2 ); + int dy = cy - ( u->sh / 2 ); + + int x,y; + int j = 0; + + uint8_t *img = u->buf[0]; + for( y = 0; y < u->sh; y ++ ) { + for( x = 0; x < u->sw; x ++ ) { + plane[ (dy + y ) * w + dx + x ] = img[ y * u->sw + x ]; + } + } + +} + + +static void viewport_draw_marker(viewport_t *v, int x, int y, int w, int h, uint8_t *plane ) +{ + int x1 = x - v->marker_size; + int y1 = y - v->marker_size; + int x2 = x + v->marker_size; + int y2 = y + v->marker_size; + + if( x1 < 0 ) x1 = 0; else if ( x1 > w ) x1 = w; + if( y1 < 0 ) y1 = 0; else if ( y1 > h ) y1 = h; + if( x2 < 0 ) x2 = 0; else if ( x2 > w ) x2 = w; + if( y2 < 0 ) y2 = 0; else if ( y2 > h ) y2 = h; + + unsigned int i,j; + for( j = x1; j < x2 ; j ++ ) + plane[ y1 * w + j ] = v->grid_val; + + for( i = y1; i < y2; i ++ ) + { + plane[ i * w + x1 ] = v->grid_val; + plane[ i * w + x2 ] = v->grid_val; + } + + for( j = x1; j < x2 ; j ++ ) + plane[ y2 * w + j ] = v->grid_val; + +} + +static void viewport_draw_grid(viewport_t *v, int width, int height, uint8_t *plane ) +{ + int x,y; + grid_t *grid = v->grid; + int k = 0; + int n = v->grid_width * v->grid_height; + int j = 0; + for( y = 0; y < v->grid_height; y ++) { + k = y * v->grid_width; + j = k + v->grid_width-1; + viewport_line( plane, grid[k].x, grid[k].y, + grid[j].x, grid[j].y, + width,height, + 170); + } + + k = 0; + n = (v->grid_height-1) * v->grid_width; + for( x = 0; x < v->grid_width; x ++ ) + { + k = x; + j = n + x; + viewport_line( plane, grid[k].x, grid[k].y, + grid[j].x, grid[j].y, + width,height, + 170); + } +} + +static void viewport_draw_points(viewport_t *v, int width, int height, uint8_t *plane ) +{ + int k; + for(k = 0; k < (v->grid_width*v->grid_height); k ++ ) + { + int x=v->grid[k].x; + int y=v->grid[k].y; + if( x >= 0 && y >= 0 && x < width && y < height ) + plane[y * width + x] = v->grid_val; + } +} +static void viewport_compute_grid( viewport_t *v ) +{ + int i; + int k = 0; + int gw = v->w/ v->grid_resolution; + int gh = v->h/v->grid_resolution; + v->grid_width = gw; + v->grid_height = gh; + + int x,y; + if(v->grid) { + free(v->grid); + v->grid = NULL; + } + if(!v->grid) { + v->grid = (grid_t*) vj_malloc(sizeof(grid_t) * gw *gh); + } + grid_t *grid = v->grid; + + for(y = 0; y < gh; y ++ ) + for( x = 0; x < gw; x ++ ) { + point_map_int( v->M, x * v->grid_resolution, + y * v->grid_resolution,&(grid[k].x), &(grid[k].y)); + k++; + } +} + + +void viewport_set_marker( void *data, int status ) +{ + viewport_t *v = (viewport_t*) data; + v->snap_marker = status; + //v->marker_size = 1; +} + +static void viewport_draw_col( void *data, uint8_t *plane, uint8_t *u, uint8_t *V ) +{ + viewport_t *v = (viewport_t*) data; + int width = v->w; + int height = v->h; + + float wx =(float) v->w / 100.0f; + float wy =(float) v->h / 100.0f; + + int fx1 = (int)( msx(v,v->x1) *wx ); + int fy1 = (int)( msy(v,v->y1) *wy ); + int fx2 = (int)( msx(v,v->x2) *wx ); + int fy2 = (int)( msy(v,v->y2) *wy ); + int fx3 = (int)( msx(v,v->x3) *wx ); + int fy3 = (int)( msy(v,v->y3) *wy ); + int fx4 = (int)( msx(v,v->x4) *wx ); + int fy4 = (int)( msy(v,v->y4) *wy ); + + + + const uint8_t p = v->grid_val; + const uint8_t uv = 128; + + if(v->grid) + switch(v->grid_mode) + { + case 2: + viewport_draw_grid(v,width,height,plane); + break; + case 1: + viewport_draw_points(v,width,height,plane); + break; + } + + + viewport_line( plane, fx1, fy1, fx2,fy2,width,height, p); + viewport_line( plane, fx1, fy1, fx4,fy4,width,height, p ); + viewport_line( plane, fx4, fy4, fx3,fy3,width,height, p ); + viewport_line( plane, fx2, fy2, fx3,fy3,width,height, p ); + + //@ Project rectangle in v->w * v->h , but scaled to size of >sw >sh + ui_t *ui = v->ui; + int cx = v->w / 2; + int cy = v->h / 2; + int dx = cx - ( ui->sw / 2 ); + int dy = cy - ( ui->sh / 2 ); + float s = (float) v->w / (float) v->ui->sw; + float sy = (float) v->h / (float) v->ui->sh; + int vx0 = (v->x0 / s) + dx; + int vy0 = (v->y0 / sy) + dy; + int vw0 = v->w0 / s; + int vh0 = v->h0 / sy; + + viewport_line( plane, v->x0, v->y0, v->x0 + v->w0, v->y0, width,height, 110); + viewport_line( plane, v->x0+v->w0, v->y0, v->x0 + v->w0, v->y0 + v->h0, width,height, 110 ); + viewport_line( plane, v->x0 + v->w0, v->y0 + v->h0, v->x0, v->y0 + v->h0, width,height, 110 ); + viewport_line( plane, v->x0, v->y0 +v->h0, v->x0, v->y0, width,height, 110); + + +//* Projection quad + viewport_line( plane, vx0, vy0, vx0 + vw0, vy0, width,height, 65); + viewport_line( plane, vx0+vw0, vy0, vx0 + vw0, vy0 + vh0, width,height, 65 ); + viewport_line( plane, vx0 + vw0, vy0 + vh0, vx0, vy0 + vh0, width,height, 65 ); + viewport_line( plane, vx0, vy0 +vh0, vx0, vy0, width,height, 65); + + + draw_point( plane, fx1,fy1, width,height, v->users[0],p ); + draw_point( plane, fx2,fy2, width,height, v->users[1],p ); + draw_point( plane, fx3,fy3, width,height, v->users[2],p ); + draw_point( plane, fx4,fy4, width,height, v->users[3],p ); + + int mx = v->usermouse[0] * wx; + int my = v->usermouse[1] * wy; + + viewport_draw_marker(v, mx,my,width,height,plane ); + + + if( mx >= 0 && my >= 0 && mx <= width && my < height ) + { + if( mx >= 0 && my >= 0 && mx < width && my < height ) + { + if( abs(v->grid_val - plane[my*width+mx]) < 32 ) + plane[my*width+mx] = 0xff - plane[my*width+mx]; + else + plane[my * width + mx] = v->grid_val; + } + } +} + +int viewport_render_ssm(void *vdata ) +{ + viewport_t *v = (viewport_t*) vdata; + + if( v->disable || v->user_ui) + return 0; + + return 1; +} + +void viewport_draw_interface_color( void *vdata, uint8_t *img[3] ) +{ + viewport_t *v = (viewport_t*) vdata; + viewport_translate_frame( v, img[0] ); + viewport_draw_col( v, img[0],img[1],img[2] ); +} + + +void viewport_produce_full_img( void *vdata, uint8_t *img[3], uint8_t *out_img[3] ) +{ + viewport_t *v = (viewport_t*) vdata; + const int len = v->w * v->h; + register const int w = v->w; + register uint32_t i,j,n; + const int32_t *map = v->map; + uint8_t *inY = img[0]; + uint8_t *inU = img[1]; + uint8_t *inV = img[2]; + uint8_t *outY = out_img[0]; + uint8_t *outU = out_img[1]; + uint8_t *outV = out_img[2]; + inY[len+1] = 0; + inU[len+1] = 128; + inV[len+1] = 128; + + register const int32_t tx1 = v->ttx1; + register const int32_t tx2 = v->ttx2; + register const int32_t ty1 = v->tty1; + register const int32_t ty2 = v->tty2; + int x,y; + + y = ty1 * w; + veejay_memset( outY,0,len); + veejay_memset( outU,128,len); + veejay_memset( outV,128,len); + + for( y = ty1; y < ty2; y ++ ) + { + for( x = tx1; x < tx2 ; x ++ ) + { + i = y * w + x; + n = map[i]; + outY[i] = inY[n]; + outU[i] = inU[n]; + outV[i] = inV[n]; + } + } + y = (v->h - ty2 ) * w; + x = ty2 * w; +} + +void viewport_produce_bw_img( void *vdata, uint8_t *img[3], uint8_t *out_img[3], int Yonly) +{ + if( !Yonly ) { + viewport_produce_full_img( vdata, img, out_img ); + return; + } + + + + viewport_t *v = (viewport_t*) vdata; + const int len = v->w * v->h; + register const int w = v->w; + register uint32_t i,j,n; + const int32_t *map = v->map; + uint8_t *inY = img[0]; + uint8_t *outY = out_img[0]; + inY[len+1] = 0; + + register const int32_t tx1 = v->ttx1; + register const int32_t tx2 = v->ttx2; + register const int32_t ty1 = v->tty1; + register const int32_t ty2 = v->tty2; + +#ifdef STRICT_CHECKING + assert(tx1>= 0 ); + assert(tx2>= 0 ); + assert(ty1>= 0 ); + assert(ty2>= 0 ); +#endif + + int x,y; + y = ty1 * w; + veejay_memset( outY,0,len); + + for( y = ty1; y < ty2; y ++ ) + { + for( x = tx1; x < tx2 ; x ++ ) + { + i = y * w + x; + n = map[i]; + outY[i] = inY[n]; + } + } + y = (v->h - ty2 ) * w; + x = ty2 * w; +} + +#define pack_yuyv_4pixel( y0,u0,y1,v0 ) (\ + ( (int) y0 ) & 0xff ) +\ + ( (((int) (u0>>1) ) & 0xff) << 8) +\ + ( ((((int) y1) & 0xff) << 16 )) +\ + ( ((((int) (v0>>1)) & 0xff) << 24 )) + +#define pack_yuyv_pixel( y0,u0,u1,y1,v0,v1 ) (\ + ( (int) y0 ) & 0xff ) +\ + ( (((int) ((u0+u1)>>1) ) & 0xff) << 8) +\ + ( ((((int) y1) & 0xff) << 16 )) +\ + ( ((((int) ((v0+v1)>>1)) & 0xff) << 24 )) + +void viewport_produce_full_img_yuyv( void *vdata, uint8_t *img[3], uint8_t *out_img ) +{ + viewport_t *v = (viewport_t*) vdata; + const int len = v->w * v->h; + const int32_t *map = v->map; + register uint8_t *inY = img[0]; + register uint8_t *inU = img[1]; + register uint8_t *inV = img[2]; + register uint32_t *plane_yuyv = (uint32_t*)out_img; + register const int32_t tx1 = v->ttx1; + register const int32_t tx2 = v->ttx2; + register const int32_t ty1 = v->tty1; + register const int32_t ty2 = v->tty2; + register const int w = v->w; + register const int h = v->h; + register const int uw = v->w >> 1; + register uint32_t i,x,y; + register int32_t n,m; + + inY[len+1] = 0; // "out of range" pixel value + inU[len+1] = 128; + inV[len+1] = 128; + + yuyv_plane_clear( len*2, plane_yuyv); + +#if defined (HAVE_ASM_MMX) || defined (HAVE_ASM_SSE ) + fast_memset_finish(); // finish yuyv_plane_clear +#endif + __builtin_prefetch( inY, 0 ,3); + __builtin_prefetch( inU, 0 ,3); + __builtin_prefetch( inV, 0 ,3); + __builtin_prefetch( plane_yuyv, 1,3); + + for( y = ty1 ; y < ty2; y ++ ) + { + for( x = tx1; x < tx2; x += 2 ) + { // 4 YUYV pixels out, 8 Y in, 16 UV in + i = y * w ; + n = map[ i + x ]; + m = map[ i + x + 1]; + + plane_yuyv[y * uw + ( (x+1)>>1)] = pack_yuyv_pixel( inY[n], inU[n], inU[m], + inY[m], inV[n], inV[m] ); + + } + } + +} + +void viewport_produce_full_img_packed( void *vdata, uint8_t *img[3], uint8_t *out_img ) +{ + viewport_t *v = (viewport_t*) vdata; + const int len = v->w * v->h; + const int32_t *map = v->map; + uint8_t *inY = img[0]; + uint8_t *inU = img[1]; + uint8_t *inV = img[2]; + uint8_t *outYUYV = out_img; + + inY[len+1] = 0; + inU[len+1] = 128; + inV[len+1] = 128; + + register const int32_t tx1 = v->ttx1; + register const int32_t tx2 = v->ttx2; + register const int32_t ty1 = v->tty1; + register const int32_t ty2 = v->tty2; + register const int w = v->w; + register uint32_t n,i,x,y,m; + + // clear the yuyv plane (black) + y = ty1 * w; + yuyv_plane_clear( len*3, out_img); //@optimize FIXME + +#if defined (HAVE_ASM_MMX) || defined (HAVE_ASM_SSE ) + fast_memset_finish(); // finish yuyv_plane_clear +#endif + + for( y = ty1 ; y < ty2; y ++ ) + { + for( x = tx1; x < tx2; x ++ ) + { + i = y * w + x; + n = map[ i ]; + outYUYV[3 * i ] = inY[n]; + outYUYV[3 * i + 1 ] = inV[n]; + outYUYV[3 * i + 3 ] = inU[n]; + } + } +} + + +void viewport_render( void *vdata, uint8_t *in[3], uint8_t *out[3],int width, int height, int uv_len ) +{ + viewport_t *v = (viewport_t*) vdata; + + if( v->disable ) + return; + + int len = (width * height); + + if(! v->user_ui ) + { + const int len = v->w * v->h; + const int w = v->w; + register uint32_t i,j,n,block; + const int32_t *map = v->map; + uint8_t *inY = in[0]; + uint8_t *inU = in[1]; + uint8_t *inV = in[2]; + uint8_t *outY = out[0]; + uint8_t *outU = out[1]; + uint8_t *outV = out[2]; + + inY[len+1] = 0; + inU[len+1] = 128; + inV[len+1] = 128; + + for( i = 0; i < len ; i += v->w ) + { + for( j = 0; j < w; j += 4 ) + { + n = map[i + j]; + outY[i + j ] = inY[n]; + outU[i + j ] = inU[n]; + outV[i + j ] = inV[n]; + n = map[ i + j + 1 ]; + outY[ i + 1 + j ] = inY[n]; + outU[ i + 1 + j ] = inU[n]; + outV[ i + 1 + j ] = inV[n]; + n = map[ i + j + 2 ]; + outY[ i + 2 + j ] = inY[n]; + outU[ i + 2 + j ] = inU[n]; + outV[ i + 2 + j ] = inV[n]; + n = map[ i + j + 3 ]; + outY[ i + 3 + j ] = inY[n]; + outU[ i + 3 + j ] = inU[n]; + outV[ i + 3 + j ] = inV[n]; + } + for( ; j < w; j ++ ) + { + n = map[i+j]; + outY[i+j] = inY[n]; + outU[i+j] = inU[n]; + outV[i+j] = inV[n]; + } + } + } +} + +void viewport_render_dynamic( void *vdata, uint8_t *in[3], uint8_t *out[3],int width, int height ) +{ + viewport_t *v = (viewport_t*) vdata; + + viewport_process_dynamic( v, in,out ); + +} + +void *viewport_fx_init_map( int wid, int hei, int x1, int y1, + int x2, int y2, int x3, int y3, int x4, int y4) +{ + viewport_t *v = (viewport_t*) vj_calloc(sizeof(viewport_t)); + + float fracx = (float) wid / 100.0f; + float fracy = (float) hei / 100.0f; + + v->x1 = x1 / fracx; + v->y1 = y1 / fracy; + v->x2 = x2 / fracx; + v->y2 = y2 / fracy; + v->x3 = x3 / fracx; + v->y3 = y3 / fracy; + v->x4 = x4 / fracx; + v->y4 = y4 / fracy; + + int res = viewport_configure (v, + v->x1, v->y1, + v->x2, v->y2, + v->x3, v->y3, + v->x4, v->y4, + 0,0, + wid,hei, + wid,hei, + 0, + 0xff, + 32 ); + + v->user_ui = 0; + + if(! res ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations"); + viewport_destroy( v ); + return NULL; + } + + + return (void*)v; +} + +int viewport_get_mode( void *vv ) { + viewport_t *v = (viewport_t*) vv; + return v->user_ui; +} + +void *viewport_fx_init(int type, int wid, int hei, int x, int y, int zoom, int dir) +{ + viewport_t *v = (viewport_t*) vj_calloc(sizeof(viewport_t)); + + float fracx = (float) wid; + float fracy = (float) hei; + + fracx *= 0.01f; + fracy *= 0.01f; + + if( type == VP_QUADZOOM ) + { + float cx = (float) x; + float cy = (float) y; + + cx = cx / fracx; + cy = cy / fracy; + + float w = 1.0 * zoom * 0.5; + float h = 1.0 * zoom * 0.5; + + v->x1 = cx - w; + v->y1 = cy - h; + v->x2 = cx + w; + v->y2 = cy - h; + v->x3 = cx + w; + v->y3 = cy + h; + v->x4 = cx - w; + v->y4 = cy + h; + } + + int res = viewport_configure (v, + v->x1, v->y1, + v->x2, v->y2, + v->x3, v->y3, + v->x4, v->y4, + 0,0, + wid,hei, + wid,hei, + dir, + 0xff, + wid/32 ); + + v->user_ui = 0; + + if(! res ) + { + veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations"); + viewport_destroy( v ); + return NULL; + } + + + return (void*)v; +} + + +static void flxml( xmlDocPtr doc, xmlNodePtr cur, float *dst , const xmlChar *name) { + if(!xmlStrcmp(cur->name, name ) ) { + xmlChar *xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode,1); + unsigned char *chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + *dst = (float) atof(chTemp); + free(chTemp); + } + free(xmlTemp); + } +} +static void ixml( xmlDocPtr doc, xmlNodePtr cur, int *dst , const xmlChar *name) { + if(!xmlStrcmp(cur->name, name ) ) { + xmlChar *xmlTemp = xmlNodeListGetString(doc, cur->xmlChildrenNode,1); + unsigned char *chTemp = UTF8toLAT1(xmlTemp); + if (chTemp) { + *dst = (int) atoi(chTemp); + free(chTemp); + } + free(xmlTemp); + } +} +void *viewport_load_xml(xmlDocPtr doc, xmlNodePtr cur, void *vv ) +{ + viewport_t *vc = (viewport_t*) vv; + if(!vc || !cur) return NULL; + + viewport_config_t *c = (viewport_config_t*) vj_calloc(sizeof(viewport_config_t)); + //effectIndex++; + while( cur != NULL ) { + flxml( doc,cur,&(c->x1),"x1" ); + flxml( doc,cur,&(c->x2),"x2" ); + flxml( doc,cur,&(c->y1),"y1" ); + flxml( doc,cur,&(c->y2),"y2" ); + flxml( doc,cur,&(c->x3),"x3" ); + flxml( doc,cur,&(c->x4),"x4" ); + flxml( doc,cur,&(c->y3),"y3" ); + flxml( doc,cur,&(c->y4),"y4" ); + ixml( doc,cur,&(c->x0),"x0" ); + ixml( doc,cur,&(c->w0),"w0" ); + ixml( doc,cur,&(c->y0),"y0" ); + ixml( doc,cur,&(c->h0),"h0" ); + ixml( doc,cur,&(c->saved_w),"saved_w" ); + ixml( doc,cur,&(c->saved_h),"saved_h" ); + ixml( doc,cur,&(c->reverse),"reverse" ); + ixml( doc,cur,&(c->grid_color),"grid_color" ); + ixml( doc,cur,&(c->grid_resolution),"grid_resolution" ); + ixml( doc,cur,&(c->composite_mode), "compositemode"); + ixml( doc,cur,&(c->colormode), "colormode"); + ixml( doc,cur,&(c->marker_size), "markersize"); + ixml( doc,cur,&(c->grid_mode), "gridmode"); + cur = cur->next; + } + return (void*) c; +} + +void viewport_save_xml(xmlNodePtr parent,void *vv) +{ + viewport_config_t *vc = (viewport_config_t*) vv; + if(!vc) return; + + xmlNodePtr node = xmlNewChild(parent, NULL, + (const xmlChar*) "calibration", + NULL ); + + char buffer[100]; + xmlNodePtr childnode; + + sprintf(buffer, "%f", vc->x1); + xmlNewChild(node, NULL, (const xmlChar *) "x1", + (const xmlChar *) buffer); + sprintf(buffer, "%f", vc->y1); + xmlNewChild(node, NULL, (const xmlChar *) "y1", + (const xmlChar *) buffer); + + sprintf(buffer, "%f", vc->x2); + xmlNewChild(node, NULL, (const xmlChar *) "x2", + (const xmlChar *) buffer); + sprintf(buffer, "%f", vc->y2); + xmlNewChild(node, NULL, (const xmlChar *) "y2", + (const xmlChar *) buffer); + + sprintf(buffer, "%f", vc->x3); + xmlNewChild(node, NULL, (const xmlChar *) "x3", + (const xmlChar *) buffer); + sprintf(buffer, "%f", vc->y3); + xmlNewChild(node, NULL, (const xmlChar *) "y3", + (const xmlChar *) buffer); + + sprintf(buffer, "%f", vc->x4); + xmlNewChild(node, NULL, (const xmlChar *) "x4", + (const xmlChar *) buffer); + sprintf(buffer, "%f", vc->y4); + xmlNewChild(node, NULL, (const xmlChar *) "y4", + (const xmlChar *) buffer); + + sprintf(buffer, "%d", vc->saved_w); + xmlNewChild(node, NULL, (const xmlChar *) "saved_w", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->saved_h); + xmlNewChild(node, NULL, (const xmlChar *) "saved_h", + (const xmlChar *) buffer); + + sprintf(buffer, "%d", vc->reverse); + xmlNewChild(node, NULL, (const xmlChar *) "reverse", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->grid_color); + xmlNewChild(node, NULL, (const xmlChar *) "grid_color", + (const xmlChar *) buffer); + + sprintf(buffer, "%d", vc->grid_resolution); + xmlNewChild(node, NULL, (const xmlChar *) "grid_resolution", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->x0); + xmlNewChild(node, NULL, (const xmlChar *) "x0", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->y0); + xmlNewChild(node, NULL, (const xmlChar *) "y0", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->w0); + xmlNewChild(node, NULL, (const xmlChar *) "w0", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->h0); + xmlNewChild(node, NULL, (const xmlChar *) "h0", + (const xmlChar *) buffer); + + sprintf(buffer, "%d", vc->colormode); + xmlNewChild(node, NULL, (const xmlChar *) "colormode", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->composite_mode); + xmlNewChild(node, NULL, (const xmlChar *) "compositemode", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->marker_size); + xmlNewChild(node, NULL, (const xmlChar *) "markersize", + (const xmlChar *) buffer); + sprintf(buffer, "%d", vc->grid_mode); + xmlNewChild(node, NULL, (const xmlChar *) "gridmode", + (const xmlChar *) buffer); +} diff --git a/branches/V-1.5.3/veejay-server/veejay/vj-viewport.h b/branches/V-1.5.3/veejay-server/veejay/vj-viewport.h new file mode 100644 index 00000000..e46ac929 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vj-viewport.h @@ -0,0 +1,64 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + */ +#ifndef VIEWPORT_H +#define VIEWPORT_H + +/* Viewport component for FX */ +#define VP_QUADZOOM 1 +void viewport_process_dynamic( void *data, uint8_t *in[3], uint8_t *out[3] ); +void viewport_process_dynamic_map( void *data, uint8_t *in[3], uint8_t *out[3], uint32_t *map, int feather ); +void *viewport_fx_init( int type, int wid, int hei, int x, int y, int zoom, int dir ); +void viewport_update_from(void *vv, void *bb); +void *viewport_clone(void *iv, int new_w, int new_h ); +void viewport_set_ui(void *vv, int value ); +/* The viewport */ +int viewport_active( void *data ); +int viewport_render_ssm(void *vdata ); +void viewport_render( void *data, uint8_t *in[3], uint8_t *out[3], int width, int height,int uv_len ); +int viewport_external_mouse( void *data, uint8_t *in[3],int sx, int sy, int button, int frontback, int w, int h ); +char *viewport_get_help(void *data); +char *viewport_get_my_status(void *v); +void viewport_clone_parameters( void *src , void *dst ); +void *viewport_init(int x0, int y0, int w0, int h0, int w, int h,int iw, int ih, const char *dir, int *enable, int *frontback, int mode); +int viewport_active( void *data ); +void viewport_destroy( void *data ); +void vewport_draw_interface_color( void *vdata, uint8_t *img[3] ); +void viewport_produce_bw_img( void *vdata, uint8_t *img[3], uint8_t *out_img[3], int Yonly); +void viewport_produce_full_img_yuyv( void *vdata, uint8_t *img[3], uint8_t *out_img ); +void viewport_draw_interface_color( void *vdata, uint8_t *img[3] ); +void viewport_set_marker( void *vdata, int status ); +void viewport_projection_inc( void *data, int incr , int w, int h ); +void viewport_transform_coords( void *data, void *coords, int n, int blob_id, int cx, int cy ,int w, int h, int num_objects,uint8_t *plane); +void viewport_dummy_send( void *data ); +int *viewport_event_get_projection(void *data, int scale); +int viewport_event_set_projection(void *data, float x, float y, int num, int fb); +void viewport_push_frame(void *data, int w, int h, uint8_t *Y, uint8_t *U, uint8_t *V ); +void viewport_reconfigure(void *vv); +int viewport_get_mode(void *vv); +int viewport_reconfigure_from_config(void *vv, void *vc); +void viewport_set_composite(void *vc, int mode, int colormode); +int viewport_get_color_mode_from_config(void *vc); +int viewport_get_composite_mode_from_config(void *vc); +void *viewport_get_configuration(void *vv ); +int viewport_finetune_coord(void *data, int screen_width, int screen_height,int inc_x,int inc_y); +void viewport_set_initial_active( void *vv, int status ); +int viewport_get_initial_active( void *vv ); +#endif + diff --git a/branches/V-1.5.3/veejay-server/veejay/vjkf.c b/branches/V-1.5.3/veejay-server/veejay/vjkf.c new file mode 100644 index 00000000..b1739972 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vjkf.c @@ -0,0 +1,371 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg < elburg@hio.hen.nl> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + * + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_XML2 +#include +#include +#endif +#ifdef STRICT_CHECKING +#include +#endif +/* veejay server stores keyframes + * + * + * + * keyframe format: + * ( [frame_num1][value1][frame_num2][value2] ... [frame_numN][valueN] ) + * + * + */ + +#include + +static char *keyframe_id( int p_id, int n_frame ) +{ + char tmp[32]; + sprintf(tmp, "FX%d_%d",p_id,n_frame ); + return strdup(tmp); +} + +static char *extract_( const char *prefix , int p_id ) +{ + char tmp[100]; + sprintf(tmp, "%s_p%d",prefix,p_id); + return strdup(tmp); +} + +unsigned char *keyframe_pack( void *port, int parameter_id, int entry_id, int *rlen ) +{ + int i,k=0; + char *result = NULL; + + + int start = 0, end = 0, type =0; + + char *k_s = extract_( "start", parameter_id ); + char *k_e = extract_( "end", parameter_id ); + char *k_t = extract_( "type", parameter_id ); + + if( vevo_property_get( port, k_s, 0, &start ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return NULL; + } + if( vevo_property_get( port, k_e, 0, &end ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return NULL; + } + if( vevo_property_get( port, k_t, 0, &type ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return NULL; + } + + free(k_s); + free(k_e); + free(k_t); + + int len = end - start + 1; + + result = vj_calloc( (len*4) + 23 ); + + sprintf(result,"key%02d%02d%08d%08d%02d", entry_id,parameter_id,start, end, type ); + + unsigned char *out = result + 25; + + for( i = start; i < end; i ++ ) + { + char *key = keyframe_id( parameter_id, i ); + int value = 0; + + if(vevo_property_get(port, key, 0, &value )==VEVO_NO_ERROR) + { + unsigned char *buf = out + (4 * k); + + buf[0] = ( value ) & 0xff; + buf[1] = (value >> 8) & 0xff; + buf[2] = (value >> 16) & 0xff; + buf[3] = (value >> 24) & 0xff; + k++; + } + else + { + unsigned char *buf = out + (4 * k); + buf[0] = 0; + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + k++; + } + + free(key); + } + + *rlen = 25 + (4 * k); + + veejay_msg(VEEJAY_MSG_DEBUG, "KF %p pack: range=%d-%d, FX entry %d, P%d, type %d", + port,start,end, entry_id,parameter_id, type ); + + return result; +} + +int keyframe_unpack( unsigned char *in, int len, int *entry, int lookup, int is_sample ) +{ + int i; + int parameter_id = 0; + int start = 0, end = 0, type = 0; + int fx_entry = 0; + int n = sscanf( in, "key%2d%2d%8d%8d%2d", &fx_entry,¶meter_id, &start, &end,&type ); + + if(n != 5 ) + { + veejay_msg(0, "Unable to unpack parameter_id,start,end"); + return 0; + } + + void *port = (is_sample ? sample_get_kf_port( lookup, fx_entry ) : vj_tag_get_kf_port( lookup, fx_entry )); + + in += (25); + + for(i = start ; i < end; i ++ ) + { + unsigned char *ptr = in + (i * 4); + int value = + ( ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24) ); + char *key = keyframe_id( parameter_id, i ); + vevo_property_set( port, key, VEVO_ATOM_TYPE_INT, 1, &value ); + free(key); + } + + char *k_s = extract_ ( "start", parameter_id ); + char *k_e = extract_ ( "end", parameter_id ); + char *k_t = extract_ ( "type", parameter_id ); + + vevo_property_set( port, k_s, VEVO_ATOM_TYPE_INT,1, &start ); + vevo_property_set( port, k_e, VEVO_ATOM_TYPE_INT,1, &end ); + vevo_property_set( port, k_t, VEVO_ATOM_TYPE_INT,1, &type ); + + free(k_s); + free(k_e); + free(k_t); + + *entry = fx_entry; + + return 1; +} + +int keyframe_get_tokens( void *port, int parameter_id, int *start, int *end, int *type ) +{ + char *k_s = extract_ ( "start", parameter_id ); + char *k_e = extract_ ( "end", parameter_id ); + char *k_t = extract_ ( "type", parameter_id ); + + if( vevo_property_get( port, k_s, 0, start ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return 0; + } + if( vevo_property_get( port, "end", 0, end ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return 0; + } + if( vevo_property_get( port, "type", 0, type ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return 0; + } + free(k_s); + free(k_e); + free(k_t); + + + return 1; +} + + + + +int keyframe_xml_pack( xmlNodePtr node, void *port, int parameter_id ) +{ + int i,k=0; + unsigned char *result = NULL; + int n_items = 0; + + int start = 0, end = 0, type = 0; + + char *k_s = extract_ ( "start", parameter_id ); + char *k_e = extract_ ( "end", parameter_id ); + char *k_t = extract_ ( "type", parameter_id ); + + + if( vevo_property_get( port, k_s, 0, &start ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return 0; + } + if( vevo_property_get( port, k_e, 0, &end ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e); free(k_t); + return 0; + } + if( vevo_property_get( port, k_t, 0, &type ) != VEVO_NO_ERROR ) + { + free(k_s); free(k_e);free(k_t); + return 0; + } + + char xmlbuf[100]; + + snprintf(xmlbuf, 100,"%d", start ); + xmlNewChild(node, NULL, (const xmlChar*) k_s, xmlbuf ); + snprintf(xmlbuf, 100,"%d", end ); + xmlNewChild(node, NULL, (const xmlChar*) k_e, xmlbuf ); + snprintf(xmlbuf, 100,"%d", type ); + xmlNewChild(node, NULL, (const xmlChar*) k_t, xmlbuf ); + + for( i = start; i < end; i ++ ) + { + char *key = keyframe_id( parameter_id, i ); + int value = 0; + + if(vevo_property_get(port, key, 0, &value )==VEVO_NO_ERROR) + { + sprintf(xmlbuf, "%d %d", parameter_id,value ); + xmlNewChild(node, NULL, (const xmlChar*) "value", xmlbuf); + } + free(key); + } + + free( k_s); + free( k_e); + free( k_t); + + return 1; +} +static int get_xml_int( xmlDocPtr doc, xmlNodePtr node ) +{ + xmlChar *tmp = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 ); + char *ch = UTF8toLAT1( tmp ); + int res = 0; + if( ch ) + { + res = atoi( ch ); + free(ch); + } + if(tmp) + free(tmp); + return res; +} +static int get_xml_2int( xmlDocPtr doc, xmlNodePtr node, int *second ) +{ + xmlChar *tmp = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 ); + char *ch = UTF8toLAT1( tmp ); + int res = 0; + if( ch ) + { + sscanf( ch, "%d %d", &res, second ); + free(ch); + } + if(tmp) + free(tmp); + return res; +} + +int keyframe_xml_unpack( xmlDocPtr doc, xmlNodePtr node, void *port ) +{ + int i; + int n_frames; + int parameter_id = 0; + int start = 0 , end = 0, type = 0; + int frame = 0; + int nodes = 0; + int res = 0; + if(!node) + return 0; + + while( node != NULL ) + { + if( !xmlStrncmp(node->name, (const xmlChar*) "start",4 )) + { + start = get_xml_int( doc, node ); + vevo_property_set( port, node->name, VEVO_ATOM_TYPE_INT,1,&start); + nodes ++; + } + else if ( !xmlStrncmp(node->name, (const xmlChar*) "end",3 )) + { + end = get_xml_int( doc, node ); + vevo_property_set(port, node->name, VEVO_ATOM_TYPE_INT,1,&end); + } + else if ( !xmlStrncmp(node->name, (const xmlChar*) "type",4 )) + { + type = get_xml_int(doc,node); + vevo_property_set(port,node->name, VEVO_ATOM_TYPE_INT,1,&type); + } + else if ( !xmlStrcmp(node->name, (const xmlChar*) "value" )) + { + int val = 0; + int pid = get_xml_2int( doc, node, &val); + char *key = keyframe_id( pid, start + frame ); + + + vevo_property_set( port, key, VEVO_ATOM_TYPE_INT, 1, &val ); + free(key); + + frame ++; + if( frame > end ) + end = frame; + } + + node = node->next; + } + + veejay_msg(VEEJAY_MSG_DEBUG, "KF loaded: %d-%d with %d values",start,end, frame ); + + return nodes; +} + + +int get_keyframe_value(void *port, int n_frame, int parameter_id, int *result ) +{ + char *key = keyframe_id( parameter_id, n_frame ); + + int error = vevo_property_get( port, key, 0, result ); + if( error != VEVO_NO_ERROR ) + return 0; + return 1; +} + diff --git a/branches/V-1.5.3/veejay-server/veejay/vjkf.h b/branches/V-1.5.3/veejay-server/veejay/vjkf.h new file mode 100644 index 00000000..b5065b74 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/vjkf.h @@ -0,0 +1,36 @@ +/* + * Linux VeeJay + * + * Copyright(C)2002-2008 Niels Elburg < elburg@hio.hen.nl> + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA. + * + * + */ +#ifndef VJKF_H +#define VJKF_H +unsigned char *keyframe_pack( void *port, int parameter_id, int entry_id, int *rlen ); + +int keyframe_unpack( unsigned char *in, int len, int *entry, int lookup, int tag ); + +int keyframe_get_tokens( void *port, int parameter_id, int *start, int *end, int *type ); + + +int keyframe_xml_pack( xmlNodePtr node, void *port, int parameter_id ); + +int keyframe_xml_unpack( xmlDocPtr doc, xmlNodePtr node, void *port ); + +int get_keyframe_value(void *port, int n_frame, int parameter_id, int *result ); +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/x11misc.c b/branches/V-1.5.3/veejay-server/veejay/x11misc.c new file mode 100644 index 00000000..c198fd06 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/x11misc.c @@ -0,0 +1,158 @@ +/* veejay - Linux VeeJay + * (C) 2002-2006 Niels Elburg + * + * + * 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 +#ifndef X_DISPLAY_MISSING +#include +#include +#include +#include + +#ifdef HAVE_XINERAMA +#include +#endif + +#define DECO (1L << 1) + +static int screen_saver_[4]; + +#ifdef HAVE_XDPMS +static CARD16 state_; +static BOOL onoff_; +#endif + +void x11_misc_init() +{ + memset(&screen_saver_,0, sizeof(screen_saver_)); +#ifdef HAVE_XDPMS + memset(&state_, 0,sizeof(state_)); + memset(&onoff_, 0,sizeof(onoff_)); +#endif +} + +void x11_disable_screensaver( void *display ) +{ + Display *d = (Display*) display; + +// XGetScreenSaver( d, &screen_saver_[0], &screen_saver_[1], +// &screen_saver_[2], &screen_saver_[3] ); + + if( screen_saver_[0] ) + { + //XSetScreenSaver( d, 0, screen_saver_[1], screen_saver_[2],screen_saver_[3] ); + } + +#ifdef HAVE_XDPMS + int n = 0; + if( DPMSQueryExtension( d, &n, &n ) ) + { + DPMSInfo( d, &state_, &ononff_ ); + DPMSDisable( d ); + } +#endif +} + +void x11_enable_screensaver( void *display ) +{ + Display *d = (Display*) display; + + if( screen_saver_[0] ) + { + // XSetScreenSaver( d, screen_saver_[0],screen_saver_[1], + // screen_saver_[2],screen_saver_[3] ); + } +#ifdef HAVE_XDPMS + int n = 0; + if( DPMSQueryExtension( d, &n, &n ) ) + { + if( onoff_ ) + DPMSEnable( d ); + } +#endif +} + +void x11_misc_set_border( void *display, void *window, int status ) +{ + +} + +static int xinerama_screen_ = -1; +static int xinerama_x_ = 0; +static int xinerama_y_ = 0; +static int xinerama_user_selected_ = 0; +static int screen_w_ = 0; +static int screen_h_ = 0; + +void x11_move( void *display, void *window ) +{ + Display *d = (Display*) display; + Window *w = (Window*) window; +#ifdef HAVE_XINERAMA + if( XineramaIsActive( d ) ) + { + //XMoveWindow( d, w, xinerama_x_, xinerama_y_ ); + } +#endif +} + +void x11_user_select( int n ) +{ + xinerama_user_selected_ = n; +} + +void x11_info(void *display) +{ + Display *d = (Display*) display; +#ifdef HAVE_XINERAMA + + int dis1,dis2; + + if( XineramaIsActive( d ) && + XineramaQueryExtension( d, &dis1,&dis2) ) + { + veejay_msg(VEEJAY_MSG_INFO, "\tUsing XFree Xinerama extension"); + + int n = 0; + XineramaScreenInfo *screens = + XineramaQueryScreens( d, &n ); + + if( xinerama_user_selected_ < 0 || + xinerama_user_selected_ >= n ) + { + veejay_msg(VEEJAY_MSG_ERROR, "\tRequested screen number invalid"); + xinerama_user_selected_ = 0; + } + + + xinerama_x_ = screens[ xinerama_user_selected_ ].x_org; + xinerama_y_ = screens[ xinerama_user_selected_ ].y_org; + screen_w_ = screens[ xinerama_user_selected_ ].width; + screen_h_ = screens[ xinerama_user_selected_ ].height; + + veejay_msg(VEEJAY_MSG_INFO, "\tUsing screen %d : %dx%d+%dx%d", + xinerama_user_selected_, screen_w_, screen_h_, xinerama_x_, xinerama_y_ ); + + // XFree( screens ); + } +#endif +} + +#endif diff --git a/branches/V-1.5.3/veejay-server/veejay/x11misc.h b/branches/V-1.5.3/veejay-server/veejay/x11misc.h new file mode 100644 index 00000000..d0373ac7 --- /dev/null +++ b/branches/V-1.5.3/veejay-server/veejay/x11misc.h @@ -0,0 +1,32 @@ +/* veejay - Linux VeeJay + * (C) 2002-2006 Niels Elburg + * + * + * 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. + */ +#ifndef X11MISC +#define X11MISC +void x11_enable_screensaver( void *display ); +void x11_disable_screensaver( void *display ); +void x11_misc_init(); +void x11_misc_set_border( void *display, void *window, int status ); + +void x11_move( void *display, void *window ); +void x11_info(void *display); + +void x11_user_select( int n ); + +#endif + diff --git a/branches/V-1.5.3/veejay-themes/AUTHORS b/branches/V-1.5.3/veejay-themes/AUTHORS new file mode 100644 index 00000000..b4aa9ac9 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/AUTHORS @@ -0,0 +1,2 @@ +Matthijs v. Henten +Niels Elburg diff --git a/branches/V-1.5.3/veejay-themes/COPYING b/branches/V-1.5.3/veejay-themes/COPYING new file mode 100644 index 00000000..d60c31a9 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/COPYING @@ -0,0 +1,340 @@ + 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. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/branches/V-1.5.3/veejay-themes/ChangeLog b/branches/V-1.5.3/veejay-themes/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/branches/V-1.5.3/veejay-themes/GrayHeart.rc b/branches/V-1.5.3/veejay-themes/GrayHeart.rc new file mode 100644 index 00000000..90a0e742 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/GrayHeart.rc @@ -0,0 +1,1587 @@ +# "BlueHeart" theme for GTK+ 2.x by Jean-Paul Bizet (jp-bizet@bigfoot.com). +# Most graphics are from Claudiu Christian Fofiu, the author of the original BlueHeart theme for GTK 1.x, E, XMMS ... +# Part of this file comes from the GlossyP theme and from other themes. + + +style "default" +{ + GtkWidget::interior_focus = 1 + GtkWidget::focus_padding = 1 + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkRange::trough_border = 0 + GtkRange::slider_width = 16 + GtkRange::slider-length = 12 + GtkRange::stepper_size = 8 + GtkPaned::handle_size = 4 + GtkScrollbar::min_slider_length = 16 + GtkCheckButton::indicator_size = 8 + GtkCheckButton::indicator_spacing = 1 + GtkMenuBar::internal_padding = 2 + GtkOptionMenu::indicator_size = { 12, 6 } + GtkOptionMenu::indicator_spacing = { 8, 2, 0, 0 } + GtkStatusbar::shadow_type = GTK_SHADOW_ETCHED_OUT + + xthickness = 2 + ythickness = 2 + + fg[NORMAL] = "#1c1c1c" + fg[PRELIGHT] = "#cacaca" + fg[ACTIVE] = "#e5e5e5" + fg[SELECTED] = "#e5e5e5" + fg[INSENSITIVE] = "#3f3f3f" + + bg[NORMAL] = "#4b4b4b" + bg[PRELIGHT] = "#4b4b4b" + bg[ACTIVE] = "#4b4b4b" + bg[SELECTED] = "#b9b9b9" + + bg[INSENSITIVE] = "#4b4b4b" + + base[NORMAL] = "#444444" + base[PRELIGHT] = "#aeafb0" + base[ACTIVE] = "#aeafb0" + base[SELECTED] = "#aeafb0" + base[INSENSITIVE] = "#4b4b4b" + + text[NORMAL] = "#e5e5e5" + text[PRELIGHT] = "#383838" + text[ACTIVE] = "#000000" + text[SELECTED] = "#7a7d80" + text[INSENSITIVE] = "#3f3f3f" + + engine "pixmap" + { + + # Flat by default + +# image +# { +# function = BOX +# } + + # handle + + image + { + function = HANDLE + recolorable = TRUE + overlay_file = "handle-h.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + image + { + function = HANDLE + recolorable = TRUE + overlay_file = "handle-v.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + + # shadow + + image + { + function = SHADOW + shadow = IN + recolorable = FALSE + file = "shadow-in.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = SHADOW + shadow = OUT + recolorable = TRUE + file = "toolbar.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = SHADOW + shadow = ETCHED_IN + recolorable = TRUE + file = "frame2.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + } + image + { + function = SHADOW + shadow = ETCHED_OUT + recolorable = TRUE + file = "frame1.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + } + image + { + function = SHADOW_GAP + recolorable = TRUE + file = "frame1.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + gap_start_file = "frame-gap-start.png" + gap_start_border = { 2, 0, 2, 0 } + gap_end_file = "frame-gap-end.png" + gap_end_border = { 0, 2, 2, 0 } + gap_side = TOP + } + image + { + function = VLINE + recolorable = TRUE + file = "line-v.png" + border = { 1, 1, 0, 0 } + stretch = TRUE + } + image + { + function = HLINE + recolorable = TRUE + file = "line-h.png" + border = { 0, 0, 1, 1 } + stretch = TRUE + } + + # focus + + image + { + function = FOCUS + recolorable = TRUE + file = "focus.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + + # arrows + + image + { + function = ARROW + recolorable = TRUE + overlay_file = "arrow-up.png" + overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + arrow_direction = UP + } + image + { + function = ARROW + recolorable = TRUE + overlay_file = "arrow-down.png" + overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + arrow_direction = DOWN + } + image + { + function = ARROW + recolorable = TRUE + overlay_file = "arrow-left.png" + overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + arrow_direction = LEFT + } + image + { + function = ARROW + recolorable = TRUE + overlay_file = "arrow-right.png" + overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + arrow_direction = RIGHT + } + image + { + function = BOX + recolorable = TRUE + file = "toolbar.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + +class "GtkWidget" style "default" + + + +style "button" = "default" +{ + + engine "pixmap" + { + image + { + function = BOX + detail = "buttondefault" + recolorable = TRUE + file = "button-default.png" + border = { 9, 9, 9, 9 } + stretch = TRUE + } + image + { + function = BOX + state = PRELIGHT + recolorable = TRUE + file = "button-prelight.png" + border = { 3, 3, 3, 3} + stretch = TRUE + } + image + { + function = BOX + state = ACTIVE + file = "button-pressed.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + state = INSENSITIVE + file = "button-insensitive.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + file = "button-normal.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + + +style "togglebutton" +{ + engine "pixmap" { + + image + { + function = BOX + recolorable = TRUE + shadow = IN + file = "button-toggle.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + shadow = OUT + file = "button-normal.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + + +style "checkradiobutton" { + engine "pixmap" { + image + { + function = FLAT_BOX + recolorable = TRUE + file = "highlight.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + +class "GtkRadioButton" style "checkradiobutton" +class "GtkCheckButton" style "checkradiobutton" + + +style "optionmenu" = "default" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + file = "button-normal.png" + border = { 4, 4, 4, 4} + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + file = "button-prelight.png" + border = { 4, 4, 4, 4} + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + file = "button-normal.png" + border = { 4, 4, 4, 4} + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = INSENSITIVE + file = "button-insensitive.png" + border = { 4, 4, 4, 4} + stretch = TRUE + } + image + { + function = TAB + recolorable = TRUE + overlay_file = "option-menu.png" + overlay_stretch = FALSE + } + } +} + + +style "combobox" = "default" +{ +engine "pixmap" { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + file = "button-normal.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } +image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + file = "button-prelight.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } +image + { + function = BOX + recolorable = TRUE + state = ACTIVE + file = "button-normal.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } +image + { + function = BOX + recolorable = TRUE + state = SELECTED + file = "button-normal.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } +image + { + function = BOX + recolorable = TRUE + state = INSENSITIVE + file = "button-insensitive.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } +image + { + function = VLINE + recolorable = TRUE + file = "null.png" + stretch = TRUE + } + } +} + + + +style "radiobutton" = "default" +{ + engine "pixmap" + { + image + { + function = OPTION + shadow = OUT + recolorable = TRUE + overlay_file = "option1.png" + #overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + } + image + { + function = OPTION + shadow = IN + recolorable = TRUE + overlay_file = "option2.png" + #overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + } + image + { + function = OPTION + shadow = ETCHED_IN + recolorable = TRUE + overlay_file = "option3.png" + #overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + } + } +} + + +style "checkbutton" = "default" +{ + engine "pixmap" + { + image + { + function = CHECK + shadow = OUT + recolorable = TRUE + overlay_file = "check1.png" + overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + } + image + { + function = CHECK + shadow = IN + recolorable = TRUE + overlay_file = "check2.png" + overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + } + image + { + function = CHECK + shadow = ETCHED_IN + recolorable = TRUE + overlay_file = "check3.png" + overlay_border = { 0, 0, 0, 0 } + overlay_stretch = FALSE + } + } +} + + +style "entry" = "default" +{ + GtkWidget::interior_focus = 1 + + engine "pixmap" + { + image + { + function = FOCUS + recolorable = TRUE + file = "shadow-in.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + + +style "spinbutton" = "entry" +{ + engine "pixmap" + { + image + { + function = ARROW + } + image + { + function = BOX + detail = "spinbutton_up" + recolorable = TRUE + file = "spin.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + overlay_file = "arrow-up.png" + overlay_border = { 10, 0, 7, 0 } + overlay_stretch = FALSE + } + image + { + function = BOX + detail = "spinbutton_down" + recolorable = TRUE + file = "spin.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + overlay_file = "arrow-down.png" + overlay_border = { 10, 0, 7, 0 } + overlay_stretch = FALSE + } + } +} + + +style "scrollbar" +{ + engine "pixmap" + { + + image + { + function = BOX + recolorable = TRUE + detail = "trough" + file = "trough.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = HORIZONTAL + } + image + { + function = BOX + recolorable = TRUE + detail = "trough" + file = "trough.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = VERTICAL + } + image + { + function = SLIDER + recolorable = TRUE + state = NORMAL + file = "slider-h.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = HORIZONTAL + overlay_file = "thumb-grip.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + image + { + function = SLIDER + recolorable = TRUE + state = PRELIGHT + file = "slider-h.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = HORIZONTAL + overlay_file = "thumb-grip-prelight.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + image + { + function = SLIDER + recolorable = TRUE + state = INSENSITIVE + file = "slider-h-insensitive.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = HORIZONTAL + overlay_file = "thumb-grip.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + image + { + function = SLIDER + recolorable = TRUE + state = NORMAL + file = "slider-v.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = VERTICAL + overlay_file = "thumb-grip.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + image + { + function = SLIDER + recolorable = TRUE + state = PRELIGHT + file = "slider-v.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = VERTICAL + overlay_file = "thumb-grip-prelight.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + image + { + function = SLIDER + recolorable = TRUE + state = INSENSITIVE + file = "slider-v-insensitive.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = VERTICAL + overlay_file = "thumb-grip.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + image + { + function = STEPPER + recolorable = TRUE + state = NORMAL + file = "stepper-up.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = UP + } + image + { + function = STEPPER + recolorable = TRUE + state = INSENSITIVE + file = "stepper-up-insensitive.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = UP + } + image + { + function = STEPPER + recolorable = TRUE + state = PRELIGHT + file = "stepper-up-prelight.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = UP + } + image + { + function = STEPPER + recolorable = TRUE + state = ACTIVE + file = "stepper-up-pressed.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = UP + } + image + { + function = STEPPER + recolorable = TRUE + state = NORMAL + file = "stepper-down.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = DOWN + } + image + { + function = STEPPER + recolorable = TRUE + state = INSENSITIVE + file = "stepper-down-insensitive.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = DOWN + } + image + { + function = STEPPER + recolorable = TRUE + state = PRELIGHT + file = "stepper-down-prelight.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = DOWN + } + image + { + function = STEPPER + recolorable = TRUE + state = ACTIVE + file = "stepper-down-pressed.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = DOWN + } + image + { + function = STEPPER + recolorable = TRUE + state = NORMAL + file = "stepper-right.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = RIGHT + } + image + { + function = STEPPER + recolorable = TRUE + state = INSENSITIVE + file = "stepper-right-insensitive.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = RIGHT + } + image + { + function = STEPPER + recolorable = TRUE + state = PRELIGHT + file = "stepper-right-prelight.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = RIGHT + } + image + { + function = STEPPER + recolorable = TRUE + state = ACTIVE + file = "stepper-right-pressed.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = RIGHT + } + image + { + function = STEPPER + recolorable = TRUE + state = NORMAL + file = "stepper-left.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = LEFT + } + image + { + function = STEPPER + recolorable = TRUE + state = INSENSITIVE + file = "stepper-left-insensitive.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = LEFT + } + image + { + function = STEPPER + recolorable = TRUE + state = PRELIGHT + file = "stepper-left-prelight.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = LEFT + } + image + { + function = STEPPER + recolorable = TRUE + state = ACTIVE + file = "stepper-left-pressed.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + arrow_direction = LEFT + } + } +} + + +style "progressbar" = "default" +{ + engine "pixmap" + { + image + { + function = BOX + detail = "trough" + recolorable = TRUE + file = "trough-progressbar.png" + border = { 5, 5, 5, 5 } + stretch = TRUE + } + image + { + function = BOX + detail = "bar" + recolorable = TRUE + file = "menubar.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + } + } +} + + +style "range" = "default" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + detail = "trough" + file = "trough.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = HORIZONTAL + } + image + { + function = BOX + recolorable = TRUE + state = INSENSITIVE + detail = "trough" + file = "trough-insensitive.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = HORIZONTAL + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + detail = "trough" + file = "trough.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = VERTICAL + } + image + { + function = BOX + recolorable = TRUE + detail = "trough" + file = "trough-insensitive.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + orientation = VERTICAL + } + image + { + function = SLIDER + recolorable = TRUE + state = NORMAL + file = "slider-range-h.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + #overlay_file = "thumb-grip-h.png" + #overlay_stretch = FALSE + orientation = HORIZONTAL + } + image + { + function = SLIDER + recolorable = TRUE + state = PRELIGHT + file = "slider-range-prelight-h.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + #overlay_file = "thumb-grip-h.png" + #overlay_stretch = FALSE + orientation = HORIZONTAL + } + image + { + function = SLIDER + recolorable = TRUE + state = INSENSITIVE + file = "slider-range-h-insensitive.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + #overlay_file = "thumb-grip-h.png" + #overlay_stretch = FALSE + orientation = HORIZONTAL + } + image + { + function = SLIDER + recolorable = TRUE + state = NORMAL + file = "slider-range-v.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + #overlay_file = "thumb-grip-v.png" + #overlay_stretch = FALSE + orientation = VERTICAL + } + image + { + function = SLIDER + recolorable = TRUE + state = PRELIGHT + file = "slider-range-prelight-v.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + #overlay_file = "thumb-grip-v.png" + #overlay_stretch = FALSE + orientation = VERTICAL + } + image + { + function = SLIDER + recolorable = TRUE + state = INSENSITIVE + file = "slider-range-v-insensitive.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + #overlay_file = "thumb-grip-v.png" + #overlay_stretch = FALSE + orientation = VERTICAL + } + } +} + + +style "menu" = "default" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + detail = "menu" + file = "menu.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + + +style "menubar" = "default" +{ + engine "pixmap" + { + image + { + function = BOX + file = "menubar.png" + border = { 3, 2, 2, 1 } + stretch = TRUE + } + } +} + + +style "menuitem" = "default" +{ + xthickness = 4 + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + file = "menuitem.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = ARROW + recolorable = TRUE + overlay_file = "arrow-right.png" + overlay_stretch = FALSE + arrow_direction = RIGHT + } + } +} + + +style "tearoffmenuitem" = "menuitem" +{ + engine "pixmap" + { + image + { + function = ARROW + file = "arrow-left.png" + stretch = TRUE + arrow_direction = LEFT + } +# image +# { +# function = HLINE +# file = "cuthere.png" +# border = { 0, 0, 0, 0 } +# stretch = TRUE +# } + } +} + + +style "notebook" = "default" +{ + + engine "pixmap" + { + image + { + function = EXTENSION + recolorable = TRUE + state = ACTIVE + file = "ext-top.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = BOTTOM + } + image + { + function = EXTENSION + recolorable = TRUE + state = ACTIVE + file = "ext-bottom.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = TOP + } + image + { + function = EXTENSION + recolorable = TRUE + state = ACTIVE + file = "ext-right.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = LEFT + } + image + { + function = EXTENSION + recolorable = TRUE + state = ACTIVE + file = "ext-left.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = RIGHT + } + image + { + function = EXTENSION + recolorable = TRUE + file = "extension-top.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = BOTTOM + } + image + { + function = EXTENSION + recolorable = TRUE + file = "extension-bottom.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = TOP + } + image + { + function = EXTENSION + recolorable = TRUE + file = "extension-left.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = RIGHT + } + image + { + function = EXTENSION + recolorable = TRUE + file = "extension-right.png" + border = { 4, 4, 4, 4 } + stretch = TRUE + gap_side = LEFT + } +# +# How to draw boxes with a gap on one side (ie the page of a notebook) +# + image + { + function = BOX_GAP + recolorable = TRUE + file = "notebook.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + gap_file = "gap_top.png" + gap_border = { 3, 2, 1, 1 } + gap_start_file = "null.png" + gap_end_file = "null.png" + gap_side = TOP + } + image + { + function = BOX_GAP + recolorable = TRUE + file = "notebook.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + gap_file = "gap_bottom.png" + gap_border = { 2, 1, 1, 1 } + gap_start_file = "null.png" + gap_end_file = "null.png" + gap_side = BOTTOM + } + image + { + function = BOX_GAP + recolorable = TRUE + file = "notebook.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + gap_file = "gap_left.png" + gap_border = { 1, 1, 2, 1 } + gap_start_file = "null.png" + gap_end_file = "null.png" + gap_side = LEFT + } + image + { + function = BOX_GAP + recolorable = TRUE + file = "notebook.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + gap_file = "gap_right.png" + gap_border = { 1, 1, 2, 1 } + gap_start_file = "null.png" + gap_end_file = "null.png" + gap_side = RIGHT + } +# +# How to draw the box of a notebook when it isnt attached to a tab +# + image + { + function = BOX + recolorable = TRUE + file = "notebook.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + gap_side = TOP + } + } +} + + +style "treeview" = "default" +{ + engine "pixmap" + { + # don't draw the focus around listitems + image + { + function = FOCUS + } + } +} + + +style "textview" = "default" +{ + bg[NORMAL] = "#000000" + + engine "pixmap" + { + # don't draw focus around textview + image + { + function = FOCUS + } + } +} + + +style "tooltips" = "default" +{ + bg[NORMAL] = "#888888" +} + + +style "ruler" = "default" +{ + engine "pixmap" { + image + { + function = BOX + recolorable = TRUE + detail = "vruler" + file = "ruler-v.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + detail = "hruler" + file = "ruler-h.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + + +style "handlebox" = "default" +{ + engine "pixmap" + { + image + { + #function = SHADOW + } + + image + { + function = HANDLE + recolorable = TRUE + overlay_file = "handle-v.png" + overlay_stretch = FALSE + orientation = VERTICAL + } + image + { + function = HANDLE + overlay_file = "handle-h.png" + overlay_stretch = FALSE + orientation = HORIZONTAL + } + } +} + + +style "flat" = "default" +{ + engine "pixmap" + { + image + { + function = SHADOW + } + } +} + + +style "list-header" +{ + #Comment out the ythickness setting below for thicker column headers. + #ythickness = 0 + GtkTreeView::odd_row_color = "#2c2c2c" + GtkTreeView::even_row_color = "#555555" + + engine "pixmap" + { + + #This image is used to draw the headers of columns in list views when they are + #not selected. + image + { + function = BOX + recolorable = TRUE + shadow = OUT + file = "list_header.png" + border = { 2, 2, 2, 1 } + stretch = TRUE + } + + #This image is used to draw the column headers in list views when they are + #clicked. + image + { + function = BOX + recolorable = TRUE + shadow = IN + file = "list_header-pressed.png" + border = { 2, 2, 2, 1 } + stretch = TRUE + } + + #Does this do anything? + image + { + function = BOX + recolorable = TRUE + shadow = OUT + state = PRELIGHT + file = "list_header-pressed.png" + border = { 2, 2, 2, 1 } + stretch = TRUE + } + } + +} + +widget_class "*List" style "list-header" +widget_class "*Tree*" style "list-header" +widget_class "GtkCList" style "list-header" + + +# This prevents Sodipodi from crashing while opening the +# Object-Style dialog. + + +style "unstyle" +{ + engine "" + { + } +} + +# recognizable pressed toggle buttons +# SPIcons seem to erase the background first. That's why I can't use +# the button style. + + +style "SPbutton" +{ + engine "pixmap" + { + image + { + function = BOX + shadow = IN + recolorable = TRUE + file = "shadow-out.png" + border = { 2, 2, 2, 2 } + stretch = TRUE + } + image + { + function = BOX + } + } +} + + +style "panelbg" +{ + xthickness = 1 + ythickness = 1 + #bg_pixmap[NORMAL] = "panel_bg.png" +} + +class "*Panel*" style "panelbg" + + +style "panelbuttons" = "default" +{ + engine "pixmap" + { + image + { + function = BOX + detail = "buttondefault" + recolorable = TRUE + file = "button-default.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + state = PRELIGHT + recolorable = TRUE + file = "button-normal-panel.png" + border = { 3, 3, 3, 3} + stretch = TRUE + } + image + { + function = BOX + state = ACTIVE + file = "button-pressed-panel.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + state = INSENSITIVE + file = "button-insensitive.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + file = "button-normal-panel.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + + +style "paneltogglebutton" +{ + engine "pixmap" { + + image + { + function = BOX + recolorable = TRUE + shadow = IN + file = "button-pressed-panel.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + shadow = OUT + file = "button-normal-panel.png" + border = { 3, 3, 3, 3 } + stretch = TRUE + } + } +} + +widget_class "*Panel*GtkToggleButton" style "paneltogglebutton" +widget_class "*Panel*GtkButton" style "panelbuttons" + + +class "GtkButton" style "button" +class "GtkRadioButton" style "radiobutton" +class "GtkToggleButton" style "togglebutton" +class "GtkRadioMenuItem" style "radiobutton" +class "GtkCheckButton" style "checkbutton" +class "GtkCheckMenuItem" style "checkbutton" +class "GtkOptionMenu" style "optionmenu" +widget_class "*Combo*" style "combobox" +class "GtkEntry" style "entry" +class "GtkOldEditable" style "entry" +class "GtkSpinButton" style "spinbutton" +class "GtkRuler" style "ruler" +class "GtkScrollbar" style "scrollbar" +class "GtkProgressBar" style "progressbar" +class "GtkRange" style "range" +class "GtkMenu" style "menu" +class "GtkMenuBar" style "menubar" +class "GtkItem" style "menuitem" +class "GtkTearoffMenuItem" style "tearoffmenuitem" +class "GtkNotebook" style "notebook" +class "GtkTextView" style "textview" +class "GtkTreeView" style "treeview" +class "GtkToolbar" style "flat" +class "GtkHandleBox" style "handlebox" +class "GtkEventBox" style "flat" +class "GtkPaned" style "handlebox" +class "SPButton" style "SPbutton" +widget "gtk-tooltips" style "tooltips" +# prevent Sodipodi from crashing +class "SPColorSlider" style "unstyle" + + +#style "metacity" { +# bg[NORMAL] = "#4b4b4b" # normal base color +# bg[INSENSITIVE] = "#4b4b4b" # unfocused titlebar background color +# bg[SELECTED] = "#4b6983" # focused titlebar background color +# fg[INSENSITIVE] = "#7bacb6" # unfocused text color +# fg[SELECTED] = "#e5e5e5" # focused text color +# fg[NORMAL] = "#e5e5e5" # focused icon color +#} + +#class "MetaFrames" style "metacity" + + +# icons from "Industrial" theme + +style "icon-style" +{ + +stock["gtk-goto-bottom"] = + { + { "stock_bottom.png", *, *, *} + } + + stock["gtk-goto-first"] = + { + { "stock_first.png", *, *, *} + } + + stock["gtk-goto-last"] = + { + { "stock_last.png", *, *, *} + } + + stock["gtk-goto-top"] = + { + { "stock_top.png", *, *, *} + } + + stock["gtk-go-back"] = + { + { "stock_left.png", *, *, *} + } + + stock["gtk-go-down"] = + { + { "stock_down.png", *, *, *} + } + + stock["gtk-go-forward"] = + { + { "stock_right.png", *, *, *} + } + + stock["gtk-go-up"] = + { + { "stock_up.png", *, *, *} + } + + stock["gtk-no"] = + { + { "stock_cancel.png", *, *, *} + } + + stock["gtk-apply"] = + { + { "stock_apply.png", *, *, *} + } + + stock["gtk-cancel"] = + { + { "stock_cancel.png", *, *, *} + } + + stock["gtk-ok"] = + { + { "stock_ok.png", *, *, *} + } + + stock["gtk-yes"] = + { + { "stock_apply.png", *, *, *} + } + + stock["gtk-refresh"] = + { + { "stock_refresh.png", *, *, *} + } +} + +class "GtkWidget" style "icon-style" diff --git a/branches/V-1.5.3/veejay-themes/GrayHeart.tar.bz2 b/branches/V-1.5.3/veejay-themes/GrayHeart.tar.bz2 new file mode 100644 index 00000000..462d3b6f Binary files /dev/null and b/branches/V-1.5.3/veejay-themes/GrayHeart.tar.bz2 differ diff --git a/branches/V-1.5.3/veejay-themes/INSTALL.sh b/branches/V-1.5.3/veejay-themes/INSTALL.sh new file mode 100644 index 00000000..f39230d2 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/INSTALL.sh @@ -0,0 +1,83 @@ +#!/bin/bash + + +# install scripts in gveejay directory, symlink to user's dir + +reloaded=`which reloaded` +srcdir=`pwd` +dstdir="" +home=$1 + +if [ -z $reloaded ]; then + echo "Cannot find reloaded in PATH" + exit 1 +fi + +echo "Using srcdir $srcdir" + +if [ -z $home ]; then + echo "Using $HOME for current reloaded user, use $0 /path/to/home to specify another" + home=$HOME +fi + +lndir=`echo $home/.veejay/theme` + +if test -x $reloaded; then + dstdir=`$reloaded -V|grep ^data\ directory|cut -d ":" -f2` + if [ -z $dstdir ]; then + echo "Wrong version of reloaded" + exit + fi +else + echo "reloaded not executable" + exit 1 +fi + +themedir=$dstdir/theme + +# make sure dir exists +mkdir -p $lndir 2>/dev/null +if [ ! -d $lndir ]; then + echo "Cannot create $lndir, abort" + exit 1 +fi + +# find all rc files in current dir +for rcfile in $srcdir/*.rc; do + tmp=`basename $rcfile` + themename=`echo $tmp|cut -d '.' -f1` + extra=$themename.tar.bz2 + mkdir -p $themedir/$themename 2>/dev/null + if [ ! -d $themedir/$themename ]; then + echo "Cannot create $themedir/$themename, abort" + exit 1 + fi + if test -f $extra ; then + cd $themedir/$themename/ + if tar -jxvf $srcdir/$extra >/dev/null ; then + echo " Extracted $extra in `pwd`" + fi + echo "$themedir/$themename" + if cp $rcfile $themedir/$themename/; then + ln -s $themedir/$themename $lndir/$themename 2>/dev/null + ln -s $lndir/$themename/$tmp $themedir/$themename/gveejay.rc 2>/dev/null + fi + cd $srcdir + else + mkdir $lndir/$themename 2>/dev/null + if cp $rcfile $themedir/$themename/; then + ln -s $themedir/$themename/$tmp $lndir/$themename/gveejay.rc 2>/dev/null + echo "Installed $themename to $themedir" + fi + + fi +done + +if test -f $lndir/theme.config ; then + content=`cat $lndir/theme.config` + echo "Current theme is $content" +else + echo "Default" > $lndir/theme.config + echo "Using default theme" +fi +echo "You can now (re)start reloaded" diff --git a/branches/V-1.5.3/veejay-themes/NEWS b/branches/V-1.5.3/veejay-themes/NEWS new file mode 100644 index 00000000..670cb836 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/NEWS @@ -0,0 +1,2 @@ + +GveejayReloaded is themeable diff --git a/branches/V-1.5.3/veejay-themes/README b/branches/V-1.5.3/veejay-themes/README new file mode 100644 index 00000000..263c2572 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/README @@ -0,0 +1,10 @@ + +These are flat themes for reloaded. + +To install them, run INSTALL.sh as root (sudo) +to remove them, run UNINSTALL.sh + + +$ sudo sh INSTALL.sh +# sh INSTALL.sh + diff --git a/branches/V-1.5.3/veejay-themes/UNINSTALL.sh b/branches/V-1.5.3/veejay-themes/UNINSTALL.sh new file mode 100644 index 00000000..ccbb3b4b --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/UNINSTALL.sh @@ -0,0 +1,38 @@ +#!/bin/bash + + +# install scripts in gveejay directory, symlink to user's dir + +reloaded=`which gveejayreloaded` +srcdir=`pwd` +dstdir="" +lndir=`echo $HOME/.veejay/theme` + +if test -x $reloaded; then + dstdir=`$reloaded -q` +else + echo "gveejayreloaded not found" + exit 1 +fi + +themedir=$dstdir/theme + +for rcfile in $srcdir/*.rc; do + tmp=`basename $rcfile` + themename=`echo $tmp|cut -d '.' -f1` + + if test -d $themedir/$themename ; then + if rm -rf $themedir/$themename; then + echo "Uninstalled $theme from $themedir" + else + echo "Unable to remove $themedir/$themename" + fi + fi + if test -f $lndir/$themename ; then + if rm -rf $lndir/$themename; then + echo "Removed $lndir/$themename" + else + echo "Unable to remove $lndir/$themename" + fi + fi +done diff --git a/branches/V-1.5.3/veejay-themes/blackvelvet.rc b/branches/V-1.5.3/veejay-themes/blackvelvet.rc new file mode 100644 index 00000000..abd60836 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/blackvelvet.rc @@ -0,0 +1,165 @@ +# Edit these colors and fonts however you like. +style "default" +{ +# engine "hcengine" {} + xthickness = 1 + ythickness = 1 + GtkWidget::shadow_type = GTK_SHADOW_ETCHED_OUT + #GtkWidget::interior_focus = 0 + #GtkWidget::focus_padding = 0 + #GtkWidget::default_border = {0, 0, 0, 0} + #GtkWidget::default_outside_border = {0, 0, 0, 0} + GtkWidget::default_spacing = 0 + GtkScale::stepper_size = 8 + GtkRange::through-width = 4 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 12 + + font_name = "Sans 8" + + fg[NORMAL] = "#333" # borders etc. + fg[PRELIGHT] = "#444" + fg[ACTIVE] = "#555" # ook borders, van sliders en notebook + fg[SELECTED] = "#666" + fg[INSENSITIVE] = "#777" + + bg[NORMAL] = "#000" # algemene achtergrond kleur + bg[PRELIGHT] = "#000" # achtergrond geselecteerd widget + bg[ACTIVE] = "#000" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#444" + bg[INSENSITIVE] = "#444" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#ccc" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#FF0000" + text[SELECTED] = "#FF0000" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#757f90" + base[SELECTED] = "#757ab3" + base[INSENSITIVE] = "#27282f" + +} + +style "scale"{ + GtkScale::stepper_size = 8 + GtkRange::through-width = 1 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 12 + + bg[ACTIVE] = "#333" # trough + bg[NORMAL] = "#444" # normal + bg[PRELIGHT] = "#7a7c7c" # mouseover + bg[INSENSITIVE] = "#222" # achtergrond kleur van niet actieve knopjes + + fg[NORMAL] = "#ccc" # values ( text) + fg[INSENSITIVE] = "#000" # shadow color insensitive + +} + +style "notebook"{ + bg[ACTIVE] = "#333" # niet actieve tabs, achtergrond sliders +} + +style "menubar"{ + bg_pixmap[NORMAL] = "gradient.png" + bg[NORMAL] = "#000000" +} + +style "frame"{ + bg[NORMAL] = "#333" # 4lgemene achtergrond kleur +} + + +style "button"{ + bg[NORMAL] = "#000" + +} + +style "text" +{ + font_name = "Sans 8" + + fg[NORMAL] = "#fff" # borders etc. + fg[PRELIGHT] = "#ccc" + fg[ACTIVE] = "#ffffff" # ook borders, van sliders en notebook + fg[SELECTED] = "#ffffff" + fg[INSENSITIVE] = "#ffffff" + + + bg[NORMAL] = "#27282F" # algemene achtergrond kleur + bg[PRELIGHT] = "#aaacc1" # achtergrond geselecteerd widget + bg[ACTIVE] = "#454f60" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#5058a0" + bg[INSENSITIVE] = "#27282f" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#d8d8d8" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#fff" + text[SELECTED] = "#fff" + text[INSENSITIVE] = "#404040" + +} + +style "tree"{ + + text[NORMAL] = "#ccc" + text[PRELIGHT] = "#fff" + text[ACTIVE] = "#ccc" # when clicked on parent + text[SELECTED] = "#fff" # selected text + text[INSENSITIVE] = "#333" + + base[NORMAL] = "#333" # default background + base[PRELIGHT] = "#444" # special click + base[ACTIVE] = "#555" # matches text + base[SELECTED] = "#444" # selected background + base[INSENSITIVE] = "#000" # disabled + +} + +style "spin"{ + +} + +style "buttons" +{ + + font_name = "Sans 8" + bg_pixmap[NORMAL] = "gradient.png" + bg[NORMAL] = "#333" # normal + bg[PRELIGHT] = "#7a7c7c" # mouseover + bg[ACTIVE] = "#0f0" # onmouseclick + bg[SELECTED] = "#00f" + bg[INSENSITIVE] = "#000" +} + +style "togglebutton" +{ + bg[PRELIGHT] = "#000" # mouseover + bg[INSENSITIVE] = "#000" + + fg[NORMAL] = "#333" # borders etc. + fg[PRELIGHT] = "#444" + fg[ACTIVE] = "#000" # border on click + fg[SELECTED] = "#000" # check on click + fg[INSENSITIVE] = "#000" # disabled +} + + + + +class "GtkButton" style "buttons" +class "GtkSpinButton" style "spin" +class "GtkToggleButton" style "togglebutton" +class "GtkCheckBox" style "togglebutton" +class "GtkLabel" style "text" +class "GtkWidget" style "default" +class "GtkScale" style "scale" +class "GtkMenuBar" style "menubar" +class "GtkFrame" style "frame" +class "GtkNotebook" style "notebook" +class "GtkTreeView" style "tree" diff --git a/branches/V-1.5.3/veejay-themes/blackvelvet.tar.bz2 b/branches/V-1.5.3/veejay-themes/blackvelvet.tar.bz2 new file mode 100644 index 00000000..8a321872 Binary files /dev/null and b/branches/V-1.5.3/veejay-themes/blackvelvet.tar.bz2 differ diff --git a/branches/V-1.5.3/veejay-themes/fruitsalade.rc b/branches/V-1.5.3/veejay-themes/fruitsalade.rc new file mode 100644 index 00000000..d5295db6 --- /dev/null +++ b/branches/V-1.5.3/veejay-themes/fruitsalade.rc @@ -0,0 +1,161 @@ +# (C) Matthijs v. Henten, 2007 +# For license details, see COPYING. +# License: GNU GPL + +style "default" +{ + xthickness = 1 + ythickness = 1 + GtkWidget::shadow_type = GTK_SHADOW_NONE + #GtkWidget::interior_focus = 0 + #GtkWidget::focus_padding = 0 + GtkWidget::default_border = {0, 0, 0, 0} + GtkWidget::default_outside_border = {0, 0, 0, 0} + GtkWidget::default_spacing = 0 + + GtkScale::stepper_size = 8 + GtkRange::through-width = 1 + GtkRange::trough_border = 0 + GtkRange::slider-width = 16 + GtkScale::slider-length = 12 + + font_name = "Sans 10" + + fg[NORMAL] = "#333" # borders etc. + fg[PRELIGHT] = "#444" + fg[ACTIVE] = "#555" # ook borders, van sliders en notebook + fg[SELECTED] = "#666" + fg[INSENSITIVE] = "#777" + + bg[NORMAL] = "#86b3b2" # algemene achtergrond kleur + bg[PRELIGHT] = "#ad8282" # achtergrond geselecteerd widget + bg[ACTIVE] = "#8e8e6b" # niet actieve tabs, achtergrond sliders + bg[SELECTED] = "#444" + bg[INSENSITIVE] = "#8e8e6b" # achtergrond kleur van niet actieve knopjes + + text[NORMAL] = "#ccc" + text[PRELIGHT] = "#d8d8d8" + text[ACTIVE] = "#fff" + text[SELECTED] = "#fff" + text[INSENSITIVE] = "#404040" + + base[NORMAL] = "#37383f" + base[PRELIGHT] = "#aaacc1" + base[ACTIVE] = "#444" + base[SELECTED] = "#444" + base[INSENSITIVE] = "#27282f" + +} + + +style "container"{ + bg[NORMAL] = "#cccc9b" + bg[ACTIVE] = "#878765" # niet actieve tabs, achtergrond sliders +} + +style "menubar"{ + # bg_pixmap[NORMAL] = "gradient.png" + bg[NORMAL] = "#000000" +} + +style "frame"{ + bg[NORMAL] = "#333" # 4lgemene achtergrond kleur +} + + +style "spin"{ + font_name = "sans bold 10" + + GtkButton::default-border = {0, 0, 0, 0} + GtkButton::default-outside-border = {0, 0, 0, 0} + GtkButton::inner-border = {0, 0, 0, 0} + + + bg[NORMAL] = "#ad8282" # normal + bg[PRELIGHT] = "#7a7c7c" # mouseover + bg[ACTIVE] = "#0f0" # onmouseclick + bg[INSENSITIVE] = "#878765" + + base[NORMAL] = "#fff" # default background + base[SELECTED] = "#444" # selected background + + text[NORMAL] = "#000" + text[SELECTED] = "#fff" +} + +style "buttons" +{ + + # bg_pixmap[NORMAL] = "gradient.png" + bg[NORMAL] = "#ad8282" # normal + bg[PRELIGHT] = "#7a7c7c" # mouseover + bg[ACTIVE] = "#0f0" # onmouseclick + bg[INSENSITIVE] = "#878765" + + GtkButton::default-border = {0, 0, 0, 0} + GtkButton::default-outside-border = {0, 0, 0, 0} + GtkButton::inner-border = {0, 0, 0, 0} + + GtkButton::child-displacement-x = 0 + GtkButton::child-displacement-y = 0 + GtkButton::displace-focus = 0 + +} + + +style "combobox" +{ + GtkButton::default-border = {0, 0, 0, 0} + GtkButton::default-outside-border = {0, 0, 0, 0} + GtkButton::inner-border = {0, 0, 0, 0} + GtkWidget::focus-line-width = 0 + GtkWidget::focus-padding = 0 + GtkWidget::focus-line-pattern = "\0\0\0\0\0\0\0\0" + GtkComboBox::hildonlike = 0 + GtkComboBox::arrow-width = 20 + GtkComboBox::arrow-height = 10 + GtkComboBox::minimum-width = 50 + GtkComboBox::minimum-height = 15 + GtkComboBox::autodimmed_button = 0 + GtkComboBox::appears-as-list = 0 +} + +style "menubar"{ + font_name = "Sans Bold Italic 10" + bg[NORMAL] = "#009696" # normal + bg[PRELIGHT] = "#7a7c7c" # mouseover + bg[ACTIVE] = "#0f0" # onmouseclick + bg[INSENSITIVE] = "#ccc" +} + +style "white"{ + bg[NORMAL] = "#fff" # normal + bg[PRELIGHT] = "#fff" # mouseover + bg[ACTIVE] = "#fff" # onmouseclick + bg[INSENSITIVE] = "#fff" + +} + + + +class "GtkButton" style "buttons" +class "GtkSpinButton" style "spin" +class "GtkToggleButton" style "spin" +class "GtkCheckBox" style "spin" +class "GtkEntry" style "spin" + + +class "GtkWidget" style "default" +class "GtkComboBox" style "combobox" +class "GtkComboBoxEntry" style "combobox" +class "GtkNotebook" style "container" + + +# class "GtkTreeView" style "tree" +class "GtkMenuBar" style "menubar" +widget "*.GtkComboBox.*" style "combobox" +widget "menubar2" style "white" +widget "sample_bank_hbox" style "container" + + + diff --git a/branches/V-1.5.3/veejay-utils/AUTHORS b/branches/V-1.5.3/veejay-utils/AUTHORS new file mode 100644 index 00000000..ad418752 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/AUTHORS @@ -0,0 +1 @@ +Niels Elburg \ No newline at end of file diff --git a/branches/V-1.5.3/veejay-utils/COPYING b/branches/V-1.5.3/veejay-utils/COPYING new file mode 100644 index 00000000..d60c31a9 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/COPYING @@ -0,0 +1,340 @@ + 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. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/branches/V-1.5.3/veejay-utils/ChangeLog b/branches/V-1.5.3/veejay-utils/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/branches/V-1.5.3/veejay-utils/INSTALL b/branches/V-1.5.3/veejay-utils/INSTALL new file mode 100644 index 00000000..23e5f25d --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/INSTALL @@ -0,0 +1,236 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free +Software Foundation, Inc. + +This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + +These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for +details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + +By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + +Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, +but needs to determine by the type of machine the package will run on. +Usually, assuming the package is built to be run on the _same_ +architectures, `configure' can figure that out, but if it prints a +message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you +can create a site shell script called `config.site' that gives default +values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). Here is a another example: + + /bin/bash ./configure CONFIG_SHELL=/bin/bash + +Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent +configuration-related scripts to be executed by `/bin/bash'. + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/branches/V-1.5.3/veejay-utils/Makefile.am b/branches/V-1.5.3/veejay-utils/Makefile.am new file mode 100644 index 00000000..be98f6c6 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/Makefile.am @@ -0,0 +1,47 @@ +# Process with automake to produce Makefile.in + +SUBDIRS = src man + +# +# Add any non autoconf'd files here, extra readmes and other misc +# info to be copied into the dist +# +EXTRA_DIST = \ + autogen.sh\ + depcomp \ + cpuinfo.sh \ + autogen.sh + +DISTCLEANFILES = \ + confdefs.h \ + config.cache \ + config.status \ + config.log + + +MAINTAINERCLEANFILES = \ + compile \ + depcomp \ + install-sh \ + missing \ + mkinstalldirs \ + Makefile.in \ + aclocal.m4 \ + config.guess \ + config.h.in \ + config.sub \ + configure \ + ltmain.sh \ + stamp-h.in + +## make rpms +rpm: Makefile + $(MAKE) dist + rpmbuild -ta --clean $(PACKAGE)-$(VERSION).tar.gz + +## make debs +deb: Makefile dist + -chmod -R +w $(PACKAGE)-$(VERSION) + rm -rf $(PACKAGE)-$(VERSION) + tar xzf $(PACKAGE)-$(VERSION).tar.gz + cd $(PACKAGE)-$(VERSION); dpkg-buildpackage -rfakeroot diff --git a/branches/V-1.5.3/veejay-utils/NEWS b/branches/V-1.5.3/veejay-utils/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/branches/V-1.5.3/veejay-utils/README b/branches/V-1.5.3/veejay-utils/README new file mode 100644 index 00000000..7370bf02 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/README @@ -0,0 +1,49 @@ + + + + + 10x0 0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 x0x1 10x0 x0x1 + 0x10x0 0x0x x10x0x10x0x10x 10x0x10x0x10x0 x0x1 10x0x10x 10x0x1 10x0x1 +0x0x10 0x0x10 x10x 10x0 x0x1 10x0x10x x0x10x 10x0 +0x0x10x0 0x0x10 x10x0x10x0x1 10x0x10x0x10 x0x1 0x10 0x0 x10x0x10 + 0x10x0 x10x0x x10x0x10x0x10x 10x0x10x0x10 x0x1 0x10x0x10x0 x10x0x10 + 10x0x1 x0x10x x10x 10x0 x0x1 0x10x0x10x0 0x0x + x0x10x0x10x0x1 x10x 10x0 x10x x0x1 0x10x0x10x0x10 0x0x + x10x0x10x0 x10x0x10x0x10x 10x0x10x0x10x0 x10x 10x0 0x0x 0x10 0x0x + 0x0x10 x10x0x10x0x10x 10x0x10x0x10x0 0x010x0 0x0x 0x10 0x0x + + + version 1.0 + + :: Veejay Utilities, a collection of commandline programs for veejay :: + http://veejayhq.net + + +Install +======= + +See file 'INSTALL' + +See doc/Howto_Compile.html +See doc/Howto_Compile_on_Ubuntu.html + +Documentation +============= + +man yuv2rawdv +man sayVIMS +man rawdv2yuv + + +Running +======= + +$ veejay -d +$ sayVIMS "600:;" + + +CONTACT / FEEDBACK & HELP +========================= + +http://veejayhq.net + diff --git a/branches/V-1.5.3/veejay-utils/autogen.sh b/branches/V-1.5.3/veejay-utils/autogen.sh new file mode 100755 index 00000000..ba7e3840 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/autogen.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + + +autoreconf -v -f -i diff --git a/branches/V-1.5.3/veejay-utils/configure.ac b/branches/V-1.5.3/veejay-utils/configure.ac new file mode 100644 index 00000000..b8b785b1 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/configure.ac @@ -0,0 +1,632 @@ +dnl Process this file with autoconf to produce a configure script. +dnl AC_INIT +AC_INIT([veejay-utils],[1.1.2],[veejay-users@lists.sourceforge.net]) +AC_PREREQ(2.57) +AC_CONFIG_SRCDIR([src/sayVIMS.c]) + +VEEJAY_MAJOR_VERSION=1 +VEEJAY_MINOR_VERSION=1 +VEEJAY_MICRO_VERSION=2 +VEEJAY_VERSION=$VEEJAY_MAJOR_VERSION.$VEEJAY_MINOR_VERSION.$VEEJAY_MICRO_VERSION +VEEJAY_CODENAME="Veejay Utilities - build $VEEJAY_MINOR_VERSION $VEEJAY_MICRO_VERSION" +AC_CONFIG_HEADERS([config.h]) +dnl AX_CONFIG_PREFIXED_HEADER([veejay-config.h], [VEEJAY], [config.h]) + +AC_CANONICAL_HOST +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE([1.7]) +AM_MAINTAINER_MODE +AM_INIT_AUTOMAKE([dist-bzip2]) + +AC_DEFINE(VEEJAYUTIL,1,[Building Veejay Utilities]) +AC_DEFINE(HAVE_CONFIG_H,1,[Include config.h]) +# libtool versioning +LT_RELEASE=$VEEJAY_MAJOR_VERSION.$VEEJAY_MINOR_VERSION +LT_CURRENT=$VEEJAY_MICRO_VERSION +LT_REVISION=$VEEJAY_MICRO_VERSION +LT_AGE=$VEEJAY_MICRO_VERSION +AC_SUBST(LT_RELEASE) +AC_SUBST(LT_CURRENT) +AC_SUBST(LT_REVISION) +AC_SUBST(LT_AGE) +dnl ********************************************************************** +dnl Options + + +dnl kill CFLAGS +CFLAGS="" +AC_ARG_ENABLE(strict, + AC_HELP_STRING([--enable-strict], + [Compile in paranoia assertion checking])) +AC_ARG_ENABLE(debug, + AC_HELP_STRING([--enable-debug], + [Compile in debugging information])) +AC_ARG_ENABLE(profile, + AC_HELP_STRING([--enable-profiling], + [Compile in profiling information])) +AC_ARG_ENABLE(compile-warnings, + AC_HELP_STRING([--enable-compile-warnings], + [Turn on compiler warnings.])) +AC_ARG_ENABLE(warnings_as_errors, + AC_HELP_STRING([--enable-warnings_as_errors], + [Compiler warnings are errors.])) +AC_ARG_ENABLE(simd-accel, + AC_HELP_STRING([--enable-simd-accel], + [use SIMD multimedia instructions such as MMX, AltiVec, etc.if possible])) +AC_ARG_WITH(extra-cflags, + AC_HELP_STRING([--with-extra-cflags=flags], + [Options to be added to CFLAGS (optional)])) + +AC_GNU_SOURCE + +dnl Initialize libtool +AC_PROG_LIBTOOL + +dnl Checks for programs. +AC_PROG_AWK +AC_PROG_CC +AM_PROG_CC_STDC +AC_PROG_YACC +AM_PROG_LEX +AC_PROG_CXX +AC_PROG_INSTALL +AC_PROG_LN_S +AC_C_BIGENDIAN +AC_C_CONST +AC_C_INLINE +AC_SYS_LARGEFILE + +dnl configure AS and ASFLAGS... +AM_PROG_AS + +AC_CHECK_HEADERS([fenv.h stdint.h inttypes.h sys/types.h alloca.h]) + +dnl AX_PREFIXED_DEFINE([VEEJAY], [HAVE_STDINT_H]) +dnl AX_PREFIXED_DEFINE([VEEJAY], [HAVE_INTTYPES_H]) + +AC_CHECK_FUNCS([posix_memalign memalign fmax lround pow bzero gettimeofday memset mmap strndup strstr strncasecmp]) +AC_CHECK_FUNCS([sched_get_priority_max]) +AC_CHECK_FUNCS([select socket getpagesize memcpy]) + +AC_CHECK_FUNC(getopt_long, + [AC_DEFINE(HAVE_GETOPT_LONG, 1, [long getopt support])], + [ # FreeBSD and BSD/OS have a gnugetopt library for this: + AC_CHECK_LIB([gnugetopt], [getopt_long], + [AC_DEFINE(HAVE_GETOPT_LONG, 1, + [long getopt support]) + LIBGETOPT_LIB="-lgnugetopt"]) + ]) + +AC_CHECK_SIZEOF([int]) +AC_CHECK_SIZEOF([long int]) +AC_CHECK_SIZEOF([size_t]) +AC_CHECK_SIZEOF([float]) + + + +AC_SUBST(LIBGETOPT_LIB) + +AC_TYPE_SIGNAL + +AC_MSG_NOTICE([The host is $host $host_cpu $host_vendor $host_os .]) + +dnl ********************************************************************* +dnl Test whether we're linux or not. If so, define HAVE_V4L and build the +dnl video4linux/hardware dependent tools. Else, undefine HAVE_V4L +have_v4l=false +have_linux=false +have_darwin=false +use_gveejayreloaded=false +dnl use_gveejay=false +case $host in + *-*-linux*) + AC_CHECK_HEADER(linux/version.h, + [have_linux=true + if test x$with_gveejayreloaded != xno ; then + use_gveejayreloaded=true + fi +dnl if test x$with_gveejay != xno ; then +dnl use_gveejay=true +dnl fi + AC_DEFINE(HAVE_LINUX,,[Linux platform]) + ], + [AC_MSG_ERROR([version.h not found - please install the linux kernel headers]) + ]) + LIBM_LIBS="-lm" + ;; + *-apple-darwin*) + AC_DEFINE(HAVE_DARWIN,,[MAC OS X Darin]) + dnl OS-X/Darwin needs no-cpp-precomp + CFLAGS="$CFLAGS -no-cpp-precomp" + have_darwin=true + LIBM_LIBS="" + ;; + *) + AC_MSG_WARN([Alien platform - Good Luck!]) + LIBM_LIBS="" + ;; +esac + + +dnl ====== check for PKG_CONFIG_PATH +if test x"$PKG_CONFIG_PATH" = x ; then + AC_MSG_NOTICE([The PKG_CONFIG_PATH variable was not set]) + AC_MSG_NOTICE([You should set it to the directories that contain the .pc files]) + AC_MSG_ERROR([Abort]) +fi + + +AC_SUBST(LIBM_LIBS) + + +have_dl_dlopen=false +AC_CHECK_LIB(dl,dlopen) +if test "$ac_cv_lib_dl_dlopen" = "yes"; then + AC_DEFINE(HAVE_DL_DLOPEN,,[Compile with dlopen support]) + have_dl_dlopen=true +fi + + +PKG_CHECK_MODULES( VEEJAY, [veejay >= 1.5.3], + [ + AC_SUBST(VEEJAY_CFLAGS) + AC_SUBST(VEEJAY_LIBS) + have_veejay=true + AC_DEFINE( HAVE_VEEJAY,1, [Veejay Installed])], + [have_veejay=false]) + +if test x$have_veejay != xtrue; then + AC_MSG_ERROR( [Cannot find veejay]) +fi + +dnl ********************************************************************* +dnl Check for mjpegtools +dnl (creates MJPEGYTOOLS_CFLAGS, +dnl ********************************************************************* +have_mjpegtools=false +PKG_CHECK_MODULES(MJPEGTOOLS, [mjpegtools >= 1.6 ], + [ + AC_SUBST(MJPEGTOOLS_CFLAGS) + AC_SUBST(MJPEGTOOLS_LIBS) + have_mjpegtools=true + AC_DEFINE(HAVE_MJPEGTOOLS, 1, [MJPEGTools installed])], + [have_mjpegtools=false]) + +if test x$have_mjpegtools != xtrue ; then + AC_MSG_ERROR([Cannot find mjpegtools. Did you set PKG_CONFIG_PATH variable?]) +fi + +dnl Check for libdv +dnl (creates LIBDV_CFLAGS, LIBDV_LIBS; defines HAVE_LIBDV) +dnl ********************************************************************* +have_libdv=false +if test x$with_libdv != xno ; then + PKG_CHECK_MODULES(LIBDV, [libdv >= 0.102], + [have_libdv=true + AC_DEFINE(SUPPORT_READ_DV2, 1, [libdv is present])], + [have_libdv=false]) +fi + +AC_MSG_CHECKING(whether to compile in debugging information) +debugCFLAGS="" +if test "x$enable_debug" = "xyes" ; then + debugCFLAGS="-g" + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +AC_MSG_CHECKING(whether to compile in profiling information) +if test "x$enable_profiling" = "xyes" ; then + debugCFLAGS="$debugCFLAGS -fprofile-arcs -ftest-coverage" + DEBUGLIBS="-lgcov" + AC_SUBST(DEBUGLIBS) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi +AC_MSG_CHECKING(whether to compile in assertion checking) +if test "x$enable_strict" = "xyes" ; then + debugCFLAGS="$debugCFLAGS -DSTRICT_CHECKING" + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +dnl ******************************************************************** +dnl Test for MMX support if an IA32 platform. If on a PPC then look for +dnl Altivec support. For the IA32 platform see if gcc understands inline +dnl MMX instructions. +dnl +dnl TODO: host = non intel, target = intel do the checks also? +dnl Remember we are checking that the toolchain can generate the +dnl code, not whether the host can execute the code, thats done +dnl at run time with the exception of the SSE code. + + +have_asm_nasm=false +have_asm_mmx=false +have_asm_sse=false +have_asm_sse2=false +have_asm_mmx2=false +have_asm_3dnow=false +have_cmov=false +have_x86cpu=false +have_x86_64cpu=false +have_altivec=false +have_mips=false +have_ppccpu=false +have_ps2=false + +OP_CFLAGS="" +YUVCFLAGS="-fif-conversion" + +AC_MSG_CHECKING([Architecture]) +case $host_cpu in + i[[3-7]]86) + AC_DEFINE(HAVE_X86CPU,, [Compiling for x86 architecture CPU]) + AC_DEFINE(ARCH_X86,1,[Compiling for x86 architecture]) + have_x86cpu=true + + PROGRAM_NOPIC="-fno-PIC" + + if test "x$enable_debug" != "xyes" ; then + OP_CFLAGS="-O3" + fi + + AC_SUBST(OP_CFLAGS) + AC_SUBST(YUVCFLAGS) + + dnl If the host is pentium, align on double word boundary + case $host_cpu in + i686) + CFLAGS="$CFLAGS" + ;; + *) + ;; + esac + + ;; + x86_64*|k8-*) + AC_DEFINE(HAVE_X86_CPU,, [Compiling for x86-64 architecture CPU]) + AC_DEFINE(ARCH_X86_64,1, [Compiling for x86-64 architecture CPU]) + have_x86cpu=true + have_x86_64cpu=true + CFLAGS="$CFLAGS -fPIC -DPIC" + ;; + powerpc | powerpc64) + AC_DEFINE(HAVE_PPCCPU,, [Compiling for PowerPC CPU]) + AC_DEFINE(ARCH_PPC,,[Compiling for PowerPC]) + have_ppccpu=true + + case $host in + *-apple-darwin*) + PROGRAM_NOPIC="-mdynamic-no-pic" # dynamic-no-pic is an Apple gcc option +dnl CFLAGS="$CFLAGS -no-cpp-precomp" + + ;; + *) + PROGRAM_NOPIC="" + ;; + esac + ;; + mips | mipsel) + AC_DEFINE(ARCH_MIPS,,[Compiling for MIPS CPU]) + AC_DEFINE(HAVE_MIPS,,[Compiling for MIPS CPU]) + have_mips=true + AC_MSG_CHECKING([if we are compiling on playstation2 hardware]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], + [[#include + #include + ]])], + [have_ps2=true], + [have_ps2=false]) + + if test x$have_ps2 = xtrue ; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_PS2,,[Compile for playstation2]) + else + AC_MSG_RESULT(no) + fi + + ;; + *) + AC_MSG_RESULT([unknown]) + ;; +esac + +dnl This flag is used for PROGRAMS not SHARED LIBRARIES. PIC code is required +dnl for shared libraries but is slower than non-pic code. Compute bound +dnl programs such as yuvdenoise and y4mspatialfilter can use this flag by +dnl simply adding programname_CFLAGS=@PROGRAM_NOPIC@ to the Makefile.am + +AC_SUBST(PROGRAM_NOPIC) + +if test x$have_x86cpu = xtrue +then + AC_CACHE_CHECK(for MMX on processor(s), ac_cv_flag_mmx, [ + if grep "^flags.* mmx" /proc/cpuinfo > /dev/null; then + ac_cv_flag_mmx=yes + else + ac_cv_flag_mmx=no + fi + ]) + + if test $ac_cv_flag_mmx = yes; then + AC_DEFINE(HAVE_ASM_MMX,,[Compiling in MMX support]) + AC_DEFINE(HAVE_MMX,,[Compiling in MMX support]) + have_asm_mmx=true + fi + + AC_CACHE_CHECK(for SSE on processor(s), ac_cv_flag_sse, [ + if grep "^flags.* sse" /proc/cpuinfo > /dev/null; then + ac_cv_flag_sse=yes + else + ac_cv_flag_sse=no + fi + ]) + + if test $ac_cv_flag_sse = yes; then + AC_DEFINE(HAVE_ASM_SSE,,[Compiling in SSE support]) + AC_DEFINE(HAVE_SSE,,[Compiling in SSE support]) + have_asm_sse=true + fi + + + dnl check for sse2 + AC_CACHE_CHECK(for SSE2 on processor(s), ac_cv_flag_sse2, [ + if grep "^flags.* sse2" /proc/cpuinfo > /dev/null; then + ac_cv_flag_sse2=yes + else + ac_cv_flag_sse2=no + fi + ]) + + if test $ac_cv_flag_sse2 = yes; then + AC_DEFINE(HAVE_ASM_SSE2,,[Compiling in SSE2 support]) + AC_DEFINE(HAVE_SSE2,,[Compiling in SSE2 support]) + have_asm_sse2=true + fi + + AC_CACHE_CHECK(for 3DNOW on processor(s), ac_cv_flag_3dnow, [ + if grep "^flags.* 3dnow" /proc/cpuinfo > /dev/null; then + ac_cv_flag_3dnow=yes + else + ac_cv_flag_3dnow=no + fi + ]) + + if test $ac_cv_flag_3dnow = yes; then + AC_DEFINE(HAVE_ASM_3DNOW,,[Compiling in 3Dnow]) + have_asm_3dnow=true + fi + + AC_CACHE_CHECK(for CMOV on processor(s), ac_cv_flag_cmov, [ + if grep "^flags.* cmov" /proc/cpuinfo > /dev/null; then + ac_cv_flag_cmov=yes + else + ac_cv_flag_cmov=yes + fi + ]) + + if test $ac_cv_flag_cmov = yes; then + AC_DEFINE(HAVE_CMOV,,[Compiling in CMOV]) + have_cmov=true + fi + + + dnl check for MMX2 + AC_CACHE_CHECK(for MMX2 on processor(s), ac_cv_flag_mmx2, [ + if grep "^flags.* mmxext" /proc/cpuinfo > /dev/null; then + ac_cv_flag_mmx2=yes + else + ac_cv_flag_mmx2=yes + fi + ]) + + if test $ac_cv_flag_mmx2 = yes; then + AC_DEFINE(HAVE_ASM_MMX2,,[Compiling in MMX2]) + AC_DEFINE(HAVE_MMX2,,[Compiling in MMX2]) + AC_DEFINE(HAVE_ASM_MMXEXT,,[Compiling in MMXEXT]) + have_asm_mmx2=true + fi + +fi + +if test x$have_ppccpu = xtrue +then + AC_MSG_CHECKING([compiler support for AltiVec]) + cat > conftest.c < +#endif +int main() { + union { vector signed int v; + signed int i; + } vi; + vi.v = vec_splat_s32(1); + return vi.i; +} +EOF + ALTIVEC_CFLAGS="" + if $CC -o conftest conftest.c >/dev/null 2>&1; then + have_altivec=true + elif $CC $CFLAGS -faltivec -o conftest conftest.c >/dev/null 2>&1; then + # Mac OS X style + have_altivec=true + ALTIVEC_CFLAGS="-faltivec" + elif $CC $CFLAGS -fvec -o conftest conftest.c >/dev/null 2>&1; then + # Motorola style + have_altivec=true + ALTIVEC_CFLAGS="-fvec" + elif $CC $CFLAGS -DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec -o conftest conftest.c >/dev/null 2>&1; then + # gcc 3.1 style + have_altivec=true + ALTIVEC_CFLAGS="-DHAVE_ALTIVEC_H=1 -maltivec -mabi=altivec" + fi + rm -f conftest*; + + if test x$have_altivec = xtrue + then + # add -O3 flag + ALTIVEC_CFLAGS="-O3 ${ALTIVEC_CFLAGS}" + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_ALTIVEC,, + [Inline PPC Altivec primitives available]) + AC_SUBST(ALTIVEC_CFLAGS) + else + AC_MSG_RESULT(no) + fi + + +fi + +if test ! -r $srcdir/cpuinfo.sh; then + AC_MSG_ERROR([cpuinfo.sh script not found - do a cvs update]) +fi + + +if test x$have_x86cpu = xtrue -o x$have_ppccpu = xtrue; then + if test x$host_alias != x; then + dnl Cross compiling + AC_MSG_CHECKING(sub-architecture settings) + if test x$have_x86cpu = xtrue; then + host_mod_cpu=`echo $host_cpu|tr _ -` + ARCHFLAGS="-march=$host_mod_cpu -mcpu=$host_mod_cpu" + AC_MSG_RESULT($ARCHFLAGS) + fi + else + AC_MSG_CHECKING(sub-architecture settings) + chmod +x $srcdir/cpuinfo.sh + + if test x$have_x86cpu = xtrue; then + ARCHFLAGS=`$srcdir/cpuinfo.sh x86` + fi + if test x$have_ppccpu = xtrue; then + ARCHFLAGS=`$srcdir/cpuinfo.sh ppc` + fi + AC_MSG_RESULT($ARCHFLAGS) + fi +fi + + +AC_MSG_RESULT($CFLAGS) + +AC_DEFINE_UNQUOTED(HAVE_FFMPEG_UNINSTALLED,, + [Defined if building against uninstalled FFmpeg source]) + +dnl ********************************************************************** +dnl All the conditional stuff for the Makefiles +AM_CONDITIONAL(HAVE_ASM_MMX, test x$have_asm_mmx = xtrue) +AM_CONDITIONAL(HAVE_X86CPU, test x$have_x86cpu = xtrue) +AM_CONDITIONAL(HAVE_PPCCPU, test x$have_ppccpu = xtrue) +AM_CONDITIONAL(ARCH_PPC, test x$have_ppccpu = xtrue) +AM_CONDITIONAL(ARCH_X86, test x$have_x86cpu = xtrue) +AM_CONDITIONAL(HAVE_ALTIVEC, test x$have_altivec = xtrue) +AM_CONDITIONAL(HAVE_ASM_MMX2, test x$have_asm_mmx2 = xtrue) +AM_CONDITIONAL(HAVE_ASM_SSE, test x$have_asm_sse = xtrue) +AM_CONDITIONAL(HAVE_ASM_SSE2, test x$have_asm_sse2 = xtrue) +AM_CONDITIONAL(HAVE_ASM_NASM, test x$have_asm_nasm = xtrue) +AM_CONDITIONAL(HAVE_MMX, test x$have_asm_mmx = xtrue) +AM_CONDITIONAL(HAVE_SSE, test x$have_asm_sse = xtrue) +AM_CONDITIONAL(HAVE_SSE2, test x$have_asm_sse2 = xtrue) +AM_CONDITIONAL(HAVE_MMX2, test x$have_asm_mmx2 = xtrue) +AM_CONDITIONAL(SUPPORT_READ_DV2, test x$have_libdv = xtrue) +AM_CONDITIONAL(HAVE_DL_DLOPEN, test x$have_dl_dlopen = xtrue) + +CFLAGS="$ARCHFLAGS $CFLAGS" +CXXFLAGS="$ARCHFLAGS $CXXFLAGS" + + +if test "x${GCC}" != "xyes" ; then + enable_compile_warnings=no +fi + +AC_MSG_CHECKING(what warning flags to pass to the C compiler) +warnCFLAGS= +warnCXXFLAGS= +if test "x$enable_compile_warnings" != "xno" ; then + if test "x$GCC" = "xyes" ; then + case "$CFLAGS" in + *-Wall*) ;; + *) warnCFLAGS="-Wall -Wunused " ;; + esac + if test "x$enable_compile_warnings" = "xyes" ; then + warnCFLAGS="$warnCFLAGS -Wmissing-prototypes -Wundef -Wshadow -Wbad-function-cast -Wconversion -Wpadded -Wunreachable-code -Wmissing-declarations -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" + warnCXXFLAGS="$warnCXXFLAGS -Wmissing-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -Wcast-qual" + fi + if test "x$enable_warnings_as_errors" = "xyes" ; then + warnCFLAGS="$warnCFLAGS -Werror" + warnCXXFLAGS="$warnCXXFLAGS -Werror" + fi + fi +fi + +if test "x$cflags_set" != "xyes" ; then + if test "x$enable_debug" = "xyes" ; then + CFLAGS="$debugCFLAGS $warnCFLAGS $CFLAGS" + else + CFLAGS="$CFLAGS $warnCFLAGS" + fi + CXXFLAGS="$CXXFLAGS $warnCXXFLAGS" + cflags_set=yes +fi + + +if test x"$with_extra_cflags" != "x"; then + CFLAGS="$CFLAGS $with_extra_cflags" + CXXFLAGS="$CXXFLAGS $with_extra_cflags" +fi + + +AC_CONFIG_FILES([ +Makefile +man/Makefile +src/Makefile +]) +AC_OUTPUT + +AC_DEFINE(VERSION, ${VERSION}) + +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Veejay-Utilities ${VERSION} build configuration :]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Compiler flags: $CFLAGS]) +AC_MSG_NOTICE([ $YUVCFLAGS]) +AC_MSG_NOTICE([ $OP_CFLAGS]) +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Architecture: ${host_cpu} ]) +AC_MSG_NOTICE([]) +if test "$have_x86cpu" = "true" ; then +AC_MSG_NOTICE([ x86 ]) +AC_MSG_NOTICE([ MMX enabled : ${ac_cv_flag_mmx}]) +AC_MSG_NOTICE([ MMX2 enabled : ${ac_cv_flag_mmx2}]) +AC_MSG_NOTICE([ SSE enabled : ${ac_cv_flag_sse}]) +AC_MSG_NOTICE([ SSE2 enabled : ${ac_cv_flag_sse2}]) +AC_MSG_NOTICE([ 3DNOW enabled : ${ac_cv_flag_3dnow}]) +AC_MSG_NOTICE([ CMOV enabled : ${ac_cv_flag_cmov}]) +fi + +if test "$have_ppccpu" = "true" ; then +AC_MSG_NOTICE([ ppc]) +AC_MSG_NOTICE([ AltiVec enabled : ${have_altivec}]) +fi + +if test "$have_mips" = "true" ; then +AC_MSG_NOTICE([ mips]) +AC_MSG_NOTICE([ PS/2 enabled : ${have_ps2}]) +fi +AC_MSG_NOTICE([]) +if test "$have_linux" = "true" ; then +AC_MSG_NOTICE([ Platform: Linux]) +fi + +if test "$have_darwin" = "true" ; then +AC_MSG_NOTICE([ Platform: Darwin]) +AC_MSG_NOTICE([ Good luck! You can be the first! ]) +fi + +AC_MSG_NOTICE([]) +AC_MSG_NOTICE([ Required dependencies:]) +AC_MSG_NOTICE([ - Veejay : ${have_veejay}]) +AC_MSG_NOTICE([ - MJPEGTools : ${have_mjpegtools}]) + diff --git a/branches/V-1.5.3/veejay-utils/cpuinfo.sh b/branches/V-1.5.3/veejay-utils/cpuinfo.sh new file mode 100755 index 00000000..a8e6ace8 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/cpuinfo.sh @@ -0,0 +1,336 @@ +#!/bin/sh + +if test x"$CC" = x; then + CC=gcc +fi + +if test $# -ne 1; then + echo "Please give the arch (ppc or x86) as an argument!" 1>&2 + exit 1 +fi + +if test `uname -s` = Darwin; then + IsDarwin=yes +else + IsDarwin=no +fi + +target=$1 + +cc_version=`$CC -dumpversion` +_cc_major=`echo $cc_version | cut -d'.' -f1` +_cc_minor=`echo $cc_version | cut -d'.' -f2` + +if test $_cc_major -ge 4; then + _opt_mcpu="-mtune" +else + _opt_mcpu="-mcpu" +fi + +do_cc() +{ + $CC -o conftest conftest.c $@ >/dev/null 2>&1 +} + +extcheck() +{ +cat > conftest.c < +void catch() { exit(1); } +int main(void){ + signal(SIGILL, catch); + __asm__ __volatile__ ("$1":::"memory"); + exit(0); +} +EOF + +do_cc +if test -x ./conftest; then + ./conftest + if test $? -ne 0; then + return 1 + fi + return 0 +else + return 1 +fi +} + +do_x86() +{ + +CFLAGS=-O +if test $IsDarwin = yes; then + CFLAGS="$CFLAGS -fno-pic -Wl,-read_only_relocs -Wl,suppress" +fi + +if test -r /proc/cpuinfo; then + _cpuinfo="cat /proc/cpuinfo" +else + $CC $CFLAGS -o cpuinfo utils/cpuinfo.c + _cpuinfo="./cpuinfo" +fi + +# Cpu determination logic adapted from the MPlayer configure script. + +pname=`$_cpuinfo | grep 'model name' | cut -d ':' -f 2 | head -n 1` +pvendor=`$_cpuinfo | grep 'vendor_id' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pfamily=`$_cpuinfo | grep 'cpu family' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pmodel=`$_cpuinfo | grep -v 'model name' | grep 'model' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pstep=`$_cpuinfo | grep 'stepping' | cut -d':' -f2 | cut -d' ' -f2 | head -n 1` +pparam=`$_cpuinfo | grep 'features' | cut -d':' -f2 | head -n 1` + +if test -z "$pparam" ; then + pparam=`$_cpuinfo | grep 'flags' | cut -d ':' -f 2 | head -n 1` +fi + +_mmx=no +_3dnow=no +_3dnowex=no +_mmx2=no +_sse=no +_sse2=no +_mtrr=no + +for i in $pparam ; do + case "$i" in + 3dnow) _3dnow=yes ;; + 3dnowext) _3dnow=yes _3dnowex=yes ;; + mmx) _mmx=yes ;; + mmxext) _mmx2=yes ;; + mtrr|k6_mtrr|cyrix_arr) _mtrr=yes ;; + xmm|sse|kni) _sse=yes _mmx2=yes ;; + sse2) _sse2=yes ;; + esac +done + +case "$pvendor" in + AuthenticAMD) + case "$pfamily" in + 3)proc=i386 + ;; + 4) proc=i486 + ;; + 5) iproc=586 + # models are: K5/SSA5 K5 K5 K5 ? ? K6 K6 K6-2 K6-3 + # K6 model 13 are the K6-2+ and K6-III+ + if test "$pmodel" -eq 9 -o "$pmodel" -eq 13; then + proc=k6-3 + elif test "$pmodel" -ge 8; then + proc=k6-2 + elif test "$pmodel" -ge 6; then + proc=k6 + else + proc=i586 + fi + ;; + 6) iproc=686 + if test "$pmodel" -ge 7; then + proc=athlon-4 + elif test "$pmodel" -ge 6; then + if test "$_sse" = yes && test "$pstep" -ge 2; then + proc=athlon-xp + else + proc=athlon-4 + fi + elif test "$pmodel" -ge 4; then + proc=athlon-tbird + else + proc=athlon + fi + ;; + 15) + # Despite what the gcc into says 'athlon64' is not accepted as + # synonym for 'k8' + proc=k8 + ;; + *) proc=athlon-xp + ;; + esac + ;; + GenuineIntel) + case "$pfamily" in + 3) proc=i386 + ;; + 4) proc=i486 + ;; + 5) iproc=586 + if test "$pmodel" -eq 4 || test "$pmodel" -eq 8; then + proc=pentium-mmx # 4 is desktop, 8 is mobile + else + proc=i586 + fi + ;; + 6) iproc=686 + if test "$pmodel" -ge 15; then + proc=nocona + elif test "$pmodel" -ge 13; then + proc=pentium-m + elif test "$pmodel" -ge 7; then + proc=pentium3 + elif test "$pmodel" -ge 3; then + proc=pentium2 + else + proc=i686 + fi + ;; + 15) proc=pentium4 + ;; + *) proc=pentium4 + ;; + esac + ;; + unknown) + case "$pfamily" in + 3) proc=i386 + ;; + 4) proc=i486 + ;; + *) proc=i586 + ;; + esac + ;; + *) + proc=i586 + ;; +esac + +# check that gcc supports our CPU, if not, fall back to earlier ones + +cat > conftest.c << EOF +int main(void) { return 0; } +EOF +if test "$proc" = "athlon64" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon-xp +fi + +if test "$proc" = "athlon-xp" || test "$proc" = "athlon-4" || test "$proc" = "athlon-tbird"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=athlon +fi + +if test "$proc" = "k6-3" || test "$proc" = "k6-2"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=k6 +fi + +if test "$proc" = "k6"; then + do_cc -march=$proc $_opt_mcpu=$proc + if test $? -ne 0; then + if do_cc -march=i586 $_opt_mcpu=i686; then + proc=i586-i686 + else + proc=i586 + fi + fi +fi + +if test "$proc" = "pentium4" || test "$proc" = "pentium3" || test "$proc" = "pentium2" || test "$proc" = "athlon"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i686 +fi +if test "$proc" = "i686" || test "$proc" = "pentium-mmx"; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i586 +fi +if test "$proc" = "i586" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i486 +fi +if test "$proc" = "i486" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=i386 +fi +if test "$proc" = "i386" ; then + do_cc -march=$proc $_opt_mcpu=$proc || proc=error +fi +if test "$proc" = "error" ; then + echo "Your $_cc does not even support \"i386\" for '-march' and $_opt_mcpu." + _mcpu="" + _march="" +elif test "$proc" = "i586-i686"; then + _march="-march=i586" + _mcpu="$_opt_mcpu=i686" +else + _march="-march=$proc" + _mcpu="$_opt_mcpu=$proc" +fi + +if test $_cc_major -ge 3; then + extcheck "xorps %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse" + extcheck "xorpd %%xmm0, %%xmm0" || _gcc3_ext="$_gcc3_ext -mno-sse2" + + if test x"$_gcc3_ext" != "x"; then + # if we had to disable sse/sse2 because the active kernel does not + # support this instruction set extension, we also have to tell + # gcc3 to not generate sse/sse2 instructions for normal C code + cat > conftest.c << EOF +int main(void) { return 0; } +EOF + do_cc $_march $_gcc3_ext && _march="$_march $_gcc3_ext" + fi +fi + +echo $_march $_mcpu +rm -f conftest.c conftest cpuinfo +return 0 +} + +do_ppc() +{ +# Linux on a PPC has /proc/info +# Darwin (OS/X) has the hostinfo command +# If neither of those we have no idea what to do - so do nothing. +if test -r /proc/cpuinfo; then + proc=`grep cpu /proc/cpuinfo | cut -d':' -f2 | cut -d',' -f1 | cut -b 2- | head -n 1` +elif test $IsDarwin = yes; then + proc=`hostinfo | grep "Processor type" | cut -f3 -d' ' | sed 's/ppc//'` +else + return 0 +fi + +case "$proc" in + 601) _march="$_opt_mcpu=601" _mcpu='-mtune=601' + ;; + 603) _march="$_opt_mcpu=603" _mcpu='-mtune=603' + ;; + 603e|603ev) _march="$_opt_mcpu=603e" _mcpu='-mtune=603e' + ;; + 604|604e|604r|604ev) _march="$_opt_mcpu=604" _mcpu='-mtune=604' + ;; + 740|740/750|745/755) _march="$_opt_mcpu=740" _mcpu='-mtune=740' + ;; + 750|750CX) _march="$_opt_mcpu=750" _mcpu='-mtune=750' + ;; + *) ;; +esac + +# gcc 3.1(.1) and up supports 7400 and 7450 +if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "1" || test "$_cc_major" -ge "4"; then + case "$proc" in + 7400*|7410*) _march="$_opt_mcpu=7400" _mcpu='-mtune=7400' ;; + 7450*|7455*) _march="$_opt_mcpu=7450" _mcpu='-mtune=7450' ;; + *) ;; + esac +fi + +# gcc 3.2 and up supports 970 +if test "$_cc_major" -ge "3" && test "$_cc_minor" -ge "3" || test "$_cc_major" -ge "4"; then + case "$proc" in + 970*) if test $IsDarwin = yes; then + _march="$_opt_mcpu=G5 -mpowerpc64 -mpowerpc-gpopt -falign-loops=16 -force_cpusubtype_ALL" _mcpu='-mtune=G5' + else + _march="$_opt_mcpu=970" _mcpu='-mtune=970' + fi + ;; + *) ;; + esac +fi + +echo $_march $_mcpu +return 0 +} + +# +# The script that runs the various functions above +# + +if test $target = x86; then + do_x86 +elif test $target = ppc; then + do_ppc +fi diff --git a/branches/V-1.5.3/veejay-utils/man/Makefile.am b/branches/V-1.5.3/veejay-utils/man/Makefile.am new file mode 100644 index 00000000..abf8678e --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/man/Makefile.am @@ -0,0 +1,3 @@ +man_MANS = sayVIMS.1 +EXTRA_DIST = $(man_MANS) +MAINTAINERCLEANFILES = Makefile.in diff --git a/branches/V-1.5.3/veejay-utils/man/sayVIMS.1 b/branches/V-1.5.3/veejay-utils/man/sayVIMS.1 new file mode 100644 index 00000000..aa096bc0 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/man/sayVIMS.1 @@ -0,0 +1,78 @@ +.TH "sayVIMS" 1 +.SH NAME +sayVIMS - sends VIMS messages to veejay +.SH SYNOPSIS +.B sayVIMS [options] [filename] +.SH DESCRIPTION +.B sayVIMS +is a simple program to send VIMS messages to veejay. + +.SH OPTIONS +The command line options allow to specify its behaviour +.TP +.B \-p [3490] +Veejay port to connect to +.TP +.B \-h [localhost] +Veejay host to connect to +.TP +.B \-f [filename] +Use a filename instead of strings on the commandline +.TP +.B \-g [multicast address] +Multicast address to send to +.TP +.B \-i +Start in interactive mode (use ? to get help) +.TP +.B \-c +Start with colored text (geek feature) + +.SH USEFULL EXAMPLES +.TP +.B sayVIMS -h localhost -p 3490 "255:;" +Start sayVIMS and connect to veejay (and tell veejay to quit) +.TP +.B sayVIMS -g 224.0.0.50 -p 5000 "255:;" +Ditto, for multicast. +.TP +.SH Message Format +A message is described as +.B :; +.TP +For example: +.B 099:1 0; +.TP +The selector is a 3 digit number identifying some atomic function in veejay. The colon is used to indicate the start of the list of arguments. The semicolon denotes the end of message. +.TP +.SH Passing arguments +Each of veejay's functions except an ordered argument list ; depending on the +In case of messages clips, streams or effect chain some values refer to defaults or current: +.TP +.B 0 for current clip/stream +.TP +.B -1 for last clip/stream +.TP +.B > 0 any clip/stream number +.TP +.B -1 for current chain entry +.TP +.B >= 0 < 20 any chain entry + + +.SH BUGS +see BUGS in the source package +.SH AUTHOR +This man page was written by Niels Elburg. +If you have questions, remarks or you just want to +contact the developers, the main mailing list for this +project is: +.I veejay-users@lists.sourceforge.net +For more info see the website at +.I http://veejay.sourceforge.net +.SH HISTORY +This tool was first named 'sendVIMS' , but it +confused to much with 'sendVIMS for PD' although +the latter is derived from this one. +.SH "SEE ALSO" +.B veejay yuv2rawdv rawdv2yuv diff --git a/branches/V-1.5.3/veejay-utils/src/Makefile.am b/branches/V-1.5.3/veejay-utils/src/Makefile.am new file mode 100644 index 00000000..ded2c172 --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/src/Makefile.am @@ -0,0 +1,15 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I$(top_srcdir) \ + -I$(includedir) $(MJPEGTOOLS_CFLAGS) $(VEEJAY_CFLAGS) $(GLIB_CFLAGS) + +sayVIMS_SOURCES = sayVIMS.c +sayVIMS_LDFLAGS = $(LAV_ALL_LIB_OPTS) +sayVIMS_LDADD = $(VEEJAY_LIBS) @LIBGETOPT_LIB@ + +YUV2RAWDV_BIN = sayVIMS + +bin_PROGRAMS = \ + $(YUV2RAWDV_BIN) + + diff --git a/branches/V-1.5.3/veejay-utils/src/sayVIMS.c b/branches/V-1.5.3/veejay-utils/src/sayVIMS.c new file mode 100644 index 00000000..fe03538d --- /dev/null +++ b/branches/V-1.5.3/veejay-utils/src/sayVIMS.c @@ -0,0 +1,256 @@ +/* sendVIMS - very simple client for VeeJay + * (C) 2002-2004 Niels Elburg + * + * + * 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 +static int interactive = 0; +static int port_num = 3490; +static char *filename = NULL; +static char *group_name = NULL; +static char *host_name = NULL; +static vj_client *sayvims = NULL; +static int colors = 0; +static int fd_in = 0; // stdin +static int single_msg = 0; +static int dump = 0; + +/* count played frames (delay) */ +static void vj_flush(int frames) { + int n = 0; + char status[100]; + bzero(status,100); + + while(frames>0) { + if( vj_client_poll(sayvims, V_STATUS )) + { + char sta_len[6]; + bzero(sta_len, 6 ); + int nb = vj_client_read( sayvims, V_STATUS, sta_len, 5 ); + if(sta_len[0] == 'V' ) + { + int bytes = 0; + sscanf( sta_len + 1, "%03d", &bytes ); + if(bytes > 0 ) + { + bzero(status, 100); + int n = vj_client_read(sayvims,V_STATUS,status,bytes); + if( n ) + { + if(dump) fprintf(stdout , "%s\n", status ); + frames -- ; + } + if(n == -1) + { + fprintf(stderr, "Error reading status from Veejay\n"); + exit(0); + } + } + } + } + } +} + +static void Usage(char *progname) +{ + fprintf(stderr, "Usage: %s [options] [messages]\n",progname); + fprintf(stderr, "where options are:\n"); + fprintf(stderr, " -p\t\tVeejay port (3490)\n"); + fprintf(stderr, " -g\t\tVeejay groupname (224.0.0.31)\n"); + fprintf(stderr, " -h\t\tVeejay hostname (localhost)\n"); + fprintf(stderr, " -m\t\tSend single message\n"); + fprintf(stderr, " -c\t\tColored output\n"); + fprintf(stderr, " -d\t\tDump status to stdout\n"); + fprintf(stderr, "Messages to send to veejay must be wrapped in quotes\n"); + fprintf(stderr, "You can send multiple messages by seperating them with a whitespace\n"); + fprintf(stderr, "Example: %s \"600:;\"\n",progname); + fprintf(stderr, " (quit veejay)\n"); + fprintf(stderr, "Example: echo \"%03d:;\" | %s \n", VIMS_QUIT, progname); + fprintf(stderr, "\n"); + fprintf(stderr, "Example: sayVIMS -h 192.168.100.12 -m \"600:;\"\n"); +} + +static int set_option(const char *name, char *value) +{ + int err = 0; + if(strcmp(name, "h") == 0 ) + { + host_name = strdup(optarg); + if(group_name) err ++; + } + else if(strcmp(name, "g") == 0) + { + if(host_name) err ++; + group_name = strdup( optarg ); + } + else if (strcmp(name, "p") == 0) + { + port_num = atoi(optarg); + } + else if (strcmp(name, "i") == 0) + { + interactive = 1; + } + else if (strcmp(name, "c") == 0) + { + colors = 1; + } + else if (strcmp(name, "m") == 0 ) + { + single_msg = 1; + } + else if(strcmp(name, "d") == 0) + { + dump = 1; + } + else err++; + + return err; +} + +vj_client *sayvims_connect(void) +{ + vj_client *client = vj_client_alloc( 0,0,0 ); + if(!client) + { + fprintf(stderr, "Memory allocation error\n"); + return NULL; + } + + if(host_name == NULL) + host_name = strdup( "localhost" ); + + if(!vj_client_connect( client, host_name,group_name, port_num )) + { + fprintf(stderr,"Unable to connect to %s:%d\n", host_name, port_num ); + return NULL; + } + + return client; +} + +int main(int argc, char *argv[]) +{ + int i; + int n = 0; + int x = 0; + int k =0; + char msg[20]; + char option[2]; + char ibuf[1024]; + int err = 0; + FILE *infile; + + veejay_set_debug_level(1); + + // parse commandline parameters + while( ( n = getopt(argc,argv, "h:g:p:micd")) != EOF) + { + sprintf(option,"%c",n); + err += set_option( option,optarg); + } + + if( err || optind > argc) + { + Usage( argv[0] ); + return -1; + } + + sayvims = sayvims_connect(); + if(!sayvims) + return -1; + + if(single_msg || interactive ) + { + char **msg = argv + optind; + int nmsg = argc - optind; + i=0; + while( i < nmsg ) + { + if(msg[i][0] == '+') + { + int delay = 1; + char *tmp = msg[i]; + if(sscanf(tmp + 1, "%d",&delay) == 1 ) + { + vj_flush(delay); + } + else + { + fprintf(stderr, "Fatal: error parsing %s\n", tmp ); + return -1; + } + } + else + { + int n = vj_client_send( sayvims,V_CMD, msg[i] ); + vj_flush(1); + } + i++; + } + } + else + { + /* read from stdin*/ + int not_done = 1; + infile = fdopen( fd_in, "r" ); + if(!infile) + { + fprintf(stderr, "Cannot read from STDIN\n"); + return 0; + } + char buf[128]; + while( fgets(buf, 100, infile) ) + { + if( buf[0] == '+' ) + { + int wait_ = 1; + + if(sscanf( buf+1, "%d", &wait_ ) ) + { + vj_flush( wait_ ); + } + else + { + fprintf(stderr,"Delay not valid: '%d'\n", wait_ ); + } + } + else + { + vj_client_send( sayvims, V_CMD, buf ); + vj_flush(1); + } + } + } + + vj_client_close(sayvims); + vj_client_free(sayvims); + + return 0; +}