diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c5af89c --- /dev/null +++ b/COPYING @@ -0,0 +1,359 @@ + guitarfx 0.001 + Copyright (C) brummer + --------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You 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. + +---------------------------------------------------------------------------- + + 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/README b/README new file mode 100644 index 0000000..3454e4c --- /dev/null +++ b/README @@ -0,0 +1,326 @@ +Hello, + +Guitarix is a simple mono amplifier to be used in a 'JACKified' +environment, i.e. a system using the JACK Audio Connection Kit, a +professionally-capable audio/MIDI server and master transport control, +available here: + + http://jackaudio.org/ + +Guitarix provides one JACK input port and two JACK output ports. It is +designed to produce nice trash/metal/rock/blues guitar sounds. Controls +for bass, treble, gain, compressor, preamp, balance, distortion, freeverb, +crybaby (wah) and echo are available. A fixed resonator is used when +distortion is disabled. To modify the sound 'pressure', you can use the +feedback and feedforward sliders. + +Guitarix includes an experimental tuner and a JACK MIDI output port +with 3 channels. They are fed by a mix from a pitch tracker and a +beat detector. You can pitch the octave (2 octaves up or down), choose the +MIDI channel, the MIDI program, the velocity and the sensitiviy, which +translates into how fast the note will read after the beat detector +emits a signal. Values for the beat detector can be set for all +channels. + + +======================= Building guitarix from source code + +---- Build environment + +As of version 0.04.5-1, guitarix uses 'waf' for the build environment. +The simplest and fastest way to build guitarix is given below: + + cd guitarix_source_directory + ./waf configure + ./waf build + sudo ./waf install + +By default, this will install guitarix and related files in +the /usr/local filesystem, e.g. /usr/local/bin. + +The installation prefix can be provided at configure time, e.g.: + + ./waf configure --prefix=/usr + ./waf build + sudo ./waf install + +Thus, guitarix will be installed in /usr/bin. + +---- Dependencies + +To compile and run properly guitarix needs the following extra +packages (runtime binaries/libraries and development packages): + + GTK+-2.0 >= 2.12.0 + libsndfile >= 1.0.17 + JACK (jackd, libjack, and their development packages) >= 0.109.1 + +By the way, most package managers usually list development packages as +'packagename-dev', e.g. libsndfile-dev. + +---- Debian + +To build a Debian package, run "dpkg-buildpackage -rfakeroot -b" + + +==================== Startup options + +---- From the command line + +Guitarix provides a few user options at startup. They can be set in +two ways. From the command line, guitarix can be invoked with the +usual -h or --help option. The following help message is displayed: + + $ guitarix --help + + Guitarix usage + All parameters are optional. Examples: + guitarix + guitarix -r black -i system:capture_3 + guitarix -c -o system:playback_1 system:playback_2 + + -h [ --help ] Print this help + -v [ --version ] Print version string and exit + + GTK configuration options: + -c [ --clear ] Use 'default' GTK style + -r [ --rcset ] arg Style to use: 'black', 'pix', 'sunburst' or 'default' + + JACK configuration options: + -i [ --jack-input ] arg guitarix JACK input + -o [ --jack-output ] arg guitarix JACK outputs + + +The options should be self explanatory but for the sake of clarity, a +few extra points are worth mentioning here. + +JACK options: +------------- + +By default, guitarix will not auto-connect to any JACK system ports +unless the latter are explicitly provided by the user from the +command line. If guitarix is started as follows: + +$ guitarix + +The user will have to manually connect the guitarix JACK ports to e.g. +system ports from Patchage (drobilla.net/software/patchage/) or the +QJackCtl (qjackctl.sourceforge.net/) connection window. + +In the following example system port names are given: + + $ guitarix -i system:capture_1 -o system:playback_1 system:playback_2 + +At startup guitarix will autoconnect to these system ports + + +GTK options: +------------ + +Guitarix comes with 2 GTK styles: 'black' and 'pix' The user can +choose one at startup by invoking the -r (or --rc-style) option: + + $ guitarix -r black + +The user can also decide not to use the shipped GTK styles and instead +use the default GTK style used by your desktop and/or window manager : + + $ guitarix -c + +It is of course possible to use combinations of different options (i.e. GTK +and JACK options). + + +---- From SHELL variables + +Guitarix offers the possibility to make some of these options more +"permanent" thanks to SHELL variables. These variables are: + + GUITARIX2JACK_INPUTS + GUITARIX2JACK_OUTPUTS1 + GUITARIX2JACK_OUTPUTS2 + GUITARIX_RC_STYLE + +Those can be defined in your $HOME/.bashrc file. Here's a typical setup: + + export GUITARIX2JACK_INPUTS=system:capture_1 + export GUITARIX2JACK_OUTPUTS1=system:playback_1 + export GUITARIX2JACK_OUTPUTS2=system:playback_2 + export GUITARIX_RC_STYLE=black + +For (t)csh shells, the following can be placed in $HOME/.cshrc + + setenv GUITARIX2JACK_INPUTS system:capture_1 + setenv GUITARIX2JACK_OUTPUTS1 system:playback_1 + setenv GUITARIX2JACK_OUTPUTS2 system:playback_2 + setenv GUITARIX_RC_STYLE black + + +==================== Keyboard shortcuts + +Guitarix benefits from keyboard shortcuts for most of its operations. +At the moment (svn@200), the following keyboard shortcuts are available: + +* Engine menu: +-------------- + - Audio engine play : Space + - Audio engine stop : Space + - Effects bypass : B (see note (i)) + - Effects back : B or Space + - MIDI out ON/OFF : Shift+M + - Quit guitarix : Ctrl+Q + +(i) Note that if jconv is running (launched from guitarix) it will still + be active and the wet/dry slider can still be used. + This implies that guitarix can be regarded as a GUI for jconv. + + +* Presets menu (as of version 0.04.7): +--------------- + +When guitarix is launched, it will browse the $HOME/.guitarix/guitarixprerc +file and store the found presets in its menu. The preset handling is quite +versatile and let you do some useful things: + + - Load a preset : 1, 2, 3, ... (note (ii)) + - Save a preset : Ctrl+1, Ctrl+2, etc (note (ii)) + - Create a new preset : Ctrl+P (insert a valid name, + spaces will be replaced by '-') + - Recall main setting : S (see note (iii)) + - Save as main setting : Ctrl+S (see note (iv)) + + Submenu "More Preset Action" : + - Cycle to next preset : Page Down (very useful) + - Cycle to prev preset : Page Up (very useful) + - Save active preset : Alt+S + - Rename active preset : Alt+R + - Delete active preset : Delete + - Delete ALL presets : Ctrl+Shift+D (gives a warning) + +Notes: + +(ii) If you have more than 9 presets, shortcuts will be disabled + +(iii) The main setting is a different context than a preset. If you quit + guitarix while you are in a preset context, the main setting will not + be saved automatically as guitarix knows only one setting at a time + (the current active setting). You can always recall the main setting and + save whatever changes you bring to it with Ctrl+S. + +(iv) Saving the main setting can be done from any context. Ctrl+S will save + the current state into the main setting and bring you back to the main + setting context. Therefore, when you were in a preset context and save + it as the main setting, you leave the preset context. + If you want instead to save the active preset, use Alt+S so you stay + in this context. + + +* Options menu: +-------------- + + - Oscilloscope ON/OFF : Shift+O + - Tuner ON/OFF : Shift+T + - Meterbridge ON/OFF : Alt+M + - Jack capture settings : Alt+J + + - Skin change cycle-through : Shift+S + +* About menu: +------------- + + - About display : Ctrl+A + + - Record / Stop record : R + + +==================== JACK startup when JACK isn't running + +Guitarix will pop up a JACK start dialog window if it finds that jackd +is not running. + +The user can choose to activate JACK or exit guitarix. Note that the +supported methods for starting JACK are (by preference order): + +1- QJackCtl --start +2- Use of $HOME/.jackdrc + +Guitarix does not support jackdbus or any JACK start method other than +the two listed above. + + +=========== Extra information + +---- LADSPA + +Guitarix also comes as a suite of LADSPA plugins. If the user wishes +to use guitarix or some of its effects in a LADSPA host (e.g. Ardour), +the guitarix plugins are available. They are installed by default in + + $PREFIX/lib/ladspa + +where PREFIX is either /usr or /usr/local. + + + +---- RECOMMENDED EXTENSION: + +=> jack_capture + +For capture (ALSA-speak for recording), guitarix uses the jack_capture +iprogram from Kjetil S. Matheussen. If you don't have it installed, look here: + + http://old.notam02.no/arkiv/src/?M=D + +You don't need jack_capture to run guitarix. However, the capture +(record) button won't work without this external +application. Pushing the record button will in this case create a +pop-up warning. Guitarix only looks in $PATH to locate jack_capture, +so be sure to install it somewhere in your declared PATH. + +Recordings will always go to $HOME/guitarix_sessionX.. A small +preference interface is provided by guitarix as to the jack_capture +parameters (file type, bit depth, JACK ports to capture from, et cetera). + +If jack_capture is to record into the OGG format, you also need the +vorbis-tools package for encoding to OGG: + + http://vorbistools.sourceforge.net/ + +=> jconv + +Guitarix can also use the excellent jconv convolution engine developed by +Fons Adriaensen, available here: + + http://www.kokkinizita.net/linuxaudio/index.html + +Jconv can be configured from guitarix. However, due to design +restrictions jconv can only be configured when not running. Despite +this restriction, it is possible to save guitarix presets with +particular jconv settings. The user can recall these presets from the +main Load Preset menu item. + +Note: When trying to load an impulse response WAV file (aka an IR file), +guitarix will check for spaces in the filename and remove them if present. +You can also resample the file to the sample rate used by JACK. Finally, +as for jack_capture, guitarix will run even if jconv is not installed. + + +=========================================== + +THANKS: + +I (Hermann Meyer) use FAUST to build the prototype and will say thanks +to the following contributors: + +Contributors : Julius Smith + : Albert Graef + : Yann Orlary + +The waf build environment and various code cleanups are provided by James Warden. + +Enjoy! :) + +If you encounter problems building or running guitarix, please inform us. + + brummer-@web.de + warjamy@yahoo.com diff --git a/README.developers b/README.developers new file mode 100644 index 0000000..ec9e354 --- /dev/null +++ b/README.developers @@ -0,0 +1,97 @@ +Documentation for Guitarix Developers + +1. Measurement of DSP processing times +2. Formatting of source code +3. Thread architecture +4. Parameters (for DSP algorithms etc.) +5. Integration of faust code + + +1. Measurement of DSP processing times +---------------------------------------------------------------- + +Guitarix must be compiled with --debug (specifically NDEBUG not +defined). Time measurement is switched on by defining the environment +variable GUITARIX_MEASURE. When setting its value to 1 results are +more verbose. Results are printed each second on stdout. + +For better controlled measurements you can disable frequency scaling +and set cpu affinity: + +$ sudo cpufreq-set -d 800MHz -u 800MHz # or whatever your cpu supports +$ GUITARIX_MEASURE=1 taskset -c 1 guitarix + + +2. Formatting of source code +---------------------------------------------------------------- + +We use emacs c++ style "linux" (other formatters like astyle have +similar styles under this name) with following modifications: + + - namespaces do not increase indentation + in .emacs: (setq c-offsets-alist '((innamespace . 0))) + + - tabs at the beginning of lines, but not for aligning indentation + ("smart tabs", http://www.emacswiki.org/emacs/SmartTabs). Should + look correct with any tab width (though for tab width 8 you need + a wide screen..). + + +3. Thread architecture +---------------------------------------------------------------- + +Basically there are 2 threads: + + - the main thread for all work (especially all user interface) + except audio processing + + - the jack rt thread for audio processing in the process() callback + in hard real time (as "hard" as available..). The jack notification + callbacks have more relaxed time constraints and may be executed in + another thread created by libjack (depends on if you are using + jack1 or jack2). + +All other threads are just waiting for some semaphore or process +signal and delegate their work to the main thread via g_idle_add (this +is safe because the glib main loop data structures are protected by a +mutex). + +An exception is the library for the zita convolver, which creates rt +threads to spread the work for convolution processing. But this is +internal to the library. + +At some places in the program g_idle and g_timeout callbacks are +called threads, but these are running synchronous in the main loop and +are not meant here (on MP systems the main thread can even run +simultaneously with the rt thread). + + +4. Parameters (for DSP algorithms etc.) +---------------------------------------------------------------- + +All parameters have a unique string id. Its a path notation of group, +subgroup(s) and name separated by ".". + +There is a base type (Parameter) and a central registry +(parameter_map) for all parameters. Parameters have a user-visible +group and name (e.g. when you set the midi controller for a +parameter) and a description, and can be defined in faust dsp code. + +Registered parameters are saved into the application settings file and +possibly into preset files (depending on a flag in the parameter +definition). + + +5. Integration of faust code +---------------------------------------------------------------- + +Since faust code (http://faust.grame.fr ) is quite legible, but not so +the generated c++ code, its a good idea to work with the faust code +directly. This could be done by using the faust generated c++ objects +(and quite some runtime shuffling), but we are using the python script +tools/dsp2cc to post-process the faust output (giving some more +control at the expense of being a bit more faust version dependent). + +Faust dsp files are in src/faust, the generated files get copied to +src/faust-cc for distribution so the program can be build later even +if faust is not installed (or no compatible version). diff --git a/changelog b/changelog new file mode 100644 index 0000000..74ef571 --- /dev/null +++ b/changelog @@ -0,0 +1,296 @@ +guitarix (0.10.0) unstable; urgency=low + + * add tonestack models + * add 2. amp model + * add cabinet impulse response modul + * add Patch Info widget + * add Preset File Load/Export option + * add simple looper + * add Oscilloscope and tuner state to main settings + * selectable distortion model (multi/single line) + * selectable EQ model (fixed/scalable freq) + * free mem when not used (delay lines) + * reworked Gui + * fix varios bugs + + -- brummer Sun, 11 Jul 2010 07:18:15 +0200 + +guitarix (0.09.0) unstable; urgency=low + + * make distortion a multiband distortion + * fix bug in resample IR-files + * resample IR-files now on-the-fly + * add insert point ports to the effect chain + * add --optimization flag for configure the build + * switch to double precision instead of single precision + * fix bug in reconfigure convolver when preset change + * add patch from Peder Hedlund, build against gtk-2.12.9 and gcc-4.3.1 + * add faust 0.9.24 to the "good_faust_versions" + + -- brummer Sun, 06 Jun 2010 17:18:15 +0200 + +guitarix (0.08.0) unstable; urgency=low + + * new portmap window + * add Quad Filter + * add Moog Filter + * add Flanger + * add new post processing tube3 + * add two 10 band parametric EQ's + * add oversample mode selector + * fix some bugs in midi out + * reworked tuner interface (show frequency(hz)) + * add new configure options (see ./waf --help form more info) + + -- Andreas Degert Fri, 14 May 2010 15:18:15 +0200 + +guitarix (0.07.1) unstable; urgency=low + + * version check of ~/.guitarix was commented out + + -- Andreas Degert Tue, 29 Mar 2010 22:13:50 +0200 + +guitarix (0.07.0) unstable; urgency=low + + * nearly complete reworked source by Andreas Degert + * amp and effect units based direct on faust expressions + * all faust sources included + * new accumulated tuner unit with new interface (analogue Style needle meter) + * Midi controller connections could saved with in presets and/or general + * a editable Midi controller map is available + * new human readable preset style + * knobs could be used like sliders (press ctrl + mouse-button + and move the mouse horizontal, leave the ctrl and hold mouse-button + for fine tune), or like real knobs (turn them around) + * convolution unit based on zita-convolver is now integrated in the engine + * presets could change with Midi Program Messages + * I'm sure I have some things forgotten to mention here. + + -- Andreas Degert Tue, 28 Mar 2010 21:09:25 +0200 + +guitarix (0.05.4-1) unstable; urgency=low + * performace boost by remove float to int casts from engine + * reorder GUI + + -- brummer Mon, 02 Dec 2009 16:20:56 +0200 + +guitarix (0.05.3-1) unstable; urgency=low + * quick update to cover renaming of jconv to jconvolver + + -- brummer Mon, 02 Dec 2009 16:20:56 +0200 + +guitarix (0.05.2-1) unstable; urgency=low + * varios improvements + + -- brummer Mon, 30 Nov 2009 13:20:56 +0200 + +guitarix (0.05.1-1) unstable; urgency=low + * varios improvements + + -- brummer Mon, 26 Oct 2009 08:24:42 +0200 + +guitarix (0.05.0-1) unstable; urgency=low + * add keyboard shortcuts + * new code structure by James + * impruved skin handling + * add middle tone control + * reworked audio engine + * add bypass mode + * add logging window + * add engine state widget + + -- brummer Mon, 27 Jul 2009 08:24:42 +0200 + +guitarix (0.04.6-1) unstable; urgency=low + * switch to waf build system + * use boost libary for cmd commands + * varios code cleanups by James + * new tube model + * add scrollwheel controlls + + -- brummer Wed, 24 Jun 2009 14:24:42 +0200 + +guitarix (0.04.5-1) unstable; urgency=low + * fix wrong porthandling in dsp + * add latency menu by James Warden + * impruve midi out + + -- brummer Thu, 26 May 2009 14:24:42 +0200 + +guitarix (0.04.4-1) unstable; urgency=low + * switch back to use portbuffer for midi output + * add some audio effect's + * impruve tuner and midi out + * add fix's for makefile/readme/changlog submit by Orcan Ogetbil + + -- brummer Wed, 21 May 2009 14:24:42 +0200 + +guitarix (0.04.3-1) unstable; urgency=low + * fix denormals + + -- brummer Wed, 06 Mar 2009 07:24:42 +0200 + +guitarix (0.04.2-1) unstable; urgency=low + * bug fix release, fix wrong porthandling + * add anti aliase unit + + -- brummer Tue, 05 Mar 2009 07:24:42 +0200 + +guitarix (0.04.1-1) unstable; urgency=low + * bug fix (upload the wrong source, sorry) + + -- brummer Thu, 28 Mar 2009 07:24:42 +0200 + +guitarix (0.04.0-1) unstable; urgency=low + * add more Oscilloscope modes + * fix bug port_registration with jackdmp + * set jack_midi_port stable + * improve UI + + -- brummer Thu, 23 Mar 2009 17:24:42 +0200 + +guitarix (0.03.9-1) unstable; urgency=low + * add Oscilloscope like wave view widget + * fix bug in jconv gain settings + * set jack_midi_port to be temporarly (off by default) + * remove sse and fast-math flags from makefile + + -- brummer Thu, 26 Mar 2009 18:24:42 +0200 + +guitarix (0.03.8-1) unstable; urgency=low + * add wave view and select samples widget to the jconv settings + * some bugfixe's, some cleanup's + * add auto gain correction to Overdrive + + -- brummer Wed, 18 Mar 2009 11:24:42 +0200 + +guitarix (0.03.7-svn-1) unstable; urgency=low + * make single ladspa plugins from the inbuild effects + * new sorce structure + + -- brummer Fri, 06 Mar 2009 11:24:42 +0200 + +guitarix (0.03.7-1) unstable; urgency=low + * rework distortion + * bugfix in adjustment call for entry's, reportet by Aurélien Leblond + + -- brummer Thu, 05 Feb 2009 11:24:42 +0200 + +guitarix (0.03.6-1) unstable; urgency=low + * add overdrive + * make GUI smaler + + -- brummer Thu, 05 Feb 2009 11:24:42 +0200 + +guitarix (0.03.5-1) unstable; urgency=low + * change knob pointer + + -- brummer Wed, 04 Feb 2009 17:24:42 +0200 + +guitarix (0.03.4-1) unstable; urgency=low + * use knobs, switchs and graphicaly sliders for the interface + * set black style as default + * make effekts modular + * new preamp model + + -- brummer Wed, 04 Feb 2009 14:24:42 +0200 + +guitarix (0.03.3-1) unstable; urgency=low + * add resampler for ir.wav files + * autoremove white space in ir.wav file names + * protected advanced setting widgets for destroy call from window manager + * add experimental tuner + * add jack midi out port + * add pitch tracker/beatdetector to midi converter + * add midi controlls for velocity, channel choose, program choose, okatve switch and sensity + * add more midi out channels (3), clean up the processing + * add controll interface for pitch tracker/beatdetector + * add extra tread for midi processing + * add system tray icon with menu + * add high cpu load sys tray warning and midi send notify + * clean up midi process + * set midi process to a lower rt level (-20) when run in realtime + * add compressor + * add midi controlles for volume and auto pichweel + + + -- brummer Wed, 14 Dec 2009 14:24:42 +0200 + +guitarix (0.03.a-1) unstable; urgency=low + * bug fix for jconv wet/dry slider + * bug fix for jconv gain settings + + -- brummer Thu, 03 Dec 2008 16:24:42 +0200 + + +guitarix (0.03.0-1) unstable; urgency=low + * add advanced setting widgets to distortion, freeverb, ImpulseResponse and Crybaby + * rework the jconv settings window + * split code + + -- brummer Sun, 23 Nov 2008 16:24:42 +0200 + +guitarix (0.02.9a-1) unstable; urgency=low + * bugfix for the run jconv handling + * bugfix a typo in the Makefile for the LADSPAPATH + * clean code + + -- brummer Mon, 10 Nov 2008 13:55:42 +0200 + + +guitarix (0.02.9-1) unstable; urgency=low + * add a wet/dry fader for jconv + * clean code + + -- brummer Sat, 08 Nov 2008 13:55:42 +0200 + +guitarix (0.02.8-1) unstable; urgency=low + * add more settings for jconv + * clean code + + -- brummer Thu, 06 Nov 2008 13:55:42 +0200 + +guitarix (0.02.7-1) unstable; urgency=low + * add suport for jconv + * use jack_capture_gui2 to create the comandline for jack_capture + * add preamp + * change preset handling to save by name include the jconv settings + * rework the distortion funktion + * add all effekts to the ladspa plugin + * add versioncheck to make sure the saved presets work with new version + + -- brummer Thu, 02 Nov 2008 13:24:31 +0200 + +guitarix (0.02.4-1) unstable; urgency=low + * change the gui to expander + * add suport for meterbridge + * add macro for no see environment + * add nogui parameter and options + * add record with jack_capture + * add feedback and feedforward filter + * start to clean the code. + * remove the skin option, all colers comes now from Gtk. + + -- brummer Thu, 05 Aug 2008 13:24:31 +0200 + +guitarix (0.02.3-1) unstable; urgency=low + * add nogui parameter and options + * add record with jack_capture + * add feedback and feedforward filter + * start to clean the code. + * remove the skin option, all colers comes now from Gtk. + + -- brummer Thu, 03 Aug 2008 13:24:31 +0200 + +guitarix (0.02.2-1) unstable; urgency=low + * add echo, crybaby and ImpulseResponse + * add menu save and load presets + + -- brummer Thu, 23 Jul 2008 13:24:31 +0200 + +guitarix (0.02.1-1) unstable; urgency=low + * add Distortion and Freeverb + * add skin and gtk.rc file suport + * Initial Release.(0.01) + + -- brummer Thu, 05 Jul 2008 13:24:31 +0200 diff --git a/guitarix.desktop b/guitarix.desktop new file mode 100644 index 0000000..4ae250f --- /dev/null +++ b/guitarix.desktop @@ -0,0 +1,10 @@ + +[Desktop Entry] +Name=guitarix +GenericName=Mono Amplifier +Comment=Simple mono amplifier simulation +Exec=guitarix +Icon=guitarix +Categories=AudioVideo;X-Jack;Midi;X-MIDI; +Terminal=false +Type=Application diff --git a/ladspa/crybaby.cpp b/ladspa/crybaby.cpp new file mode 100644 index 0000000..fb7d506 --- /dev/null +++ b/ladspa/crybaby.cpp @@ -0,0 +1,706 @@ +//----------------------------------------------------- +// name: "crybaby" +// version: "0.1" +// author: "brummer" +// license: "GPL" +// +// Code generated with Faust 0.9.9.4k-par (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "emptty"); + m->declare("version", "0.01"); + m->declare("author", "brummer"); + m->declare("license", "GPL"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classinitcry(int samplingFreq) { + } + virtual void instanceinitcry(int samplingFreq) { + fSamplingFreq = samplingFreq; + fslider0 = 0.0f; + for (int i=0; i<2; i++) fRec1[i] = 0; + fslider1 = 0.1f; + fslider2 = 0.0f; + fConst0 = (2827.43335f / fSamplingFreq); + fConst1 = (1413.716675f / fSamplingFreq); + for (int i=0; i<2; i++) fRec2[i] = 0; + for (int i=0; i<2; i++) fRec3[i] = 0; + for (int i=0; i<3; i++) fRec0[i] = 0; + fcheckbox0 = 1.0; + } + virtual void initcry(int samplingFreq) { + classinitcry(samplingFreq); + instanceinitcry(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openHorizontalBox("crybaby"); + interface->addHorizontalSlider("level", &fslider1, 0.1f, 0.0f, 1.0f, 1.000000e-02f); + interface->addVerticalSlider0("wah", &fslider0, 0.0f, 0.0f, 1.0f, 1.000000e-02f); + interface->addVerticalSlider("wet/dry", &fslider2, 0.0f, -1.0f, 1.0f, 1.000000e-03f); + interface->closeBox(); + } + virtual void compute (int count, float** input, float** output) { + float fSlow0 = fslider0; + float fSlow1 = (9.999872e-05f * powf(4.0f, fSlow0)); + float fSlow2 = fslider2; + float fSlow3 = ((1 - max(0, (0 - fSlow2))) * fslider1); + float fSlow4 = powf(2.0f, (2.3f * fSlow0)); + float fSlow5 = (1 - (fConst1 * (fSlow4 / powf(2.0f, (1.0f + (2.0f * (1.0f - fSlow0))))))); + float fSlow6 = (9.999871e-04f * (0 - (2.0f * (fSlow5 * cosf((fConst0 * fSlow4)))))); + float fSlow7 = (9.999871e-04f * (fSlow5 * fSlow5)); + float fSlow8 = (1 - max(0, fSlow2)); + int iSlow9 = int(fcheckbox0); + float* input0 = input[0]; + float* output0 = output[0]; + for (int i=0; i fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescrcry(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBox(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_0 ); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_1 ); + } + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE , min, max); + } + + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM , min, max); + } + + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW, min, max); + } + + virtual void addNumEntry(const char* label, float* zone, float initcry, float min, float max, float step) { + addPortDescrcry(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { + addPortDescrcry(OCONTROL, label, 0, -10000, +10000); + } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { + addPortDescrcry(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + addPortDescrcry(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){ + addPortDescrcry(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox(const char* label) { openAnyBox(label); } + virtual void openTabBox(const char* label) { openAnyBox(label); } + virtual void openHorizontalBox(const char* label) { openAnyBox(label); } + virtual void openVerticalBox(const char* label) { openAnyBox(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor) { + const char* name = sym(crydsp); + descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor->PortDescriptors = fPortDescs; + descriptor->PortNames = fPortNames; + descriptor->PortRangeHints = fPortHints; + + descriptor->Label = strdup(name); + descriptor->UniqueID = 4062; +// descriptor->Label = strdup(fPluginName.c_str()); +// descriptor->UniqueID = makeID(fPluginName.c_str()); + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = name; +// descriptor->Name = strdup(fPluginName.c_str()); + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + } +}; + + + + +//--------------------------------------portData---------------------------------------- +// +// portData : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone[MAXPORT]; // + float* fPortData[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone(float* zone) + { + fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData() {} + + + //------------------------------Collect the control zones------------------------------- + + virtual void addButton(const char* label, float* zone) { addZone(zone); } + virtual void addToggleButton(const char* label, float* zone) { addZone(zone); } + virtual void addCheckButton(const char* label, float* zone) { addZone(zone); } + + virtual void addVerticalSlider(const char* label, float* zone, float initcry, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addHorizontalSlider(const char* label, float* zone, float initcry, float min, float max, float step) { addZone(zone); } + virtual void addNumEntry(const char* label, float* zone, float initcry, float min, float max, float step) { addZone(zone); } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addZone(zone); } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + + virtual void openFrameBox(const char* label) { } + virtual void openTabBox(const char* label) { } + virtual void openHorizontalBox(const char* label) { } + virtual void openVerticalBox(const char* label) { } + virtual void closeBox() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortDatacry (unsigned long port, LADSPA_Data* data) { + fPortData[port] = data; + } + + void updateCtrlZones() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i]; + } + + float** getInputs() { + return &fPortData[0]; + } + + float** getOutputs() { + return &fPortData[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptorc = 0; + +struct PLUGIN +{ + unsigned long fSampleRate; + portData* fPortData; + dsp* fDsp; + + PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {} +}; + +LADSPA_Handle instantiate_methodcry (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dsp* p = new crydsp(); + portData* d = new portData(p->getNumInputs(), p->getNumOutputs()); + + p->buildUserInterface(d); + return new PLUGIN (SampleRate, d, p); +} + +void connect_methodcry (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->setPortDatacry(Port, DataLocation); +} + +void activate_methodcry (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fDsp->initcry(p->fSampleRate); +} + +void run_methodcry (LADSPA_Handle Instance, unsigned long SampleCount) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->updateCtrlZones(); + p->fDsp->compute(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs()); +} + +void deactivate_methodcry (LADSPA_Handle Instance) +{ +} + +void cleanup_methodcry (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + delete p->fPortData; + delete p->fDsp; + delete p; +} + + +//-------------------------------------------------------------------------------------- + +void initcry_descriptor(LADSPA_Descriptor* descriptor) +{ + descriptor->UniqueID = 4062; + descriptor->Label = "crybaby"; + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = "crybaby"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + + descriptor->ImplementationData = 0; + + // description des methodcrys + descriptor->instantiate = instantiate_methodcry; + descriptor->connect_port = connect_methodcry; + descriptor->activate = activate_methodcry; + descriptor->run = run_methodcry; + descriptor->run_adding = 0; + descriptor->set_run_adding_gain = 0; + descriptor->deactivate = deactivate_methodcry; + descriptor->cleanup = cleanup_methodcry; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptorc == 0) + { + // allocate temporaries dsp and portCollector to build the plugin description + crydsp* p = new crydsp(); + if (p) { + portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs()); + p->buildUserInterface(c); + gDescriptorc = new LADSPA_Descriptor; + initcry_descriptor(gDescriptorc); + c->fillPortDescription(gDescriptorc); + delete p; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptorc; + } else { + return NULL; + } +} + diff --git a/ladspa/distortion.cpp b/ladspa/distortion.cpp new file mode 100644 index 0000000..8ca1f77 --- /dev/null +++ b/ladspa/distortion.cpp @@ -0,0 +1,862 @@ +//----------------------------------------------------- +// name: "emptty" +// version: "0.01" +// author: "brummer" +// license: "BSD" +// copyright: "(c)brummer 2008" +// +// Code generated with Faust 0.9.9.4k-par (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "distortion"); + m->declare("version", "0.1"); + m->declare("author", "brummer"); + m->declare("license", "GPL"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classinitdis(int samplingFreq) { + } + virtual void instanceinitdis(int samplingFreq) { + fSamplingFreq = samplingFreq; + fslider0 = 0.12f; + IOTA = 0; + for (int i=0; i<4096; i++) fVec0[i] = 0; + fslider1 = 0.5f; + for (int i=0; i<2; i++) fRec1[i] = 0; + fentry0 = 5000.0f; + fConst0 = (3.141593f / fSamplingFreq); + for (int i=0; i<2; i++) fVec1[i] = 0; + for (int i=0; i<2; i++) fRec3[i] = 0; + fentry1 = 130.0f; + fConst1 = (3.141593f * fSamplingFreq); + fConst2 = (0.5f / fSamplingFreq); + for (int i=0; i<2; i++) fVec2[i] = 0; + for (int i=0; i<2; i++) fRec2[i] = 0; + fcheckbox0 = 1.0; + fslider2 = 5000.0f; + fslider3 = 130.0f; + for (int i=0; i<2; i++) fVec3[i] = 0; + for (int i=0; i<2; i++) fRec7[i] = 0; + for (int i=0; i<2; i++) fVec4[i] = 0; + for (int i=0; i<2; i++) fRec6[i] = 0; + for (int i=0; i<3; i++) fRec5[i] = 0; + for (int i=0; i<3; i++) fRec4[i] = 0; + fcheckbox1 = 1.0; + fslider4 = 0.0f; + fslider5 = 0.64f; + for (int i=0; i<2; i++) fVec5[i] = 0; + for (int i=0; i<2; i++) fRec0[i] = 0; + fslider6 = 0.0f; + for (int i=0; i<2; i++) fRec8[i] = 0; + for (int i=0; i<2; i++) fVec6[i] = 0; + for (int i=0; i<2; i++) fRec12[i] = 0; + for (int i=0; i<2; i++) fVec7[i] = 0; + for (int i=0; i<2; i++) fRec11[i] = 0; + for (int i=0; i<3; i++) fRec10[i] = 0; + for (int i=0; i<3; i++) fRec9[i] = 0; + drive = 0.0f; + overdrive4 = 0.0; + for (int i=0; i<2; i++) fRecover0[i] = 0; + } + virtual void initdis(int samplingFreq) { + classinitdis(samplingFreq); + instanceinitdis(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openHorizontalBox("distortion"); + // interface->openVerticalBox("overdrive"); + interface->addVerticalSlider("overdrive ", &drive, 0.0f, 1.0f, 20.0f, 0.1f); + interface->addToggleButton("over_drive", &overdrive4); + // interface->closeBox(); + interface->addVerticalSlider("drive", &fslider5, 0.64f, 0.0f, 1.0f, 0.01f); + interface->addVerticalSlider0("drivelevel", &fslider4, 0.0f, 0.0f, 1.0f, 0.01f); + interface->addVerticalSlider("drivegain", &fslider6, 0.0f, -20.0f, 20.0f, 0.1f); + //interface->openHorizontalBox("low/highpass"); + //interface->openVerticalBox(""); + interface->addHorizontalSlider("highpass", &fentry1, 130.0f, 8.0f, 1000.0f, 1.0f); + interface->addVerticalSlider("lowpass", &fentry0, 5000.0f, 1000.0f, 10000.0f, 1.0f); + //interface->closeBox(); + interface->addCheckButton("low_highpass", &fcheckbox0); + //interface->closeBox(); + //interface->openHorizontalBox("low/highcut"); + interface->addVerticalSlider("highcut", &fslider2, 5000.0f, 1000.0f, 10000.0f, 1.0f); + interface->addHorizontalSlider("lowcut", &fslider3, 130.0f, 8.0f, 1000.0f, 1.0f); + interface->addCheckButton("low_highcut", &fcheckbox1); + //interface->closeBox(); + //interface->openVerticalBox("resonanz"); + interface->addVerticalSlider1("trigger", &fslider0, 1.0f, 0.0f, 1.0f,0.01f); + interface->addVerticalSlider1("vibrato", &fslider1, 0.5f, 0.01f, 1.0f, 0.01f); + //interface->closeBox(); + interface->closeBox(); + } + virtual void compute (int count, float** input, float** output) { + float fSlow0 = (1.0f - fslider0); + float fSlow1 = fslider1; + int iSlow2 = int((int((fSlow1 - 1)) & 4095)); + int iSlow3 = int((int(fSlow1) & 4095)); + float fSlow4 = (1.0f / tanf((fConst0 * fentry0))); + float fSlow5 = (fSlow4 - 1); + float fSlow6 = (1.0f / (1 + fSlow4)); + float fSlow7 = (1.0f / tanf((fConst2 * (fConst1 - (6.283185f * fentry1))))); + float fSlow8 = (1 + fSlow7); + float fSlow9 = (1.0f / fSlow8); + float fSlow10 = (0 - ((fSlow7 - 1) / fSlow8)); + int iSlow11 = int(fcheckbox0); + float fSlow12 = tanf((fConst0 * fslider2)); + float fSlow13 = (2 * (1 - (1.0f / (fSlow12 * fSlow12)))); + float fSlow14 = (1.0f / fSlow12); + float fSlow15 = (1 + ((fSlow14 - 0.765367f) / fSlow12)); + float fSlow16 = (1.0f / (1 + ((0.765367f + fSlow14) / fSlow12))); + float fSlow17 = (1 + ((fSlow14 - 1.847759f) / fSlow12)); + float fSlow18 = (1.0f / (1 + ((1.847759f + fSlow14) / fSlow12))); + float fSlow19 = (fConst0 * fslider3); + float fSlow20 = (1.0f / (1 + fSlow19)); + float fSlow21 = (1 - fSlow19); + int iSlow22 = int(fcheckbox1); + float fSlow23 = fslider4; + float drivem1 = drive - 1.0f; + float fSlow24 = powf(10.0f, (2 * fslider5)); + float fSlow25 = (9.999871e-04f * powf(10, (5.000000e-02f * (fslider6 - 10)))); + float fSlowover0 = (9.999871e-04f * powf(10, (5.000000e-02f * (drive*-0.5)))); + float* input0 = input[0]; + float* output0 = output[0]; + for (int i=0; i fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescrdis(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBox(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO | LADSPA_HINT_DEFAULT_NONE; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO | LADSPA_HINT_DEFAULT_NONE; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_0 ); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_1 ); + } + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE , min, max); + } + + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM , min, max); + } + + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW, min, max); + } + + virtual void addNumEntry(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrdis(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { + addPortDescrdis(OCONTROL, label, 0, -10000, +10000); + } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { + addPortDescrdis(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + addPortDescrdis(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){ + addPortDescrdis(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox(const char* label) { openAnyBox(label); } + virtual void openTabBox(const char* label) { openAnyBox(label); } + virtual void openHorizontalBox(const char* label) { openAnyBox(label); } + virtual void openVerticalBox(const char* label) { openAnyBox(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor) { + const char* name = sym(distdsp); + descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor->PortDescriptors = fPortDescs; + descriptor->PortNames = fPortNames; + descriptor->PortRangeHints = fPortHints; + + descriptor->Label = "guitarix-distortion"; + descriptor->UniqueID = 4061; +// descriptor->Label = strdup(fPluginName.c_str()); +// descriptor->UniqueID = makeID(fPluginName.c_str()); + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = name; +// descriptor->Name = strdup(fPluginName.c_str()); + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + } +}; + + + + +//--------------------------------------portData---------------------------------------- +// +// portData : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone[MAXPORT]; // + float* fPortData[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone(float* zone) + { + fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData() {} + + + //------------------------------Collect the control zones------------------------------- + + virtual void addButton(const char* label, float* zone) { addZone(zone); } + virtual void addToggleButton(const char* label, float* zone) { addZone(zone); } + virtual void addCheckButton(const char* label, float* zone) { addZone(zone); } + + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addNumEntry(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addZone(zone); } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + + virtual void openFrameBox(const char* label) { } + virtual void openTabBox(const char* label) { } + virtual void openHorizontalBox(const char* label) { } + virtual void openVerticalBox(const char* label) { } + virtual void closeBox() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortData (unsigned long port, LADSPA_Data* data) { + fPortData[port] = data; + } + + void updateCtrlZones() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i]; + } + + float** getInputs() { + return &fPortData[0]; + } + + float** getOutputs() { + return &fPortData[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptord = 0; + +struct PLUGIN +{ + unsigned long fSampleRate; + portData* fPortData; + dsp* fDsp; + + PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {} +}; + +LADSPA_Handle instantiate_methoddis (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dsp* p = new distdsp(); + portData* d = new portData(p->getNumInputs(), p->getNumOutputs()); + + p->buildUserInterface(d); + return new PLUGIN (SampleRate, d, p); +} + +void connect_methoddis (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->setPortData(Port, DataLocation); +} + +void activate_methoddis (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fDsp->initdis(p->fSampleRate); +} + +void run_methoddis (LADSPA_Handle Instance, unsigned long SampleCount) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->updateCtrlZones(); + p->fDsp->compute(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs()); +} + +void deactivate_methoddis (LADSPA_Handle Instance) +{ +} + +void cleanup_methoddis (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + delete p->fPortData; + delete p->fDsp; + delete p; +} + + +//-------------------------------------------------------------------------------------- + +void initdis_descriptor(LADSPA_Descriptor* descriptor) +{ + descriptor->UniqueID = 4061; + descriptor->Label = "distortion"; + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = "distortion"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + + descriptor->ImplementationData = 0; + + // description des methoddiss + descriptor->instantiate = instantiate_methoddis; + descriptor->connect_port = connect_methoddis; + descriptor->activate = activate_methoddis; + descriptor->run = run_methoddis; + descriptor->run_adding = 0; + descriptor->set_run_adding_gain = 0; + descriptor->deactivate = deactivate_methoddis; + descriptor->cleanup = cleanup_methoddis; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptord == 0) + { + // allocate temporaries dsp and portCollector to build the plugin description + distdsp* p = new distdsp(); + if (p) { + portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs()); + p->buildUserInterface(c); + gDescriptord = new LADSPA_Descriptor; + initdis_descriptor(gDescriptord); + c->fillPortDescription(gDescriptord); + delete p; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptord; + } else { + return NULL; + } +} + diff --git a/ladspa/echo.cpp b/ladspa/echo.cpp new file mode 100644 index 0000000..43b7bd2 --- /dev/null +++ b/ladspa/echo.cpp @@ -0,0 +1,685 @@ +//----------------------------------------------------- +// name: "echo" +// version: "0.1" +// author: "brummer" +// license: "GPL" +// +// Code generated with Faust 0.9.9.4k-par (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "echo"); + m->declare("version", "0.1"); + m->declare("author", "brummer"); + m->declare("license", "GPL"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classinitech(int samplingFreq) { + } + virtual void instanceinitech(int samplingFreq) { + fSamplingFreq = samplingFreq; + fslider0 = 0.0f; + fConst0 = (1.000000e-03f * fSamplingFreq); + fslider1 = 0.0f; + IOTA = 0; + for (int i=0; i<262144; i++) fRec0[i] = 0; + fcheckbox0 = 1.0; + } + virtual void initech(int samplingFreq) { + classinitech(samplingFreq); + instanceinitech(samplingFreq); + } + virtual void buildUserInterfaceech(UI* interface) { + interface->openHorizontalBox("echo"); + interface->addVerticalSlider("release", &fslider1, 0.0f, 0.0f, 100.0f, 0.1f); + interface->addVerticalSlider("time", &fslider0, 1.0f, 1.0f, 2000.0f, 1.0f); + interface->closeBox(); + } + virtual void computeech (int count, float** input, float** output) { + int iSlow0 = int((1 + int((int((int((fConst0 * fslider0)) - 1)) & 131071)))); + float fSlow1 = (1.000000e-02f * fslider1); + int iSlow2 = int(fcheckbox0); + float* input0 = input[0]; + float* output0 = output[0]; + for (int i=0; i fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescrechech(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBoxech(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_0 ); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_1 ); + } + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE , min, max); + } + + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM , min, max); + } + + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW, min, max); + } + + virtual void addNumEntry(const char* label, float* zone, float initech, float min, float max, float step) { + addPortDescrechech(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { + addPortDescrechech(OCONTROL, label, 0, -10000, +10000); + } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { + addPortDescrechech(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + addPortDescrechech(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){ + addPortDescrechech(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox(const char* label) { openAnyBoxech(label); } + virtual void openTabBox(const char* label) { openAnyBoxech(label); } + virtual void openHorizontalBox(const char* label) { openAnyBoxech(label); } + virtual void openVerticalBox(const char* label) { openAnyBoxech(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor) { + const char* name = sym(echodsp); + descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor->PortDescriptors = fPortDescs; + descriptor->PortNames = fPortNames; + descriptor->PortRangeHints = fPortHints; + + descriptor->Label = strdup(name); + descriptor->UniqueID = 4063; +// descriptor->Label = strdup(fPluginName.c_str()); +// descriptor->UniqueID = makeID(fPluginName.c_str()); + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = name; +// descriptor->Name = strdup(fPluginName.c_str()); + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + } +}; + + + + +//--------------------------------------portData---------------------------------------- +// +// portData : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone[MAXPORT]; // + float* fPortData[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone(float* zone) + { + fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData() {} + + + //------------------------------Collect the control zones------------------------------- + + virtual void addButton(const char* label, float* zone) { addZone(zone); } + virtual void addToggleButton(const char* label, float* zone) { addZone(zone); } + virtual void addCheckButton(const char* label, float* zone) { addZone(zone); } + + virtual void addVerticalSlider(const char* label, float* zone, float initech, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addHorizontalSlider(const char* label, float* zone, float initech, float min, float max, float step) { addZone(zone); } + virtual void addNumEntry(const char* label, float* zone, float initech, float min, float max, float step) { addZone(zone); } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addZone(zone); } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + + virtual void openFrameBox(const char* label) { } + virtual void openTabBox(const char* label) { } + virtual void openHorizontalBox(const char* label) { } + virtual void openVerticalBox(const char* label) { } + virtual void closeBox() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortDataech (unsigned long port, LADSPA_Data* data) { + fPortData[port] = data; + } + + void updateCtrlZones() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i]; + } + + float** getInputs() { + return &fPortData[0]; + } + + float** getOutputs() { + return &fPortData[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptore = 0; + +struct PLUGIN +{ + unsigned long fSampleRate; + portData* fPortData; + dsp* fDsp; + + PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {} +}; + +LADSPA_Handle instantiate_methodech (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dsp* p = new echodsp(); + portData* d = new portData(p->getNumInputs(), p->getNumOutputs()); + + p->buildUserInterfaceech(d); + return new PLUGIN (SampleRate, d, p); +} + +void connect_methodech (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->setPortDataech(Port, DataLocation); +} + +void activate_methodech (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fDsp->initech(p->fSampleRate); +} + +void run_methodech (LADSPA_Handle Instance, unsigned long SampleCount) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->updateCtrlZones(); + p->fDsp->computeech(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs()); +} + +void deactivate_methodech (LADSPA_Handle Instance) +{ +} + +void cleanup_methodech (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + delete p->fPortData; + delete p->fDsp; + delete p; +} + + +//-------------------------------------------------------------------------------------- + +void initech_descriptor(LADSPA_Descriptor* descriptor) +{ + descriptor->UniqueID = 4063; + descriptor->Label = "echo"; + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = "echo"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + + descriptor->ImplementationData = 0; + + // description des methodechs + descriptor->instantiate = instantiate_methodech; + descriptor->connect_port = connect_methodech; + descriptor->activate = activate_methodech; + descriptor->run = run_methodech; + descriptor->run_adding = 0; + descriptor->set_run_adding_gain = 0; + descriptor->deactivate = deactivate_methodech; + descriptor->cleanup = cleanup_methodech; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptore == 0) + { + // allocate temporaries dsp and portCollector to build the plugin description + echodsp* p = new echodsp(); + if (p) { + portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs()); + p->buildUserInterfaceech(c); + gDescriptore = new LADSPA_Descriptor; + initech_descriptor(gDescriptore); + c->fillPortDescription(gDescriptore); + delete p; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptore; + } else { + return NULL; + } +} + diff --git a/ladspa/freeverb.cpp b/ladspa/freeverb.cpp new file mode 100644 index 0000000..460d2b4 --- /dev/null +++ b/ladspa/freeverb.cpp @@ -0,0 +1,807 @@ +//----------------------------------------------------- +// name: "freeverb" +// version: "0.1" +// author: "brummer" +// license: "GPL" +// +// Code generated with Faust 0.9.9.4k-par (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "freeverb"); + m->declare("version", "0.1"); + m->declare("author", "brummer"); + m->declare("license", "GPL"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classinitfree(int samplingFreq) { + } + virtual void instanceinitfree(int samplingFreq) { + fSamplingFreq = samplingFreq; + fslider0 = 0.3333f; + fslider1 = 0.5f; + for (int i=0; i<2; i++) fRec9[i] = 0; + fslider2 = 0.5f; + IOTA = 0; + for (int i=0; i<2048; i++) fVec0[i] = 0; + for (int i=0; i<2; i++) fRec8[i] = 0; + for (int i=0; i<2; i++) fRec11[i] = 0; + for (int i=0; i<2048; i++) fVec1[i] = 0; + for (int i=0; i<2; i++) fRec10[i] = 0; + for (int i=0; i<2; i++) fRec13[i] = 0; + for (int i=0; i<2048; i++) fVec2[i] = 0; + for (int i=0; i<2; i++) fRec12[i] = 0; + for (int i=0; i<2; i++) fRec15[i] = 0; + for (int i=0; i<2048; i++) fVec3[i] = 0; + for (int i=0; i<2; i++) fRec14[i] = 0; + for (int i=0; i<2; i++) fRec17[i] = 0; + for (int i=0; i<2048; i++) fVec4[i] = 0; + for (int i=0; i<2; i++) fRec16[i] = 0; + for (int i=0; i<2; i++) fRec19[i] = 0; + for (int i=0; i<2048; i++) fVec5[i] = 0; + for (int i=0; i<2; i++) fRec18[i] = 0; + for (int i=0; i<2; i++) fRec21[i] = 0; + for (int i=0; i<2048; i++) fVec6[i] = 0; + for (int i=0; i<2; i++) fRec20[i] = 0; + for (int i=0; i<2; i++) fRec23[i] = 0; + for (int i=0; i<2048; i++) fVec7[i] = 0; + for (int i=0; i<2; i++) fRec22[i] = 0; + for (int i=0; i<1024; i++) fVec8[i] = 0; + for (int i=0; i<2; i++) fRec6[i] = 0; + for (int i=0; i<512; i++) fVec9[i] = 0; + for (int i=0; i<2; i++) fRec4[i] = 0; + for (int i=0; i<512; i++) fVec10[i] = 0; + for (int i=0; i<2; i++) fRec2[i] = 0; + for (int i=0; i<256; i++) fVec11[i] = 0; + for (int i=0; i<2; i++) fRec0[i] = 0; + fcheckbox0 = 1.0; + } + virtual void initfree(int samplingFreq) { + classinitfree(samplingFreq); + instanceinitfree(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openVerticalBox("freeverb"); + interface->addVerticalSlider("RoomSize", &fslider2, 0.5f, 0.0f, 1.0f, 2.500000e-02f); + interface->addVerticalSlider("damp", &fslider1, 0.5f, 0.0f, 1.0f, 2.500000e-02f); + interface->addHorizontalSlider("dry/wet/", &fslider0, 0.3333f, 0.0f, 1.0f, 2.500000e-02f); + interface->closeBox(); + } + virtual void computfr (int count, float** input, float** output) { + float fSlow0 = fslider0; + float fSlow1 = (2 * (1 - fSlow0)); + float fSlow2 = (0.4f * fslider1); + float fSlow3 = (1 - fSlow2); + float fSlow4 = (0.7f + (0.28f * fslider2)); + int iSlow5 = int(fcheckbox0); + float* input0 = input[0]; + float* output0 = output[0]; + for (int i=0; i fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescrfr(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBox(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_0 ); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_1 ); + } + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE , min, max); + } + + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM , min, max); + } + + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW, min, max); + } + + virtual void addNumEntry(const char* label, float* zone, float initfree, float min, float max, float step) { + addPortDescrfr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { + addPortDescrfr(OCONTROL, label, 0, -10000, +10000); + } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { + addPortDescrfr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + addPortDescrfr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){ + addPortDescrfr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox(const char* label) { openAnyBox(label); } + virtual void openTabBox(const char* label) { openAnyBox(label); } + virtual void openHorizontalBox(const char* label) { openAnyBox(label); } + virtual void openVerticalBox(const char* label) { openAnyBox(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor) { + const char* name = sym(frdsp); + descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor->PortDescriptors = fPortDescs; + descriptor->PortNames = fPortNames; + descriptor->PortRangeHints = fPortHints; + + descriptor->Label = strdup(name); + descriptor->UniqueID = 4064; +// descriptor->Label = strdup(fPluginName.c_str()); +// descriptor->UniqueID = makeID(fPluginName.c_str()); + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = name; +// descriptor->Name = strdup(fPluginName.c_str()); + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + } +}; + + + + +//--------------------------------------portData---------------------------------------- +// +// portData : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone[MAXPORT]; // + float* fPortData[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone(float* zone) + { + fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData() {} + + + //------------------------------Collect the control zones------------------------------- + + virtual void addButton(const char* label, float* zone) { addZone(zone); } + virtual void addToggleButton(const char* label, float* zone) { addZone(zone); } + virtual void addCheckButton(const char* label, float* zone) { addZone(zone); } + + virtual void addVerticalSlider(const char* label, float* zone, float initfree, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addHorizontalSlider(const char* label, float* zone, float initfree, float min, float max, float step) { addZone(zone); } + virtual void addNumEntry(const char* label, float* zone, float initfree, float min, float max, float step) { addZone(zone); } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addZone(zone); } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + + virtual void openFrameBox(const char* label) { } + virtual void openTabBox(const char* label) { } + virtual void openHorizontalBox(const char* label) { } + virtual void openVerticalBox(const char* label) { } + virtual void closeBox() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortDatafr (unsigned long port, LADSPA_Data* data) { + fPortData[port] = data; + } + + void updateCtrlZonesfr() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i]; + } + + float** getInputs() { + return &fPortData[0]; + } + + float** getOutputs() { + return &fPortData[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptorfe = 0; + +struct PLUGIN +{ + unsigned long fSampleRate; + portData* fPortData; + dsp* fDsp; + + PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {} +}; + +LADSPA_Handle instantiate_methodfr (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dsp* p = new frdsp(); + portData* d = new portData(p->getNumInputs(), p->getNumOutputs()); + + p->buildUserInterface(d); + return new PLUGIN (SampleRate, d, p); +} + +void connect_methodfr (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->setPortDatafr(Port, DataLocation); +} + +void activate_methodfr (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fDsp->initfree(p->fSampleRate); +} + +void run_methodfr (LADSPA_Handle Instance, unsigned long SampleCount) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->updateCtrlZonesfr(); + p->fDsp->computfr(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs()); +} + +void deactivate_methodfr (LADSPA_Handle Instance) +{ +} + +void cleanup_methodfr (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + delete p->fPortData; + delete p->fDsp; + delete p; +} + + +//-------------------------------------------------------------------------------------- + +void initfree_descriptor(LADSPA_Descriptor* descriptor) +{ + descriptor->UniqueID = 4064; + descriptor->Label = "freeverb"; + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = "freeverb"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + + descriptor->ImplementationData = 0; + + // description des methodfrs + descriptor->instantiate = instantiate_methodfr; + descriptor->connect_port = connect_methodfr; + descriptor->activate = activate_methodfr; + descriptor->run = run_methodfr; + descriptor->run_adding = 0; + descriptor->set_run_adding_gain = 0; + descriptor->deactivate = deactivate_methodfr; + descriptor->cleanup = cleanup_methodfr; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptorfe == 0) + { + // allocate temporaries dsp and portCollector to build the plugin description + frdsp* p = new frdsp(); + if (p) { + portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs()); + p->buildUserInterface(c); + gDescriptorfe = new LADSPA_Descriptor; + initfree_descriptor(gDescriptorfe); + c->fillPortDescription(gDescriptorfe); + delete p; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptorfe; + } else { + return NULL; + } +} + diff --git a/ladspa/guitarix-ladspa.cpp b/ladspa/guitarix-ladspa.cpp new file mode 100644 index 0000000..8df607c --- /dev/null +++ b/ladspa/guitarix-ladspa.cpp @@ -0,0 +1,1140 @@ +//----------------------------------------------------- +// name : "guitarix" +// version : "0.02.7" +// author : "brummer" +// contributors : "Julius O. Smith (jos at ccrma.stanford.edu)" +// license : "BSD" +// copyright : "(c)brummer 2008" +// reference : "http://ccrma.stanford.edu/realsimple/faust_strings/" +// +// Code generated with Faust 0.9.9.4f (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "guitarix"); + m->declare("version", "0.01"); + m->declare("author", "brummer"); + m->declare("contributor", "Julius O. Smith (jos at ccrma.stanford.edu)"); + m->declare("license", "BSD"); + m->declare("copyright", "(c)brummer 2008"); + m->declare("reference", "http://ccrma.stanford.edu/realsimple/faust_strings/"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 2; } + static void classInit(int samplingFreq) { + } + virtual void instanceInit(int samplingFreq) { + fSamplingFreq = samplingFreq; + fslider13 = 0.0f; + fslider2 = 0.0f; + fslider1 = 0.0f; + fslider3 = 0.0f; + fslider7 = 0.0f; + fcheckbox1 = 0.0; + fslider4 = 0.64f; + fcheckbox2 = 0.0; + fslider6 = 0.5f; + fcheckbox4 = 0.0; + fslider10 = 440.0f; + fslider11 = 1.0f; + fcheckbox6 = 0.0; + fslider5 = 0.0f; + fcheckbox3 = 0.0; + fslider9 = 0.0f; + fslider8 = 0.0f; + fcheckbox5 = 0.0; + fslider0 = 0.0f; + fslider12 = 0.0f; + fConst0 = (7539.822754f / fSamplingFreq); + fConst1 = cosf(fConst0); + fConst2 = (1.414214f * sinf(fConst0)); + fConst3 = (1884.955688f / fSamplingFreq); + fConst4 = cosf(fConst3); + fConst5 = (1.414214f * sinf(fConst3)); + for (int i=0; i<2; i++) fVec0[i] = 0; + fcheckbox0 = 1.0; + for (int i=0; i<2; i++) fRec4[i] = 0; + for (int i=0; i<2; i++) fRec3[i] = 0; + fConst6 = tanf((15707.963867f / fSamplingFreq)); + fConst7 = (2 * (1 - (1.0f / (fConst6 * fConst6)))); + fConst8 = (1.0f / fConst6); + fConst9 = (1 + ((fConst8 - 0.765367f) / fConst6)); + fConst10 = (1.0f / (1 + ((0.765367f + fConst8) / fConst6))); + fConst11 = (1 + ((fConst8 - 1.847759f) / fConst6)); + fConst12 = (1.0f / (1 + ((1.847759f + fConst8) / fConst6))); + fConst13 = (408.407043f / fSamplingFreq); + fConst14 = (1 - fConst13); + fConst15 = (1.0f / tanf((0.5f * (((3.141593f * fSamplingFreq) - 4526.93457f) / fSamplingFreq)))); + fConst16 = (1 + fConst15); + fConst17 = (0 - ((fConst15 - 1) / fConst16)); + fConst18 = (1.0f / tanf((2272.725586f / fSamplingFreq))); + fConst19 = (fConst18 - 1); + fConst20 = (1.0f / (1 + fConst18)); + for (int i=0; i<2; i++) fRec15[i] = 0; + fConst21 = (1.0f / fConst16); + for (int i=0; i<2; i++) fRec14[i] = 0; + fConst22 = (1.0f / (1 + fConst13)); + for (int i=0; i<2; i++) fRec13[i] = 0; + for (int i=0; i<2; i++) fRec12[i] = 0; + for (int i=0; i<3; i++) fRec11[i] = 0; + for (int i=0; i<3; i++) fRec10[i] = 0; + for (int i=0; i<2; i++) fVec1[i] = 0; + for (int i=0; i<2; i++) fRec9[i] = 0; + for (int i=0; i<2; i++) fRec16[i] = 0; + for (int i=0; i<2; i++) fVec2[i] = 0; + for (int i=0; i<2; i++) fRec8[i] = 0; + for (int i=0; i<2; i++) fRec7[i] = 0; + for (int i=0; i<3; i++) fRec6[i] = 0; + for (int i=0; i<3; i++) fRec5[i] = 0; + for (int i=0; i<3; i++) fVec3[i] = 0; + for (int i=0; i<3; i++) fRec2[i] = 0; + for (int i=0; i<3; i++) fRec1[i] = 0; + for (int i=0; i<2; i++) fRec18[i] = 0; + fConst23 = (2827.43335f / fSamplingFreq); + fConst24 = (1413.716675f / fSamplingFreq); + for (int i=0; i<2; i++) fRec19[i] = 0; + for (int i=0; i<2; i++) fRec20[i] = 0; + for (int i=0; i<3; i++) fRec17[i] = 0; + for (int i=0; i<2; i++) fRec30[i] = 0; + IOTA = 0; + for (int i=0; i<2048; i++) fVec4[i] = 0; + for (int i=0; i<2; i++) fRec29[i] = 0; + for (int i=0; i<2; i++) fRec32[i] = 0; + for (int i=0; i<2048; i++) fVec5[i] = 0; + for (int i=0; i<2; i++) fRec31[i] = 0; + for (int i=0; i<2; i++) fRec34[i] = 0; + for (int i=0; i<2048; i++) fVec6[i] = 0; + for (int i=0; i<2; i++) fRec33[i] = 0; + for (int i=0; i<2; i++) fRec36[i] = 0; + for (int i=0; i<2048; i++) fVec7[i] = 0; + for (int i=0; i<2; i++) fRec35[i] = 0; + for (int i=0; i<2; i++) fRec38[i] = 0; + for (int i=0; i<2048; i++) fVec8[i] = 0; + for (int i=0; i<2; i++) fRec37[i] = 0; + for (int i=0; i<2; i++) fRec40[i] = 0; + for (int i=0; i<2048; i++) fVec9[i] = 0; + for (int i=0; i<2; i++) fRec39[i] = 0; + for (int i=0; i<2; i++) fRec42[i] = 0; + for (int i=0; i<2048; i++) fVec10[i] = 0; + for (int i=0; i<2; i++) fRec41[i] = 0; + for (int i=0; i<2; i++) fRec44[i] = 0; + for (int i=0; i<2048; i++) fVec11[i] = 0; + for (int i=0; i<2; i++) fRec43[i] = 0; + for (int i=0; i<1024; i++) fVec12[i] = 0; + for (int i=0; i<2; i++) fRec27[i] = 0; + for (int i=0; i<512; i++) fVec13[i] = 0; + for (int i=0; i<2; i++) fRec25[i] = 0; + for (int i=0; i<512; i++) fVec14[i] = 0; + for (int i=0; i<2; i++) fRec23[i] = 0; + for (int i=0; i<256; i++) fVec15[i] = 0; + for (int i=0; i<2; i++) fRec21[i] = 0; + for (int i=0; i<2; i++) fRec45[i] = 0; + fConst25 = (1.000000e-03f * fSamplingFreq); + for (int i=0; i<262144; i++) fRec46[i] = 0; + for (int i=0; i<3; i++) fVec16[i] = 0; + fConst26 = expf((0 - (314.159271f / fSamplingFreq))); + fConst27 = (6.283185f / fSamplingFreq); + fConst28 = (0.5f * (1 - (fConst26 * fConst26))); + for (int i=0; i<3; i++) fRec47[i] = 0; + for (int i=0; i<4; i++) fVec17[i] = 0; + for (int i=0; i<6; i++) fRec0[i] = 0; + + } + virtual void init(int samplingFreq) { + classInit(samplingFreq); + instanceInit(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openVerticalBox("guitarix"); + interface->addHorizontalSlider("balance", &fslider13, 0.0f, -1.0f, 1.0f, 1.000000e-03f); + interface->openHorizontalBox("tone"); + interface->addVerticalSlider("bass", &fslider2, 0.0f, -20.0f, 20.0f, 0.1f); + interface->addVerticalSlider("treble", &fslider1, 0.0f, -20.0f, 20.0f, 0.1f); + interface->closeBox(); + interface->openVerticalBox("gain"); + interface->openHorizontalBox(""); + interface->addVerticalSlider("in", &fslider3, 0.0f, -40.0f, 40.0f, 0.1f); + interface->addVerticalSlider("out", &fslider7, 0.0f, -40.0f, 40.0f, 0.1f); + interface->closeBox(); + interface->addToggleButton("preamp", &fcheckbox1); + interface->closeBox(); + interface->openVerticalBox("distortion"); + interface->addVerticalSlider("drive", &fslider4, 0.64f, 0.0f, 1.0f, 1.000000e-02f); + interface->addToggleButton("on/off", &fcheckbox2); + interface->closeBox(); + interface->openVerticalBox("freeverb"); + interface->addVerticalSlider("RoomSize", &fslider6, 0.5f, 0.0f, 1.0f, 2.500000e-02f); + interface->addToggleButton("on/off", &fcheckbox4); + interface->closeBox(); + interface->openVerticalBox("IR"); + interface->openHorizontalBox(""); + interface->addHorizontalSlider("frequency(Hz)", &fslider10, 440.0f, 20.0f, 2200.0f, 10.0f); + interface->addHorizontalSlider("peakgain", &fslider11, 1.0f, 0.0f, 10.0f, 0.2f); + interface->closeBox(); + interface->addToggleButton("on/off", &fcheckbox6); + interface->closeBox(); + interface->openVerticalBox("crybaby"); + interface->addVerticalSlider("wah", &fslider5, 0.0f, 0.0f, 1.0f, 1.000000e-02f); + interface->addToggleButton("on/off", &fcheckbox3); + interface->closeBox(); + interface->openVerticalBox("echo"); + interface->openHorizontalBox(""); + interface->addVerticalSlider("release", &fslider9, 0.0f, 0.0f, 100.0f, 0.1f); + interface->addVerticalSlider("time", &fslider8, 0.0f, 0.0f, 2000.0f, 1.0f); + interface->closeBox(); + interface->addToggleButton("on/off", &fcheckbox5); + interface->closeBox(); + interface->addHorizontalSlider("feedbackgain", &fslider0, 0.0f, -1.0f, 1.0f, 1.000000e-02f); + interface->addHorizontalSlider("feedforwardgain", &fslider12, 0.0f, -1.0f, 1.0f, 1.000000e-02f); + interface->closeBox(); + + } + virtual void compute (int count, float** input, float** output) { + float fSlow0 = fslider0; + float fSlow1 = powf(10, (2.500000e-02f * fslider1)); + float fSlow2 = (1 + fSlow1); + float fSlow3 = (fConst1 * fSlow2); + float fSlow4 = (2 * (0 - ((1 + fSlow3) - fSlow1))); + float fSlow5 = (fConst1 * (fSlow1 - 1)); + float fSlow6 = (fConst2 * sqrtf(fSlow1)); + float fSlow7 = (fSlow2 - (fSlow6 + fSlow5)); + float fSlow8 = powf(10, (2.500000e-02f * fslider2)); + float fSlow9 = (1 + fSlow8); + float fSlow10 = (fConst4 * fSlow9); + float fSlow11 = (0 - (2 * ((fSlow8 + fSlow10) - 1))); + float fSlow12 = (fConst5 * sqrtf(fSlow8)); + float fSlow13 = (fConst4 * (fSlow8 - 1)); + float fSlow14 = ((1 + (fSlow8 + fSlow13)) - fSlow12); + float fSlow15 = fcheckbox0; + float fSlow16 = (7.118644f * fSlow15); + int iSlow17 = int(fcheckbox1); + float fSlow18 = (9.999871e-04f * powf(10, (5.000000e-02f * fslider3))); + float fSlow19 = powf(10.0f, (2 * fslider4)); + int iSlow20 = int(fcheckbox2); + float fSlow21 = (fSlow9 - (fSlow12 + fSlow13)); + float fSlow22 = (2 * (0 - ((1 + fSlow10) - fSlow8))); + float fSlow23 = (fSlow8 + fSlow12); + float fSlow24 = ((1 + fSlow23) - fSlow13); + float fSlow25 = (1.0f / (1 + (fSlow13 + fSlow23))); + float fSlow26 = (fSlow1 * ((1 + (fSlow1 + fSlow5)) - fSlow6)); + float fSlow27 = (fSlow1 + fSlow6); + float fSlow28 = (fSlow1 * (1 + (fSlow5 + fSlow27))); + float fSlow29 = (((fSlow1 + fSlow3) - 1) * (0 - (2 * fSlow1))); + float fSlow30 = (1.0f / ((1 + fSlow27) - fSlow5)); + float fSlow31 = fslider5; + float fSlow32 = (9.999872e-05f * powf(4.0f, fSlow31)); + float fSlow33 = powf(2.0f, (2.3f * fSlow31)); + float fSlow34 = (1 - (fConst24 * (fSlow33 / powf(2.0f, (1.0f + (2.0f * (1.0f - fSlow31))))))); + float fSlow35 = (9.999871e-04f * (0 - (2.0f * (fSlow34 * cosf((fConst23 * fSlow33)))))); + float fSlow36 = (9.999871e-04f * (fSlow34 * fSlow34)); + int iSlow37 = int(fcheckbox3); + float fSlow38 = (0.7f + (0.28f * fslider6)); + int iSlow39 = int(fcheckbox4); + float fSlow40 = (9.999871e-04f * powf(10, (5.000000e-02f * fslider7))); + int iSlow41 = int((1 + int((int((int((fConst25 * fslider8)) - 1)) & 131071)))); + float fSlow42 = (1.000000e-02f * fslider9); + int iSlow43 = int(fcheckbox5); + float fSlow44 = (2 * cosf((fConst27 * fslider10))); + float fSlow45 = (fConst28 * fslider11); + int iSlow46 = int(fcheckbox6); + float fSlow47 = fslider12; + float fSlow48 = fslider13; + float fSlow49 = (1 - max(0, fSlow48)); + float fSlow50 = (1 - max(0, (0 - fSlow48))); + float* input0 = input[0]; + float* output0 = output[0]; + float* output1 = output[1]; + for (int i=0; i0; i--) fRec0[i] = fRec0[i-1]; + for (int i=3; i>0; i--) fVec17[i] = fVec17[i-1]; + fRec47[2] = fRec47[1]; fRec47[1] = fRec47[0]; + fVec16[2] = fVec16[1]; fVec16[1] = fVec16[0]; + fRec45[1] = fRec45[0]; + fRec21[1] = fRec21[0]; + fRec23[1] = fRec23[0]; + fRec25[1] = fRec25[0]; + fRec27[1] = fRec27[0]; + fRec43[1] = fRec43[0]; + fRec44[1] = fRec44[0]; + fRec41[1] = fRec41[0]; + fRec42[1] = fRec42[0]; + fRec39[1] = fRec39[0]; + fRec40[1] = fRec40[0]; + fRec37[1] = fRec37[0]; + fRec38[1] = fRec38[0]; + fRec35[1] = fRec35[0]; + fRec36[1] = fRec36[0]; + fRec33[1] = fRec33[0]; + fRec34[1] = fRec34[0]; + fRec31[1] = fRec31[0]; + fRec32[1] = fRec32[0]; + fRec29[1] = fRec29[0]; + IOTA = IOTA+1; + fRec30[1] = fRec30[0]; + fRec17[2] = fRec17[1]; fRec17[1] = fRec17[0]; + fRec20[1] = fRec20[0]; + fRec19[1] = fRec19[0]; + fRec18[1] = fRec18[0]; + fRec1[2] = fRec1[1]; fRec1[1] = fRec1[0]; + fRec2[2] = fRec2[1]; fRec2[1] = fRec2[0]; + fVec3[2] = fVec3[1]; fVec3[1] = fVec3[0]; + fRec5[2] = fRec5[1]; fRec5[1] = fRec5[0]; + fRec6[2] = fRec6[1]; fRec6[1] = fRec6[0]; + fRec7[1] = fRec7[0]; + fRec8[1] = fRec8[0]; + fVec2[1] = fVec2[0]; + fRec16[1] = fRec16[0]; + fRec9[1] = fRec9[0]; + fVec1[1] = fVec1[0]; + fRec10[2] = fRec10[1]; fRec10[1] = fRec10[0]; + fRec11[2] = fRec11[1]; fRec11[1] = fRec11[0]; + fRec12[1] = fRec12[0]; + fRec13[1] = fRec13[0]; + fRec14[1] = fRec14[0]; + fRec15[1] = fRec15[0]; + fRec3[1] = fRec3[0]; + fRec4[1] = fRec4[0]; + fVec0[1] = fVec0[0]; + } + } +}; + + + + + + + +//-----------------------------------portCollector-------------------------------------- +// +// portCollector is passed to the buildUserInterface method of a dsp object +// in order to build a description of its inputs, outputs and control ports. +// This description is used to fill a LADSPA_Descriptor +// +//-------------------------------------------------------------------------------------- + + + +//--------------------------------useful constants-------------------------------------- + +#define MAXPORT 1024 +static const int ICONTROL = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL; +static const int OCONTROL = LADSPA_PORT_OUTPUT|LADSPA_PORT_CONTROL; +static const int RANGE = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL; + +static const char* inames[] = { + "input00", "input01", "input02", "input03", "input04", + "input05", "input06", "input07", "input08", "input09", + "input10", "input11", "input12", "input13", "input14", + "input15", "input16", "input17", "input18", "input19", + "input20", "input21", "input22", "input23", "input24", + "input25", "input26", "input27", "input28", "input29", + "input30", "input31", "input32", "input33", "input34", + "input35", "input36", "input37", "input38", "input39" +}; + +static const char* onames[] = { + "output00", "output01", "output02", "output03", "output04", + "output05", "output06", "output07", "output08", "output09", + "output10", "output11", "output12", "output13", "output14", + "output15", "output16", "output17", "output18", "output19", + "output20", "output21", "output22", "output23", "output24", + "output25", "output26", "output27", "output28", "output29", + "output30", "output31", "output32", "output33", "output34", + "output35", "output36", "output37", "output38", "output39" +}; + + + +class portCollector : public UI +{ + private: + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + LADSPA_PortDescriptor fPortDescs[MAXPORT]; // table of port descriptors to be used in a LADSPA_Descriptor + const char* fPortNames[MAXPORT]; // table of port names to be used in a LADSPA_Descriptor + LADSPA_PortRangeHint fPortHints[MAXPORT]; // table of port hints to be used in a LADSPA_Descriptor + + string fPluginName; // toplevel prefix used as plugin name + stack fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescr(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBox(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone) { + addPortDescr(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescr(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescr(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) { + addPortDescr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) { + addPortDescr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) { + addPortDescr(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { + addPortDescr(OCONTROL, label, 0, -10000, +10000); + } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { + addPortDescr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + addPortDescr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){ + addPortDescr(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox(const char* label) { openAnyBox(label); } + virtual void openTabBox(const char* label) { openAnyBox(label); } + virtual void openHorizontalBox(const char* label) { openAnyBox(label); } + virtual void openVerticalBox(const char* label) { openAnyBox(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor) { + const char* name = sym(mydsp); + descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor->PortDescriptors = fPortDescs; + descriptor->PortNames = fPortNames; + descriptor->PortRangeHints = fPortHints; + + descriptor->Label = "Simulators"; + descriptor->UniqueID = 4068; +// descriptor->Label = strdup(fPluginName.c_str()); +// descriptor->UniqueID = makeID(fPluginName.c_str()); + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = name; +// descriptor->Name = "monoamlifier"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + } +}; + + + + +//--------------------------------------portData---------------------------------------- +// +// portData : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone[MAXPORT]; // + float* fPortData[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone(float* zone) + { + fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData() {} + + + //------------------------------Collect the control zones------------------------------- + + virtual void addButton(const char* label, float* zone) { addZone(zone); } + virtual void addToggleButton(const char* label, float* zone) { addZone(zone); } + virtual void addCheckButton(const char* label, float* zone) { addZone(zone); } + + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) { addZone(zone); } + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) { addZone(zone); } + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) { addZone(zone); } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addZone(zone); } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + + virtual void openFrameBox(const char* label) { } + virtual void openTabBox(const char* label) { } + virtual void openHorizontalBox(const char* label) { } + virtual void openVerticalBox(const char* label) { } + virtual void closeBox() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortData (unsigned long port, LADSPA_Data* data) { + fPortData[port] = data; + } + + void updateCtrlZones() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i]; + } + + float** getInputs() { + return &fPortData[0]; + } + + float** getOutputs() { + return &fPortData[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptor = 0; + +struct PLUGIN +{ + unsigned long fSampleRate; + portData* fPortData; + dsp* fDsp; + + PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {} +}; + +LADSPA_Handle instantiate_method (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dsp* p = new mydsp(); + portData* d = new portData(p->getNumInputs(), p->getNumOutputs()); + + p->buildUserInterface(d); + return new PLUGIN (SampleRate, d, p); +} + +void connect_method (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->setPortData(Port, DataLocation); +} + +void activate_method (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fDsp->init(p->fSampleRate); +} + +void run_method (LADSPA_Handle Instance, unsigned long SampleCount) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->updateCtrlZones(); + p->fDsp->compute(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs()); +} + +void deactivate_method (LADSPA_Handle Instance) +{ +} + +void cleanup_method (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + delete p->fPortData; + delete p->fDsp; + delete p; +} + + +//-------------------------------------------------------------------------------------- + +void init_descriptor(LADSPA_Descriptor* descriptor) +{ + descriptor->UniqueID = 4068; + descriptor->Label = "Simulators"; + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = "guitarix"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + + descriptor->ImplementationData = 0; + + // description des methods + descriptor->instantiate = instantiate_method; + descriptor->connect_port = connect_method; + descriptor->activate = activate_method; + descriptor->run = run_method; + descriptor->run_adding = 0; + descriptor->set_run_adding_gain = 0; + descriptor->deactivate = deactivate_method; + descriptor->cleanup = cleanup_method; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptor == 0) + { + // allocate temporaries dsp and portCollector to build the plugin description + mydsp* p = new mydsp(); + if (p) { + portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs()); + p->buildUserInterface(c); + gDescriptor = new LADSPA_Descriptor; + init_descriptor(gDescriptor); + c->fillPortDescription(gDescriptor); + delete p; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptor; + } else { + return NULL; + } +} + diff --git a/ladspa/guitarix.rdf b/ladspa/guitarix.rdf new file mode 100644 index 0000000..2bbd4a1 --- /dev/null +++ b/ladspa/guitarix.rdf @@ -0,0 +1,49 @@ + + + + + +]> + + + brummer + guitarix-distortion + + + + brummer + guitarix-crybaby + + + + brummer + guitarix-echo + + + + brummer + guitarix-freeverb + + + + brummer + guitarix-IR + + + + brummer + guitarix-monoamp + + + + brummer + guitarix-monocompressor + + + + brummer + guitarix + + + diff --git a/ladspa/impulseresponse.cpp b/ladspa/impulseresponse.cpp new file mode 100644 index 0000000..01cbfd3 --- /dev/null +++ b/ladspa/impulseresponse.cpp @@ -0,0 +1,693 @@ +//----------------------------------------------------- +// name: "impulseresponse" +// version: "0.1" +// author: "brummer" +// license: "GPL" +// +// Code generated with Faust 0.9.9.4k-par (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "impulseresponse"); + m->declare("version", "0.1"); + m->declare("author", "brummer"); + m->declare("license", "GPL"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classinitir(int samplingFreq) { + } + virtual void instanceinitir(int samplingFreq) { + fSamplingFreq = samplingFreq; + for (int i=0; i<3; i++) fVec0[i] = 0; + fslider0 = 100.0f; + fConst0 = (3.141593f / fSamplingFreq); + fslider1 = 440.0f; + fConst1 = (6.283185f / fSamplingFreq); + fslider2 = 1.0f; + for (int i=0; i<3; i++) fRec0[i] = 0; + fcheckbox0 = 1.0; + } + virtual void initir(int samplingFreq) { + classinitir(samplingFreq); + instanceinitir(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openHorizontalBox("IR"); + interface->addVerticalSlider0("bandwidth(Hz)", &fslider0, 100.0f, 20.0f, 20000.0f, 10.0f); + interface->addVerticalSlider("frequency(Hz)", &fslider1, 440.0f, 20.0f, 2200.0f, 10.0f); + interface->addHorizontalSlider("peakgain", &fslider2, 1.0f, 0.0f, 10.0f, 0.2f); + interface->closeBox(); + } + virtual void compute (int count, float** input, float** output) { + float fSlow0 = expf((0 - (fConst0 * fslider0))); + float fSlow1 = (2 * cosf((fConst1 * fslider1))); + float fSlow2 = (0.5f * (fslider2 * (1 - (fSlow0 * fSlow0)))); + int iSlow3 = int(fcheckbox0); + float* input0 = input[0]; + float* output0 = output[0]; + for (int i=0; i fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescrir(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBox(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_0 ); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_1 ); + } + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE , min, max); + } + + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM , min, max); + } + + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW, min, max); + } + + virtual void addNumEntry(const char* label, float* zone, float initir, float min, float max, float step) { + addPortDescrir(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { + addPortDescrir(OCONTROL, label, 0, -10000, +10000); + } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { + addPortDescrir(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + addPortDescrir(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){ + addPortDescrir(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox(const char* label) { openAnyBox(label); } + virtual void openTabBox(const char* label) { openAnyBox(label); } + virtual void openHorizontalBox(const char* label) { openAnyBox(label); } + virtual void openVerticalBox(const char* label) { openAnyBox(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor) { + const char* name = sym(irdsp); + descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor->PortDescriptors = fPortDescs; + descriptor->PortNames = fPortNames; + descriptor->PortRangeHints = fPortHints; + + descriptor->Label = strdup(name); + descriptor->UniqueID = 4065; +// descriptor->Label = strdup(fPluginName.c_str()); +// descriptor->UniqueID = makeID(fPluginName.c_str()); + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = name; +// descriptor->Name = strdup(fPluginName.c_str()); + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + } +}; + + + + +//--------------------------------------portData---------------------------------------- +// +// portData : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone[MAXPORT]; // + float* fPortData[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone(float* zone) + { + fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData() {} + + + //------------------------------Collect the control zones------------------------------- + + virtual void addButton(const char* label, float* zone) { addZone(zone); } + virtual void addToggleButton(const char* label, float* zone) { addZone(zone); } + virtual void addCheckButton(const char* label, float* zone) { addZone(zone); } + + virtual void addVerticalSlider(const char* label, float* zone, float initir, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addHorizontalSlider(const char* label, float* zone, float initir, float min, float max, float step) { addZone(zone); } + virtual void addNumEntry(const char* label, float* zone, float initir, float min, float max, float step) { addZone(zone); } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addZone(zone); } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + + virtual void openFrameBox(const char* label) { } + virtual void openTabBox(const char* label) { } + virtual void openHorizontalBox(const char* label) { } + virtual void openVerticalBox(const char* label) { } + virtual void closeBox() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortDatair (unsigned long port, LADSPA_Data* data) { + fPortData[port] = data; + } + + void updateCtrlZones() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i]; + } + + float** getInputs() { + return &fPortData[0]; + } + + float** getOutputs() { + return &fPortData[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptori = 0; + +struct PLUGIN +{ + unsigned long fSampleRate; + portData* fPortData; + dsp* fDsp; + + PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {} +}; + +LADSPA_Handle instantiate_methodir (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dsp* p = new irdsp(); + portData* d = new portData(p->getNumInputs(), p->getNumOutputs()); + + p->buildUserInterface(d); + return new PLUGIN (SampleRate, d, p); +} + +void connect_methodir (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->setPortDatair(Port, DataLocation); +} + +void activate_methodir (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fDsp->initir(p->fSampleRate); +} + +void run_methodir (LADSPA_Handle Instance, unsigned long SampleCount) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->updateCtrlZones(); + p->fDsp->compute(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs()); +} + +void deactivate_methodir (LADSPA_Handle Instance) +{ +} + +void cleanup_methodir (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + delete p->fPortData; + delete p->fDsp; + delete p; +} + + +//-------------------------------------------------------------------------------------- + +void initir_descriptor(LADSPA_Descriptor* descriptor) +{ + descriptor->UniqueID = 4065; + descriptor->Label = "ImpulseResponse"; + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = "IR"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + + descriptor->ImplementationData = 0; + + // description des methodirs + descriptor->instantiate = instantiate_methodir; + descriptor->connect_port = connect_methodir; + descriptor->activate = activate_methodir; + descriptor->run = run_methodir; + descriptor->run_adding = 0; + descriptor->set_run_adding_gain = 0; + descriptor->deactivate = deactivate_methodir; + descriptor->cleanup = cleanup_methodir; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptori == 0) + { + // allocate temporaries dsp and portCollector to build the plugin description + irdsp* p = new irdsp(); + if (p) { + portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs()); + p->buildUserInterface(c); + gDescriptori = new LADSPA_Descriptor; + initir_descriptor(gDescriptori); + c->fillPortDescription(gDescriptori); + delete p; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptori; + } else { + return NULL; + } +} + diff --git a/ladspa/monoamp.cpp b/ladspa/monoamp.cpp new file mode 100644 index 0000000..1a4fcbe --- /dev/null +++ b/ladspa/monoamp.cpp @@ -0,0 +1,760 @@ +//----------------------------------------------------- +// name: "monoamp" +// version: "0.1" +// author: "brummer" +// license: "GPL" +// +// Code generated with Faust 0.9.9.4k-par (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "monoamp"); + m->declare("version", "0.1"); + m->declare("author", "brummer"); + m->declare("license", "GPL"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classInit(int samplingFreq) { + } + virtual void instanceInit1(int samplingFreq) { + fSamplingFreq = samplingFreq; + fslideramp0 = 0.0f; + fslideramp1 = 0.0f; + fConstamp0 = (7539.822754f / fSamplingFreq); + fConstamp1 = cosf(fConstamp0); + fConstamp2 = (1.414214f * sinf(fConstamp0)); + fslideramp2 = 0.0f; + fConstamp3 = (1884.955688f / fSamplingFreq); + fConstamp4 = cosf(fConstamp3); + fConstamp5 = (1.414214f * sinf(fConstamp3)); + fcheckbox0 = 0.0; + fslideramp3 = 0.0f; + for (int i=0; i<2; i++) fRecamp3[i] = 0; + for (int i=0; i<3; i++) fVecamp0[i] = 0; + for (int i=0; i<3; i++) fRecamp2[i] = 0; + for (int i=0; i<4; i++) fRecamp1[i] = 0; + fslideramp4 = 0.0f; + for (int i=0; i<6; i++) fRecamp0[i] = 0; + } + virtual void initamp(int samplingFreq) { + classInit(samplingFreq); + instanceInit1(samplingFreq); + } + virtual void buildUserInterface1(UI* interface1) { + interface1->openHorizontalBox1("monoamp"); + //interface1->openVerticalBox1("preamp"); + interface1->addToggleButton("preamp", &fcheckbox0); + //interface1->closeBox1(); + interface1->addVerticalSlider("gain", &fslideramp3, 0.0f, -40.0f, 40.0f, 0.1f); + interface1->addVerticalSlider("bass", &fslideramp2, 0.0f, -20.0f, 20.0f, 0.1f); + interface1->addVerticalSlider("treble", &fslideramp1, 0.0f, -20.0f, 20.0f, 0.1f); + interface1->addVerticalSlider0("feedbackgain", &fslideramp0, 0.0f, 0.0f, 1.0f, 0.01f); + interface1->addVerticalSlider0("feedforwardgain", &fslideramp4, 0.0f, 0.0f, 1.0f, 0.01f); + interface1->closeBox1(); + } + virtual void computeamp (int count, float** input, float** output) { + float fSlowamp0 = fslideramp0; + float fSlowamp1 = powf(10, (2.500000e-02f * fslideramp1)); + float fSlowamp2 = (1 + fSlowamp1); + float fSlowamp3 = (fConstamp1 * fSlowamp2); + float fSlowamp4 = (2 * (0 - ((1 + fSlowamp3) - fSlowamp1))); + float fSlowamp5 = (fConstamp1 * (fSlowamp1 - 1)); + float fSlowamp6 = (fConstamp2 * sqrtf(fSlowamp1)); + float fSlowamp7 = (fSlowamp2 - (fSlowamp6 + fSlowamp5)); + float fSlowamp8 = powf(10, (2.500000e-02f * fslideramp2)); + float fSlowamp9 = (1 + fSlowamp8); + float fSlowamp10 = (fConstamp4 * fSlowamp9); + float fSlowamp11 = (0 - (2 * ((fSlowamp8 + fSlowamp10) - 1))); + float fSlowamp12 = (fConstamp5 * sqrtf(fSlowamp8)); + float fSlowamp13 = (fConstamp4 * (fSlowamp8 - 1)); + float fSlowamp14 = ((1 + (fSlowamp8 + fSlowamp13)) - fSlowamp12); + int iSlowamp15 = int(fcheckbox0); + float fSlowamp16 = (9.999871e-04f * powf(10, (5.000000e-02f * fslideramp3))); + float fSlowamp17 = (fSlowamp9 - (fSlowamp12 + fSlowamp13)); + float fSlowamp18 = (2 * (0 - ((1 + fSlowamp10) - fSlowamp8))); + float fSlowamp19 = (fSlowamp8 + fSlowamp12); + float fSlowamp20 = ((1 + fSlowamp19) - fSlowamp13); + float fSlowamp21 = (1.0f / (1 + (fSlowamp13 + fSlowamp19))); + float fSlowamp22 = (fSlowamp1 * ((1 + (fSlowamp1 + fSlowamp5)) - fSlowamp6)); + float fSlowamp23 = (fSlowamp1 + fSlowamp6); + float fSlowamp24 = (fSlowamp1 * (1 + (fSlowamp5 + fSlowamp23))); + float fSlowamp25 = (((fSlowamp1 + fSlowamp3) - 1) * (0 - (2 * fSlowamp1))); + float fSlowamp26 = (1.0f / ((1 + fSlowamp23) - fSlowamp5)); + float fSlowamp27 = fslideramp4; + float* input0 = input[0]; + float* output0 = output[0]; + for (int i=0; i=1.0) + in = 2/3.0; + else if (in<-1.0) + in = -2/3.0; + else in = (in - in*in*in/3.0); + Samp0[1] = in; + } //preamp ende + float fTempamp1 = (fRecamp3[0] * Samp0[iSlowamp15]); + fVecamp0[0] = fTempamp1; + fRecamp2[0] = (fSlowamp21 * ((fSlowamp8 * (((fSlowamp20 * fVecamp0[0]) + (fSlowamp18 * fVecamp0[1])) + (fSlowamp17 * fVecamp0[2]))) - ((fSlowamp14 * fRecamp2[2]) + (fSlowamp11 * fRecamp2[1])))); + fRecamp1[0] = (fSlowamp26 * ((((fSlowamp25 * fRecamp2[1]) + (fSlowamp24 * fRecamp2[0])) + (fSlowamp22 * fRecamp2[2])) + (0 - ((fSlowamp7 * fRecamp1[2]) + (fSlowamp4 * fRecamp1[1]))))); + fRecamp0[0] = ((fRecamp1[0] + (fSlowamp27 * fRecamp1[3])) - (fSlowamp0 * fRecamp0[5])); + output0[i] = fRecamp0[0]; + // post processing + for (int i=5; i>0; i--) fRecamp0[i] = fRecamp0[i-1]; + for (int i=3; i>0; i--) fRecamp1[i] = fRecamp1[i-1]; + fRecamp2[2] = fRecamp2[1]; fRecamp2[1] = fRecamp2[0]; + fVecamp0[2] = fVecamp0[1]; fVecamp0[1] = fVecamp0[0]; + fRecamp3[1] = fRecamp3[0]; + } + } +}; + + + + + + + +//-----------------------------------portCollector1-------------------------------------- +// +// portCollector1 is passed to the buildUserInterface1 method of a dsp object +// in order to build a description of its inputs, outputs and control ports. +// This description is used to fill a LADSPA_Descriptor +// +//-------------------------------------------------------------------------------------- + + + +//--------------------------------useful constants-------------------------------------- + +#define MAXPORT 1024 +static const int ICONTROL1 = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL; +static const int OCONTROL1 = LADSPA_PORT_OUTPUT|LADSPA_PORT_CONTROL; +static const int RANGE1 = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL; + +static const char* inames[] = { + "input00", "input01", "input02", "input03", "input04", + "input05", "input06", "input07", "input08", "input09", + "input10", "input11", "input12", "input13", "input14", + "input15", "input16", "input17", "input18", "input19", + "input20", "input21", "input22", "input23", "input24", + "input25", "input26", "input27", "input28", "input29", + "input30", "input31", "input32", "input33", "input34", + "input35", "input36", "input37", "input38", "input39" +}; + +static const char* onames[] = { + "output00", "output01", "output02", "output03", "output04", + "output05", "output06", "output07", "output08", "output09", + "output10", "output11", "output12", "output13", "output14", + "output15", "output16", "output17", "output18", "output19", + "output20", "output21", "output22", "output23", "output24", + "output25", "output26", "output27", "output28", "output29", + "output30", "output31", "output32", "output33", "output34", + "output35", "output36", "output37", "output38", "output39" +}; + + + +class portCollector1 : public UI +{ + private: + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + LADSPA_PortDescriptor fPortDescs[MAXPORT]; // table of port descriptors to be used in a LADSPA_Descriptor + const char* fPortNames[MAXPORT]; // table of port names to be used in a LADSPA_Descriptor + LADSPA_PortRangeHint fPortHints[MAXPORT]; // table of port hints to be used in a LADSPA_Descriptor + + string fPluginName; // toplevel prefix used as plugin name + stack fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescr1(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBox1(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector1(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector1() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone1) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_0 ); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_1 ); + } + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE , min, max); + } + + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM , min, max); + } + + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW, min, max); + } + + virtual void addNumEntry1(const char* label, float* zone1, float initamp, float min, float max, float step) { + addPortDescr1(ICONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE| LADSPA_HINT_DEFAULT_0, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay1(const char* label, float* zone1, int precision) { + addPortDescr1(OCONTROL1, label, 0, -10000, +10000); + } + virtual void addTextDisplay1(const char* label, float* zone1, char* names[], float min, float max) { + addPortDescr1(OCONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph1(const char* label, float* zone1, float min, float max) { + addPortDescr1(OCONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph1(const char* label, float* zone1, float min, float max){ + addPortDescr1(OCONTROL1, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox1(const char* label) { openAnyBox1(label); } + virtual void openTabBox1(const char* label) { openAnyBox1(label); } + virtual void openHorizontalBox1(const char* label) { openAnyBox1(label); } + virtual void openVerticalBox1(const char* label) { openAnyBox1(label); } + + virtual void closeBox1() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID1 (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor1) { + const char* name = sym(ampdsp); + descriptor1->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor1->PortDescriptors = fPortDescs; + descriptor1->PortNames = fPortNames; + descriptor1->PortRangeHints = fPortHints; + + descriptor1->Label = strdup(name); + descriptor1->UniqueID = 4066; +// descriptor1->Label = strdup(fPluginName.c_str()); +// descriptor1->UniqueID = makeID1(fPluginName.c_str()); + descriptor1->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor1->Name = name; +// descriptor1->Name = strdup(fPluginName.c_str()); + descriptor1->Maker = "brummer"; + descriptor1->Copyright = "GPL"; + } +}; + + + + +//--------------------------------------portData1---------------------------------------- +// +// portData1 : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData1 : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone1[MAXPORT]; // + float* fPortData1[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone1(float* zone1) + { + fPortZone1[fInsCount + fOutsCount + fCtrlCount] = zone1; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData1(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData1() {} + + + //------------------------------Collect the control zone1s------------------------------- + + virtual void addButton(const char* label, float* zone1) { addZone1(zone1); } + virtual void addToggleButton(const char* label, float* zone1) { addZone1(zone1); } + virtual void addCheckButton(const char* label, float* zone1) { addZone1(zone1); } + + virtual void addVerticalSlider(const char* label, float* zone1, float initamp, float min, float max, float step) { addZone1(zone1); } + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { addZone1(zone); } + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { addZone1(zone); } + virtual void addHorizontalSlider(const char* label, float* zone1, float initamp, float min, float max, float step) { addZone1(zone1); } + virtual void addNumEntry1(const char* label, float* zone1, float initamp, float min, float max, float step) { addZone1(zone1); } + + // -- passive widgets + + virtual void addNumDisplay1(const char* label, float* zone1, int precision) { addZone1(zone1); } + virtual void addTextDisplay1(const char* label, float* zone1, char* names[], float min, float max) { addZone1(zone1); } + virtual void addHorizontalBargraph1(const char* label, float* zone1, float min, float max) { addZone1(zone1); } + virtual void addVerticalBargraph1(const char* label, float* zone1, float min, float max) { addZone1(zone1); } + + virtual void openFrameBox1(const char* label) { } + virtual void openTabBox1(const char* label) { } + virtual void openHorizontalBox1(const char* label) { } + virtual void openVerticalBox1(const char* label) { } + virtual void closeBox1() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortData1 (unsigned long port, LADSPA_Data* data) { + fPortData1[port] = data; + } + + void updateCtrlZones1() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone1[i] = *fPortData1[i]; + } + + float** getInputs() { + return &fPortData1[0]; + } + + float** getOutputs() { + return &fPortData1[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptor1 = 0; + +struct PLUGIN1 +{ + unsigned long fSampleRate; + portData1* fPortData1; + dspamp* fDspamp; + + PLUGIN1(unsigned long r, portData1* d, dspamp* p) : fSampleRate(r), fPortData1(d), fDspamp(p) {} +}; + +LADSPA_Handle instantiate_method1 (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dspamp* p1 = new ampdsp(); + portData1* damp = new portData1(p1->getNumInputs(), p1->getNumOutputs()); + + p1->buildUserInterface1(damp); + return new PLUGIN1 (SampleRate, damp, p1); +} + +void connect_method1 (LADSPA_Handle Instance1, unsigned long Port, LADSPA_Data * DataLocation1) +{ + PLUGIN1* p1 = (PLUGIN1*) Instance1; + p1->fPortData1->setPortData1(Port, DataLocation1); +} + +void activate_method1 (LADSPA_Handle Instance1) +{ + PLUGIN1* p1 = (PLUGIN1*) Instance1; + p1->fDspamp->initamp(p1->fSampleRate); +} + +void run_method1 (LADSPA_Handle Instance1, unsigned long SampleCount) +{ + PLUGIN1* p1 = (PLUGIN1*) Instance1; + p1->fPortData1->updateCtrlZones1(); + p1->fDspamp->computeamp(SampleCount, p1->fPortData1->getInputs(), p1->fPortData1->getOutputs()); +} + +void deactivate_method1 (LADSPA_Handle Instance1) +{ +} + +void cleanup_method (LADSPA_Handle Instance1) +{ + PLUGIN1* p1 = (PLUGIN1*) Instance1; + delete p1->fPortData1; + delete p1->fDspamp; + delete p1; +} + + +//-------------------------------------------------------------------------------------- + +void initamp_descriptor(LADSPA_Descriptor* descriptor1) +{ + descriptor1->UniqueID = 4066; + descriptor1->Label = "monoamp"; + descriptor1->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor1->Name = "monoamp"; + descriptor1->Maker = "brummer"; + descriptor1->Copyright = "GPL"; + + descriptor1->ImplementationData = 0; + + // description des methods + descriptor1->instantiate = instantiate_method1; + descriptor1->connect_port = connect_method1; + descriptor1->activate = activate_method1; + descriptor1->run = run_method1; + descriptor1->run_adding = 0; + descriptor1->set_run_adding_gain = 0; + descriptor1->deactivate = deactivate_method1; + descriptor1->cleanup = cleanup_method; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptor1 == 0) + { + // allocate temporaries dsp and portCollector1 to build the plugin description + ampdsp* p1 = new ampdsp(); + if (p1) { + portCollector1* c=new portCollector1(p1->getNumInputs(), p1->getNumOutputs()); + p1->buildUserInterface1(c); + gDescriptor1 = new LADSPA_Descriptor; + initamp_descriptor(gDescriptor1); + c->fillPortDescription(gDescriptor1); + delete p1; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptor1; + } else { + return NULL; + } +} + diff --git a/ladspa/monocompressor.cpp b/ladspa/monocompressor.cpp new file mode 100644 index 0000000..236691d --- /dev/null +++ b/ladspa/monocompressor.cpp @@ -0,0 +1,708 @@ +//----------------------------------------------------- +// name: "mono-compressor" +// version: "0.1" +// author: "brummer" +// license: "GPL" +// +// Code generated with Faust 0.9.9.4k-par (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ladspa.h" + + +using namespace std; + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +#define sym(name) xsym(name) +#define xsym(name) #name + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<declare("name", "mono-compressor/limiter unit"); + m->declare("version", "0.1"); + m->declare("author", "brummer"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classinitfmon(int samplingFreq) { + } + virtual void instanceinitfmon(int samplingFreq) { + fSamplingFreq = samplingFreq; + fentry0 = -20.0f; + fentry1 = 3.0f; + fConst0 = (1.0f / fSamplingFreq); + fslider0 = 2.000000e-03f; + fslider1 = 0.5f; + for (int i=0; i<2; i++) fRec0[i] = 0; + fentry2 = 2.0f; + fslider2 = 0.0f; + } + virtual void initfmon(int samplingFreq) { + classinitfmon(samplingFreq); + instanceinitfmon(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openVerticalBox("compressor"); + //interface->openHorizontalBox("compression"); + interface->addNumEntry("knee", &fentry1, 3.0f, 0.0f, 20.0f, 0.1f); + interface->addNumEntry("ratio", &fentry2, 2.0f, 1.0f, 20.0f, 0.1f); + interface->addNumEntry("threshold", &fentry0, -20.0f, -96.0f, 10.0f, 0.1f); + //interface->closeBox(); + //interface->openVerticalBox("envelop"); + interface->addVerticalSlider0("attack", &fslider0, 2.000000e-03f, 0.0f, 1.0f, 1.000000e-03f); + interface->addHorizontalSlider("release", &fslider1, 0.5f, 0.0f, 10.0f, 1.000000e-02f); + //interface->closeBox(); + //interface->openVerticalBox("gain"); + //interface->addHorizontalBargraph("gain", &fbargraph0, -96.0f, 0.0f); + interface->addVerticalSlider("gain", &fslider2, 0.0f, -96.0f, 96.0f, 0.1f); + //interface->closeBox(); + interface->closeBox(); + } + virtual void compute (int count, float** input, float** output) { + float fSlow0 = fentry1; + float fSlow1 = (fSlow0 - fentry0); + float fSlow2 = expf((0 - (fConst0 / max(fConst0, fslider0)))); + float fSlow3 = expf((0 - (fConst0 / max(fConst0, fslider1)))); + float fSlow4 = (1.0f / (1.000000e-03f + fSlow0)); + float fSlow5 = (fentry2 - 1); + float fSlow6 = fslider2; + float* input0 = input[0]; + float* output0 = output[0]; + for (int i=0; i= fTemp1)) + (fSlow2 * (fRec0[1] < fTemp1))); + fRec0[0] = ((fTemp1 * (0 - (fTemp2 - 1))) + (fRec0[1] * fTemp2)); + float fTemp3 = max(0, ((20 * log10f(fRec0[0])) + fSlow1)); + float fTemp4 = (fSlow5 * min(1, max(0, (fSlow4 * fTemp3)))); + float fTemp5 = ((fTemp3 * (0 - fTemp4)) / (1 + fTemp4)); + //fbargraph0 = fTemp5; + output0[i] = (fTemp0 * powf(10, (5.000000e-02f * (fSlow6 + fTemp5)))); + // post processing + fRec0[1] = fRec0[0]; + } + } +}; + + + + + + + +//-----------------------------------portCollector-------------------------------------- +// +// portCollector is passed to the buildUserInterface methodmon of a dsp object +// in order to build a description of its inputs, outputs and control ports. +// This description is used to fill a LADSPA_Descriptor +// +//-------------------------------------------------------------------------------------- + + + +//--------------------------------useful constants-------------------------------------- + +#define MAXPORT 1024 +static const int ICONTROL = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL; +static const int OCONTROL = LADSPA_PORT_OUTPUT|LADSPA_PORT_CONTROL; +static const int RANGE = LADSPA_PORT_INPUT|LADSPA_PORT_CONTROL; + +static const char* inames[] = { + "input00", "input01", "input02", "input03", "input04", + "input05", "input06", "input07", "input08", "input09", + "input10", "input11", "input12", "input13", "input14", + "input15", "input16", "input17", "input18", "input19", + "input20", "input21", "input22", "input23", "input24", + "input25", "input26", "input27", "input28", "input29", + "input30", "input31", "input32", "input33", "input34", + "input35", "input36", "input37", "input38", "input39" +}; + +static const char* onames[] = { + "output00", "output01", "output02", "output03", "output04", + "output05", "output06", "output07", "output08", "output09", + "output10", "output11", "output12", "output13", "output14", + "output15", "output16", "output17", "output18", "output19", + "output20", "output21", "output22", "output23", "output24", + "output25", "output26", "output27", "output28", "output29", + "output30", "output31", "output32", "output33", "output34", + "output35", "output36", "output37", "output38", "output39" +}; + + + +class portCollector : public UI +{ + private: + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + LADSPA_PortDescriptor fPortDescs[MAXPORT]; // table of port descriptors to be used in a LADSPA_Descriptor + const char* fPortNames[MAXPORT]; // table of port names to be used in a LADSPA_Descriptor + LADSPA_PortRangeHint fPortHints[MAXPORT]; // table of port hints to be used in a LADSPA_Descriptor + + string fPluginName; // toplevel prefix used as plugin name + stack fPrefix; // current prefix for controls name + + + //-------------------------------------------------------------------------------------- + string simplify(const string& src) + { + int i=0; + int level=2; + string dst; + + while (src[i] ) { + + switch (level) { + + case 0 : + case 1 : + case 2 : + // Skip the begin of the label "--foo-" + // until 3 '-' have been read + if (src[i]=='-') { level++; } + break; + + case 3 : + // copy the content, but skip non alphnum + // and content in parenthesis + switch (src[i]) { + case '(' : + case '[' : + level++; + break; + + case '-' : + dst += '-'; + break; + + default : + if (isalnum(src[i])) { + dst+= tolower(src[i]); + } + + } + break; + + default : + // here we are inside parenthesis and + // we skip the content until we are back to + // level 3 + switch (src[i]) { + + case '(' : + case '[' : + level++; + break; + + case ')' : + case ']' : + level--; + break; + + default : + break; + } + + } + i++; + } + return (dst.size() > 0) ? dst :src; + } + + void addPortDescrmon(int type, const char* label, int hint, float min=0.0, float max=0.0) + { + string fullname = simplify(fPrefix.top() + "-" + label); + char * str = strdup(fullname.c_str()); + + fPortDescs[fInsCount + fOutsCount + fCtrlCount] = type; + fPortNames[fInsCount + fOutsCount + fCtrlCount] = str; + fPortHints[fInsCount + fOutsCount + fCtrlCount].HintDescriptor = hint; + fPortHints[fInsCount + fOutsCount + fCtrlCount].LowerBound = min; + fPortHints[fInsCount + fOutsCount + fCtrlCount].UpperBound = max; + fCtrlCount++; + } + + void openAnyBox(const char* label) + { + if (fPrefix.size() == 0) { + // top level label is used as plugin name + fPluginName = label; + fPrefix.push(label); + + } else { + string s; + if (label && label[0]) { + s = fPrefix.top() + "-" + label; + } else { + s = fPrefix.top(); + } + fPrefix.push(s); + } + + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portCollector(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) + { + for (int i = 0; i < ins; i++) { + fPortDescs[i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO; + fPortNames[i] = inames[i]; + fPortHints[i].HintDescriptor = 0; + } + for (int j = 0; j < outs; j++) { + fPortDescs[ins + j] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO; + fPortNames[ins + j] = onames[j]; + fPortHints[ins + j].HintDescriptor = 0; + } + }; + + virtual ~portCollector() {} + + + + //------------------------------Collect the control ports------------------------------- + + virtual void addButton(const char* label, float* zone) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_TOGGLED); + } + + virtual void addToggleButton(const char* label, float* zone) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_0 ); + } + + virtual void addCheckButton(const char* label, float* zone) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_TOGGLED| LADSPA_HINT_DEFAULT_1 ); + } + + virtual void addVerticalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MIDDLE , min, max); + } + + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MINIMUM , min, max); + } + + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_MAXIMUM, min, max); + } + + virtual void addHorizontalSlider(const char* label, float* zone, float initdis, float min, float max, float step) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_DEFAULT_LOW, min, max); + } + + virtual void addNumEntry(const char* label, float* zone, float initfmon, float min, float max, float step) { + addPortDescrmon(ICONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { + addPortDescrmon(OCONTROL, label, 0, -10000, +10000); + } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { + addPortDescrmon(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { + addPortDescrmon(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max){ + addPortDescrmon(OCONTROL, label, LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE, min, max); + } + + virtual void openFrameBox(const char* label) { openAnyBox(label); } + virtual void openTabBox(const char* label) { openAnyBox(label); } + virtual void openHorizontalBox(const char* label) { openAnyBox(label); } + virtual void openVerticalBox(const char* label) { openAnyBox(label); } + + virtual void closeBox() { fPrefix.pop(); } + + virtual void show() {} + virtual void run() {} + + + + //---------------------------------Fill the LADSPA descriptor--------------------------- + + // generate an ID from a plugin name + int makeID (const char* s) { + int h = 0; + for (int i = 0; s[i]; i++) { + h = (h << 3) + (s[i] & 7); + } + return 1+h%1000; + } + + // fill a ladspa descriptor with the information collected on ports + void fillPortDescription (LADSPA_Descriptor * descriptor) { + const char* name = sym(comprdsp); + descriptor->PortCount = fCtrlCount+fInsCount+fOutsCount; + descriptor->PortDescriptors = fPortDescs; + descriptor->PortNames = fPortNames; + descriptor->PortRangeHints = fPortHints; + + descriptor->Label = strdup(name); + descriptor->UniqueID = 4067; +// descriptor->Label = strdup(fPluginName.c_str()); +// descriptor->UniqueID = makeID(fPluginName.c_str()); + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = name; +// descriptor->Name = strdup(fPluginName.c_str()); + descriptor->Maker = "brummer"; + descriptor->Copyright = "BSD"; + } +}; + + + + +//--------------------------------------portData---------------------------------------- +// +// portData : a user interface used to associate the data buffers and the ports +// +//-------------------------------------------------------------------------------------- + + +class portData : public UI +{ + + + private: + + + //-------------------------------------------------------------------------------------- + + const int fInsCount; // number of audio input ports + const int fOutsCount; // number of audio output ports + int fCtrlCount; // number of control ports + + float* fPortZone[MAXPORT]; // + float* fPortData[MAXPORT]; + + + //-------------------------------------------------------------------------------------- + + void addZone(float* zone) + { + fPortZone[fInsCount + fOutsCount + fCtrlCount] = zone; + fCtrlCount++; + } + + + + public: + + + //--------------------------------Collect the audio ports------------------------------- + + portData(int ins, int outs) : UI(), fInsCount(ins), fOutsCount(outs), fCtrlCount(0) {}; + virtual ~portData() {} + + + //------------------------------Collect the control zones------------------------------- + + virtual void addButton(const char* label, float* zone) { addZone(zone); } + virtual void addToggleButton(const char* label, float* zone) { addZone(zone); } + virtual void addCheckButton(const char* label, float* zone) { addZone(zone); } + + virtual void addVerticalSlider(const char* label, float* zone, float initfmon, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider1(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addVerticalSlider0(const char* label, float* zone, float initdis, float min, float max, float step) { addZone(zone); } + virtual void addHorizontalSlider(const char* label, float* zone, float initfmon, float min, float max, float step) { addZone(zone); } + virtual void addNumEntry(const char* label, float* zone, float initfmon, float min, float max, float step) { addZone(zone); } + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) { addZone(zone); } + virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) { addZone(zone); } + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) { addZone(zone); } + + virtual void openFrameBox(const char* label) { } + virtual void openTabBox(const char* label) { } + virtual void openHorizontalBox(const char* label) { } + virtual void openVerticalBox(const char* label) { } + virtual void closeBox() { } + + virtual void show() {} + virtual void run() {} + + + //---------------------------------interaction with LADSPA------------------------------ + + void setPortDatamon (unsigned long port, LADSPA_Data* data) { + fPortData[port] = data; + } + + void updateCtrlZones() { + for (int i = fInsCount+fOutsCount; i < fInsCount+fOutsCount+fCtrlCount; i++) *fPortZone[i] = *fPortData[i]; + } + + float** getInputs() { + return &fPortData[0]; + } + + float** getOutputs() { + return &fPortData[fInsCount]; + } +}; + + + + +//--------------------------------Faust-LADSPA plugin----------------------------------- +// +// Plugin structure, callbacks and LADSPA_descriptor(i) entry point +// +//-------------------------------------------------------------------------------------- + +LADSPA_Descriptor* gDescriptorm = 0; + +struct PLUGIN +{ + unsigned long fSampleRate; + portData* fPortData; + dsp* fDsp; + + PLUGIN(unsigned long r, portData* d, dsp* p) : fSampleRate(r), fPortData(d), fDsp(p) {} +}; + +LADSPA_Handle instantiate_methodmon (const struct _LADSPA_Descriptor * Descriptor, unsigned long SampleRate) +{ + dsp* p = new comprdsp(); + portData* d = new portData(p->getNumInputs(), p->getNumOutputs()); + + p->buildUserInterface(d); + return new PLUGIN (SampleRate, d, p); +} + +void connect_methodmon (LADSPA_Handle Instance, unsigned long Port, LADSPA_Data * DataLocation) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->setPortDatamon(Port, DataLocation); +} + +void activate_methodmon (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fDsp->initfmon(p->fSampleRate); +} + +void run_methodmon (LADSPA_Handle Instance, unsigned long SampleCount) +{ + PLUGIN* p = (PLUGIN*) Instance; + p->fPortData->updateCtrlZones(); + p->fDsp->compute(SampleCount, p->fPortData->getInputs(), p->fPortData->getOutputs()); +} + +void deactivate_methodmon (LADSPA_Handle Instance) +{ +} + +void cleanup_methodmon (LADSPA_Handle Instance) +{ + PLUGIN* p = (PLUGIN*) Instance; + delete p->fPortData; + delete p->fDsp; + delete p; +} + + +//-------------------------------------------------------------------------------------- + +void initfmon_descriptor(LADSPA_Descriptor* descriptor) +{ + descriptor->UniqueID = 4067; + descriptor->Label = "mono-compressor"; + descriptor->Properties = LADSPA_PROPERTY_HARD_RT_CAPABLE; + descriptor->Name = "mono-compressor"; + descriptor->Maker = "brummer"; + descriptor->Copyright = "GPL"; + + descriptor->ImplementationData = 0; + + // description des methodmons + descriptor->instantiate = instantiate_methodmon; + descriptor->connect_port = connect_methodmon; + descriptor->activate = activate_methodmon; + descriptor->run = run_methodmon; + descriptor->run_adding = 0; + descriptor->set_run_adding_gain = 0; + descriptor->deactivate = deactivate_methodmon; + descriptor->cleanup = cleanup_methodmon; +} + + + +//-------------------------------------------------------------------------------------- + +const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index) +{ + if (Index == 0) { + if (gDescriptorm == 0) + { + // allocate temporaries dsp and portCollector to build the plugin description + comprdsp* p = new comprdsp(); + if (p) { + portCollector* c=new portCollector(p->getNumInputs(), p->getNumOutputs()); + p->buildUserInterface(c); + gDescriptorm = new LADSPA_Descriptor; + initfmon_descriptor(gDescriptorm); + c->fillPortDescription(gDescriptorm); + delete p; + } else { + printf("Memory Error : unable to allocate the dsp object\n"); + } + } + return gDescriptorm; + } else { + return NULL; + } +} + diff --git a/ladspa/wscript b/ladspa/wscript new file mode 100644 index 0000000..ab3b0f8 --- /dev/null +++ b/ladspa/wscript @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import os + +def configure(conf): + pass + +def create_ladspa_plugin(bld, source, target, defstr, uselib = None): + ladspa_define = target + "=" + defstr + + ladspa_plugin = bld.new_task_gen('cxx', 'shlib') + ladspa_plugin.env['shlib_PATTERN'] = '%s.so' + ladspa_plugin.defines = ladspa_define + ladspa_plugin.name = target + ladspa_plugin.target = defstr + ladspa_plugin.source = source + ladspa_plugin.env.append_value("CXXFLAGS", ['-fPIC', '-shared']) + ladspa_plugin.install_path = '${LADSPADIR}' + ladspa_plugin.chmod = 0755 + return ladspa_plugin + + +def build(bld): + sources = [ + 'crybaby.cpp', + 'distortion.cpp', + 'echo.cpp', + 'freeverb.cpp', + 'impulseresponse.cpp', + 'monoamp.cpp', + 'monocompressor.cpp', + 'guitarix-ladspa.cpp' + ] + + targets = [ + 'crydsp', + 'distdsp', + 'echodsp', + 'frdsp', + 'irdsp', + 'ampdsp', + 'comprdsp', + 'mydsp' + ] + + defines = [ + 'guitarix_crybaby', + 'guitarix_distortion', + 'guitarix_echo', + 'guitarix_freeverb', + 'guitarix_IR', + 'guitarix_amp', + 'guitarix_compressor', + 'guitarix' + ] + + for i in range(0, len(sources)): + create_ladspa_plugin(bld, sources[i], targets[i], defines[i]) + + bld.install_files('${SHAREDIR}/ladspa/rdf', 'guitarix.rdf') diff --git a/pixmaps/guitarix-midi.png b/pixmaps/guitarix-midi.png new file mode 100644 index 0000000..2851dac Binary files /dev/null and b/pixmaps/guitarix-midi.png differ diff --git a/pixmaps/guitarix-warn.png b/pixmaps/guitarix-warn.png new file mode 100644 index 0000000..42011cc Binary files /dev/null and b/pixmaps/guitarix-warn.png differ diff --git a/pixmaps/guitarix.png b/pixmaps/guitarix.png new file mode 100644 index 0000000..9a87e8d Binary files /dev/null and b/pixmaps/guitarix.png differ diff --git a/pixmaps/gx_bypass.png b/pixmaps/gx_bypass.png new file mode 100644 index 0000000..29f78ed Binary files /dev/null and b/pixmaps/gx_bypass.png differ diff --git a/pixmaps/gx_off.png b/pixmaps/gx_off.png new file mode 100644 index 0000000..e5bc5d9 Binary files /dev/null and b/pixmaps/gx_off.png differ diff --git a/pixmaps/gx_on.png b/pixmaps/gx_on.png new file mode 100644 index 0000000..dcabae4 Binary files /dev/null and b/pixmaps/gx_on.png differ diff --git a/pixmaps/jackd_off.png b/pixmaps/jackd_off.png new file mode 100644 index 0000000..b259c93 Binary files /dev/null and b/pixmaps/jackd_off.png differ diff --git a/pixmaps/jackd_on.png b/pixmaps/jackd_on.png new file mode 100644 index 0000000..a51c6a1 Binary files /dev/null and b/pixmaps/jackd_on.png differ diff --git a/pixmaps/wscript b/pixmaps/wscript new file mode 100644 index 0000000..c8897c1 --- /dev/null +++ b/pixmaps/wscript @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import Build + +# start each filename with a space +pixmap_files = '' +pixmap_files += ' guitarix-midi.png' +pixmap_files += ' guitarix.png' +pixmap_files += ' guitarix-warn.png' +pixmap_files += ' gx_on.png' +pixmap_files += ' gx_off.png' +pixmap_files += ' jackd_on.png' +pixmap_files += ' jackd_off.png' +pixmap_files += ' gx_bypass.png' + +def configure(conf): + pass + +def build(bld): + bld.install_files(bld.env['GX_PIXMAPS_DIR'], pixmap_files, chmod=0644) diff --git a/rcstyles/cairo.jpg b/rcstyles/cairo.jpg new file mode 100644 index 0000000..e6c78a1 Binary files /dev/null and b/rcstyles/cairo.jpg differ diff --git a/rcstyles/cairo1.jpg b/rcstyles/cairo1.jpg new file mode 100644 index 0000000..f564fca Binary files /dev/null and b/rcstyles/cairo1.jpg differ diff --git a/rcstyles/cairo2.jpg b/rcstyles/cairo2.jpg new file mode 100644 index 0000000..3b2a278 Binary files /dev/null and b/rcstyles/cairo2.jpg differ diff --git a/rcstyles/controls.jpg b/rcstyles/controls.jpg new file mode 100644 index 0000000..9bc27f5 Binary files /dev/null and b/rcstyles/controls.jpg differ diff --git a/rcstyles/controls1.jpg b/rcstyles/controls1.jpg new file mode 100644 index 0000000..530a78a Binary files /dev/null and b/rcstyles/controls1.jpg differ diff --git a/rcstyles/controls2.jpg b/rcstyles/controls2.jpg new file mode 100644 index 0000000..54ef1b6 Binary files /dev/null and b/rcstyles/controls2.jpg differ diff --git a/rcstyles/controls3.jpg b/rcstyles/controls3.jpg new file mode 100644 index 0000000..f1f8a1d Binary files /dev/null and b/rcstyles/controls3.jpg differ diff --git a/rcstyles/controls4.jpg b/rcstyles/controls4.jpg new file mode 100644 index 0000000..b16041b Binary files /dev/null and b/rcstyles/controls4.jpg differ diff --git a/rcstyles/controlsbl.jpg b/rcstyles/controlsbl.jpg new file mode 100644 index 0000000..8206a4e Binary files /dev/null and b/rcstyles/controlsbl.jpg differ diff --git a/rcstyles/controlsbl1.jpg b/rcstyles/controlsbl1.jpg new file mode 100644 index 0000000..8178154 Binary files /dev/null and b/rcstyles/controlsbl1.jpg differ diff --git a/rcstyles/controlsbl2.jpg b/rcstyles/controlsbl2.jpg new file mode 100644 index 0000000..88a5ec4 Binary files /dev/null and b/rcstyles/controlsbl2.jpg differ diff --git a/rcstyles/controlsbl3.jpg b/rcstyles/controlsbl3.jpg new file mode 100644 index 0000000..42f447b Binary files /dev/null and b/rcstyles/controlsbl3.jpg differ diff --git a/rcstyles/controlsbl4.jpg b/rcstyles/controlsbl4.jpg new file mode 100644 index 0000000..c735f49 Binary files /dev/null and b/rcstyles/controlsbl4.jpg differ diff --git a/rcstyles/guitarix-darkblack-relief.jpg b/rcstyles/guitarix-darkblack-relief.jpg new file mode 100644 index 0000000..0387dee Binary files /dev/null and b/rcstyles/guitarix-darkblack-relief.jpg differ diff --git a/rcstyles/guitarix_black.rc b/rcstyles/guitarix_black.rc new file mode 100644 index 0000000..787917b --- /dev/null +++ b/rcstyles/guitarix_black.rc @@ -0,0 +1,224 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.80, 0.80, 0.80 } + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.0, 0.0, 0.0 } + bg[PRELIGHT] = "#303084" + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[INSENSITIVE] = "#c4c0c0" + bg[SELECTED] = "#000094" + bg_pixmap[NORMAL] = "" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + +} + + +class "GtkWidget" style:highest "guitarix" +class "GtkLabel" style:highest "guitarix" +class "GtkHScale" style:highest "guitarix" +class "GtkVScale" style:highest "guitarix" +class "GtkCheckButton" style:highest "guitarix" +class "GtkButton" style:highest "guitarix" +class "GtkFrame" style:highest "guitarix" +class "GtkExpander" style:highest "guitarix" +#class "GtkEventBox" style:highest "guitarix" + +style "guitarix-event" +{ + bg_pixmap[NORMAL] = "controlsbl2.jpg" +} +widget "*.osc_box" style:highest "guitarix-event" +class "GtkEventBox" style:highest "guitarix" + +style "guitarix-dialog" +{ + bg_pixmap[NORMAL] = "controls4.jpg" +} + +#widget_class "GtkDialog*" style:highest "guitarix-dialog" + +style "guitarix-menu" +{ + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = "#303084" + font_name = "sans 9" +} + +class "GtkMenu" style:highest "guitarix-menu" +class "GtkMenuBar" style:highest "guitarix-menu" + +style "b_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "controlsbl3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "controlsbl4.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + shadow = OUT + file = "controlsbl3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} + +style "c_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "controlsbl.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + + } +} + +style "guitarix-l_black" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_black" +{ + fg[NORMAL] = { 0.6, 0.6, 0.6 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_black" +{ + fg[NORMAL] = { 0.5, 0.5, 0.5 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_black" +widget "*.value_label" style:highest "guitarix-l_black" +widget "*.beffekt_label" style:highest "guitarix-b_black" + + +style "h_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "guitarix-darkblack-relief.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } +} + +class "GtkHandleBox" style:highest "h_style" +class "GtkScrolledWindow" style:highest "h_style" +widget_class "GtkDialog*" style:highest "h_style" +widget_class "*GtkToggleButton*" style:highest "b_style" +class "GtkButton" style:highest "b_style" +class "GtkSpinButton" style:highest "c_style" + +style "p_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "controls4.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} +widget_class "*GtkProgressBar*" style:highest "p_style" + diff --git a/rcstyles/guitarix_cairo.rc b/rcstyles/guitarix_cairo.rc new file mode 100644 index 0000000..b58d1ab --- /dev/null +++ b/rcstyles/guitarix_cairo.rc @@ -0,0 +1,230 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix_cairo" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.80, 0.80, 0.80 } + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.0, 0.0, 0.0 } + bg[PRELIGHT] = "#303084" + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[INSENSITIVE] = "#c4c0c0" + bg[SELECTED] = "#000094" + bg_pixmap[NORMAL] = "" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + +} + + +class "GtkWidget" style:highest "guitarix_cairo" +class "GtkLabel" style:highest "guitarix_cairo" +class "GtkHScale" style:highest "guitarix_cairo" +class "GtkVScale" style:highest "guitarix_cairo" +class "GtkCheckButton" style:highest "guitarix_cairo" +class "GtkButton" style:highest "guitarix_cairo" +class "GtkFrame" style:highest "guitarix_cairo" +class "GtkExpander" style:highest "guitarix_cairo" + + +style "guitarix-cairo-event" +{ + bg_pixmap[NORMAL] = "controlsbl2.jpg" +} +widget "*.osc_box" style:highest "guitarix-cairo-event" + + +style "guitarix-dialog" +{ + bg_pixmap[NORMAL] = "controls4.jpg" +} + +#widget_class "GtkDialog*" style:highest "guitarix-dialog" + +style "guitarix-menu" +{ + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = "#303084" + font_name = "sans 9" +} + +class "GtkMenu" style:highest "guitarix-menu" +class "GtkMenuBar" style:highest "guitarix-menu" + + +style "guitarix-l_cairo" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_cairo" +{ + fg[NORMAL] = { 0.6, 0.6, 0.6 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +style "guitarix-o_cairo" +{ + bg[NORMAL] = { 0.01, 0.02, 0.03 } + + +} +style "guitarix-b_cairo" +{ + fg[NORMAL] = { 0.5, 0.5, 0.5 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_cairo" +widget "*.value_label" style:highest "guitarix-l_cairo" +widget "*.beffekt_label" style:highest "guitarix-b_cairo" +class "GtkEventBox" style:highest "guitarix-o_cairo" + +style "bc_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "cairo2.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "cairo1.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + shadow = OUT + file = "cairo2.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} + +style "cc_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "cairo.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + + } +} + +style "hc_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "cairo.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } +} + +class "GtkHandleBox" style:highest "hc_style" +class "GtkScrolledWindow" style:highest "hc_style" +widget_class "GtkDialog*" style:highest "hc_style" +widget_class "*GtkToggleButton*" style:highest "bc_style" +class "GtkButton" style:highest "bc_style" +class "GtkSpinButton" style:highest "cc_style" + +style "pc_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "cairo.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} +widget_class "*GtkProgressBar*" style:highest "pc_style" + diff --git a/rcstyles/guitarix_default.rc b/rcstyles/guitarix_default.rc new file mode 100644 index 0000000..d8d7087 --- /dev/null +++ b/rcstyles/guitarix_default.rc @@ -0,0 +1,133 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './skins:./:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix_default" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.80, 0.80, 0.80 } + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.03, 0.03, 0.03 } + # bg[NORMAL] = { 0.35, 0.35, 0.40 } + # bg_pixmap[NORMAL] = "guitarixback4.jpg" + bg[PRELIGHT] = { 0.40, 0.40, 0.45 } + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[SELECTED] = "#c4c0c0" + bg_pixmap[NORMAL] = "" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + engine "clearlooks" + { + menubarstyle = 0 # 0 = flat, 1 = sunken, 2 = flat gradient + } +} + + +class "GtkWidget" style:highest "guitarix_default" +class "GtkLabel" style:highest "guitarix_default" +class "GtkHScale" style:highest "guitarix_default" +class "GtkVScale" style:highest "guitarix_default" +class "GtkCheckButton" style:highest "guitarix_default" +class "GtkButton" style:highest "guitarix_default" +class "GtkFrame" style:highest "guitarix_default" +class "GtkExpander" style:highest "guitarix_default" + +widget_class "*GtkToggleButton*" style:highest "guitarix_default" +class "GtkButton" style:highest "guitarix_default" +class "GtkSpinButton" style:highest "guitarix_default" +widget_class "GtkDialog*" style:highest "guitarix_default" + +style "guitarix_handle_default" +{ + fg[NORMAL] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.05, 0.05, 0.04 } + engine "clearlooks" {} + #font_name = "sans 9" + +} + + +class "GtkHandleBox" style:highest "guitarix_handle_default" + +style "guitarix_event_default" +{ + bg[NORMAL] = { 0.2, 0.2, 0.2 } + bg_pixmap[NORMAL] = "" + engine "clearlooks" {} +} + +widget "*.osc_box" style:highest "guitarix_event_default" +class "GtkEventBox" style:highest "guitarix_default" + +style "guitarix_menu_default" +{ + fg[NORMAL] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.35, 0.35, 0.40 } + + font_name = "sans 9" + engine "clearlooks" {} +} + +class "GtkMenu" style:highest "guitarix_menu_default" +class "GtkMenuBar" style:highest "guitarix_menu_default" + + +style "guitarix-l_default" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_default" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_default" +{ + fg[NORMAL] = { 0.8, 0.8, 0.8 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_default" +widget "*.value_label" style:highest "guitarix-l_default" +widget "*.beffekt_label" style:highest "guitarix-b_default" + diff --git a/rcstyles/guitarix_pix.rc b/rcstyles/guitarix_pix.rc new file mode 100644 index 0000000..70f0c04 --- /dev/null +++ b/rcstyles/guitarix_pix.rc @@ -0,0 +1,207 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarixp" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.80, 0.80, 0.80 } + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.30, 0.30, 0.30 } + bg[PRELIGHT] = "#760608" + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[INSENSITIVE] = "#c4c0c0" + bg[SELECTED] = "#760608" + bg_pixmap[NORMAL] = "" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + +} + + +class "GtkWidget" style:highest "guitarixp" +class "GtkLabel" style:highest "guitarixp" +class "GtkHScale" style:highest "guitarixp" +class "GtkVScale" style:highest "guitarixp" +class "GtkCheckButton" style:highest "guitarixp" +class "GtkButton" style:highest "guitarixp" +class "GtkFrame" style:highest "guitarixp" +class "GtkExpander" style:highest "guitarixp" + + +style "guitarix-event-xp" +{ + bg_pixmap[NORMAL] = "controls3.jpg" +} +widget "*.osc_box" style:highest "guitarix-event-xp" +class "GtkEventBox" style:highest "guitarix-event-xp" + +style "guitarix-pdialog" +{ + bg_pixmap[NORMAL] = "controls1.jpg" +} + +#widget_class "GtkDialog*" style:highest "guitarix-pdialog" + +style "guitarix-pmenu" +{ + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = "#600405" + bg[SELECTED] = "#120202" + font_name = "sans 9" +} + +class "GtkMenu" style:highest "guitarix-pmenu" +class "GtkMenuBar" style:highest "guitarix-pmenu" + + +style "guitarix-l_pix" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_pix" +{ + fg[NORMAL] = { 0.6, 0.6, 0.6 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_pix" +{ + fg[NORMAL] = { 0.5, 0.5, 0.5 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_pix" +widget "*.value_label" style:highest "guitarix-l_pix" +widget "*.beffekt_label" style:highest "guitarix-b_pix" + + +style "bix_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "controls.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "controls2.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + shadow = OUT + file = "controls.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} + +style "hix_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "controls.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } +} + +class "GtkHandleBox" style:highest "hix_style" +widget_class "*GtkToggleButton*" style:highest "bix_style" +widget_class "GtkDialog*" style:highest "hix_style" +class "GtkButton" style:highest "bix_style" +class "GtkSpinButton" style:highest "bix_style" + +style "pix_style" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "controls4.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} +widget_class "*GtkProgressBar*" style:highest "pix_style" + diff --git a/rcstyles/guitarix_rainbow.rc b/rcstyles/guitarix_rainbow.rc new file mode 100644 index 0000000..156de54 --- /dev/null +++ b/rcstyles/guitarix_rainbow.rc @@ -0,0 +1,224 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix_rainbow" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.80, 0.80, 0.80 } + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.0, 0.0, 0.0 } + bg[PRELIGHT] = "#1c5d09" + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[INSENSITIVE] = "#c4c0c0" + bg[SELECTED] = "#103004" + bg_pixmap[NORMAL] = "" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#103004" + base[NORMAL] = "#103004" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + +} + + +class "GtkWidget" style:highest "guitarix_rainbow" +class "GtkLabel" style:highest "guitarix_rainbow" +class "GtkHScale" style:highest "guitarix_rainbow" +class "GtkVScale" style:highest "guitarix_rainbow" +class "GtkCheckButton" style:highest "guitarix_rainbow" +class "GtkButton" style:highest "guitarix_rainbow" +class "GtkFrame" style:highest "guitarix_rainbow" +class "GtkExpander" style:highest "guitarix_rainbow" + + +style "guitarix-event_rainbow" +{ + bg_pixmap[NORMAL] = "rainbow3.jpg" +} +widget "*.osc_box" style:highest "guitarix-event_rainbow" +class "GtkEventBox" style:highest "guitarix-event_rainbow" + +style "guitarix-dialog_rainbow" +{ + bg_pixmap[NORMAL] = "rainbow3.jpg" +} + +#widget_class "GtkDialog*" style:highest "guitarix-dialog_rainbow" + +style "guitarix-m_rainbow" +{ + fg[NORMAL] = "#8c5214" + bg[NORMAL] = "#1c5d09" + font_name = "sans 9" +} + +class "GtkMenu" style:highest "guitarix-m_rainbow" +class "GtkMenuBar" style:highest "guitarix-m_rainbow" + + +style "guitarix-l_rainbow" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_rainbow" +{ + fg[NORMAL] = { 0.6, 0.6, 0.6 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_rainbow" +{ + fg[NORMAL] = { 0.5, 0.5, 0.5 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_rainbow" +widget "*.value_label" style:highest "guitarix-l_rainbow" +widget "*.beffekt_label" style:highest "guitarix-b_rainbow" + + +style "b_style_rainbow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "rainbow1.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "rainbow2.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + shadow = OUT + file = "rainbow1.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} + +style "c_style_rainbow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "rainbow.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + + } +} + +style "h_style_rainbow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "rainbow.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#103004" + base[NORMAL] = "#103004" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } +} + +class "GtkHandleBox" style:highest "h_style_rainbow" +widget_class "*GtkToggleButton*" style:highest "b_style_rainbow" +widget_class "GtkDialog*" style:highest "h_style_rainbow" +class "GtkButton" style:highest "b_style_rainbow" +class "GtkSpinButton" style:highest "c_style_rainbow" + +style "p_style_rainbow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "rainbow3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} +widget_class "*GtkProgressBar*" style:highest "p_style_rainbow" + diff --git a/rcstyles/guitarix_sunburst.rc b/rcstyles/guitarix_sunburst.rc new file mode 100644 index 0000000..d8d9303 --- /dev/null +++ b/rcstyles/guitarix_sunburst.rc @@ -0,0 +1,224 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix_sunburst" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.80, 0.80, 0.80 } + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.0, 0.0, 0.0 } + bg[PRELIGHT] = "#1e0000" + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[INSENSITIVE] = "#c4c0c0" + bg[SELECTED] = "#973419" + bg_pixmap[NORMAL] = "" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + +} + + +class "GtkWidget" style:highest "guitarix_sunburst" +class "GtkLabel" style:highest "guitarix_sunburst" +class "GtkHScale" style:highest "guitarix_sunburst" +class "GtkVScale" style:highest "guitarix_sunburst" +class "GtkCheckButton" style:highest "guitarix_sunburst" +class "GtkButton" style:highest "guitarix_sunburst" +class "GtkFrame" style:highest "guitarix_sunburst" +class "GtkExpander" style:highest "guitarix_sunburst" + + +style "guitarix-event_sunburst" +{ + bg_pixmap[NORMAL] = "sunburst2.jpg" +} +widget "*.osc_box" style:highest "guitarix-event_sunburst" +class "GtkEventBox" style:highest "guitarix-event_sunburst" + +style "guitarix-dialog_sunburst" +{ + bg_pixmap[NORMAL] = "sunburst2.jpg" +} + +#widget_class "GtkDialog*" style:highest "guitarix-dialog_sunburst" + +style "guitarix-m_sunburst" +{ + fg[NORMAL] = "#8c5214" + bg[NORMAL] = "#450000" + font_name = "sans 9" +} + +class "GtkMenu" style:highest "guitarix-m_sunburst" +class "GtkMenuBar" style:highest "guitarix-m_sunburst" + + +style "guitarix-l_sun" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_sun" +{ + fg[NORMAL] = { 0.6, 0.6, 0.6 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_sun" +{ + fg[NORMAL] = { 0.5, 0.5, 0.5 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_sun" +widget "*.value_label" style:highest "guitarix-l_sun" +widget "*.beffekt_label" style:highest "guitarix-b_sun" + + +style "b_style_sunburst" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "sunburst3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "sunburst4.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + shadow = OUT + file = "sunburst3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} + +style "c_style_sunburst" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "sunburst.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + + } +} + +style "h_style_sunburst" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "sunburst.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } +} + +class "GtkHandleBox" style:highest "h_style_sunburst" +widget_class "*GtkToggleButton*" style:highest "b_style_sunburst" +widget_class "GtkDialog*" style:highest "h_style_sunburst" +class "GtkButton" style:highest "b_style_sunburst" +class "GtkSpinButton" style:highest "c_style_sunburst" + +style "p_style_sunburst" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "sunburst2.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} +widget_class "*GtkProgressBar*" style:highest "p_style_sunburst" + diff --git a/rcstyles/guitarix_yellow.rc b/rcstyles/guitarix_yellow.rc new file mode 100644 index 0000000..64fad5b --- /dev/null +++ b/rcstyles/guitarix_yellow.rc @@ -0,0 +1,224 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix_yellow" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.0, 0.0, 0.0 } + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.0, 0.0, 0.0 } + bg[PRELIGHT] = "#e8760a" + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[INSENSITIVE] = "#c4c0c0" + bg[SELECTED] = "#aa5a01" + bg_pixmap[NORMAL] = "" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + +} + + +class "GtkWidget" style:highest "guitarix_yellow" +class "GtkLabel" style:highest "guitarix_yellow" +widget "fWindow.Gtk?Box.lw" style:highest "guitarix_yellow" +class "GtkHScale" style:highest "guitarix_yellow" +class "GtkVScale" style:highest "guitarix_yellow" +class "GtkCheckButton" style:highest "guitarix_yellow" +class "GtkButton" style:highest "guitarix_yellow" +class "GtkFrame" style:highest "guitarix_yellow" +class "GtkExpander" style:highest "guitarix_yellow" + + + +style "guitarix-event_yellow" +{ + bg_pixmap[NORMAL] = "yellow2.jpg" +} +widget "*.osc_box" style:highest "guitarix-event_yellow" +class "GtkEventBox" style:highest "guitarix-event_yellow" + +style "guitarix-dialog_yellow" +{ + bg_pixmap[NORMAL] = "yellow2.jpg" +} + +#widget_class "GtkDialog*" style:highest "guitarix-dialog_yellow" + +style "guitarix-m_yellow" +{ + fg[NORMAL] = "#8c5214" + bg[NORMAL] = "#aa5a01" + font_name = "sans 9" +} + +style "guitarix-l_yellow" +{ + fg[NORMAL] = { 0.7, 0.7, 0.7 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_yellow" +{ + fg[NORMAL] = { 0.6, 0.6, 0.6 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_yellow" +{ + fg[NORMAL] = { 0.5, 0.5, 0.5 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_yellow" +widget "*.value_label" style:highest "guitarix-l_yellow" +widget "*.beffekt_label" style:highest "guitarix-b_yellow" + +class "GtkMenu" style:highest "guitarix-m_yellow" +class "GtkMenuBar" style:highest "guitarix-m_yellow" + +style "b_style_yellow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "yellow.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "yellow1.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + shadow = OUT + file = "yellow.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} + +style "c_style_yellow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "yellow.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + + } +} + +style "h_style_yellow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "yellow3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } + fg[NORMAL] = { 0.80, 0.80, 0.80 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#272a2f" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } +} + +class "GtkHandleBox" style:highest "h_style_yellow" +widget_class "*GtkToggleButton*" style:highest "b_style_yellow" +widget_class "GtkDialog*" style:highest "h_style_yellow" +class "GtkButton" style:highest "b_style_yellow" +class "GtkSpinButton" style:highest "c_style_yellow" + +style "p_style_yellow" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "yellow2.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} +widget_class "*GtkProgressBar*" style:highest "p_style_yellow" + diff --git a/rcstyles/guitarix_zac.rc b/rcstyles/guitarix_zac.rc new file mode 100644 index 0000000..e4bfb6d --- /dev/null +++ b/rcstyles/guitarix_zac.rc @@ -0,0 +1,133 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './skins:./:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix_zzz" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + + + fg[NORMAL] = { 0.1, 0.1, 0.1 } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 0.3, 0.3, 0.3 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.4, 0.4, 0.4 } + + bg[NORMAL] = { 0.5, 0.5, 0.5 } + # bg[NORMAL] = { 0.35, 0.35, 0.40 } + # bg_pixmap[NORMAL] = "guitarixback4.jpg" + bg[PRELIGHT] = { 0.40, 0.40, 0.45 } + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[SELECTED] = "#c4c0c0" + + text[NORMAL] = { 0.1, 0.1, 0.1 } + text[ACTIVE] = { 0.2, 0.2, 0.2 } + text[PRELIGHT] = { 0.3, 0.3, 0.3 } + text[INSENSITIVE] = { 0.5, 0.5, 0.5} + text[SELECTED] = { 0.4, 0.4, 0.4 } + + base[ACTIVE] = { 0.0, 0.0, 0.0 } + base[NORMAL] = { 0.8, 0.8, 0.8 } + base[PRELIGHT] = { 0.6, 0.6, 0.6 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.0, 0.0, 0.0 } + font_name = "sans 10" + engine "clearlooks" + { + menubarstyle = 0 # 0 = flat, 1 = sunken, 2 = flat gradient + } +} + + +class "GtkWidget" style:highest "guitarix_zzz" +class "GtkLabel" style:highest "guitarix_zzz" +class "GtkHScale" style:highest "guitarix_zzz" +class "GtkVScale" style:highest "guitarix_zzz" +class "GtkCheckButton" style:highest "guitarix_zzz" +class "GtkButton" style:highest "guitarix_zzz" +class "GtkFrame" style:highest "guitarix_zzz" +class "GtkExpander" style:highest "guitarix_zzz" + +widget_class "*GtkToggleButton*" style:highest "guitarix_zzz" +class "GtkButton" style:highest "guitarix_zzz" +class "GtkSpinButton" style:highest "guitarix_zzz" +widget_class "GtkDialog*" style:highest "guitarix_zzz" + +style "guitarix_zhandle_zzz" +{ + fg[NORMAL] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.5, 0.5, 0.5 } + engine "clearlooks" {} + #font_name = "sans 9" + +} + + +class "GtkHandleBox" style:highest "guitarix_zhandle_zzz" + +style "guitarix_event_zzz" +{ + bg[NORMAL] = { 0.2, 0.2, 0.2 } + bg_pixmap[NORMAL] = "" + engine "clearlooks" {} +} + +widget "*.osc_box" style:highest "guitarix_event_zzz" +class "GtkEventBox" style:highest "guitarix_event_zzz" + +style "guitarix_menu_default" +{ + fg[NORMAL] = { 0.80, 0.80, 0.80 } + + bg[NORMAL] = { 0.35, 0.35, 0.40 } + + font_name = "sans 9" + engine "clearlooks" {} +} + +class "GtkMenu" style:highest "guitarix_menu_default" +class "GtkMenuBar" style:highest "guitarix_menu_default" + + +style "guitarix-l_default" +{ + fg[NORMAL] = { 0.03, 0.03, 0.03 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_default" +{ + fg[NORMAL] = { 0.01, 0.01, 0.02 } + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_default" +{ + fg[NORMAL] = { 0., 0., 0. } + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_default" +widget "*.value_label" style:highest "guitarix-l_default" +widget "*.beffekt_label" style:highest "guitarix-b_default" + + diff --git a/rcstyles/guitarix_zreadable.rc b/rcstyles/guitarix_zreadable.rc new file mode 100644 index 0000000..2a31ec0 --- /dev/null +++ b/rcstyles/guitarix_zreadable.rc @@ -0,0 +1,244 @@ +# +# This is the GTK rc style file for guitarix +# + +pixmap_path './:/usr/share/guitarix/skins:/usr/local/share/guitarix/skins' + + +style "guitarix_zreadable" +{ + + + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkButton::button_relief = GTK_RELIEF_NONE + +#font-color menu + fg[NORMAL] = "#1e2e44" + fg[ACTIVE] = { 0.80, 0.80, 0.80 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } + fg[SELECTED] = { 0.80, 0.80, 0.80 } +# background below main-menu + bg[NORMAL] = "#bdd9eb" + bg[PRELIGHT] = "#84919c" + bg[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[INSENSITIVE] = "#c4c0c0" + bg[SELECTED] = "#867e81" + bg_pixmap[NORMAL] = "zreadable5.jpg" + + text[NORMAL] = { 0.80, 0.80, 0.80 } + text[ACTIVE] = { 0.80, 0.80, 0.80 } + text[PRELIGHT] = { 0.80, 0.80, 0.80 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#bcd9f6" + base[NORMAL] = "#1a1e20" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } + font_name = "sans 10" + +} + + +class "GtkWidget" style:highest "guitarix_zreadable" +class "GtkLabel" style:highest "guitarix_zreadable" +class "GtkHScale" style:highest "guitarix_zreadable" +class "GtkVScale" style:highest "guitarix_zreadable" +class "GtkCheckButton" style:highest "guitarix_zreadable" +class "GtkButton" style:highest "guitarix_zreadable" +class "GtkFrame" style:highest "guitarix_zreadable" +class "GtkExpander" style:highest "guitarix_zreadable" + + +style "guitarix-event_zreadable" +{ + bg_pixmap[NORMAL] = "zreadable2.jpg" +} +widget "*.osc_box" style:highest "guitarix-event_zreadable" + +style "guitarix-osc_zreadable" +{ + bg[NORMAL] = { 0.5, 0.5, 0.5 } + bg_pixmap[NORMAL] = "" +} +class "GtkEventBox" style:highest "guitarix-osc_zreadable" + +style "guitarix-dialog_zreadable" +{ + bg_pixmap[NORMAL] = "zreadable2.jpg" +} + +#widget_class "GtkDialog*" style:highest "guitarix-dialog_zreadable" + +style "guitarix-m_zreadable" +{ + fg[NORMAL] = "#222a3b" + bg[NORMAL] = "#b8c5d9" + font_name = "sans 9" +} + +class "GtkMenu" style:highest "guitarix-m_zreadable" +class "GtkMenuBar" style:highest "guitarix-m_zreadable" + + +style "guitarix-l_zreadable" +{ + fg[NORMAL] = "#222a3b" + bg[NORMAL] = "#b8c5d9" + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-v_zreadable" +{ + fg[NORMAL] = "#062f56" + bg[NORMAL] = "#b8c5d9" + fg[ACTIVE] = { 0.8, 0.8, 0.8 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.8, 0.8, 0.8 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} + +style "guitarix-b_zreadable" +{ + fg[NORMAL] = "#2389e8" + bg[NORMAL] = "#b8c5d9" + fg[ACTIVE] = { 0.2, 0.2, 0.2 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } + fg[INSENSITIVE] = { 0.0, 0.0, 0.0 } + fg[SELECTED] = { 0.8, 0.8, 0.8 } + +} +widget "*.effekt_label" style:highest "guitarix-v_zreadable" +widget "*.value_label" style:highest "guitarix-l_zreadable" +widget "*.beffekt_label" style:highest "guitarix-b_zreadable" + + +style "b_style_zreadable" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "zreadable3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "zreadable4.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "zreadable5.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + image + { + function = BOX + recolorable = TRUE + state = ACTIVE + shadow = OUT + file = "zreadable3.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} + +style "c_style_zreadable" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "zreadable.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + + } +} + +style "h_style_zreadable" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = NORMAL + shadow = OUT + file = "zreadable.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } + fg[NORMAL] = { 0.0, 0.0, 0.80 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + + text[NORMAL] = { 0.1, 0.1, 0.2 } + text[ACTIVE] = { 0.1, 0.1, 0.3 } + text[PRELIGHT] = { 0.1, 0.1, 0.4 } + text[INSENSITIVE] = { 0.80, 0.80, 0.80} + text[SELECTED] = { 1.0, 1.0, 1.0 } + + base[ACTIVE] = "#bcd9f6" + base[NORMAL] = "#bdd9eb" + base[PRELIGHT] = { 0.20, 0.20, 0.20 } + base[INSENSITIVE] = "#4c5159" + base[SELECTED] = { 0.25, 0.25, 0.25 } +} + +class "GtkHandleBox" style:highest "h_style_zreadable" +widget_class "*GtkToggleButton*" style:highest "b_style_zreadable" +widget_class "GtkDialog*" style:highest "h_style_zreadable" +class "GtkButton" style:highest "b_style_zreadable" +class "GtkSpinButton" style:highest "c_style_zreadable" + +style "p_style_zreadable" +{ + engine "pixmap" + { + image + { + function = BOX + recolorable = TRUE + state = PRELIGHT + shadow = OUT + file = "zreadable2.jpg" + border = { 0, 0, 0, 0 } + stretch = TRUE + } + } +} +widget_class "*GtkProgressBar*" style:highest "p_style_zreadable" + diff --git a/rcstyles/rainbow.jpg b/rcstyles/rainbow.jpg new file mode 100644 index 0000000..3f6e5b2 Binary files /dev/null and b/rcstyles/rainbow.jpg differ diff --git a/rcstyles/rainbow1.jpg b/rcstyles/rainbow1.jpg new file mode 100644 index 0000000..7b6728b Binary files /dev/null and b/rcstyles/rainbow1.jpg differ diff --git a/rcstyles/rainbow2.jpg b/rcstyles/rainbow2.jpg new file mode 100644 index 0000000..7cd782f Binary files /dev/null and b/rcstyles/rainbow2.jpg differ diff --git a/rcstyles/rainbow3.jpg b/rcstyles/rainbow3.jpg new file mode 100644 index 0000000..4592687 Binary files /dev/null and b/rcstyles/rainbow3.jpg differ diff --git a/rcstyles/sunburst.jpg b/rcstyles/sunburst.jpg new file mode 100644 index 0000000..a364407 Binary files /dev/null and b/rcstyles/sunburst.jpg differ diff --git a/rcstyles/sunburst1.jpg b/rcstyles/sunburst1.jpg new file mode 100644 index 0000000..0511dd4 Binary files /dev/null and b/rcstyles/sunburst1.jpg differ diff --git a/rcstyles/sunburst2.jpg b/rcstyles/sunburst2.jpg new file mode 100644 index 0000000..111c22d Binary files /dev/null and b/rcstyles/sunburst2.jpg differ diff --git a/rcstyles/sunburst3.jpg b/rcstyles/sunburst3.jpg new file mode 100644 index 0000000..bdd2231 Binary files /dev/null and b/rcstyles/sunburst3.jpg differ diff --git a/rcstyles/sunburst4.jpg b/rcstyles/sunburst4.jpg new file mode 100644 index 0000000..c7de74c Binary files /dev/null and b/rcstyles/sunburst4.jpg differ diff --git a/rcstyles/wscript b/rcstyles/wscript new file mode 100644 index 0000000..bbca2d1 --- /dev/null +++ b/rcstyles/wscript @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import Build + +# start each filename with a space +style_files = '' +style_files += ' controls1.jpg' +style_files += ' controls2.jpg' +style_files += ' controls3.jpg' +style_files += ' controls4.jpg' +style_files += ' controlsbl1.jpg' +style_files += ' controlsbl2.jpg' +style_files += ' controlsbl3.jpg' +style_files += ' controlsbl4.jpg' +style_files += ' controlsbl.jpg' +style_files += ' controls.jpg' +style_files += ' guitarix-darkblack-relief.jpg' +style_files += ' sunburst.jpg' +style_files += ' sunburst1.jpg' +style_files += ' sunburst2.jpg' +style_files += ' sunburst3.jpg' +style_files += ' sunburst4.jpg' +style_files += ' rainbow.jpg' +style_files += ' rainbow1.jpg' +style_files += ' rainbow2.jpg' +style_files += ' rainbow3.jpg' +style_files += ' yellow.jpg' +style_files += ' yellow1.jpg' +style_files += ' yellow2.jpg' +style_files += ' yellow3.jpg' +style_files += ' cairo.jpg' +style_files += ' cairo1.jpg' +style_files += ' cairo2.jpg' +style_files += ' zreadable.jpg' +style_files += ' zreadable1.jpg' +style_files += ' zreadable2.jpg' +style_files += ' zreadable3.jpg' +style_files += ' zreadable4.jpg' +style_files += ' zreadable5.jpg' +style_files += ' guitarix_black.rc' +style_files += ' guitarix_cairo.rc' +style_files += ' guitarix_pix.rc' +style_files += ' guitarix_sunburst.rc' +style_files += ' guitarix_rainbow.rc' +style_files += ' guitarix_yellow.rc' +style_files += ' guitarix_default.rc' +style_files += ' guitarix_zac.rc' +style_files += ' guitarix_zreadable.rc' + +def configure(conf): + pass + +def build(bld): + bld.install_files(bld.env['GX_STYLE_DIR'], style_files, chmod=0644) + + + diff --git a/rcstyles/yellow.jpg b/rcstyles/yellow.jpg new file mode 100644 index 0000000..e3b8c3d Binary files /dev/null and b/rcstyles/yellow.jpg differ diff --git a/rcstyles/yellow1.jpg b/rcstyles/yellow1.jpg new file mode 100644 index 0000000..a4289d6 Binary files /dev/null and b/rcstyles/yellow1.jpg differ diff --git a/rcstyles/yellow2.jpg b/rcstyles/yellow2.jpg new file mode 100644 index 0000000..7a566c6 Binary files /dev/null and b/rcstyles/yellow2.jpg differ diff --git a/rcstyles/yellow3.jpg b/rcstyles/yellow3.jpg new file mode 100644 index 0000000..9cea385 Binary files /dev/null and b/rcstyles/yellow3.jpg differ diff --git a/rcstyles/zreadable.jpg b/rcstyles/zreadable.jpg new file mode 100644 index 0000000..983808f Binary files /dev/null and b/rcstyles/zreadable.jpg differ diff --git a/rcstyles/zreadable1.jpg b/rcstyles/zreadable1.jpg new file mode 100644 index 0000000..5722959 Binary files /dev/null and b/rcstyles/zreadable1.jpg differ diff --git a/rcstyles/zreadable2.jpg b/rcstyles/zreadable2.jpg new file mode 100644 index 0000000..d11faad Binary files /dev/null and b/rcstyles/zreadable2.jpg differ diff --git a/rcstyles/zreadable3.jpg b/rcstyles/zreadable3.jpg new file mode 100644 index 0000000..285da4e Binary files /dev/null and b/rcstyles/zreadable3.jpg differ diff --git a/rcstyles/zreadable4.jpg b/rcstyles/zreadable4.jpg new file mode 100644 index 0000000..b7b93e1 Binary files /dev/null and b/rcstyles/zreadable4.jpg differ diff --git a/rcstyles/zreadable5.jpg b/rcstyles/zreadable5.jpg new file mode 100644 index 0000000..57681bd Binary files /dev/null and b/rcstyles/zreadable5.jpg differ diff --git a/src/GtkFastMeter.cpp b/src/GtkFastMeter.cpp new file mode 100644 index 0000000..015e17b --- /dev/null +++ b/src/GtkFastMeter.cpp @@ -0,0 +1,554 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * ------------------------------------------------------------------------- + * + * Code shamelessly stolen from Ardour by Paul Davis, thanks man! + * This is actually an adaptation of the C++ gtkmm2ext class in the + * GTK C style. + * + * ------------------------------------------------------------------------- + */ +#include +#include +#include "GtkFastMeter.h" + +#ifndef max +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#endif + +#ifndef min +#define min(x,y) (((x)<(y)) ? (x) : (y)) +#endif + +#define UINT_TO_RGB(u,r,g,b) { (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; } +#define UINT_TO_RGBA(u,r,g,b,a) { UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; } + +int GtkFastMeter::min_v_pixbuf_size = 10; +int GtkFastMeter::max_v_pixbuf_size = 1024; + +int GtkFastMeter::rgb0 = 0; +int GtkFastMeter::rgb1 = 0; +int GtkFastMeter::rgb2 = 0; +int GtkFastMeter::rgb3 = 0; + +static void gtk_fast_meter_class_init (GtkFastMeterClass*); +static void gtk_fast_meter_init (GtkFastMeter*); + +extern gboolean gtk_fast_meter_expose_event (GtkWidget*, GdkEventExpose*); +static void gtk_fast_meter_size_request (GtkWidget*, GtkRequisition*); +static void gtk_fast_meter_size_allocate (GtkWidget*, GtkAllocation*); +static void gtk_fast_meter_realize (GtkWidget*); + +static gboolean vertical_expose (GtkFastMeter*, GdkEventExpose*); +static void queue_vertical_redraw (GtkFastMeter*, GdkWindow*, float); +static GdkPixbuf* request_vertical_meter (int w, int h); + +static GtkWidgetClass* parent_class = NULL; + +/* ----- fast meter widget type ----- */ +GType gtk_fast_meter_get_type(void) +{ + static GType fm_type = 0; + + if (!fm_type) + { + static const GTypeInfo fm_info = + { + sizeof(GtkFastMeterClass), + NULL, + NULL, + (GClassInitFunc)gtk_fast_meter_class_init, + NULL, + NULL, + sizeof(GtkFastMeter), + 0, + (GInstanceInitFunc)gtk_fast_meter_init + }; + + fm_type = + g_type_register_static(GTK_TYPE_WIDGET, + "GtkFastMeter", &fm_info, (GTypeFlags)0); + } + + return fm_type; +} + +/* ----- fast meter class init ----- */ +void gtk_fast_meter_class_init(GtkFastMeterClass* klass) +{ + GtkObjectClass* object_class; + GtkWidgetClass* widget_class; + + object_class = (GtkObjectClass*)klass; + widget_class = (GtkWidgetClass*)klass; + + parent_class = + (GtkWidgetClass*)gtk_type_class(gtk_widget_get_type()); + + object_class->destroy = gtk_fast_meter_destroy; + + widget_class->realize = gtk_fast_meter_realize; + widget_class->size_request = gtk_fast_meter_size_request; + widget_class->expose_event = gtk_fast_meter_expose_event; + widget_class->size_allocate = gtk_fast_meter_size_allocate; +} + +/* ----- fast meter init ----- */ +void gtk_fast_meter_init (GtkFastMeter* fm) +{ + fm->hold_cnt = 0; + fm->hold_state = 0; + + fm->current_peak = 0; + fm->current_level = 0; + + fm->last_peak_rect.width = 0; + fm->last_peak_rect.height = 0; + + GtkFastMeter::rgb0 = 0x00ff00; + GtkFastMeter::rgb1 = 0xffff00; + GtkFastMeter::rgb2 = 0xffaa00; + GtkFastMeter::rgb3 = 0xff0000; +} + +/* -------------- */ +GtkWidget* gtk_fast_meter_new (long hold, + unsigned long dimen, + int len, + int clr0, + int clr1, + int clr2, + int clr3) +{ + GtkFastMeter* fm; + fm = GTK_FAST_METER(g_object_new(GTK_TYPE_FAST_METER, NULL)); + + fm->hold_cnt = hold; + + GtkFastMeter::rgb0 = clr0; + GtkFastMeter::rgb1 = clr1; + GtkFastMeter::rgb2 = clr2; + GtkFastMeter::rgb3 = clr0; + + gtk_widget_set_events(GTK_WIDGET(fm), + GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + + fm->pixrect.x = 0; + fm->pixrect.y = 0; + + if (len == 0) len = 140; + fm->pixbuf = request_vertical_meter(dimen, len); + + fm->pixheight = gdk_pixbuf_get_height(fm->pixbuf); + fm->pixwidth = gdk_pixbuf_get_width(fm->pixbuf); + + fm->pixrect.width = min(fm->pixwidth, (gint)dimen); + fm->pixrect.height = fm->pixheight; + + fm->request_width = fm->pixrect.width; + fm->request_height = fm->pixrect.height; + + return GTK_WIDGET (fm); +} + +/* ----- create pixbuf for vertical meter ------ */ +static GdkPixbuf* request_vertical_meter(int width, int height) +{ + if (height < GtkFastMeter::min_v_pixbuf_size) + height = GtkFastMeter::min_v_pixbuf_size; + + if (height > GtkFastMeter::max_v_pixbuf_size) + height = GtkFastMeter::max_v_pixbuf_size; + + GdkPixbuf* ret; + guint8* data = (guint8*)malloc(width*height * 3); + + guint8 r,g,b,r0,g0,b0,r1,g1,b1,r2,g2,b2,r3,g3,b3,a; + + UINT_TO_RGBA (GtkFastMeter::rgb0, &r0, &g0, &b0, &a); + UINT_TO_RGBA (GtkFastMeter::rgb1, &r1, &g1, &b1, &a); + UINT_TO_RGBA (GtkFastMeter::rgb2, &r2, &g2, &b2, &a); + UINT_TO_RGBA (GtkFastMeter::rgb3, &r3, &g3, &b3, &a); + + int knee = (int)floor((float)height *0.996f ); + int y; + + for (y = 0; y < knee/2; y++) + { + r = (guint8)floor((float)abs(r1 - r0) * (float)y / (float)(knee/2)); + (r0 >= r1) ? r = r0 - r : r += r0; + + g = (guint8)floor((float)abs(g1 - g0) * (float)y / (float)(knee/2)); + (g0 >= g1) ? g = g0 - g : g += g0; + + b = (guint8)floor((float)abs(b1 - b0) * (float)y / (float)(knee/2)); + (b0 >= b1) ? b = b0 - b : b += b0; + + for (int x = 0; x < width; x++) + { + data[ (x+(height-y-1)*width) * 3 + 0 ] = r; + data[ (x+(height-y-1)*width) * 3 + 1 ] = g; + data[ (x+(height-y-1)*width) * 3 + 2 ] = b; + } + } + + + int offset = knee - y; + for (int i=0; i < offset; i++,y++) + { + + r = (guint8)floor((float)abs(r2 - r1) * (float)i / (float)offset); + (r1 >= r2) ? r = r1 - r : r += r1; + + g = (guint8)floor((float)abs(g2 - g1) * (float)i / (float)offset); + (g1 >= g2) ? g = g1 - g : g += g1; + + b = (guint8)floor((float)abs(b2 - b1) * (float)i / (float)offset); + (b1 >= b2) ? b = b1 - b : b += b1; + + for (int x = 0; x < width; x++) + { + data[ (x+(height-y-1)*width) * 3 + 0 ] = r; + data[ (x+(height-y-1)*width) * 3 + 1 ] = g; + data[ (x+(height-y-1)*width) * 3 + 2 ] = b; + } + } + + for (; y < height; y++) + { + for (int x = 0; x < width; x++) { + data[ (x+(height-y-1)*width) * 3 + 0 ] = r3; + data[ (x+(height-y-1)*width) * 3 + 1 ] = g3; + data[ (x+(height-y-1)*width) * 3 + 2 ] = b3; + } + } + + ret = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, false, 8, width, height, width * 3, NULL, NULL); + return ret; +} + +/* ------ hold count ----- */ +void gtk_fast_meter_set_hold_count(GtkFastMeter* fm, long val) +{ + if (val < 1) val = 1; + + fm->hold_cnt = val; + fm->hold_state = 0; + fm->current_peak = 0; + + gtk_widget_queue_draw(GTK_WIDGET(fm)); +} + +/* ------- on size request ------- */ +void gtk_fast_meter_size_request (GtkWidget* wd, GtkRequisition* req) +{ + GtkFastMeter* fm = GTK_FAST_METER(wd); + + req->height = fm->request_height; + req->height = max(req->height, GtkFastMeter::min_v_pixbuf_size); + req->height = min(req->height, GtkFastMeter::max_v_pixbuf_size); + + req->width = fm->request_width; +} + +/* ------- on size allocate ------- */ +void gtk_fast_meter_size_allocate (GtkWidget* wd, GtkAllocation* alloc) +{ + g_return_if_fail (wd != NULL); + g_return_if_fail (GTK_IS_FAST_METER (wd)); + g_return_if_fail (alloc != NULL); + + GtkFastMeter* fm = GTK_FAST_METER(wd); + + if (alloc->width != fm->request_width) + alloc->width = fm->request_width; + + int h = alloc->height; + h = max(h, GtkFastMeter::min_v_pixbuf_size); + h = min(h, GtkFastMeter::max_v_pixbuf_size); + + if (h != alloc->height) + alloc->height = h; + + if (fm->pixheight != h) + fm->pixbuf = request_vertical_meter(fm->request_width, h); + + fm->pixheight = gdk_pixbuf_get_height(fm->pixbuf); + fm->pixwidth = gdk_pixbuf_get_width (fm->pixbuf); + + wd->allocation = *alloc; + + if (GTK_WIDGET_REALIZED (wd)) + gdk_window_move_resize (wd->window, + alloc->x, alloc->y, alloc->width, alloc->height); +} + + +/* ------- widget realize -------- */ +void gtk_fast_meter_realize (GtkWidget* wd) +{ + + g_return_if_fail (wd != NULL); + g_return_if_fail (GTK_IS_FAST_METER (wd)); + + GdkWindowAttr attributes; + gint attributes_mask; + + GTK_WIDGET_SET_FLAGS (wd, GTK_REALIZED); + + attributes.x = wd->allocation.x; + attributes.y = wd->allocation.y; + attributes.width = wd->allocation.width; + attributes.height = wd->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.event_mask = gtk_widget_get_events (wd) | GDK_EXPOSURE_MASK; + attributes.visual = gtk_widget_get_visual (wd); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; + wd->window = gdk_window_new(wd->parent->window, &attributes, attributes_mask); + wd->style = gtk_style_attach (wd->style, wd->window); + + gdk_window_set_user_data (wd->window, wd); + + gtk_style_set_background (wd->style, wd->window, GTK_STATE_ACTIVE); +} + +/* ------- expose event -------- */ +gboolean gtk_fast_meter_expose_event (GtkWidget* wd, GdkEventExpose* ev) +{ + GtkFastMeter* fm = GTK_FAST_METER(wd); + return vertical_expose (fm ,ev); +} + +/* ------- setting meter level ----------- */ +void gtk_fast_meter_set(GtkFastMeter* fm, float lvl) +{ + float old_level = fm->current_level; + float old_peak = fm->current_peak; + + fm->current_level = lvl; + + if (lvl > fm->current_peak) + { + fm->current_peak = lvl; + fm->hold_state = fm->hold_cnt; + } + + if (fm->hold_state > 0) + if (--fm->hold_state == 0) + fm->current_peak = lvl; + + if (fm->current_level == old_level && + fm->current_peak == old_peak && + fm->hold_state == 0) + return; + + GdkWindow* window = GTK_WIDGET(fm)->window;/*gtk_widget_get_window(GTK_WIDGET(fm));*/; + if (window == 0) + { + gtk_widget_queue_draw(GTK_WIDGET(fm)); + return; + } + + queue_vertical_redraw(fm, window, old_level); +} + +/* ------------- clear fast meter object ------------ */ +void gtk_fast_meter_clear(GtkFastMeter* fm) +{ + fm->current_level = 0; + fm->current_peak = 0; + fm->hold_state = 0; + gtk_widget_queue_draw(GTK_WIDGET(fm)); +} + + + +/* -------------- */ +void gtk_fast_meter_destroy(GtkObject* object) +{ + GtkFastMeter* fm; + + g_return_if_fail(object != NULL); + g_return_if_fail(GTK_IS_FAST_METER (object)); + + fm = GTK_FAST_METER(object); + + if (GTK_WIDGET(object)->parent && + GTK_WIDGET_MAPPED(object)) + gtk_widget_unmap(GTK_WIDGET(object)); + + if (GTK_OBJECT_CLASS(parent_class)->destroy) + (*GTK_OBJECT_CLASS(parent_class)->destroy) (object); +} + +/* ------------------------------ static functions ------------------------- */ + +/* ------- vertical expose event ----------- */ +gboolean vertical_expose (GtkFastMeter* fm, GdkEventExpose* ev) +{ + gint top_of_meter; + GdkRectangle intersection; + GdkRectangle background; + + top_of_meter = (gint) floor (fm->pixheight * fm->current_level); + + /* reset the height & origin of the rect that needs to show the pixbuf */ + + fm->pixrect.height = top_of_meter; + fm->pixrect.y = fm->pixheight - top_of_meter; + + background.x = 0; + background.y = 0; + background.width = fm->pixrect.width; + background.height = fm->pixheight - top_of_meter; + + if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) + { + GdkWindow* window = GTK_WIDGET(fm)->window;/*gtk_widget_get_window(GTK_WIDGET(fm));*/ + GtkStyle* style = gtk_widget_get_style (GTK_WIDGET(fm)); + + gdk_draw_rectangle(GDK_DRAWABLE(window), + style->black_gc, + TRUE, + intersection.x, + intersection.y, + intersection.width, + intersection.height); + } + + if (gdk_rectangle_intersect(&fm->pixrect, &ev->area, &intersection)) + { + // draw the part of the meter image that we need. + // the area we draw is bounded "in reverse" (top->bottom) + GdkWindow* window = GTK_WIDGET(fm)->window;/*gtk_widget_get_window(GTK_WIDGET(fm));*/ + GtkStyle* style = gtk_widget_get_style (GTK_WIDGET(fm)); + + gdk_draw_pixbuf(GDK_DRAWABLE(window), + style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(fm))], + fm->pixbuf, + intersection.x, intersection.y, + intersection.x, intersection.y, + intersection.width, intersection.height, + GDK_RGB_DITHER_NONE, 0, 0); + } + + // draw peak bar + + if (fm->hold_state) + { + fm->last_peak_rect.x = 0; + fm->last_peak_rect.width = fm->pixwidth; + fm->last_peak_rect.y = fm->pixheight - + (gint)floor(fm->pixheight * fm->current_peak); + + fm->last_peak_rect.height = min(3, fm->pixheight - fm->last_peak_rect.y); + + GdkWindow* window = GTK_WIDGET(fm)->window; + GtkStyle* style = gtk_widget_get_style (GTK_WIDGET(fm)); + + gdk_draw_pixbuf(GDK_DRAWABLE(window), + style->fg_gc[GTK_WIDGET_STATE(GTK_WIDGET(fm))], + fm->pixbuf, + 0, fm->last_peak_rect.y, + 0, fm->last_peak_rect.y, + fm->pixwidth, fm->last_peak_rect.height, + GDK_RGB_DITHER_NONE, 0, 0); + } + else + { + fm->last_peak_rect.width = 0; + fm->last_peak_rect.height = 0; + } + + return TRUE; +} + +/* --------- vertical drawing queue ----------- */ +void queue_vertical_redraw (GtkFastMeter* fm, + GdkWindow* win, + float old_level) +{ + GdkRectangle rect; + + gint new_top = (gint)floor(fm->pixheight * fm->current_level); + + rect.x = 0; + rect.width = fm->pixwidth; + rect.height = new_top; + rect.y = fm->pixheight - new_top; + + if (fm->current_level > old_level) + { + /* colored/pixbuf got larger, just draw the new section */ + /* rect.y stays where it is because of X coordinates */ + /* height of invalidated area is between new.y (smaller) and old.y + (larger). + X coordinates just make my brain hurt. + */ + rect.height = fm->pixrect.y - rect.y; + } + else + { + /* it got smaller, compute the difference */ + /* rect.y becomes old.y (the smaller value) */ + rect.y = fm->pixrect.y; + /* rect.height is the old.y (smaller) minus the new.y (larger) */ + rect.height = fm->pixrect.height - rect.height; + } + + + GdkRegion* region = 0; + bool queue = false; + + if (rect.height != 0) + { + /* ok, first region to draw ... */ + region = gdk_region_rectangle (&rect); + queue = true; + } + + /* redraw the last place where the last peak hold bar was; + the next expose will draw the new one whether its part of + expose region or not. */ + + if (fm->last_peak_rect.width * fm->last_peak_rect.height != 0) + { + if (!queue) + { + region = gdk_region_new (); + queue = true; + } + + gdk_region_union_with_rect (region, &fm->last_peak_rect); + } + + if (queue) + gdk_window_invalidate_region (win, region, TRUE); + + // avoid mem leak + if (region) + { + gdk_region_destroy(region); + region = 0; + } +} + +/* -------------- */ +/* EOF */ + diff --git a/src/GtkRegler.cpp b/src/GtkRegler.cpp new file mode 100644 index 0000000..68bc3d1 --- /dev/null +++ b/src/GtkRegler.cpp @@ -0,0 +1,2401 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// ***** GtkRegler.cpp ***** +/****************************************************************************** +part of guitarix, use reglers with Gtk +******************************************************************************/ + +#include +#include +#include +#include +#include + +using namespace std; +#include "GtkRegler.h" + +#define GTK_TYPE_REGLER (gtk_regler_get_type()) +#define GTK_REGLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_REGLER, GtkRegler)) +#define GTK_IS_REGLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_REGLER)) +#define GTK_REGLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_REGLER, GtkReglerClass)) +#define GTK_IS_REGLER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_REGLER)) + +GtkRegler::GtkRegler() +// GtkRegler constructor +{ + +} + +GtkRegler::~GtkRegler() +{ + // Nothing specific to do... +} + +struct GtkReglerClass { + GtkRangeClass parent_class; + GdkPixbuf *regler_image; + GdkPixbuf *bigregler_image; + GdkPixbuf *toggle_image; + GdkPixbuf *toggle_image1; + GdkPixbuf *switch_image; + GdkPixbuf *switch_image1; + GdkPixbuf *slider_image; + GdkPixbuf *slider_image1; + GdkPixbuf *vslider_image; + GdkPixbuf *vslider_image1; + GdkPixbuf *minislider_image; + GdkPixbuf *minislider_image1; + GdkPixbuf *eqslider_image; + GdkPixbuf *eqslider_image1; + GdkPixbuf *wheel_image; + GdkPixbuf *wheel_image1; + GdkPixbuf *pointer_image1; + GdkPixbuf *b_toggle_image; + GdkPixbuf *b_toggle_image1; + GdkPixbuf *led_image; + GdkPixbuf *rp_image; + GdkPixbuf *p_image; + GdkPixbuf *rp_image1; + GdkPixbuf *p_image1; + +//----------- small knob + int regler_x; + int regler_y; + int regler_step; +//----------- Big knob + int bigknob_x; + int bigknob_y; + int bigknob_step; +//----------- switcher + int toggle_x; + int toggle_y ; + int toggle_step; +//----------- switcherII + int switch_x; + int switch_y ; + int switch_step; +//----------- minitoggle + int minitoggle_x; + int minitoggle_y ; + int minitoggle_step; +//----------- horizontal slider + int slider_x; + int slider_y; + int vslider_x; + int slider_step; + int vslider_step; +//----------- horizontal slider + int minislider_x; + int minislider_y; + int minislider_step; +//----------- eqslider + int eqslider_x; + int eqslider_y; + int eqslider_step; +//----------- horizontal slider + int wheel_x; + int wheel_y; + int wheel_step; +//-----------in or outline graphic + int in_regler; + int in_knob; + int in_toggle; + int in_switch; + int in_slider; + int in_minislider; +//----------- toggle button + int b_toggle_x; + int b_toggle_y ; + int b_toggle_step; +//----------- event button + int button_is; + int pix_is; + int pix_switch; +//----------- selector button + int selector_x; + int selector_y ; + int selector_step; +//----------- led + int led_x; + int led_y; +//----------- value display + int vd_x; + int vd_y; +//----------- rec/play button + int rp_x; + int rp_y; + int rp_step; + +}; + +//------forward declaration +GType gtk_regler_get_type (); + +/**************************************************************** + ** calculate the knop pointer with dead zone + */ + +const double scale_zero = 20 * (M_PI/180); // defines "dead zone" for knobs + +//------------ calculate needed precision +int precision(double n) +{ + if (n < 0.009999) return 3; + else if (n < 0.099999) return 2; + else if (n < 0.999999) return 1; + else return 0; +} + + +static void knob_expose(GtkWidget *widget, int knob_x, int knob_y, + GdkPixbuf *regler_image, int arc_offset) +{ + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + int reglerx = widget->allocation.x + (widget->allocation.width - knob_x) * 0.5; + int reglery = widget->allocation.y + (widget->allocation.height - knob_y) * 0.5; + double reglerstate = (adj->value - adj->lower) / (adj->upper - adj->lower); + double angle = scale_zero + reglerstate * 2 * (M_PI - scale_zero); + const double pointer_off = 5; + double radius = min(knob_x-pointer_off, knob_y-pointer_off) / 2; + double lengh_x = (reglerx+radius+pointer_off/2) - radius * sin(angle); + double lengh_y = (reglery+radius+pointer_off/2) + radius * cos(angle); + double radius1 = min(knob_x, knob_y) / 2; + + GdkColor color; + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + // linear color change in RGB space from (52480, 0, 5120) to (8448, 46004, 5120) + color.red = 52480 - int(44032 * reglerstate); + color.green = int(46004 * reglerstate); + color.blue = 5120; + gtk_paint_focus(widget->style, widget->window, GTK_STATE_NORMAL, NULL, widget, NULL, + reglerx, reglery, knob_x, knob_y); + } else { + color.red = 5120; + color.green = 742; + color.blue = 52480; + } + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + regler_image, 0,0, reglerx, reglery, + knob_x, knob_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + /** this is to create a pointer rotating on the knob with painting funktions **/ + GdkGC *line = gdk_gc_new(GDK_DRAWABLE(widget->window)); + cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_set_line_width(cr, 5.0); + cairo_move_to(cr, reglerx+radius1, reglery+radius1); + cairo_line_to(cr,lengh_x,lengh_y); + cairo_stroke(cr); + cairo_set_source_rgb(cr, 0.9, 0.9, 0.9); + cairo_set_line_width(cr, 1.0); + cairo_move_to(cr, reglerx+radius1, reglery+radius1); + cairo_line_to(cr,lengh_x,lengh_y); + cairo_stroke(cr); + cairo_destroy(cr); + + gdk_gc_set_rgb_fg_color(line, &color); + gdk_gc_set_line_attributes(line, 1,GDK_LINE_SOLID,GDK_CAP_BUTT,GDK_JOIN_ROUND); + gdk_draw_arc(GDK_DRAWABLE(widget->window), line, FALSE, + reglerx+arc_offset, reglery+arc_offset, + knob_x-1-2*arc_offset, knob_y-1-2*arc_offset,-90*64,360*64); + g_object_unref(line); + /** pointer ready **/ +} + +/**************************************************************** + ** general expose events for all "regler" controllers + */ + +//----------- draw the Regler when moved +static gboolean gtk_regler_expose (GtkWidget *widget, GdkEventExpose *event) +{ + g_assert(GTK_IS_REGLER(widget)); + GtkRegler *regler = GTK_REGLER(widget); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + GdkWindow *window = widget->window; + + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + + int reglerx = widget->allocation.x, reglery = widget->allocation.y; + +//----------- small knob + if (regler->regler_type == 0) { + knob_expose(widget, klass->regler_x, klass->regler_y, klass->regler_image, 0); + } +//--------- Big knob + else if (regler->regler_type == 1) { + knob_expose(widget, klass->bigknob_x, klass->bigknob_y, klass->bigregler_image, 2); + } + +//---------- switch + else if (regler->regler_type == 2) { + reglerx += (widget->allocation.width - + klass->toggle_x) *0.5; + reglery += (widget->allocation.height - + klass->toggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->toggle_step / (adj->upper - adj->lower)); + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->toggle_image1, reglerstate * + klass->toggle_x, 0, reglerx, reglery, + klass->toggle_x, + klass->toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } else { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->toggle_image, reglerstate * + klass->toggle_x, 0, reglerx, reglery, + klass->toggle_x, + klass->toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + } + +//--------- horizontal slider + else if (regler->regler_type == 3) { + reglerx += (widget->allocation.width - + klass->slider_x) *0.5; + reglery += (widget->allocation.height - + klass->slider_y) *0.5; + + int reglerstate = (int)((adj->value - adj->lower) * + klass->slider_step / (adj->upper - adj->lower)); + + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gtk_paint_focus(widget->style, window, GTK_STATE_NORMAL, NULL, widget, NULL, + reglerx, reglery, klass->slider_x, + klass->slider_y); + + gdk_pixbuf_copy_area(klass->slider_image,0,0, + klass->slider_x, + klass->slider_y, + klass->slider_image1,0,0); + + gdk_pixbuf_copy_area(klass->slider_image, + klass->slider_x,0,20, + klass->slider_y, + klass->slider_image1, reglerstate,0); + + gdk_pixbuf_saturate_and_pixelate(klass->slider_image1, + klass->slider_image1,70.0,FALSE); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->slider_image1, 0, 0, reglerx, reglery, + klass->slider_x, + klass->slider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } else { + + gdk_pixbuf_copy_area(klass->slider_image,0,0, + klass->slider_x, + klass->slider_y, + klass->slider_image1,0,0); + + gdk_pixbuf_copy_area(klass->slider_image, + klass->slider_x,0,20, + klass->slider_y, + klass->slider_image1, reglerstate,0); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->slider_image1, 0, 0, reglerx, reglery, + klass->slider_x, + klass->slider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + } + +//--------- mini slider + else if (regler->regler_type == 4) { + reglerx += (widget->allocation.width - + klass->minislider_x) *0.5; + reglery += (widget->allocation.height - + klass->minislider_y) *0.5; + + int reglerstate = (int)((adj->value - adj->lower) * + klass->minislider_step / (adj->upper - adj->lower)); + + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gdk_pixbuf_copy_area(klass->minislider_image,0,0, + klass->minislider_x, + klass->minislider_y, + klass->minislider_image1,0,0); + + gdk_pixbuf_copy_area(klass->minislider_image, + klass->minislider_x,0,6, + klass->minislider_y, + klass->minislider_image1, reglerstate,0); + + gdk_pixbuf_saturate_and_pixelate(klass->minislider_image1, + klass->minislider_image1,99.0,FALSE); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->minislider_image1, 0, 0, reglerx, reglery, + klass->minislider_x, + klass->minislider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } else { + + gdk_pixbuf_copy_area(klass->minislider_image,0,0, + klass->minislider_x, + klass->minislider_y, + klass->minislider_image1,0,0); + + gdk_pixbuf_copy_area(klass->minislider_image, + klass->minislider_x,0,6, + klass->minislider_y, + klass->minislider_image1, reglerstate,0); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->minislider_image1, 0, 0, reglerx, reglery, + klass->minislider_x, + klass->minislider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + } + +//---------- switchII + else if (regler->regler_type == 5) { + reglerx += (widget->allocation.width - + klass->switch_x) *0.5; + reglery += (widget->allocation.height - + klass->switch_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->switch_step / (adj->upper - adj->lower)); + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image1, reglerstate * + klass->switch_x, 0, reglerx, reglery, + klass->switch_x, + klass->switch_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } else { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image, reglerstate * + klass->switch_x, 0, reglerx, reglery, + klass->switch_x, + klass->switch_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + } + +//---------- minitoggle + else if (regler->regler_type == 6) { + reglerx += (widget->allocation.width - + klass->minitoggle_x) *0.5; + reglery += (widget->allocation.height - + klass->minitoggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->switch_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =2; + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image1, reglerstate * + klass->minitoggle_x, 0, reglerx, reglery, + klass->minitoggle_x, + klass->minitoggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } else { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image, reglerstate * + klass->minitoggle_x, 0, reglerx, reglery, + klass->minitoggle_x, + klass->minitoggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + } + +//----------- wheel + else if (regler->regler_type == 7) { + reglerx += (widget->allocation.width - + klass->wheel_x) *0.5; + reglery += (widget->allocation.height - + klass->wheel_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->wheel_step / (adj->upper - adj->lower)); + int smoth_pointer = 0; + if (reglerstate>(adj->upper - adj->lower))smoth_pointer=-4; + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image1, 0, 0, reglerx, reglery, + klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image, + reglerstate + klass->wheel_x, 0, + reglerx, reglery, klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->pointer_image1,0, 0, + reglerx+smoth_pointer+reglerstate*0.4, reglery, 2, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + } else { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image1, 0, 0, reglerx, reglery, + klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image, + reglerstate + klass->wheel_x, 0, + reglerx, reglery, klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->pointer_image1,0, 0, + reglerx+smoth_pointer+reglerstate*0.4, reglery, 2, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + } + } + +//---------- toggle button + else if (regler->regler_type == 8) { + reglerx += (widget->allocation.width - + klass->b_toggle_x) *0.5; + reglery += (widget->allocation.height - + klass->b_toggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->b_toggle_step / (adj->upper - adj->lower)); + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->b_toggle_image1, 0, + reglerstate * klass->b_toggle_y, reglerx, reglery, + klass->b_toggle_x, + klass->b_toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } else { + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->b_toggle_image, 0, + reglerstate * klass->b_toggle_y, + reglerx, reglery, klass->b_toggle_x, + klass->b_toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + } + +//--------- vertical slider + else if (regler->regler_type == 9) { + reglerx += (widget->allocation.width - + klass->slider_y) *0.5; + reglery += (widget->allocation.height - + klass->vslider_x) *0.5; + + int reglerstate = (int)((adj->upper - adj->value ) * + klass->vslider_step / (adj->upper - adj->lower)); + + if (GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + gtk_paint_focus(widget->style, window, GTK_STATE_NORMAL, NULL, widget, NULL, + reglerx, reglery, klass->slider_y, + klass->vslider_x); + + gdk_pixbuf_copy_area(klass->vslider_image,0,20, + klass->slider_y, + klass->vslider_x, + klass->vslider_image1,0,0); + + gdk_pixbuf_copy_area(klass->vslider_image,0, + klass->slider_x,10,20, + klass->vslider_image1,0, reglerstate); + + gdk_pixbuf_saturate_and_pixelate(klass->vslider_image1, + klass->vslider_image1,70.0,FALSE); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->vslider_image1, 0, 0, reglerx, reglery, + klass->slider_y, + klass->vslider_x, GDK_RGB_DITHER_NORMAL, 0, 0); + } else { + + gdk_pixbuf_copy_area(klass->vslider_image,0,20, + klass->slider_y, + klass->vslider_x, + klass->vslider_image1,0,0); + + gdk_pixbuf_copy_area(klass->vslider_image,0, + klass->slider_x,10,20, + klass->vslider_image1, 0,reglerstate); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->vslider_image1, 0, 0, reglerx, reglery, + klass->slider_y, + klass->vslider_x, GDK_RGB_DITHER_NORMAL, 0, 0); + } + } + +//--------- mini slider + else if (regler->regler_type == 10) { + reglerx += (widget->allocation.width - + klass->eqslider_x) *0.5; + reglery += (widget->allocation.height - + klass->eqslider_y) *0.5; + + int reglerstate = (int)((adj->value - adj->lower) * + klass->eqslider_step / (adj->upper - adj->lower)); + + + gdk_pixbuf_copy_area(klass->eqslider_image,0,reglerstate+8, + klass->eqslider_x, + klass->eqslider_y, + klass->eqslider_image1,0,0); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->eqslider_image1, 0, 0, reglerx, reglery, + klass->eqslider_x, + klass->eqslider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + } + +//---------- selector button + else if (regler->regler_type == 11) { + /*reglerx += ((widget->allocation.width - + klass->selector_x) *0.5)+2; + reglery += (widget->allocation.height - + klass->selector_y) *0.5; */ + int reglerstate = (int)((adj->value - adj->lower) * + (regler->max_value) / (adj->upper - adj->lower)); + assert(reglerstate >= 0 && reglerstate <= regler->max_value); + + cairo_t*cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + cairo_set_line_width (cr, 2.0); + cairo_rectangle (cr, reglerx+8,reglery+1,widget->allocation.width-18,widget->allocation.height-2); + cairo_set_source_rgba (cr, 0, 0, 0, 0.5); + cairo_fill_preserve (cr); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_stroke (cr); + cairo_rectangle (cr, reglerx+widget->allocation.width-19,reglery+2,9,widget->allocation.height-4); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill_preserve (cr); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); + cairo_stroke (cr); + + ostringstream tir; + tir << regler->labels[reglerstate] ; + + cairo_set_source_rgba (cr, 0.4, 1, 0.2, 0.8); + cairo_set_font_size (cr, 10.0); + cairo_move_to (cr, reglerx+10, reglery+11); + cairo_show_text(cr, tir.str().c_str()); + cairo_stroke (cr); + cairo_destroy(cr); + } + +//---------- led + else if (regler->regler_type == 12) { + /*reglerx += (widget->allocation.x); + reglery += (widget->allocation.height - + klass->led_y) *0.5;*/ + int reglerstate = (int)((adj->value - adj->lower) * + klass->b_toggle_step / (adj->upper - adj->lower)); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->led_image, 0, + reglerstate * klass->led_y, 8, 12, //left upper corner, else use reglex,reglery + klass->led_x, + klass->led_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + + //---------- value diplay + else if (regler->regler_type == 13) { + reglerx += (widget->allocation.x); + reglery += (widget->allocation.height - + klass->vd_y) *0.5; + /*int reglerstate = (int)((adj->value - adj->lower) * + klass->b_toggle_step / (adj->upper - adj->lower));*/ + float v = adj->value; + + char s[64]; + + if (adj->step_increment < 0.009999) { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[3-1], v); + } else if (adj->step_increment < 0.09999) { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[2-1], v); + } else if (adj->step_increment < 0.9999) { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[1-1], v); + } else if (adj->step_increment < 9.9999) { + snprintf(s, 63, "%d", int(v)); + } else + snprintf(s, 63, "%d", int(v)); + + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(widget->window); + + double x0 = widget->allocation.x+2; + double y0 = widget->allocation.y+2; + + double rect_width = widget->allocation.width-4; + double rect_height = widget->allocation.height-4; + + cairo_rectangle (cr, x0-1,y0-1,rect_width+2,rect_height+2); + cairo_set_source_rgba (cr, 0, 0, 0, 0.4); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width-10, rect_height, 20.0); + cairo_pattern_add_color_stop_rgba (pat, 1, 0., 0., 0., 0.8); + cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 0, 0.4); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+2,y0+2,rect_width-4,rect_height-4); + cairo_fill (cr); + + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+rect_width-3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+rect_height-2); + cairo_line_to(cr, x0+2, y0+rect_height-2); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+3, y0+rect_height-1); + cairo_line_to(cr, x0+3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+3); + cairo_stroke(cr); + + ostringstream tir; + tir << s ; + + cairo_set_source_rgba (cr, 0.4, 1, 0.2, 0.8); + cairo_set_font_size (cr, 10.0); + cairo_move_to (cr, x0+5, y0+rect_height-4); + cairo_show_text(cr, tir.str().c_str()); + cairo_stroke (cr); + + cairo_destroy(cr); + } + + //---------- rec button + else if (regler->regler_type == 14) { + reglerx += (widget->allocation.width - + klass->rp_x) *0.5; + reglery += (widget->allocation.height - + klass->rp_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->rp_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =1; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->rp_image,0, reglerstate * + klass->rp_y, reglerx, reglery, + klass->rp_x, + klass->rp_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + + //---------- play button + else if (regler->regler_type == 15) { + reglerx += (widget->allocation.width - + klass->rp_x) *0.5; + reglery += (widget->allocation.height - + klass->rp_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->rp_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =1; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->p_image,0, reglerstate * + klass->rp_y, reglerx, reglery, + klass->rp_x, + klass->rp_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + + return TRUE; +} + +/**************************************************************** + ** redraw when leave + */ + +static gboolean gtk_regler_leave_out (GtkWidget *widget, GdkEventCrossing *event) +{ + g_assert(GTK_IS_REGLER(widget)); + GtkRegler *regler = GTK_REGLER(widget); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + int reglerx = widget->allocation.x, reglery = widget->allocation.y; + +//----------- small knob + if (regler->regler_type == 0) { + if (GTK_WIDGET_HAS_GRAB(widget) || GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + return TRUE; + } + reglerx += (widget->allocation.width - + klass->regler_x) *0.5; + reglery += (widget->allocation.height - + klass->regler_y) *0.5; + + GdkGC * line = gdk_gc_new(GDK_DRAWABLE(widget->window)); + GdkColor color ; + + color.red = 20 * 256; + color.blue = 205 * 256; + color.green = 742; + gdk_gc_set_rgb_fg_color(line, &color); + gdk_gc_set_line_attributes (line, 1,GDK_LINE_SOLID,GDK_CAP_BUTT,GDK_JOIN_ROUND); + gdk_draw_arc(GDK_DRAWABLE(widget->window), line, FALSE,reglerx, reglery, + klass->regler_x-1 , + klass->regler_y-1,-90*64,360*64); + g_object_unref(line ); + } + +//----------- Big knob + else if (regler->regler_type == 1) { + if (GTK_WIDGET_HAS_GRAB(widget) || GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + return TRUE; + } + reglerx += (widget->allocation.width - + klass->bigknob_x) *0.5; + reglery += (widget->allocation.height - + klass->bigknob_y) *0.5; + + GdkGC * line = gdk_gc_new(GDK_DRAWABLE(widget->window)); + GdkColor color ; + + color.red = 20 * 256; + color.blue = 205 * 256; + color.green = 742; + gdk_gc_set_rgb_fg_color(line, &color); + gdk_gc_set_line_attributes (line, 1,GDK_LINE_SOLID,GDK_CAP_BUTT,GDK_JOIN_ROUND); + gdk_draw_arc(GDK_DRAWABLE(widget->window), line, FALSE,reglerx+2, reglery+2, + klass->bigknob_x-5 , + klass->bigknob_y-5,-90*64,360*64); + g_object_unref(line ); + } + +//----------- switch + else if (regler->regler_type == 2) { + reglerx += (widget->allocation.width - + klass->toggle_x) *0.5; + reglery += (widget->allocation.height - + klass->toggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->toggle_step / (adj->upper - adj->lower)); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->toggle_image, + reglerstate * klass->toggle_x, 0, + reglerx, reglery, klass->toggle_x, + klass->toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- horizontal slider + else if (regler->regler_type == 3) { + reglerx += (widget->allocation.width - + klass->slider_x) *0.5; + reglery += (widget->allocation.height - + klass->slider_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->slider_step / (adj->upper - adj->lower)); + + gdk_pixbuf_copy_area(klass->slider_image,0,0, + klass->slider_x, + klass->slider_y, + klass->slider_image1,0,0); + + gdk_pixbuf_copy_area(klass->slider_image, + klass->slider_x,0,20, + klass->slider_y, + klass->slider_image1, reglerstate,0); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->slider_image1, 0, 0, reglerx, reglery, + klass->slider_x, + klass->slider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- mini slider + else if (regler->regler_type == 4) { + reglerx += (widget->allocation.width - + klass->minislider_x) *0.5; + reglery += (widget->allocation.height - + klass->minislider_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->minislider_step / (adj->upper - adj->lower)); + + gdk_pixbuf_copy_area(klass->minislider_image,0,0, + klass->minislider_x, + klass->minislider_y, + klass->minislider_image1,0,0); + + gdk_pixbuf_copy_area(klass->minislider_image, + klass->minislider_x,0,6, + klass->minislider_y, + klass->minislider_image1, reglerstate,0); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->minislider_image1, 0, 0, reglerx, reglery, + klass->minislider_x, + klass->minislider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- switchII + else if (regler->regler_type == 5) { + reglerx += (widget->allocation.width - + klass->switch_x) *0.5; + reglery += (widget->allocation.height - + klass->switch_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->switch_step / (adj->upper - adj->lower)); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image, + reglerstate * klass->switch_x, 0, + reglerx, reglery, klass->switch_x, + klass->switch_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- minitoggle + else if (regler->regler_type == 6) { + reglerx += (widget->allocation.width - + klass->minitoggle_x) *0.5; + reglery += (widget->allocation.height - + klass->minitoggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->minitoggle_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =2; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image, + reglerstate * klass->minitoggle_x, 0, + reglerx, reglery, klass->minitoggle_x, + klass->minitoggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- wheel + else if (regler->regler_type == 7) { + reglerx += (widget->allocation.width - + klass->wheel_x) *0.5; + reglery += (widget->allocation.height - + klass->wheel_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->wheel_step / (adj->upper - adj->lower)); + int smoth_pointer = 0; + if (reglerstate>(adj->upper - adj->lower))smoth_pointer=-4; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image1, 0, 0, reglerx, reglery, + klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image, + reglerstate + klass->wheel_x, 0, reglerx, reglery, + klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->pointer_image1,0, 0, + reglerx+smoth_pointer+reglerstate*0.4, reglery, 2, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + } + +//---------- toggle button + else if (regler->regler_type == 8) { + reglerx += (widget->allocation.width - + klass->b_toggle_x) *0.5; + reglery += (widget->allocation.height - + klass->b_toggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->b_toggle_step / (adj->upper - adj->lower)); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->b_toggle_image, 0, + reglerstate * klass->b_toggle_y, + reglerx, reglery, klass->b_toggle_x, + klass->b_toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + } + +//----------- vertical slider + else if (regler->regler_type == 9) { + reglerx += (widget->allocation.width - + klass->slider_y) *0.5; + reglery += (widget->allocation.height - + klass->vslider_x) *0.5; + int reglerstate = (int)((adj->upper -adj->value ) * + klass->vslider_step / (adj->upper - adj->lower)); + + gdk_pixbuf_copy_area(klass->vslider_image,0,20, + klass->slider_y, + klass->vslider_x, + klass->vslider_image1,0,0); + + gdk_pixbuf_copy_area(klass->vslider_image,0, + klass->slider_x,10,20, + klass->vslider_image1, 0,reglerstate); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->vslider_image1, 0, 0, reglerx, reglery, + klass->slider_y, + klass->vslider_x, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//---------- selector button + else if (regler->regler_type == 11) { + /*reglerx += ((widget->allocation.width - + klass->selector_x) *0.5)+2; + reglery += (widget->allocation.height - + klass->selector_y) *0.5; */ + + cairo_t*cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + + cairo_rectangle (cr, reglerx+widget->allocation.width-19,reglery+2,9,widget->allocation.height-4); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill_preserve (cr); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); + cairo_stroke (cr); + cairo_destroy(cr); + } + + //---------- rec button + else if (regler->regler_type == 14) { + reglerx += (widget->allocation.width - + klass->rp_x) *0.5; + reglery += (widget->allocation.height - + klass->rp_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->rp_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =1; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->rp_image,0, reglerstate * + klass->rp_y, reglerx, reglery, + klass->rp_x, + klass->rp_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + + //---------- play button + else if (regler->regler_type == 15) { + reglerx += (widget->allocation.width - + klass->rp_x) *0.5; + reglery += (widget->allocation.height - + klass->rp_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->rp_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =1; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->p_image,0, reglerstate * + klass->rp_y, reglerx, reglery, + klass->rp_x, + klass->rp_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + + + return TRUE; +} + +/**************************************************************** + ** redraw when enter + */ + +static gboolean gtk_regler_enter_in (GtkWidget *widget, GdkEventCrossing *event) +{ + g_assert(GTK_IS_REGLER(widget)); + GtkRegler *regler = GTK_REGLER(widget); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + int reglerx = widget->allocation.x, reglery = widget->allocation.y; + +//----------- small knob + if (regler->regler_type == 0) { + if (GTK_WIDGET_HAS_GRAB(widget) || GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + return TRUE; + } + reglerx += (widget->allocation.width - + klass->regler_x) *0.5; + reglery += (widget->allocation.height - + klass->regler_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->regler_step / (adj->upper - adj->lower)); + + GdkGC * line = gdk_gc_new(GDK_DRAWABLE(widget->window)); + GdkColor color ; + + color.red = (205-reglerstate*2) * 256; + color.blue = 20 * 256; + color.green = reglerstate*742; + gdk_gc_set_rgb_fg_color(line, &color); + gdk_gc_set_line_attributes (line, 1,GDK_LINE_SOLID,GDK_CAP_BUTT,GDK_JOIN_ROUND); + gdk_draw_arc(GDK_DRAWABLE(widget->window), line, FALSE,reglerx, reglery, + klass->regler_x-1 , + klass->regler_y-1, + (-reglerstate-90)*64,(-reglerstate-360)*64); + g_object_unref(line ); + + } + +//----------- Big knob + else if (regler->regler_type == 1) { + if (GTK_WIDGET_HAS_GRAB(widget) || GTK_WIDGET_HAS_FOCUS(widget)== TRUE) { + return TRUE; + } + reglerx += (widget->allocation.width - + klass->bigknob_x) *0.5; + reglery += (widget->allocation.height - + klass->bigknob_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->bigknob_step / (adj->upper - adj->lower)); + + GdkGC * line = gdk_gc_new(GDK_DRAWABLE(widget->window)); + GdkColor color ; + + color.red = (205-reglerstate*2) * 256; + color.blue = 20 * 256; + color.green = reglerstate*742; + gdk_gc_set_rgb_fg_color(line, &color); + gdk_gc_set_line_attributes (line, 1,GDK_LINE_SOLID,GDK_CAP_BUTT,GDK_JOIN_ROUND); + gdk_draw_arc(GDK_DRAWABLE(widget->window), line, FALSE,reglerx+2, reglery+2, + klass->bigknob_x-5 , + klass->bigknob_y-5, + (-reglerstate-90)*64,(-reglerstate-360)*64); + g_object_unref(line ); + + } + +//----------- switch + else if (regler->regler_type == 2) { + reglerx += (widget->allocation.width - + klass->toggle_x) *0.5; + reglery += (widget->allocation.height - + klass->toggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->toggle_step / (adj->upper - adj->lower)); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->toggle_image1, + reglerstate * klass->toggle_x, 0, + reglerx, reglery, klass->toggle_x, + klass->toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- horizontal slider + else if (regler->regler_type == 3) { + reglerx += (widget->allocation.width - + klass->slider_x) *0.5; + reglery += (widget->allocation.height - + klass->slider_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->slider_step / (adj->upper - adj->lower)); + + gdk_pixbuf_copy_area(klass->slider_image,0,0, + klass->slider_x, + klass->slider_y, + klass->slider_image1,0,0); + + gdk_pixbuf_copy_area(klass->slider_image, + klass->slider_x,0,20, + klass->slider_y, + klass->slider_image1, reglerstate,0); + + gdk_pixbuf_saturate_and_pixelate(klass->slider_image1, + klass->slider_image1,70.0,FALSE); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->slider_image1, 0, 0, + reglerx, reglery, klass->slider_x, + klass->slider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- mini slider + else if (regler->regler_type == 4) { + reglerx += (widget->allocation.width - + klass->minislider_x) *0.5; + reglery += (widget->allocation.height - + klass->minislider_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->minislider_step / (adj->upper - adj->lower)); + + gdk_pixbuf_copy_area(klass->minislider_image,0,0, + klass->minislider_x, + klass->minislider_y, + klass->minislider_image1,0,0); + + gdk_pixbuf_copy_area(klass->minislider_image, + klass->minislider_x,0,6, + klass->minislider_y, + klass->minislider_image1, reglerstate,0); + + gdk_pixbuf_saturate_and_pixelate(klass->minislider_image1, + klass->minislider_image1,99.0,FALSE); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->minislider_image1, 0, 0, + reglerx, reglery, klass->minislider_x, + klass->minislider_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- switch + else if (regler->regler_type == 5) { + reglerx += (widget->allocation.width - + klass->switch_x) *0.5; + reglery += (widget->allocation.height - + klass->switch_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->switch_step / (adj->upper - adj->lower)); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image1, + reglerstate * klass->switch_x, 0, + reglerx, reglery, klass->switch_x, + klass->switch_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- minitoggle + else if (regler->regler_type == 6) { + reglerx += (widget->allocation.width - + klass->minitoggle_x) *0.5; + reglery += (widget->allocation.height - + klass->minitoggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->minitoggle_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =2; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->switch_image1, reglerstate * + klass->minitoggle_x, 0, reglerx, reglery, + klass->minitoggle_x, + klass->minitoggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//----------- wheel + else if (regler->regler_type == 7) { + reglerx += (widget->allocation.width - + klass->wheel_x) *0.5; + reglery += (widget->allocation.height - + klass->wheel_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->wheel_step / (adj->upper - adj->lower)); + int smoth_pointer = 0; + if (reglerstate>(adj->upper - adj->lower))smoth_pointer=-4; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image1, 0, 0, reglerx, reglery, + klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->wheel_image, + reglerstate + klass->wheel_x, 0, + reglerx, reglery, klass->wheel_x, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->pointer_image1,0, 0, + reglerx+smoth_pointer+reglerstate*0.4, reglery, 2, + klass->wheel_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + } + +//---------- toggle button + else if (regler->regler_type == 8) { + reglerx += (widget->allocation.width - + klass->b_toggle_x) *0.5; + reglery += (widget->allocation.height - + klass->b_toggle_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->b_toggle_step / (adj->upper - adj->lower)); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->b_toggle_image1, 0, + reglerstate * klass->b_toggle_y, + reglerx, reglery, klass->b_toggle_x, + klass->b_toggle_y, GDK_RGB_DITHER_NORMAL, 0, 0); + + } + +//----------- vertical slider + else if (regler->regler_type == 9) { + reglerx += (widget->allocation.width - + klass->slider_y) *0.5; + reglery += (widget->allocation.height - + klass->vslider_x) *0.5; + int reglerstate = (int)((adj->upper -adj->value ) * + klass->vslider_step / (adj->upper - adj->lower)); + + gdk_pixbuf_copy_area(klass->vslider_image,0,20, + klass->slider_y, + klass->vslider_x, + klass->vslider_image1,0,0); + + gdk_pixbuf_copy_area(klass->vslider_image,0, + klass->slider_x,10,20, + klass->vslider_image1, 0,reglerstate); + + gdk_pixbuf_saturate_and_pixelate(klass->vslider_image1, + klass->vslider_image1,70.0,FALSE); + + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->vslider_image1, 0, 0, + reglerx, reglery, klass->slider_y, + klass->vslider_x, GDK_RGB_DITHER_NORMAL, 0, 0); + } + +//---------- selector button + else if (regler->regler_type == 11) { + /*reglerx += ((widget->allocation.width - + klass->selector_x) *0.5)+2; + reglery += (widget->allocation.height - + klass->selector_y) *0.5; */ + + cairo_t*cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + + cairo_rectangle (cr, reglerx+widget->allocation.width-19,reglery+2,9,widget->allocation.height-4); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill_preserve (cr); + cairo_move_to(cr,reglerx+widget->allocation.width-18,reglery+10); + cairo_line_to (cr,reglerx+widget->allocation.width-14 , reglery+4); + cairo_line_to (cr,reglerx+widget->allocation.width-10 , reglery+10); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 0.3, 0.3, 0.3); + cairo_stroke (cr); + cairo_destroy(cr); + } + + //---------- rec button + else if (regler->regler_type == 14) { + reglerx += (widget->allocation.width - + klass->rp_x) *0.5; + reglery += (widget->allocation.height - + klass->rp_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->rp_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =1; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->rp_image1,0, reglerstate * + klass->rp_y, reglerx, reglery, + klass->rp_x, + klass->rp_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + + //---------- play button + else if (regler->regler_type == 15) { + reglerx += (widget->allocation.width - + klass->rp_x) *0.5; + reglery += (widget->allocation.height - + klass->rp_y) *0.5; + int reglerstate = (int)((adj->value - adj->lower) * + klass->rp_step / (adj->upper - adj->lower)); + if (reglerstate > 0) reglerstate =1; + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + klass->p_image1,0, reglerstate * + klass->rp_y, reglerx, reglery, + klass->rp_x, + klass->rp_y, GDK_RGB_DITHER_NORMAL, 0, 0); + } + + + return TRUE; +} + +/**************************************************************** + ** set size for GdkDrawable per type + */ + +static void gtk_regler_size_request (GtkWidget *widget, GtkRequisition *requisition) +{ + g_assert(GTK_IS_REGLER(widget)); + GtkRegler *regler = GTK_REGLER(widget); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + +//----------- small knob + if (regler->regler_type == 0) { + requisition->width = klass->regler_x; + requisition->height = klass->regler_y; + } +//----------- Big knob + else if (regler->regler_type == 1) { + requisition->width = klass->bigknob_x; + requisition->height = klass->bigknob_y; + } +//----------- switch + else if (regler->regler_type == 2) { + requisition->width = klass->toggle_x; + requisition->height = klass->toggle_y; + } +//----------- horizontal slider + else if (regler->regler_type == 3) { + requisition->width = klass->slider_x; + requisition->height = klass->slider_y; + } +//----------- mini slider + else if (regler->regler_type == 4) { + requisition->width = klass->minislider_x; + requisition->height = klass->minislider_y; + } +//----------- switch2 + else if (regler->regler_type == 5) { + requisition->width = klass->switch_x; + requisition->height = klass->switch_y; + } +//----------- minitoggle + else if (regler->regler_type == 6) { + requisition->width = klass->minitoggle_x; + requisition->height = klass->minitoggle_y; + } +//----------- horizontal slider + else if (regler->regler_type == 7) { + requisition->width = klass->wheel_x; + requisition->height = klass->wheel_y; + } +//----------- togglebutton + else if (regler->regler_type == 8) { + requisition->width = klass->b_toggle_x; + requisition->height = klass->b_toggle_y; + } +//----------- vertical slider + else if (regler->regler_type == 9) { + requisition->width = klass->slider_y; + requisition->height = klass->vslider_x; + } +//----------- eqslider + else if (regler->regler_type == 10) { + requisition->width = klass->eqslider_x; + requisition->height = klass->eqslider_y; + } +//----------- selector + else if (regler->regler_type == 11) { + requisition->width = klass->selector_x; + requisition->height = klass->selector_y; + } +//----------- led + else if (regler->regler_type == 12) { + requisition->width = klass->led_x; + requisition->height = klass->led_y; + } +//----------- led + else if (regler->regler_type == 13) { + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + char s[64]; + snprintf(s, 63, "%f",adj->upper); + string st = s; + double display_lenght = st.length(); + requisition->width = display_lenght*4+4; + requisition->height = klass->vd_y; + } + +} + +/**************************************************************** + ** set value from key bindings + */ + +static void gtk_regler_set_value (GtkWidget *widget, int dir_down) +{ + g_assert(GTK_IS_REGLER(widget)); + + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + + int oldstep = (int)(0.5f + (adj->value - adj->lower) / adj->step_increment); + int step; + int nsteps = (int)(0.5f + (adj->upper - adj->lower) / adj->step_increment); + if (dir_down) + step = oldstep - 1; + else + step = oldstep + 1; + float value = adj->lower + step * double(adj->upper - adj->lower) / nsteps; + gtk_widget_grab_focus(widget); + gtk_range_set_value(GTK_RANGE(widget), value); +} + +/**************************************************************** + ** keyboard bindings + */ + +static gboolean gtk_regler_key_press (GtkWidget *widget, GdkEventKey *event) +{ + g_assert(GTK_IS_REGLER(widget)); + + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + switch (event->keyval) { + case GDK_Home: + gtk_range_set_value(GTK_RANGE(widget), adj->lower); + return TRUE; + case GDK_End: + gtk_range_set_value(GTK_RANGE(widget), adj->upper); + return TRUE; + case GDK_Up: + gtk_regler_set_value(widget, 0); + return TRUE; + case GDK_Right: + gtk_regler_set_value(widget, 0); + return TRUE; + case GDK_Down: + gtk_regler_set_value(widget, 1); + return TRUE; + case GDK_Left: + gtk_regler_set_value(widget, 1); + return TRUE; + } + + return FALSE; +} + +//------------ calculate value for display +static double gtk_regler_get_value(GtkAdjustment *adj,double pos) +{ + if (adj->step_increment < 0.009999) pos = (floor (pos*1000))*0.001; + else if (adj->step_increment < 0.099999) pos = (floor (pos*100))*0.01; + else if (adj->step_increment < 0.999999) pos = (floor (pos*10))*0.1; + else pos = floor (pos); + return pos; + +} + +/**************************************************************** + ** alternative knob motion mode (ctrl + mouse pressed) + */ + +static void knob_pointer_event(GtkWidget *widget, gdouble x, gdouble y, int knob_x, int knob_y, + bool drag, int state) +{ + static double last_x = 2e20; + GtkRegler *regler = GTK_REGLER(widget); + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + double radius = min(knob_x, knob_y) / 2; + int reglerx = (widget->allocation.width - knob_x) / 2; + int reglery = (widget->allocation.height - knob_y) / 2; + double posx = (reglerx + radius) - x; // x axis right -> left + double posy = (reglery + radius) - y; // y axis top -> bottom + double value; + if (!drag) { + if (state & GDK_CONTROL_MASK) { + last_x = posx; + return; + } else { + last_x = 2e20; + } + } + if (last_x < 1e20) { // in drag started with Control Key + const double scaling = 0.005; + double scal = (state & GDK_CONTROL_MASK ? scaling : scaling*0.1); + value = (last_x - posx) * scal; + last_x = posx; + gtk_range_set_value(GTK_RANGE(widget), adj->value + value * (adj->upper - adj->lower)); + return; + } + + double angle = atan2(-posx, posy) + M_PI; // clockwise, zero at 6 o'clock, 0 .. 2*M_PI + if (drag) { + // block "forbidden zone" and direct moves between quadrant 1 and 4 + int quadrant = 1 + int(angle/M_PI_2); + if (regler->last_quadrant == 1 && (quadrant == 3 || quadrant == 4)) { + angle = scale_zero; + } else if (regler->last_quadrant == 4 && (quadrant == 1 || quadrant == 2)) { + angle = 2*M_PI - scale_zero; + } else { + if (angle < scale_zero) { + angle = scale_zero; + } else if (angle > 2*M_PI - scale_zero) { + angle = 2*M_PI - scale_zero; + } + regler->last_quadrant = quadrant; + } + } else { + if (angle < scale_zero) { + angle = scale_zero; + } else if (angle > 2*M_PI - scale_zero) { + angle = 2*M_PI - scale_zero; + } + regler->last_quadrant = 0; + } + angle = (angle - scale_zero) / (2 * (M_PI-scale_zero)); // normalize to 0..1 + gtk_range_set_value(GTK_RANGE(widget), adj->lower + angle * (adj->upper - adj->lower)); +} + +/**************************************************************** + ** mouse button pressed set value + */ + +static gboolean gtk_regler_button_press (GtkWidget *widget, GdkEventButton *event) +{ + g_assert(GTK_IS_REGLER(widget)); + GtkRegler *regler = GTK_REGLER(widget); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + GtkWidget * dialog,* spinner, *ok_button, *vbox, *toplevel; + + switch (event->button) { + case 1: // left button + + gtk_widget_grab_focus(widget); + gtk_widget_grab_default (widget); + gtk_grab_add(widget); + klass->button_is = 1; + +//----------- knob + if (regler->regler_type == 0) { //| (regler->regler_type < 2)) + knob_pointer_event(widget, event->x, event->y, klass->regler_x, klass->regler_y, + false, event->state); + } +//----------- big knob + else if (regler->regler_type == 1) { + knob_pointer_event(widget, event->x, event->y, klass->bigknob_x, klass->bigknob_y, + false, event->state); + } +//----------- slider + else if (regler->regler_type == 3) { + + int reglerx = (widget->allocation.width - + klass->slider_x) *0.5; + double pos = adj->lower + (((event->x - reglerx-10)*0.01)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } +//----------- minislider + else if (regler->regler_type == 4) { + + int reglerx = (widget->allocation.width - + klass->minislider_x) *0.5; + double pos = adj->lower + (((event->x - reglerx-3)*0.03575)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } +//----------- wheel + else if (regler->regler_type == 7) { + + int wheelx = (widget->allocation.width - + klass->wheel_x) *0.5; + double pos = adj->lower + (((event->x - wheelx)*0.03)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } +//----------- vertical slider + else if (regler->regler_type == 9) { + + int reglery = (widget->allocation.height - + klass->vslider_x) *0.5; + double pos = adj->upper - (((event->y - reglery-10)*0.02)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } +//----------- eqslider + else if (regler->regler_type == 10) { + + int reglery = (widget->allocation.height - + klass->eqslider_x) *0.5; + double pos = adj->upper - (((event->y - reglery+18)*0.02)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } +//---------- selector + else if (regler->regler_type == 11) { + gint start_value = gtk_range_get_value(GTK_RANGE(widget)); + if (start_value < regler->max_value) { + gtk_range_set_value(GTK_RANGE(widget), start_value+1); + } else { + gtk_range_set_value(GTK_RANGE(widget), 0); + } + } +//----------- switches and toggle + else { // if ((regler->regler_type == 2) || (regler->regler_type == 5) || (regler->regler_type == 6)|| (regler->regler_type == 8)) + if (gtk_range_get_value(GTK_RANGE(widget)) == 0) { + gtk_range_set_value(GTK_RANGE(widget), 1); + } else { + gtk_range_set_value(GTK_RANGE(widget), 0); + } + } + + break; + + case 2: //wheel + klass->button_is = 2; + break; + + case 3: // right button show num entry + klass->button_is = 3; + dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL); + spinner = gtk_spin_button_new (GTK_ADJUSTMENT(adj), adj->step_increment, + precision(adj->step_increment)); + gtk_entry_set_activates_default(GTK_ENTRY(spinner), TRUE); + ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); + GTK_WIDGET_SET_FLAGS (GTK_WIDGET(ok_button), GTK_CAN_DEFAULT); + vbox = gtk_vbox_new (false, 4); + gtk_container_add (GTK_CONTAINER(vbox), spinner); + gtk_container_add (GTK_CONTAINER(vbox), ok_button); + gtk_container_add (GTK_CONTAINER(dialog), vbox); + gtk_window_set_decorated(GTK_WINDOW(dialog), false); + gtk_window_set_title (GTK_WINDOW (dialog), "set"); + gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); + gtk_window_set_gravity(GTK_WINDOW(dialog), GDK_GRAVITY_SOUTH); + gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); + gtk_window_set_keep_below (GTK_WINDOW(dialog), FALSE); + gtk_widget_grab_default(ok_button); + toplevel = gtk_widget_get_toplevel (widget); + if (GTK_WIDGET_TOPLEVEL (toplevel)) + { + gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(toplevel)); + } + + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + g_signal_connect_swapped (ok_button, "clicked", + G_CALLBACK (gtk_widget_destroy), dialog); + + gtk_widget_show_all(dialog); + break; + + default: // do nothing + break; + } + return TRUE; +} + +/**************************************************************** + ** mouse button release + */ + +static gboolean gtk_regler_button_release (GtkWidget *widget, GdkEventButton *event) +{ + g_assert(GTK_IS_REGLER(widget)); + GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->button_is = 0; + if (GTK_WIDGET_HAS_GRAB(widget)) + gtk_grab_remove(widget); + return FALSE; +} + +/**************************************************************** + ** set the value from mouse movement + */ + +static gboolean gtk_regler_pointer_motion (GtkWidget *widget, GdkEventMotion *event) +{ + g_assert(GTK_IS_REGLER(widget)); + GtkRegler *regler = GTK_REGLER(widget); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(widget)); + gdk_event_request_motions (event); + if (GTK_WIDGET_HAS_GRAB(widget)) { + if (regler->regler_type == 0) { + knob_pointer_event(widget, event->x, event->y, klass->regler_x, klass->regler_y, + true, event->state); + } else if (regler->regler_type == 1) { + knob_pointer_event(widget, event->x, event->y, klass->bigknob_x, klass->bigknob_y, + true, event->state); + } +//----------- slider + else if (regler->regler_type == 3) { + if (event->x > 0) { + int sliderx = (widget->allocation.width - + klass->slider_x)*0.5; + double pos = adj->lower + (((event->x - sliderx-10)*0.01)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } + } +//----------- minislider + else if (regler->regler_type == 4) { + if (event->x > 0) { + int sliderx = (widget->allocation.width - + klass->minislider_x)*0.5; + double pos = adj->lower + (((event->x - sliderx-3)*0.03575)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } + } +//----------- wheel + else if (regler->regler_type == 7) { + if (event->x > 0) { + int wheelx = (widget->allocation.width - + klass->wheel_x)*0.5; + double pos = adj->lower + (((event->x - wheelx)*0.03)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } + } +//----------- vertical slider + else if (regler->regler_type == 9) { + if (event->y > 0) { + int slidery = (widget->allocation.height - + klass->vslider_x)*0.5; + double pos = adj->upper - (((event->y - slidery-10)*0.02)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } + } +//----------- eqslider + else if (regler->regler_type == 10) { + if (event->y > 0) { + int slidery = (widget->allocation.height - + klass->eqslider_x)*0.5; + double pos = adj->upper - (((event->y - slidery+18)*0.02)* (adj->upper - adj->lower)); + gtk_range_set_value(GTK_RANGE(widget), gtk_regler_get_value(adj,pos)); + } + } + } + return FALSE; +} + +/**************************************************************** + ** set value from mouseweel + */ + +static gboolean gtk_regler_scroll (GtkWidget *widget, GdkEventScroll *event) +{ + usleep(5000); + gtk_regler_set_value(widget, event->direction); + return FALSE; +} + +/**************************************************************** + ** init the used background images to the used skins + */ + +void GtkRegler::gtk_regler_init_pixmaps(int change_knob) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + g_assert(GTK_IS_REGLER(widget)); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + +//---------- here are the inline pixmaps for regler +#include "GtkReglerpix.cpp" + klass->pix_switch = change_knob; + if (klass->pix_switch == 0) { +//----------- Big knob + klass->bigregler_image = gdk_pixbuf_new_from_xpm_data (knob1_xpm); + g_assert(klass->bigregler_image != NULL); +//----------- small knob + klass->regler_image = gdk_pixbuf_scale_simple(klass->bigregler_image,25,25,GDK_INTERP_HYPER); + g_assert(klass->regler_image != NULL); + klass->pix_switch = 1; +//----------- eq slider + klass->eqslider_image = gdk_pixbuf_new_from_xpm_data(eqslider1_xpm); + g_assert(klass->eqslider_image != NULL); + klass->eqslider_image1 = gdk_pixbuf_copy( klass->eqslider_image ); + g_assert(klass->eqslider_image1 != NULL); + } else if (klass->pix_switch == 1) { +//----------- Big knob + klass->bigregler_image = gdk_pixbuf_new_from_xpm_data (knob2_xpm); + g_assert(klass->bigregler_image != NULL); +//----------- small knob + klass->regler_image = gdk_pixbuf_scale_simple(klass->bigregler_image,25,25,GDK_INTERP_HYPER); + g_assert(klass->regler_image != NULL); + klass->pix_switch = 0; +//----------- eq slider + klass->eqslider_image = gdk_pixbuf_new_from_xpm_data(eqslider_xpm); + g_assert(klass->eqslider_image != NULL); + klass->eqslider_image1 = gdk_pixbuf_copy( klass->eqslider_image ); + g_assert(klass->eqslider_image1 != NULL); + } else if (klass->pix_switch == 2) { +//----------- Big knob + klass->bigregler_image = gdk_pixbuf_new_from_xpm_data (knob3_xpm); + g_assert(klass->bigregler_image != NULL); +//----------- small knob + klass->regler_image = gdk_pixbuf_scale_simple(klass->bigregler_image,25,25,GDK_INTERP_HYPER); + g_assert(klass->regler_image != NULL); + klass->pix_switch = 0; +//----------- eq slider + klass->eqslider_image = gdk_pixbuf_new_from_xpm_data(eqslider_xpm); + g_assert(klass->eqslider_image != NULL); + klass->eqslider_image1 = gdk_pixbuf_copy( klass->eqslider_image ); + g_assert(klass->eqslider_image1 != NULL); + } else if (klass->pix_switch == 3) { +//----------- Big knob + klass->bigregler_image = gdk_pixbuf_new_from_xpm_data (knob4_xpm); + g_assert(klass->bigregler_image != NULL); +//----------- small knob + klass->regler_image = gdk_pixbuf_scale_simple(klass->bigregler_image,25,25,GDK_INTERP_HYPER); + g_assert(klass->regler_image != NULL); + klass->pix_switch = 0; +//----------- eq slider + klass->eqslider_image = gdk_pixbuf_new_from_xpm_data(eqslider_xpm); + g_assert(klass->eqslider_image != NULL); + klass->eqslider_image1 = gdk_pixbuf_copy( klass->eqslider_image ); + g_assert(klass->eqslider_image1 != NULL); + } else if (klass->pix_switch == 4) { +//----------- Big knob + klass->bigregler_image = gdk_pixbuf_new_from_xpm_data (knob5_xpm); + g_assert(klass->bigregler_image != NULL); +//----------- small knob + klass->regler_image = gdk_pixbuf_scale_simple(klass->bigregler_image,25,25,GDK_INTERP_HYPER); + g_assert(klass->regler_image != NULL); + klass->pix_switch = 0; +//----------- eq slider + klass->eqslider_image = gdk_pixbuf_new_from_xpm_data(eqslider_xpm); + g_assert(klass->eqslider_image != NULL); + klass->eqslider_image1 = gdk_pixbuf_copy( klass->eqslider_image ); + g_assert(klass->eqslider_image1 != NULL); + } else if (klass->pix_switch == 5) { +//----------- Big knob + klass->bigregler_image = gdk_pixbuf_new_from_xpm_data (knob6_xpm); + g_assert(klass->bigregler_image != NULL); +//----------- small knob + klass->regler_image = gdk_pixbuf_scale_simple(klass->bigregler_image,25,25,GDK_INTERP_HYPER); + g_assert(klass->regler_image != NULL); + klass->pix_switch = 0; +//----------- eq slider + klass->eqslider_image = gdk_pixbuf_new_from_xpm_data(eqslider1_xpm); + g_assert(klass->eqslider_image != NULL); + klass->eqslider_image1 = gdk_pixbuf_copy( klass->eqslider_image ); + g_assert(klass->eqslider_image1 != NULL); + } + +//----------- general pixmap init + if (klass->pix_is != 1) { +//----------- switch + klass->toggle_image = gdk_pixbuf_new_from_xpm_data (switchit_xpm); + g_assert(klass->toggle_image != NULL); + klass->toggle_image1 = gdk_pixbuf_copy( klass->toggle_image ); + g_assert(klass->toggle_image1 != NULL); + gdk_pixbuf_saturate_and_pixelate(klass->toggle_image1,klass->toggle_image1,10.0,FALSE); +//----------- switchII + klass->switch_image = gdk_pixbuf_new_from_xpm_data (switch_xpm); + g_assert(klass->switch_image != NULL); + klass->switch_image1 = gdk_pixbuf_copy( klass->switch_image ); + g_assert(klass->switch_image1 != NULL); + gdk_pixbuf_saturate_and_pixelate(klass->switch_image1,klass->switch_image1,10.0,FALSE); +//----------- led + klass->led_image = gdk_pixbuf_new_from_xpm_data (led_xpm); + g_assert(klass->led_image != NULL); +//----------- horizontal slider + klass->slider_image = gdk_pixbuf_new_from_xpm_data(slidersm_xpm); + g_assert(klass->slider_image != NULL); + klass->slider_image1 = gdk_pixbuf_copy( klass->slider_image ); + g_assert(klass->slider_image1 != NULL); +//----------- vertical slider + klass->vslider_image = gdk_pixbuf_rotate_simple(klass->slider_image, + GDK_PIXBUF_ROTATE_CLOCKWISE); + g_assert(klass->vslider_image != NULL); + klass->vslider_image = gdk_pixbuf_flip(klass->vslider_image, TRUE); + klass->vslider_image1 = gdk_pixbuf_copy( klass->vslider_image ); + g_assert(klass->vslider_image1 != NULL); +//----------- mini slider + klass->minislider_image = gdk_pixbuf_scale_simple(klass->slider_image,40,6,GDK_INTERP_HYPER); + g_assert(klass->minislider_image != NULL); + klass->minislider_image1 = gdk_pixbuf_copy( klass->minislider_image ); + g_assert(klass->minislider_image1 != NULL); + +//----------- horizontal wheel + klass->wheel_image = gdk_pixbuf_new_from_xpm_data(wheel_xpm); + g_assert(klass->wheel_image != NULL); + klass->wheel_image1 = gdk_pixbuf_new_from_xpm_data(wheel_s_xpm); + g_assert(klass->wheel_image1 != NULL); + klass->pointer_image1 = gdk_pixbuf_new_from_xpm_data(pointer_xpm); + g_assert(klass->pointer_image1 != NULL); +//----------- toggle_button + klass->b_toggle_image = gdk_pixbuf_new_from_xpm_data (button_xpm); + g_assert(klass->b_toggle_image != NULL); + klass->b_toggle_image1 = gdk_pixbuf_new_from_xpm_data (button1_xpm); + g_assert(klass->b_toggle_image1 != NULL); +//----------- rec_button + klass->rp_image = gdk_pixbuf_new_from_xpm_data (rbutton_xpm); + g_assert(klass->rp_image != NULL); + klass->rp_image1 = gdk_pixbuf_copy( klass->rp_image ); + g_assert(klass->rp_image1 != NULL); + gdk_pixbuf_saturate_and_pixelate(klass->rp_image1,klass->rp_image1,10.0,FALSE); + +//----------- play_button + klass->p_image = gdk_pixbuf_new_from_xpm_data (pbutton_xpm); + g_assert(klass->p_image != NULL); + klass->p_image1 = gdk_pixbuf_copy( klass->p_image ); + g_assert(klass->p_image1 != NULL); + gdk_pixbuf_saturate_and_pixelate(klass->p_image1,klass->p_image1,10.0,FALSE); + + klass->pix_is = 1; + } +} + +/**************************************************************** + ** init the GtkReglerClass + */ + +static void gtk_regler_class_init (GtkReglerClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + + /** set here the sizes and steps for the used regler **/ +//--------- small knob size and steps + klass->regler_x = 25; + klass->regler_y = 25; + klass->regler_step = 86; + +//--------- big knob size and steps + klass->bigknob_x = 51; + klass->bigknob_y = 51; + klass->bigknob_step = 86; + +//--------- switch size and steps + klass->toggle_x = 37 ; + klass->toggle_y = 28 ; + klass->toggle_step = 1; + +//--------- switchII size and steps + klass->switch_x = 20 ; + klass->switch_y = 10 ; + klass->switch_step = 1; + +//--------- switch minitoggle and steps + klass->minitoggle_x = 10 ; + klass->minitoggle_y = 10 ; + klass->minitoggle_step = 1; + +//--------- horizontal slider size and steps + klass->slider_x = 120 ; //this is the scale size + klass->vslider_x = 70 ; //this is the scale size + klass->slider_y = 10 ; // this is the knob size x and y be the same + klass->slider_step = 100; + klass->vslider_step = 50; + +//--------- mini slider size and steps + klass->minislider_x = 34 ; //this is the scale size + klass->minislider_y = 6 ; // this is the knob size x and y be the same + klass->minislider_step = 28; + +//--------- eqslider size and steps + klass->eqslider_x = 13 ; //this is the scale size + klass->eqslider_y = 55 ; // this is the knob size x and y be the same + klass->eqslider_step = 50; + +//--------- horizontal wheel size and steps + klass->wheel_x = 40 ; //this is the scale size + klass->wheel_y = 8 ; // this is the knob size x and y be the same + klass->wheel_step = 100; + +//--------- switch size and steps + klass->b_toggle_x = 25 ; + klass->b_toggle_y = 15 ; + klass->b_toggle_step = 1; + +//--------- selector size and steps + klass->selector_x = 65 ; + klass->selector_y = 15 ; + klass->selector_step = 6; + +//--------- led + klass->led_x = 20 ; + klass->led_y = 20 ; +//--------- led + klass->vd_x = -1 ; + klass->vd_y = 21 ; +//--------- led + klass->rp_x = 22 ; + klass->rp_y = 23 ; + klass->rp_step = 1; + +//--------- event button + klass->button_is = 0; + +//--------- init pixmaps + klass->pix_is = 0; + +//--------- connect the events with funktions + widget_class->enter_notify_event = gtk_regler_enter_in; + widget_class->leave_notify_event = gtk_regler_leave_out; + widget_class->expose_event = gtk_regler_expose; + widget_class->size_request = gtk_regler_size_request; + widget_class->button_press_event = gtk_regler_button_press; + widget_class->button_release_event = gtk_regler_button_release; + widget_class->motion_notify_event = gtk_regler_pointer_motion; + widget_class->key_press_event = gtk_regler_key_press; + widget_class->scroll_event = gtk_regler_scroll; + + GtkRegler::gtk_regler_init_pixmaps(0); +} + +/**************************************************************** + ** init the Regler type/size + */ + +static void gtk_regler_init (GtkRegler *regler) +{ + GtkWidget *widget = GTK_WIDGET(regler); + GtkReglerClass *klass = GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget)); + + GTK_WIDGET_SET_FLAGS (GTK_WIDGET(regler), GTK_CAN_FOCUS); + GTK_WIDGET_SET_FLAGS (GTK_WIDGET(regler), GTK_CAN_DEFAULT); + + if (regler->regler_type == 0) { + widget->requisition.width = klass->regler_x; + widget->requisition.height = klass->regler_y; + } else if (regler->regler_type == 1) { + widget->requisition.width = klass->bigknob_x; + widget->requisition.height = klass->bigknob_y; + } else if (regler->regler_type == 2) { + widget->requisition.width = klass->toggle_x; + widget->requisition.height = klass->toggle_y; + } else if (regler->regler_type == 3) { + widget->requisition.width = klass->slider_x; + widget->requisition.height = klass->slider_y; + } else if (regler->regler_type == 4) { + widget->requisition.width = klass->minislider_x; + widget->requisition.height = klass->minislider_y; + } else if (regler->regler_type == 5) { + widget->requisition.width = klass->switch_x; + widget->requisition.height = klass->switch_y; + } else if (regler->regler_type == 6) { + widget->requisition.width = klass->minitoggle_x; + widget->requisition.height = klass->minitoggle_y; + } else if (regler->regler_type == 7) { + widget->requisition.width = klass->wheel_x; + widget->requisition.height = klass->wheel_y; + } else if (regler->regler_type == 8) { + widget->requisition.width = klass->b_toggle_x; + widget->requisition.height = klass->b_toggle_y; + } else if (regler->regler_type == 9) { + widget->requisition.width = klass->slider_y; + widget->requisition.height = klass->vslider_x; + } else if (regler->regler_type == 10) { + widget->requisition.width = klass->eqslider_x; + widget->requisition.height = klass->eqslider_y; + } else if (regler->regler_type == 11) { + widget->requisition.width = klass->selector_x; + widget->requisition.height = klass->selector_y; + } else if (regler->regler_type == 12) { + widget->requisition.width = klass->led_x; + widget->requisition.height = klass->led_y; + } else if (regler->regler_type == 13) { + widget->requisition.width = klass->vd_x; + widget->requisition.height = klass->vd_y; + } +} + +/**************************************************************** + ** redraw when value changed + */ + +static gboolean gtk_regler_value_changed(gpointer obj) +{ + GtkWidget *widget = (GtkWidget *)obj; + gtk_widget_queue_draw(widget); + return FALSE; +} + +/**************************************************************** + ** destructer + */ +//-------- the destructer doesen't work in virtual mode, so we need this destroy funktion +//-------- to clean up when exit. This must call in the destroy funktion of the main app. +void GtkRegler::gtk_regler_destroy () +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + g_assert(GTK_IS_REGLER(widget)); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> regler_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> regler_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> bigregler_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> bigregler_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> toggle_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->toggle_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> toggle_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->toggle_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> slider_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->slider_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> slider_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->slider_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> minislider_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->minislider_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> minislider_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->minislider_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> switch_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->switch_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> switch_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->switch_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> wheel_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->wheel_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> wheel_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->wheel_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> b_toggle_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->b_toggle_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> vslider_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->vslider_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> vslider_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->vslider_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> eqslider_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->eqslider_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> eqslider_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->eqslider_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> led_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->led_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> rp_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->rp_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> rp_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->rp_image1); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> p_image)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->p_image); + if (G_IS_OBJECT(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))-> p_image1)) + g_object_unref(GTK_REGLER_CLASS(GTK_OBJECT_GET_CLASS(widget))->p_image1); +} + + +/**************************************************************** + ** create small knob + */ + +GtkWidget *GtkRegler::gtk_regler_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 0; + regler->last_quadrant = 0; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create Big knob + */ + +GtkWidget *GtkRegler::gtk_big_regler_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 1; + regler->last_quadrant = 0; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a switcher + */ + +GtkWidget *GtkRegler::gtk_toggle_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 2; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a horizontal slider + */ + +GtkWidget *GtkRegler::gtk_hslider_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 3; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a horizontal mini slider + */ + +GtkWidget *GtkRegler::gtk_mini_slider_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 4; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a switcher + */ + +GtkWidget *GtkRegler::gtk_switch_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 5; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a minitoggle + */ + +GtkWidget *GtkRegler::gtk_mini_toggle_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 6; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a horizontal wheel + */ + +GtkWidget *GtkRegler::gtk_wheel_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 7; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a toggle button + */ + +GtkWidget *GtkRegler::gtk_button_toggle_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 8; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a vertical slider + */ + +GtkWidget *GtkRegler::gtk_vslider_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 9; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a eqslider + */ + +GtkWidget *GtkRegler::gtk_eq_slider_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 10; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a selector + */ + +GtkWidget *GtkRegler::gtk_selector_new_with_adjustment(GtkAdjustment *_adjustment, int maxv, const char* label[]) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 11; + regler->max_value = maxv-1; + for (int i=0; i < maxv; i++) + regler->labels[i]=label[i]; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a led + */ + +GtkWidget *GtkRegler::gtk_led_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 12; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a value display + */ +GtkWidget *GtkRegler::gtk_value_display(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 13; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a toggle button + */ + +GtkWidget *GtkRegler::gtk_button_rec_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 14; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** create a toggle button + */ + +GtkWidget *GtkRegler::gtk_button_play_new_with_adjustment(GtkAdjustment *_adjustment) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_REGLER, NULL )); + GtkRegler *regler = GTK_REGLER(widget); + regler->regler_type = 15; + if (widget) { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_regler_value_changed), widget); + } + return widget; +} + +/**************************************************************** + ** get the Regler type + */ + +GType gtk_regler_get_type (void) +{ + static GType kn_type = 0; + if (!kn_type) { + static const GTypeInfo kn_info = { + sizeof(GtkReglerClass), NULL, NULL, (GClassInitFunc)gtk_regler_class_init, NULL, NULL, sizeof (GtkRegler), 0, (GInstanceInitFunc)gtk_regler_init + }; + kn_type = g_type_register_static(GTK_TYPE_RANGE, "GtkRegler", &kn_info, (GTypeFlags)0); + } + return kn_type; +} + diff --git a/src/GtkReglerpix.cpp b/src/GtkReglerpix.cpp new file mode 100644 index 0000000..bd19051 --- /dev/null +++ b/src/GtkReglerpix.cpp @@ -0,0 +1,1460 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/****************************************************************************** +xpm pixmaps for the GtkReglerClass used as inline data +******************************************************************************/ + +/* XPM */ +static const char * knob1_xpm[] = { + "51 51 31 1", + " c None", + ". c #030602", + "+ c #11120F", + "@ c #181917", + "# c #1E1F1D", + "$ c #232422", + "% c #272826", + "& c #2B2D2B", + "* c #313230", + "= c #353735", + "- c #3A3B39", + "; c #40413F", + "> c #434346", + ", c #444643", + "' c #484947", + ") c #4C4D4B", + "! c #515250", + "~ c #595A58", + "{ c #60615F", + "] c #676967", + "^ c #6F716F", + "/ c #777876", + "( c #7F817E", + "_ c #888A87", + ": c #929492", + "< c #A2A4A2", + "[ c #B5B7B4", + "} c #C7C9C6", + "| c #D6D8D7", + "1 c #E5E6E4", + "2 c #F8F9F7", + " ", + " ", + " ", + " ", + " ", + " !!~/__:_^ ", + " !_}|||}}}[[[<:( ", + " !<|111||}[[<<:::__( ", + " ~<|111|[[<:((//(_:_(//] ", + " (2|111}[_(////////^^//^]~ ", + " _2|11||<__((////^^^^^^^/^!) ", + " _2}|12}<<:_(///^^^^^^^]^]]{,, ", + " /2}|12}[[<:_(//^^^]]]]]]]]]]~-- ", + " !|}||2}[[<<:_(/^^]]]]]]]]]]]]]~** ", + " %<[}}1[[[[<::_(/^]]]]]]]{{{{{{{{)%# ", + " ;[}[[<<<<<<::_(/^]]{{{{{{{{{{{{{{*# ", + " #([[<:::<<:::_(/^]]{{{{{{{{{{{{~~{!%@ ", + " &:[<:((______((/]]{{{{{~~~~~~~~~~~~*@ ", + " .,<<_^^////((((/^]{{{~~~~~~~~~~~~~~~,$+ ", + " +]<:/]]]]]^^//^^]]{~~~~~~~~!!!!!!!!!!&+ ", + " $(<({{{{{]]]]]]]{{~~~~!!!!!!!!!!!!!!!&+ ", + " .%(:/~~~~~{{{{{{~~~~!!!!!!!!!!!))))))!-#. ", + " .%((]!!!!!~~~~~~~~!!!!!)))))))))))))'';$. ", + " .$/^~!!!!!!!!!!!!!!)))))')'''''''''''''%. ", + " .$^]!))))))))))))))''''''''''',,,,>,>>'%. ", + " .$^{!))))))))))))))''''''''>'',,,>,>,>'%. ", + " .$]{)''''''''''','',,,,,,,,,,,,,,;,;>>'%. ", + " .#{~'',>,,,,,,,,,,,,,;;;,;;;;>;;;;;;;;;$. ", + " .#{~,,,,,;;;;;;;;;;;>;;;;;;;;;;;;;;;;;;#. ", + " .@!!>;>;;;;;;;;;;;;;;>;---------------=#. ", + " +;'>;;;;--->----------------------==-%+ ", + " .$,;------------====================-#. ", + " .+,;-===================****=**=*****@. ", + " +=-==*=****************************%+ ", + " .@==****&&&&&*************&**&&*&&*@. ", + " +*=**&&&&&&&&&&&&&&&&&&&&&&&&&&&&%+ ", + " .+&&&&%%%%%&&&&&&&%&&&&&&&&&&&%%&@. ", + " .$&&$$$$$%%%%&&%%%%%%%%%%%%%%%&$+ ", + " +$$###$$$$$%%&%%%%%%%%%%$$$$%%+ ", + " +%######$$$%%$$$$$$$$$$$$$%%+ ", + " @########$$$$###########$$+ ", + " +@@@####################+ ", + " ..@####@#@##@@@@@@###@. ", + " .+@@@###@@@@###@@@+ ", + " ..+$#@++++@#$+. ", + " ......... ", + " ", + " ", + " ", + " ", + " "}; + +/* XPM */ +static const char * knob2_xpm[] = { + "51 51 31 1", + " c None", + ". c #100101", + "+ c #0A0402", + "@ c #1B0101", + "# c #270001", + "$ c #360100", + "% c #440001", + "& c #540000", + "* c #6A0000", + "= c #1A1C19", + "- c #890000", + "; c #AD0000", + "> c #292524", + ", c #C40000", + "' c #522322", + ") c #E00800", + "! c #3B3433", + "~ c #743B3C", + "{ c #5F4142", + "] c #4E4948", + "^ c #B2321F", + "/ c #EE360C", + "( c #655F5E", + "_ c #855D5B", + ": c #766F6E", + "< c #807B7A", + "[ c #938D8C", + "} c #A29D9C", + "| c #B7B2B1", + "1 c #C4C0BE", + "2 c #FCDD7C", + " ", + " ", + " ", + " ", + " }||1111||}] ", + " [|111||}}||1111[: ", + " }11|<::::::::::<}11|! ", + " }11<::::::(]](::::::<|1| ", + " ]|1[:::(>++++++++++>(:::<|1( ", + " (|}::<]++++++++++++++++]:::}1: ", + " (|[::(+++++=>]]::]>>.+++++(::[|< ", + " (|<::]++++:|||||||||||[.++++]::<|( ", + " ]}[::!++++}||||||||||||||:++++=::<}] ", + " [[::>+++..]|1}(({'{(:}1||>..+++=::[}! ", + " <[::]+++...@:#@##$$$$###:}@@...++!::[[ ", + " [<:(++<[..@@##$'______~$$#@@@@}}++]::[! ", + " <<::++![:.@@#$$%__~~~__~%%$$#@@>[:++::<< ", + " ]<::]++(].@@#$$&&&**---**&&%$$#@@@]]+!::<] ", + " ]:::++>].@#('%&&**-----;-**&%~{'@@.!++:::: ", + " :::]++>.@@{{~&&*---^^^^----*&%'$@@..++!::: ", + " !:::=++..@#''&&*--;;;,,;;;---*&%$#@@..++<::] ", + " ](::+++.@@#$%&*--;;,)//)),;;--*&%$@@..++::(] ", + " ](::++..@@#$&&*^^;))////)),;--*&%$#@@.++]:(] ", + " ](:]++..@@$%&*--;,)))///))),;--*&$#@@.++>:(] ", + " ](:!++..@#$%&*-;;)))/////)));--*&%$@@..+=::] ", + " ](:>++..@#$%&*-;,))//22///));;-*&%$@@..++::]= ", + " !(:=++.@@#$%&*-;,))//22///));;-*&%$#@..++::]= ", + " !(:!++..@#$%&*-;,))///////));;-*&%$@@..++::! ", + " >]:]++..@#$%&*-;;)))/////)));--*&%$@@..+>:(! ", + " >]:(++..@@$%&*--;,)))///))),;--*&$#@@.++!:]> ", + " =!::++..@@#$&**-;;)))))))),;--*&%$#@@.++]:!= ", + " +>::+++.@@#$%&*--;;,))))),;;--*&%$#@..++<:>+ ", + " =(:!++..@@$$&&*--;;;,,,;;;--*&%$#@@..+>::=+ ", + " =!:(++..@@#$%&&*---;;;;----*&&$$@@..++]:]= ", + " +>::>++..@@#$%&&**-------**&&$$#@@..++::>+ ", + " =]:(+++..@@#$%&&&*******&&%$$#@@..++(:(= ", + " +=::!++..@@@#$$%&&&&&&&&%%$$#@@..+++::>= ", + " =]::+++..@@@#$$$%%%%%%$$$##@@...++::]= ", + " +=(::+++...@@@##$$$$$$$##@@@...++(:(=+ ", + " ==(:(+++...@@@@@#####@@@@...+++]::>= ", + " =>:::++++...@@@@@@@@@@@...+++(::>= ", + " ==:::=+++..............++++:::>= ", + " ==(::(+++++........+++++]::(>= ", + " ==]:::]=++++++++++++=]:::]== ", + " +==(::::]=++++++=]::::(>== ", + " ==>(::::::::::::::(>== ", + " ===>](::::::(]>>==+ ", + " ++====>>====++ ", + " ++++ ", + " ", + " "}; + +/* XPM */ +static const char * knob3_xpm[] = { + "51 51 31 1", + " c None", + ". c #03020B", + "+ c #070215", + "@ c #05021D", + "# c #040602", + "$ c #070135", + "% c #080229", + "& c #090147", + "* c #0C015C", + "= c #100070", + "- c #160189", + "; c #1700A6", + "> c #1500C2", + ", c #191918", + "' c #3604E5", + ") c #262627", + "! c #292254", + "~ c #6120E6", + "{ c #423B6A", + "] c #42414F", + "^ c #434344", + "/ c #6F2BDB", + "( c #7538CD", + "_ c #5C5B60", + ": c #635C87", + "< c #6E706D", + "[ c #727077", + "} c #838387", + "| c #9B9B9D", + "1 c #B7B7B9", + "2 c #D0D1CF", + " ", + " ", + " ", + " ", + " |11111111|^ ", + " }122111||111221}< ", + " |211}[[[[[[[[[[[|121^ ", + " |11}[[[[[[_^^_[[[[[[[111 ", + " ^11}[[[_)..##..##..)_[[[}11_ ", + " <1|[[[_.#............#.^[[[|1< ", + " <1|[[_,#...,)]_[[]))....#._[[}1} ", + " _1}[[_#...[11111111111|+....^[[[|_ ", + " ^|}[[)#...|11111111111111[....,[[}|_ ", + " |}[[)#....]11|[]]{]_[|111@+....,[[}|^ ", + " }|[[^#....+@[%+%%$$$$%@%[|@++...#)[[}} ", + " }[[_#.[|.++@@%$!::::::{$$%@@++||.._[[|^ ", + " <}[[..)|[++@%$$&::{!{::{&&$%%@+)}[..[[}} ", + " ^}[[^#.[_++@%$&&***==--=**&&$$@+++_].][[}^ ", + " _<[[..)]++%:!&&**=----;;==**&{{{@++].#[[[< ", + " <[[^#.)++@]{{&*==-;((((;--=**&!$@+++..][[< ", + " )<[[,..+++@!!&*=--;;>>>>;;;-=**&$%@++..,[[<^ ", + " ^<[[....++%$&**=-;>>'~~~'>;;-=*&&$@++..#[[<^ ", + " ^_[[#..++@%$&*=-;>>'~''~''>;;-=*&$%++...^[_^ ", + " ^_[^#..++@$&**-;;>'''''''''>;-=*&$%@++..)[_^ ", + " ^_[^...++@$&*=-;>''''~~''''>;;-*&&%@++..,[[^ ", + " ^_[)...++%$&*=-;>'''~//~''''>;-=*&$@++..,[[^, ", + " ^_[,...++%$&*=-;>'''/((/''''>;-=*&$@++...[[^, ", + " )_[)...++%$&*=-;>'''~((/~'''>;-=*&$@++..,[[^ ", + " )_[^...++@$&*=-;>'''~~/~'''';;-*&&%@++..)[_) ", + " )^[_#..++@$&**-;;>'''''''''>;-=*&$%@++..)[_) ", + " ,^[[...++@%$&*=-;>>'''''''>;;-=*&$%++..#_[^, ", + " ,)[[....++%$&**--;>>'''''>;;-=*&&$@++...[[), ", + " ,_[)...++@%$&*=--;;>>>>>;;-=**&$%@++..)[[,# ", + " ,^[_#..+++%$&&*=--;;;;;;--=**&$%@++...^[_, ", + " #)[[)...++@%$&&**=------==**&&$%@++...[[), ", + " ,^[_#...++@%$&&***=====**&&$$%@++..._[_, ", + " #,[[)...+++@%$$&&&*****&&&$$%@++....[[), ", + " ,^[[....+++@%%$$&&&&&&&$$%@+++....[[^, ", + " #,_[[....++++@%%%$$$$$%%@@+++...._[_,, ", + " ,,_[_.....++++@@@@@@@@@++++....^[[), ", + " ,)[[[......+++++++++++++....._[[), ", + " ,,[[[,......+++++++++......[[[), ", + " ,,_[[_.................._[[_), ", + " ,,^[[[^,#...........,^[[[_,, ", + " ,,,_[[[[^,,....,,^[[[[_),, ", + " ,,)_[[[[[[[[[[[[[[_),, ", + " ,,,)^_[[[[[[_^)),,# ", + " #,,,,,)),,,,,# ", + " #,,# ", + " ", + " "}; + +/* XPM */ +static const char * knob5_xpm[] = { + "51 51 31 1", + " c None", + ". c #080000", + "+ c #0A0301", + "@ c #120203", + "# c #150400", + "$ c #1B0400", + "% c #200604", + "& c #250600", + "* c #290602", + "= c #2D0706", + "- c #2A0905", + "; c #350806", + "> c #310A02", + ", c #390A02", + "' c #3F0A08", + ") c #3B0D05", + "! c #3C0E08", + "~ c #420D04", + "{ c #490D0A", + "] c #451009", + "^ c #4C0F06", + "/ c #50130B", + "( c #571208", + "_ c #541608", + ": c #5A150B", + "< c #5C170D", + "[ c #5F1909", + "} c #65170C", + "| c #681A0F", + "1 c #6F1A13", + "2 c #6A1C11", + " ", + " ", + " ", + " ", + " ", + " ]^/[}}|}< ", + " ]}22222222||||} ", + " ^|2212222|||||||}}[ ", + " /|211222|||}}[[}}}}}[[: ", + " }121122|}}[[[[[[[[<<[[<:/ ", + " }121122|}}}[[[[[<<<<<<<[<^] ", + " }122112||}}}[[[<[<<<<<:<::_!) ", + " [122212||||}}[[<<<::::::::::/>> ", + " ^2222122|||}}}[<<:::::::((((((^&& ", + " $||2212|||||}}}[<:::(((((__:___(]#@ ", + " ,|2||||2||||}}}[<:((____________(*+ ", + " @}||||||||||}}}[<:(_____(_((//////]$+ ", + " $||||}}}}}}}}}}[::(__((////////////&+ ", + " .!|2}<<[[[[}}}[[<:(_(/////////^^^^^^)#. ", + " +(||[((:::<<[[<<:(_////^^^^^^^^^^^^^^%. ", + " @}|}_____(:::::(_(//^^^^^^^^^^^^^{{^^%+ ", + " .#}}[//////__(/////^^^^^{{{]]]]]]]]]{]=+. ", + " .#}}(^^^^^^^^///^^^^^{]]]{]]]]]]]~]~~~,@. ", + " .@[>>>>>>>@. ", + " .+^],,,,,,,,,;;;;>;>>>>>>>>;>>>>>>>>>>-+. ", + " .,~,;>>>>>>;>>>>>>>>>>>>>>==========>$. ", + " .#,,>>>>>>===============--------***>+. ", + " .+),=====----*******-************&&&-+. ", + " .=>*****&&&&&********&&&&&&&&&&&&&&$. ", + " .+-*&&&%%&&&&%&&%%%&&%%%&%%%%%%%%&&+. ", + " .%*&%&%%%%%%%&&&&&&&&&&%%%%%%%%%&$. ", + " .+%&%$$#$$$$%%%%%%%%%%%$$$%%$$$$%+. ", + " .#%%@##@##$$$$$$$$$$$$$$$$$$$$%@. ", + " .@#@@@@#@@##$$$$$###########$$. ", + " .#@@@@@@@#@###@@@@##@@###@#$+ ", + " ++@+@@@@@#@#@@@@@@@@@@@@##+ ", + " .+++++++@@@+++++@++++@@+. ", + " ..++@@+++++++++++++@@+. ", + " ..+++@@++++++@@+++. ", + " ...@@+....+@@.. ", + " ......... ", + " ", + " ", + " ", + " ", + " "}; + + +/* XPM */ +static const char * knob4_xpm[] = { + "51 51 31 1", + " c None", + ". c #010400", + "+ c #040703", + "@ c #0D0605", + "# c #060905", + "$ c #100B0A", + "% c #0A0D09", + "& c #0F110E", + "* c #151110", + "= c #111310", + "- c #141513", + "; c #171916", + "> c #1B1818", + ", c #191B18", + "' c #1B1C1A", + ") c #1F1D1F", + "! c #201E21", + "~ c #1F201E", + "{ c #222421", + "] c #252725", + "^ c #282629", + "/ c #292A28", + "( c #2C2E2B", + "_ c #322E2D", + ": c #30322F", + "< c #303436", + "[ c #323431", + "} c #353634", + "| c #373936", + "1 c #3B3D3A", + "2 c #3E3F3D", + " ", + " ", + " ", + " ", + " ", + " ]/(}||1|} ", + " ]|222222221111| ", + " /122222221111111||| ", + " (1222222111|||||||||}}[ ", + " |2222221|||||||}}}}[||}<( ", + " |2222221||||||}}}}}}}}[}[/] ", + " |22222211|||||}}_[[[[[<[[[(~~ ", + " |2222221112|||}}[[[[[[[[[[[:(,; ", + " /2222222111||||}[[[[[:::::::::/-= ", + " %11222211111|||}[[[:::::::::::::]%# ", + " !12111121111|||}[[::::::((((((((_-+ ", + " #|1111111111||||[:::::((_(__((((((]%@ ", + " &1111||||||||||}[:::(__((((((((((((=. ", + " .~12|[}}}|||||||}[:(_(((((((((//////~%. ", + " .:12|::[[[[}}}}[[:(((((////_/////////&. ", + " @|1|:((:::::[[_::_((///////////////^/&. ", + " .%||}((((((((_(((((////////]]]]]]]]]^];+. ", + " .%||:////////(((//////]]]^]]]]]]]{]{{{~%. ", + " .%|<(//^//////////]]]]{{{{{{{{{{{{{{{{{$. ", + " .%<:/]]]]]]]]]]]]]{{{{{{{{{{{{~~~~~~!!{%. ", + " .%[:]]]]]]]{^^]]{{{{{{{{{{{!{{~~~!~!~!{%. ", + " .@[({{{^{{~{{{{{~~{~~~~~~~~~~~~~~!~!!!~%. ", + " .#:({{~~~~~~~~~~~~~~~!!!~!!!~!''''''''!%. ", + " .+_/~~~~~!!!~~~'')''''''''''''',,,,,,,,#. ", + " ../]!'''''''''''',',,,,,,,,>,,,,,;;;;;-+. ", + " .'{!',,,,,,>,,,,,,;;;;;;;;;;;;;;;;;;;%. ", + " .%~!,;;;;;;;;;;;;;;;;;;;;;;;;>;;;---;+. ", + " ..~~;;;;;;;;;----------------------->@. ", + " .;;--*----==--*-----------=---*===-%. ", + " ..;----==****=*==================*-.. ", + " .=--=*&&&&&&&**********&&&&&&&&&*%. ", + " ..=*&&%%%%%&&&&&&&&&&&&&&&#&&&&%&.. ", + " .%&&%%%%%%%%%&&%%%%%%%%$%%%%%%&@. ", + " .%%###@%%%%%%&%%$%%%%%%%%%%%%%. ", + " .%#+####@%%%%%%%%%%@@%%%%@%%. ", + " .+#+#####%%%@########@+@%%. ", + " ....++++###++++++++++@@+. ", + " ...+##@.+@++......+##.. ", + " .....##+....+##.... ", + " ...@#......#@.. ", + " ......... ", + " ", + " ", + " ", + " ", + " "}; + +/* XPM */ +static const char * knob6_xpm[] = { + "51 51 31 1", + " c None", + ". c #010400", + "+ c #000902", + "@ c #040C00", + "# c #011203", + "$ c #061200", + "% c #031701", + "& c #051A00", + "* c #021E04", + "= c #0A2000", + "- c #042303", + "; c #0B2601", + "> c #052A06", + ", c #0B2D02", + "' c #053107", + ") c #0B3403", + "! c #0E3707", + "~ c #093A02", + "{ c #0C3C05", + "] c #104009", + "^ c #154203", + "/ c #0E4506", + "( c #154A0B", + "_ c #145108", + ": c #19550D", + "< c #165A08", + "[ c #1B5E0D", + "} c #1F6111", + "| c #206212", + "1 c #1C660B", + "2 c #226B11", + " ", + " ", + " ", + " ", + " ", + " /(_[1111< ", + " /|222222222211| ", + " (12222222221111111[ ", + " _1222222211|}[[|11|}[[< ", + " |2222222|}[[[[[[[[<<[[<:_ ", + " 122222211||[[[[[<<<<<<<[<(/ ", + " |222222111|}[[[<<<<<<<<<<<_{~ ", + " [2222222211|}[[<<<<<<<<<<<<<_), ", + " (22222222111|}[<<<<<<<<<::::::(;- ", + " &122222222111|}[<<<<::::::::::::/%@ ", + " !222211221111|}[<<:::::::________;@ ", + " @|221111111111|[<<::::____________/&@ ", + " &1211}}|1111||}[<<::_______________-+ ", + " .{12|<<[[[[}}}[}<<:___________((((((~%. ", + " +:11[::<<<<<[[<<<:_____((((((((((((((*. ", + " $}1}:__:::<<<<<::___(((((((((((((//((=+ ", + " .%|1[______________(((((//////////////,@. ", + " .%}|:((((((((___(((((////////////^/^]]!%. ", + " .%[[_(((///(((((((////^]]^]]]]]]]]^]{{{&. ", + " .$<<(/////////////^]]]^]]]{{{{{{{{{{~{{&. ", + " .$<:///////^////^^^]]]]]]]{{{{{{{~{~~~{&. ", + " .$<_^]]]^]^]]]]{{{{{{{{{{~~~~~!!!!!!!!{%. ", + " .@:_]{{{{{{{{{~~!~~!!!!!!!!!!!))))))))!%. ", + " .@_({~!!!!!!!!!))!)))))))))))))''''''''#. ", + " .+(/!))))))))))))')'''')))))'''''',,,',@. ", + " .)]!)'''')))))'''',,,,,,,,,,,,,,,,,,,&. ", + " .%!!',,,,,,,,,,,,,,,,,,,,>>>>>>>>>>>,@. ", + " .+~!,,,,,>>>>>>>>>>>>>;;;;;;;;;;;;;;,@. ", + " .,,>;>;;;;--;;;;;;;;;;;;;;-;;;;---;&. ", + " .@>>;;;-------;-----;-------------;@. ", + " .-;;--******=----------=====*==*-&. ", + " .+--*&&%&&&&***********&&&**&&&&*+. ", + " .$=*%$$%%%&&&&&&&&&&&&&&&&&&&&*$. ", + " .%%###$$%%%%&&&&&%%%%%%%%%%%&&. ", + " .%##@@##$$%%%%%%%%%%%%$$$$%&+ ", + " @@#@#@@##$%$$###########$%+ ", + " .@+@@@@@@#@@@@@@@@@@@$#@. ", + " ..+@#@@@@@@@@@@@@@@@#+. ", + " ..@@@##@@@+@@@@@@@. ", + " ...$#+....@#$.. ", + " ......... ", + " ", + " ", + " ", + " ", + " "}; + + +/* XPM */ +static const char * switchit_xpm[] = { + "74 28 241 2"," c None",". c #000000","+ c #040404","@ c #080808", + "# c #090909","$ c #050505","% c #010101","& c #151515","* c #2B2B2B", + "= c #2D2D2D","- c #191919","; c #060606","> c #030303",", c #141414", + "' c #2A2A2A",") c #070707","! c #F86925","~ c #C53F02","{ c #C33D00", + "] c #C83E01","^ c #46E41B","/ c #2FCA04","( c #29BF00","_ c #2BC701", + ": c #FFC77A","< c #FFC075","[ c #FE7A31","} c #E64D07","| c #D84400", + "1 c #D14100","2 c #CA3E00","3 c #1B1B1B","4 c #3A3A3A","5 c #414141", + "6 c #C6FF94","7 c #AFFF7C","8 c #63FE31","9 c #37E607","0 c #2ED800", + "a c #2CD100","b c #2CD000","c c #020202","d c #FFB86E","e c #FFF8B0", + "f c #FFB26C","g c #ED5712","h c #D44300","i c #CD4000","j c #C23C00", + "k c #C62C00","l c #353535","m c #D0D1D1","n c #D0D0D1","o c #D1D1D0", + "p c #D0D0D0","q c #373737","r c #76F946","s c #A3FF70","t c #E1FFB0", + "u c #9CFF6C","v c #41ED12","w c #2ED400","x c #2CCD00","y c #2AC600", + "z c #2FDD00","A c #0B0B0B","B c #F65308","C c #FD7028","D c #FFA862", + "E c #FFA15D","F c #EA5714","G c #CF4201","H c #C83E00","I c #CA3A00", + "J c #4D4D4D","K c #C4C4C5","L c #C5C4C5","M c #C4C4C4","N c #C4C4C3", + "O c #C3C3C3","P c #C4C3C4","Q c #C3C4C3","R c #40F60E","S c #5AFD28", + "T c #92FF62","U c #8CFF5D","V c #42EA14","W c #2DCF01","X c #2BC800", + "Y c #2AC200","Z c #2FDB01","` c #272727"," . c #313131",".. c #E44801", + "+. c #E44B05","@. c #E95410","#. c #E85513","$. c #D44605","%. c #CA3F00", + "&. c #C43D00","*. c #BE3B00","=. c #C93300","-. c #B8B8B8",";. c #B8B7B8",">. c #B7B8B8", + ",. c #B7B7B7","'. c #B7B7B6","). c #363636","!. c #32E201","~. c #35E405","{. c #3EE910", + "]. c #40E813","^. c #32D405","/. c #2BCA00","(. c #2AC400","_. c #29BE00",":. c #2ED500", + "<. c #B5B5B5","[. c #404040","}. c #4A4A4A","|. c #B6B7B6","1. c #DA4400","2. c #D74300", + "3. c #D44200","4. c #CF4100","5. c #C03C00","6. c #BA3A00","7. c #A82300","8. c #ABABAC", + "9. c #ABACAB","0. c #ABACAC","a. c #ABABAB","b. c #ABAAAB","c. c #AAABAB","d. c #AAAAAA", + "e. c #ABABAA","f. c #2ED700","g. c #2DCF00","h. c #29C000","i. c #28BA00","j. c #2BC900", + "k. c #A9A9AA","l. c #A9A9A9","m. c #7D7D7D","n. c #AAAAAB","o. c #D14000","p. c #D04000", + "q. c #CC4000","r. c #BF3B00","s. c #BB3A00","t. c #AE3500","u. c #9F9FA0", + "v. c #9FA09F","w. c #9F9F9F","x. c #9E9F9F","y. c #3E3E3E","z. c #0C0C0C","A. c #101010", + "B. c #9E9E9F","C. c #9E9E9E","D. c #9E9D9D","E. c #2DD200","F. c #2CCC00","G. c #28BB00", + "H. c #27B600","I. c #9D9D9D","J. c #9D9E9D","K. c #9D9E9E","L. c #0F0F0F","M. c #9E9F9E", + "N. c #C13B00","O. c #C53E00","P. c #AF3500","Q. c #B33400","R. c #939393","S. c #929393", + "T. c #939392","U. c #6F6E6E","V. c #929291","W. c #929192","X. c #929292", + "Y. c #919191","Z. c #28BE00","`. c #29C500"," + c #3C3C3C",".+ c #4B4B4B", + "++ c #939394","@+ c #B22500","#+ c #CF3C00","$+ c #C03100","%+ c #A72300", + "&+ c #868687","*+ c #868787","=+ c #868686","-+ c #858685",";+ c #858485", + ">+ c #858585",",+ c #2DD301","'+ c #2DD100",")+ c #2AC700","!+ c #878686", + "~+ c #6C6C6C","{+ c #878787","]+ c #878888","^+ c #888787","/+ c #878788", + "(+ c #7A7A7A","_+ c #797979",":+ c #787878","<+ c #797878","[+ c #7B7B7B", + "}+ c #7A7A7B","|+ c #7B7A7B","1+ c #7B7B7C","2+ c #7C7B7B","3+ c #7C7C7C", + "4+ c #6D6D6D","5+ c #696969","6+ c #6E6F6E","7+ c #6F6F6E","8+ c #6F6F6F", + "9+ c #706F70","0+ c #6F706F","a+ c #6F6F70","b+ c #707070","c+ c #616161", + "d+ c #606060","e+ c #636363","f+ c #646463","g+ c #636463","h+ c #646464", + "i+ c #656564","j+ c #585758","k+ c #575757","l+ c #585858","m+ c #575758", + "n+ c #585958","o+ c #585859","p+ c #4C4B4B","q+ c #4C4C4C","r+ c #4C4D4D", + " ", + " ", + " . . . . ", + " . + @ # $ % ", + " . + & * = - ; . ", + " - - - - - - - - > + , ' = - ) > ", + " ! ~ { ] - - - - - - - - - - - - ^ / ( _ - - % . + @ # $ % % - - ", + " : < [ } | 1 2 - - - - 3 = 4 5 ' - - - - - 6 7 8 9 0 a b - - - % . . . . . . c - - - ", + " d e f g h i j k - - - - l m n o p p p q - - - - r s t u v w x y z - - - - # . . . . . . A - - - - ", + " B C D E F G H j I - - - J K L M N O P P Q J - - - R S T U V W X Y Z - - - J ` . . . . . . .J - - - ", + " ..+.@.#.$.%.&.*.=. - - - q -.;.-.-.>.,.,.,.'.,.).- - - !.~.{.].^./.(._.:. - - - ).<.[.+ . . . . $ }.|.q - - - ", + " 1.2.3.4.%.&.5.6.7. - - - 8.9.0.8.a.a.b.a.c.d.e.d.3 - - 0 f.w g./.(.h.i.j. - - 3 k.l.m.> . . . . % n.e.n.- - - ", + " o.p.q.H &.r.s.t. - - ' u.v.w.x.y.z.A.J B.C.D.C.= - - E.b F.X (.( G.H. - - = I.J.K.L.. . . . 3 M.M.w.' - - ", + " N.O.j *.6.P.Q. - - 5 R.S.T.U.+ . . c V.W.X.Y.4 - - j.y Y Z.i.H.`. - - 4 X.V.X. +> . . ; .+R.R.++5 - - ", + " @+#+$+%+ - - 4 &+*+=+ +> . . ; .+-+;+>+5 - - ,+f.'+)+ - - 5 !+&+&+~++ . . c {+]+^+/+4 - - ", + " - - = (+(+(+L.. . . . 3 _+:+<+' - - - - ' (+[+}+|+y.z.A.J 1+2+[+3+= - - ", + " - - 3 4+4+5+> . . . . % ~+~+~+- - - - - - 6+7+8+8+9+0+a+9+9+b+b+b+3 - - ", + " - - - ).c+[.+ . . . . $ }.d+q - - - - - - q e+e+e+f+g+e+h+h+h+i+).- - - ", + " - - - J ` . . . . . . .J - - - - - - J j+k+l+m+l+n+o+l+J - - - ", + " - - - - # . . . . . . A - - - - - - - - l p+q+q+q+r+q+q - - - - ", + " - - - % . . . . . . c - - - - - - - 3 = 4 5 ' - - - - - ", + " - - % . + @ # $ % % - - - - - - - - - - - - - - ", + " > + , ' = - ) > - - - - - - - - ", + " . + & * = - ; . ", + " . + @ # $ % ", + " . . . . ", + " ", + " "}; + +/* XPM */ +static const char * slidersm_xpm[] = { + "140 10 69 1"," c None",". c #060606","+ c #020202","@ c #010101","# c #222222", + "$ c #2E2E2E","% c #2C2C2C","& c #1D1D1D","* c #000000","= c #0E0E0E", + "- c #A7A7A7","; c #F9F9F9","> c #CFCFCF",", c #B4B4B4","' c #969696", + ") c #878787","! c #696968","~ c #1E1E1E","{ c #A0A0A0", + "] c #0C0C0C","^ c #515150","/ c #EAEAEA","( c #909090","_ c #787878", + ": c #707070","< c #676868","[ c #656565","} c #626262","| c #4E4E4E", + "1 c #292929","2 c #646464","3 c #AEAEAE","4 c #929292","5 c #424242", + "6 c #9B9B9B","7 c #686868","8 c #5E5E5E","9 c #585858","0 c #505050", + "a c #4C4C4C","b c #464646","c c #424142","d c #3C3C3C","e c #605F5F", + "f c #808080","g c #787979","h c #6E6E6E","i c #343434","j c #494949", + "k c #373737","l c #303030","m c #2A2A2A","n c #3C3C3E","o c #575757", + "p c #454545","q c #525252","r c #262626","s c #181818","t c #141414", + "u c #242424","v c #101010","w c #1F1F1F","x c #383838","y c #080808", + "z c #040404","A c #0A0A0A","B c #101111","C c #1C1C1C","D c #070707", + " .+@#$%&*+. ", + " ***=-;>,')!~**** ", + " **{]^/(_:<[}|*12** ", + " *3*4+567890abc*de*f*", + "*************************************************************************************************************************g*h*ihj5dkilm*#n*o*", + "*************************************************************************************************************************p*|*mqlmr#~st*=u*%*", + " *v*%*wxst=y.z@*@v*y*", + " **A*BC+@********** ", + " ****.*********** ", + " D+******+D "}; + +/* XPM */ +static const char * switch_xpm[] = { + "40 10 78 1", + " c #444242", + ". c #000000", + "+ c #888989", + "@ c #818181", + "# c #797979", + "$ c #717171", + "% c #696969", + "& c #616161", + "* c #5A595A", + "= c #515151", + "- c #4A4A4A", + "; c #28BB00", + "> c #373737", + ", c #1C1919", + "' c #868686", + ") c #7E7E7E", + "! c #767676", + "~ c #6E6E6E", + "{ c #666666", + "] c #5E5E5F", + "^ c #565656", + "/ c #4F4E4F", + "( c #474747", + "_ c #2DCF01", + ": c #828383", + "< c #7B7B7B", + "[ c #737373", + "} c #6B6B6B", + "| c #636364", + "1 c #5B5B5B", + "2 c #535353", + "3 c #4B4C4B", + "4 c #434344", + "5 c #808080", + "6 c #787878", + "7 c #707070", + "8 c #686968", + "9 c #606060", + "0 c #595858", + "a c #515050", + "b c #484949", + "c c #414140", + "d c #7D7D7D", + "e c #757575", + "f c #6D6E6D", + "g c #656566", + "h c #5D5E5E", + "i c #555655", + "j c #4E4D4E", + "k c #454646", + "l c #3E3E3E", + "m c #7B7A7A", + "n c #737372", + "o c #6A6A6A", + "p c #636362", + "q c #5B5A5B", + "r c #535352", + "s c #4B4B4A", + "t c #434342", + "u c #3B3B3B", + "v c #777778", + "w c #6F6F70", + "x c #686768", + "y c #5F605F", + "z c #575757", + "A c #504F50", + "B c #484848", + "C c #404040", + "D c #383838", + "E c #747475", + "F c #6D6C6C", + "G c #646464", + "H c #5D5D5D", + "I c #555555", + "J c #4D4D4D", + "K c #444545", + "L c #3D3D3D", + "M c #353535", + " ", + " ........ +@#$%&*=- ;;;;;;;;; ........ ", + " .>>>,... ')!~{]^/( ;_____;;; .>>>,... ", + " .>>,.... :<[}|1234 ;___;;;;; .>>,.... ", + " .>,..... 567890abc ;__;;;;;; .>,..... ", + " .,...... defghijkl ;_;;;;;;; .,...... ", + " ........ mnopqrstu ;_;;;;;;; ........ ", + " ........ vwxyzABCD ;;;;;;;;; ........ ", + " ........ EFGHIJKLM ;;;;;;;;; ........ ", + " "}; + +/* XPM */ +static const char * wheel_xpm[] = { + "200 8 21 1", + " c None", + ". c #213E41", + "+ c #1A4042", + "@ c #044746", + "# c #1F403D", + "$ c #124444", + "% c #263F3D", + "& c #2D3E3E", + "* c #333E3F", + "= c #094A49", + "- c #3B3F41", + "; c #3F413F", + "> c #444643", + ", c #314E51", + "' c #484A47", + ") c #4F514E", + "! c #535552", + "~ c #575856", + "{ c #5D5F5C", + "] c #636562", + "^ c #676966", + "^ ] ] { { { ~ ~ ! ) ) ' ' > > ; ; ; - - * * * & & & % % . + + + $ $ $ $ @ @ = = =", + "^ ] ] { { { ~ ~ ! ) ) ' ' > > ; ; ; - - * * * & & & % % . + + + $ $ $ $ @ @ = = =", + "^ ] ] { { { ~ ~ ! ) ) ' ' > > ; ; - - * * * * & & & % % % + + + $ $ $ $ @ @ @ = =", + "^ ] ] { { { ~ ~ ! ) ) ' ' > > ; ; - - * * * * & & & % % % + + + $ $ $ $ @ @ @ = =", + "^ ] ] { { { ~ ~ ! ) ) ' ' > > ; ; - - * * * * & & & % % % # + + $ $ $ $ @ @ @ = =", + "^ ] ] { { { ~ ! ! ) ) ' ' > > ; ; ; - - * * * & & & % % # + + + $ $ $ $ @ @ @ = =", + "^ ] ] { { { ~ ! ! ) ) ' ' > > ; ; ; - - * * * & & & % % # + + + $ $ $ $ @ @ @ = =", + "^ ] ] { { { ~ ! ! ) ) ' ' > > ; ; ; - - * * * & & & % . + # + + $ $ $ $ @ @ @ = ="}; + +/* XPM */ +static const char * wheel_s_xpm[] = { + "40 8 21 1", + " c None", + ". c #252422", + "+ c #353634", + "@ c #484947", + "# c #575756", + "$ c #5E5F5D", + "% c #686967", + "& c #737472", + "* c #80817F", + "= c #8D8D8C", + "- c #979896", + "; c #A1A4A3", + "> c #AEAEAD", + ", c #B7B8B6", + "' c #C1C1BE", + ") c #C9C9C6", + "! c #D3D4D2", + "~ c #DDDFDD", + "{ c #E7E9E6", + "] c #EEF0EE", + "^ c #F9FBF7", + "#$%&*=-;>')!~{^^]{~!)',>>;-=**&%$#@@++..", + "#$%&*=-;>')!~{^^]{~!)',>>;-=**&%$#@@++..", + "#$%&*=-;>,)!~{^^]{~!)',>;;-=**&%$#@@++..", + "#$%&*=-;>,)!~{^^]{~!)',>;;-=**&%$#@@++..", + "#$%&*=-;>,)!~{^^]{~!)),,>;-=**&%$#@@++..", + "#$%&*=-;>,)!~{^^]{~!!),,>;-=**&%$#@@++..", + "#$%&*=-;>,)!~{^^]{~!!),,>;-=**&%$#@@++..", + "##%&*=-;>,)!~{^^]{~!!)',>;-=**&%$#@@++.."}; + + +/* XPM */ +static const char * pointer_xpm[] = { + "2 8 2 1", + " c None", + ". c #2525A4", + "..", + "..", + "..", + "..", + "..", + "..", + "..", + ".."}; + +/* XPM */ +static const char * button_xpm[] = { + "25 30 31 1", + " c None", + ". c #0F110E", + "+ c #171211", + "@ c #1C1817", + "# c #231F1E", + "$ c #282423", + "% c #252A22", + "& c #2F2B2A", + "* c #242F25", + "= c #283B26", + "- c #3B3736", + "; c #2F472A", + "> c #474342", + ", c #2A5927", + "' c #1F6624", + ") c #585151", + "! c #2F642A", + "~ c #625D5C", + "{ c #6B6665", + "] c #3D813D", + "^ c #726E6C", + "/ c #7B7675", + "( c #7E7A78", + "_ c #3E963A", + ": c #379B33", + "< c #8A8584", + "[ c #39A738", + "} c #42B839", + "| c #3ABD3D", + "1 c #42BB43", + "2 c #A79F9F", + " $&--&#@ ", + " ++$&--&#@++ ", + " .#)<2<<<(((>$@. ", + " +>22/{/(//^^<^-#. ", + " .^2({/((///((//^>@. ", + " .)2~(//(((/((((//{-$. ", + " .@/<{//((((((((((/^>&+. ", + " .&^^$@. ", + " .+)$@. ", + " .-~^((((((((//~-$+. ", + " +#-){^//^^{)>&#+. ", + " .+#$&---&$$@@+. ", + " +++++.+++++ ", + " +++++++ ", + " @@###@@ ", + " ..@@###@@.. ", + " .@%;]_[[[_];%@. ", + " +*![1||}|}||1[!*+ ", + " +,:||}|||||||}||:,+ ", + " .=:1|}|||||||||}|1:=. ", + " .+,}}|||||||||||||}},+. ", + " .#'|||||||||||||||||'#. ", + " .+,}}|||||||||||||}},+. ", + " .=:1|}|||||||||}|1:=. ", + " +,:||}|||||||}||:,+ ", + " +*![1||}|}||1[!*+ ", + " .@%;]_[[[_];%@. ", + " ..@@###@@.. ", + " @@###@@ "}; + +/* XPM */ +static const char * button1_xpm[] = { + "25 30 31 1", + " c None", + ". c #020400", + "+ c #0C0503", + "@ c #080A06", + "# c #100A09", + "$ c #140F0D", + "% c #181413", + "& c #1C1817", + "* c #221E1D", + "= c #262322", + "- c #2A2726", + "; c #302C2B", + "> c #34302F", + ", c #393635", + "' c #403B3A", + ") c #454140", + "! c #4C4746", + "~ c #575251", + "{ c #675D5D", + "] c #716C6B", + "^ c #777271", + "/ c #7E7A78", + "( c #857F7E", + "_ c #898483", + ": c #918C8B", + "< c #95908F", + "[ c #999392", + "} c #9B9694", + "| c #A6A19F", + "1 c #C3AFB2", + "2 c #CFC3C3", + " *;',-&$ ", + " ++*;',-&$++ ", + " .&{|2||||<:!*$. ", + " #~12::::}[(/}/'&. ", + " @(2*. ", + " .#:|/::<<<<<<<<<<:(!=+. ", + " .-(/}::<<<<<<<<<<:(!*#. ", + " .@{}_::<<<<<<<<<<:]>&+. ", + " .'[(::<<<<<<<::_^!=@. ", + " .>]_<<<<<<<<:_{'*@. ", + " +&'~^(_:_/^{)-&@. ", + " .#&*-,',;=*%$+. ", + " ++###@++#++ ", + " ###@++# ", + " $$%&%$$ ", + " ..$$%&%$$.. ", + " .$=']/(_(/]'=$. ", + " +=~(|[[[[[[[|(~=+ ", + " +!/}[[[}[}[}[[[}/!+ ", + " .>^<[[[}}}}}}}[[[<^>. ", + " .@)<[[}}}}}}}}}}}[[<)@. ", + " .&!}[[}}}}}}}}}}}[[}!&. ", + " .@)<[[}}}}}}}}}}}[[<)@. ", + " .>^<[[[}}}}}}}[[[<^>. ", + " +!/}[[[}[}[}[[[}/!+ ", + " +=~(|[[[[[[[|(~=+ ", + " .$=']/(_(/]'=$. ", + " ..$$%&%$$.. ", + " $$%&%$$ "}; + +/* XPM */ +static const char * eqslider1_xpm[] = { +"13 120 25 1", +" c None", +". c #000200", +"+ c #060805", +"@ c #131413", +"# c #282928", +"$ c #323432", +"% c #3F403E", +"& c #4B4C4B", +"* c #575856", +"= c #60615F", +"- c #666765", +"; c #676866", +"> c #6E706E", +", c #71716F", +"' c #7B7B79", +") c #00AD00", +"! c #7E7F7D", +"~ c #878987", +"{ c #8F908E", +"] c #9B9D9A", +"^ c #AAABA9", +"/ c #ACAEAB", +"( c #00F210", +"_ c #B2B3B0", +": c #B9BBB8", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" ;.. ", +" :_^^^~- ", +" ~__^{{!-= ", +" #+++++++@ ", +" ~:_{!!-*& ", +" !~'=**%$$ ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ())/ ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) ", +" ()) "}; + +/* XPM */ +static const char * eqslider_xpm[] = { + "13 120 21 1", + " c None", + ". c #000200", + "+ c #282927", + "@ c #433F3E", + "# c #4F5252", + "$ c #656664", + "% c #9B680C", + "& c #90720E", + "* c #8B7710", + "= c #857F14", + "- c #00AA00", + "; c #7A8A11", + "> c #719213", + ", c #848485", + "' c #679B17", + ") c #5CA718", + "! c #50B118", + "~ c #4AB81B", + "{ c #45BD19", + "] c #3CC51B", + "^ c #25D816", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @...@ ", + " @@@@@@@@@ ", + " @,,$#@+...@ ", + "@@@#@+@.@.@@@", + " @@+.......@ ", + " @@@@@@@@@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-^-@ ", + " @-]-@ ", + " @-]-@ ", + " @-]-@ ", + " @-]-@ ", + " @-{-@ ", + " @-{-@ ", + " @-{-@ ", + " @-~-@ ", + " @-~-@ ", + " @-~-@ ", + " @-!-@ ", + " @-!-@ ", + " @-!-@ ", + " @-)-@ ", + " @-)-@ ", + " @-)-@ ", + " @-)-@ ", + " @-)-@ ", + " @-'-@ ", + " @-'-@ ", + " @-'-@ ", + " @-'-@ ", + " @->-@ ", + " @->-@ ", + " @->-@ ", + " @-;-@ ", + " @-;-@ ", + " @-;-@ ", + " @-=-@ ", + " @-=-@ ", + " @-=-@ ", + " @-=-@ ", + " @-=-@ ", + " @-*-@ ", + " @-*-@ ", + " @-&-@ ", + " @-&-@ ", + " @-&-@ ", + " @-%-@ ", + " @-%-@ ", + " @-%-@ ", + " @-%-@ "}; + + +/* XPM */ +static const char * led_xpm[] = { +"20 40 21 1", +" c None", +". c #030702", +"+ c #0F0401", +"@ c #210403", +"# c #540A07", +"$ c #7C0809", +"% c #092E0C", +"& c #2C221D", +"* c #A4040D", +"= c #D50D0F", +"- c #434542", +"; c #784641", +"> c #1B6F15", +", c #777A75", +"' c #1C9E1D", +") c #B08B87", +"! c #24D11A", +"~ c #ABAFA9", +"{ c #3CFF36", +"] c #8AFF82", +"^ c #C4FDB9", +" ", +" ", +" ", +" ", +" ~~,- ", +" ~~~,,-&.. ", +" ~~);$##@... ", +" ,,;*==###@+. ", +" ,;*=====$#@.. ", +" -#=======$#@. ", +" -#=======*$@. ", +" &@=======**@. ", +" &@$======*$+. ", +" ..@*====*$@. ", +" .++$***$@+. ", +" ..+++++.. ", +" ...... ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ~~,- ", +" ~~~,,-&.. ", +" ~~~,,--&... ", +" ,,,~^^>>>%.. ", +" ,,~^^]]{'>%.. ", +" --]^]]{{{'>&. ", +" --]]]{{{{!'%. ", +" &&]]{{{{{!!%. ", +" &&'{{{{{{!'%. ", +" ..&!{{{{!'%. ", +" ...'!!!'%.. ", +" ......... ", +" ...... ", +" ", +" ", +" "}; + +/* XPM */ +static const char * rbutton_xpm[] = { +"22 46 26 1", +" c None", +". c #000300", +"+ c #020230", +"@ c #2C052A", +"# c #141513", +"$ c #380646", +"% c #250D7B", +"& c #022D01", +"* c #222421", +"= c #063031", +"- c #132A8D", +"; c #A00E49", +"> c #E00D20", +", c #3A3C39", +"' c #EE1011", +") c #484947", +"! c #555654", +"~ c #686967", +"{ c #747673", +"] c #00A608", +"^ c #80827F", +"/ c #8D8F8C", +"( c #989A97", +"_ c #19E20A", +": c #00F00C", +"< c #C2C4C1", +";@........*", +"*.....@>''''>@.......*", +"*.....;'''''';.......*", +"*.....>''''''>+......*", +"*.....>''''''>.......*", +"*.....;'''''';.......*", +"*.....@>''''>@.......*", +"*......$;'>;@........*", +"*....................*", +"*....................*", +"*....................*", +"*....................*", +",********************,", +"!!!!!!!!!!!!!!!!!!!!!!", +"^{^^^^^^^^^^^^^^^^^^{^", +"<^<<<<<<<<<<<<<<<<<<^<", +"{(((((((((((((((((((({", +"!))))))))))))))))))))!", +"*....................*", +"#....................#", +"#....................#", +"#....................#", +"#....................#", +"#......-::_]&........#", +"#.....&_::::_&.......#", +"#.....]::::::].......#", +"#....._:::::::+......#", +"#....._::::::_.......#", +"#.....]::::::].......#", +"#.....&_::::_&.......#", +"#......=]:_]&........#", +"#....................#", +"#....................#", +"#....................#", +"#....................#", +",********************,", +"~{{{{{{{{{{{{{{{{{{{{~", +"/<<<<<<<<<<<<<<<<<<< c #1300FC", +", c #222321", +"' c #393B38", +") c #40423F", +"! c #484947", +"~ c #545653", +"{ c #686967", +"] c #747673", +"^ c #80827F", +"/ c #8D8F8C", +"( c #989A96", +"_ c #17F10C", +": c #C2C4C0", +":~^^^^^^^^^^^^^^^^^^~:", +"~{{{{{{{{{{{{{{{{{{{{~", +")'''''''''''''''''''')", +",$$$$$$$$$$$$$$$$$$$$,", +", ,", +", ,", +", ,", +", ,", +", *#. ,", +", *>>* ,", +", *>>>-= ,", +", *>>>>>-@ ,", +", *>>>>-@ ,", +", *>>>= ,", +", *>& ,", +", %. ,", +", ,", +", ,", +", ,", +", ,", +"',,,,,,,,,,,,,,,,,,,,'", +"~~~~~~~~~~~~~~~~~~~~~~", +"^]^^^^^^^^^^^^^^^^^^]^", +":^::::::::::::::::::^:", +"]((((((((((((((((((((]", +"~!!!!!!!!!!!!!!!!!!!!~", +", ,", +"; ;", +"; ;", +"; ;", +"; ;", +"; #_ ;", +"; #__- ;", +"; #____& ;", +"; #______@ ;", +"; #_____+ ;", +"; #___& ;", +"; #_- ;", +"; @. ;", +"; ;", +"; ;", +"; ;", +"; ;", +"',,,,,,,,,,,,,,,,,,,,'", +"{]]]]]]]]]]]]]]]]]]]]{", +"/::::::::::::::::::::/"}; + diff --git a/src/GtkWaveView.cpp b/src/GtkWaveView.cpp new file mode 100644 index 0000000..e3fb975 --- /dev/null +++ b/src/GtkWaveView.cpp @@ -0,0 +1,1208 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// ***** GtkWaveView.cpp ***** +/****************************************************************************** +part of guitarix, show a wave with Gtk +******************************************************************************/ + +#include "guitarix.h" + +using namespace gx_jconv; + +#define GTK_TYPE_WAVEVIEW (gtk_waveview_get_type()) +#define GTK_WAVEVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WAVEVIEW, GtkWaveView)) +#define GTK_IS_WAVEVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WAVEVIEW)) +#define GTK_WAVEVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WAVEVIEW, GtkWaveViewClass)) +#define GTK_IS_WAVEVIEW_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WAVEVIEW)) + + +struct GtkWaveViewClass +{ + GtkRangeClass parent_class; + cairo_surface_t *surface_file; + cairo_surface_t *surface_selection; + + GdkPixbuf *liveview_image; + GtkTooltips *comandline; + + int waveview_x; + int waveview_y; + int waveleft; + int wavestay; + int wavebutton; + double scale_view; + + int offset_cut; + int length_cut; + int filelength; + double drawscale; + + int liveview_x; + int liveview_y; + float *live_view; + float *live_viewin; + // float *live_freq; + int new_pig; + + int tunerview_x; + int tunerview_y; + cairo_surface_t *surface_tuner; + +}; + +GType gtk_waveview_get_type (); + +//----- draw a new wave in a idle thread +static gboolean gtk_waveview_paint(gpointer obj) +{ + GtkWidget *widget = (GtkWidget *)obj; + g_assert(GTK_IS_WAVEVIEW(widget)); + GtkWaveView *waveview = GTK_WAVEVIEW(widget); + + cairo_t *cr, *cr_show; + + cr_show = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + cr = cairo_create (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_file); +// retrieve JConv settings + GxJConvSettings* const jcset = GxJConvSettings::instance(); + + /* read the floating points from a wave file as string to a file */ + // ofstream outfile ("test.txt"); + // string cim = ""; + + // gx_system::gx_print_info("Wave view NEW expose", jcset->getIRFile().c_str()); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut = 0; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut = 0; + + // IR file parameters + SNDFILE* pvInput = NULL; + + int counter = 0; + int vecsize = 64; + int length = 0; + int countframe = 1; + int countfloat; + int chans; + int sr; + float *sfsig; + + double waw = 600; // widget->allocation.width*4 we cant use width in a scrolable window + double wah = widget->allocation.height*0.5; + double wah1 = widget->allocation.height*0.25; + + + // some usefull cairo settings + cr = cairo_create (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_file); + cairo_set_source_rgb (cr, 0.1, 0.1, 0.1); + cairo_set_antialias(cr,CAIRO_ANTIALIAS_SUBPIXEL); + cairo_set_line_join(cr,CAIRO_LINE_JOIN_ROUND); + cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND); + // draw the background + cairo_move_to (cr, 0, 0); + cairo_rectangle (cr, 0, 0, waw, widget->allocation.height); + cairo_fill_preserve (cr); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 0.3, 0.7, 0.3); + cairo_stroke (cr); + // draw the widget frame + cairo_move_to (cr, 0, wah); + cairo_line_to (cr, waw, wah); + cairo_set_line_width (cr, 2.0); + cairo_set_source_rgb (cr, 0.3, 0.7, 0.3); + cairo_stroke (cr); + + //----- draw an X if JConv IR file not valid + if (jcset->isValid() == false) { + gx_system::gx_print_warning("Wave view expose", + GxJConvSettings::instance()->getIRFile() + + " cannot be exposed "); + + cairo_move_to (cr, 0, widget->allocation.height); + cairo_line_to (cr, waw, 0); + cairo_move_to (cr, 0, 0); + cairo_line_to (cr, waw, widget->allocation.height); + cairo_set_line_width (cr, 8.0); + cairo_set_source_rgb (cr, 0.8, 0.2, 0.2); + cairo_stroke (cr); + } else { //----- okay, here we go, draw the wave view per sample + gx_system::gx_print_info("Wave view expose", jcset->getIRFile()); + float *sig = new float[vecsize*2]; + pvInput = gx_sndfile::openInputSoundFile(jcset->getFullIRPath().c_str(), &chans, &sr, &length); + double dws = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->drawscale = ((double)waw)/length; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->filelength = length; + + switch (chans) { + //----- mono file + case 1: + cairo_set_line_width (cr, 1 + dws*0.5); + cairo_set_source_rgb (cr, 0.8, 0.8, 0.8); + + //cairo_move_to (cr, dws, wah); + while (counter < length-1) { + gx_sndfile::readSoundInput(pvInput, sig, vecsize); + counter += vecsize; + countfloat = vecsize; + sfsig = sig; + while (countfloat-- > 0) { + cairo_move_to (cr, countframe*dws, wah); + cairo_line_to (cr, countframe*dws, (1 + *sfsig++) * wah); + countframe++; + } + cairo_stroke (cr); + } + + /// close file desc. + gx_sndfile::closeSoundFile(pvInput); + break; + + //----- stereo file + case 2: { + wah = widget->allocation.height*0.75; + wah1 = widget->allocation.height*0.25; + + cairo_move_to (cr, 0, wah); + cairo_line_to (cr, waw, wah); + cairo_move_to (cr, 0, wah1); + cairo_line_to (cr, waw, wah1); + cairo_set_line_width (cr, 2.0); + cairo_set_source_rgb (cr, 0.3, 0.7, 0.3); + cairo_stroke (cr); + + int yval[] = { 50, 150 }; + cairo_set_line_width (cr, 1 + dws*0.5); + cairo_set_source_rgb (cr, 0.8, 0.8, 0.8); + + while (counter 0) { + for (int c = 0; c < 2; c++) { + cairo_move_to (cr, countframe*dws, yval[c]); + cairo_line_to (cr, countframe*dws, + *sfsig++ *wah1 + yval[c]); + /* if((c==0)&&(countfloat<=52)&&(countfloat>9)){ + outfile << cim <<*sfsig; + outfile << cim <<", "; + } */ + } + countframe++; + } + cairo_stroke (cr); + } + + //outfile.close(); + + gx_sndfile::closeSoundFile(pvInput); + // sf_close(pvInput); + break; + } + default: // do nothing + break; + } + delete[] sig; + } + // copy the surface to a packup surface for the selection + cr = cairo_create (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection); + cairo_set_source_surface (cr, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_file, 0,0); + cairo_paint (cr); + + + + //----- draw the selected part (offset length) with transparent green rectangle + if ((jcset->getOffset() != (guint)GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut) || + (jcset->getLength() != (guint)GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut)) + { + // -- IR offset + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut = + jcset->getOffset(); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut = + jcset->getLength(); + + jcset->setOffset(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut); + + if ((GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut < 0) || + (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut > + (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->filelength))) + { + jcset->setOffset(0); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut + += GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut = 0; + } + + // -- IR length (starting at offset) + jcset->setLength(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut); + if (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut > + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->filelength) + { + jcset->setLength(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->filelength - + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut = jcset->getLength(); + } + + // -- tooltips + ostringstream tip; + tip << "offset (" << jcset->getOffset() + << ") length (" << jcset->getLength() << ") "; + + gtk_widget_set_sensitive(widget, TRUE); + gtk_tooltips_set_tip (GTK_TOOLTIPS (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->comandline), + widget, tip.str().c_str(), "the offset and length."); + + cairo_set_source_rgba (cr, 0.5, 0.8, 0.5,0.3); + cairo_rectangle (cr, jcset->getOffset()*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->drawscale, 0, + jcset->getLength()*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->drawscale, widget->allocation.height); + cairo_fill (cr); + + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay = + jcset->getOffset()*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->drawscale; + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveleft = + jcset->getLength()*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->drawscale; + + } +// set scal range to the surface and the screen + gtk_widget_set_size_request (GTK_WIDGET(waveview), 300.0*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view*2, 200.0); + cairo_scale (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, 1); + // copy the surface to the screen + cairo_set_source_surface (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection, widget->allocation.x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, widget->allocation.y); + cairo_paint (cr_show); + // destroy surface handler + cairo_destroy (cr); + cairo_destroy (cr_show); + + return false; + +} + +//----- create and draw the widgets +static gboolean gtk_waveview_expose (GtkWidget *widget, GdkEventExpose *event) +{ + g_assert(GTK_IS_WAVEVIEW(widget)); + GtkWaveView *waveview = GTK_WAVEVIEW(widget); + + // ============= preview widget for JConv settings + if (waveview->waveview_type == kWvTypeJConv) + { + cairo_t *cr, *cr_show; + cr = cairo_create (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection); + cr_show = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + //----- create the background widget when opening a new file + if (gx_gui::new_wave_view == true) + { + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_move_to (cr, 0, 0); + cairo_rectangle (cr, 0, 0, 600, 200); + cairo_fill_preserve (cr); + cairo_set_source_rgba (cr, 0.8, 0.8, 0.2,0.6); + cairo_set_font_size (cr, 84.0); + cairo_move_to (cr, 120, 150); + cairo_show_text(cr, "loading"); + cairo_stroke (cr); + // paint the wave in a low prio idle thread + g_idle_add(gtk_waveview_paint,gpointer (widget)); + // done with new view: + gx_gui::new_wave_view = false; + } + // set scal range to the surface and the screen + gtk_widget_set_size_request (GTK_WIDGET(waveview), 300.0*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view*2, 200.0); + cairo_scale (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, 1); + // copy the surface to the screen + cairo_set_source_surface (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection, widget->allocation.x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, widget->allocation.y); + cairo_paint (cr_show); + // destroy surface handler + cairo_destroy (cr); + cairo_destroy (cr_show); + + } //----- end of the JConv IR file section, + + // ========================================================================================= + + // ============= Live Wave Draw section (oscilloscope) + else if (waveview->waveview_type == kWvTypeLive) + { + int liveviewx = widget->allocation.x; + int liveviewy = widget->allocation.y; + + liveviewx += (widget->allocation.width - GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_x) *0.5+10; + liveviewy += (widget->allocation.height - GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_y) *0.5+15; + + cairo_t*cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + + //----- create the background, done only once at oscilloscope init. + if (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->new_pig == 0) + { + cairo_pattern_t*pat = + cairo_pattern_create_radial (-130.4, -270.4, 1.6, -1.4, -4.4, 300.0); + + cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.2, 0.3, 1); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.05, 1); + cairo_set_source_rgb(cr, 0.05, 0.05, 0.05); + cairo_rectangle (cr, liveviewx, liveviewy, 280, 50); + cairo_set_source (cr, pat); + cairo_fill (cr); + cairo_pattern_destroy (pat); + + /* cairo_set_line_width (cr, 10.0); + cairo_set_source_rgba (cr, 0, 0, 0,0.4); + cairo_rectangle (cr, liveviewx-5, liveviewy-5, 286, 60); + cairo_stroke (cr); + + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgba (cr, 0.1, 0.1, 0.1,0.7); + cairo_rectangle (cr, liveviewx-6, liveviewy-6, 288, 62); + cairo_stroke (cr); + + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgba (cr, 0.5, 0.5, 0.5,0.1); + cairo_rectangle (cr, liveviewx-12, liveviewy-12, 302, 74); + cairo_rectangle (cr, liveviewx-2, liveviewy-2, 302, 54); + cairo_stroke (cr); */ + + cairo_set_line_width (cr, 1.5); + cairo_set_source_rgba (cr,0.2, 1.0, 0.2, 0.4); + cairo_move_to (cr, liveviewx, liveviewy+25); + cairo_line_to (cr, liveviewx+280, liveviewy+25); + cairo_stroke (cr); + + cairo_set_source_rgba (cr,0.2, 1.0, 0.2, 0.4); + cairo_rectangle (cr, liveviewx, liveviewy, 280.0, 50.0); + cairo_stroke (cr); + + int gitter = 0; + for (int i=0; i<28; i++) + { + gitter += 10; + cairo_move_to (cr, liveviewx+gitter-5, liveviewy); + cairo_line_to (cr, liveviewx+gitter-5, liveviewy+50); + } + + gitter = 0; + for (int i=0; i<5; i++) + { + gitter += 10; + cairo_move_to (cr, liveviewx, liveviewy+gitter-5); + cairo_line_to (cr, liveviewx+280, liveviewy+gitter-5); + } + + cairo_set_source_rgba (cr,0.2, 1.0, 0.2, 0.05); + cairo_stroke (cr); + gdk_pixbuf_get_from_drawable(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_image, + GDK_DRAWABLE(widget->window), gdk_colormap_get_system(), + liveviewx-1, liveviewy-1,0,0,282,52); + + + // done with background def. + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->new_pig = 1; + + } //controll pixmap ready + + //----- background created, now we just need to copy the pixbuffs every expose event to the widget + gdk_draw_pixbuf(GDK_DRAWABLE(widget->window), widget->style->fg_gc[0], + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_image, + 0,0,liveviewx-1, liveviewy-1 , 282, 52, GDK_RGB_DITHER_NORMAL, 0, 0); + + + //----- some maybe usfull infos about the jack server + // we can add more stuff here ? + const int frag = (const int)gx_jack::jack_bs; + const int dsp_load = round(gx_jack::jcpu_load); + ostringstream tir; + tir << " ht frames " << (gx_jack::time_is/100000); + + cairo_set_source_rgba (cr, 0.8, 0.8, 0.2,0.6); + cairo_set_font_size (cr, 8.0); + cairo_move_to (cr, liveviewx, liveviewy+48); + cairo_show_text(cr, tir.str().c_str()); + + tir.str(""); + tir << " latency " << frag ; + cairo_move_to (cr, liveviewx+210, liveviewy+10); + cairo_show_text(cr, tir.str().c_str()); + + tir.str(""); + if (gx_jack::is_rt == 1)tir << " RT mode yes "; + else + { + cairo_stroke_preserve (cr); + cairo_set_source_rgba (cr, 0.8, 0.1, 0.1,0.6); + tir << " RT mode NO "; + cairo_stroke_preserve (cr); + } + + cairo_move_to (cr, liveviewx+210, liveviewy+48); + cairo_show_text(cr, tir.str().c_str()); + + cairo_set_source_rgba (cr, 0.8, 0.8, 0.2,0.6); + tir.str(""); + tir << " dsp load " << dsp_load << " %"; + cairo_move_to (cr, liveviewx, liveviewy+10); + cairo_show_text(cr, tir.str().c_str()); + + cairo_stroke (cr); + + cairo_move_to (cr, liveviewx+280, liveviewy+25); + + float wave_go = 0; + float sc = 260.0/frag; + float sc1 = liveviewx+270-sc; + float sc2 = liveviewy+25; + //----- draw the frame + for (int i = 0; i < frag; i++) + { + float x_in = gx_engine::get_frame[i]; //FIXME get_frame correct??? + cairo_line_to (cr, sc1 - sc*i+1, + sc2 + double(x_in)*75.0); + wave_go = max(wave_go, abs(x_in)); + } + + //----- get the sample, for display the gain value + + float wave_db = log(fabs( wave_go))*6/log(2); + double xl = floor(exp(log(1.055)*2.1*wave_db)*150); + + if (xl > 125.0) xl = 125.0; + else if (xl < -125.0) xl = -125.0; + + cairo_set_line_width (cr, 1.0); + cairo_line_to (cr, liveviewx, liveviewy+25); + cairo_pattern_t* linpat = + cairo_pattern_create_linear (liveviewx, liveviewy-15,liveviewx, liveviewy+25); + + cairo_pattern_set_extend(linpat, CAIRO_EXTEND_REFLECT); + cairo_pattern_add_color_stop_rgba (linpat, 0.4, 1, 0.2, 0,0.8); + cairo_pattern_add_color_stop_rgba (linpat, 0.8, 0.2, 1, 0.2,0.8); + cairo_set_source (cr, linpat); + cairo_close_path (cr); + + cairo_fill_preserve (cr); + cairo_stroke (cr); + cairo_pattern_destroy (linpat); + + //----- draw the gain value + double dashes[] = {5.0, 1.0 }; + cairo_set_dash (cr, dashes, 2, -0.25); + cairo_move_to (cr, liveviewx+140-xl, liveviewy); + cairo_line_to (cr, liveviewx+140+xl, liveviewy); + cairo_move_to (cr, liveviewx+140-xl, liveviewy+50); + cairo_line_to (cr, liveviewx+140+xl, liveviewy+50); + //cairo_set_source_rgba (cr, redline, greenline, 0.2,0.8); + linpat = + cairo_pattern_create_linear (liveviewx, liveviewy,liveviewx+140, liveviewy); + + cairo_pattern_set_extend(linpat, CAIRO_EXTEND_REFLECT); + cairo_pattern_add_color_stop_rgba (linpat, 0.2, 1, 0.2, 0,0.8); + cairo_pattern_add_color_stop_rgba (linpat, 0.8, 0.2, 1, 0.2,0.8); + cairo_set_source (cr, linpat); + cairo_set_line_width (cr, 3.0); + cairo_stroke (cr); + cairo_destroy(cr); + + } + else if (waveview->waveview_type == kWvTypeTuner) + { + static int is_init = 0; + if (is_init == 0) + { + cairo_t *cr; + + double x0 = 0; + double y0 = 0; + double rect_width = 100; + double rect_height = 60; + + // paint tuner background picture only once + + cr = cairo_create(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_tuner); + + cairo_rectangle (cr, x0-1,y0-1,rect_width+2,rect_height+2); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width-10, rect_height, 20.0); + cairo_pattern_add_color_stop_rgb (pat, 0, 1, 1, 1); + cairo_pattern_add_color_stop_rgb (pat, 0.3, 0.4, 0.4, 0.4); + cairo_pattern_add_color_stop_rgb (pat, 0.6, 0.05, 0.05, 0.05); + cairo_pattern_add_color_stop_rgb (pat, 1, 0.0, 0.0, 0.0); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+2,y0+2,rect_width-3,rect_height-3); + cairo_fill (cr); + + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+98, y0+3); + cairo_line_to(cr, x0+98, y0+64); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+3, y0+64); + cairo_line_to(cr, x0+3, y0+3); + cairo_line_to(cr, x0+98, y0+3); + cairo_stroke(cr); + + pat = cairo_pattern_create_linear (x0+50, y0,x0, y0); + cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT); + cairo_pattern_add_color_stop_rgb (pat, 0, 0.1, 0.8, 0.1); + cairo_pattern_add_color_stop_rgb (pat, 1, 1, 0.1, 0.1); + cairo_set_source (cr, pat); + + double dashes[] = { + 0.0, /* ink */ + rect_height, /* skip */ + 10.0, /* ink */ + 10.0 /* skip*/ + }; + int ndash = sizeof (dashes)/sizeof(dashes[0]); + double offset = 100.0; + + cairo_set_dash (cr, dashes, ndash, offset); + cairo_set_line_width(cr, 3.0); + for (int i = -5;i<6;i++) { + cairo_move_to(cr,x0+50, y0+rect_height-5); + cairo_line_to(cr, (((i*0.08))*rect_width)+x0+50, y0+(((i*0.1*i*0.1))*30)+2); + } + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.1, 1, 0.1); + cairo_move_to(cr,x0+50, y0+rect_height-5); + cairo_line_to(cr, x0+50, y0+2); + cairo_stroke(cr); + cairo_destroy(cr); + is_init = 1; //TUNER BACKGROUND IMAGE IS FINISH + } + + char s[64]; + int vis = round(gx_engine::audio.fConsta1t); + int freq = round(gx_engine::midi.fConsta4); + int set = 0; + float scale = ((gx_engine::audio.fConsta1t-vis)-(-1.0))/(1.0-(-1.0)); + if ((scale <= 0.0) || (scale > 1.0)) scale = 0.0; + vis += 9; + static const char* note[] = {"C ","C#","D ","D#","E ","F ","F#","G ","G#","A ","A#","B "}; + if (gx_gui::shownote == 1) + { + if ((vis>=0)&&(vis<=11)) snprintf(s, 63, "%s", note[vis]); + else if ((vis>=-24)&&(vis<=-13)) snprintf(s, 63, "%s", note[vis+24]); + else if ((vis>=-12)&&(vis<=-1)) snprintf(s, 63, "%s", note[vis+12]); + else if ((vis>=12)&&(vis<=23)) snprintf(s, 63, "%s", note[vis-12]); + else if ((vis>=24)&&(vis<=35)) snprintf(s, 63,"%s", note[vis-24]); + else if ((vis>=36)&&(vis<=47)) snprintf(s, 63,"%s", note[vis-36]); + else + { + snprintf(s, 63, "%s", ""); + scale = 0.0; + freq = 0; + } + + if (freq>9999) + { + set = 20; + } + else if (freq > 999) + { + set = 15; + } + else if (freq > 99) + { + set = 10; + } + else if (freq > 9) + { + set = 5; + } + if ((scale >= 0.0) && (scale < 1.0)) + { + scale -= 0.5; + cairo_t *cr; + + double x0 = widget->allocation.x + (widget->allocation.width - 100) * 0.5; + double y0 = widget->allocation.y + (widget->allocation.height - 90) * 0.5; + double rect_width = 100; + double rect_height = 60; + + cr = gdk_cairo_create(widget->window); + cairo_rectangle (cr, x0,y0+60,rect_width+1,30); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 5.0); + cairo_move_to(cr,x0+2, y0+63); + cairo_line_to(cr, x0+99, y0+63); + cairo_stroke(cr); + + cairo_set_source_surface (cr, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_tuner,x0,y0); + cairo_paint (cr); + ostringstream tir; + tir << s; + cairo_set_source_rgba (cr, scale*scale*4, 1-(scale*scale*4), 0.2,1-(scale*scale*4)); + cairo_set_font_size (cr, 18.0); + cairo_move_to (cr,x0+50 -9 , y0+30 +9 ); + cairo_show_text(cr, tir.str().c_str()); + + tir.str(""); + tir << (freq) << " hz"; + + cairo_set_source_rgba (cr, 0.8, 0.8, 0.2,0.6); + cairo_set_font_size (cr, 8.0); + cairo_move_to (cr, x0+72-set, y0+58); + cairo_show_text(cr, tir.str().c_str()); + + + cairo_move_to(cr, x0+50, y0+rect_height-5); + static double dashe[] = { + 0, /* ink */ + 5, /* skip */ + rect_height-20, /* ink */ + 100.0 /* skip*/ + }; + cairo_set_dash (cr, dashe, 4, 0); + + cairo_set_source_rgb(cr, 0.5, 0.1, 0.1); + cairo_set_line_width(cr, 2.0); + cairo_arc (cr, x0+50, y0+rect_height-5, 2.0, 0, 2*M_PI); + cairo_move_to(cr,x0+50, y0+rect_height-5); + cairo_line_to(cr, (scale*2*rect_width)+x0+50, y0+(scale*scale*30)+2); + cairo_stroke(cr); + + cairo_destroy(cr); + } + } + + } + return TRUE; +} + +//----- a new wavefile is load to the jconv preview widget +gboolean GtkWaveView::gtk_waveview_set_value (GtkWidget *cwidget, gpointer data ) +{ + gx_gui::new_wave_view = true; + return TRUE; +} + +//----- refresh osiloscope when change rcstyle +gboolean GtkWaveView::gtk_waveview_refresh (GtkWidget *widget, gpointer data ) +{ + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->new_pig = 0; + return TRUE; +} + +//----- refresh osiloscope when change rcstyle +gboolean GtkWaveView::gtk_tuner_refresh (GtkWidget *widget, gpointer data ) +{ + if (widget->window) { + GdkRectangle rect = {int(widget->allocation.x + (widget->allocation.width - 100) * 0.5)+5, + int(widget->allocation.y + (widget->allocation.height - 90) * 0.5)+5,90,55}; + gdk_window_invalidate_rect(GDK_WINDOW(widget->window),&rect,TRUE); + } + return TRUE; +} + +//----- mouse funktions to select a part of the file +static gboolean gtk_waveview_pointer_motion (GtkWidget *widget, GdkEventMotion *event) +{ + g_assert(GTK_IS_WAVEVIEW(widget)); + GtkWaveView *waveview = GTK_WAVEVIEW(widget); + + gdk_event_request_motions (event); + // JConv IR file + if ((waveview->waveview_type == kWvTypeJConv)&&(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavebutton)) + { + // retrieve JConv settings handler + GxJConvSettings* const jcset = GxJConvSettings::instance(); + cairo_t *cr, *cr_show; + + cr = cairo_create (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection); + cr_show = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + + if (GTK_WIDGET_HAS_GRAB(widget)) + { + // copy the file surface to the selection surface for a new selection + cairo_set_source_surface (cr, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_file,0,0); + cairo_paint (cr); + cairo_set_source_rgba (cr, 0.5, 0.8, 0.5,0.3); + double event_x; + + switch (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavebutton) + { + case 1: // left mouse button is pressed and move to right + if (event->x>waveview->start_x) + { + cairo_rectangle (cr,round( waveview->start_x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view), 0, + round((event->x - waveview->start_x)/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view), widget->allocation.height); + cairo_fill (cr); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveleft = round((event->x - waveview->start_x)/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay = round(waveview->start_x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view); + } + else // left mouse button is pressed and move to left + { + cairo_rectangle (cr, round(waveview->start_x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view), 0, + round((event->x - waveview->start_x)/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view), widget->allocation.height); + cairo_fill (cr); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveleft = round((waveview->start_x - event->x)/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay = round(event->x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view); + } + break; + + case 2: // middle mouse button is pressed and move + event_x = round((event->x)/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view - (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveleft *0.5 )); + cairo_rectangle (cr, event_x, 0, + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveleft,widget->allocation.height); + cairo_fill (cr); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay = event_x; + break; + + case 3: // right mousbutton is pressed and move + if (event->x>GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay) + { + + cairo_rectangle (cr, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay, 0, + round((event->x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view)-GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay),widget->allocation.height); + cairo_fill (cr); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveleft = + round((event->x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view)-GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay); + } + break; + + default: // do nothing + break; + } + + // -- IR offset + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut = + round(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavestay/ + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->drawscale); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut = + round(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveleft/ + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->drawscale); + + jcset->setOffset(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut); + + if (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut < 0) + { + jcset->setOffset(0); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut + += GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut = 0; + } + + // -- IR length (starting at offset) + jcset->setLength(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut); + if (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut > + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->filelength) + { + jcset->setLength(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->filelength - + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut = jcset->getLength(); + } + + + } + // set scale range to the screen and copy suface to it + gtk_widget_set_size_request (GTK_WIDGET(waveview), 300.0*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view*2, 200.0); + cairo_scale (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, 1); + cairo_set_source_surface (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection, widget->allocation.x/GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, widget->allocation.y); + cairo_paint (cr_show); + + // set tooltip to the new offset/lengh + if (GTK_WIDGET_HAS_GRAB(widget)) + { + // -- tooltips + ostringstream tip; + tip << "offset (" << jcset->getOffset() + << ") length (" << jcset->getLength() << ") "; + + gtk_widget_set_sensitive(widget, TRUE); + gtk_tooltips_set_tip (GTK_TOOLTIPS (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->comandline), + widget, tip.str().c_str(), "the offset and length."); + } + + cairo_destroy (cr); + cairo_destroy (cr_show); + + + } + return FALSE; +} + +//-------- button press event +static gboolean gtk_waveview_button_press(GtkWidget *widget, GdkEventButton *event) +{ + g_assert(GTK_IS_WAVEVIEW(widget)); + GtkWaveView *waveview = GTK_WAVEVIEW(widget); + + gtk_widget_grab_focus(widget); + gtk_widget_grab_default(widget); + gtk_grab_add(widget); + + // ----------- JConv view + if (waveview->waveview_type == kWvTypeJConv) + { + // retrieve instance of jconv settings handler + GxJConvSettings* jcset = GxJConvSettings::instance(); + ostringstream tip; + + switch (event->button) + { + case 1: + waveview->start_x = event->x; + waveview->start_y = event->y; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavebutton = 1; + break; + + case 2: + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavebutton = 2; + break; + + case 3: // scale the surface to screen + cairo_t *cr, *cr_show; + + cr = cairo_create (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection); + cairo_set_source_surface (cr, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_file,0,0); + cairo_paint (cr); + cr_show = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + gtk_widget_set_size_request (GTK_WIDGET(waveview), 300.0*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view*2, 200.0); + cairo_scale (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, 1); + cairo_set_source_surface (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection, widget->allocation.x, widget->allocation.y); + cairo_paint (cr_show); + + + + cairo_destroy (cr); + cairo_destroy (cr_show); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->offset_cut = 0; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->length_cut = 0; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavebutton = 3; + + jcset->setOffset(0); + jcset->setLength(0); + + tip << "offset (" << jcset->getOffset() + << ") length (" << jcset->getLength() << ") "; + + gtk_widget_set_sensitive(widget, TRUE); + gtk_tooltips_set_tip (GTK_TOOLTIPS (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->comandline), + widget, tip.str().c_str(), "the offset and length."); + break; + + default: // do nothing + break; + } + } + + return TRUE; +} + +static gboolean gtk_waveview_button_release (GtkWidget *widget, GdkEventButton *event) +{ + g_assert(GTK_IS_WAVEVIEW(widget)); + + if (GTK_WIDGET_HAS_GRAB(widget)) + gtk_grab_remove(widget); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->wavebutton=0; + + return FALSE; +} + +//----------- set value from mouseweel +static gboolean gtk_waveview_scroll (GtkWidget *widget, GdkEventScroll *event) +{ + g_assert(GTK_IS_WAVEVIEW(widget)); + GtkWaveView *waveview = GTK_WAVEVIEW(widget); + + if (waveview->waveview_type == kWvTypeJConv) + { + double setscale; + + if (event->direction == 0) setscale = -0.1; + else setscale = 0.1; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view += setscale; + if (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view <0.5) + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view = 0.5; + else if (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view >10) + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view = 10; + + cairo_t *cr, *cr_show; + + cr = cairo_create (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection); + + cr_show = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + gtk_widget_set_size_request (GTK_WIDGET(waveview), 300.0*GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view*2, 200.0); + cairo_scale (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->scale_view, 1); + cairo_set_source_surface (cr_show, GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_selection, widget->allocation.x, widget->allocation.y); + cairo_paint (cr_show); + + + + cairo_destroy (cr); + cairo_destroy (cr_show); + } + + return FALSE; +} + +//----------- set size for GdkDrawable per type +static void gtk_waveview_size_request (GtkWidget *widget, GtkRequisition *requisition) +{ + g_assert(GTK_IS_WAVEVIEW(widget)); + GtkWaveView *waveview = GTK_WAVEVIEW(widget); + + if (waveview->waveview_type == kWvTypeJConv) + { + requisition->width = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveview_x; + requisition->height = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveview_y; + } + else if (waveview->waveview_type == kWvTypeLive) + { + requisition->width = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_x; + requisition->height = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_y; + } + else if (waveview->waveview_type == kWvTypeTuner) + { + requisition->width = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->tunerview_x; + requisition->height = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->tunerview_y; + } +} + +//----------- init the GtkWaveViewClass +static void gtk_waveview_class_init (GtkWaveViewClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); + + klass->waveview_x = 300; + klass->waveview_y = 200; + klass->liveview_x = 300; + klass->liveview_y = 80; + klass->tunerview_x = 102; + klass->tunerview_y = 92; + klass->scale_view = 0.5; + + widget_class->expose_event = gtk_waveview_expose; + widget_class->size_request = gtk_waveview_size_request; + widget_class->button_press_event = gtk_waveview_button_press; + widget_class->button_release_event = gtk_waveview_button_release; + widget_class->motion_notify_event = gtk_waveview_pointer_motion; + widget_class->scroll_event = gtk_waveview_scroll; + + klass->surface_file = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, klass->waveview_x*2, klass->waveview_y); + g_assert(klass->surface_file != NULL); + klass->surface_selection = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, klass->waveview_x*2, klass->waveview_y); + g_assert(klass->surface_selection != NULL); + + klass->liveview_image = gdk_pixbuf_new(GDK_COLORSPACE_RGB,FALSE,8,282,52); + g_assert(klass->liveview_image != NULL); + + klass->surface_tuner = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, klass->tunerview_x, klass->tunerview_y); + g_assert(klass->surface_tuner != NULL); +} + +//----------- init the WaveView type +static void gtk_waveview_init (GtkWaveView *waveview) +{ + GtkWidget *widget = GTK_WIDGET(waveview); + + + if (waveview->waveview_type == kWvTypeJConv) + { + GTK_WIDGET_SET_FLAGS (GTK_WIDGET(waveview), GTK_CAN_FOCUS); + GTK_WIDGET_SET_FLAGS (GTK_WIDGET(waveview), GTK_CAN_DEFAULT); + widget->requisition.width = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveview_x; + widget->requisition.height = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->waveview_y; + } + else if (waveview->waveview_type == kWvTypeLive) + { + widget->requisition.width = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_x; + widget->requisition.height = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_y; + } + else if (waveview->waveview_type == kWvTypeTuner) + { + widget->requisition.width = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->tunerview_x; + widget->requisition.height = GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->tunerview_y; + } +} + +//----------- redraw when value changed +static gboolean gtk_waveview_value_changed(gpointer obj) +{ + GtkWidget *widget = (GtkWidget *)obj; + // gtk_widget_queue_draw(widget); + if(GDK_IS_WINDOW(widget->window)) + gdk_window_invalidate_rect(GDK_WINDOW(widget->window),NULL,TRUE); + return FALSE; +} + +void GtkWaveView::gtk_waveview_destroy (GtkWidget *weidget, gpointer data ) +{ + GtkWidget *widget = GTK_WIDGET( g_object_new (GTK_TYPE_WAVEVIEW, NULL )); + g_assert(GTK_IS_WAVEVIEW(widget)); + + if (G_IS_OBJECT(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))-> surface_file)) + cairo_surface_destroy(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))-> surface_file); + + if (G_IS_OBJECT(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))-> surface_selection)) + cairo_surface_destroy(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))-> surface_selection); + + if (G_IS_OBJECT(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))-> liveview_image)) + g_object_unref(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->liveview_image); + + if (G_IS_OBJECT(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))-> surface_tuner)) + g_object_unref(GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->surface_tuner); + +} + +//----------- create waveview widget +GtkWidget* GtkWaveView::gtk_wave_view() +{ + GtkWidget* widget = GTK_WIDGET( g_object_new (GTK_TYPE_WAVEVIEW, NULL )); + GtkWaveView *waveview = GTK_WAVEVIEW(widget); + + gx_gui::new_wave_view = false; + waveview->waveview_type = kWvTypeJConv; + + // retrieve JConv settings + GxJConvSettings* jcset = GxJConvSettings::instance(); + + ostringstream tip; + tip << "offset (" << jcset->getOffset() << ") " + << "length (" << jcset->getLength() << ") "; + + gtk_widget_set_sensitive(widget, TRUE); + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->comandline = + gtk_tooltips_new (); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->comandline), + widget, tip.str().c_str(), "the IR offset and length."); + + return widget; +} + +//----------- create live waveview widget +GtkWidget* GtkWaveView::gtk_wave_live_view(float* outfloat, float* infloat,GtkAdjustment *_adjustment) +{ + GtkWidget* widget = GTK_WIDGET( g_object_new (GTK_TYPE_WAVEVIEW, NULL )); + GtkWaveView* waveview = GTK_WAVEVIEW(widget); + + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->live_view = outfloat; + GTK_WAVEVIEW_CLASS(GTK_OBJECT_GET_CLASS(widget))->live_viewin = infloat; + + waveview->waveview_type = kWvTypeLive; + if (widget) + { + gtk_range_set_adjustment(GTK_RANGE(widget), _adjustment); + g_signal_connect(GTK_OBJECT(widget), "value-changed", + G_CALLBACK(gtk_waveview_value_changed), widget); + } + return widget; +} + +//----------- create live waveview widget +GtkWidget* GtkWaveView::gtk_tuner_view() +{ + GtkWidget* widget = GTK_WIDGET( g_object_new (GTK_TYPE_WAVEVIEW, NULL )); + GtkWaveView* waveview = GTK_WAVEVIEW(widget); + + waveview->waveview_type = kWvTypeTuner; + + return widget; +} + +//----------- get the WaveView type +GType gtk_waveview_get_type (void) +{ + static GType kn_type = 0; + if (!kn_type) + { + static const GTypeInfo kn_info = + { + sizeof(GtkWaveViewClass), NULL, NULL, + (GClassInitFunc)gtk_waveview_class_init, NULL, NULL, + sizeof (GtkWaveView), 0, (GInstanceInitFunc)gtk_waveview_init + }; + kn_type = g_type_register_static(GTK_TYPE_RANGE, + "GtkWaveView", &kn_info, (GTypeFlags)0); + } + return kn_type; +} + +//----------- wrapper for signal connection +void gx_waveview_set_value(GtkWidget* widget, gpointer data) +{ + + GtkWaveView wave_view; + wave_view.gtk_waveview_set_value(widget, data); +} + +//---- +void gx_waveview_destroy(GtkWidget* widget, gpointer data) +{ + + GtkWaveView wave_view; + wave_view.gtk_waveview_destroy(widget, data); +} + +//---- +void gx_waveview_refresh(GtkWidget* widget, gpointer data) +{ + + GtkWaveView wave_view; + wave_view.gtk_waveview_refresh(widget, data); +} + +//---- +void gx_tuner_refresh(GtkWidget* widget, gpointer data) +{ + + GtkWaveView wave_view; + wave_view.gtk_tuner_refresh(widget, data); +} + +//---- +GtkWidget* gx_wave_view() +{ + GtkWaveView wave_view; + return wave_view.gtk_wave_view(); +} + +//---- +GtkWidget* gx_tuner_view() +{ + GtkWaveView wave_view; + return wave_view.gtk_tuner_view(); +} +//---- +GtkWidget* gx_wave_live_view(float* outfloat, float* infloat, GtkAdjustment* _adjustment) +{ + GtkWaveView wave_view; + return wave_view.gtk_wave_live_view(outfloat, infloat, _adjustment); +} diff --git a/src/faust/AntiAlias.dsp b/src/faust/AntiAlias.dsp new file mode 100644 index 0000000..e82add6 --- /dev/null +++ b/src/faust/AntiAlias.dsp @@ -0,0 +1,4 @@ +import("guitarix.lib"); + +faas1 = vgroup("anti_aliase", vslider("feedback[name:Feedback]", 0.3, 0.3, 0.9, 0.01)); +process = add_dc : +~_''*faas1; diff --git a/src/faust/Exp.dsp b/src/faust/Exp.dsp new file mode 100644 index 0000000..ff8d793 --- /dev/null +++ b/src/faust/Exp.dsp @@ -0,0 +1,68 @@ +import("music.lib"); +import("filter.lib"); +import("effect.lib"); +import("guitarix.lib"); + +/**************************************************************** + ** unused + */ + +/* +distort(x) = x : *(pregain) : (+ : flt : BP(vtu) : flt) ~ *(back) : gain with +{ + back = vslider("FB",0.95,0.6,0.99,0.001); + mapper(v) = 1 - 19.7 * v * v; + flt(x) = +(x - x') ~ *(mapper(vslider("FreqT", 1250, 200, 3000, 1)/SR)); + vtu(x) = valve.vtu_(dist, q, g, x); + g = vslider("Duty", 0, -1.0, 1.0, 0.01) : *(1-log(2)) : +(1); + q = vslider("Qual", 0.5, 0, 1, 0.01)*1.75 - 1.04 : pow(_, 9); + dist = pow(10, 4*(vslider("Dist", 0.5, 0, 1, 0.01))); + pregain = 0.7*sqrt(1-back); + gain = BP(*(0.4/(vtu(0.2)-vtu(-0.2)))); +}; +*/ + +/* +process = hgroup("Tube [option : detachable]", BP( + hgroup("1 Amp",distort) : + vgroup("2 Highpass",BP(highpass1(fch))) : + vgroup("3 Lowpass",BP(lowpass1(fcl))) + )) with +{ + fch = vslider("freq",130,50,200,1); + fcl = vslider("freq",200,1400,8000,10); +}; +*/ + +/* +process = hgroup("2 Tube", + hgroup("1a Distortion", BP(vtu)): + hgroup("1b Distortion", BP(vtu)): + hgroup("1c Distortion", BP(vtu)): + hgroup("1d Distortion", BP(vtu)): + hgroup("2 Highpass",BP(highpass2(fch))) : + hgroup("3 Lowpass",BP(lowpass1(fcl))) + ) with +{ + vtu = valve.vtu(dist, q, g) : *(0.1/(valve.vtu(dist, q, g, 0.05)-valve.vtu(dist, q, g, -0.05))); + dist = pow(10, 4*vslider("dist", 0.5, 0, 1, 0.01)); + q = vslider("qual", 0.5, 0, 1, 0.01) : -(0.9) : /(10); + g = vslider("duty", 0, -1.0, 1.0, 0.01) : *(1-log(2)) : +(1); + fch = vslider("freq",130,50,200,1); + fcl = vslider("freq",200,1400,8000,10); +}; +*/ + +// envelope meter for insertion +// the log10 function might be slow, with execution +// time depending on input +meter = _ <: (graph*1e-50,_) :> _ with { + t = 0.05; + g = exp(-1/(SR*t)); + env = abs : *(1-g) : + ~ *(g); + graph = env : 20*log10 : clip(-20,20) : vbargraph("ENV",-20,20); +}; + +wet_dry = vslider("wet_dry[name:wet/dry]", 0, -1, 1, 0.1); + +process = hgroup("test", hgroup("tremolo",wet_dry_mix(wet_dry, BP(component("tremolo.dsp"))))); diff --git a/src/faust/ExpFilter.dsp b/src/faust/ExpFilter.dsp new file mode 100644 index 0000000..9c1aabc --- /dev/null +++ b/src/faust/ExpFilter.dsp @@ -0,0 +1,29 @@ +import("music.lib"); +import("filter.lib"); +import("guitarix.lib"); + +filter = tf2(b0,b1,b2,a1,a2) with +{ + c = 1.059; + R = 0.9221; + lc0 = 0.00506158; + lc1 = 0.06446806; + lc2 = 0.27547621; + lc3 = 0.43359433; + lc4 = 1.31282248; + lc5 = 0.07238887; + fc = vslider("Freq",1200,300,3000,5) : *(2*PI/SR) : log; + p = lc0*pow(fc,5) + lc1*pow(fc,4) + lc2*pow(fc,3) + lc3*pow(fc,2) + lc4*fc + lc5 : exp; + //b0 = 1; + //b1 = -1.01; + //b2 = 0; + //a1 = -1.84; + //a2 = 0.846416; + b0 = 1; + b1 = -c; + b2 = 0; + a1 = -2*R*cos(p); + a2 = R*R; +}; + +process = hgroup("1 Filter",BP(filter : *(db2linear(-10)))); diff --git a/src/faust/HighShelf.dsp b/src/faust/HighShelf.dsp new file mode 100644 index 0000000..e85643d --- /dev/null +++ b/src/faust/HighShelf.dsp @@ -0,0 +1,13 @@ +import("maxmsp.lib"); +import("guitarix.lib"); + +declare name "HighShelf"; + +hs(x) = highShelf(x,F,G,Q) +with { + G = -20.; + F = SR/2 -100.; + Q = 100.; +}; + +process = +(anti_denormal_ac) : hs; diff --git a/src/faust/amp2.dsp b/src/faust/amp2.dsp new file mode 100644 index 0000000..3e37380 --- /dev/null +++ b/src/faust/amp2.dsp @@ -0,0 +1,33 @@ +import("music.lib"); +import("filter.lib"); +import("effect.lib"); +import("guitarix.lib"); + + +/**************************************************************** + ** Tube Preamp Emulation stage 1 - 2 + */ + + +tubestage(tb,fck,Rk) = tube : hpf with { + lpfk = lowpass1(fck); + Ftube = ffunction(float Ftube(int,float), "valve.h", ""); + vplus = 250.0; + divider = 40; + Rp = 100.0e3; + tube = (+ : Ftube(tb)) ~ (-(vplus) : *(Rk/Rp) : lpfk) : /(divider); + hpf = highpass1(31.0); +}; + +process = hgroup("amp2", hgroup("preamp",(BP(preamp))) : + hgroup("stage1", BP(stage1)) : + hgroup("stage2", BP(stage2)) + ) with { + preamp = *(vslider("Pregain",30,-10,80,0.1):db2linear : smoothi(0.999)); + stage1 = tubestage(0,86.0,2700.0) : *(gain1) with { + gain1 = vslider("gain1", 6, -10.0, 20.0, 0.1) : db2linear : smoothi(0.999); + }; + stage2 = lowpass1(6531.0) : tubestage(1,132.0,1500.0) : *(gain2) with { + gain2 = vslider("gain2", 6, -10.0, 20.0, 0.1) : db2linear : smoothi(0.999); + }; +}; diff --git a/src/faust/autowah.dsp b/src/faust/autowah.dsp new file mode 100644 index 0000000..f7278ed --- /dev/null +++ b/src/faust/autowah.dsp @@ -0,0 +1,16 @@ +//----------------------------------------------- +// Auto-Wah +//----------------------------------------------- + +import("effect.lib"); //for crybaby definition + +a = 20 * vslider(".crybaby.wah[alias]", 0, 0, 1, 0.01); + +Sum(n,x) = +(x - (x @ n)) ~_ ; + +Average(n,x) = x * (1<<22) : int : abs : Sum(n) : float : /(1<<22) + : /(n); + +Map(x) = x * a : max(0) : min(1) ; + +process(x) = x : crybaby(x : Average(1000) : Map) ; diff --git a/src/faust/balance.dsp b/src/faust/balance.dsp new file mode 100644 index 0000000..22b70a3 --- /dev/null +++ b/src/faust/balance.dsp @@ -0,0 +1,5 @@ +import("guitarix.lib"); + +bal = vslider(".amp.balance[name:Balance]", 0, -1, 1, 0.1); + +process = balance(bal); diff --git a/src/faust/balance1.dsp b/src/faust/balance1.dsp new file mode 100644 index 0000000..6b4f91c --- /dev/null +++ b/src/faust/balance1.dsp @@ -0,0 +1,5 @@ +import("guitarix.lib"); + +bal = vslider(".amp.balance[name:Balance][alias]", 0, -1, 1, 0.1); + +process = _ <: balance(bal); diff --git a/src/faust/bassbooster.dsp b/src/faust/bassbooster.dsp new file mode 100644 index 0000000..313856e --- /dev/null +++ b/src/faust/bassbooster.dsp @@ -0,0 +1,23 @@ +import("filter.lib"); + +//------------------------------------------------------------------ +// DAFX, Digital Audio Effects (Wiley ed.) +// chapter 2 : filters +// section 2.3 : Equalizers +// page 53 : second order shelving filter design +//------------------------------------------------------------------ + +lfboost(F,G) = tf2(b0,b1,b2,a0,a1) +with { + V = db2linear(G); + K = tan(PI*F/SR); + D = 1 + sqrt(2)*K + K*K; + + b0 = (1 + sqrt(2*V)*K + V*K*K) / D; + b1 = 2 * (V*K*K - 1) / D; + b2 = (1 - sqrt(2*V)*K + V*K*K) / D; + a0 = 2 * (K*K - 1) / D; + a1 = (1 - sqrt(2)*K + K*K) / D; +}; + +process = lfboost(120, 10); diff --git a/src/faust/biquad.dsp b/src/faust/biquad.dsp new file mode 100644 index 0000000..f2dac9e --- /dev/null +++ b/src/faust/biquad.dsp @@ -0,0 +1,29 @@ +import("music.lib"); +import("filter.lib"); +import("guitarix.lib"); + +filter = tf2(b0,b1,b2,a1,a2) with +{ + c = 1.059; + R = 0.9221; + lc0 = 0.00506158; + lc1 = 0.06446806; + lc2 = 0.27547621; + lc3 = 0.43359433; + lc4 = 1.31282248; + lc5 = 0.07238887; + fc = vslider("Freq",1200,300,3000,5) : *(2*PI/SR) : log; + p = lc0*pow(fc,5) + lc1*pow(fc,4) + lc2*pow(fc,3) + lc3*pow(fc,2) + lc4*fc + lc5 : exp; + //b0 = 1; + //b1 = -1.01; + //b2 = 0; + //a1 = -1.84; + //a2 = 0.846416; + b0 = 1; + b1 = -c; + b2 = 0; + a1 = -2*R*cos(p); + a2 = R*R; +}; + +process = filter : *(db2linear(-10)); diff --git a/src/faust/chorus.dsp b/src/faust/chorus.dsp new file mode 100644 index 0000000..95cde66 --- /dev/null +++ b/src/faust/chorus.dsp @@ -0,0 +1,35 @@ + +/* Stereo chorus. */ + +// declare name "chorus -- stereo chorus effect"; +declare author "Albert Graef"; +declare version "1.0"; + +import("music.lib"); + +level = hslider("level", 0.5, 0, 1, 0.01); +freq = hslider("freq", 3, 0, 10, 0.01); +dtime = hslider("delay", 0.02, 0, 0.2, 0.01); +depth = hslider("depth", 0.02, 0, 1, 0.01); + +tblosc(n,f,freq,mod) = (1-d)*rdtable(n,waveform,i&(n-1)) + + d*rdtable(n,waveform,(i+1)&(n-1)) +with { + waveform = time*(2.0*PI)/n : f; + phase = freq/SR : (+ : decimal) ~ _; + modphase = decimal(phase+mod/(2*PI))*n; + i = int(floor(modphase)); + d = decimal(modphase); +}; + +chorus(dtime,freq,depth,phase,x) + = x+level*fdelay(1<<16, t, x) +with { + t = SR*dtime/2*(1+depth*tblosc(1<<16, sin, freq, phase)); +}; + +process = vgroup("chorus", (left, right)) +with { + left = chorus(dtime,freq,depth,0); + right = chorus(dtime,freq,depth,PI/2); +}; diff --git a/src/faust/compressor.dsp b/src/faust/compressor.dsp new file mode 100644 index 0000000..4c546e9 --- /dev/null +++ b/src/faust/compressor.dsp @@ -0,0 +1,78 @@ + +/* Compressor unit. */ + +//declare name "compressor -- compressor/limiter unit"; +declare author "Albert Graef"; +declare version "1.0"; + +import("music.lib"); +import("guitarix.lib"); + +/* Controls. */ + +// partition the controls into these three groups +comp_group(x) = hgroup("1-compression", x); +env_group(x) = vgroup("2-envelop", x); +gain_group(x) = vgroup("3-gain", x); + +// compressor controls: ratio, threshold and knee size +ratio = nentry("ratio", 2, 1, 20, 0.1); +threshold = nentry("threshold", -20, -96, 10, 0.1); +knee = nentry("knee", 3, 0, 20, 0.1); + +// attack and release controls; clamped to a minimum of 1 sample +attack = hslider("attack", 0.002, 0, 1, 0.001) : max(1/SR); +release = hslider("release", 0.5, 0, 10, 0.01) : max(1/SR); + +// gain controls: make-up gain, compression gain meter +makeup_gain = gain_group(hslider("makeup gain", 0, -96, 96, 0.1)); +gain(x) = attach(x, x : gain_group(hbargraph("gain", -96, 0))); + + + +t = 0.1; +g = exp(-1/(SR*t)); +env = abs : *(1-g) : + ~ *(g); +rms = sqr : *(1-g) : + ~ *(g) : sqrt; +sqr(x) = x*x; + +/* Compute the envelop of a stereo signal. Replace env with rms if you want to + use the RMS value instead. */ + +//env2(x,y) = max(env(x),env(y)); +env2(x) = max(env(x)); + +/* Compute the compression factor for the current input level. The gain is + always 0 dB if we're below the reduced threshold, threshold-knee. Beyond + the real threshold value the level is scaled by 1/ratio. Between these two + extremes we return a convex combination of those factors. This is also + known as "soft-knee" compression: the compression kicks in gradually at + threshold-knee and reaches its full value at threshold. For special + effects, you can also achieve old-school "hard-knee" compression by setting + the knee value to zero. Also note that, before computing the gain, the + input level is first smoothed out using a 1 pole IIR to prevent clicks when + the input level changes abruptly. The attack and release times of this + filter are configured with the corresponding envelop controls of the + compressor. */ + +compress(env) = level*(1-r)/r +with { + // the (filtered) input level above the threshold + level = env : h ~ _ : linear2db : (_-threshold+knee) : max(0) + with { + h(x,y) = f*x+(1-f)*y with { f = (x=y)*gr; }; + ga = exp(-1/(SR*attack)); + gr = exp(-1/(SR*release)); + }; + // the knee factor, clamped to 0..1; we add a small perturbation in + // the denominator to prevent infinities and nan when knee<<1 + p = level/(knee+eps) : max(0) : min(1) with { eps = 0.001; }; + // the actual compression ratio + r = 1-p+p*ratio; +}; + +process(x) = g(x)*x +with { + //g = env2(x) : compress : gain : +(makeup_gain) : db2linear ; + g = add_dc : env : compress : db2linear ; +}; diff --git a/src/faust/crybaby.dsp b/src/faust/crybaby.dsp new file mode 100644 index 0000000..dfe5554 --- /dev/null +++ b/src/faust/crybaby.dsp @@ -0,0 +1,27 @@ +import("effect.lib"); +import("guitarix.lib"); + +_crybaby(wah) = *(gs(s)) : tf2(1,-1*0.996,0,a1s(s)*0.996,a2s(s)*0.996) +with { + s = 0.999; // smoothing parameter (one-pole pole location) + Q = pow(2.0,(2.0*(1.0-wah)+1.0)); // Resonance "quality factor" + fr = 450.0*pow(2.0,2.3*wah); // Resonance tuning + g = 0.1*pow(4.0,wah); // gain (optional) + + // Biquad fit using z = exp(s T) ~ 1 + sT for low frequencies: + frn = fr/SR; // Normalized pole frequency (cycles per sample) + R = 1 - PI*frn/Q; // pole radius + theta = 2*PI*frn; // pole angle + a1 = 0-2.0*R*cos(theta); // biquad coeff + a2 = R*R; // biquad coeff + + // dezippering of slider-driven signals: + a1s(s) = a1 : smooth(s); + a2s(s) = a2 : smooth(s); + gs(s) = g : smooth(s); +}; + +level = vslider("level", 0.1, 0, 1, 0.01); +wah = vslider("wah", 0, 0, 1, 0.01); +wet_dry = vslider("wet_dry[name:wet/dry]", 0, -1, 1, 0.1); +process = wet_dry_mix(wet_dry, *(level) : _crybaby(wah)); diff --git a/src/faust/delay.dsp b/src/faust/delay.dsp new file mode 100644 index 0000000..8e8455a --- /dev/null +++ b/src/faust/delay.dsp @@ -0,0 +1,7 @@ +import("music.lib"); +import("guitarix.lib"); +msec = SR/1000.0; +gain = vslider("gain", 0, -20, 20, 0.1) : db2linear : smoothi(0.999); +d = vslider("delay", 0, 0, 5000, 10)*msec; +process = _ <: _ + gain * fdelay43s(d) :> _; +//FIXME: fdelay only for needed time diff --git a/src/faust/distortion.dsp b/src/faust/distortion.dsp new file mode 100644 index 0000000..d134d24 --- /dev/null +++ b/src/faust/distortion.dsp @@ -0,0 +1,83 @@ +//declare name "distortion"; +declare version "0.01"; +declare author "brummer"; +declare license "BSD"; +declare copyright "(c)brummer 2008"; + +import("math.lib"); +import("music.lib"); +import("effect.lib"); +import("filter.lib"); +import("guitarix.lib"); +import("maxmsp.lib"); + +F = nentry("split_low_freq", 250, 20, 600, 10); +F1 = nentry("split_high_freq", 650, 600, 1250, 10); + +high_s(x) = highShelf(x,F1,G,Q) +with { + G = -24.; + Q = 1.; +}; + +low_s(x) = lowShelf(x,F,G,Q) +with { + G = -24.; + Q = 1.; +}; + +middle_high_s(x) = highShelf(x,F1,G,Q) +with { + G = -24.; + Q = 1.; +}; + +middle_low_s(x) = lowShelf(x,F,G,Q) +with { + G = -24.; + Q = 1.; +}; + +//----------distortion--------- + +//-speaker emulation +sbp1 = vslider("low_freq[name:low freq][tooltip:low-freq cutoff Hz]",130,20,1000,10); +sbp2 = vslider("high_freq[name:high freq][tooltip:high-freq cutoff Hz]",5000,1000,12000,10); +switch1 = checkbox("on_off[name:low highcutoff]"); +sbp = hgroup("low_highcutoff", bypass(switch1, +(anti_denormal_ac) : speakerbp(sbp1,sbp2))); + +//-low and highpass +lowpassfreq = nentry("low_freq[name:low freq]", 5000, 20, 12000, 10); +highpassfreq = nentry("high_freq[name:high freq]", 130, 20, 7040, 10); +switch = checkbox("on_off[name:low highpass]"); +passo = +(anti_denormal_ac) : lowpass1(lowpassfreq) : highpass1(highpassfreq); +pass = hgroup("low_highpass", bypass(switch, passo)); + +//-distortion +drivelevel = vslider("level", 0.01, 0, 0.5, 0.01); +drivegain1 = vslider("gain", 2, -10, 10, 0.1)-10 : db2linear : smoothi(0.999); +low_gain = vslider("low_gain", 10, -10, 20, 0.1)-10 : db2linear : smoothi(0.999); +high_gain = vslider("high_gain", 10, -10, 20, 0.1)-10 : db2linear : smoothi(0.999); +middle_gain = vslider("middle_gain", 10, -10, 20, 0.1)-10 : db2linear : smoothi(0.999); +drive = vslider("drive", 0.64, 0, 1, 0.01); +drive1 = vslider("low_drive", 1, 0, 1, 0.01)*drive; +drive2 = vslider("high_drive", 1, 0, 1, 0.01)*drive; +drive3 = vslider("middle_drive", 1, 0, 1, 0.01)*drive; +distortion1 = high_s : cubicnl(drive1,drivelevel): *(low_gain); +distortion2 = low_s : cubicnl(drive2,drivelevel) : *(high_gain); +distortion3 = middle_low_s :middle_high_s : cubicnl(drive3,drivelevel) : *(middle_gain); +distortion(x) = distortion1(x) + distortion2(x) + distortion3(x) ; + + +//-resonator +resonator = (+ <: (delay(4096, d-1) + delay(4096, d)) / 2) ~ *(1.0-a) +with { + d = vslider("vibrato", 1, 0, 1, 0.01); + a = vslider("trigger", 0.12, 0, 1, 0.01); +}; + +switch2 = checkbox("resonator.on_off[name:resonat]"); +//reso = hgroup("resonator", bypass(switch2, resonator)); + +hs = component("HighShelf.dsp").hs; +process = bypass(switch2, resonator) : +(anti_denormal_ac) : pass : sbp : hs : distortion : *(drivegain1) : hs : sbp; diff --git a/src/faust/distortion1.dsp b/src/faust/distortion1.dsp new file mode 100644 index 0000000..40510eb --- /dev/null +++ b/src/faust/distortion1.dsp @@ -0,0 +1,42 @@ +declare name "distortion1"; +declare version "0.01"; +declare author "brummer"; +declare license "BSD"; +declare copyright "(c)brummer 2008"; + +import("math.lib"); +import("music.lib"); +import("effect.lib"); +import("filter.lib"); +import("guitarix.lib"); + +//----------distortion--------- + +//-speaker emulation +sbp1 = vslider("low_freq[name:low freq][tooltip:low-freq cutoff Hz]",130,20,1000,10); +sbp2 = vslider("high_freq[name:high freq][tooltip:high-freq cutoff Hz]",5000,1000,12000,10); +switch1 = checkbox("on_off[name:low highcutoff]"); +sbp = hgroup("low_highcutoff", bypass(switch1, +(anti_denormal_ac) : speakerbp(sbp1,sbp2))); + +//-low and highpass +lowpassfreq = nentry("low_freq[name:low freq]", 5000, 20, 12000, 10); +highpassfreq = nentry("high_freq[name:high freq]", 130, 20, 7040, 10); +switch = checkbox("on_off[name:low highpass]"); +passo = +(anti_denormal_ac) : lowpass1(lowpassfreq) : highpass1(highpassfreq ); +pass = hgroup("low_highpass", bypass(switch, passo)); + +//-distortion +drivelevel = vslider("level", 0.01, 0, 0.5, 0.01); +drivegain1 = vslider("gain", 2, -10, 10, 0.1)-10 : db2linear : smoothi(0.999); +drive = vslider("drive", 0.64, 0, 1, 0.01); +distortion = cubicnl(drive,drivelevel); + +//-resonator +switch2 = checkbox("resonator.on_off[name:resonat]"); +resonator = (+ <: (delay(4096, d-1) + delay(4096, d)) / 2) ~ *(1.0-a) +with { + d = vslider("vibrato", 1, 0, 1, 0.01); + a = vslider("trigger", 0.12, 0, 1, 0.01); +}; + +process = bypass(switch2, resonator) : +(anti_denormal_ac) : pass : add_dc : sbp : component("HighShelf.dsp").hs : distortion : *(drivegain1) : component("HighShelf.dsp").hs : sbp; diff --git a/src/faust/drive.dsp b/src/faust/drive.dsp new file mode 100644 index 0000000..7fb14b6 --- /dev/null +++ b/src/faust/drive.dsp @@ -0,0 +1,9 @@ +import("guitarix.lib"); + +fuzzy = vslider("value[name:drive]", 1, 1, 10, 1); +process = fuzzy_tube(a,b,c,fuzzy) +with { + a = 4; + b = 4; + c = 0.125; +}; diff --git a/src/faust/echo.dsp b/src/faust/echo.dsp new file mode 100644 index 0000000..f9f2d5b --- /dev/null +++ b/src/faust/echo.dsp @@ -0,0 +1,16 @@ +//declare name "emptty"; +declare version "0.01"; +declare author "brummer"; +declare license "BSD"; +declare copyright "(c)brummer 2008"; + +import("math.lib"); +import("music.lib"); +import("effect.lib"); +import("filter.lib"); + +t = vslider("time", 1, 1, 2000, 1); +release = vslider("percent", 0, 0, 100, 0.1); + +echo1 = +~(delay(131072, int(t*millisec)-1) * (release/100.0)); +process = echo1; diff --git a/src/faust/eq.dsp b/src/faust/eq.dsp new file mode 100644 index 0000000..682a125 --- /dev/null +++ b/src/faust/eq.dsp @@ -0,0 +1,22 @@ +declare name "eq"; +declare license "BSD"; +declare copyright "(c)GRAME 2006"; + +import("math.lib"); +import("music.lib"); +import("guitarix.lib"); + +//------------------------- Process -------------------------------- + + +process = ifilter(vslider("Q31_25", 50, 1, 100, 1), 31.25, vslider("f31_25[tooltip:gain (dB) at 31.25 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q62_5", 50, 1, 100, 1), 62.5, vslider("f62_5 [tooltip:gain (dB) at 62.5 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q125", 50, 1, 100, 1), 125, vslider("f125 [tooltip:gain (dB) at 125 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q250", 50, 1, 100, 1), 250, vslider("f250 [tooltip:gain (dB) at 250 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q500", 50, 1, 100, 1), 500, vslider("f500 [tooltip:gain (dB) at 500 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q1k", 50, 1, 100, 1), 1000, vslider("f1k [tooltip:gain (dB) at 1 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q2k", 50, 1, 100, 1), 2000, vslider("f2k [tooltip:gain (dB) at 2 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q4k", 50, 1, 100, 1), 4000, vslider("f4k [tooltip:gain (dB) at 4 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q8k", 50, 1, 100, 1), 8000, vslider("f8k [tooltip:gain (dB) at 8 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q16k", 50, 1, 100, 1),16000, vslider("f16k [tooltip:gain (dB) at 16 kHz]", 0, -50, 10, 0.1)) + ; diff --git a/src/faust/feed.dsp b/src/faust/feed.dsp new file mode 100644 index 0000000..466f3a2 --- /dev/null +++ b/src/faust/feed.dsp @@ -0,0 +1,16 @@ +declare name "amp"; + +import("math.lib"); + +fold = ffunction(float fold(float,float), , ""); +ngate = fvariable(float ngate, ); + +feedback = hslider("feedback[name:Feedback]", 0, -1, 1, 0.01); +feedforward = hslider("feedforward[name:Feedforward]", 0, -1, 1, 0.01); +threshold = hslider("fuzz[name:fuzz]", 1, 0, 1, 0.01); +tmax = 1-pow(10,-6); // 0 is bad value when using sigmoid in fold + +fforw(x) = x + feedforward * x'''; +fbackw = (- : neg : *(ngate) : fold(min(tmax,threshold))) ~ (feedback * _''''); + +process = fforw : fbackw <: _,_; diff --git a/src/faust/flanger.dsp b/src/faust/flanger.dsp new file mode 100644 index 0000000..e96291c --- /dev/null +++ b/src/faust/flanger.dsp @@ -0,0 +1,24 @@ +declare name "flanger"; +declare license "BSD"; + + +import("effect.lib"); +import("osc.lib"); + +flangerstereogx = *(level),*(level) : flangerstereo(dmax,curdel1,curdel2,depth,fb,invert) // change to flanger_stereo for faust >= 0.9.27 +with { + lfol = component("osc.lib").oscrs; // sine for left channel + lfor = component("osc.lib").oscrc; // cosine for right channel + dmax = 2048; + dflange = 0.001 * SR * hslider("flange delay [unit:ms]", 10, 0, 20, 0.01); + odflange = 0.001 * SR * hslider("flange delay offset [unit:ms]", 1, 0, 20, 0.01); + freq = hslider("LFO freq [unit:Hz]", 0.2, 0, 5, 0.01); + depth = hslider("depth", 1, 0, 1, 0.01); + fb = hslider("feedback gain", 0, 0, 1, 0.01); + invert = checkbox("invert[enum:linear|invert]"); + level = hslider("level [unit:dB]", 0, -60, 10, 0.1) : db2linear; + curdel1 = odflange+dflange*(1 + lfol(freq))/2; + curdel2 = odflange+dflange*(1 + lfor(freq))/2; +}; + +process = flangerstereogx; diff --git a/src/faust/freeverb.dsp b/src/faust/freeverb.dsp new file mode 100644 index 0000000..4d17047 --- /dev/null +++ b/src/faust/freeverb.dsp @@ -0,0 +1,63 @@ +//declare name "emptty"; +declare version "0.01"; +declare author "brummer"; +declare license "BSD"; +declare copyright "(c)brummer 2008"; + +import("math.lib"); +import("music.lib"); +import("effect.lib"); +import("filter.lib"); + +/*----------------------------------------------- + freeverb by "Grame" + -----------------------------------------------*/ + +// Filter Parameters + +combtuningL1 = 1116; +combtuningL2 = 1188; +combtuningL3 = 1277; +combtuningL4 = 1356; +combtuningL5 = 1422; +combtuningL6 = 1491; +combtuningL7 = 1557; +combtuningL8 = 1617; + +allpasstuningL1 = 556; +allpasstuningL2 = 441; +allpasstuningL3 = 341; +allpasstuningL4 = 225; + +roomsizeSlider = vslider("RoomSize", 0.5, 0, 1, 0.025)*0.28 + 0.7; +dampslider = vslider("damp",0.5, 0, 1, 0.025); +combfeed = roomsizeSlider; +wetslider = 0.5 + vslider("wet_dry[name:wet/dry]", 0, -0.5, 0.5, 0.1); + +// Comb and Allpass filters + +allpass(dt,fb) = (_,_ <: (*(fb),_:+:@(dt)), -) ~ _ : (!,_); +comb(dt, fb, damp) = (+:@(dt)) ~ (*(1-damp) : (+ ~ *(damp)) : *(fb)); + +// Reverb components + +monoReverb(fb1, fb2, damp, spread) + = _ <: comb(combtuningL1+spread, fb1, damp), + comb(combtuningL2+spread, fb1, damp), + comb(combtuningL3+spread, fb1, damp), + comb(combtuningL4+spread, fb1, damp), + comb(combtuningL5+spread, fb1, damp), + comb(combtuningL6+spread, fb1, damp), + comb(combtuningL7+spread, fb1, damp), + comb(combtuningL8+spread, fb1, damp) + +> + allpass (allpasstuningL1+spread, fb2) + : allpass (allpasstuningL2+spread, fb2) + : allpass (allpasstuningL3+spread, fb2) + : allpass (allpasstuningL4+spread, fb2) + ; + +//---------------------------------------------------------------- + +fxctrl(g,w,Fx) = _ <: (*(g) <: _ + Fx : *(w)), *(2*(1-w)) +> _; +process = fxctrl(0.015, wetslider, monoReverb(combfeed, 0.5, dampslider, 23)); diff --git a/src/faust/guitarix.lib b/src/faust/guitarix.lib new file mode 100644 index 0000000..523b39c --- /dev/null +++ b/src/faust/guitarix.lib @@ -0,0 +1,255 @@ +/**************************************************************** +** helper definitions +*/ +bypass(switch, block) = _ <: select2(switch, _, block); +BP(block) = bypass(checkbox("ON"), block); + +copysign = ffunction(float copysign(float,float), , ""); + +anti_denormal = pow(10,-20); +//add_dc = +(anti_denormal); +add_dc = +(anti_denormal); +anti_denormal_ac = 1 - 1' : *(anti_denormal) : + ~ *(-1); + +smoothi(c) = *(1-c) : +~*(c); + +clip(lo,hi) = min(hi) : max(lo); +sym_clip(thr) = clip(-thr,thr); + +balance(b) = *(1 - max(0, b)), *(1 - max(0, -b)); +wet_dry_mix(w, Fx) = _ <: _, Fx : balance(w) : +; + + +/**************************************************************** +** nonlinear functions +*/ + +// from thesis of Ragnar Bendiksen (used in swh ladspa valve plugin) + +valve = environment { + ex(x) = (1 - exp(-x)); + nlim = 50; // exp(-nlim)+1 == 1, exp(nlim)/(exp(nlim)+1) == 1 + + tr(x) = select2(abs(x) > eps, tr_taylor(x), tr_func(max(-600,x))) with + { + eps = pow(10,-4); + tr_func(x) = select2(x < -nlim, x / ex(x), -x*exp(x)); + tr_taylor(x) = 1 + x/2 + x*x/12; + }; + df(x) = select2(abs(x) > eps, df_taylor(x), df_func(max(-600,x))) with + { + eps = pow(10,-4); + df_func(x) = select2(x < -nlim, 1/ex(x) - (x * exp(-x)) / (ex(x)*ex(x)), -x*exp(x)); + df_taylor(x) = 0.5 + x/6 - x*x*x/180; + }; + qd(dist, q, x) = dist * (x - q); + vt(dist, q, x) = (tr(qd(dist, q, x)) - tr(qd(dist, q, 0))) / dist; + vt_scaled(dist, q, x) = select2(dist*q > nlim, vt(dist, q, x) / df(qd(dist, q, 0)), vt_lim(dist, q, x)) with + { + bigval = pow(10,10); + f(dist, q, x) = (qd(dist, q, x)/(1 - exp(-qd(dist, q, x)))*exp(dist*q) - dist*q)/(dist*dist*q); + vt_lim(dist, q, x) = select2(dist*x > nlim, select2(dist*x < -nlim, f(dist, q, x), -1/dist), bigval); + }; + vts(dist, q, x) = abs(x) : neg : vt_scaled(dist, q) : copysign(_, x); + vtu(dist, q, g) = vt_scaled(dist, q) : *(g) : neg : vt(dist, q) : neg; + vtu_(dist, q, g) = vt_scaled(dist, q) :neg : *(g) : vt_scaled(dist, q) : /(g) : neg; +}; + +saturate(t, x) = select2(abs(x) < t, x, v) +with { + sigmoid(x) = x * (1.5 - 0.5 * x * x); + sat(x) = t + (1 - t)*sigmoid((abs(x)-t)/((1-t)*1.5)); + v = copysign(x, sat(x)); +}; + +nonlin(a,b,c,x) = ((a * x - b * abs(x) * x) - x) * c; +nonlin1 = nonlin(2,1,0.5); + +/**************************************************************** + ** Guitar tone stacks + ** values from CAPS plugin tonestack (based on work from D.T. Yeh + */ +ts = environment { + k = *(1e3); + M = *(1e6); + nF = *(1e-9); + pF = *(1e-12); + + /* Fender */ + + bassman = environment { /* 59 Bassman 5F6-A */ + R1 = 250:k; + R2 = 1:M; + R3 = 25:k; + R4 = 56:k; + C1 = 250:pF; + C2 = 20:nF; + C3 = 20:nF; + }; + + twin = environment { /* 69 Twin Reverb AA270 */ + R1 = 250:k; + R2 = 250:k; + R3 = 10:k; + R4 = 100:k; + C1 = 120:pF; + C2 = 100:nF; + C3 = 47:nF; + }; + + princeton = environment { /* 64 Princeton AA1164 */ + R1 = 250:k; + R2 = 250:k; + R3 = 4.8:k; + R4 = 100:k; + C1 = 250:pF; + C2 = 100:nF; + C3 = 47:nF; + }; + + /* Marshall */ + + jcm800 = environment { /* 59/81 JCM-800 Lead 100 2203 */ + R1 = 220:k; + R2 = 1:M; + R3 = 22:k; + R4 = 33:k; + C1 = 470:pF; + C2 = 22:nF; + C3 = 22:nF; + }; + /* 90 JCM-900 Master 2100: same as JCM-800 */ + + jcm2000 = environment { /* 81 2000 Lead */ + R1 = 250:k; + R2 = 1:M; + R3 = 25:k; + R4 = 56:k; /* a 10 k fixed + 100 k pot in series actually */ + C1 = 500:pF; + C2 = 22:nF; + C3 = 22:nF; + }; + + /* parameter order is R1 - R4, C1 - C3 */ + mlead = environment { /* 67 Major Lead 200 */ + R1 = 250:k; + R2 = 1:M; + R3 = 25:k; + R4 = 33:k; + C1 = 500:pF; + C2 = 22:nF; + C3 = 22:nF; + }; + + m2199 = environment { /* undated M2199 30W solid state */ + R1 = 250:k; + R2 = 250:k; + R3 = 25:k; + R4 = 56:k; + C1 = 250:pF; + C2 = 47:nF; + C3 = 47:nF; + }; + + /* Vox */ + ac30 = environment { /* 59/86 AC-30 */ + /* R3 is fixed (circuit differs anyway) */ + R1 = 1:M; + R2 = 1:M; + R3 = 10:k; + R4 = 100:k; + C1 = 50:pF; + C2 = 22:nF; + C3 = 22:nF; + }; +}; + +tonestack(tse) = 1/A0*tf3(B0,B1,B2,B3,A1/A0,A2/A0,A3/A0) with { + C1 = tse.C1; + C2 = tse.C2; + C3 = tse.C3; + R1 = tse.R1; + R2 = tse.R2; + R3 = tse.R3; + R4 = tse.R4; + + t = vslider("Treble", 0.5, 0, 1, 0.01); + m = vslider("Middle", 0.5, 0, 1, 0.01); + l = vslider("Bass", 0.5, 0, 1, 0.01) : (_-1)*3.4 : exp; + + b1 = t*C1*R1 + m*C3*R3 + l*(C1*R2 + C2*R2) + (C1*R3 + C2*R3); + + b2 = t*(C1*C2*R1*R4 + C1*C3*R1*R4) - m*m*(C1*C3*R3*R3 + C2*C3*R3*R3) + + m*(C1*C3*R1*R3 + C1*C3*R3*R3 + C2*C3*R3*R3) + + l*(C1*C2*R1*R2 + C1*C2*R2*R4 + C1*C3*R2*R4) + + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3) + + (C1*C2*R1*R3 + C1*C2*R3*R4 + C1*C3*R3*R4); + + b3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4) + - m*m*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4) + + m*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4) + + t*C1*C2*C3*R1*R3*R4 - t*m*C1*C2*C3*R1*R3*R4 + + t*l*C1*C2*C3*R1*R2*R4; + + a0 = 1; + + a1 = (C1*R1 + C1*R3 + C2*R3 + C2*R4 + C3*R4) + + m*C3*R3 + l*(C1*R2 + C2*R2); + + a2 = m*(C1*C3*R1*R3 - C2*C3*R3*R4 + C1*C3*R3*R3 + C2*C3*R3*R3) + + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3) + - m*m*(C1*C3*R3*R3 + C2*C3*R3*R3) + + l*(C1*C2*R2*R4 + C1*C2*R1*R2 + C1*C3*R2*R4 + C2*C3*R2*R4) + + (C1*C2*R1*R4 + C1*C3*R1*R4 + C1*C2*R3*R4 + C1*C2*R1*R3 + C1*C3*R3*R4 + C2*C3*R3*R4); + + a3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4) + - m*m*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4) + + m*(C1*C2*C3*R3*R3*R4 + C1*C2*C3*R1*R3*R3 - C1*C2*C3*R1*R3*R4) + + l*C1*C2*C3*R1*R2*R4 + + C1*C2*C3*R1*R3*R4; + + c = 2*float(SR); + + B0 = -b1*c - b2*pow(c,2) - b3*pow(c,3); + B1 = -b1*c + b2*pow(c,2) + 3*b3*pow(c,3); + B2 = b1*c + b2*pow(c,2) - 3*b3*pow(c,3); + B3 = b1*c - b2*pow(c,2) + b3*pow(c,3); + A0 = -a0 - a1*c - a2*pow(c,2) - a3*pow(c,3); + A1 = -3*a0 - a1*c + a2*pow(c,2) + 3*a3*pow(c,3); + A2 = -3*a0 + a1*c + a2*pow(c,2) - 3*a3*pow(c,3); + A3 = -a0 + a1*c - a2*pow(c,2) + a3*pow(c,3); +}; + +/**************************************************************** +** filter +*/ + +//---------------------second order Parametric Equalizer--------- +// filter(Q,F,G) +// Q : quality factor [1..100] +// F : frequency (Hz) +// G : gain [0..1] +//--------------------------------------------------------------- +// from "bandfilter.dsp" in the faust2pd distribution +// which was released under the BSD license. + +eqfilter(Q,F,G) = TF2( (1 + K/Q + K*K) / D, + 2 * (K*K - 1) / D, + (1 - K/Q + K*K) / D, + 2 * (K*K - 1) / D, + (1 - V*K/Q + K*K) / D + ) + with { + V = db2linear(G); + K = tan(PI*F/SR); + D = 1 + V*K/Q + K*K; + }; + + +ifilter(Q,F,G) = eqfilter(Q,F,-G); + + +/**************************************************************** +** building blocks +*/ +fuzzy_tube(a,b,c,fuzzy) = _ <: _ + nonlin(a,b,c) * fuzzy * 0.5 : sym_clip(0.7); diff --git a/src/faust/impulseresponse.dsp b/src/faust/impulseresponse.dsp new file mode 100644 index 0000000..358de60 --- /dev/null +++ b/src/faust/impulseresponse.dsp @@ -0,0 +1,30 @@ +declare name "IR"; +declare version "0.01"; +declare author "brummer"; +declare license "BSD"; +declare copyright "(c)brummer 2008"; + +import("math.lib"); +import("music.lib"); +import("effect.lib"); +import("filter.lib"); +import("guitarix.lib"); + +g3 = hslider("peak[tooltip:peak gain]", 1, 0, 10, 0.2); +fr = hslider("freq[tooltip:frequency (Hz)]", 440, 20, 12000, 10); +auto_ir = checkbox("auto_freq[name:auto freq][enum:manual|auto]") : clip(0, 1); + +check_auto_ir(v) = select2(auto_ir, v, sym_clip(0.6)); + +feedbackcontroll(x) = firpart : + ~ feedback +with { + bw = hslider("bandwidth[tooltip:bandwidth (Hz)]", 100, 20, 20000, 10); + R = exp(0-PI*bw/SR); // pole radius [0 required] + A = 2*PI*fr/SR; // pole angle (radians pole = 2) + RR = R*R; + firpart = (x - x'') * g3 * ((1-RR)/2); // radius = 2 + // time-domain coefficients ASSUMING ONE PIPELINE DELAY: + feedback(v) = 0 + R*check_auto_ir(2*cos(A),x)*v - RR*v'; +}; + +process(x) = x + feedbackcontroll(x); diff --git a/src/faust/inputgain.dsp b/src/faust/inputgain.dsp new file mode 100644 index 0000000..f4b7596 --- /dev/null +++ b/src/faust/inputgain.dsp @@ -0,0 +1,7 @@ +declare name "amp"; + +import("music.lib"); +import("guitarix.lib"); + +gain = vslider("in_level[name:in / level]", 0, -40, 40, 0.1) : db2linear : smoothi(0.999); +process = *(gain); diff --git a/src/faust/jconv_post.dsp b/src/faust/jconv_post.dsp new file mode 100644 index 0000000..9102130 --- /dev/null +++ b/src/faust/jconv_post.dsp @@ -0,0 +1,15 @@ +declare name "jconv"; + +import("music.lib"); +import("guitarix.lib"); + +wet_dry = vslider("wet_dry[name:wet/dry]", 0, -1, 1, 0.1); +ldelay = vslider("left_delay[name:Left Delay]", 0, 0, 5000, 10)*millisec; +rdelay = vslider("right_delay[name:Right Delay]", 0, 0, 5000, 10)*millisec; +lgain = vslider("left_gain[name:Left Gain]", 0, -20, 20, 0.1) : db2linear : smoothi(0.999); +rgain = vslider("right_gain[name:Right Gain]", 0, -20, 20, 0.1): db2linear : smoothi(0.999); +bal = vslider(".amp.balance[name:Balance][alias]", 0, -1, 1, 0.1); + +dry = 1 - max(0, wet_dry); +wet = 1 - max(0, -wet_dry); +process = *(dry), *(dry), lgain * fdelay43s(ldelay) * wet, rgain * fdelay43s(rdelay) * wet :> balance(bal); diff --git a/src/faust/moog.dsp b/src/faust/moog.dsp new file mode 100644 index 0000000..bf56d2d --- /dev/null +++ b/src/faust/moog.dsp @@ -0,0 +1,11 @@ +declare name "moog"; +declare license "BSD"; + + +import("effect.lib"); +import("guitarix.lib"); + +Q = hslider("Q", 1, 0, 4, 0.1); +fr = hslider("fr", 3000, 440, 6000, 10): smoothi(0.999); + +process = ( +(anti_denormal_ac): moogvcf(Q,fr)), (+(anti_denormal_ac): moogvcf(Q,fr)); diff --git a/src/faust/multifilter.dsp b/src/faust/multifilter.dsp new file mode 100644 index 0000000..db27772 --- /dev/null +++ b/src/faust/multifilter.dsp @@ -0,0 +1,25 @@ +declare name "MultiBandFilter"; +declare version "1.0"; +declare author "Grame"; +declare license "BSD"; +declare copyright "(c)GRAME 2006"; + +import("math.lib"); +import("music.lib"); +import("guitarix.lib"); + + +//------------------------- Process -------------------------------- + + +process = ifilter(vslider("Q31_25", 50, 1, 100, 1), 31.25, vslider("f31_25[tooltip:gain (dB) at 31.25 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Q62_5", 50, 1, 100, 1), 62.5, vslider("f62_5 [tooltip:gain (dB) at 62.5 Hz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q125", 50, 1, 100, 1), 125, vslider("f125 [tooltip:gain (dB) at 125 Hz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q250", 50, 1, 100, 1), 250, vslider("f250 [tooltip:gain (dB) at 250 Hz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q500", 50, 1, 100, 1), 500, vslider("f500 [tooltip:gain (dB) at 500 Hz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q1k", 50, 1, 100, 1), 1000, vslider("f1k [tooltip:gain (dB) at 1 kHz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q2k", 50, 1, 100, 1), 2000, vslider("f2k [tooltip:gain (dB) at 2 kHz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q4k", 50, 1, 100, 1), 4000, vslider("f4k [tooltip:gain (dB) at 4 kHz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q8k", 50, 1, 100, 1), 8000, vslider("f8k [tooltip:gain (dB) at 8 kHz] ", 0, -50, 10, 0.1)) + : ifilter(vslider("Q16k", 50, 1, 100, 1),16000, vslider("f16k [tooltip:gain (dB) at 16 kHz] ", 0, -50, 10, 0.1)) + ; diff --git a/src/faust/noise_shaper.dsp b/src/faust/noise_shaper.dsp new file mode 100644 index 0000000..a6c1466 --- /dev/null +++ b/src/faust/noise_shaper.dsp @@ -0,0 +1,30 @@ +declare name "shaper"; + +import("music.lib"); + +sharp = vslider("sharper[name:sharper]", 1, 1, 10, 1); +press = 5 * sharp; + +attack = 0.005; +release = 10; +knee = 10.5; +ratio = 1.5; + +env = abs : max(1); + +compress(env) = level * (1-r)/r +with { + level = env : h ~ _ : linear2db : (_ + press) : max(0) + with { + h(x,y) = f*x+(1-f)*y with { f = (x=y)*gr; }; + ga = exp(-1/(SR*attack)); + gr = exp(-1/(SR*release)); + }; + p = level/(knee+eps) : max(0) : min(1) with { eps = 0.001; }; + r = 1 - p + p * ratio; +}; + +process(x) = g(x) * x +with { + g = env : compress + sharp : db2linear; +}; diff --git a/src/faust/osc_tube.dsp b/src/faust/osc_tube.dsp new file mode 100644 index 0000000..eff8a3a --- /dev/null +++ b/src/faust/osc_tube.dsp @@ -0,0 +1,19 @@ +declare name "tube2"; + +import("music.lib"); +import("effect.lib"); +import("guitarix.lib"); + +resonator = (+ <: (delay(4096, d-1) + delay(4096, d))/2.0)~*(1.0-a) +with { +//d = vslider("vibrato", 0.5, 0, 1, 0.01); +d = 1 - vslider("vibrato", 1, 0, 0.99, 0.01); +//a = vslider("trigger[name:resonanz]", 0.12, 0, 1, 0.01); +a = 0.9 - vslider("resonanz", 0.5, 0, 0.9, 0.01); +}; + +//fuzzy = vslider("fuzzy[name:tube]", 0.5, 0, 1, 0.01); +fuzzy = vslider("fuzzy[name:tube]", 1, -3, 10, 1); + +tube1 = component("HighShelf.dsp").hs : nonlin1 : resonator : +(anti_denormal_ac) : speakerbp(130,5000) * fuzzy * 0.5; +process(x) = x + tube1(x) : sym_clip(0.7); diff --git a/src/faust/outputgain.dsp b/src/faust/outputgain.dsp new file mode 100644 index 0000000..30ab896 --- /dev/null +++ b/src/faust/outputgain.dsp @@ -0,0 +1,7 @@ +declare name "amp"; + +import("music.lib"); +import("guitarix.lib"); + +gain = vslider("out_master[name:out / master]", 0, -40, 40, 0.1) : db2linear : smoothi(0.999); +process = *(gain); diff --git a/src/faust/overdrive.dsp b/src/faust/overdrive.dsp new file mode 100644 index 0000000..ad412e3 --- /dev/null +++ b/src/faust/overdrive.dsp @@ -0,0 +1,7 @@ +import("music.lib"); +import("guitarix.lib"); + +drive = vslider("drive", 1, 1, 20, 0.1); +f = drive * -0.5 : db2linear : smoothi(0.999); + +process(x) = (x*(abs(x) + drive)/(x*x + (drive-1)*abs(x) + 1)) * f; diff --git a/src/faust/preamp.dsp b/src/faust/preamp.dsp new file mode 100644 index 0000000..b1d2750 --- /dev/null +++ b/src/faust/preamp.dsp @@ -0,0 +1,14 @@ +//declare name "preamp"; + +import("guitarix.lib"); + +fatan = vslider("atan[name:drive][tooltip:Input level for pre-amp (higher level gives more distortion)]", 1, 1, 10, 1); +moving_filter(x) = (x+x'+x'')/3; +nonlin1p(x) = (x-0.15*x*x)-(0.15*(x+anti_denormal_ac)*x*x); +nonlin2p(x) = 1.5*x - 0.5*(x+anti_denormal_ac)*x*x; +normalize(fatan) = 1/atan(fatan) * atan(_*fatan); +process = moving_filter : nonlin1p : nonlin2p : normalize(fatan)*0.75 : moving_filter; +/* +** old definition was: +** moving_filter*0.001 : nonlin1 : nonlin2 : normalize(fatan)*750; +*/ diff --git a/src/faust/reso_tube.dsp b/src/faust/reso_tube.dsp new file mode 100644 index 0000000..be7e83e --- /dev/null +++ b/src/faust/reso_tube.dsp @@ -0,0 +1,17 @@ +declare name "tube2"; +import("music.lib"); +import("guitarix.lib"); + +resonator = (+ <: (delay(4096, d-1) + delay(4096, d))/2.0)~*(1.0-a) +with { +//d = vslider("vibrato", 0.5, 0, 1, 0.01); +d = 1 - vslider("vibrato[alias]", 1, 0, 1, 0.01); +//a = vslider("trigger", 0.12, 0, 1, 0.01); +a = 0.9 - vslider("resonanz[alias]", 0.5, 0, 0.9, 0.01); +}; + +//fuzzy = vslider("fuzzy", 0.5, 0, 1, 0.01); +fuzzy = vslider("fuzzy[name:tube][alias]", 1, -3, 10, 1); +tube1 = nonlin1 : resonator * fuzzy * 0.5 : sym_clip(0.7) : neg; + +process = add_dc <: _ + tube1 : sym_clip(0.7); diff --git a/src/faust/selecteq.dsp b/src/faust/selecteq.dsp new file mode 100644 index 0000000..22461b1 --- /dev/null +++ b/src/faust/selecteq.dsp @@ -0,0 +1,23 @@ +declare name "eqs"; +declare license "BSD"; +declare copyright "(c)GRAME 2006"; + +import("math.lib"); +import("music.lib"); +import("guitarix.lib"); + + +//------------------------- Process -------------------------------- + + +process = ifilter(vslider("Qs31_25", 50, 1, 100, 1), vslider("freq31_25 [tooltip:Hz]",31, 20, 20000, 1), vslider("fs31_25[tooltip:gain (dB) at 31.25 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs62_5", 50, 1, 100, 1), vslider("freq62_5 [tooltip:Hz]",62, 20, 20000, 1), vslider("fs62_5 [tooltip:gain (dB) at 62.5 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs125", 50, 1, 100, 1), vslider("freq125 [tooltip:Hz]",125., 20, 20000, 1), vslider("fs125 [tooltip:gain (dB) at 125 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs250", 50, 1, 100, 1), vslider("freq250 [tooltip:Hz]",250., 20, 20000, 1), vslider("fs250 [tooltip:gain (dB) at 250 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs500", 50, 1, 100, 1), vslider("freq500 [tooltip:Hz]",500., 20, 20000, 1), vslider("fs500 [tooltip:gain (dB) at 500 Hz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs1k", 50, 1, 100, 1), vslider("freq1k [tooltip:Hz]",1000., 20, 20000, 1), vslider("fs1k [tooltip:gain (dB) at 1 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs2k", 50, 1, 100, 1), vslider("freq2k [tooltip:Hz]",2000., 20, 20000, 1), vslider("fs2k [tooltip:gain (dB) at 2 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs4k", 50, 1, 100, 1), vslider("freq4k [tooltip:Hz]",4000., 20, 20000, 1), vslider("fs4k [tooltip:gain (dB) at 4 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs8k", 50, 1, 100, 1), vslider("freq8k [tooltip:Hz]",8000., 20, 20000, 1), vslider("fs8k [tooltip:gain (dB) at 8 kHz]", 0, -50, 10, 0.1)) + : ifilter(vslider("Qs16k", 50, 1, 100, 1),vslider("freq16k [tooltip:Hz]",16000., 20, 20000, 1), vslider("fs16k [tooltip:gain (dB) at 16 kHz]", 0, -50, 10, 0.1)) + ; diff --git a/src/faust/sloop.dsp b/src/faust/sloop.dsp new file mode 100644 index 0000000..0ba3d9e --- /dev/null +++ b/src/faust/sloop.dsp @@ -0,0 +1,25 @@ +declare name "sloop"; +declare version "1.0"; +declare author "brummer"; +declare license "BSD"; + + +import("music.lib"); + + +B = checkbox("Capture"); // Capture sound while pressed +C = checkbox("Play"); + +I = int(B); // convert button signal from float to integer +R = (I-I') <= 0; // Reset capture when button is pressed +D = (+(I):*(R))~_; // Compute capture duration while button is pressed: 0..NNNN0..MMM + + +capture = ( *(B) : (+ : fdelay(2097152, D-1)) ~ *(1.0-B)) *(C); + + +smooth(c) = *(1-c) : +~*(c); +level = hslider("gain", 0, -96, 4, 0.1) : db2linear : smooth(0.999); + +process = vgroup( "SampleLooper", _ <:_, (capture : *(level)):>_ ) ; + diff --git a/src/faust/stage3.dsp b/src/faust/stage3.dsp new file mode 100644 index 0000000..da8d86d --- /dev/null +++ b/src/faust/stage3.dsp @@ -0,0 +1,16 @@ +import("music.lib"); +import("filter.lib"); +import("effect.lib"); +import("guitarix.lib"); + + +/**************************************************************** + ** Tube Preamp Emulation stage 3 + */ + + process = hgroup("stage3", BP(stage3)) + with { + stage3 = lowpass1(6531.0) : component("amp2.dsp").tubestage(1,194.0,820.0) : *(gain3) with { + gain3 = vslider("gain3", 6, -10.0, 20.0, 0.1) : db2linear : smoothi(0.999); + }; +}; diff --git a/src/faust/tone.dsp b/src/faust/tone.dsp new file mode 100644 index 0000000..e290920 --- /dev/null +++ b/src/faust/tone.dsp @@ -0,0 +1,71 @@ +declare name "amp.tone"; +declare version "0.01"; +declare author "brummer"; +declare license "BSD"; +declare copyright "(c)brummer 2008"; + +import("math.lib"); +import("music.lib"); +import("effect.lib"); +import("filter.lib"); +import("guitarix.lib"); + +/*----------------------------------------------- + The tone control + Low and high shelf filters, from Robert Bristow-Johnson's "Audio + EQ Cookbook", see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt. + -----------------------------------------------*/ + +filter(b0,b1,b2,a0,a1,a2) = f : (+ ~ g) +with { + f(x) = (b0/a0)*x+(b1/a0)*x'+(b2/a0)*x''; + g(y) = 0-(a1/a0)*y-(a2/a0)*y'; +}; + +low_shelf(f0,g) = filter(b0,b1,b2,a0,a1,a2) +with { + S = 1; + A = pow(10,g/40); + w0 = 2*PI*f0/SR; + alpha = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 ); + + b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha ); + b1 = 2*A*( (A-1) - (A+1)*cos(w0) ); + b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha ); + a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha; + a1 = -2*( (A-1) + (A+1)*cos(w0) ); + a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha; +}; + +high_shelf(f0,g) = filter(b0,b1,b2,a0,a1,a2) +with { + S = 1; + A = pow(10,g/40); + w0 = 2*PI*f0/SR; + alpha = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 ); + + b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha ); + b1 = -2*A*( (A-1) + (A+1)*cos(w0) ); + b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha ); + a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha; + a1 = 2*( (A-1) - (A+1)*cos(w0) ); + a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha; +}; + + +/* Fixed bass and treble frequencies.*/ +bass_freq = 600; +treble_freq = 2400; + +bass_gain = vslider("bass[name:bass]", 0, -20, 20, 0.1); +mid_gain = vslider("middle[name:middle]", 0, -20, 20, 0.1)/2; +treble_gain = vslider("treble[name:treble]", 0, -20, 20, 0.1); +tone(b,m,t) = low_shelf(bass_freq,b-m) : + low_shelf(treble_freq,m): + high_shelf(bass_freq,m) : + high_shelf(treble_freq,t-m); +process = add_dc : + low_shelf(bass_freq,bass_gain-mid_gain) : + low_shelf(treble_freq,mid_gain): + high_shelf(bass_freq,mid_gain) : + high_shelf(treble_freq,treble_gain-mid_gain); diff --git a/src/faust/tonestack.dsp b/src/faust/tonestack.dsp new file mode 100644 index 0000000..78c7ce2 --- /dev/null +++ b/src/faust/tonestack.dsp @@ -0,0 +1,205 @@ +//tonestack selector + +declare name "amp.tonestack"; + +import("music.lib"); +import("filter.lib"); +import("effect.lib"); + + +/**************************************************************** + ** Guitar tone stacks + ** values from CAPS plugin tonestack (based on work from D.T. Yeh + */ + +ts = environment { + k = *(1e3); + M = *(1e6); + nF = *(1e-9); + pF = *(1e-12); + + /* Fender */ + + bassman = environment { /* 59 Bassman 5F6-A */ + R1 = 250:k; + R2 = 1:M; + R3 = 25:k; + R4 = 56:k; + C1 = 250:pF; + C2 = 20:nF; + C3 = 20:nF; + }; + + twin = environment { /* 69 Twin Reverb AA270 */ + R1 = 250:k; + R2 = 250:k; + R3 = 10:k; + R4 = 100:k; + C1 = 120:pF; + C2 = 100:nF; + C3 = 47:nF; + }; + + princeton = environment { /* 64 Princeton AA1164 */ + R1 = 250:k; + R2 = 250:k; + R3 = 4.8:k; + R4 = 100:k; + C1 = 250:pF; + C2 = 100:nF; + C3 = 47:nF; + }; + + /* Marshall */ + + jcm800 = environment { /* 59/81 JCM-800 Lead 100 2203 */ + R1 = 220:k; + R2 = 1:M; + R3 = 22:k; + R4 = 33:k; + C1 = 470:pF; + C2 = 22:nF; + C3 = 22:nF; + }; + /* 90 JCM-900 Master 2100: same as JCM-800 */ + + jcm2000 = environment { /* 81 2000 Lead */ + R1 = 250:k; + R2 = 1:M; + R3 = 25:k; + R4 = 56:k; /* a 10 k fixed + 100 k pot in series actually */ + C1 = 500:pF; + C2 = 22:nF; + C3 = 22:nF; + }; + + /* parameter order is R1 - R4, C1 - C3 */ + mlead = environment { /* 67 Major Lead 200 */ + R1 = 250:k; + R2 = 1:M; + R3 = 25:k; + R4 = 33:k; + C1 = 500:pF; + C2 = 22:nF; + C3 = 22:nF; + }; + + m2199 = environment { /* undated M2199 30W solid state */ + R1 = 250:k; + R2 = 250:k; + R3 = 25:k; + R4 = 56:k; + C1 = 250:pF; + C2 = 47:nF; + C3 = 47:nF; + }; + + /* Vox */ + ac30 = environment { /* 59/86 AC-30 */ + /* R3 is fixed (circuit differs anyway) */ + R1 = 1:M; + R2 = 1:M; + R3 = 10:k; + R4 = 100:k; + C1 = 50:pF; + C2 = 22:nF; + C3 = 22:nF; + }; +}; + + t = vslider("Treble", 0.5, 0, 1, 0.01); + m = vslider("Middle", 0.5, 0, 1, 0.01); + l = vslider("Bass", 0.5, 0, 1, 0.01) : (_-1)*3.4 : exp; + +tonestack(tse) = 1/A0*tf3(B0,B1,B2,B3,A1/A0,A2/A0,A3/A0) with { + C1 = tse.C1; + C2 = tse.C2; + C3 = tse.C3; + R1 = tse.R1; + R2 = tse.R2; + R3 = tse.R3; + R4 = tse.R4; + + b1 = t*C1*R1 + m*C3*R3 + l*(C1*R2 + C2*R2) + (C1*R3 + C2*R3); + + b2 = t*(C1*C2*R1*R4 + C1*C3*R1*R4) - m*m*(C1*C3*R3*R3 + C2*C3*R3*R3) + + m*(C1*C3*R1*R3 + C1*C3*R3*R3 + C2*C3*R3*R3) + + l*(C1*C2*R1*R2 + C1*C2*R2*R4 + C1*C3*R2*R4) + + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3) + + (C1*C2*R1*R3 + C1*C2*R3*R4 + C1*C3*R3*R4); + + b3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4) + - m*m*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4) + + m*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4) + + t*C1*C2*C3*R1*R3*R4 - t*m*C1*C2*C3*R1*R3*R4 + + t*l*C1*C2*C3*R1*R2*R4; + + a0 = 1; + + a1 = (C1*R1 + C1*R3 + C2*R3 + C2*R4 + C3*R4) + + m*C3*R3 + l*(C1*R2 + C2*R2); + + a2 = m*(C1*C3*R1*R3 - C2*C3*R3*R4 + C1*C3*R3*R3 + C2*C3*R3*R3) + + l*m*(C1*C3*R2*R3 + C2*C3*R2*R3) + - m*m*(C1*C3*R3*R3 + C2*C3*R3*R3) + + l*(C1*C2*R2*R4 + C1*C2*R1*R2 + C1*C3*R2*R4 + C2*C3*R2*R4) + + (C1*C2*R1*R4 + C1*C3*R1*R4 + C1*C2*R3*R4 + C1*C2*R1*R3 + C1*C3*R3*R4 + C2*C3*R3*R4); + + a3 = l*m*(C1*C2*C3*R1*R2*R3 + C1*C2*C3*R2*R3*R4) + - m*m*(C1*C2*C3*R1*R3*R3 + C1*C2*C3*R3*R3*R4) + + m*(C1*C2*C3*R3*R3*R4 + C1*C2*C3*R1*R3*R3 - C1*C2*C3*R1*R3*R4) + + l*C1*C2*C3*R1*R2*R4 + + C1*C2*C3*R1*R3*R4; + + c = 2*float(SR); + + B0 = -b1*c - b2*pow(c,2) - b3*pow(c,3); + B1 = -b1*c + b2*pow(c,2) + 3*b3*pow(c,3); + B2 = b1*c + b2*pow(c,2) - 3*b3*pow(c,3); + B3 = b1*c - b2*pow(c,2) + b3*pow(c,3); + A0 = -a0 - a1*c - a2*pow(c,2) - a3*pow(c,3); + A1 = -3*a0 - a1*c + a2*pow(c,2) + 3*a3*pow(c,3); + A2 = -3*a0 + a1*c + a2*pow(c,2) - 3*a3*pow(c,3); + A3 = -a0 + a1*c - a2*pow(c,2) + a3*pow(c,3); +}; + + +aba = environment { + sl = hslider("select[enum:default|Bassman|Twin Reverb|Princeton|JCM-800|JCM-2000|M-Lead|M2199|AC-30|Off]",1,0,9,1); + a = min(2, max(0,sl)); + b = min(2, max(0,sl-1)); + c = min(2, max(0,sl-2)); + d = min(2, max(0,sl-3)); + e = min(2, max(0,sl-4)); + f = min(2, max(0,sl-5)); + g = min(2, max(0,sl-6)); + h = min(2, max(0,sl-7)); + x = min(2, max(0,sl-8)); +}; + + + +process = hgroup("tonestack",_<: a <: b <: c <: d <: e<: f <: g <:h :>_) with { + a = select3(aba.a,N,A,_) ; + b = select3(aba.b,_,B:*(1.5),_); //add a bit gain + c = select3(aba.c,_,C:*(1.5),_); //add a bit gain + d = select3(aba.d,_,D,_); + e = select3(aba.e,_,E,_); + f = select3(aba.f,_,F,_); + g = select3(aba.g,_,G,_); + h = select3(aba.h,_,H,_); + x = select3(aba.x,_,X,_); +} + + with { + N = component("tone.dsp").tone((l*20)-10,(m*10)-5,(t*20)-10); + A = tonestack(ts.bassman); + B = tonestack(ts.twin); + C = tonestack(ts.princeton); + D = tonestack(ts.jcm800); + E = tonestack(ts.jcm2000); + F = tonestack(ts.mlead); + G = tonestack(ts.m2199); + H = tonestack(ts.ac30); + X = _; +}; diff --git a/src/faust/tremolo.dsp b/src/faust/tremolo.dsp new file mode 100644 index 0000000..32cec2c --- /dev/null +++ b/src/faust/tremolo.dsp @@ -0,0 +1,43 @@ +/* +** Model of a vactrol tremolo unit by "transmogrify" +** c.f. http://sourceforge.net/apps/phpbb/guitarix/viewtopic.php?f=7&t=44&p=233&hilit=transmogrifox#p233 +** http://transmogrifox.webs.com/vactrol.m +*/ + +import("music.lib"); +import("osc.lib"); + +/* vactrol model */ + +R1 = 2700; +Ra = 1e6; +Rb = 300; +b = exp(log(Ra)/log(Rb)) - exp(1); +dTC = 0.06; +minTC = log(0.005/dTC); + +cds = ((_ <: _,_),_ : _+(1-alpha)*_) ~ (_<:*(alpha)) with { + iSR = 1/SR; + dRC = dTC * exp(*(minTC)); + alpha = 1 - iSR / (dRC + iSR); +}; + +vactrol = pow(_,1.9) : cds : *(b) + exp(1) : exp(log(Ra)/log) : R1/(_ + R1); + + +/* triangle oscillator (not bandlimited, frequency is approximate) */ + +trianglewave(freq) = _ ~ (_ <: _ + hyst) : /(periodsamps) with { + if(c,t,e) = select2(c,e,t); + hyst(x) = if(_ > 0, 2 * (x < periodsamps) - 1, 1 - 2 * (x > 0)) ~ _; + periodsamps = int(SR / (2*float(freq))); +}; + +/* tremolo unit, using triangle or sine oscillator as lfo */ + +tremolo(freq, depth) = lfo * depth + 1 - depth : vactrol with { + sine(freq) = (oscs(freq) + 1) / 2 : max(0); // max(0) because of numerical inaccuracy + lfo = select2(checkbox("SINE"), trianglewave(freq), sine(freq)); +}; + +process = *(tremolo(hslider("freq",5,0.1,50,0.1),hslider("depth",0.5,0,1,0.01))); diff --git a/src/faust/tube.dsp b/src/faust/tube.dsp new file mode 100644 index 0000000..858795f --- /dev/null +++ b/src/faust/tube.dsp @@ -0,0 +1,9 @@ +import("guitarix.lib"); + +fuzzy = vslider("fuzzy[name:count]", 1, -3, 10, 1); +process = fuzzy_tube(a,b,c,fuzzy) +with { + a = 2; + b = 1; + c = 0.5; +}; diff --git a/src/faust/tube3.dsp b/src/faust/tube3.dsp new file mode 100644 index 0000000..0d161ea --- /dev/null +++ b/src/faust/tube3.dsp @@ -0,0 +1,19 @@ +// dsp algorithm from swh ladspa valve plugin (Steve Harrison) + +import("music.lib"); +import("guitarix.lib"); + +g = vslider("g", 1, 0.2, 2, 0.1); + + +vt = valve.vt(dist, q) : *(g) : neg : valve.vt(dist, q) : neg with +{ + q_p = vslider("q", 0.4, 0.4, 1, 0.001); + dist_p = vslider("dist", 0, 0, 1.7, 0.01); + q = -q_p*-q_p*-q_p; + dist = pow(10,dist_p); +}; + + + +process = vt ; diff --git a/src/faust/tubevibrato.dsp b/src/faust/tubevibrato.dsp new file mode 100644 index 0000000..376f5e6 --- /dev/null +++ b/src/faust/tubevibrato.dsp @@ -0,0 +1,7 @@ +declare name "tube"; + +import("guitarix.lib"); + +vibrato = vslider("vibrato", 0, 0, 2, 0.02); + +process = + ~ *(vibrato/2) : sym_clip(0.7); diff --git a/src/faust/valve.dsp b/src/faust/valve.dsp new file mode 100644 index 0000000..4e41a73 --- /dev/null +++ b/src/faust/valve.dsp @@ -0,0 +1,32 @@ +// dsp algorithm from swh ladspa valve plugin (Steve Harrison) + +import("music.lib"); +import("guitarix.lib"); + +vt = valve.vt(dist, q) : neg : valve.vt(dist, q) : neg with +{ + q_p = vslider("q", 0, -1.7, 1.7, 0.01); + dist_p = vslider("dist", 0, -2, 2, 0.01); + q = q_p*q_p*q_p; + dist = pow(10,dist_p); +}; + +vtu = valve.vt(dist, q) with +{ + q_p = vslider("q", 0, -1.7, 1.7, 0.01); + dist_p = vslider("dist", 0, -2, 2, 0.01); + q = q_p*q_p*q_p; + dist = pow(10,dist_p); +}; + +vts(x) = abs(x) : neg : valve.vt(dist, q) : neg : copysign(_,x) +with +{ + q_p = vslider("q", 0, -1.7, 1.7, 0.01); + dist_p = vslider("dist", 0, -2, 2, 0.01); + q = q_p*q_p*q_p; + dist = pow(10,dist_p); + copysign = ffunction(float copysign(float,float), , ""); +}; + +process = vt; diff --git a/src/faust/valve_rect.dsp b/src/faust/valve_rect.dsp new file mode 100644 index 0000000..bfe0d36 --- /dev/null +++ b/src/faust/valve_rect.dsp @@ -0,0 +1,19 @@ +// dsp algorithm from swh ladspa valve_rect plugin (Steve Harrison) + +import("music.lib"); +import("guitarix.lib"); + +sag = vslider("sag", 0, 0, 1, 0.01); +dist_p = vslider("dist", 0, 0, 1, 0.01); + +process(x) = valve.vt(dist, q(x), x) +with { + dist = dist_p * 40 + 0.1; + q(x) = lp1tm1(x) * sag - lp2tm1(x) * 1.02 - 1.0 : clip(-1,-0.01); + lp(a) = *(1 - a) : + ~ *(a); + lp1tm1 = abs <: lp(0.9999), _ : max; + avgs = lp1tm1 : avg; + avg_size = SR/9; + avg(x) = x - delay1s(avg_size,x) : + ~ _ : /(avg_size); + lp2tm1 = avgs : lp(0.999); +}; diff --git a/src/faust/wscript b/src/faust/wscript new file mode 100644 index 0000000..9321b84 --- /dev/null +++ b/src/faust/wscript @@ -0,0 +1,140 @@ +#! /usr/bin/env python +# encoding: utf-8 + +import Task, TaskGen, Utils, Logs, os, errno, shutil + +# task function for task "dsp" +# use the specified processor to create the output file and copy +# the output file to a corresponding directory in the +# source tree (the directory will be created if it doesn't +# yet exist) +def dsp2cc(task): + src = task.inputs[0].srcpath(task.env) + o = task.outputs[0] + dst = o.bldpath(task.env) + cpy = o.relpath_gen(o.bld.bldnode) + cpydir = os.path.dirname(cpy) + try: + os.mkdir(cpydir) + except OSError, e: + if e.errno != errno.EEXIST: + Logs.error("runner: cannot create directory -> %s" % e) + return e.errno + lst = [task.proc,"-o",dst] + task.proc_args + [src] + Logs.debug("runner: system command -> %s" % " ".join(lst)) + ret = Utils.exec_command(lst,shell=False) + if ret != 0: + return ret + try: + shutil.copy2(dst, cpy) + except (OSError, IOError), e: + Logs.error("runner: cannot copy file -> %s" % e) + return e.errno + return 0 + +# definition of task "dsp" +Task.task_type_from_func( + name = 'dsp', + func = dsp2cc, + color = 'BLUE', + ext_in = '.dsp', + ext_out = '.cc', + before = 'cc cxx') + +@TaskGen.extension('.dsp') +def dsp_file(self, node): + # process all ".dsp" files with task "dsp", put the + # output file with extension ".cc" in a sibling directory + # of the source directory with "-cc" appended to its name + tsk = self.create_task('dsp') + tsk.proc = self.proc + tsk.proc_args = getattr(self, "proc_args", []) + tsk.set_inputs(node) + parent = node.parent + o = parent.parent.find_or_declare([parent.name+"-cc",node.name]) + o = o.change_ext('.cc') + tsk.set_outputs(o) + bld = tsk.generator.bld + bld.add_manual_dependency(node,bld.bldnode.find_resource(self.proc)) + +def build(bld): + float_arg = ["-s","40000","-float"] + if bld.env['FAUST_DOUBLE']: + arg = ["-double"] + else: + arg = ["-float"] + sources = [ + # amp + 'preamp.dsp', + 'inputgain.dsp', + 'noise_shaper.dsp', + 'AntiAlias.dsp', + 'HighShelf.dsp', + 'drive.dsp', + 'osc_tube.dsp', + 'reso_tube.dsp', + 'tube.dsp', + 'tube3.dsp', + 'tubevibrato.dsp', + #'tone.dsp', + 'multifilter.dsp', + 'eq.dsp', + 'bassbooster.dsp', + 'outputgain.dsp', + 'feed.dsp', + 'balance.dsp', + 'balance1.dsp', + 'tonestack.dsp', + 'amp2.dsp', + 'stage3.dsp', + + # effects + 'overdrive.dsp', + 'compressor.dsp', + 'crybaby.dsp', + 'autowah.dsp', + 'distortion.dsp', + 'distortion1.dsp', + 'freeverb.dsp', + 'flanger.dsp', + 'impulseresponse.dsp', + 'moog.dsp', + 'biquad.dsp', + 'selecteq.dsp', + ] + + float_sources = [ # big arrays and no sensitive processing + 'jconv_post.dsp', + 'sloop.dsp', + 'echo.dsp', + 'delay.dsp', + 'chorus.dsp', + ] + + experimental_soures = [ + #"valve.dsp", + #"valve_rect.dsp", + "Exp.dsp", + #"ExpFilter.dsp", + ] + + task = bld.new_task_gen( + source = sources, + proc = "../tools/dsp2cc", + proc_args = arg, + ) + + bld.new_task_gen( + source = float_sources, + proc = "../tools/dsp2cc", + proc_args = float_arg, + ) + + bld.new_task_gen( + source=experimental_soures, + proc = "../tools/dsp2cc_exp", + proc_args = ["-a","../src/faust-include.cpp","-f","-double"], + ) + +def configure(conf): + pass diff --git a/src/faust-cc/AntiAlias.cc b/src/faust-cc/AntiAlias.cc new file mode 100644 index 0000000..9d8acf1 --- /dev/null +++ b/src/faust-cc/AntiAlias.cc @@ -0,0 +1,32 @@ +namespace AntiAlias { +// generated from file '../src/faust/AntiAlias.dsp' + +FAUSTFLOAT fslider0; +double fRec0[4]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + for (int i=0; i<4; i++) fRec0[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = fslider0; + for (int i=0; i0; i--) fRec0[i] = fRec0[i-1]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("anti_aliase.feedback","Feedback","S","",&fslider0, 0.3, 0.3, 0.9, 0.01); + registerInit("anti_aliase", init); +} + +} // end namespace AntiAlias diff --git a/src/faust-cc/Exp.cc b/src/faust-cc/Exp.cc new file mode 100644 index 0000000..e9653f1 --- /dev/null +++ b/src/faust-cc/Exp.cc @@ -0,0 +1,1409 @@ +namespace Exp { +// generated from file '../src/faust/Exp.dsp' + +//----------------------------------------------------- +// +// Code generated with Faust 0.9.24 (http://faust.grame.fr) +//----------------------------------------------------- +/* link with */ +/* +** most of this file is a copy of faust architecture/jack-gtk.cpp +** which is licensed under GPL V2. +*/ + +struct Meta : map +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1< clist; + typedef map zmap; + +protected: + static list fGuiList; + zmap fZoneMap; + +public: + + UI() { + fGuiList.push_back(this); + } + + virtual ~UI() { + // suppression de this dans fGuiList + } + + // -- registerZone(z,c) : zone management + + void registerZone(float* z, uiItem* c) + { + if (fZoneMap.find(z) == fZoneMap.end()) fZoneMap[z] = new clist(); + fZoneMap[z]->push_back(c); + } + + // -- saveState(filename) : save the value of every zone to a file + + void saveState(const char* filename) + { + ofstream f(filename); + + for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) { + f << *(i->first) << ' '; + } + + f << endl; + f.close(); + } + + // -- recallState(filename) : load the value of every zone from a file + + void recallState(const char* filename) + { + ifstream f(filename); + if (f.good()) { + for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) { + f >> *(i->first); + } + } + f.close(); + } + + void updateAllZones(); + + void updateZone(float* z); + + static void updateAllGuis() + { + list::iterator g; + for (g = fGuiList.begin(); g != fGuiList.end(); g++) { + (*g)->updateAllZones(); + } + } + + // -- active widgets + + virtual void addButton(const char* label, float* zone) = 0; + virtual void addToggleButton(const char* label, float* zone) = 0; + virtual void addCheckButton(const char* label, float* zone) = 0; + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0; + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0; + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0; + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) = 0; + virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) = 0; + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0; + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0; + + void addCallback(float* zone, uiCallback foo, void* data); + + // -- widget's layouts + + virtual void openFrameBox(const char* label) = 0; + virtual void openTabBox(const char* label) = 0; + virtual void openHorizontalBox(const char* label) = 0; + virtual void openVerticalBox(const char* label) = 0; + + // -- extra widget's layouts + + virtual void openDialogBox(const char* label, float* zone) = 0; + virtual void openEventBox(const char* label) = 0; + virtual void openHandleBox(const char* label) = 0; + virtual void openExpanderBox(const char* label, float* zone) = 0; + + virtual void closeBox() = 0; + + virtual void run() {}; + + virtual void declare(float* zone, const char* key, const char* value) {} +}; + + +/** + * User Interface Item: abstract definition + */ + +class uiItem +{ +protected : + + UI* fGUI; + float* fZone; + float fCache; + + uiItem (UI* ui, float* zone) : fGUI(ui), fZone(zone), fCache(-123456.654321) + { + ui->registerZone(zone, this); + } + + +public : + virtual ~uiItem() {} + + void modifyZone(float v) + { + fCache = v; + if (*fZone != v) { + *fZone = v; + fGUI->updateZone(fZone); + } + } + + float cache() { return fCache; } + virtual void reflectZone() = 0; +}; + + +/** + * Callback Item + */ + +struct uiCallbackItem : public uiItem +{ + uiCallback fCallback; + void* fData; + + uiCallbackItem(UI* ui, float* zone, uiCallback foo, void* data) + : uiItem(ui, zone), fCallback(foo), fData(data) {} + + virtual void reflectZone() { + float v = *fZone; + fCache = v; + fCallback(v, fData); + } +}; + +// en cours d'installation de call back. a finir!!!!! + +/** + * Update all user items reflecting zone z + */ + +inline void UI::updateZone(float* z) +{ + float v = *z; + clist* l = fZoneMap[z]; + for (clist::iterator c = l->begin(); c != l->end(); c++) { + if ((*c)->cache() != v) (*c)->reflectZone(); + } +} + + +/** + * Update all user items not up to date + */ + +inline void UI::updateAllZones() +{ + for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) { + float* z = m->first; + clist* l = m->second; + float v = *z; + for (clist::iterator c = l->begin(); c != l->end(); c++) { + if ((*c)->cache() != v) (*c)->reflectZone(); + } + } +} + +inline void UI::addCallback(float* zone, uiCallback foo, void* data) +{ + new uiCallbackItem(this, zone, foo, data); +}; + +/****************************************************************************** +******************************************************************************* + + GRAPHIC USER INTERFACE + gtk interface + +******************************************************************************* +*******************************************************************************/ + + +#define stackSize 256 + +// Insertion modes + +#define kSingleMode 0 +#define kBoxMode 1 +#define kTabMode 2 + +/** + * rmWhiteSpaces(): Remove the leading and trailing white spaces of a string + * (but not those in the middle of the string) + */ +static string rmWhiteSpaces(const string& s) +{ + size_t i = s.find_first_not_of(" \t"); + size_t j = s.find_last_not_of(" \t"); + + if (i != string::npos && j != string::npos) { + return s.substr(i, 1+j-i); + } else { + return ""; + } +} + + +/** + * Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata + */ +static void extractMetadata(const string& fulllabel, string& label, map& metadata) +{ + enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue}; + int state = kLabel; int deep = 0; + string key, value; + + for (unsigned int i=0; i < fulllabel.size(); i++) { + char c = fulllabel[i]; + switch (state) { + case kLabel : + assert (deep == 0); + switch (c) { + case '\\' : state = kEscape1; break; + case '[' : state = kKey; deep++; break; + default : label += c; + } + break; + + case kEscape1 : + label += c; + state = kLabel; + break; + + case kEscape2 : + key += c; + state = kKey; + break; + + case kEscape3 : + value += c; + state = kValue; + break; + + case kKey : + assert (deep > 0); + switch (c) { + case '\\' : state = kEscape2; + break; + + case '[' : deep++; + key += c; + break; + + case ':' : if (deep == 1) { + state = kValue; + } else { + key += c; + } + break; + case ']' : deep--; + if (deep < 1) { + metadata[rmWhiteSpaces(key)] = ""; + state = kLabel; + key=""; + value=""; + } else { + key += c; + } + break; + default : key += c; + } + break; + + case kValue : + assert (deep > 0); + switch (c) { + case '\\' : state = kEscape3; + break; + + case '[' : deep++; + value += c; + break; + + case ']' : deep--; + if (deep < 1) { + metadata[rmWhiteSpaces(key)]=rmWhiteSpaces(value); + state = kLabel; + key=""; + value=""; + } else { + value += c; + } + break; + default : value += c; + } + break; + + default : + cerr << "ERROR unrecognized state " << state << endl; + } + } + label = rmWhiteSpaces(label); +} + + +class GTKUI : public UI +{ +private : + static list fGuiList; + static map fGuiSize; // map widget zone with widget size coef + static map fTooltip; // map widget zone with tooltip strings + +protected : + int fTop; + GtkWidget* fBox[stackSize]; + int fMode[stackSize]; + + GtkWidget* addWidget(const char* label, GtkWidget* w); + virtual void pushBox(int mode, GtkWidget* w); + + +public : + + static const gboolean expand = TRUE; + static const gboolean fill = TRUE; + static const gboolean homogene = FALSE; + + GTKUI(GtkWidget *window); + + // -- Labels and metadata + + virtual void declare (float* zone, const char* key, const char* value); + virtual int checkLabelOptions (GtkWidget* widget, const string& fullLabel, string& simplifiedLabel); + virtual void checkForTooltip (float* zone, GtkWidget* widget); + + // -- layout groups + + virtual void openFrameBox(const char* label); + virtual void openTabBox(const char* label = ""); + virtual void openHorizontalBox(const char* label = ""); + virtual void openVerticalBox(const char* label = ""); + + // -- extra widget's layouts + + virtual void openDialogBox(const char* label, float* zone); + virtual void openEventBox(const char* label = ""); + virtual void openHandleBox(const char* label = ""); + virtual void openExpanderBox(const char* label, float* zone); + + virtual void closeBox(); + virtual void adjustStack(int n); + + // -- active widgets + + virtual void addButton(const char* label, float* zone); + virtual void addToggleButton(const char* label, float* zone); + virtual void addCheckButton(const char* label, float* zone); + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step); + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step); + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step); + + // -- passive display widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision); + virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max); + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max); + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max); + + virtual void run(); + +}; + + + +/****************************************************************************** +******************************************************************************* + + GRAPHIC USER INTERFACE (v2) + gtk implementation + +******************************************************************************* +*******************************************************************************/ + +// global static fields + +list UI::fGuiList; + +map GTKUI::fGuiSize; +map GTKUI::fTooltip; + +GTKUI::GTKUI(GtkWidget *window) +{ + fTop = 0; + fBox[fTop] = gtk_vbox_new (homogene, 4); + fMode[fTop] = kBoxMode; + gtk_container_add (GTK_CONTAINER (window), fBox[fTop]); +} + +// empilement des boites + +void GTKUI::pushBox(int mode, GtkWidget* w) +{ + ++fTop; + assert(fTop < stackSize); + fMode[fTop] = mode; + fBox[fTop] = w; +} + + +/** + * Remove n levels from the stack S before the top level + * adjustStack(n): S -> S' with S' = S(0),S(n+1),S(n+2),... + */ +void GTKUI::adjustStack(int n) +{ + if (n > 0) { + assert(fTop >= n); + + fTop -= n; + fMode[fTop] = fMode[fTop+n]; + fBox[fTop] = fBox[fTop+n]; + } +} + +void GTKUI::closeBox() +{ + --fTop; + assert(fTop >= 0); +} + + +/** + * Analyses the widget zone metadata declarations and takes + * appropriate actions + */ +void GTKUI::declare(float* zone, const char* key, const char* value) +{ + if (strcmp(key,"size")==0) { + fGuiSize[zone]=atof(value); + } + else if (strcmp(key,"tooltip")==0) { + fTooltip[zone] = value ; + } +} + + + +/** + * Analyses a full label and activates the relevant options. returns a simplified + * label (without options) and an amount of stack adjustement (in case additional + * containers were pushed on the stack). + */ + +int GTKUI::checkLabelOptions(GtkWidget* widget, const string& fullLabel, string& simplifiedLabel) +{ + map metadata; + extractMetadata(fullLabel, simplifiedLabel, metadata); + + if (metadata.count("tooltip")) { + gtk_tooltips_set_tip (gtk_tooltips_new (), widget, metadata["tooltip"].c_str(), NULL); + } + if (metadata["option"] == "detachable") { + openHandleBox(simplifiedLabel.c_str()); + return 1; + } + + // no adjustement of the stack needed + return 0; +} + +/** + * Check if a tooltip is associated to a zone and add it to the corresponding widget + */ +void GTKUI::checkForTooltip(float* zone, GtkWidget* widget) +{ + if (fTooltip.count(zone)) { + gtk_tooltips_set_tip (gtk_tooltips_new (), widget, fTooltip[zone].c_str(), NULL); + } +} + + +// les differentes boites + +void GTKUI::openFrameBox(const char* label) +{ + GtkWidget * box = gtk_frame_new (label); + //gtk_container_set_border_width (GTK_CONTAINER (box), 10); + + pushBox(kSingleMode, addWidget(label, box)); +} + + +void GTKUI::openTabBox(const char* fullLabel) +{ + string label; + GtkWidget* widget = gtk_notebook_new(); + + int adjust = checkLabelOptions(widget, fullLabel, label); + + pushBox(kTabMode, addWidget(label.c_str(), widget)); + + // adjust stack because otherwise Handlebox will remain open + adjustStack(adjust); +} + + +void GTKUI::openHorizontalBox(const char* fullLabel) +{ + string label; + GtkWidget* box = gtk_hbox_new (homogene, 4); + int adjust = checkLabelOptions(box, fullLabel, label); + + gtk_container_set_border_width (GTK_CONTAINER (box), 10); + + if (fMode[fTop] != kTabMode && label[0] != 0) { + GtkWidget * frame = addWidget(label.c_str(), gtk_frame_new (label.c_str())); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } else { + pushBox(kBoxMode, addWidget(label.c_str(), box)); + } + + // adjust stack because otherwise Handlebox will remain open + adjustStack(adjust); +} + + +void GTKUI::openVerticalBox(const char* fullLabel) +{ + string label; + GtkWidget * box = gtk_vbox_new (homogene, 4); + int adjust = checkLabelOptions(box, fullLabel, label); + + gtk_container_set_border_width (GTK_CONTAINER (box), 10); + g_signal_connect(box, "expose-event", G_CALLBACK(gx_cairo::tribal_box_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) { + GtkWidget * frame = addWidget(label.c_str(), gtk_frame_new (label.c_str())); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } else { + pushBox(kBoxMode, addWidget(label.c_str(), box)); + } + + // adjust stack because otherwise Handlebox will remain open + adjustStack(adjust); +} + + +void GTKUI::openHandleBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_handle_box_new ()); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + + +void GTKUI::openEventBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_event_box_new ()); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + + +struct uiExpanderBox : public uiItem +{ + GtkExpander* fButton; + uiExpanderBox(UI* ui, float* zone, GtkExpander* b) : uiItem(ui, zone), fButton(b) {} + static void expanded (GtkWidget *widget, gpointer data) + { + float v = gtk_expander_get_expanded (GTK_EXPANDER(widget)); + if (v == 1.000000) + { + v = 0; + } + else v = 1; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_expander_set_expanded(GTK_EXPANDER(fButton), v); + } +}; + +void GTKUI::openExpanderBox(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget * box = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_expander_new (label)); + gtk_container_add (GTK_CONTAINER(frame), box); + uiExpanderBox* c = new uiExpanderBox(this, zone, GTK_EXPANDER(frame)); + gtk_signal_connect (GTK_OBJECT (frame), "activate", GTK_SIGNAL_FUNC (uiExpanderBox::expanded), (gpointer)c); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + + + +GtkWidget* GTKUI::addWidget(const char* label, GtkWidget* w) +{ + switch (fMode[fTop]) { + case kSingleMode : gtk_container_add (GTK_CONTAINER(fBox[fTop]), w); break; + case kBoxMode : gtk_box_pack_start (GTK_BOX(fBox[fTop]), w, expand, fill, 0); break; + case kTabMode : gtk_notebook_append_page (GTK_NOTEBOOK(fBox[fTop]), w, gtk_label_new(label)); break; + } + gtk_widget_show (w); + return w; +} + +// --------------------------- Press button --------------------------- + +struct uiButton : public uiItem +{ + GtkButton* fButton; + + uiButton (UI* ui, float* zone, GtkButton* b) : uiItem(ui, zone), fButton(b) {} + + static void pressed( GtkWidget *widget, gpointer data ) + { + uiItem* c = (uiItem*) data; + c->modifyZone(1.0); + } + + static void released( GtkWidget *widget, gpointer data ) + { + uiItem* c = (uiItem*) data; + c->modifyZone(0.0); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + if (v > 0.0) gtk_button_pressed(fButton); else gtk_button_released(fButton); + } +}; + +void GTKUI::addButton(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget* button = gtk_button_new_with_label (label); + addWidget(label, button); + + uiButton* c = new uiButton(this, zone, GTK_BUTTON(button)); + + gtk_signal_connect (GTK_OBJECT (button), "pressed", GTK_SIGNAL_FUNC (uiButton::pressed), (gpointer) c); + gtk_signal_connect (GTK_OBJECT (button), "released", GTK_SIGNAL_FUNC (uiButton::released), (gpointer) c); + + checkForTooltip(zone, button); +} + +// --------------------------- Toggle Buttons --------------------------- + +struct uiToggleButton : public uiItem +{ + GtkToggleButton* fButton; + + uiToggleButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {} + + static void toggled (GtkWidget *widget, gpointer data) + { + float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_toggle_button_set_active(fButton, v > 0.0); + } +}; + +void GTKUI::addToggleButton(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget* button = gtk_toggle_button_new_with_label (label); + addWidget(label, button); + + uiToggleButton* c = new uiToggleButton(this, zone, GTK_TOGGLE_BUTTON(button)); + gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC (uiToggleButton::toggled), (gpointer) c); + + checkForTooltip(zone, button); +} + + + +void show_dialog(GtkWidget *widget, gpointer data) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)) == TRUE) + { + gtk_widget_show(GTK_WIDGET(data)); + gint root_x, root_y; + gtk_window_get_position (GTK_WINDOW(data), &root_x, &root_y); + root_y -= 120; + gtk_window_move(GTK_WINDOW(data), root_x, root_y); + } + else gtk_widget_hide(GTK_WIDGET(data)); +} + +static gboolean deleteevent( GtkWidget *widget, gpointer data ) +{ + return TRUE; +} + +void GTKUI::openDialogBox(const char* label, float* zone) +{ + // create toplevel window and set properties + GtkWidget * dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_decorated(GTK_WINDOW(dialog), TRUE); + gtk_window_set_deletable(GTK_WINDOW(dialog), FALSE); + gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); + gtk_window_set_gravity(GTK_WINDOW(dialog), GDK_GRAVITY_SOUTH); + //##FIXME gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(fWindow)); + gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); + gtk_window_set_keep_below (GTK_WINDOW(dialog), FALSE); + gtk_window_set_title (GTK_WINDOW (dialog), label); + g_signal_connect (G_OBJECT (dialog), "delete_event", G_CALLBACK (deleteevent), NULL); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + + GtkWidget * box = gtk_hbox_new (homogene, 4); + + *zone = 0.0; + GtkWidget* button = gtk_toggle_button_new (); + gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC (show_dialog), (gpointer) dialog); + + gtk_container_add (GTK_CONTAINER(fBox[fTop]), button); + gtk_container_add (GTK_CONTAINER(dialog), box); + gtk_widget_show (button); + gtk_widget_show(box); + pushBox(kBoxMode, box); +} + +// --------------------------- Adjustmenty based widgets --------------------------- + +struct uiAdjustment : public uiItem +{ + GtkAdjustment* fAdj; + + uiAdjustment(UI* ui, float* zone, GtkAdjustment* adj) : uiItem(ui, zone), fAdj(adj) {} + + static void changed (GtkWidget *widget, gpointer data) + { + float v = GTK_ADJUSTMENT (widget)->value; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_adjustment_set_value(fAdj, v); + } +}; + +static int precision(double n) +{ + if (n < 0.009999) return 3; + else if (n < 0.099999) return 2; + else if (n < 0.999999) return 1; + else return 0; +} + +struct uiValueDisplay : public uiItem +{ + GtkLabel* fLabel; + int fPrecision ; + + uiValueDisplay(UI* ui, float* zone, GtkLabel* label, int precision) + : uiItem(ui, zone), fLabel(label), fPrecision(precision) {} + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + char s[64]; + if (fPrecision <= 0) + snprintf(s, 63, "%d", int(v)); + + else if (fPrecision > 3) + snprintf(s, 63, "%f", v); + + else if (fPrecision == 1) + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[1-1], v); + } + else if (fPrecision == 2) + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[2-1], v); + } + else + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[3-1], v); + } + gtk_label_set_text(fLabel, s); + } +}; + +// --------------------------- Check Button --------------------------- + +struct uiCheckButton : public uiItem +{ + GtkToggleButton* fButton; + + uiCheckButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {} + + static void toggled (GtkWidget *widget, gpointer data) + { + float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_toggle_button_set_active(fButton, v > 0.0); + } +}; + +void GTKUI::addCheckButton(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_mini_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + openHorizontalBox(""); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); + checkForTooltip(zone, slider); +} + + +// -------------------------- Vertical Slider ----------------------------------- + +void GTKUI::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkWidget* lw = gtk_label_new(""); + GtkWidget* lwl = gtk_label_new(label); + gtk_widget_set_name (lw,"value_label"); + gtk_widget_set_name (lwl,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + gtk_widget_modify_font(lwl, style->font_desc); + new uiValueDisplay(this, zone, GTK_LABEL(lw),precision(step)); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_regler_new_with_adjustment(GTK_ADJUSTMENT(adj)); + + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + openVerticalBox(""); + addWidget(label, lwl); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); + checkForTooltip(zone, slider); +} + +// -------------------------- Horizontal Slider ----------------------------------- + +void GTKUI::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + + gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c); + + GtkWidget* slider = gtk_hscale_new (GTK_ADJUSTMENT(adj)); + gtk_scale_set_digits(GTK_SCALE(slider), precision(step)); + float size = 160 * pow(2, fGuiSize[zone]); + gtk_widget_set_usize(slider, size, -1); + + if (label && label[0]!=0) { + openFrameBox(label); + addWidget(label, slider); + closeBox(); + } else { + addWidget(label, slider); + } + + checkForTooltip(zone, slider); +} + + +// ------------------------------ Num Entry ----------------------------------- + +void GTKUI::addNumEntry(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, step); + + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + + gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c); + + GtkWidget* spinner = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 0.005, precision(step)); + + //gtk_widget_set_usize(slider, 160, -1); + openFrameBox(label); + addWidget(label, spinner); + closeBox(); + + checkForTooltip(zone, spinner); +} + + +// ========================== passive widgets =============================== + + +// ------------------------------ Progress Bar ----------------------------------- + +struct uiBargraph : public uiItem +{ + GtkProgressBar* fProgressBar; + float fMin; + float fMax; + + uiBargraph(UI* ui, float* zone, GtkProgressBar* pbar, float lo, float hi) + : uiItem(ui, zone), fProgressBar(pbar), fMin(lo), fMax(hi) {} + + float scale(float v) { return (v-fMin)/(fMax-fMin); } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_progress_bar_set_fraction(fProgressBar, scale(v)); + } +}; + + + +void GTKUI::addVerticalBargraph(const char* label, float* zone, float lo, float hi) +{ + GtkWidget* pb = gtk_progress_bar_new(); + gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_BOTTOM_TO_TOP); + gtk_widget_set_size_request(pb, 8, -1); + new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi); + openFrameBox(label); + addWidget(label, pb); + closeBox(); + + checkForTooltip(zone, pb); +} + + +void GTKUI::addHorizontalBargraph(const char* label, float* zone, float lo, float hi) +{ + GtkWidget* pb = gtk_progress_bar_new(); + gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_LEFT_TO_RIGHT); + gtk_widget_set_size_request(pb, -1, 8); + new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi); + openFrameBox(label); + addWidget(label, pb); + closeBox(); + + checkForTooltip(zone, pb); +} + + +// ------------------------------ Num Display ----------------------------------- + +struct uiNumDisplay : public uiItem +{ + GtkLabel* fLabel; + int fPrecision; + + uiNumDisplay(UI* ui, float* zone, GtkLabel* label, int precision) + : uiItem(ui, zone), fLabel(label), fPrecision(precision) {} + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + char s[64]; + if (fPrecision <= 0) { + snprintf(s, 63, "%d", int(v)); + } else if (fPrecision>3) { + snprintf(s, 63, "%f", v); + } else { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[fPrecision-1], v); + } + gtk_label_set_text(fLabel, s); + } +}; + + +void GTKUI::addNumDisplay(const char* label, float* zone, int precision ) +{ + GtkWidget* lw = gtk_label_new(""); + new uiNumDisplay(this, zone, GTK_LABEL(lw), precision); + openFrameBox(label); + addWidget(label, lw); + closeBox(); + + checkForTooltip(zone, lw); +} + + +// ------------------------------ Text Display ----------------------------------- + +struct uiTextDisplay : public uiItem +{ + GtkLabel* fLabel; + const char** fNames; + float fMin; + float fMax; + int fNum; + + + uiTextDisplay (UI* ui, float* zone, GtkLabel* label, const char* names[], float lo, float hi) + : uiItem(ui, zone), fLabel(label), fNames(names), fMin(lo), fMax(hi) + { + fNum = 0; + while (fNames[fNum] != 0) fNum++; + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + + int idx = int(fNum*(v-fMin)/(fMax-fMin)); + + if (idx < 0) idx = 0; + else if (idx >= fNum) idx = fNum-1; + + gtk_label_set_text(fLabel, fNames[idx]); + } +}; + + +void GTKUI::addTextDisplay(const char* label, float* zone, const char* names[], float lo, float hi ) +{ + GtkWidget* lw = gtk_label_new(""); + new uiTextDisplay (this, zone, GTK_LABEL(lw), names, lo, hi); + openFrameBox(label); + addWidget(label, lw); + closeBox(); + + checkForTooltip(zone, lw); +} + + + +/** + * Update all user items reflecting zone z + */ + +static gboolean callUpdateAllGuis(gpointer) +{ + UI::updateAllGuis(); + return TRUE; +} + + +void GTKUI::run() +{ + assert(fTop == 0); + gtk_widget_show (fBox[0]); + gtk_timeout_add(40, callUpdateAllGuis, 0); +} + + +/****************************************************************************** +******************************************************************************* + + FAUST DSP + +******************************************************************************* +*******************************************************************************/ + + + + + +//---------------------------------------------------------------- +// Definition of an abstract signal processor +//---------------------------------------------------------------- + +class dsp { +protected: + float fSamplingFreq; +public: + dsp() {} + virtual ~dsp() {} + + virtual int getNumInputs() = 0; + virtual int getNumOutputs() = 0; + virtual void buildUserInterface(UI* interface) = 0; + virtual void init(int samplingRate) = 0; + virtual void compute(int len, float** inputs, float** outputs) = 0; + void setup(GtkWidget *window); +}; + +void dsp::setup(GtkWidget *window) +{ + GTKUI *interface = new GTKUI (window); + buildUserInterface(interface); + interface->run(); +} + +#define DSP_HAS_SETUP + + +//---------------------------------------------------------------------------- +// FAUST generated code +//---------------------------------------------------------------------------- + +#ifndef FAUSTFLOAT +#define FAUSTFLOAT float +#endif + +typedef long double quad; + +class mydsp : public dsp{ + protected: + FAUSTFLOAT fslider0; + int iVec0[2]; + double fConst0; + FAUSTFLOAT fslider1; + double fConst1; + int iRec2[2]; + int iRec1[2]; + double fConst2; + double fRec5[2]; + double fRec4[2]; + double fRec3[2]; + FAUSTFLOAT fcheckbox0; + FAUSTFLOAT fslider2; + double fRec0[2]; + FAUSTFLOAT fcheckbox1; + public: + static void metadata(Meta* m) { + m->declare("filter.lib/name", "Faust Filter Library"); + m->declare("filter.lib/author", "Julius O. Smith (jos at ccrma.stanford.edu)"); + m->declare("filter.lib/copyright", "Julius O. Smith III"); + m->declare("filter.lib/version", "1.5"); + m->declare("filter.lib/license", "STK-4.3"); + m->declare("filter.lib/reference", "http://ccrma.stanford.edu/~jos/filters/"); + m->declare("effect.lib/name", "Faust Effect Library"); + m->declare("effect.lib/author", "Julius O. Smith (jos at ccrma.stanford.edu)"); + m->declare("effect.lib/copyright", "Julius O. Smith III"); + m->declare("effect.lib/version", "1.1"); + m->declare("effect.lib/license", "STK-4.3"); + m->declare("effect.lib/reference", "http://ccrma.stanford.edu/realsimple/faust_strings/"); + m->declare("osc.lib/name", "Faust Oscillator Library"); + m->declare("osc.lib/author", "Julius O. Smith (jos at ccrma.stanford.edu)"); + m->declare("osc.lib/copyright", "Julius O. Smith III"); + m->declare("osc.lib/version", "1.2"); + m->declare("osc.lib/license", "STK-4.3"); + } + + virtual int getNumInputs() { return 1; } + virtual int getNumOutputs() { return 1; } + static void classInit(int samplingFreq) { + } + virtual void instanceInit(int samplingFreq) { + fSamplingFreq = samplingFreq; + for (int i=0; i<2; i++) iVec0[i] = 0; + fConst0 = (1.0 / fSamplingFreq); + fConst1 = (0.5 * fSamplingFreq); + for (int i=0; i<2; i++) iRec2[i] = 0; + for (int i=0; i<2; i++) iRec1[i] = 0; + fConst2 = (6.283185307179586 / fSamplingFreq); + for (int i=0; i<2; i++) fRec5[i] = 0; + for (int i=0; i<2; i++) fRec4[i] = 0; + for (int i=0; i<2; i++) fRec3[i] = 0; + for (int i=0; i<2; i++) fRec0[i] = 0; + } + virtual void init(int samplingFreq) { + classInit(samplingFreq); + instanceInit(samplingFreq); + } + virtual void buildUserInterface(UI* interface) { + interface->openHorizontalBox("test"); + interface->openHorizontalBox("tremolo"); + interface->addCheckButton("ON", &fcheckbox1); + interface->addCheckButton("SINE", &fcheckbox0); + interface->addHorizontalSlider("depth", &fslider2, 0.5, 0.0, 1.0, 0.01); + interface->addHorizontalSlider("freq", &fslider1, 5.0, 0.1, 5e+01, 0.1); + interface->declare(&fslider0, "name", "wet/dry"); + interface->addVerticalSlider("wet_dry", &fslider0, 0.0, -1.0, 1.0, 0.1); + interface->closeBox(); + interface->closeBox(); + } + virtual void compute (int count, FAUSTFLOAT** input, FAUSTFLOAT** output) { + double fSlow0 = fslider0; + double fSlow1 = (1 - max(0, fSlow0)); + double fSlow2 = fslider1; + int iSlow3 = int((fConst1 / double(fSlow2))); + double fSlow4 = (1.0 / iSlow3); + double fSlow5 = (fConst2 * fSlow2); + int iSlow6 = int(fcheckbox0); + double fSlow7 = fslider2; + int iSlow8 = int(fcheckbox1); + double fSlow9 = (1 - max(0, (0 - fSlow0))); + FAUSTFLOAT* input0 = input[0]; + FAUSTFLOAT* output0 = output[0]; + for (int i=0; i 0)))?((2 * (iRec1[1] < iSlow3)) - 1):(1 - (2 * (iRec1[1] > 0)))); + iRec1[0] = (iRec2[0] + iRec1[1]); + fRec5[0] = ((fSlow5 * (0 - fRec3[1])) + fRec5[1]); + fRec4[0] = ((1 + ((fSlow5 * fRec5[0]) + fRec4[1])) - iVec0[1]); + fRec3[0] = fRec4[0]; + fRec0[0] = (fTemp1 + (fConst0 * (pow((1 + (fSlow7 * (((iSlow6)?max(0, (0.5 * (1 + fRec3[0]))):(fSlow4 * iRec1[0])) - 1))),1.9) / (fConst0 + (0.06 * exp((0 - (2.4849066497880004 * fTemp1)))))))); + output0[i] = (FAUSTFLOAT)((fSlow9 * ((iSlow8)?(2700 * (fTemp0 / (2700 + exp((13.815510557964274 / log((2.718281828459045 + (8.551967507929417 * fRec0[0])))))))):fTemp0)) + (fSlow1 * fTemp0)); + // post processing + fRec0[1] = fRec0[0]; + fRec3[1] = fRec3[0]; + fRec4[1] = fRec4[0]; + fRec5[1] = fRec5[0]; + iRec1[1] = iRec1[0]; + iRec2[1] = iRec2[0]; + iVec0[1] = iVec0[0]; + } + } +}; + + + +struct DspBlock: mydsp +{ + DspBlock(); + static void static_init(int); +}; + +DspBlock instance; + +void init(int samplingRate) +{ + instance.init(samplingRate); +} + +#ifdef DSP_HAS_SETUP +void setup(GtkWidget *w) +{ + instance.setup(w); +} +#endif + +DspBlock::DspBlock() +{ + registerVar("test.tremolo.ON","","B","",&fcheckbox1,0,0,1,1); + registerVar("test.tremolo.SINE","","B","",&fcheckbox0,0,0,1,1); + registerVar("test.tremolo.depth","","S","",&fslider2,0.5,0.0,1.0,0.01); + registerVar("test.tremolo.freq","","S","",&fslider1,5.0,0.1,5e+01,0.1); + registerVar("test.tremolo.wet_dry","wet/dry","S","",&fslider0,0.0,-1.0,1.0,0.1); + registerInit("Experimental", Exp::init); +#ifdef DSP_HAS_SETUP + registerSetup(Exp::setup); +#endif +} + +void compute(int len, FAUSTFLOAT *input0, FAUSTFLOAT *output0) +{ + FAUSTFLOAT* inputs[1] = { input0 }; + FAUSTFLOAT* outputs[1] = { output0 }; + instance.compute(len, inputs, outputs); +} + +} // end namespace Exp diff --git a/src/faust-cc/HighShelf.cc b/src/faust-cc/HighShelf.cc new file mode 100644 index 0000000..9f72ad6 --- /dev/null +++ b/src/faust-cc/HighShelf.cc @@ -0,0 +1,66 @@ +namespace HighShelf { +// generated from file '../src/faust/HighShelf.dsp' + +int iVec0[2]; +double fConst0; +double fConst1; +double fConst2; +double fConst3; +double fConst4; +double fConst5; +double fConst6; +double fRec1[2]; +double fVec1[3]; +double fConst7; +double fConst8; +double fConst9; +double fConst10; +double fConst11; +double fRec0[3]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + for (int i=0; i<2; i++) iVec0[i] = 0; + fConst0 = (6.283185307179586 * (max(0, ((0.5 * fSamplingFreq) - 1e+02)) / fSamplingFreq)); + fConst1 = cos(fConst0); + fConst2 = (1.316227766016838 * fConst1); + fConst3 = (0 - (2 * (0 - (0.683772233983162 + fConst2)))); + fConst4 = (0.683772233983162 * fConst1); + fConst5 = (0.005623413251903491 * sin(fConst0)); + fConst6 = (fConst5 - (fConst4 + 1.316227766016838)); + for (int i=0; i<2; i++) fRec1[i] = 0; + for (int i=0; i<3; i++) fVec1[i] = 0; + fConst7 = (fConst5 + fConst4); + fConst8 = (0.31622776601683794 * (1.316227766016838 - fConst7)); + fConst9 = (0.31622776601683794 * ((fConst5 + 1.316227766016838) - fConst4)); + fConst10 = (0 - (0.6324555320336759 * (fConst2 - 0.683772233983162))); + fConst11 = (1.0 / (1.316227766016838 + fConst7)); + for (int i=0; i<3; i++) fRec0[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + for (int i=0; i(fTemp4)) + (0.999 * fRec4[1])); + fRec0[0] = (0 - (((fRec4[0] * fRec0[2]) + (fRec3[0] * fRec0[1])) - (fTemp0 * fRec1[0]))); + output0[i] = (FAUSTFLOAT)(fRec0[0] - fRec0[1]); + // post processing + fRec0[2] = fRec0[1]; fRec0[1] = fRec0[0]; + fRec4[1] = fRec4[0]; + fRec3[1] = fRec3[0]; + fRec1[1] = fRec1[0]; + iRec2[1] = iRec2[0]; + IOTA = IOTA+1; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerInit("autowah", init); +} + +} // end namespace autowah diff --git a/src/faust-cc/balance.cc b/src/faust-cc/balance.cc new file mode 100644 index 0000000..433334d --- /dev/null +++ b/src/faust-cc/balance.cc @@ -0,0 +1,30 @@ +namespace balance { +// generated from file '../src/faust/balance.dsp' + +FAUSTFLOAT fslider0; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; +} + +void compute(int count, float *input0, float *input1, float *output0, float *output1) +{ + double fSlow0 = fslider0; + double fSlow1 = (1 - max(0, fSlow0)); + double fSlow2 = (1 - max(0, (0 - fSlow0))); + for (int i=0; i(fConst0); + fConst2 = (2 * (fConst1 - 1)); + fConst3 = (1 + (fConst0 * (fConst0 - 1.4142135623730951))); + fConst4 = (1.0 / (1 + (fConst0 * (1.4142135623730951 + fConst0)))); + for (int i=0; i<3; i++) fRec0[i] = 0; + fConst5 = (3.1622776601683795 * fConst0); + fConst6 = (1 + (fConst0 * (fConst5 - 2.514866859365871))); + fConst7 = (2 * ((3.1622776601683795 * fConst1) - 1)); + fConst8 = (1 + (fConst0 * (fConst5 + 2.514866859365871))); +} + +void compute(int count, float *input0, float *output0) +{ + for (int i=0; i= fRec1[0])) + (fSlow2 * (fRec0[1] < fRec1[0]))); + fRec0[0] = ((fRec1[0] * (0 - (fTemp1 - 1))) + (fRec0[1] * fTemp1)); + double fTemp2 = max(0, ((20 * log10(fRec0[0])) + fSlow1)); + double fTemp3 = (fSlow5 * min(1, max(0, (fSlow4 * fTemp2)))); + output0[i] = (FAUSTFLOAT)(fTemp0 * pow(10,(0.05 * ((fTemp2 * (0 - fTemp3)) / (1 + fTemp3))))); + // post processing + fRec0[1] = fRec0[0]; + fRec1[1] = fRec1[0]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("compressor.ratio","","S","",&fentry2, 2.0, 1.0, 2e+01, 0.1); + registerVar("compressor.knee","","S","",&fentry1, 3.0, 0.0, 2e+01, 0.1); + registerVar("compressor.threshold","","S","",&fentry0, -2e+01, -96.0, 1e+01, 0.1); + registerVar("compressor.release","","S","",&fslider1, 0.5, 0.0, 1e+01, 0.01); + registerVar("compressor.attack","","S","",&fslider0, 0.002, 0.0, 1.0, 0.001); + registerInit("compressor", init); +} + +} // end namespace compressor diff --git a/src/faust-cc/crybaby.cc b/src/faust-cc/crybaby.cc new file mode 100644 index 0000000..3c115f1 --- /dev/null +++ b/src/faust-cc/crybaby.cc @@ -0,0 +1,62 @@ +namespace crybaby { +// generated from file '../src/faust/crybaby.dsp' + +FAUSTFLOAT fslider0; +FAUSTFLOAT fslider1; +double fConst0; +double fConst1; +double fRec1[2]; +double fRec2[2]; +double fRec3[2]; +FAUSTFLOAT fslider2; +double fRec0[3]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + fConst0 = (1413.7166941154069 / fSamplingFreq); + fConst1 = (2827.4333882308138 / fSamplingFreq); + for (int i=0; i<2; i++) fRec1[i] = 0; + for (int i=0; i<2; i++) fRec2[i] = 0; + for (int i=0; i<2; i++) fRec3[i] = 0; + for (int i=0; i<3; i++) fRec0[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = fslider0; + double fSlow1 = (1 - max(0, fSlow0)); + double fSlow2 = fslider1; + double fSlow3 = pow(2.0,(2.3 * fSlow2)); + double fSlow4 = (1 - (fConst0 * (fSlow3 / pow(2.0,(1.0 + (2.0 * (1.0 - fSlow2))))))); + double fSlow5 = (0.0010000000000000009 * (0 - (2.0 * (cos((fConst1 * fSlow3)) * fSlow4)))); + double fSlow6 = (0.0010000000000000009 * faustpower<2>(fSlow4)); + double fSlow7 = (0.0001000000000000001 * pow(4.0,fSlow2)); + double fSlow8 = fslider2; + double fSlow9 = (1 - max(0, (0 - fSlow0))); + for (int i=0; i(fSlow30)))); + double fSlow32 = (1.0 / fSlow30); + double fSlow33 = (1 + ((fSlow32 - 0.76536686473018) / fSlow30)); + double fSlow34 = (1.0 / (1 + ((0.76536686473018 + fSlow32) / fSlow30))); + double fSlow35 = (1 + ((fSlow32 - 1.847759065022573) / fSlow30)); + double fSlow36 = (1.0 / (1 + ((1.847759065022573 + fSlow32) / fSlow30))); + double fSlow37 = (fConst8 * fslider5); + double fSlow38 = (1.0 / (1 + fSlow37)); + double fSlow39 = (1 - fSlow37); + int iSlow40 = int(fcheckbox2); + double fSlow41 = (0.251188643150958 * ((1.251188643150958 + fSlow13) - fSlow14)); + double fSlow42 = (0.251188643150958 * (1.251188643150958 + fSlow15)); + double fSlow43 = (0.502377286301916 * (0 - (0.748811356849042 + fSlow11))); + double fSlow44 = (1.0 / ((1.251188643150958 + fSlow14) - fSlow13)); + double fSlow45 = (fSlow7 + fSlow6); + double fSlow46 = (0.251188643150958 * (1.251188643150958 - fSlow45)); + double fSlow47 = (0.251188643150958 * ((fSlow7 + 1.251188643150958) - fSlow6)); + double fSlow48 = (0 - (0.502377286301916 * (fSlow4 - 0.748811356849042))); + double fSlow49 = (1.0 / (1.251188643150958 + fSlow45)); + double fSlow50 = fslider6; + double fSlow51 = fslider8; + double fSlow52 = pow(1e+01,(2 * (fSlow51 * fslider7))); + double fSlow53 = (0.0010000000000000009 * pow(10,(0.05 * (fslider9 - 10)))); + double fSlow54 = pow(1e+01,(2 * (fSlow51 * fslider10))); + double fSlow55 = (0.0010000000000000009 * pow(10,(0.05 * (fslider11 - 10)))); + double fSlow56 = pow(1e+01,(2 * (fSlow51 * fslider12))); + for (int i=0; i(fTemp8)))); + fVec7[0] = fTemp9; + fRec3[0] = ((fVec7[0] + (0.995 * fRec3[1])) - fVec7[1]); + fRec15[0] = (fSlow53 + (0.999 * fRec15[1])); + double fTemp10 = max(-1, min(1, (fSlow54 * (fSlow50 + fRec5[0])))); + double fTemp11 = (fTemp10 * (1 - (0.3333333333333333 * faustpower<2>(fTemp10)))); + fVec8[0] = fTemp11; + fRec16[0] = ((fVec8[0] + (0.995 * fRec16[1])) - fVec8[1]); + fRec17[0] = (fSlow55 + (0.999 * fRec17[1])); + fRec19[0] = (fSlow49 * ((((fSlow48 * fRec6[1]) + (fSlow47 * fRec6[0])) + (fSlow46 * fRec6[2])) + ((fSlow8 * fRec19[2]) + (fSlow5 * fRec19[1])))); + double fTemp12 = max(-1, min(1, (fSlow56 * (fSlow50 + fRec19[0])))); + double fTemp13 = (fTemp12 * (1 - (0.3333333333333333 * faustpower<2>(fTemp12)))); + fVec9[0] = fTemp13; + fRec18[0] = ((fVec9[0] + (0.995 * fRec18[1])) - fVec9[1]); + double fTemp14 = ((((fRec18[0] * fRec17[0]) + (fRec16[0] * fRec15[0])) + (fRec3[0] * fRec2[0])) * fRec1[0]); + fVec10[0] = fTemp14; + fRec0[0] = (fConst15 * ((((fConst14 * fVec10[1]) + (fConst13 * fVec10[0])) + (fConst12 * fVec10[2])) + ((fConst6 * fRec0[2]) + (fConst3 * fRec0[1])))); + double fTemp15 = (fRec7[0] + fRec0[0]); + fVec11[0] = (fSlow38 * fTemp15); + fRec23[0] = ((fSlow38 * (fTemp15 + (fSlow39 * fRec23[1]))) - fVec11[1]); + fVec12[0] = (fSlow38 * fRec23[0]); + fRec22[0] = ((fSlow38 * (fRec23[0] + (fSlow39 * fRec22[1]))) - fVec12[1]); + fRec21[0] = (fRec22[0] - (fSlow36 * ((fSlow35 * fRec21[2]) + (fSlow31 * fRec21[1])))); + fRec20[0] = ((fSlow36 * (fRec21[2] + (fRec21[0] + (2 * fRec21[1])))) - (fSlow34 * ((fSlow33 * fRec20[2]) + (fSlow31 * fRec20[1])))); + output0[i] = (FAUSTFLOAT)((iSlow40)?(fSlow34 * (fRec20[2] + (fRec20[0] + (2 * fRec20[1])))):fRec0[0]); + // post processing + fRec20[2] = fRec20[1]; fRec20[1] = fRec20[0]; + fRec21[2] = fRec21[1]; fRec21[1] = fRec21[0]; + fRec22[1] = fRec22[0]; + fVec12[1] = fVec12[0]; + fRec23[1] = fRec23[0]; + fVec11[1] = fVec11[0]; + fRec0[2] = fRec0[1]; fRec0[1] = fRec0[0]; + fVec10[2] = fVec10[1]; fVec10[1] = fVec10[0]; + fRec18[1] = fRec18[0]; + fVec9[1] = fVec9[0]; + fRec19[2] = fRec19[1]; fRec19[1] = fRec19[0]; + fRec17[1] = fRec17[0]; + fRec16[1] = fRec16[0]; + fVec8[1] = fVec8[0]; + fRec15[1] = fRec15[0]; + fRec3[1] = fRec3[0]; + fVec7[1] = fVec7[0]; + fRec4[2] = fRec4[1]; fRec4[1] = fRec4[0]; + fRec5[2] = fRec5[1]; fRec5[1] = fRec5[0]; + fRec6[2] = fRec6[1]; fRec6[1] = fRec6[0]; + fVec6[2] = fVec6[1]; fVec6[1] = fVec6[0]; + fRec11[2] = fRec11[1]; fRec11[1] = fRec11[0]; + fRec12[2] = fRec12[1]; fRec12[1] = fRec12[0]; + fRec13[1] = fRec13[0]; + fVec5[1] = fVec5[0]; + fRec14[1] = fRec14[0]; + fVec4[1] = fVec4[0]; + fRec9[1] = fRec9[0]; + fVec3[1] = fVec3[0]; + fRec10[1] = fRec10[0]; + fVec2[1] = fVec2[0]; + fRec8[1] = fRec8[0]; + IOTA = IOTA+1; + fRec7[1] = fRec7[0]; + fRec2[1] = fRec2[0]; + fRec1[1] = fRec1[0]; + iVec0[1] = iVec0[0]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("distortion.low_drive","","S","",&fslider12, 1.0, 0.0, 1.0, 0.01); + registerVar("distortion.low_gain","","S","",&fslider11, 1e+01, -1e+01, 2e+01, 0.1); + registerVar("distortion.high_drive","","S","",&fslider10, 1.0, 0.0, 1.0, 0.01); + registerVar("distortion.low_highpass.on_off","low highpass","B","",&fcheckbox1, 0.0, 0.0, 1.0, 1.0); + registerVar("distortion.resonator.on_off","resonat","B","",&fcheckbox0, 0.0, 0.0, 1.0, 1.0); + registerVar("distortion.low_highcutoff.on_off","low highcutoff","B","",&fcheckbox2, 0.0, 0.0, 1.0, 1.0); + registerVar("distortion.split_low_freq","","S","",&fentry1, 2.5e+02, 2e+01, 6e+02, 1e+01); + registerVar("distortion.split_high_freq","","S","",&fentry0, 6.5e+02, 6e+02, 1.25e+03, 1e+01); + registerVar("distortion.low_highpass.high_freq","high freq","S","",&fentry3, 1.3e+02, 2e+01, 7.04e+03, 1e+01); + registerVar("distortion.low_highpass.low_freq","low freq","S","",&fentry2, 5e+03, 2e+01, 1.2e+04, 1e+01); + registerVar("distortion.middle_drive","","S","",&fslider7, 1.0, 0.0, 1.0, 0.01); + registerVar("distortion.level","","S","",&fslider6, 0.01, 0.0, 0.5, 0.01); + registerVar("distortion.low_highcutoff.low_freq","low freq","S","low-freq cutoff Hz",&fslider5, 1.3e+02, 2e+01, 1e+03, 1e+01); + registerVar("distortion.low_highcutoff.high_freq","high freq","S","high-freq cutoff Hz",&fslider4, 5e+03, 1e+03, 1.2e+04, 1e+01); + registerVar("distortion.vibrato","","S","",&fslider3, 1.0, 0.0, 1.0, 0.01); + registerVar("distortion.trigger","","S","",&fslider2, 0.12, 0.0, 1.0, 0.01); + registerVar("distortion.middle_gain","","S","",&fslider1, 1e+01, -1e+01, 2e+01, 0.1); + registerVar("distortion.gain","","S","",&fslider0, 2.0, -1e+01, 1e+01, 0.1); + registerVar("distortion.high_gain","","S","",&fslider9, 1e+01, -1e+01, 2e+01, 0.1); + registerVar("distortion.drive","","S","",&fslider8, 0.64, 0.0, 1.0, 0.01); + registerInit("distortion", init); +} + +} // end namespace distortion diff --git a/src/faust-cc/distortion1.cc b/src/faust-cc/distortion1.cc new file mode 100644 index 0000000..29e0c8e --- /dev/null +++ b/src/faust-cc/distortion1.cc @@ -0,0 +1,228 @@ +namespace distortion1 { +// generated from file '../src/faust/distortion1.dsp' + +int iVec0[2]; +double fConst0; +double fConst1; +double fConst2; +double fConst3; +double fConst4; +double fConst5; +double fConst6; +FAUSTFLOAT fslider0; +double fRec1[2]; +double fRec4[2]; +FAUSTFLOAT fslider1; +int IOTA; +double fVec1[4096]; +FAUSTFLOAT fslider2; +double fRec5[2]; +FAUSTFLOAT fcheckbox0; +FAUSTFLOAT fentry0; +double fConst7; +double fVec2[2]; +double fRec7[2]; +FAUSTFLOAT fentry1; +double fConst8; +double fConst9; +double fVec3[2]; +double fRec6[2]; +FAUSTFLOAT fcheckbox1; +FAUSTFLOAT fslider3; +FAUSTFLOAT fslider4; +double fVec4[2]; +double fRec11[2]; +double fVec5[2]; +double fRec10[2]; +double fRec9[3]; +double fRec8[3]; +FAUSTFLOAT fcheckbox2; +double fVec6[3]; +double fConst10; +double fConst11; +double fConst12; +double fConst13; +double fConst14; +double fRec3[3]; +FAUSTFLOAT fslider5; +FAUSTFLOAT fslider6; +double fVec7[2]; +double fRec2[2]; +double fVec8[3]; +double fRec0[3]; +double fVec9[2]; +double fRec15[2]; +double fVec10[2]; +double fRec14[2]; +double fRec13[3]; +double fRec12[3]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + for (int i=0; i<2; i++) iVec0[i] = 0; + fConst0 = (6.283185307179586 * (max(0, ((0.5 * fSamplingFreq) - 1e+02)) / fSamplingFreq)); + fConst1 = cos(fConst0); + fConst2 = (1.316227766016838 * fConst1); + fConst3 = (0 - (2 * (0 - (0.683772233983162 + fConst2)))); + fConst4 = (0.683772233983162 * fConst1); + fConst5 = (0.005623413251903491 * sin(fConst0)); + fConst6 = (fConst5 - (fConst4 + 1.316227766016838)); + for (int i=0; i<2; i++) fRec1[i] = 0; + for (int i=0; i<2; i++) fRec4[i] = 0; + IOTA = 0; + for (int i=0; i<4096; i++) fVec1[i] = 0; + for (int i=0; i<2; i++) fRec5[i] = 0; + fConst7 = (3.141592653589793 / fSamplingFreq); + for (int i=0; i<2; i++) fVec2[i] = 0; + for (int i=0; i<2; i++) fRec7[i] = 0; + fConst8 = (3.141592653589793 * fSamplingFreq); + fConst9 = (0.5 / fSamplingFreq); + for (int i=0; i<2; i++) fVec3[i] = 0; + for (int i=0; i<2; i++) fRec6[i] = 0; + for (int i=0; i<2; i++) fVec4[i] = 0; + for (int i=0; i<2; i++) fRec11[i] = 0; + for (int i=0; i<2; i++) fVec5[i] = 0; + for (int i=0; i<2; i++) fRec10[i] = 0; + for (int i=0; i<3; i++) fRec9[i] = 0; + for (int i=0; i<3; i++) fRec8[i] = 0; + for (int i=0; i<3; i++) fVec6[i] = 0; + fConst10 = (fConst5 + fConst4); + fConst11 = (0.31622776601683794 * (1.316227766016838 - fConst10)); + fConst12 = (0.31622776601683794 * ((fConst5 + 1.316227766016838) - fConst4)); + fConst13 = (0 - (0.6324555320336759 * (fConst2 - 0.683772233983162))); + fConst14 = (1.0 / (1.316227766016838 + fConst10)); + for (int i=0; i<3; i++) fRec3[i] = 0; + for (int i=0; i<2; i++) fVec7[i] = 0; + for (int i=0; i<2; i++) fRec2[i] = 0; + for (int i=0; i<3; i++) fVec8[i] = 0; + for (int i=0; i<3; i++) fRec0[i] = 0; + for (int i=0; i<2; i++) fVec9[i] = 0; + for (int i=0; i<2; i++) fRec15[i] = 0; + for (int i=0; i<2; i++) fVec10[i] = 0; + for (int i=0; i<2; i++) fRec14[i] = 0; + for (int i=0; i<3; i++) fRec13[i] = 0; + for (int i=0; i<3; i++) fRec12[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = (0.0010000000000000009 * pow(10,(0.05 * (fslider0 - 10)))); + double fSlow1 = (1.0 - fslider1); + double fSlow2 = fslider2; + int iSlow3 = int((int((fSlow2 - 1)) & 4095)); + int iSlow4 = int((int(fSlow2) & 4095)); + int iSlow5 = int(fcheckbox0); + double fSlow6 = (1.0 / tan((fConst7 * fentry0))); + double fSlow7 = (fSlow6 - 1); + double fSlow8 = (1.0 / (1 + fSlow6)); + double fSlow9 = (1.0 / tan((fConst9 * (fConst8 - (6.283185307179586 * fentry1))))); + double fSlow10 = (1 + fSlow9); + double fSlow11 = (1.0 / fSlow10); + double fSlow12 = (0 - ((fSlow9 - 1) / fSlow10)); + int iSlow13 = int(fcheckbox1); + double fSlow14 = tan((fConst7 * fslider3)); + double fSlow15 = (2 * (1 - (1.0 / faustpower<2>(fSlow14)))); + double fSlow16 = (1.0 / fSlow14); + double fSlow17 = (1 + ((fSlow16 - 0.76536686473018) / fSlow14)); + double fSlow18 = (1.0 / (1 + ((0.76536686473018 + fSlow16) / fSlow14))); + double fSlow19 = (1 + ((fSlow16 - 1.847759065022573) / fSlow14)); + double fSlow20 = (1.0 / (1 + ((1.847759065022573 + fSlow16) / fSlow14))); + double fSlow21 = (fConst7 * fslider4); + double fSlow22 = (1.0 / (1 + fSlow21)); + double fSlow23 = (1 - fSlow21); + int iSlow24 = int(fcheckbox2); + double fSlow25 = fslider5; + double fSlow26 = pow(1e+01,(2 * fslider6)); + for (int i=0; i(fTemp8)))); + fVec7[0] = fTemp9; + fRec2[0] = ((fVec7[0] + (0.995 * fRec2[1])) - fVec7[1]); + double fTemp10 = (fRec2[0] * fRec1[0]); + fVec8[0] = fTemp10; + fRec0[0] = (fConst14 * ((((fConst13 * fVec8[1]) + (fConst12 * fVec8[0])) + (fConst11 * fVec8[2])) + ((fConst6 * fRec0[2]) + (fConst3 * fRec0[1])))); + double fTemp11 = (fRec4[0] + fRec0[0]); + fVec9[0] = (fSlow22 * fTemp11); + fRec15[0] = ((fSlow22 * (fTemp11 + (fSlow23 * fRec15[1]))) - fVec9[1]); + fVec10[0] = (fSlow22 * fRec15[0]); + fRec14[0] = ((fSlow22 * (fRec15[0] + (fSlow23 * fRec14[1]))) - fVec10[1]); + fRec13[0] = (fRec14[0] - (fSlow20 * ((fSlow19 * fRec13[2]) + (fSlow15 * fRec13[1])))); + fRec12[0] = ((fSlow20 * (fRec13[2] + (fRec13[0] + (2 * fRec13[1])))) - (fSlow18 * ((fSlow17 * fRec12[2]) + (fSlow15 * fRec12[1])))); + output0[i] = (FAUSTFLOAT)((iSlow24)?(fSlow18 * (fRec12[2] + (fRec12[0] + (2 * fRec12[1])))):fRec0[0]); + // post processing + fRec12[2] = fRec12[1]; fRec12[1] = fRec12[0]; + fRec13[2] = fRec13[1]; fRec13[1] = fRec13[0]; + fRec14[1] = fRec14[0]; + fVec10[1] = fVec10[0]; + fRec15[1] = fRec15[0]; + fVec9[1] = fVec9[0]; + fRec0[2] = fRec0[1]; fRec0[1] = fRec0[0]; + fVec8[2] = fVec8[1]; fVec8[1] = fVec8[0]; + fRec2[1] = fRec2[0]; + fVec7[1] = fVec7[0]; + fRec3[2] = fRec3[1]; fRec3[1] = fRec3[0]; + fVec6[2] = fVec6[1]; fVec6[1] = fVec6[0]; + fRec8[2] = fRec8[1]; fRec8[1] = fRec8[0]; + fRec9[2] = fRec9[1]; fRec9[1] = fRec9[0]; + fRec10[1] = fRec10[0]; + fVec5[1] = fVec5[0]; + fRec11[1] = fRec11[0]; + fVec4[1] = fVec4[0]; + fRec6[1] = fRec6[0]; + fVec3[1] = fVec3[0]; + fRec7[1] = fRec7[0]; + fVec2[1] = fVec2[0]; + fRec5[1] = fRec5[0]; + IOTA = IOTA+1; + fRec4[1] = fRec4[0]; + fRec1[1] = fRec1[0]; + iVec0[1] = iVec0[0]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("distortion1.low_highpass.on_off","low highpass","B","",&fcheckbox1, 0.0, 0.0, 1.0, 1.0); + registerVar("distortion1.resonator.on_off","resonat","B","",&fcheckbox0, 0.0, 0.0, 1.0, 1.0); + registerVar("distortion1.low_highcutoff.on_off","low highcutoff","B","",&fcheckbox2, 0.0, 0.0, 1.0, 1.0); + registerVar("distortion1.low_highpass.high_freq","high freq","S","",&fentry1, 1.3e+02, 2e+01, 7.04e+03, 1e+01); + registerVar("distortion1.low_highpass.low_freq","low freq","S","",&fentry0, 5e+03, 2e+01, 1.2e+04, 1e+01); + registerVar("distortion1.drive","","S","",&fslider6, 0.64, 0.0, 1.0, 0.01); + registerVar("distortion1.level","","S","",&fslider5, 0.01, 0.0, 0.5, 0.01); + registerVar("distortion1.low_highcutoff.low_freq","low freq","S","low-freq cutoff Hz",&fslider4, 1.3e+02, 2e+01, 1e+03, 1e+01); + registerVar("distortion1.low_highcutoff.high_freq","high freq","S","high-freq cutoff Hz",&fslider3, 5e+03, 1e+03, 1.2e+04, 1e+01); + registerVar("distortion1.vibrato","","S","",&fslider2, 1.0, 0.0, 1.0, 0.01); + registerVar("distortion1.trigger","","S","",&fslider1, 0.12, 0.0, 1.0, 0.01); + registerVar("distortion1.gain","","S","",&fslider0, 2.0, -1e+01, 1e+01, 0.1); + registerInit("distortion1", init); +} + +} // end namespace distortion1 diff --git a/src/faust-cc/drive.cc b/src/faust-cc/drive.cc new file mode 100644 index 0000000..d735d90 --- /dev/null +++ b/src/faust-cc/drive.cc @@ -0,0 +1,28 @@ +namespace drive { +// generated from file '../src/faust/drive.dsp' + +FAUSTFLOAT fslider0; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = (0.0625 * fslider0); + for (int i=0; i(fConst0) - 1)); + fConst2 = tan((25132.741228718343 / fSamplingFreq)); + fConst3 = (2 * (faustpower<2>(fConst2) - 1)); + fConst4 = tan((12566.370614359172 / fSamplingFreq)); + fConst5 = (2 * (faustpower<2>(fConst4) - 1)); + fConst6 = tan((6283.185307179586 / fSamplingFreq)); + fConst7 = (2 * (faustpower<2>(fConst6) - 1)); + fConst8 = tan((3141.592653589793 / fSamplingFreq)); + fConst9 = (2 * (faustpower<2>(fConst8) - 1)); + fConst10 = tan((1570.7963267948965 / fSamplingFreq)); + fConst11 = (2 * (faustpower<2>(fConst10) - 1)); + fConst12 = tan((785.3981633974482 / fSamplingFreq)); + fConst13 = (2 * (faustpower<2>(fConst12) - 1)); + fConst14 = tan((392.6990816987241 / fSamplingFreq)); + fConst15 = (2 * (faustpower<2>(fConst14) - 1)); + fConst16 = tan((196.34954084936206 / fSamplingFreq)); + fConst17 = (2 * (faustpower<2>(fConst16) - 1)); + fConst18 = tan((98.17477042468103 / fSamplingFreq)); + fConst19 = (2 * (faustpower<2>(fConst18) - 1)); + for (int i=0; i<3; i++) fRec9[i] = 0; + for (int i=0; i<3; i++) fRec8[i] = 0; + for (int i=0; i<3; i++) fRec7[i] = 0; + for (int i=0; i<3; i++) fRec6[i] = 0; + for (int i=0; i<3; i++) fRec5[i] = 0; + for (int i=0; i<3; i++) fRec4[i] = 0; + for (int i=0; i<3; i++) fRec3[i] = 0; + for (int i=0; i<3; i++) fRec2[i] = 0; + for (int i=0; i<3; i++) fRec1[i] = 0; + for (int i=0; i<3; i++) fRec0[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = fslider0; + double fSlow1 = (pow(10,(0.05 * (0 - fslider1))) / fSlow0); + double fSlow2 = (1 + (fConst0 * (fConst0 - fSlow1))); + double fSlow3 = (1.0 / (1 + (fConst0 * (fConst0 + fSlow1)))); + double fSlow4 = fslider2; + double fSlow5 = (pow(10,(0.05 * (0 - fslider3))) / fSlow4); + double fSlow6 = (1 + (fConst2 * (fConst2 - fSlow5))); + double fSlow7 = (1.0 / (1 + (fConst2 * (fConst2 + fSlow5)))); + double fSlow8 = fslider4; + double fSlow9 = (pow(10,(0.05 * (0 - fslider5))) / fSlow8); + double fSlow10 = (1 + (fConst4 * (fConst4 - fSlow9))); + double fSlow11 = (1.0 / (1 + (fConst4 * (fConst4 + fSlow9)))); + double fSlow12 = fslider6; + double fSlow13 = (pow(10,(0.05 * (0 - fslider7))) / fSlow12); + double fSlow14 = (1 + (fConst6 * (fConst6 - fSlow13))); + double fSlow15 = (1.0 / (1 + (fConst6 * (fConst6 + fSlow13)))); + double fSlow16 = fslider8; + double fSlow17 = (pow(10,(0.05 * (0 - fslider9))) / fSlow16); + double fSlow18 = (1 + (fConst8 * (fConst8 - fSlow17))); + double fSlow19 = (1.0 / (1 + (fConst8 * (fConst8 + fSlow17)))); + double fSlow20 = fslider10; + double fSlow21 = (pow(10,(0.05 * (0 - fslider11))) / fSlow20); + double fSlow22 = (1 + (fConst10 * (fConst10 - fSlow21))); + double fSlow23 = (1.0 / (1 + (fConst10 * (fConst10 + fSlow21)))); + double fSlow24 = fslider12; + double fSlow25 = (pow(10,(0.05 * (0 - fslider13))) / fSlow24); + double fSlow26 = (1 + (fConst12 * (fConst12 - fSlow25))); + double fSlow27 = (1.0 / (1 + (fConst12 * (fConst12 + fSlow25)))); + double fSlow28 = fslider14; + double fSlow29 = (pow(10,(0.05 * (0 - fslider15))) / fSlow28); + double fSlow30 = (1 + (fConst14 * (fConst14 - fSlow29))); + double fSlow31 = (1.0 / (1 + (fConst14 * (fConst14 + fSlow29)))); + double fSlow32 = fslider16; + double fSlow33 = (pow(10,(0.05 * (0 - fslider17))) / fSlow32); + double fSlow34 = (1 + (fConst16 * (fConst16 - fSlow33))); + double fSlow35 = (1.0 / (1 + (fConst16 * (fConst16 + fSlow33)))); + double fSlow36 = fslider18; + double fSlow37 = (pow(10,(0.05 * (0 - fslider19))) / fSlow36); + double fSlow38 = (1 + (fConst18 * (fConst18 - fSlow37))); + double fSlow39 = (1.0 / (1 + (fConst18 * (fConst18 + fSlow37)))); + double fSlow40 = (1.0 / fSlow36); + double fSlow41 = (1 + (fConst18 * (fConst18 - fSlow40))); + double fSlow42 = (1 + (fConst18 * (fConst18 + fSlow40))); + double fSlow43 = (1.0 / fSlow32); + double fSlow44 = (1 + (fConst16 * (fConst16 - fSlow43))); + double fSlow45 = (1 + (fConst16 * (fConst16 + fSlow43))); + double fSlow46 = (1.0 / fSlow28); + double fSlow47 = (1 + (fConst14 * (fConst14 - fSlow46))); + double fSlow48 = (1 + (fConst14 * (fConst14 + fSlow46))); + double fSlow49 = (1.0 / fSlow24); + double fSlow50 = (1 + (fConst12 * (fConst12 - fSlow49))); + double fSlow51 = (1 + (fConst12 * (fConst12 + fSlow49))); + double fSlow52 = (1.0 / fSlow20); + double fSlow53 = (1 + (fConst10 * (fConst10 - fSlow52))); + double fSlow54 = (1 + (fConst10 * (fConst10 + fSlow52))); + double fSlow55 = (1.0 / fSlow16); + double fSlow56 = (1 + (fConst8 * (fConst8 - fSlow55))); + double fSlow57 = (1 + (fConst8 * (fConst8 + fSlow55))); + double fSlow58 = (1.0 / fSlow12); + double fSlow59 = (1 + (fConst6 * (fConst6 - fSlow58))); + double fSlow60 = (1 + (fConst6 * (fConst6 + fSlow58))); + double fSlow61 = (1.0 / fSlow8); + double fSlow62 = (1 + (fConst4 * (fConst4 - fSlow61))); + double fSlow63 = (1 + (fConst4 * (fConst4 + fSlow61))); + double fSlow64 = (1.0 / fSlow4); + double fSlow65 = (1 + (fConst2 * (fConst2 - fSlow64))); + double fSlow66 = (1 + (fConst2 * (fConst2 + fSlow64))); + double fSlow67 = (1.0 / fSlow0); + double fSlow68 = (1 + (fConst0 * (fConst0 - fSlow67))); + double fSlow69 = (1 + (fConst0 * (fConst0 + fSlow67))); + for (int i=0; i0; i--) fRec0[i] = fRec0[i-1]; + for (int i=3; i>0; i--) fVec0[i] = fVec0[i-1]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("amp.feedforward","Feedforward","S","",&fslider2, 0.0, -1.0, 1.0, 0.01); + registerVar("amp.feedback","Feedback","S","",&fslider1, 0.0, -1.0, 1.0, 0.01); + registerVar("amp.fuzz","fuzz","S","",&fslider0, 1.0, 0.0, 1.0, 0.01); + registerInit("amp", init); +} + +} // end namespace feed diff --git a/src/faust-cc/flanger.cc b/src/faust-cc/flanger.cc new file mode 100644 index 0000000..31cbb78 --- /dev/null +++ b/src/faust-cc/flanger.cc @@ -0,0 +1,92 @@ +namespace flanger { +// generated from file '../src/faust/flanger.dsp' + +FAUSTFLOAT fslider0; +int iVec0[2]; +FAUSTFLOAT fslider1; +int IOTA; +double fVec1[2048]; +FAUSTFLOAT fslider2; +double fConst0; +double fRec1[2]; +double fRec2[2]; +FAUSTFLOAT fslider3; +FAUSTFLOAT fslider4; +double fRec0[2]; +FAUSTFLOAT fslider5; +FAUSTFLOAT fcheckbox0; +double fVec2[2048]; +double fRec3[2]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + for (int i=0; i<2; i++) iVec0[i] = 0; + IOTA = 0; + for (int i=0; i<2048; i++) fVec1[i] = 0; + fConst0 = (6.283185307179586 / fSamplingFreq); + for (int i=0; i<2; i++) fRec1[i] = 0; + for (int i=0; i<2; i++) fRec2[i] = 0; + for (int i=0; i<2; i++) fRec0[i] = 0; + for (int i=0; i<2048; i++) fVec2[i] = 0; + for (int i=0; i<2; i++) fRec3[i] = 0; +} + +void compute(int count, float *input0, float *input1, float *output0, float *output1) +{ + double fSlow0 = pow(10,(0.05 * fslider0)); + double fSlow1 = fslider1; + double fSlow2 = (fConst0 * fslider2); + double fSlow3 = sin(fSlow2); + double fSlow4 = cos(fSlow2); + double fSlow5 = (0 - fSlow3); + double fSlow6 = (0.0005 * fslider3); + double fSlow7 = (0.001 * fslider4); + double fSlow8 = fslider5; + double fSlow9 = ((int(fcheckbox0))?(0 - fSlow8):fSlow8); + for (int i=0; i(fSlow0)))); + for (int i=0; i(fTemp0); + double fTemp2 = (1.0 - fTemp0); + fRec6[0] = ((1e-20 * (1 - iVec0[1])) - fRec6[1]); + fRec5[0] = ((((double)input0[i] + fRec6[0]) + (fSlow1 * fRec0[1])) + (fTemp2 * fRec5[1])); + fRec4[0] = (fRec5[0] + (fTemp2 * fRec4[1])); + fRec3[0] = (fRec4[0] + (fTemp2 * fRec3[1])); + fRec2[0] = (fRec3[0] + (fTemp2 * fRec2[1])); + fRec0[0] = (fRec2[0] * fTemp1); + output0[i] = (FAUSTFLOAT)fRec0[0]; + fRec11[0] = ((((double)input1[i] + fRec6[0]) + (fSlow1 * fRec7[1])) + (fTemp2 * fRec11[1])); + fRec10[0] = (fRec11[0] + (fTemp2 * fRec10[1])); + fRec9[0] = (fRec10[0] + (fTemp2 * fRec9[1])); + fRec8[0] = (fRec9[0] + (fTemp2 * fRec8[1])); + fRec7[0] = (fRec8[0] * fTemp1); + output1[i] = (FAUSTFLOAT)fRec7[0]; + // post processing + fRec7[1] = fRec7[0]; + fRec8[1] = fRec8[0]; + fRec9[1] = fRec9[0]; + fRec10[1] = fRec10[0]; + fRec11[1] = fRec11[0]; + fRec0[1] = fRec0[0]; + fRec2[1] = fRec2[0]; + fRec3[1] = fRec3[0]; + fRec4[1] = fRec4[0]; + fRec5[1] = fRec5[0]; + fRec6[1] = fRec6[0]; + fRec1[1] = fRec1[0]; + iVec0[1] = iVec0[0]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("moog.Q","","S","",&fslider1, 1.0, 0.0, 4.0, 0.1); + registerVar("moog.fr","","S","",&fslider0, 3e+03, 4.4e+02, 6e+03, 1e+01); + registerInit("moog", init); +} + +} // end namespace moog diff --git a/src/faust-cc/multifilter.cc b/src/faust-cc/multifilter.cc new file mode 100644 index 0000000..6d8257e --- /dev/null +++ b/src/faust-cc/multifilter.cc @@ -0,0 +1,225 @@ +namespace multifilter { +// generated from file '../src/faust/multifilter.dsp' + +double fConst0; +double fConst1; +FAUSTFLOAT fslider0; +FAUSTFLOAT fslider1; +double fConst2; +double fConst3; +FAUSTFLOAT fslider2; +FAUSTFLOAT fslider3; +double fConst4; +double fConst5; +FAUSTFLOAT fslider4; +FAUSTFLOAT fslider5; +double fConst6; +double fConst7; +FAUSTFLOAT fslider6; +FAUSTFLOAT fslider7; +double fConst8; +double fConst9; +FAUSTFLOAT fslider8; +FAUSTFLOAT fslider9; +double fConst10; +double fConst11; +FAUSTFLOAT fslider10; +FAUSTFLOAT fslider11; +double fConst12; +double fConst13; +FAUSTFLOAT fslider12; +FAUSTFLOAT fslider13; +double fConst14; +double fConst15; +FAUSTFLOAT fslider14; +FAUSTFLOAT fslider15; +double fConst16; +double fConst17; +FAUSTFLOAT fslider16; +FAUSTFLOAT fslider17; +double fConst18; +double fConst19; +FAUSTFLOAT fslider18; +FAUSTFLOAT fslider19; +double fRec9[3]; +double fRec8[3]; +double fRec7[3]; +double fRec6[3]; +double fRec5[3]; +double fRec4[3]; +double fRec3[3]; +double fRec2[3]; +double fRec1[3]; +double fRec0[3]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + fConst0 = tan((50265.48245743669 / fSamplingFreq)); + fConst1 = (2 * (faustpower<2>(fConst0) - 1)); + fConst2 = tan((25132.741228718343 / fSamplingFreq)); + fConst3 = (2 * (faustpower<2>(fConst2) - 1)); + fConst4 = tan((12566.370614359172 / fSamplingFreq)); + fConst5 = (2 * (faustpower<2>(fConst4) - 1)); + fConst6 = tan((6283.185307179586 / fSamplingFreq)); + fConst7 = (2 * (faustpower<2>(fConst6) - 1)); + fConst8 = tan((3141.592653589793 / fSamplingFreq)); + fConst9 = (2 * (faustpower<2>(fConst8) - 1)); + fConst10 = tan((1570.7963267948965 / fSamplingFreq)); + fConst11 = (2 * (faustpower<2>(fConst10) - 1)); + fConst12 = tan((785.3981633974482 / fSamplingFreq)); + fConst13 = (2 * (faustpower<2>(fConst12) - 1)); + fConst14 = tan((392.6990816987241 / fSamplingFreq)); + fConst15 = (2 * (faustpower<2>(fConst14) - 1)); + fConst16 = tan((196.34954084936206 / fSamplingFreq)); + fConst17 = (2 * (faustpower<2>(fConst16) - 1)); + fConst18 = tan((98.17477042468103 / fSamplingFreq)); + fConst19 = (2 * (faustpower<2>(fConst18) - 1)); + for (int i=0; i<3; i++) fRec9[i] = 0; + for (int i=0; i<3; i++) fRec8[i] = 0; + for (int i=0; i<3; i++) fRec7[i] = 0; + for (int i=0; i<3; i++) fRec6[i] = 0; + for (int i=0; i<3; i++) fRec5[i] = 0; + for (int i=0; i<3; i++) fRec4[i] = 0; + for (int i=0; i<3; i++) fRec3[i] = 0; + for (int i=0; i<3; i++) fRec2[i] = 0; + for (int i=0; i<3; i++) fRec1[i] = 0; + for (int i=0; i<3; i++) fRec0[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = fslider0; + double fSlow1 = (pow(10,(0.05 * (0 - fslider1))) / fSlow0); + double fSlow2 = (1 + (fConst0 * (fConst0 - fSlow1))); + double fSlow3 = (1.0 / (1 + (fConst0 * (fConst0 + fSlow1)))); + double fSlow4 = fslider2; + double fSlow5 = (pow(10,(0.05 * (0 - fslider3))) / fSlow4); + double fSlow6 = (1 + (fConst2 * (fConst2 - fSlow5))); + double fSlow7 = (1.0 / (1 + (fConst2 * (fConst2 + fSlow5)))); + double fSlow8 = fslider4; + double fSlow9 = (pow(10,(0.05 * (0 - fslider5))) / fSlow8); + double fSlow10 = (1 + (fConst4 * (fConst4 - fSlow9))); + double fSlow11 = (1.0 / (1 + (fConst4 * (fConst4 + fSlow9)))); + double fSlow12 = fslider6; + double fSlow13 = (pow(10,(0.05 * (0 - fslider7))) / fSlow12); + double fSlow14 = (1 + (fConst6 * (fConst6 - fSlow13))); + double fSlow15 = (1.0 / (1 + (fConst6 * (fConst6 + fSlow13)))); + double fSlow16 = fslider8; + double fSlow17 = (pow(10,(0.05 * (0 - fslider9))) / fSlow16); + double fSlow18 = (1 + (fConst8 * (fConst8 - fSlow17))); + double fSlow19 = (1.0 / (1 + (fConst8 * (fConst8 + fSlow17)))); + double fSlow20 = fslider10; + double fSlow21 = (pow(10,(0.05 * (0 - fslider11))) / fSlow20); + double fSlow22 = (1 + (fConst10 * (fConst10 - fSlow21))); + double fSlow23 = (1.0 / (1 + (fConst10 * (fConst10 + fSlow21)))); + double fSlow24 = fslider12; + double fSlow25 = (pow(10,(0.05 * (0 - fslider13))) / fSlow24); + double fSlow26 = (1 + (fConst12 * (fConst12 - fSlow25))); + double fSlow27 = (1.0 / (1 + (fConst12 * (fConst12 + fSlow25)))); + double fSlow28 = fslider14; + double fSlow29 = (pow(10,(0.05 * (0 - fslider15))) / fSlow28); + double fSlow30 = (1 + (fConst14 * (fConst14 - fSlow29))); + double fSlow31 = (1.0 / (1 + (fConst14 * (fConst14 + fSlow29)))); + double fSlow32 = fslider16; + double fSlow33 = (pow(10,(0.05 * (0 - fslider17))) / fSlow32); + double fSlow34 = (1 + (fConst16 * (fConst16 - fSlow33))); + double fSlow35 = (1.0 / (1 + (fConst16 * (fConst16 + fSlow33)))); + double fSlow36 = fslider18; + double fSlow37 = (pow(10,(0.05 * (0 - fslider19))) / fSlow36); + double fSlow38 = (1 + (fConst18 * (fConst18 - fSlow37))); + double fSlow39 = (1.0 / (1 + (fConst18 * (fConst18 + fSlow37)))); + double fSlow40 = (1.0 / fSlow36); + double fSlow41 = (1 + (fConst18 * (fConst18 - fSlow40))); + double fSlow42 = (1 + (fConst18 * (fConst18 + fSlow40))); + double fSlow43 = (1.0 / fSlow32); + double fSlow44 = (1 + (fConst16 * (fConst16 - fSlow43))); + double fSlow45 = (1 + (fConst16 * (fConst16 + fSlow43))); + double fSlow46 = (1.0 / fSlow28); + double fSlow47 = (1 + (fConst14 * (fConst14 - fSlow46))); + double fSlow48 = (1 + (fConst14 * (fConst14 + fSlow46))); + double fSlow49 = (1.0 / fSlow24); + double fSlow50 = (1 + (fConst12 * (fConst12 - fSlow49))); + double fSlow51 = (1 + (fConst12 * (fConst12 + fSlow49))); + double fSlow52 = (1.0 / fSlow20); + double fSlow53 = (1 + (fConst10 * (fConst10 - fSlow52))); + double fSlow54 = (1 + (fConst10 * (fConst10 + fSlow52))); + double fSlow55 = (1.0 / fSlow16); + double fSlow56 = (1 + (fConst8 * (fConst8 - fSlow55))); + double fSlow57 = (1 + (fConst8 * (fConst8 + fSlow55))); + double fSlow58 = (1.0 / fSlow12); + double fSlow59 = (1 + (fConst6 * (fConst6 - fSlow58))); + double fSlow60 = (1 + (fConst6 * (fConst6 + fSlow58))); + double fSlow61 = (1.0 / fSlow8); + double fSlow62 = (1 + (fConst4 * (fConst4 - fSlow61))); + double fSlow63 = (1 + (fConst4 * (fConst4 + fSlow61))); + double fSlow64 = (1.0 / fSlow4); + double fSlow65 = (1 + (fConst2 * (fConst2 - fSlow64))); + double fSlow66 = (1 + (fConst2 * (fConst2 + fSlow64))); + double fSlow67 = (1.0 / fSlow0); + double fSlow68 = (1 + (fConst0 * (fConst0 - fSlow67))); + double fSlow69 = (1 + (fConst0 * (fConst0 + fSlow67))); + for (int i=0; i= fTemp1)) + (fConst0 * (fRec0[1] < fTemp1))); + fRec0[0] = ((fTemp1 * (0 - (fTemp2 - 1))) + (fRec0[1] * fTemp2)); + double fTemp3 = max(0, (fSlow1 + (20 * log10(fRec0[0])))); + double fTemp4 = (0.5 * min(1, max(0, (0.09522902580706599 * fTemp3)))); + output0[i] = (FAUSTFLOAT)(fTemp0 * pow(10,(0.05 * (fSlow0 + ((fTemp3 * (0 - fTemp4)) / (1 + fTemp4)))))); + // post processing + fRec0[1] = fRec0[0]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("shaper.sharper","sharper","S","",&fslider0, 1.0, 1.0, 1e+01, 1.0); + registerInit("shaper", init); +} + +} // end namespace noise_shaper diff --git a/src/faust-cc/osc_tube.cc b/src/faust-cc/osc_tube.cc new file mode 100644 index 0000000..9480d4f --- /dev/null +++ b/src/faust-cc/osc_tube.cc @@ -0,0 +1,133 @@ +namespace osc_tube { +// generated from file '../src/faust/osc_tube.dsp' + +int iVec0[2]; +double fConst0; +double fConst1; +double fConst2; +double fConst3; +double fConst4; +double fConst5; +double fConst6; +double fConst7; +double fConst8; +double fConst9; +double fRec4[2]; +FAUSTFLOAT fslider0; +double fConst10; +double fConst11; +double fConst12; +double fConst13; +double fConst14; +double fConst15; +double fConst16; +double fVec1[3]; +double fConst17; +double fConst18; +double fConst19; +double fConst20; +double fConst21; +double fRec6[3]; +int IOTA; +double fVec2[4096]; +FAUSTFLOAT fslider1; +double fRec5[2]; +double fVec3[2]; +double fConst22; +double fRec3[2]; +double fRec2[2]; +double fRec1[3]; +double fRec0[3]; +FAUSTFLOAT fslider2; +double fConst23; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + for (int i=0; i<2; i++) iVec0[i] = 0; + fConst0 = tan((15707.963267948966 / fSamplingFreq)); + fConst1 = (2 * (1 - (1.0 / faustpower<2>(fConst0)))); + fConst2 = (1.0 / fConst0); + fConst3 = (1 + ((fConst2 - 0.76536686473018) / fConst0)); + fConst4 = (1 + ((0.76536686473018 + fConst2) / fConst0)); + fConst5 = (1.0 / fConst4); + fConst6 = (1 + ((fConst2 - 1.847759065022573) / fConst0)); + fConst7 = (1.0 / (1 + ((1.847759065022573 + fConst2) / fConst0))); + fConst8 = (408.4070449666731 / fSamplingFreq); + fConst9 = (1 - fConst8); + for (int i=0; i<2; i++) fRec4[i] = 0; + fConst10 = (6.283185307179586 * (max(0, ((0.5 * fSamplingFreq) - 1e+02)) / fSamplingFreq)); + fConst11 = cos(fConst10); + fConst12 = (1.316227766016838 * fConst11); + fConst13 = (0 - (2 * (0 - (0.683772233983162 + fConst12)))); + fConst14 = (0.683772233983162 * fConst11); + fConst15 = (0.005623413251903491 * sin(fConst10)); + fConst16 = (fConst15 - (fConst14 + 1.316227766016838)); + for (int i=0; i<3; i++) fVec1[i] = 0; + fConst17 = (fConst15 + fConst14); + fConst18 = (0.31622776601683794 * (1.316227766016838 - fConst17)); + fConst19 = (0.31622776601683794 * ((fConst15 + 1.316227766016838) - fConst14)); + fConst20 = (0 - (0.6324555320336759 * (fConst12 - 0.683772233983162))); + fConst21 = (1.0 / (1.316227766016838 + fConst17)); + for (int i=0; i<3; i++) fRec6[i] = 0; + IOTA = 0; + for (int i=0; i<4096; i++) fVec2[i] = 0; + for (int i=0; i<2; i++) fRec5[i] = 0; + for (int i=0; i<2; i++) fVec3[i] = 0; + fConst22 = (1.0 / (1 + fConst8)); + for (int i=0; i<2; i++) fRec3[i] = 0; + for (int i=0; i<2; i++) fRec2[i] = 0; + for (int i=0; i<3; i++) fRec1[i] = 0; + for (int i=0; i<3; i++) fRec0[i] = 0; + fConst23 = (0.5 / fConst4); +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = (fslider0 + 0.09999999999999998); + double fSlow1 = fslider1; + int iSlow2 = int((int((0 - fSlow1)) & 4095)); + int iSlow3 = int((int((1 - fSlow1)) & 4095)); + double fSlow4 = (fConst23 * fslider2); + for (int i=0; i(fTemp0)))); + // post processing + fRec0[1] = fRec0[0]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("overdrive.drive","","S","",&fslider0, 1.0, 1.0, 2e+01, 0.1); + registerInit("overdrive", init); +} + +} // end namespace overdrive diff --git a/src/faust-cc/preamp.cc b/src/faust-cc/preamp.cc new file mode 100644 index 0000000..f626679 --- /dev/null +++ b/src/faust-cc/preamp.cc @@ -0,0 +1,49 @@ +namespace preamp { +// generated from file '../src/faust/preamp.dsp' + +double fVec0[3]; +int iVec1[2]; +double fRec0[2]; +FAUSTFLOAT fslider0; +double fVec2[3]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + for (int i=0; i<3; i++) fVec0[i] = 0; + for (int i=0; i<2; i++) iVec1[i] = 0; + for (int i=0; i<2; i++) fRec0[i] = 0; + for (int i=0; i<3; i++) fVec2[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = fslider0; + double fSlow1 = (0.75 / atan(fSlow0)); + for (int i=0; i(fSlow0) - 1)); + double fSlow2 = fslider1; + double fSlow3 = (pow(10,(0.05 * (0 - fslider2))) / fSlow2); + double fSlow4 = (1 + (fSlow0 * (fSlow0 - fSlow3))); + double fSlow5 = (1.0 / (1 + (fSlow0 * (fSlow0 + fSlow3)))); + double fSlow6 = tan((fConst0 * fslider3)); + double fSlow7 = (2 * (faustpower<2>(fSlow6) - 1)); + double fSlow8 = fslider4; + double fSlow9 = (pow(10,(0.05 * (0 - fslider5))) / fSlow8); + double fSlow10 = (1 + (fSlow6 * (fSlow6 - fSlow9))); + double fSlow11 = (1.0 / (1 + (fSlow6 * (fSlow6 + fSlow9)))); + double fSlow12 = tan((fConst0 * fslider6)); + double fSlow13 = (2 * (faustpower<2>(fSlow12) - 1)); + double fSlow14 = fslider7; + double fSlow15 = (pow(10,(0.05 * (0 - fslider8))) / fSlow14); + double fSlow16 = (1 + (fSlow12 * (fSlow12 - fSlow15))); + double fSlow17 = (1.0 / (1 + (fSlow12 * (fSlow12 + fSlow15)))); + double fSlow18 = tan((fConst0 * fslider9)); + double fSlow19 = (2 * (faustpower<2>(fSlow18) - 1)); + double fSlow20 = fslider10; + double fSlow21 = (pow(10,(0.05 * (0 - fslider11))) / fSlow20); + double fSlow22 = (1 + (fSlow18 * (fSlow18 - fSlow21))); + double fSlow23 = (1.0 / (1 + (fSlow18 * (fSlow18 + fSlow21)))); + double fSlow24 = tan((fConst0 * fslider12)); + double fSlow25 = (2 * (faustpower<2>(fSlow24) - 1)); + double fSlow26 = fslider13; + double fSlow27 = (pow(10,(0.05 * (0 - fslider14))) / fSlow26); + double fSlow28 = (1 + (fSlow24 * (fSlow24 - fSlow27))); + double fSlow29 = (1.0 / (1 + (fSlow24 * (fSlow24 + fSlow27)))); + double fSlow30 = tan((fConst0 * fslider15)); + double fSlow31 = (2 * (faustpower<2>(fSlow30) - 1)); + double fSlow32 = fslider16; + double fSlow33 = (pow(10,(0.05 * (0 - fslider17))) / fSlow32); + double fSlow34 = (1 + (fSlow30 * (fSlow30 - fSlow33))); + double fSlow35 = (1.0 / (1 + (fSlow30 * (fSlow30 + fSlow33)))); + double fSlow36 = tan((fConst0 * fslider18)); + double fSlow37 = (2 * (faustpower<2>(fSlow36) - 1)); + double fSlow38 = fslider19; + double fSlow39 = (pow(10,(0.05 * (0 - fslider20))) / fSlow38); + double fSlow40 = (1 + (fSlow36 * (fSlow36 - fSlow39))); + double fSlow41 = (1.0 / (1 + (fSlow36 * (fSlow36 + fSlow39)))); + double fSlow42 = tan((fConst0 * fslider21)); + double fSlow43 = (2 * (faustpower<2>(fSlow42) - 1)); + double fSlow44 = fslider22; + double fSlow45 = (pow(10,(0.05 * (0 - fslider23))) / fSlow44); + double fSlow46 = (1 + (fSlow42 * (fSlow42 - fSlow45))); + double fSlow47 = (1.0 / (1 + (fSlow42 * (fSlow42 + fSlow45)))); + double fSlow48 = tan((fConst0 * fslider24)); + double fSlow49 = (2 * (faustpower<2>(fSlow48) - 1)); + double fSlow50 = fslider25; + double fSlow51 = (pow(10,(0.05 * (0 - fslider26))) / fSlow50); + double fSlow52 = (1 + (fSlow48 * (fSlow48 - fSlow51))); + double fSlow53 = (1.0 / (1 + (fSlow48 * (fSlow48 + fSlow51)))); + double fSlow54 = tan((fConst0 * fslider27)); + double fSlow55 = (2 * (faustpower<2>(fSlow54) - 1)); + double fSlow56 = fslider28; + double fSlow57 = (pow(10,(0.05 * (0 - fslider29))) / fSlow56); + double fSlow58 = (1 + (fSlow54 * (fSlow54 - fSlow57))); + double fSlow59 = (1.0 / (1 + (fSlow54 * (fSlow54 + fSlow57)))); + double fSlow60 = (1.0 / fSlow56); + double fSlow61 = (1 + (fSlow54 * (fSlow54 - fSlow60))); + double fSlow62 = (1 + (fSlow54 * (fSlow54 + fSlow60))); + double fSlow63 = (1.0 / fSlow50); + double fSlow64 = (1 + (fSlow48 * (fSlow48 - fSlow63))); + double fSlow65 = (1 + (fSlow48 * (fSlow48 + fSlow63))); + double fSlow66 = (1.0 / fSlow44); + double fSlow67 = (1 + (fSlow42 * (fSlow42 - fSlow66))); + double fSlow68 = (1 + (fSlow42 * (fSlow42 + fSlow66))); + double fSlow69 = (1.0 / fSlow38); + double fSlow70 = (1 + (fSlow36 * (fSlow36 - fSlow69))); + double fSlow71 = (1 + (fSlow36 * (fSlow36 + fSlow69))); + double fSlow72 = (1.0 / fSlow32); + double fSlow73 = (1 + (fSlow30 * (fSlow30 - fSlow72))); + double fSlow74 = (1 + (fSlow30 * (fSlow30 + fSlow72))); + double fSlow75 = (1.0 / fSlow26); + double fSlow76 = (1 + (fSlow24 * (fSlow24 - fSlow75))); + double fSlow77 = (1 + (fSlow24 * (fSlow24 + fSlow75))); + double fSlow78 = (1.0 / fSlow20); + double fSlow79 = (1 + (fSlow18 * (fSlow18 - fSlow78))); + double fSlow80 = (1 + (fSlow18 * (fSlow18 + fSlow78))); + double fSlow81 = (1.0 / fSlow14); + double fSlow82 = (1 + (fSlow12 * (fSlow12 - fSlow81))); + double fSlow83 = (1 + (fSlow12 * (fSlow12 + fSlow81))); + double fSlow84 = (1.0 / fSlow8); + double fSlow85 = (1 + (fSlow6 * (fSlow6 - fSlow84))); + double fSlow86 = (1 + (fSlow6 * (fSlow6 + fSlow84))); + double fSlow87 = (1.0 / fSlow2); + double fSlow88 = (1 + (fSlow0 * (fSlow0 - fSlow87))); + double fSlow89 = (1 + (fSlow0 * (fSlow0 + fSlow87))); + for (int i=0; i(fConst0); + fConst2 = (3 * fConst0); + for (int i=0; i<4; i++) fRec0[i] = 0; + fConst3 = (15079.644737231007 / fSamplingFreq); + fConst4 = cos(fConst3); + fConst5 = (1.4142135623730951 * sin(fConst3)); + fConst6 = (3769.9111843077517 / fSamplingFreq); + fConst7 = cos(fConst6); + fConst8 = (1.4142135623730951 * sin(fConst6)); + for (int i=0; i<3; i++) fRec4[i] = 0; + for (int i=0; i<3; i++) fRec3[i] = 0; + for (int i=0; i<3; i++) fRec2[i] = 0; + for (int i=0; i<3; i++) fRec1[i] = 0; + for (int i=0; i<4; i++) fRec5[i] = 0; + for (int i=0; i<4; i++) fRec6[i] = 0; + for (int i=0; i<4; i++) fRec7[i] = 0; + for (int i=0; i<4; i++) fRec8[i] = 0; + for (int i=0; i<4; i++) fRec9[i] = 0; + for (int i=0; i<4; i++) fRec10[i] = 0; + for (int i=0; i<4; i++) fRec11[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = fslider0; + double fSlow1 = (2.5312500000000006e-07 * fSlow0); + double fSlow2 = exp((3.4 * (fslider1 - 1))); + double fSlow3 = (7.4525e-07 + ((2.4210000000000004e-05 * fSlow2) + (fSlow0 * (((1.0125e-05 * fSlow2) - 2.75625e-07) - fSlow1)))); + double fSlow4 = ((7.650000000000002e-10 * fSlow2) - (1.9125000000000002e-11 * fSlow0)); + double fSlow5 = (1.4000000000000001e-09 * fSlow2); + double fSlow6 = (3.500000000000001e-11 + (fSlow5 + (fSlow0 * (fSlow4 - 1.5875000000000007e-11)))); + double fSlow7 = (fConst0 * fSlow6); + double fSlow8 = (0.0005 * fSlow0); + double fSlow9 = (0.02025 * fSlow2); + double fSlow10 = (fConst0 * (0.0028087500000000005 + (fSlow9 + fSlow8))); + double fSlow11 = ((fSlow10 + (fConst1 * (fSlow7 - fSlow3))) - 1); + double fSlow12 = (fConst2 * fSlow6); + double fSlow13 = ((fConst1 * (fSlow3 + fSlow12)) - (3 + fSlow10)); + double fSlow14 = ((fSlow10 + (fConst1 * (fSlow3 - fSlow12))) - 3); + double fSlow15 = (1.0 / (0 - (1 + (fSlow10 + (fConst1 * (fSlow3 + fSlow7)))))); + double fSlow16 = fslider2; + double fSlow17 = ((fSlow0 * (1.9125000000000002e-11 + fSlow4)) + (fSlow16 * (fSlow5 + (3.500000000000001e-11 - (3.500000000000001e-11 * fSlow0))))); + double fSlow18 = (fConst2 * fSlow17); + double fSlow19 = (4.525e-08 + (((1.4e-07 * fSlow16) + (fSlow0 * (2.8437500000000003e-07 - fSlow1))) + (fSlow2 * (1.8100000000000002e-06 + (1.0125e-05 * fSlow0))))); + double fSlow20 = (6.25e-05 * fSlow16); + double fSlow21 = (0.00050625 + (fSlow9 + (fSlow8 + fSlow20))); + double fSlow22 = (fConst0 * fSlow21); + double fSlow23 = (fSlow22 + (fConst1 * (fSlow19 - fSlow18))); + double fSlow24 = (fConst0 * fSlow17); + double fSlow25 = (fSlow22 + (fConst1 * (fSlow24 - fSlow19))); + double fSlow26 = (fConst0 * (0 - fSlow21)); + double fSlow27 = (fSlow26 + (fConst1 * (fSlow19 + fSlow18))); + double fSlow28 = (fSlow26 - (fConst1 * (fSlow19 + fSlow24))); + double fSlow29 = (10 * fSlow0); + double fSlow30 = (5 + fSlow29); + double fSlow31 = pow(10,(0.025 * ((20 * fSlow16) - fSlow30))); + double fSlow32 = (1 + fSlow31); + double fSlow33 = (fConst4 * fSlow32); + double fSlow34 = (2 * (0 - ((1 + fSlow33) - fSlow31))); + double fSlow35 = (fConst4 * (fSlow31 - 1)); + double fSlow36 = (fConst5 * sqrt(fSlow31)); + double fSlow37 = (fSlow32 - (fSlow36 + fSlow35)); + double fSlow38 = pow(10,(0.025 * (fSlow29 - 5))); + double fSlow39 = (1 + fSlow38); + double fSlow40 = (fConst7 * fSlow39); + double fSlow41 = (2 * (0 - ((1 + fSlow40) - fSlow38))); + double fSlow42 = (fSlow38 - 1); + double fSlow43 = (fConst7 * fSlow42); + double fSlow44 = sqrt(fSlow38); + double fSlow45 = (fConst8 * fSlow44); + double fSlow46 = (fSlow39 - (fSlow45 + fSlow43)); + double fSlow47 = (fConst4 * fSlow39); + double fSlow48 = (0 - (2 * ((fSlow38 + fSlow47) - 1))); + double fSlow49 = (fConst5 * fSlow44); + double fSlow50 = (fConst4 * fSlow42); + double fSlow51 = ((1 + (fSlow38 + fSlow50)) - fSlow49); + double fSlow52 = pow(10,(0.025 * ((20 * fSlow2) - fSlow30))); + double fSlow53 = (1 + fSlow52); + double fSlow54 = (fConst7 * fSlow53); + double fSlow55 = (0 - (2 * ((fSlow52 + fSlow54) - 1))); + double fSlow56 = (fConst8 * sqrt(fSlow52)); + double fSlow57 = (fConst7 * (fSlow52 - 1)); + double fSlow58 = ((1 + (fSlow52 + fSlow57)) - fSlow56); + double fSlow59 = (fSlow53 - (fSlow56 + fSlow57)); + double fSlow60 = (2 * (0 - ((1 + fSlow54) - fSlow52))); + double fSlow61 = (fSlow52 + fSlow56); + double fSlow62 = ((1 + fSlow61) - fSlow57); + double fSlow63 = (1.0 / (1 + (fSlow57 + fSlow61))); + double fSlow64 = (fSlow39 - (fSlow49 + fSlow50)); + double fSlow65 = (2 * (0 - ((1 + fSlow47) - fSlow38))); + double fSlow66 = (fSlow38 + fSlow49); + double fSlow67 = ((1 + fSlow66) - fSlow50); + double fSlow68 = (1.0 / (1 + (fSlow50 + fSlow66))); + double fSlow69 = (fSlow38 * ((1 + (fSlow38 + fSlow43)) - fSlow45)); + double fSlow70 = (fSlow38 + fSlow45); + double fSlow71 = (fSlow38 * (1 + (fSlow43 + fSlow70))); + double fSlow72 = (((fSlow38 + fSlow40) - 1) * (0 - (2 * fSlow38))); + double fSlow73 = (1.0 / ((1 + fSlow70) - fSlow43)); + double fSlow74 = (fSlow31 * ((1 + (fSlow31 + fSlow35)) - fSlow36)); + double fSlow75 = (fSlow31 + fSlow36); + double fSlow76 = (fSlow31 * (1 + (fSlow35 + fSlow75))); + double fSlow77 = (((fSlow31 + fSlow33) - 1) * (0 - (2 * fSlow31))); + double fSlow78 = (1.0 / ((1 + fSlow75) - fSlow35)); + double fSlow79 = fslider3; + int iSlow80 = int(min(2, max(0, fSlow79))); + double fSlow81 = (4.7056400000000006e-07 * fSlow0); + double fSlow82 = (5.188640000000001e-06 + ((0.00011869100000000002 * fSlow2) + (fSlow0 * (((1.1764100000000001e-05 * fSlow2) - 4.215336e-06) - fSlow81)))); + double fSlow83 = (4.935e-10 * fSlow2); + double fSlow84 = (fSlow83 - (1.974e-11 * fSlow0)); + double fSlow85 = (3.525e-09 * fSlow2); + double fSlow86 = (1.41e-10 + (fSlow85 + (fSlow0 * (fSlow84 - 1.2126e-10)))); + double fSlow87 = (fConst0 * fSlow86); + double fSlow88 = (0.00047000000000000004 * fSlow0); + double fSlow89 = (0.02503 * fSlow2); + double fSlow90 = (fConst0 * (0.0157312 + (fSlow89 + fSlow88))); + double fSlow91 = ((fSlow90 + (fConst1 * (fSlow87 - fSlow82))) - 1); + double fSlow92 = (fConst2 * fSlow86); + double fSlow93 = ((fConst1 * (fSlow82 + fSlow92)) - (3 + fSlow90)); + double fSlow94 = ((fSlow90 + (fConst1 * (fSlow82 - fSlow92))) - 3); + double fSlow95 = (0 - (1 + (fSlow90 + (fConst1 * (fSlow82 + fSlow87))))); + double fSlow96 = (1.0 / fSlow95); + double fSlow97 = (1.41e-10 - (1.41e-10 * fSlow0)); + double fSlow98 = ((fSlow0 * (1.974e-11 + fSlow84)) + (fSlow16 * (fSlow85 + fSlow97))); + double fSlow99 = (fConst2 * fSlow98); + double fSlow100 = (4.764000000000001e-08 + (((4.410000000000001e-07 * fSlow16) + (fSlow0 * (4.846640000000001e-07 - fSlow81))) + (fSlow2 * (1.1910000000000001e-06 + (1.1764100000000001e-05 * fSlow0))))); + double fSlow101 = (0.0010012 + (fSlow89 + (fSlow88 + (3e-05 * fSlow16)))); + double fSlow102 = (fConst0 * fSlow101); + double fSlow103 = (fSlow102 + (fConst1 * (fSlow100 - fSlow99))); + double fSlow104 = (fConst0 * fSlow98); + double fSlow105 = (fSlow102 + (fConst1 * (fSlow104 - fSlow100))); + double fSlow106 = (fConst0 * (0 - fSlow101)); + double fSlow107 = (fSlow106 + (fConst1 * (fSlow100 + fSlow99))); + double fSlow108 = (fSlow106 - (fConst1 * (fSlow100 + fSlow104))); + double fSlow109 = (1.5 / fSlow95); + int iSlow110 = int(min(2, max(0, (fSlow79 - 1)))); + double fSlow111 = (1.0855872000000003e-07 * fSlow0); + double fSlow112 = (3.222390000000001e-06 + ((0.00011998125000000002 * fSlow2) + (fSlow0 * (((5.6541000000000015e-06 * fSlow2) - 2.1333412800000006e-06) - fSlow111)))); + double fSlow113 = (fSlow83 - (9.4752e-12 * fSlow0)); + double fSlow114 = (7.343750000000001e-09 * fSlow2); + double fSlow115 = (1.41e-10 + (fSlow114 + (fSlow0 * (fSlow113 - 1.315248e-10)))); + double fSlow116 = (fConst0 * fSlow115); + double fSlow117 = (0.0002256 * fSlow0); + double fSlow118 = (0.0250625 * fSlow2); + double fSlow119 = (fConst0 * (0.015243699999999999 + (fSlow118 + fSlow117))); + double fSlow120 = ((fSlow119 + (fConst1 * (fSlow116 - fSlow112))) - 1); + double fSlow121 = (fConst2 * fSlow115); + double fSlow122 = ((fConst1 * (fSlow112 + fSlow121)) - (3 + fSlow119)); + double fSlow123 = ((fSlow119 + (fConst1 * (fSlow112 - fSlow121))) - 3); + double fSlow124 = (0 - (1 + (fSlow119 + (fConst1 * (fSlow112 + fSlow116))))); + double fSlow125 = (1.0 / fSlow124); + double fSlow126 = ((fSlow0 * (9.4752e-12 + fSlow113)) + (fSlow16 * (fSlow97 + fSlow114))); + double fSlow127 = (fConst2 * fSlow126); + double fSlow128 = (4.764000000000001e-08 + (((9.187500000000001e-07 * fSlow16) + (fSlow0 * (1.2265872000000003e-07 - fSlow111))) + (fSlow2 * (2.48125e-06 + (5.6541000000000015e-06 * fSlow0))))); + double fSlow129 = (0.00048120000000000004 + (fSlow118 + (fSlow20 + fSlow117))); + double fSlow130 = (fConst0 * fSlow129); + double fSlow131 = (fSlow130 + (fConst1 * (fSlow128 - fSlow127))); + double fSlow132 = (fConst0 * fSlow126); + double fSlow133 = (fSlow130 + (fConst1 * (fSlow132 - fSlow128))); + double fSlow134 = (fConst0 * (0 - fSlow129)); + double fSlow135 = (fSlow134 + (fConst1 * (fSlow128 + fSlow127))); + double fSlow136 = (fSlow134 - (fConst1 * (fSlow128 + fSlow132))); + double fSlow137 = (1.5 / fSlow124); + int iSlow138 = int(min(2, max(0, (fSlow79 - 2)))); + double fSlow139 = (2.3926056000000006e-07 * fSlow0); + double fSlow140 = (5.665800800000001e-07 + ((1.892924e-05 * fSlow2) + (fSlow0 * (((1.0875480000000001e-05 * fSlow2) - 6.207784000000001e-08) - fSlow139)))); + double fSlow141 = ((1.2661536800000005e-09 * fSlow2) - (2.7855380960000008e-11 * fSlow0)); + double fSlow142 = (1.6515048000000004e-09 * fSlow2); + double fSlow143 = (3.6333105600000014e-11 + (fSlow142 + (fSlow0 * (fSlow141 - 8.477724640000006e-12)))); + double fSlow144 = (fConst0 * fSlow143); + double fSlow145 = (0.00048400000000000006 * fSlow0); + double fSlow146 = (0.022470000000000004 * fSlow2); + double fSlow147 = (fConst0 * (0.0020497400000000004 + (fSlow146 + fSlow145))); + double fSlow148 = ((fSlow147 + (fConst1 * (fSlow144 - fSlow140))) - 1); + double fSlow149 = (fConst2 * fSlow143); + double fSlow150 = ((fConst1 * (fSlow140 + fSlow149)) - (3 + fSlow147)); + double fSlow151 = ((fSlow147 + (fConst1 * (fSlow140 - fSlow149))) - 3); + double fSlow152 = (1.0 / (0 - (1 + (fSlow147 + (fConst1 * (fSlow140 + fSlow144)))))); + double fSlow153 = ((fSlow0 * (2.7855380960000008e-11 + fSlow141)) + (fSlow16 * (fSlow142 + (3.6333105600000014e-11 - (3.6333105600000014e-11 * fSlow0))))); + double fSlow154 = (fConst2 * fSlow153); + double fSlow155 = (6.505928000000001e-08 + (((1.5013680000000003e-07 * fSlow16) + (fSlow0 * (2.893061600000001e-07 - fSlow139))) + (fSlow2 * (2.95724e-06 + (1.0875480000000001e-05 * fSlow0))))); + double fSlow156 = (0.00049434 + (fSlow146 + (fSlow145 + (0.0001034 * fSlow16)))); + double fSlow157 = (fConst0 * fSlow156); + double fSlow158 = (fSlow157 + (fConst1 * (fSlow155 - fSlow154))); + double fSlow159 = (fConst0 * fSlow153); + double fSlow160 = (fSlow157 + (fConst1 * (fSlow159 - fSlow155))); + double fSlow161 = (fConst0 * (0 - fSlow156)); + double fSlow162 = (fSlow161 + (fConst1 * (fSlow155 + fSlow154))); + double fSlow163 = (fSlow161 - (fConst1 * (fSlow155 + fSlow159))); + int iSlow164 = int(min(2, max(0, (fSlow79 - 3)))); + double fSlow165 = (3.0937500000000006e-07 * fSlow0); + double fSlow166 = (1.2375000000000003e-05 * fSlow2); + double fSlow167 = (1.08515e-06 + ((3.108600000000001e-05 * fSlow2) + (fSlow0 * ((fSlow166 - 2.99475e-07) - fSlow165)))); + double fSlow168 = ((1.8513000000000002e-09 * fSlow2) - (4.628250000000001e-11 * fSlow0)); + double fSlow169 = (3.3880000000000003e-09 * fSlow2); + double fSlow170 = (8.470000000000002e-11 + (fSlow169 + (fSlow0 * (fSlow168 - 3.8417500000000006e-11)))); + double fSlow171 = (fConst0 * fSlow170); + double fSlow172 = (0.00055 * fSlow0); + double fSlow173 = (0.022500000000000003 * fSlow2); + double fSlow174 = (fSlow173 + fSlow172); + double fSlow175 = (fConst0 * (0.0031515000000000002 + fSlow174)); + double fSlow176 = ((fSlow175 + (fConst1 * (fSlow171 - fSlow167))) - 1); + double fSlow177 = (fConst2 * fSlow170); + double fSlow178 = ((fConst1 * (fSlow167 + fSlow177)) - (3 + fSlow175)); + double fSlow179 = ((fSlow175 + (fConst1 * (fSlow167 - fSlow177))) - 3); + double fSlow180 = (1.0 / (0 - (1 + (fSlow175 + (fConst1 * (fSlow167 + fSlow171)))))); + double fSlow181 = ((fSlow0 * (4.628250000000001e-11 + fSlow168)) + (fSlow16 * (fSlow169 + (8.470000000000002e-11 - (8.470000000000002e-11 * fSlow0))))); + double fSlow182 = (fConst2 * fSlow181); + double fSlow183 = (1.2375000000000003e-05 * fSlow0); + double fSlow184 = (fSlow0 * (3.781250000000001e-07 - fSlow165)); + double fSlow185 = (9.955000000000001e-08 + (((3.08e-07 * fSlow16) + fSlow184) + (fSlow2 * (3.982e-06 + fSlow183)))); + double fSlow186 = (0.0005625000000000001 + (fSlow173 + (fSlow172 + (0.000125 * fSlow16)))); + double fSlow187 = (fConst0 * fSlow186); + double fSlow188 = (fSlow187 + (fConst1 * (fSlow185 - fSlow182))); + double fSlow189 = (fConst0 * fSlow181); + double fSlow190 = (fSlow187 + (fConst1 * (fSlow189 - fSlow185))); + double fSlow191 = (fConst0 * (0 - fSlow186)); + double fSlow192 = (fSlow191 + (fConst1 * (fSlow185 + fSlow182))); + double fSlow193 = (fSlow191 - (fConst1 * (fSlow185 + fSlow189))); + int iSlow194 = int(min(2, max(0, (fSlow79 - 4)))); + double fSlow195 = (6.677000000000001e-07 + ((1.9448000000000004e-05 * fSlow2) + (fSlow0 * ((fSlow166 - 2.1175000000000003e-08) - fSlow165)))); + double fSlow196 = ((1.7121500000000001e-09 * fSlow2) - (4.2803750000000003e-11 * fSlow0)); + double fSlow197 = (1.9965000000000003e-09 * fSlow2); + double fSlow198 = (4.991250000000001e-11 + (fSlow197 + (fSlow0 * (fSlow196 - 7.108750000000004e-12)))); + double fSlow199 = (fConst0 * fSlow198); + double fSlow200 = (fConst0 * (0.0021395000000000003 + fSlow174)); + double fSlow201 = ((fSlow200 + (fConst1 * (fSlow199 - fSlow195))) - 1); + double fSlow202 = (fConst2 * fSlow198); + double fSlow203 = ((fConst1 * (fSlow195 + fSlow202)) - (3 + fSlow200)); + double fSlow204 = ((fSlow200 + (fConst1 * (fSlow195 - fSlow202))) - 3); + double fSlow205 = (1.0 / (0 - (1 + (fSlow200 + (fConst1 * (fSlow195 + fSlow199)))))); + double fSlow206 = ((fSlow0 * (4.2803750000000003e-11 + fSlow196)) + (fSlow16 * (fSlow197 + (4.991250000000001e-11 - (4.991250000000001e-11 * fSlow0))))); + double fSlow207 = (fConst2 * fSlow206); + double fSlow208 = (8.690000000000002e-08 + ((fSlow184 + (1.815e-07 * fSlow16)) + (fSlow2 * (3.4760000000000007e-06 + fSlow183)))); + double fSlow209 = (fSlow187 + (fConst1 * (fSlow208 - fSlow207))); + double fSlow210 = (fConst0 * fSlow206); + double fSlow211 = (fSlow187 + (fConst1 * (fSlow210 - fSlow208))); + double fSlow212 = (fSlow191 + (fConst1 * (fSlow208 + fSlow207))); + double fSlow213 = (fSlow191 - (fConst1 * (fSlow208 + fSlow210))); + int iSlow214 = int(min(2, max(0, (fSlow79 - 5)))); + double fSlow215 = (1.38796875e-06 * fSlow0); + double fSlow216 = (3.5279375000000002e-06 + ((3.1989375e-05 * fSlow2) + (fSlow0 * (((1.38796875e-05 * fSlow2) - 1.6311937500000001e-06) - fSlow215)))); + double fSlow217 = ((1.0561781250000004e-09 * fSlow2) - (1.0561781250000003e-10 * fSlow0)); + double fSlow218 = (1.9328750000000005e-09 * fSlow2); + double fSlow219 = (1.9328750000000007e-10 + (fSlow218 + (fSlow0 * (fSlow217 - 8.766968750000004e-11)))); + double fSlow220 = (fConst0 * fSlow219); + double fSlow221 = (0.001175 * fSlow0); + double fSlow222 = (0.011812500000000002 * fSlow2); + double fSlow223 = (fConst0 * (0.0065077500000000005 + (fSlow222 + fSlow221))); + double fSlow224 = ((fSlow223 + (fConst1 * (fSlow220 - fSlow216))) - 1); + double fSlow225 = (fConst2 * fSlow219); + double fSlow226 = ((fConst1 * (fSlow216 + fSlow225)) - (3 + fSlow223)); + double fSlow227 = ((fSlow223 + (fConst1 * (fSlow216 - fSlow225))) - 3); + double fSlow228 = (1.0 / (0 - (1 + (fSlow223 + (fConst1 * (fSlow216 + fSlow220)))))); + double fSlow229 = ((fSlow0 * (1.0561781250000003e-10 + fSlow217)) + (fSlow16 * (fSlow218 + (1.9328750000000007e-10 - (1.9328750000000007e-10 * fSlow0))))); + double fSlow230 = (fConst2 * fSlow229); + double fSlow231 = (1.0633750000000002e-07 + (((3.2900000000000005e-07 * fSlow16) + (fSlow0 * (1.4614062500000001e-06 - fSlow215))) + (fSlow2 * (1.0633750000000002e-06 + (1.38796875e-05 * fSlow0))))); + double fSlow232 = (0.00118125 + (fSlow222 + (fSlow20 + fSlow221))); + double fSlow233 = (fConst0 * fSlow232); + double fSlow234 = (fSlow233 + (fConst1 * (fSlow231 - fSlow230))); + double fSlow235 = (fConst0 * fSlow229); + double fSlow236 = (fSlow233 + (fConst1 * (fSlow235 - fSlow231))); + double fSlow237 = (fConst0 * (0 - fSlow232)); + double fSlow238 = (fSlow237 + (fConst1 * (fSlow231 + fSlow230))); + double fSlow239 = (fSlow237 - (fConst1 * (fSlow231 + fSlow235))); + int iSlow240 = int(min(2, max(0, (fSlow79 - 6)))); + double fSlow241 = (4.851e-08 * fSlow0); + double fSlow242 = (7.172000000000001e-07 + ((4.972000000000001e-05 * fSlow2) + (fSlow0 * (((4.8510000000000015e-06 * fSlow2) - 4.2449000000000006e-07) - fSlow241)))); + double fSlow243 = ((2.6620000000000007e-10 * fSlow2) - (2.662e-12 * fSlow0)); + double fSlow244 = (2.4200000000000003e-09 * fSlow2); + double fSlow245 = (2.4200000000000004e-11 + (fSlow244 + (fSlow0 * (fSlow243 - 2.1538000000000003e-11)))); + double fSlow246 = (fConst0 * fSlow245); + double fSlow247 = (0.00022 * fSlow0); + double fSlow248 = (0.022050000000000004 * fSlow2); + double fSlow249 = (fConst0 * (0.0046705 + (fSlow248 + fSlow247))); + double fSlow250 = ((fSlow249 + (fConst1 * (fSlow246 - fSlow242))) - 1); + double fSlow251 = (fConst2 * fSlow245); + double fSlow252 = ((fConst1 * (fSlow242 + fSlow251)) - (3 + fSlow249)); + double fSlow253 = ((fSlow249 + (fConst1 * (fSlow242 - fSlow251))) - 3); + double fSlow254 = (1.0 / (0 - (1 + (fSlow249 + (fConst1 * (fSlow242 + fSlow246)))))); + double fSlow255 = ((fSlow0 * (2.662e-12 + fSlow243)) + (fSlow16 * (fSlow244 + (2.4200000000000004e-11 - (2.4200000000000004e-11 * fSlow0))))); + double fSlow256 = (fConst2 * fSlow255); + double fSlow257 = (1.32e-08 + (((2.2000000000000004e-07 * fSlow16) + (fSlow0 * (5.951000000000001e-08 - fSlow241))) + (fSlow2 * (1.32e-06 + (4.8510000000000015e-06 * fSlow0))))); + double fSlow258 = (0.00022050000000000002 + (fSlow248 + (fSlow247 + (5e-05 * fSlow16)))); + double fSlow259 = (fConst0 * fSlow258); + double fSlow260 = (fSlow259 + (fConst1 * (fSlow257 - fSlow256))); + double fSlow261 = (fConst0 * fSlow255); + double fSlow262 = (fSlow259 + (fConst1 * (fSlow261 - fSlow257))); + double fSlow263 = (fConst0 * (0 - fSlow258)); + double fSlow264 = (fSlow263 + (fConst1 * (fSlow257 + fSlow256))); + double fSlow265 = (fSlow263 - (fConst1 * (fSlow257 + fSlow261))); + int iSlow266 = int(min(2, max(0, (fSlow79 - 7)))); + for (int i=0; i0; i--) fRec11[i] = fRec11[i-1]; + for (int i=3; i>0; i--) fRec10[i] = fRec10[i-1]; + for (int i=3; i>0; i--) fRec9[i] = fRec9[i-1]; + for (int i=3; i>0; i--) fRec8[i] = fRec8[i-1]; + for (int i=3; i>0; i--) fRec7[i] = fRec7[i-1]; + for (int i=3; i>0; i--) fRec6[i] = fRec6[i-1]; + for (int i=3; i>0; i--) fRec5[i] = fRec5[i-1]; + fRec1[2] = fRec1[1]; fRec1[1] = fRec1[0]; + fRec2[2] = fRec2[1]; fRec2[1] = fRec2[0]; + fRec3[2] = fRec3[1]; fRec3[1] = fRec3[0]; + fRec4[2] = fRec4[1]; fRec4[1] = fRec4[0]; + for (int i=3; i>0; i--) fRec0[i] = fRec0[i-1]; + fVec0[2] = fVec0[1]; fVec0[1] = fVec0[0]; + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + static const char *fslider3_values[] = {"default","Bassman","Twin Reverb","Princeton","JCM-800","JCM-2000","M-Lead","M2199","AC-30","Off",0}; + registerEnumVar("amp.tonestack.select","","S","",fslider3_values,&fslider3, 1.0, 0.0, 9.0, 1.0); + registerVar("amp.tonestack.Treble","","S","",&fslider2, 0.5, 0.0, 1.0, 0.01); + registerVar("amp.tonestack.Bass","","S","",&fslider1, 0.5, 0.0, 1.0, 0.01); + registerVar("amp.tonestack.Middle","","S","",&fslider0, 0.5, 0.0, 1.0, 0.01); + registerInit("amp.tonestack", init); +} + +} // end namespace tonestack diff --git a/src/faust-cc/tube.cc b/src/faust-cc/tube.cc new file mode 100644 index 0000000..e1a18d1 --- /dev/null +++ b/src/faust-cc/tube.cc @@ -0,0 +1,28 @@ +namespace tube { +// generated from file '../src/faust/tube.dsp' + +FAUSTFLOAT fslider0; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = (0.25 * fslider0); + for (int i=0; i((0 - fslider0)); + double fSlow1 = pow(10,fslider1); + double fSlow2 = (fSlow1 * (0 - fSlow0)); + double fSlow3 = max(-600, fSlow2); + double fSlow4 = (0 - fSlow3); + double fSlow5 = ((int((fabs(fSlow2) > 0.0001)))?((int((fSlow3 < -50)))?(exp(fSlow3) * fSlow4):(fSlow3 / (1 - exp(fSlow4)))):(1 + (fSlow2 * (0.5 + (0.08333333333333333 * fSlow2))))); + double fSlow6 = (0.08333333333333333 * fSlow1); + double fSlow7 = (fslider2 / fSlow1); + double fSlow8 = (1.0 / fSlow1); + for (int i=0; i 0.0001)))?((int((fTemp2 < -50)))?(exp(fTemp2) * fTemp3):(fTemp2 / (1 - exp(fTemp3)))):(1 + (fSlow1 * (fTemp0 * (0.5 + (fSlow6 * fTemp0)))))) - fSlow5)))); + double fTemp5 = (fSlow1 * fTemp4); + double fTemp6 = max(-600, fTemp5); + double fTemp7 = (0 - fTemp6); + output0[i] = (FAUSTFLOAT)(0 - (fSlow8 * (((int((fabs(fTemp5) > 0.0001)))?((int((fTemp6 < -50)))?(exp(fTemp6) * fTemp7):(fTemp6 / (1 - exp(fTemp7)))):(1 + (fSlow1 * (fTemp4 * (0.5 + (fSlow6 * fTemp4)))))) - fSlow5))); + } +} + +static struct RegisterParams { RegisterParams(); } RegisterParams; +RegisterParams::RegisterParams() +{ + registerVar("tube3.g","","S","",&fslider2, 1.0, 0.2, 2.0, 0.1); + registerVar("tube3.dist","","S","",&fslider1, 0.0, 0.0, 1.7, 0.01); + registerVar("tube3.q","","S","",&fslider0, 0.4, 0.4, 1.0, 0.001); + registerInit("tube3", init); +} + +} // end namespace tube3 diff --git a/src/faust-cc/tubevibrato.cc b/src/faust-cc/tubevibrato.cc new file mode 100644 index 0000000..57d33b0 --- /dev/null +++ b/src/faust-cc/tubevibrato.cc @@ -0,0 +1,32 @@ +namespace tubevibrato { +// generated from file '../src/faust/tubevibrato.dsp' + +FAUSTFLOAT fslider0; +double fRec0[2]; +int fSamplingFreq; + +void init(int samplingFreq) +{ + fSamplingFreq = samplingFreq; + for (int i=0; i<2; i++) fRec0[i] = 0; +} + +void compute(int count, float *input0, float *output0) +{ + double fSlow0 = (0.5 * fslider0); + for (int i=0; i +{ + void declare (const char* key, const char* value) { (*this)[key]=value; } +}; + + + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + + +// abs is now predefined +//template T abs (T a) { return (a> n); } + +inline int int2pow2 (int x) { int r=0; while ((1<> + + + + + + +/****************************************************************************** +******************************************************************************* + + GRAPHIC USER INTERFACE (v2) + abstract interfaces + +******************************************************************************* +*******************************************************************************/ + +struct uiItem; +typedef void (*uiCallback)(float val, void* data); + +/** + * Graphic User Interface : abstract definition + */ + +class UI +{ + typedef list clist; + typedef map zmap; + +private: + static list fGuiList; + zmap fZoneMap; + +public: + + UI() { + fGuiList.push_back(this); + } + + virtual ~UI() { + // suppression de this dans fGuiList + } + + // -- registerZone(z,c) : zone management + + void registerZone(float* z, uiItem* c) + { + if (fZoneMap.find(z) == fZoneMap.end()) fZoneMap[z] = new clist(); + fZoneMap[z]->push_back(c); + } + + // -- saveState(filename) : save the value of every zone to a file + + void saveState(const char* filename) + { + ofstream f(filename); + + for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) { + f << *(i->first) << ' '; + } + + f << endl; + f.close(); + } + + // -- recallState(filename) : load the value of every zone from a file + + void recallState(const char* filename) + { + ifstream f(filename); + if (f.good()) { + for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) { + f >> *(i->first); + } + } + f.close(); + } + + void updateAllZones(); + + void updateZone(float* z); + + static void updateAllGuis() + { + list::iterator g; + for (g = fGuiList.begin(); g != fGuiList.end(); g++) { + (*g)->updateAllZones(); + } + } + + // -- active widgets + + virtual void addButton(const char* label, float* zone) = 0; + virtual void addToggleButton(const char* label, float* zone) = 0; + virtual void addCheckButton(const char* label, float* zone) = 0; + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0; + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0; + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0; + + // -- passive widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision) = 0; + virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max) = 0; + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0; + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0; + + void addCallback(float* zone, uiCallback foo, void* data); + + // -- widget's layouts + + virtual void openFrameBox(const char* label) = 0; + virtual void openTabBox(const char* label) = 0; + virtual void openHorizontalBox(const char* label) = 0; + virtual void openVerticalBox(const char* label) = 0; + + // -- extra widget's layouts + + virtual void openDialogBox(const char* label, float* zone) = 0; + virtual void openEventBox(const char* label) = 0; + virtual void openHandleBox(const char* label) = 0; + virtual void openExpanderBox(const char* label, float* zone) = 0; + + virtual void closeBox() = 0; + + virtual void run() {}; + + virtual void declare(float* zone, const char* key, const char* value) {} +}; + + +/** + * User Interface Item: abstract definition + */ + +class uiItem +{ +protected : + + UI* fGUI; + float* fZone; + float fCache; + + uiItem (UI* ui, float* zone) : fGUI(ui), fZone(zone), fCache(-123456.654321) + { + ui->registerZone(zone, this); + } + + +public : + virtual ~uiItem() {} + + void modifyZone(float v) + { + fCache = v; + if (*fZone != v) { + *fZone = v; + fGUI->updateZone(fZone); + } + } + + float cache() { return fCache; } + virtual void reflectZone() = 0; +}; + + +/** + * Callback Item + */ + +struct uiCallbackItem : public uiItem +{ + uiCallback fCallback; + void* fData; + + uiCallbackItem(UI* ui, float* zone, uiCallback foo, void* data) + : uiItem(ui, zone), fCallback(foo), fData(data) {} + + virtual void reflectZone() { + float v = *fZone; + fCache = v; + fCallback(v, fData); + } +}; + +// en cours d'installation de call back. a finir!!!!! + +/** + * Update all user items reflecting zone z + */ + +inline void UI::updateZone(float* z) +{ + float v = *z; + clist* l = fZoneMap[z]; + for (clist::iterator c = l->begin(); c != l->end(); c++) { + if ((*c)->cache() != v) (*c)->reflectZone(); + } +} + + +/** + * Update all user items not up to date + */ + +inline void UI::updateAllZones() +{ + for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) { + float* z = m->first; + clist* l = m->second; + float v = *z; + for (clist::iterator c = l->begin(); c != l->end(); c++) { + if ((*c)->cache() != v) (*c)->reflectZone(); + } + } +} + +inline void UI::addCallback(float* zone, uiCallback foo, void* data) +{ + new uiCallbackItem(this, zone, foo, data); +}; + +/****************************************************************************** +******************************************************************************* + + GRAPHIC USER INTERFACE + gtk interface + +******************************************************************************* +*******************************************************************************/ + +#include + +#define stackSize 256 + +// Insertion modes + +#define kSingleMode 0 +#define kBoxMode 1 +#define kTabMode 2 + +/** + * rmWhiteSpaces(): Remove the leading and trailing white spaces of a string + * (but not those in the middle of the string) + */ +static string rmWhiteSpaces(const string& s) +{ + size_t i = s.find_first_not_of(" \t"); + size_t j = s.find_last_not_of(" \t"); + + if (i != string::npos && j != string::npos) { + return s.substr(i, 1+j-i); + } else { + return ""; + } +} + + +/** + * Extracts metdata from a label : 'vol [unit: dB]' -> 'vol' + metadata + */ +static void extractMetadata(const string& fulllabel, string& label, map& metadata) +{ + enum {kLabel, kEscape1, kEscape2, kEscape3, kKey, kValue}; + int state = kLabel; int deep = 0; + string key, value; + + for (unsigned int i=0; i < fulllabel.size(); i++) { + char c = fulllabel[i]; + switch (state) { + case kLabel : + assert (deep == 0); + switch (c) { + case '\\' : state = kEscape1; break; + case '[' : state = kKey; deep++; break; + default : label += c; + } + break; + + case kEscape1 : + label += c; + state = kLabel; + break; + + case kEscape2 : + key += c; + state = kKey; + break; + + case kEscape3 : + value += c; + state = kValue; + break; + + case kKey : + assert (deep > 0); + switch (c) { + case '\\' : state = kEscape2; + break; + + case '[' : deep++; + key += c; + break; + + case ':' : if (deep == 1) { + state = kValue; + } else { + key += c; + } + break; + case ']' : deep--; + if (deep < 1) { + metadata[rmWhiteSpaces(key)] = ""; + state = kLabel; + key=""; + value=""; + } else { + key += c; + } + break; + default : key += c; + } + break; + + case kValue : + assert (deep > 0); + switch (c) { + case '\\' : state = kEscape3; + break; + + case '[' : deep++; + value += c; + break; + + case ']' : deep--; + if (deep < 1) { + metadata[rmWhiteSpaces(key)]=rmWhiteSpaces(value); + state = kLabel; + key=""; + value=""; + } else { + value += c; + } + break; + default : value += c; + } + break; + + default : + cerr << "ERROR unrecognized state " << state << endl; + } + } + label = rmWhiteSpaces(label); +} + + +class GTKUI : public UI +{ +private : + static list fGuiList; + static map fGuiSize; // map widget zone with widget size coef + static map fTooltip; // map widget zone with tooltip strings + +protected : + int fTop; + GtkWidget* fBox[stackSize]; + int fMode[stackSize]; + + GtkWidget* addWidget(const char* label, GtkWidget* w); + virtual void pushBox(int mode, GtkWidget* w); + + +public : + + static const gboolean expand = TRUE; + static const gboolean fill = TRUE; + static const gboolean homogene = FALSE; + + GTKUI(GtkWidget *window); + + // -- Labels and metadata + + virtual void declare (float* zone, const char* key, const char* value); + virtual int checkLabelOptions (GtkWidget* widget, const string& fullLabel, string& simplifiedLabel); + virtual void checkForTooltip (float* zone, GtkWidget* widget); + + // -- layout groups + + virtual void openFrameBox(const char* label); + virtual void openTabBox(const char* label = ""); + virtual void openHorizontalBox(const char* label = ""); + virtual void openVerticalBox(const char* label = ""); + + // -- extra widget's layouts + + virtual void openDialogBox(const char* label, float* zone); + virtual void openEventBox(const char* label = ""); + virtual void openHandleBox(const char* label = ""); + virtual void openExpanderBox(const char* label, float* zone); + + virtual void closeBox(); + virtual void adjustStack(int n); + + // -- active widgets + + virtual void addButton(const char* label, float* zone); + virtual void addToggleButton(const char* label, float* zone); + virtual void addCheckButton(const char* label, float* zone); + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step); + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step); + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step); + + // -- passive display widgets + + virtual void addNumDisplay(const char* label, float* zone, int precision); + virtual void addTextDisplay(const char* label, float* zone, const char* names[], float min, float max); + virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max); + virtual void addVerticalBargraph(const char* label, float* zone, float min, float max); + + virtual void run(); + +}; + + + +/****************************************************************************** +******************************************************************************* + + GRAPHIC USER INTERFACE (v2) + gtk implementation + +******************************************************************************* +*******************************************************************************/ + +// global static fields + +list UI::fGuiList; + +map GTKUI::fGuiSize; +map GTKUI::fTooltip; + +GTKUI::GTKUI(GtkWidget *window) +{ + fTop = 0; + fBox[fTop] = gtk_vbox_new (homogene, 4); + fMode[fTop] = kBoxMode; + gtk_container_add (GTK_CONTAINER (window), fBox[fTop]); +} + +// empilement des boites + +void GTKUI::pushBox(int mode, GtkWidget* w) +{ + ++fTop; + assert(fTop < stackSize); + fMode[fTop] = mode; + fBox[fTop] = w; +} + + +/** + * Remove n levels from the stack S before the top level + * adjustStack(n): S -> S' with S' = S(0),S(n+1),S(n+2),... + */ +void GTKUI::adjustStack(int n) +{ + if (n > 0) { + assert(fTop >= n); + + fTop -= n; + fMode[fTop] = fMode[fTop+n]; + fBox[fTop] = fBox[fTop+n]; + } +} + +void GTKUI::closeBox() +{ + --fTop; + assert(fTop >= 0); +} + + +/** + * Analyses the widget zone metadata declarations and takes + * appropriate actions + */ +void GTKUI::declare(float* zone, const char* key, const char* value) +{ + if (strcmp(key,"size")==0) { + fGuiSize[zone]=atof(value); + } + else if (strcmp(key,"tooltip")==0) { + fTooltip[zone] = value ; + } +} + + + +/** + * Analyses a full label and activates the relevant options. returns a simplified + * label (without options) and an amount of stack adjustement (in case additional + * containers were pushed on the stack). + */ + +int GTKUI::checkLabelOptions(GtkWidget* widget, const string& fullLabel, string& simplifiedLabel) +{ + map metadata; + extractMetadata(fullLabel, simplifiedLabel, metadata); + + if (metadata.count("tooltip")) { + gtk_tooltips_set_tip (gtk_tooltips_new (), widget, metadata["tooltip"].c_str(), NULL); + } + if (metadata["option"] == "detachable") { + openHandleBox(simplifiedLabel.c_str()); + return 1; + } + + // no adjustement of the stack needed + return 0; +} + +/** + * Check if a tooltip is associated to a zone and add it to the corresponding widget + */ +void GTKUI::checkForTooltip(float* zone, GtkWidget* widget) +{ + if (fTooltip.count(zone)) { + gtk_tooltips_set_tip (gtk_tooltips_new (), widget, fTooltip[zone].c_str(), NULL); + } +} + + +// les differentes boites + +void GTKUI::openFrameBox(const char* label) +{ + GtkWidget * box = gtk_frame_new (label); + //gtk_container_set_border_width (GTK_CONTAINER (box), 10); + + pushBox(kSingleMode, addWidget(label, box)); +} + + +void GTKUI::openTabBox(const char* fullLabel) +{ + string label; + GtkWidget* widget = gtk_notebook_new(); + + int adjust = checkLabelOptions(widget, fullLabel, label); + + pushBox(kTabMode, addWidget(label.c_str(), widget)); + + // adjust stack because otherwise Handlebox will remain open + adjustStack(adjust); +} + + +void GTKUI::openHorizontalBox(const char* fullLabel) +{ + string label; + GtkWidget* box = gtk_hbox_new (homogene, 4); + int adjust = checkLabelOptions(box, fullLabel, label); + + gtk_container_set_border_width (GTK_CONTAINER (box), 10); + + if (fMode[fTop] != kTabMode && label[0] != 0) { + GtkWidget * frame = addWidget(label.c_str(), gtk_frame_new (label.c_str())); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } else { + pushBox(kBoxMode, addWidget(label.c_str(), box)); + } + + // adjust stack because otherwise Handlebox will remain open + adjustStack(adjust); +} + + +void GTKUI::openVerticalBox(const char* fullLabel) +{ + string label; + GtkWidget * box = gtk_vbox_new (homogene, 4); + int adjust = checkLabelOptions(box, fullLabel, label); + + gtk_container_set_border_width (GTK_CONTAINER (box), 10); + g_signal_connect(box, "expose-event", G_CALLBACK(gx_cairo::tribal_box_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) { + GtkWidget * frame = addWidget(label.c_str(), gtk_frame_new (label.c_str())); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } else { + pushBox(kBoxMode, addWidget(label.c_str(), box)); + } + + // adjust stack because otherwise Handlebox will remain open + adjustStack(adjust); +} + + +void GTKUI::openHandleBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_handle_box_new ()); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + + +void GTKUI::openEventBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_event_box_new ()); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + + +struct uiExpanderBox : public uiItem +{ + GtkExpander* fButton; + uiExpanderBox(UI* ui, float* zone, GtkExpander* b) : uiItem(ui, zone), fButton(b) {} + static void expanded (GtkWidget *widget, gpointer data) + { + float v = gtk_expander_get_expanded (GTK_EXPANDER(widget)); + if (v == 1.000000) + { + v = 0; + } + else v = 1; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_expander_set_expanded(GTK_EXPANDER(fButton), v); + } +}; + +void GTKUI::openExpanderBox(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget * box = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_expander_new (label)); + gtk_container_add (GTK_CONTAINER(frame), box); + uiExpanderBox* c = new uiExpanderBox(this, zone, GTK_EXPANDER(frame)); + gtk_signal_connect (GTK_OBJECT (frame), "activate", GTK_SIGNAL_FUNC (uiExpanderBox::expanded), (gpointer)c); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + + + +GtkWidget* GTKUI::addWidget(const char* label, GtkWidget* w) +{ + switch (fMode[fTop]) { + case kSingleMode : gtk_container_add (GTK_CONTAINER(fBox[fTop]), w); break; + case kBoxMode : gtk_box_pack_start (GTK_BOX(fBox[fTop]), w, expand, fill, 0); break; + case kTabMode : gtk_notebook_append_page (GTK_NOTEBOOK(fBox[fTop]), w, gtk_label_new(label)); break; + } + gtk_widget_show (w); + return w; +} + +// --------------------------- Press button --------------------------- + +struct uiButton : public uiItem +{ + GtkButton* fButton; + + uiButton (UI* ui, float* zone, GtkButton* b) : uiItem(ui, zone), fButton(b) {} + + static void pressed( GtkWidget *widget, gpointer data ) + { + uiItem* c = (uiItem*) data; + c->modifyZone(1.0); + } + + static void released( GtkWidget *widget, gpointer data ) + { + uiItem* c = (uiItem*) data; + c->modifyZone(0.0); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + if (v > 0.0) gtk_button_pressed(fButton); else gtk_button_released(fButton); + } +}; + +void GTKUI::addButton(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget* button = gtk_button_new_with_label (label); + addWidget(label, button); + + uiButton* c = new uiButton(this, zone, GTK_BUTTON(button)); + + gtk_signal_connect (GTK_OBJECT (button), "pressed", GTK_SIGNAL_FUNC (uiButton::pressed), (gpointer) c); + gtk_signal_connect (GTK_OBJECT (button), "released", GTK_SIGNAL_FUNC (uiButton::released), (gpointer) c); + + checkForTooltip(zone, button); +} + +// --------------------------- Toggle Buttons --------------------------- + +struct uiToggleButton : public uiItem +{ + GtkToggleButton* fButton; + + uiToggleButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {} + + static void toggled (GtkWidget *widget, gpointer data) + { + float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_toggle_button_set_active(fButton, v > 0.0); + } +}; + +void GTKUI::addToggleButton(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget* button = gtk_toggle_button_new_with_label (label); + addWidget(label, button); + + uiToggleButton* c = new uiToggleButton(this, zone, GTK_TOGGLE_BUTTON(button)); + gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC (uiToggleButton::toggled), (gpointer) c); + + checkForTooltip(zone, button); +} + + + +void show_dialog(GtkWidget *widget, gpointer data) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget)) == TRUE) + { + gtk_widget_show(GTK_WIDGET(data)); + gint root_x, root_y; + gtk_window_get_position (GTK_WINDOW(data), &root_x, &root_y); + root_y -= 120; + gtk_window_move(GTK_WINDOW(data), root_x, root_y); + } + else gtk_widget_hide(GTK_WIDGET(data)); +} + +static gboolean deleteevent( GtkWidget *widget, gpointer data ) +{ + return TRUE; +} + +void GTKUI::openDialogBox(const char* label, float* zone) +{ + // create toplevel window and set properties + GtkWidget * dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_decorated(GTK_WINDOW(dialog), TRUE); + gtk_window_set_deletable(GTK_WINDOW(dialog), FALSE); + gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); + gtk_window_set_gravity(GTK_WINDOW(dialog), GDK_GRAVITY_SOUTH); + //##FIXME gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(fWindow)); + gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); + gtk_window_set_keep_below (GTK_WINDOW(dialog), FALSE); + gtk_window_set_title (GTK_WINDOW (dialog), label); + g_signal_connect (G_OBJECT (dialog), "delete_event", G_CALLBACK (deleteevent), NULL); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + + GtkWidget * box = gtk_hbox_new (homogene, 4); + + *zone = 0.0; + GtkWidget* button = gtk_toggle_button_new (); + gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC (show_dialog), (gpointer) dialog); + + gtk_container_add (GTK_CONTAINER(fBox[fTop]), button); + gtk_container_add (GTK_CONTAINER(dialog), box); + gtk_widget_show (button); + gtk_widget_show(box); + pushBox(kBoxMode, box); +} + +// --------------------------- Adjustmenty based widgets --------------------------- + +struct uiAdjustment : public uiItem +{ + GtkAdjustment* fAdj; + + uiAdjustment(UI* ui, float* zone, GtkAdjustment* adj) : uiItem(ui, zone), fAdj(adj) {} + + static void changed (GtkWidget *widget, gpointer data) + { + float v = GTK_ADJUSTMENT (widget)->value; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_adjustment_set_value(fAdj, v); + } +}; + +static int precision(double n) +{ + if (n < 0.009999) return 3; + else if (n < 0.099999) return 2; + else if (n < 0.999999) return 1; + else return 0; +} + +struct uiValueDisplay : public uiItem +{ + GtkLabel* fLabel; + int fPrecision ; + + uiValueDisplay(UI* ui, float* zone, GtkLabel* label, int precision) + : uiItem(ui, zone), fLabel(label), fPrecision(precision) {} + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + char s[64]; + if (fPrecision <= 0) + snprintf(s, 63, "%d", int(v)); + + else if (fPrecision > 3) + snprintf(s, 63, "%f", v); + + else if (fPrecision == 1) + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[1-1], v); + } + else if (fPrecision == 2) + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[2-1], v); + } + else + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[3-1], v); + } + gtk_label_set_text(fLabel, s); + } +}; + +// --------------------------- Check Button --------------------------- + +struct uiCheckButton : public uiItem +{ + GtkToggleButton* fButton; + + uiCheckButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {} + + static void toggled (GtkWidget *widget, gpointer data) + { + float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0; + ((uiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_toggle_button_set_active(fButton, v > 0.0); + } +}; + +void GTKUI::addCheckButton(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_mini_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + openHorizontalBox(""); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); + checkForTooltip(zone, slider); +} + + +// -------------------------- Vertical Slider ----------------------------------- + +void GTKUI::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkWidget* lw = gtk_label_new(""); + GtkWidget* lwl = gtk_label_new(label); + gtk_widget_set_name (lw,"value_label"); + gtk_widget_set_name (lwl,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + gtk_widget_modify_font(lwl, style->font_desc); + new uiValueDisplay(this, zone, GTK_LABEL(lw),precision(step)); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_regler_new_with_adjustment(GTK_ADJUSTMENT(adj)); + + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + openVerticalBox(""); + addWidget(label, lwl); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); + checkForTooltip(zone, slider); +} + +// -------------------------- Horizontal Slider ----------------------------------- + +void GTKUI::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + + gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c); + + GtkWidget* slider = gtk_hscale_new (GTK_ADJUSTMENT(adj)); + gtk_scale_set_digits(GTK_SCALE(slider), precision(step)); + float size = 160 * pow(2, fGuiSize[zone]); + gtk_widget_set_usize(slider, size, -1); + + if (label && label[0]!=0) { + openFrameBox(label); + addWidget(label, slider); + closeBox(); + } else { + addWidget(label, slider); + } + + checkForTooltip(zone, slider); +} + + +// ------------------------------ Num Entry ----------------------------------- + +void GTKUI::addNumEntry(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, step); + + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + + gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c); + + GtkWidget* spinner = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 0.005, precision(step)); + + //gtk_widget_set_usize(slider, 160, -1); + openFrameBox(label); + addWidget(label, spinner); + closeBox(); + + checkForTooltip(zone, spinner); +} + + +// ========================== passive widgets =============================== + + +// ------------------------------ Progress Bar ----------------------------------- + +struct uiBargraph : public uiItem +{ + GtkProgressBar* fProgressBar; + float fMin; + float fMax; + + uiBargraph(UI* ui, float* zone, GtkProgressBar* pbar, float lo, float hi) + : uiItem(ui, zone), fProgressBar(pbar), fMin(lo), fMax(hi) {} + + float scale(float v) { return (v-fMin)/(fMax-fMin); } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_progress_bar_set_fraction(fProgressBar, scale(v)); + } +}; + + + +void GTKUI::addVerticalBargraph(const char* label, float* zone, float lo, float hi) +{ + GtkWidget* pb = gtk_progress_bar_new(); + gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_BOTTOM_TO_TOP); + gtk_widget_set_size_request(pb, 8, -1); + new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi); + openFrameBox(label); + addWidget(label, pb); + closeBox(); + + checkForTooltip(zone, pb); +} + + +void GTKUI::addHorizontalBargraph(const char* label, float* zone, float lo, float hi) +{ + GtkWidget* pb = gtk_progress_bar_new(); + gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_LEFT_TO_RIGHT); + gtk_widget_set_size_request(pb, -1, 8); + new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi); + openFrameBox(label); + addWidget(label, pb); + closeBox(); + + checkForTooltip(zone, pb); +} + + +// ------------------------------ Num Display ----------------------------------- + +struct uiNumDisplay : public uiItem +{ + GtkLabel* fLabel; + int fPrecision; + + uiNumDisplay(UI* ui, float* zone, GtkLabel* label, int precision) + : uiItem(ui, zone), fLabel(label), fPrecision(precision) {} + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + char s[64]; + if (fPrecision <= 0) { + snprintf(s, 63, "%d", int(v)); + } else if (fPrecision>3) { + snprintf(s, 63, "%f", v); + } else { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[fPrecision-1], v); + } + gtk_label_set_text(fLabel, s); + } +}; + + +void GTKUI::addNumDisplay(const char* label, float* zone, int precision ) +{ + GtkWidget* lw = gtk_label_new(""); + new uiNumDisplay(this, zone, GTK_LABEL(lw), precision); + openFrameBox(label); + addWidget(label, lw); + closeBox(); + + checkForTooltip(zone, lw); +} + + +// ------------------------------ Text Display ----------------------------------- + +struct uiTextDisplay : public uiItem +{ + GtkLabel* fLabel; + const char** fNames; + float fMin; + float fMax; + int fNum; + + + uiTextDisplay (UI* ui, float* zone, GtkLabel* label, const char* names[], float lo, float hi) + : uiItem(ui, zone), fLabel(label), fNames(names), fMin(lo), fMax(hi) + { + fNum = 0; + while (fNames[fNum] != 0) fNum++; + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + + int idx = int(fNum*(v-fMin)/(fMax-fMin)); + + if (idx < 0) idx = 0; + else if (idx >= fNum) idx = fNum-1; + + gtk_label_set_text(fLabel, fNames[idx]); + } +}; + + +void GTKUI::addTextDisplay(const char* label, float* zone, const char* names[], float lo, float hi ) +{ + GtkWidget* lw = gtk_label_new(""); + new uiTextDisplay (this, zone, GTK_LABEL(lw), names, lo, hi); + openFrameBox(label); + addWidget(label, lw); + closeBox(); + + checkForTooltip(zone, lw); +} + + + +/** + * Update all user items reflecting zone z + */ + +static gboolean callUpdateAllGuis(gpointer) +{ + UI::updateAllGuis(); + return TRUE; +} + + +void GTKUI::run() +{ + assert(fTop == 0); + gtk_widget_show (fBox[0]); + gtk_timeout_add(40, callUpdateAllGuis, 0); +} + + +/****************************************************************************** +******************************************************************************* + + FAUST DSP + +******************************************************************************* +*******************************************************************************/ + + + + + +//---------------------------------------------------------------- +// Definition of an abstract signal processor +//---------------------------------------------------------------- + +class dsp { +protected: + int fSamplingFreq; +public: + dsp() {} + virtual ~dsp() {} + + virtual int getNumInputs() = 0; + virtual int getNumOutputs() = 0; + virtual void buildUserInterface(UI* interface) = 0; + virtual void init(int samplingRate) = 0; + virtual void compute(int len, float** inputs, float** outputs) = 0; + void setup(GtkWidget *window); +}; + +void dsp::setup(GtkWidget *window) +{ + GTKUI *interface = new GTKUI (window); + buildUserInterface(interface); + interface->run(); +} + +#define DSP_HAS_SETUP + + +//---------------------------------------------------------------------------- +// FAUST generated code +//---------------------------------------------------------------------------- + +<> diff --git a/src/gx_cairo_callbacks.cpp b/src/gx_cairo_callbacks.cpp new file mode 100644 index 0000000..71874b2 --- /dev/null +++ b/src/gx_cairo_callbacks.cpp @@ -0,0 +1,1051 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 are the cairo callbacks to draw the guitarix UI + * + * + * -------------------------------------------------------------------------- + */ + +#include "guitarix.h" + +/* --------------------------- gx_cairo namespace ------------------------ */ +namespace gx_cairo +{ + +// set cairo color related to the used skin +void gx_skin_color(cairo_pattern_t *pat) +{ + int skin_is = int(float(gx_gui::gx_current_skin)); + + switch (skin_is) + { + case 0: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.2, 0.3, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.05, 0.6); + break; + case 1: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.2, 0.3, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.05, 0.6); + break; + case 2: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.3, 0.2, 0.3, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.05, 0.6); + break; + case 3: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.5, 0.02, 0.03, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.05, 0.1, 0.6); + break; + case 4: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.5, 0.2, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.05, 0.1, 0.05, 0.6); + break; + case 5: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.8, 0.2, 0.02, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.2, 0.09, 0.005, 0.6); + break; + case 6: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.8, 0.3, 0.02, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.2, 0.06, 0.005, 0.6); + break; + case 7: + cairo_pattern_add_color_stop_rgba (pat, 0, 0.8, 0.8, 0.8, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.3, 0.3, 0.3, 0.6); + break; + case 8: + cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 0.9); + cairo_pattern_add_color_stop_rgba (pat, 0.8, 0.9, 0.9, 1, 0.9); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.8, 0.8, 0.9, 0.5); + break; + } + +} + +//----- paint boxes with cairo ----- +gboolean amp_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+2; + double y0 = wi->allocation.y+2; + double rect_width = wi->allocation.width-4; + double rect_height = wi->allocation.height-4; + double radius = 25.; + double x1,y1; + x1=x0+rect_width; + y1=y0+rect_height; + + 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); + + cairo_set_source_rgba (cr, 0, 0, 0, 0.6); + cairo_set_line_width (cr, 5.0); + cairo_stroke (cr); + + 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); + + cairo_set_source_rgb (cr, 0.02, 0.02, 0.02); + cairo_set_line_width (cr, 1.0); + cairo_stroke (cr); + + cairo_destroy(cr); + return FALSE; +} + +gboolean conv_widget_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + cairo_pattern_t *pat; + + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+5; + double y0 = wi->allocation.y+5; + double rect_width = wi->allocation.width-10; + double rect_height = wi->allocation.height-10; + double radius = 36.; + double x1,y1; + x1=x0+rect_width; + y1=y0+rect_height; + + 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); + + pat = cairo_pattern_create_linear (0, y0, 0, y1); + cairo_pattern_add_color_stop_rgba (pat, 1, 0., 0., 0., 0.8); + cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 0, 0.4); + cairo_set_source (cr, pat); + cairo_fill_preserve (cr); + + cairo_set_source_rgba (cr, 0, 0, 0, 0.8); + cairo_set_line_width (cr, 9.0); + cairo_stroke (cr); + + 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); + + cairo_set_source_rgb (cr, 0.2, 0.2, 0.2); + cairo_set_line_width (cr, 1.0); + cairo_stroke (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean upper_widget_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + cairo_pattern_t *pat; + + gint x, y; + gint w, h; + /* get the dimensions */ + x = wi->allocation.x+2; + y = wi->allocation.y+2; + w = wi->allocation.width-4; + h = wi->allocation.height-4; + + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + cairo_move_to (cr, x, y); + cairo_curve_to (cr, x+w*0.66, y, x+w*0.33, y+h, x+w, y+h); + cairo_line_to (cr, x+w , y); + cairo_set_line_width (cr, 3.0); + cairo_close_path (cr); + + pat = cairo_pattern_create_linear (0, y, 0, y+h); + cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 0.8); + cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 0, 0); + cairo_set_source (cr, pat); + cairo_fill_preserve (cr); + cairo_stroke (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; + +} + +gboolean rectangle_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-11; + + cairo_rectangle (cr, x0,y0,rect_width,rect_height+3); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width+100, rect_height, 0.0); + cairo_pattern_add_color_stop_rgb (pat, 0, 0.2, 0.2, 0.3); + cairo_pattern_add_color_stop_rgb (pat, 1, 0.05, 0.05, 0.05); + gx_skin_color(pat); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+1,y0+1,rect_width-2,rect_height-1); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean rectangle_skin_color_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-2; + + cairo_rectangle (cr, x0,y0,rect_width,rect_height+3); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width-10, rect_height, 20.0); + gx_skin_color(pat); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+1,y0+1,rect_width-2,rect_height-1); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean convolver_icon_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo black arc to given widget */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-2; + + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + cairo_rectangle (cr, x0,y0,rect_width,rect_height+3); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width+100, rect_height, 0.0); + gx_skin_color(pat); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+1,y0+1,rect_width-2,rect_height-1); + cairo_fill (cr); + + cairo_move_to (cr, x0+10, y0 + (rect_height*0.5)); + cairo_curve_to (cr, x0+30,y0 + (rect_height*0.005), x0+50, y0 + (rect_height*0.995), x0+70, y0 + (rect_height*0.5)); + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_set_line_width (cr, 1.0); + cairo_stroke (cr); + + cairo_move_to (cr, x0+10, y0 + (rect_height*0.5)); + cairo_line_to (cr, x0+75 , y0 + (rect_height*0.5)); + cairo_move_to (cr, x0+10, y0 + (rect_height*0.2)); + cairo_line_to (cr, x0+10 , y0 + (rect_height*0.8)); + cairo_set_source_rgb (cr, 0.2, 0.8, 0.2); + cairo_set_line_width (cr, 1.0); + cairo_stroke (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean zac_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-3; + + cairo_rectangle (cr, x0,y0,rect_width,rect_height+3); + cairo_pattern_t*pat = + cairo_pattern_create_radial (200, rect_height*0.5, 5,200, rect_height*0.5, 200.0); + cairo_pattern_add_color_stop_rgb (pat, 0, 0.8, 0.8, 0.8); + cairo_pattern_add_color_stop_rgb (pat, 1, 0.3, 0.3, 0.3); + cairo_set_source (cr, pat); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean level_meter_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + cairo_set_font_size (cr, 7.0); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+2; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-4; + + int db_points[] = { -50, -40, -20, -30, -10, -3, 0, 4 }; + char buf[32]; + + cairo_rectangle (cr, x0,y0,rect_width,rect_height+2); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width-10, rect_height, 20.0); + cairo_pattern_add_color_stop_rgb (pat, 0, 0.2, 0.2, 0.3); + cairo_pattern_add_color_stop_rgb (pat, 1, 0.05, 0.05, 0.05); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+1,y0+1,rect_width-2,rect_height-2); + cairo_fill (cr); + + for (uint32_t i = 0; i < sizeof (db_points)/sizeof (db_points[0]); ++i) + { + float fraction = gx_threads::log_meter (db_points[i]); + cairo_set_source_rgb (cr, 0.12*i, 1, 0.1); + + cairo_move_to (cr, x0+rect_width*0.2,y0+rect_height - (rect_height * fraction)); + cairo_line_to (cr, x0+rect_width*0.8 ,y0+rect_height - (rect_height * fraction)); + if (i<6) + { + snprintf (buf, sizeof (buf), "%d", db_points[i]); + cairo_move_to (cr, x0+rect_width*0.32,y0+rect_height - (rect_height * fraction)); + } + else + { + snprintf (buf, sizeof (buf), " %d", db_points[i]); + cairo_move_to (cr, x0+rect_width*0.34,y0+rect_height - (rect_height * fraction)); + } + cairo_show_text (cr, buf); + } + + cairo_set_source_rgb (cr, 0.4, 0.8, 0.4); + cairo_set_line_width (cr, 0.5); + cairo_stroke (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean AmpBox_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-2; + + cairo_rectangle (cr, x0-1,y0-1,rect_width+2,rect_height+2); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width-10, rect_height, 20.0); + gx_skin_color(pat); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+2,y0+2,rect_width-4,rect_height-4); + cairo_fill (cr); + + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+rect_width-3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+rect_height-2); + cairo_line_to(cr, x0+2, y0+rect_height-2); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+3, y0+rect_height-1); + cairo_line_to(cr, x0+3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+3); + cairo_stroke(cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean tribal_box_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + if (int(float(gx_gui::gx_current_skin)!=1) && int(float(gx_gui::gx_current_skin)<7)) + { + GdkPixbuf *_image; + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-3; + + _image = gdk_pixbuf_scale_simple(tribeimage1,rect_width,rect_height,GDK_INTERP_HYPER); + + cairo_pattern_t*pat; + + double radius = 38.; + if (rect_width<38) radius = rect_width; + else if (rect_height<38) radius = rect_height; + double x1,y1; + + x1=x0+rect_width; + y1=y0+rect_height; + + 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); + pat = cairo_pattern_create_linear (0, y0, 0, y1); + cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 0.8); + cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.05, 0.05, 0.05, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.2, 0.2, 0.4); + cairo_set_source (cr, pat); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + gdk_draw_pixbuf(GDK_DRAWABLE(wi->window), gdk_gc_new(GDK_DRAWABLE(wi->window)), + _image, 0, 0, + x0, y0, rect_width,rect_height, + GDK_RGB_DITHER_NORMAL, 0, 0); + + g_object_unref(_image); + } + return FALSE; +} + +gboolean vbox_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + if (int(float(gx_gui::gx_current_skin)==1)) + { + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-3; + + cairo_rectangle (cr, x0,y0,rect_width,rect_height+3); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width+100, rect_height, 0.0); + cairo_pattern_add_color_stop_rgb (pat, 0, 0.2, 0.2, 0.3); + cairo_pattern_add_color_stop_rgb (pat, 1, 0.05, 0.05, 0.05); + + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+1,y0+1,rect_width-2,rect_height-1); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + } + else if (int(float(gx_gui::gx_current_skin)>=7)) + zac_expose(wi,ev,user_data); + + return FALSE; +} + +gboolean filter_box_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + GdkPixbuf *_image; + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-3; + + _image = gdk_pixbuf_scale_simple(tribeimage,rect_width,rect_height,GDK_INTERP_HYPER); + + cairo_pattern_t*pat; + + gdk_draw_pixbuf(GDK_DRAWABLE(wi->window), gdk_gc_new(GDK_DRAWABLE(wi->window)), + _image, 0, 0, + x0, y0, rect_width,rect_height, + GDK_RGB_DITHER_NORMAL, 0, 0); + + double radius = 38.; + if (rect_width<38) radius = rect_width; + else if (rect_height<38) radius = rect_height; + double x1,y1; + + x1=x0+rect_width; + y1=y0+rect_height; + + 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); + + pat = cairo_pattern_create_linear (0, y0, 0, y1); + cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 0, 0.8); + cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.05, 0.05, 0.05, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 0, 0.2, 0.2, 0.2, 0.4); + cairo_set_source (cr, pat); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + g_object_unref(_image); + + return FALSE; +} + +gboolean boxamp_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + if(!gx_engine::audio.fampexpand) { + GdkPixbuf *_image; + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height; + + _image = gdk_pixbuf_scale_simple(tribeimage2,rect_width,rect_height,GDK_INTERP_HYPER); + + gdk_draw_pixbuf(GDK_DRAWABLE(wi->window), gdk_gc_new(GDK_DRAWABLE(wi->window)), + _image, 0, 0, + x0, y0, rect_width,rect_height, + GDK_RGB_DITHER_NORMAL, 0, 0); + + cairo_destroy(cr); + g_object_unref(_image); + } + return FALSE; +} + +gboolean eq_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+5; + double y0 = wi->allocation.y; + // double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-50; + float p = gx_gui::parameter_map["eq.f31_25"].getFloat().value; + float q = 100 - gx_gui::parameter_map["eq.Q31_25"].getFloat().value; + //float v = p.value; + cairo_move_to (cr, x0 , y0 + rect_height-(62*q*0.01)-p); + cairo_line_to (cr, x0 + 14, y0 + rect_height-62 - p); + cairo_line_to (cr, x0 + 33, y0 + rect_height-(62*q*0.01)-p); + p = gx_gui::parameter_map["eq.f62_5"].getFloat().value; + q = 100 - gx_gui::parameter_map["eq.Q62_5"].getFloat().value; + cairo_move_to (cr, x0 +35 , y0 + rect_height-(62*q*0.01)-p); + cairo_line_to (cr, x0 + 46, y0 + rect_height-62 - p); + cairo_line_to (cr, x0 +62 , y0 + rect_height-(62*q*0.01)-p); + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_set_line_width(cr, 2.0); + cairo_stroke(cr); + + cairo_destroy(cr); + return FALSE; +} + +gboolean plug_box_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-2; + + cairo_rectangle (cr, x0-1,y0-1,rect_width+2,rect_height+2); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width-10, rect_height, 20.0); + gx_skin_color(pat); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+2,y0+2,rect_width-4,rect_height-4); + cairo_fill (cr); + + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+rect_width-3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+rect_height-2); + cairo_line_to(cr, x0+2, y0+rect_height-2); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+3, y0+rect_height-1); + cairo_line_to(cr, x0+3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+3); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); + cairo_set_line_width(cr, 1.5); + cairo_arc (cr, x0+7, y0+7, 1.5, 0, 2*M_PI); + cairo_move_to(cr,x0+rect_width-8, y0+7); + cairo_arc (cr, x0+rect_width-7, y0+7, 1.5, 0, 2*M_PI); + cairo_move_to(cr,x0+rect_width-7, y0+rect_height-6); + cairo_arc (cr, x0+rect_width-7, y0+rect_height-6, 1.5, 0, 2*M_PI); + cairo_move_to(cr,x0+7, y0+rect_height-6); + cairo_arc (cr, x0+7, y0+rect_height-6, 1.5, 0, 2*M_PI); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean info_box_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-2; + + cairo_rectangle (cr, x0-1,y0-1,rect_width+2,rect_height+2); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_set_line_width(cr, 2.0); + cairo_stroke(cr); + + cairo_pattern_t*pat = cairo_pattern_create_linear (x0, y0+50,x0, y0); + cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT); + if(gx_jconv::GxJConvSettings::checkbutton7 == 1) { + cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0.8, 0, 0.8); + cairo_pattern_add_color_stop_rgba (pat, 0.5, 0.05, 0.8, 0.05, 0.6); + cairo_pattern_add_color_stop_rgba (pat, 1, 0.2, 0.8, 0.2, 0.4); + } else { + gx_skin_color(pat); + } + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+2,y0+2,rect_width-4,rect_height-4); + cairo_fill (cr); + + cairo_rectangle (cr, x0+8,y0+31,rect_width-16,rect_height-60); + cairo_set_source_rgb (cr, 0.5, 0.5, 0.5); + cairo_set_line_width(cr, 2.0); + cairo_stroke_preserve(cr); + pat = cairo_pattern_create_linear (x0, y0+50,x0, y0); + cairo_pattern_set_extend(pat, CAIRO_EXTEND_REFLECT); + gx_skin_color(pat); + cairo_set_source (cr, pat); + cairo_fill (cr); + + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+rect_width-3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+rect_height-2); + cairo_line_to(cr, x0+2, y0+rect_height-2); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+3, y0+rect_height-1); + cairo_line_to(cr, x0+3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+3); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); + cairo_set_line_width(cr, 1.5); + cairo_arc (cr, x0+7, y0+7, 1.5, 0, 2*M_PI); + cairo_move_to(cr,x0+rect_width-8, y0+7); + cairo_arc (cr, x0+rect_width-7, y0+7, 1.5, 0, 2*M_PI); + cairo_move_to(cr,x0+rect_width-7, y0+rect_height-6); + cairo_arc (cr, x0+rect_width-7, y0+rect_height-6, 1.5, 0, 2*M_PI); + cairo_move_to(cr,x0+7, y0+rect_height-6); + cairo_arc (cr, x0+7, y0+rect_height-6, 1.5, 0, 2*M_PI); + cairo_stroke_preserve(cr); + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_fill (cr); + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +gboolean slooper_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data) +{ + cairo_t *cr; + /* create a cairo context */ + cr = gdk_cairo_create(wi->window); + + double x0 = wi->allocation.x+1; + double y0 = wi->allocation.y+1; + double rect_width = wi->allocation.width-2; + double rect_height = wi->allocation.height-2; + + cairo_rectangle (cr, x0-1,y0-1,rect_width+2,rect_height+2); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_fill (cr); + + cairo_pattern_t*pat = + cairo_pattern_create_radial (-50, y0, 5,rect_width-10, rect_height, 20.0); + gx_skin_color(pat); + cairo_set_source (cr, pat); + cairo_rectangle (cr, x0+2,y0+2,rect_width-4,rect_height-27); + cairo_fill (cr); + + cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+rect_width-3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+rect_height-2); + cairo_line_to(cr, x0+2, y0+rect_height-2); + cairo_move_to(cr,x0+2, y0+rect_height-25); + cairo_line_to(cr, x0+rect_width-3, y0+rect_height-25); + cairo_stroke(cr); + + cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); + cairo_set_line_width(cr, 2.0); + cairo_move_to(cr,x0+3, y0+rect_height-1); + cairo_line_to(cr, x0+3, y0+3); + cairo_line_to(cr, x0+rect_width-3, y0+3); + cairo_move_to(cr,x0+2, y0+rect_height-27); + cairo_line_to(cr, x0+rect_width-3, y0+rect_height-27); + cairo_stroke(cr); + + + cairo_pattern_destroy (pat); + cairo_destroy(cr); + + return FALSE; +} + +void gx_init_pixmaps() +{ + /* XPM */ + static const char * tribe_xpm[] = + { + "200 129 3 1", + " c None", + ". c #194C4C", + "+ c #194E4E", + " ", + " ", + " ", + " .+ ", + " ++ ", + " ++ ", + " .. ", + " +++ ", + " +.+ ", + " +.+. ", + " ++.+ ", + " ++ +. ", + " + + ", + " . ++ ", + " +. +. ", + " .. +. ", + " +. +++ ", + " ++ ++ ... ", + " + +.+ .+. ", + " .+ ... .... + ", + " . .++..+.++ .+ ", + " ++ .. ..++ . ", + " . .. ..++.+ . ", + " . ++ . .++ ", + " .+ .++ +.+... ", + " +. ... . +. ", + " .. .++ . .. ", + " +. +++ .. ", + " .+. .+. ", + " +.. ++.. ", + " . . .. .++. ", + " + + . ++. ", + " . +. ++ .. .+ ", + " . ++ ++ + + ", + " . +.. +. .+ ", + " .+ . ++. .. .+ ", + " ++ . +.. ++ + ", + " +++ . . .+.+ +. .+ ", + " .+. .+ + .... ..++ ", + " +.+ ++ +. .+.+ ++. ", + " .++ .+ .+ ..++. + ", + " +... .. ++ .++.++ ", + " +.++ +. +. +++.. ", + " .++. ++ .. .+++.+ ", + " ..+++ .++. + .. .+.+.. ", + " .+++. .+++ ++ .. .++ ", + " ...++ .++. +.. +.+ .. ", + " +... +++. ... +++ .. ", + " +.. +++.+ +..+ ... . ", + " . +++++ +..+ .+.. ", + " + +++.++ .+++ ++.+.+. ", + " . +++++. +++.. ++++.. ", + " . ++++.++ ++++. +++ +.+.. ", + " .. . ++++... +.+.+. +... ..+ ", + " +..+ +++++++. +..++ ++++++ ", + " ...+++ +.+++++.. +++ +.++++.++ ", + " ..+.++ ..++++..+ ++++.+++.+..+ ", + " .+. .++ .++++.... +.+..++++..+ ", + " .+.+ .+. .+++ +++.... .+ . ++.++++.++..+.. ", + " + +...+.. +. ++... + .+... .+++. ....+. .++.+.++..+.+.++++++.+. ", + " .+++..++..+ .. .+... + .++++. .+ .+ ..+.. .++++.++++++.++.+.++ ", + " +..++ .+.+.. ++++ +++ +.+++.+. ++++. .++..+ ++.+...+ ... ", + " +++...+ +.. .... .+ ++++++++. . +..++.+. +++ . ", + " +.+..+... +. .+.+. .+ .+++++++ +++++++++++..+ ++ ", + " ..+.+..+ ..++.+ + .++++.+. ..+++++++++++.. ", + " + .+.+.+++ ++.++++ ..++++.. . +.+.+++......+. ", + " ... .+.+ +.++.+..+ +..++.+ .++..+. .++. ..+.+. ++++. ", + " ++. +..+ .++ ..+.+ +.+++.+ .+.+. ++++. +++..+ ++ ", + " +.. ..... ..+ +..++. +.++... + .++...+ ..++ ....+. ", + " ++. .+.++ ..++.+.++. .+++++++ +. ....++... .+. +......+ ", + " ++.+ +..+++ ++. .+..+ +.+++.. +...++++++.+.. . .+ +.+..+ ", + " ..++ ++.++. +.+..+++.+ +++++.. ..+ +++++.++.+++.+ + ....++.. ", + " + .++++ +..+.+ ++.++++++++ .++.+ ..++ +++++. .+++++ .. +.+..+.+.. ", + " + +. .+... ..++.+ +.++++++.. ... +.+... .+++.+. .+ ..+++.+.+.. ", + " . +. . ++++. +..+ .++++++++ .+ ...+++. +++.+ .+++ ++ .++.++++++. ", + " +. .+ . ++..+ .+ +.++++... ++....++++++.+ +++. +..+.. ....+ .+..++++...+.+..++.+ + ", + " . .. . ....++ + .++..++. +. .+++++++++++.++ ... +++++.+ ++.+...+ ..+..++.+..... ++ ", + " +. ..+ +. +...++ ++ ...++ .... ...++++++++++. .. .++++.+. ..+.++..+++.+++ +.+ ", + " +. ..+ + .++ ++ . ..+++. .+++++++++++.. .+.+++.++ +. ++++.... ", + " +. + ...+ ++ .+ .. +++.++.++..+.+. ++.++..++.+..+ +.+++++.+ ..++.....+..+... ", + " +. + ...+ . + .+ +. ++ .+.+.++.++++.+ ......+ . +..+++.++ ............ ", + " .. . .+.. . +. ++ ++ +++. ..+++++++++++. +.+.+ .. +++...+.. ..+.+.+.. ", + " . .+ + +.... + +. +. .. ...+ ++++++++++++.. +++. ++++.+ .++.+.++.+ ..++ ", + " . +.. +. ..... +. + + .+ ... +..++.. .+++++++++++.. .. .+++.+ + . ..+++++ ", + " + .+. ++ ..++++ .. .. +. .+ ..+..++..+++.+ +.++++++++++.+ .+++++. .+++. + ", + " + ... .. .+...+ ..+.. .. .. ..+++.++++++. ....+ +...+..+ ++++++. ++...+.+... ", + " .. +..+ . +.+++ ...+.... +++ .. +.+ +.++++++++++++ +++++. ... +..+++ ", + " + +. .++. .. +++. ++.++++. . ++..++. +..++++.+...++ .++.. ..+ ..+++.. ", + " ++ . .+++. ++ . ++...++. .. ++++.+++...++ .+.. ..+.... ...+.+ ", + " +..+ +. +.+++ +.++++ ...+++. ..+ +.+.. +.+.. +. ++. ..+ +.++. + ", + " ...+.+. .. ++...+ +..+++ +..+ +++ . +++.+...++.+++ .. .. .+++. +. ", + " +++... .. ...+... +.+.+ .++++. .+... +.... +.+.+ +++ .. +.+ ++++. .. ", + " .++.+ .+ +++++.. +. +.++.+. ... +....+. ... +.+ .. ..+. .. ", + " ..+ ++ .+.+.++. +..++++ .. +.+ +. .++ .+ .+ +++. .+ ", + " ... +.+ ++.+++.. .... ++++ +++ +. .+ ... .+ ...+ +. ", + " +.++ ... .++++.+ .++ +..+. +. +. .+ ++ + +. +.++. ", + " +++.+.+ ..+ ..+++. ..+. .+.+.+ +++ +.. +. .++..+++ .. .. ", + " ...+++++.. +.+ .+++.+ ...+ ++++. .+++ .++ ++ .+..++. ++ + ", + " ...+++++++.+ .. ..+++ +++ .++++ +. .++ ++ .+ +.+++++ .. + ", + " ...++++++++++ .+ .++++ ++. . +++. ++ .. +.+ +.+ + .++++. . + ", + " ++ ...+.++++++++++ +. +.++.. .. ++ +++. + +. +..++. ++ .++++. .. + . ", + " .++ ++..+++.+..++.++ +. +.++++ ++ +.+ ++++ + +. ++.++. .+ ..+++. +. ", + " + ++. +++.+..+++. .. +. ..+++.++ . . ++++ + + ++++. +.+ +.+.+. +. + ", + " ..++. ++.+..+ .+ .+ .+++.++ + ++ +.+. + +. .+++. +...+ ..+.. +.. ", + " ...+. +..++ +..+ +. .+++ +. .. ..+. + . +..++ ++.++ ....+ ... ", + " .++++ .... +.+.+ + +.++. . + +.++ . . .... ++++ +..+ .. ", + " +.+. ...+ .+.+ +. +..+ +. ++.. + +.+ ++.. +++. +.. ", + " .++ .. +.. . .+++ + +.. + +.+ +.+ ..+. +. ", + " .... ++ +.+ +. +... . ..+ +++ +.. .+.. .+. ", + " +.. ++ ..+ . ...+ + ++. ++. +++ ++. ++ ", + " + + ++ ++ +... . .+ +.+ ..+ ... .. ", + " +. ++ .. .+.+ .. +. ++ .++ .+ ", + " . ++ . ..+. +. ++ .. +. . ", + " . + . ++++ +. +. .+ +. . ", + " . +.. +. .+ . . ", + " +. +. + + + ", + " ++. . + ", + " . ", + " + ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " "}; + +/* XPM */ + static const char * guitar_xpm[] = { + "65 20 3 1", + " c None", + ". c #353535", + "+ c #343434", + " ", + " ", + " ", + " ", + " . + ", + " .. ++.+++ . ...++ ", + " . ++. + + + +.+ ", + " + ++ .+ .+ +. +. ..+ ++ ", + " +.. .+ . ++ .+. + +.. +. . + ++.+ ", + " + + . . + .+ +. + . .+ .. + ", + " + +. . . . + +.++ .++. +. + +. + . + ", + " ++ .. . +++++. + ++.... . + .++.+ . ....... ++. +. ", + " + ++ +..+++.++. + .. + . + +.++.++ .+. ", + " . .+ . ", + " +.. ++ ", + " +. . ", + " ", + " ", + " ", + " "}; + + /* XPM */ + static const char * skull_xpm[] = { +"240 30 26 1", +" c None", +". c #562334", +"+ c #4A2B64", +"@ c #4A2E7F", +"# c #4C383C", +"$ c #4A3D68", +"% c #69399B", +"& c #673FAC", +"* c #5A4B9B", +"= c #6A4988", +"- c #4E5297", +"; c #505BC3", +"> c #67618D", +", c #6D636A", +"' c #59748A", +") c #5875B8", +"! c #5078D0", +"~ c #5A7AA5", +"{ c #54857C", +"] c #6D8266", +"^ c #8C7C4D", +"/ c #837E69", +"( c #549070", +"_ c #8C7F81", +": c #788F56", +"< c #5DA961", +" ", +" ", +" ", +" ", +" .+$-- @*%%== ......+$ ", +" ++$*; *%%%% @+....++ =...# ", +" +$$*; %%%%= +@++++++$ *=..# ", +" +++=* %%%== ++++++ >=>.# ", +" ==+++= %%===> +++++ ##,>.. ", +" =>>>>>>'{]]: /:_=.,$= ,>.## +++=* *==** %%%%===>> {]]:::]'', _=.,$=$## #+++++=*****= %===> >>>>'{] ::]'' :_=.,$ ##+++++=*****==******% ==>>>> {]]:: ,]/:_=.,$= ##_,,>.##+ ", +" ->~>>>>']_/], /]]:_=.$%%$ _,.#$ ++*** --*+=; ***@@**->~> ]_/],]]',, :_=.$%%$##, #$++++*****--* @**->~>>>>']_/ ,]]', :_=.$% #$++++*****--*+=;;***** *->~> ]_/], ,,/]]:_=.$%% ##,__,.#$+ ", +" ~''''''{]>//> ,/]^:_=#,=%$$ .##$+ +++*-- --*==; --****---~'''' ]>//>,'',, ]^:_=#,=%$$### #$+++++*------* ---~''''''{]>/ ,'', :_=#, $+++++*------*==;;;--** -~''' ]>//> ,,/]^:_=#,=% $###.##$++ ", +" >''''''{]>_:, /^^^:_=:<,&=+ ##$++ @@**-* *--*=* ;;---->>>>'''' ]>_:,,,,,/ ^^:_=:<,&=+$## $++@@@**-*;*--* >>>>''''''{]>_ ,,,,/ ^:_=:< @@@** --*=*;!;;;-- >>''' ]>_:, ,/^^^:_=:<,& ####$ ", +" >~'''{ ]__/: ::^^^: <,=&+ $++@@ @@@--; *--*=* ;;;;-- ~'''{ ']__/: ^^^:_, &++++ ++@@@@ ;**-- >>>>~'' {']__ ^^^:: ^:_,< @@@@@- ;;;;- >>~''' ']__/: ::^^^:_,< +++$++ ", +" )~~~'' {]__^ ::^^: :<=%& @@@@@@=@@@*;****** ;;;;;;!!))~~~'' {{]__^ ^^::>]<:<=%&+@@ @@@@@ ;**** !!))~~ {{{]_ /^::: ^::>]< @@=@@ *****;;;;;;; ))~~~ {{]__ ::^^::>]<:< +@@@@ ", +" ;;!)) {(:/, ::^^: ::{*% @%@='''>=%****===* ;;;;;;;;;;;!))~ ({(:/ ^^:/,::::{*%&@@ %@='' ***== ;;;;; {({(: ^:::: ^:/,: '''>= *===*&;;;;;;; ;;;!) ({(:/ ::^^:/,:::: &@@@% ", +" ;;;!! ({{:: _:::] :::-% %%$''==> =@*;**** *;;;;;;;;;;;!!) {({{: ::]>]].:::-%*&& %$''= @*;*** ;;;;; '{({{ ,$_:::]>] '==>> ;****;;***;;;; ;;;;! '{({{: :::]>]].:: *&&%% ", +" !!!!! '{{{(: #>__> #:]]-% @=>'-*** >@*);;*- !;;!; ~'{{{( __>/: =>'-* >@*);;* ;;!!!! )~'{{{ ^$#>__>/: -***> );;*-)) -!;;!; !!!!! ~'{{{( >/:/#:] *&*@= ", +" ~~~~~)!!)~'({(( /,,,::^^]:_/* =>'>@=* >@-)))) ~>)!;;!)~~~~~) )~'({ ,,::^^]:_/*&*; >'>@=**=>@-))) ;!)~~~~~)!!)~'( ^_/,,,:: >@=**= ))))~'~>~~>)!; ~~~~~)!!)~'({ _/,,,::^^]:_ *;*=>' ", +" {{{{''~!))'{{( /]:<:^/::/_,% >>'>@-* >@---)~ )~~)!;!~{{{{'' ))'{{ :<:^/::/_,%%&; >'>@-***>@---) ;!~{{{{''~!))'{ :^/]:<:^ >@-** --)~~~))))~~) {{{{''~!))'{{ :^/]:<:^/::/_ &;*>>'>@ ", +" ((]{{'~))!'{{ /,,,////__> >,,>@=- **---~ !)~!!!~((]{{' )!'{{ ,,////__>%%*; ,,>@=-->**---~ !!~((]{{'~))!' ::/,,, >@=-- --~~~)))!!!)~ ((]{{'~))!'{{ <::/,,,////__ *;*>,,>@ ", +" ({'''~~))~{{ //_,___/ ,,,>** @*-->' )~)!!'({'''~ )~{{( _,___/_,*&*; ,>**==*@*-->' !!'({'''~~))~ <<:// >**== >'~)))!!!!)~ ({'''~~))~{{( <<<://_,___ *;-,,,>* ", +" {('~~~ <<<]/ ", +" (<{'~ <<<<<: ", +" <<<(( (<<(<<<: ", +" <<<<< <<<<<<< ", +" ({((< <<<<<< ", +" ", +" ", +" "}; + + + tribeimage = gdk_pixbuf_new_from_xpm_data(tribe_xpm); + tribeimage1 = gdk_pixbuf_new_from_xpm_data(guitar_xpm); + tribeimage2 = gdk_pixbuf_new_from_xpm_data(skull_xpm); +} + +} diff --git a/src/gx_child_process.cpp b/src/gx_child_process.cpp new file mode 100644 index 0000000..694e955 --- /dev/null +++ b/src/gx_child_process.cpp @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix module handling child processes spawned from it + * + * -------------------------------------------------------------------------- + */ + +#include +#include +#include "guitarix.h" + +using namespace gx_system; +using namespace gx_engine; + +namespace gx_child_process +{ + +/**************************************************************** + ** GxChild, GxChildProcs + */ + +bool GxChild::kill() +{ + return ::kill(m_pid, m_killsignal) != -1; +} + +GxChildProcs::~GxChildProcs() +{ + for (list::iterator i = children.begin(); i != children.end(); i++) { + (*i)->kill(); + delete *i; + } +} + +bool GxChildProcs::killall() +{ + int ret = true; + for (list::iterator i = children.begin(); i != children.end(); i++) { + if (! (*i)->kill()) { + ret = false; + } + } + return ret; +} + +bool GxChildProcs::kill(string name) +{ + GxChild *p = find(name); + if (p) { + return p->kill(); + } + return true; +} + +GxChild *GxChildProcs::find(string name) +{ + for (list::iterator i = children.begin(); i != children.end(); i++) { + if ((*i)->hasName(name)) { + return *i; + } + } + return 0; +} + +#define EXIT_PGM_NOT_FOUND 127 + +gboolean gx_sigchld_handler(gpointer) +{ + int status; + pid_t pid = waitpid(-1, &status, WNOHANG); + if (pid == 0 || pid == -1) { + return false; + } + bool pgm_found = true; + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_PGM_NOT_FOUND) { + pgm_found = false; + } + } else if (!WIFSIGNALED(status)) { + // process didn't terminate + return false; + } + // child pid has terminated + list& cl = childprocs.children; + GxChild *p = 0; + for (list::iterator i = cl.begin(); i != cl.end(); i++) { + if ((*i)->hasPid(pid)) { + p = *i; + cl.erase(i); + break; + } + } + if (p) { + p->terminated(pgm_found); + return false; + } + return false; +} + +GxChild *GxChildProcs::launch(string name, const char *const args[], int killsignal) +{ + // fork produces about 3ms latency on linux 2.6.31-9-rt + // vfork works + // FIXME check if its a version-specific bug + int pid = vfork(); + switch (pid) { + case -1: // error, in parent + return 0; + + case 0: // in child + execvp(args[0], (char**)args); + _exit(EXIT_PGM_NOT_FOUND); + /*NOTREACHED*/ + return 0; + + default: // in parent + GxChild *p = new GxChild(name, killsignal, pid); + children.push_back(p); + return p; + } +} + +GxChild *GxChildProcs::launch(string name, list args, int killsignal) +{ + const char **p = new const char*[args.size()+1]; + unsigned int i = 0; + for (list::iterator j = args.begin(); j != args.end(); j++) { + //cout << *j << endl; + p[i++] = j->c_str(); + } + assert(i == args.size()); + p[i] = 0; + GxChild *c = launch(name, p, killsignal); + delete p; + return c; +} + +GxChildProcs childprocs; + +/**************************************************************** + ** Menu Callbacks + */ + +//----------------------- jack_capture settings --------------------------- +JackCaptureGui::JackCaptureGui(GxChild *p, GtkCheckMenuItem *i): + item(i) +{ + gtk_widget_ref(GTK_WIDGET(item)); + p->terminated.connect(sigc::mem_fun(*this, &JackCaptureGui::terminated)); +} + +void JackCaptureGui::terminated(bool pgm_found) +{ + gtk_check_menu_item_set_active(item, false); + if (pgm_found) { + gx_print_info("Jack capture gui", "jack_capture_gui2 terminated"); + } else { + gx_gui::gx_message_popup( + " " + " ERORR [Jack Capture GUI]\n\n " + " jack_capture_gui2 is not installed! " + ); + } + gtk_widget_unref(GTK_WIDGET(item)); + delete this; +} + +void JackCaptureGui::start_stop(GtkCheckMenuItem *menuitem, gpointer) +{ + const char *app_name = "jack_capture_gui2"; + if (gtk_check_menu_item_get_active(menuitem)) { + if (childprocs.find(app_name)) { + return; + } + string sess = string(getenv("HOME")) + "/guitarix_session"; + const char * const args[] = { + app_name, "-o", "yes", "-f", sess.c_str(), "-n", "guitarix", "-p", "/.guitarix/ja_ca_ssetrc", 0 }; + GxChild *jack_cap_gui = childprocs.launch(app_name, args, SIGTERM); + if (jack_cap_gui) { + new JackCaptureGui(jack_cap_gui, menuitem); + } else { + gx_gui::gx_message_popup( + " " + "ERROR [Jack capture gui]\n\n " + "jack_capture_gui2 could not be launched!" + ); + gx_print_error("Jack capture gui", + string("jack_capture_gui2 could not be launched (fork failed)!")); + gtk_check_menu_item_set_active(menuitem, FALSE); + } + } else { + childprocs.kill(app_name); + } +} + +//---------------------------- Jack Capture ------------------------------- + +JackCapture::JackCapture(GxChild *p, GtkToggleButton *b): + button(b) +{ + gtk_widget_ref(GTK_WIDGET(button)); + p->terminated.connect(sigc::mem_fun(*this, &JackCapture::terminated)); +} + +void JackCapture::terminated(bool pgm_found) +{ + gtk_toggle_button_set_active(button, false); + if (pgm_found) { + gx_print_info("Jack Capture", "jack_capture terminated"); + } else { + gx_print_warning("Record", + " WARNING [jack_capture]\n " + " You need jack_capture >= 0.9.30 by Kjetil S. Matheussen \n " + " Please look here\n " + " http://old.notam02.no/arkiv/src/?M=D\n"); + } + gtk_widget_unref(GTK_WIDGET(button)); + delete this; +} + +//---- wav file construction for jack_capture +string JackCapture::make_fname(string buf, size_t j, size_t i, int n) +{ + ostringstream str; + str << buf.substr(0,j+1) << n << buf.substr(i); + return str.str(); +} + +list JackCapture::capture_command(int& seq) +{ + // open jack_capture setup file + string gfilename = gx_user_dir + jcapsetup_file; + ifstream f(gfilename.c_str()); + + list l; + string buf; + while (true) { + f >> buf; + if (!f.good()) { + break; + } + l.push_back(buf); + } + f.close(); + if (l.empty()) { + (void)gx_gui::gx_message_popup( + " ERROR [Record]\n\n " + " Please run jack capture settings first [alt+j]" + ); + return l; + } + buf = *l.rbegin(); // last argument should be filename + l.pop_back(); // pop last argument (re-add later after processing) + l.push_back("--hide-buffer-usage"); // add additional option + size_t i = buf.find_last_of("."); + if (i == string::npos) { + gx_print_error("Record", "could not parse cmd file (internal error)"); + l.clear(); + return l; + } + size_t j = buf.find_last_not_of("0123456789", i-1); + int n; + string fname; + for (n = 1; n < 1000; n++) { + fname = make_fname(buf, j, i, n); + if (access(fname.c_str(),F_OK) != 0) { + break; + } + } + if (n == 1000) { + gx_print_error("Record", "more than 999 capture files in directory?!"); + l.clear(); + return l; + } + seq = n; + l.push_back(fname); // add filename + return l; +} + +void JackCapture::stop() +{ + childprocs.kill("jack_capture"); +} + +void JackCapture::start_stop(GtkWidget *widget, gpointer data) +{ + static int last_seqno; + // here, const applies to pointer, not pointed data ;) + GtkToggleButton* const cap_button = (GtkToggleButton*)widget; + const char *app_name = "jack_capture"; + if (gtk_toggle_button_get_active(cap_button) == FALSE) { + // ---- stop recording + GxChild *jack_capture = childprocs.find(app_name); + if (jack_capture) { + if (jack_capture->kill()) { + gx_print_info("Record", + string(" Terminated jack_capture, session file #") + + gx_i2a(last_seqno)); + } else { + gx_print_error("Record", + string(" Sorry, could not stop (Ctrl-C) jack_capture")); + } + } + return; + } + + if (gx_jack::client == NULL) { + gtk_toggle_button_set_active(cap_button, FALSE); + (void)gx_gui::gx_message_popup( + " WARNING [Record]\n\n " + " Reconnect to Jack server first (Shift+C)" + ); + return; + } + + gx_print_info("Record", " Trying to run jack_capture"); + list capturas = capture_command(last_seqno); + if (capturas.empty()) { + gtk_toggle_button_set_active(cap_button, FALSE); + return; // messages to user already done + } + GxChild *jack_capture = childprocs.launch(app_name, capturas, SIGINT); + if (! jack_capture) { + gtk_toggle_button_set_active(cap_button, FALSE); + gx_print_error("Record", " WARNING [jack_capture] Sorry, could not start jack_capture"); + return; + } + new JackCapture(jack_capture, cap_button); + gx_print_info("Record", + string("Started jack_capture, session file #") + gx_i2a(last_seqno)); +} + +//-------------------- meterbridge -------------------------- + +Meterbridge::Meterbridge(GxChild *p, GtkCheckMenuItem *i): + item(i) +{ + gtk_widget_ref(GTK_WIDGET(item)); + p->terminated.connect(sigc::mem_fun(*this, &Meterbridge::terminated)); +} + +void Meterbridge::terminated(bool pgm_found) +{ + gtk_check_menu_item_set_active(item, false); + if (pgm_found) { + gx_print_info("Meterbridge", "meterbridge terminated"); + } else { + gx_gui::gx_message_popup( + " " + " WARNING [meterbridge]\n\n " + " meterbridge is not installed! " + ); + } + gtk_widget_unref(GTK_WIDGET(item)); + delete this; +} + +void Meterbridge::stop() +{ + childprocs.kill("meterbridge"); +} + +void Meterbridge::start_stop(GtkCheckMenuItem *menuitem, gpointer) +{ + // no need to do all this if jack is not running + if (!gx_jack::client) { + (void)gx_gui::gx_message_popup( + " WARNING [Meterbridge]\n\n " + " Reconnect to Jack server first (Shift+C)" + ); + return; + } + + const char *app_name = "meterbridge"; + if (gtk_check_menu_item_get_active(menuitem)) { + if (childprocs.find(app_name)) { + return; + } + string s = gx_jack::client_instance + "_" + app_name; + const char * const args[] = { + app_name, "-n", s.c_str(), "-t", "sco", "guitarix:in_0", "guitarix:out_0", 0 }; + GxChild *meterbridge = childprocs.launch(app_name, args, SIGTERM); + if (meterbridge) { + new Meterbridge(meterbridge, menuitem); + } else { + gx_gui::gx_message_popup( + " " + "WARNING [meterbridge]\n\n " + "meterbridge could not be launched!" + ); + gx_print_error("Meterbridge", + string("meterbridge could not be launched (fork failed)!")); + gtk_check_menu_item_set_active(menuitem, FALSE); + } + } else { // -- deactivate meterbridge + childprocs.kill(app_name); + } +} + +} /* end of gx_child_process namespace */ diff --git a/src/gx_convolver.cpp b/src/gx_convolver.cpp new file mode 100644 index 0000000..5c317e6 --- /dev/null +++ b/src/gx_convolver.cpp @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix convolver, part of gx_engine_audio ------- */ + +#include +#include +#include "guitarix.h" + +/**************************************************************** + ** some pieces in this file are copied from jconvolver + */ + +/**************************************************************** + ** AudioFile + */ + +namespace gx_engine +{ + +Audiofile::Audiofile (void) +{ + reset(); +} + + +Audiofile::~Audiofile (void) +{ + close(); +} + + +void Audiofile::reset (void) +{ + _sndfile = 0; + _type = TYPE_OTHER; + _form = FORM_OTHER; + _rate = 0; + _chan = 0; + _size = 0; +} + + +int Audiofile::open_read (string name) +{ + SF_INFO I; + + reset (); + + if ((_sndfile = sf_open (name.c_str(), SFM_READ, &I)) == 0) return ERR_OPEN; + + switch (I.format & SF_FORMAT_TYPEMASK) + { + case SF_FORMAT_CAF: + _type = TYPE_CAF; + break; + case SF_FORMAT_WAV: + _type = TYPE_WAV; + break; + case SF_FORMAT_WAVEX: +#ifdef SFC_WAVEX_GET_AMBISONIC + if (sf_command (_sndfile, SFC_WAVEX_GET_AMBISONIC, 0, 0) == SF_AMBISONIC_B_FORMAT) + _type = TYPE_AMB; + else +#endif + _type = TYPE_WAV; + } + + switch (I.format & SF_FORMAT_SUBMASK) + { + case SF_FORMAT_PCM_16: + _form = FORM_16BIT; + break; + case SF_FORMAT_PCM_24: + _form = FORM_24BIT; + break; + case SF_FORMAT_PCM_32: + _form = FORM_32BIT; + break; + case SF_FORMAT_FLOAT: + _form = FORM_FLOAT; + break; + } + + _rate = I.samplerate; + _chan = I.channels; + _size = I.frames; + + return 0; +} + + +int Audiofile::close (void) +{ + if (_sndfile) sf_close (_sndfile); + reset (); + return 0; +} + + +int Audiofile::seek (uint32_t posit) +{ + if (!_sndfile) return ERR_MODE; + if (sf_seek (_sndfile, posit, SEEK_SET) != posit) return ERR_SEEK; + return 0; +} + + +int Audiofile::read (float *data, uint32_t frames) +{ + return sf_readf_float (_sndfile, data, frames); +} + + +/**************************************************************** + ** GxConvolverBase + */ + +void GxConvolverBase::adjust_values( + unsigned int audio_size, unsigned int& count, unsigned int& offset, + unsigned int& delay, unsigned int& ldelay, unsigned int& length, + unsigned int& size, unsigned int& bufsize) +{ + if (bufsize < count) { + bufsize = count; + } + if (offset > audio_size) { + offset = audio_size; + } + if (!size) { + if (offset + length > audio_size) { + gx_system::gx_print_warning("convolver", "data truncated"); + length = audio_size - offset; + } + if (!length) { + length = audio_size - offset; + } + size = max(delay, ldelay) + offset + length; + } else { + if (delay > size) { + delay = size; + } + if (ldelay > size) { + ldelay = size; + } + if (offset > size - max(delay, ldelay)) { + offset = size - max(delay, ldelay); + } + if (length > size - max(delay, ldelay) - offset) { + length = size - max(delay, ldelay) - offset; + gx_system::gx_print_warning("convolver", "data truncated"); + } + if (!length) { + length = size - max(delay, ldelay) - offset; + } + } +} + +bool GxConvolverBase::start() +{ + int abspri, policy; + struct sched_param spar; + pthread_getschedparam(jack_client_thread_id(gx_jack::client), &policy, &spar); + abspri = spar.sched_priority; + int rc = start_process(abspri, policy); + if (rc != 0) { + gx_system::gx_print_error("convolver", "can't start convolver"); + return false; + } + ready = true; + return true; +} + +void GxConvolverBase::checkstate() +{ + if (state() == Convproc::ST_WAIT) { + check(); + } else if (state() == ST_STOP) { + ready = false; + } +} + + +/**************************************************************** + ** GxConvolver + */ + +bool GxConvolver::read_sndfile ( + Audiofile& audio, int nchan, int samplerate, const float *gain, + unsigned int *delay, unsigned int offset, unsigned int length) +{ + unsigned int nfram; + float *buff, *p; + float *rbuff = 0; + float *bufp; + // keep BSIZE big enough so that resamp.flush() doesn't cause overflow + // (> 100 should be enough, and should be kept bigger anyhow) + const unsigned int BSIZE = 0x4000; + gx_resample::StreamingResampler resamp; + + if (offset && audio.seek(offset)) { + gx_system::gx_print_error("convolver", "Can't seek to offset"); + audio.close (); + return false; + } + try { + buff = new float[BSIZE * nchan]; + } catch (...) { + audio.close(); + gx_system::gx_print_error("convolver", "out of memory"); + return false; + } + if (samplerate != audio.rate()) { + ostringstream buf; + buf << "resampling from " << audio.rate() << " to " << samplerate; + gx_system::gx_print_info("convolver", buf.str()); + if (!resamp.setup(audio.rate(), samplerate, nchan)) { + assert(false); + } + try { + rbuff = new float[resamp.get_max_out_size(BSIZE)*nchan]; + } catch (...) { + audio.close(); + gx_system::gx_print_error("convolver", "out of memory"); + return false; + } + bufp = rbuff; + } else { + bufp = buff; + } + bool done = false; + while (!done) { + unsigned int cnt; + nfram = (length > BSIZE) ? BSIZE : length; + if (length) { + nfram = audio.read(buff, nfram); + if (nfram < 0) { + gx_system::gx_print_error("convolver", "Error reading file"); + audio.close (); + delete[] buff; + delete[] rbuff; + return false; + } + cnt = nfram; + if (rbuff) { + cnt = resamp.process(nfram, buff, rbuff); + } + } else { + if (rbuff) { + cnt = resamp.flush(rbuff); + done = true; + } else { + break; + } + } + if (cnt) { + for (int ichan = 0; ichan < nchan; ichan++) { + int rc; + if (ichan >= audio.chan()) { + rc = impdata_copy(0, 0, ichan, ichan); + } else { + p = bufp + ichan; + if (gain[ichan] != 1.0) { + for (unsigned int ifram = 0; ifram < cnt; ifram++) { + p[ifram * nchan] *= gain[ichan]; + } + } + rc = impdata_create(ichan, ichan, audio.chan(), p, + delay[ichan], delay[ichan] + cnt); + } + if (rc) { + audio.close (); + delete[] buff; + delete[] rbuff; + gx_system::gx_print_error("convolver", "out of memory"); + return false; + } + delay[ichan] += cnt; + } + length -= nfram; + } + } + + audio.close (); + delete[] buff; + delete[] rbuff; + return true; +} + +bool GxConvolver::configure( + unsigned int count, int samplerate, string fname, float gain, float lgain, + unsigned int delay, unsigned int ldelay, unsigned int offset, + unsigned int length, unsigned int size, unsigned int bufsize) +{ + Audiofile audio; + cleanup(); + if (audio.open_read (fname)) { + gx_system::gx_print_error("convolver", "Unable to open '" + fname + "'"); + return false; + } + if (audio.chan() > 2) { + ostringstream buf; + buf << "only taking 2 of " << audio.chan() << " channels in impulse response"; + gx_system::gx_print_error("convolver", buf.str()); + return false; + } + adjust_values(audio.size(), count, offset, delay, ldelay, length, size, bufsize); + /* FIXME remove + cout << "state=" << state() << ", ready=" << ready << endl; + cout << "fname=" << fname << ", size=" << audio.size() + << ", channels=" << audio.chan() << endl; + cout << "convolver: size=" << size << ", count=" << count << ", bufsize=" + << bufsize << ", offset=" << offset << ", delay=" << delay + << ", ldelay=" << ldelay << ", length=" << length << ", gain" << gain + << ", lgain" << lgain << endl; + */ + if (Convproc::configure(2, 2, size, count, bufsize, Convproc::MAXPART)) { + gx_system::gx_print_error("convolver", "error in Convproc::configure"); + return false; + } + float gain_a[2] = {gain, lgain}; + unsigned int delay_a[2] = {delay, ldelay}; + return read_sndfile(audio, 2, samplerate, gain_a, delay_a, offset, length); +} + +bool GxConvolver::compute(int count, float* input1, float *input2, float *output1, float *output2) +{ + if (state() == Convproc::ST_WAIT) { + check(); + } + if (state() != Convproc::ST_PROC) { + if (input1 != output1) { + memcpy(output1, input1, count * sizeof(float)); + } + if (input2 != output2) { + memcpy(output2, input2, count * sizeof(float)); + } + if (state() == ST_STOP) { + ready = false; + return flags() == 0; + } + return true; + } + memcpy(inpdata(0), input1, count * sizeof(float)); + memcpy(inpdata(1), input2, count * sizeof(float)); + + process(); + + memcpy (output1, outdata(0), count * sizeof(float)); + memcpy (output2, outdata(1), count * sizeof(float)); + return true; +} + +GxConvolver conv; + + +/**************************************************************** + ** GxSimpleConvolver + */ + +bool GxSimpleConvolver::configure(int count, float *impresp, unsigned int samplerate) +{ + bool dyn = false; + if (samplerate != gx_jack::jack_sr) { + gx_resample::BufferResampler r; + impresp = r.process(samplerate, count, impresp, gx_jack::jack_sr, count); + if (!impresp) { + gx_system::gx_print_error("convolver", "failed to resample"); + return false; + } + dyn = true; + } + cleanup(); + bool ret; + if (Convproc::configure(1, 1, count, gx_jack::jack_bs, gx_jack::jack_bs, Convproc::MAXPART)) { + gx_system::gx_print_error("convolver", "error in Convproc::configure"); + ret = false; + } else if (impdata_create(0, 0, 1, impresp, 0, count)) { + gx_system::gx_print_error("convolver", "out of memory"); + ret = false; + } else { + ret = true; + } + if (dyn) { + delete impresp; + } + return ret; +} + +bool GxSimpleConvolver::compute(int count, float* input, float *output) +{ + if (state() == Convproc::ST_WAIT) { + check(); + } + if (state() != Convproc::ST_PROC) { + if (input != output) { + memcpy(output, input, count * sizeof(float)); + } + if (state() == ST_STOP) { + ready = false; + return flags() == 0; + } + return true; + } + memcpy(inpdata(0), input, count * sizeof(float)); + + process(); + + memcpy (output, outdata(0), count * sizeof(float)); + return true; +} + +GxSimpleConvolver cab_conv; + +} diff --git a/src/gx_engine.cpp b/src/gx_engine.cpp new file mode 100644 index 0000000..55a297c --- /dev/null +++ b/src/gx_engine.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix engine definitions + * + * + * -------------------------------------------------------------------------- + */ + +#include +#include "guitarix.h" + +using namespace gx_system; +using namespace gx_resample; + +namespace gx_engine +{ + +void gx_engine_init( const string *optvar ) +{ + //----- lock the buffer for the oscilloscope + const int frag = (const int)gx_jack::jack_bs; + + get_frame = new float[frag]; + get_frame1 = new float[frag]; + checkfreq = new float[frag]; + oversample = new float[frag*MAX_UPSAMPLE]; + result = new float[frag+46]; + + (void)memset(get_frame, 0, frag*sizeof(float)); + (void)memset(get_frame1, 0, frag*sizeof(float)); + (void)memset(checkfreq, 0, frag*sizeof(float)); + (void)memset(oversample, 0, frag*MAX_UPSAMPLE*sizeof(float)); + (void)memset(result, 0, (frag+46)*sizeof(float)); + + midi.init(gx_jack::jack_sr); + faust_init(gx_jack::jack_sr); + //resampTube.setup(gx_jack::jack_sr, 2); + //resampDist.setup(gx_jack::jack_sr, 2); + if (!optvar[LOAD_FILE].empty()) { + gx_preset::gx_recall_settings_file(&optvar[LOAD_FILE]); + } else { + gx_preset::gx_recall_settings_file(); + } + + initialized = true; +} + +void gx_engine_reset() +{ + if (checkfreq) delete[] checkfreq; + if (get_frame) delete[] get_frame; + if (get_frame1) delete[] get_frame1; + if (oversample) delete[] oversample; + if (result) delete[] result; + + initialized = false; +} + +} /* end of gx_engine namespace */ diff --git a/src/gx_engine_audio.cpp b/src/gx_engine_audio.cpp new file mode 100644 index 0000000..7551ab3 --- /dev/null +++ b/src/gx_engine_audio.cpp @@ -0,0 +1,640 @@ +/* + * Copyright (C) 2009-2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the Guitarix Audio Engine + * + * + * -------------------------------------------------------------------------- + */ + +#include +#include +#include +#include "guitarix.h" + +using namespace gx_resample; + +namespace gx_engine { + +#include "gx_engine_tubetable.cc" + +/**************************************************************** + ** registering of audio variables + */ + +inline void registerNonMidiParam(const char*a, float*c, bool d, float std=0, float lower=0, float upper=1) +{ + gx_gui::parameter_map.insert(new gx_gui::FloatParameter(a,"",gx_gui::Parameter::None,d,*c,std,lower,upper,0,false)); +} + +// should be int +inline void registerEnumParam(const char*a,const char*b,const char** vl,float*c,int std=0,bool exp=false) +{ + gx_gui::parameter_map.insert(new gx_gui::FloatEnumParameter(a,b,vl,true,*c,std,true,exp)); +} + +inline void registerEnumParam(const char*a,const char*b,const char** vl, int*c,int std=0,bool exp=false) +{ + gx_gui::parameter_map.insert(new gx_gui::EnumParameter(a,b,vl,true,*c,std,true,exp)); +} + +/**************************************************************** + ** definitions for code generated with faust / dsp2cc + */ + +#include "gx_faust_includes.cc" + +/**************************************************************** + ** register audio variables to paramtable + */ + +AudioVariables::AudioVariables() +{ + static const char *amp_threshold[] = {"off","clip","foldback",0}; + registerEnumParam("amp.threshold", "threshold", amp_threshold, &ffuse, 0); + gx_gui::registerParam("MultiBandFilter.on_off", "on/off", &fmultifilter, 0); + static const char *crybaby_autowah[] = {"manual","auto",0}; + registerEnumParam("crybaby.autowah", "select", crybaby_autowah, &fautowah, 0); + gx_gui::registerParam("overdrive.on_off", "on/off", &foverdrive4, 0); + gx_gui::registerParam("distortion.on_off", "on/off", &fcheckbox4, 0); + static const char *distortiont_onetwo[] = {"multi","single",0}; + registerEnumParam("distortiont.onetwo", "select", distortiont_onetwo, &witchdistortion, 0); + static const char *eqt_onetwo[] = {"fixed","scale",0}; + registerEnumParam("eqt.onetwo", "select", eqt_onetwo, &witcheq, 0); + gx_gui::registerParam("freeverb.on_off", "on/off", &fcheckbox6, 0); + gx_gui::registerParam("IR.on_off", "on/off", &fcheckbox8, 0); + gx_gui::registerParam("crybaby.on_off", "on/off", &fcheckbox5, 0); + gx_gui::registerParam("echo.on_off", "on/off", &fcheckbox7, 0); + gx_gui::registerParam("delay.on_off", "on/off", &fdelay, 0); + gx_gui::registerParam("chorus.on_off", "on/off", &fchorus, 0); + gx_gui::registerParam("compressor.on_off", "on/off", &fcheckboxcom1, 0); + gx_gui::registerParam("tube2.on_off", "on/off", &ftube3, 0); + gx_gui::registerParam("tube3.on_off", "on/off", &ftube3e, 0); + gx_gui::registerParam("tube.vibrato.on_off", "on/off", &fresoon, 0); + gx_gui::registerParam("tube.on_off", "on/off", &ftube, 0); + gx_gui::registerParam("drive.on_off", "on/off", &fprdr, 0); + gx_gui::registerParam("preamp.on_off", "on/off", &fcheckbox1, 0); + static const char *convolve_select[] = {"amp 1","amp 2", "amp 3","amp 4","amp 5", "amp 6", "amp 7",0}; + registerEnumParam("convolve.select", "select", convolve_select, &convolvefilter, 0); + gx_gui::registerParam("convolve.on_off", "on/off", &fconvolve, 0); + gx_gui::registerParam("amp.bass_boost.on_off", "on/off", &fboost, 0); + gx_gui::registerParam("amp.oversample.on_off", "on/off", &fupsample, 0); + gx_gui::registerParam("anti_aliase.on_off", "on/off", &antialis0, 0); + gx_gui::registerParam("noise_gate.on_off", "on/off", &fnoise_g, 0); + gx_gui::registerParam("noise_gate.threshold", "Threshold", &fnglevel, 0.017f, 0.01f, 0.21f, 0.001f); + gx_gui::registerParam("shaper.on_off", "on/off", &fng, 0); + gx_gui::registerParam("eq.on_off", "on/off", &feq, 0); + gx_gui::registerParam("moog.on_off", "on/off", &fmoog, 0); + gx_gui::registerParam("biquad.on_off", "on/off", &fbiquad, 0); + gx_gui::registerParam("flanger.on_off", "on/off", &fflanger, 0); + gx_gui::registerParam("SampleLooper.on_off", "on/off", &fsloop, 0); + gx_gui::registerParam("jconv.on_off", "Run", &gx_jconv::GxJConvSettings::checkbutton7); + static const char *amp_select[] = {"1x","2x", "3x","4x","5x", "6x", "7x", "8x",0}; + registerEnumParam("amp.select", "select", amp_select, &upsample_mode, 3); + static const char *amp_model[] = {"amp 1","amp 2",0}; + registerEnumParam("amp.model", "select", amp_model, &witchamp, 0); + gx_gui::registerParam("cab.on_off", "Cab-ImpResp", &fcab,0); + + // only save and restore, no midi control + + // positions of effects + registerNonMidiParam("crybaby.position", &posit0, true, 5, 0, 7); + registerNonMidiParam("overdrive.position", &posit1, true, 2, 0, 7); + registerNonMidiParam("distortion.position", &posit2, true, 1, 0, 7); + registerNonMidiParam("freeverb.position", &posit3, true, 3, 0, 7); + registerNonMidiParam("IR.position", &posit4, true, 4, 0, 7); + registerNonMidiParam("compressor.position", &posit5, true, 0, 0, 7); + registerNonMidiParam("echo.position", &posit6, true, 6, 0, 7); + registerNonMidiParam("delay.position", &posit7, true, 7, 0, 7); + registerNonMidiParam("chorus.position", &posit8, true, 8, 8, 8); + registerNonMidiParam("flanger.position", &posit9, true, 9, 9, 9); + + // togglebuttons for dialogboxes and expander for effect details + registerNonMidiParam("compressor.dialog", &fdialogbox8, false); + registerNonMidiParam("distortion.dialog", &fdialogbox1, false); + registerNonMidiParam("freeverb.dialog", &fdialogbox2, false); + registerNonMidiParam("IR.dialog", &fdialogbox3, false); + registerNonMidiParam("crybaby.dialog", &fdialogbox4, false); + registerNonMidiParam("chorus.dialog", &fchorusbox, false); + registerNonMidiParam("midi_out.dialog", &fdialogbox6, false); + registerNonMidiParam("jconv.dialog", &fdialogboxj, false); + registerNonMidiParam("jconv.expander", &fexpand2, false); + registerNonMidiParam("jconv.filedialog", &filebutton, false); + registerNonMidiParam("eq.dialog", &fdialogbox_eq, false); + registerNonMidiParam("eqs.dialog", &fdialogbox_eqs, false); + registerNonMidiParam("MultiBandFilter.dialog", &fdialogbox_mbf, false); + registerNonMidiParam("moog.dialog", &fdialogbox_moo, false); + registerNonMidiParam("biquad.dialog", &fbiquadbox, false); + registerNonMidiParam("flanger.dialog", &fflangerbox, false); + + // user interface options + registerNonMidiParam("ui.latency_nowarn", &fwarn, false, 0); + registerNonMidiParam("ui.skin", &fskin, false, 0, 0, 100); + registerNonMidiParam("ui.main_expander", &fexpand, false); + registerNonMidiParam("ui.amp_expander", &fampexpand, false); + + // shouldn't be saved, only output? + registerNonMidiParam("system.fConsta1t", &fConsta1t, false); + registerNonMidiParam("system.midistat", &midistat, false); + registerNonMidiParam("system.waveview", &viv, false); +} + +AudioVariables audio; + +/**************************************************************** + ** some dsp funktions + */ + +static float filters[][45] = { + + // filter 0 + {0.0222473, 0.0253601, 0.0159607, 0.0184326, 0.0240784, + 0.02771, 0.0483398, 0.0802917, 0.12915, 0.196259, 0.259521, + 0.334656, 0.398376, 0.421448, 0.401306, 0.340759, 0.216827, + 0.058197, -0.117432, -0.287354, -0.438507, -0.540161, + 0.0583801, 0.0596924, 0.0499573, 0.0406799, 0.0445862, + 0.0334473, 0.0296021, 0.022644, 0.0142212, 0.0027771, + -0.00805664, -0.0206909, -0.0270386, -0.0247498, + -0.0259399, -0.0132751, 0.216827, 0.058197, -0.117432, + -0.287354, -0.438507, -0.540161, -0.438507 + }, + + // filter 1 + {0.19,0.15,0.12,0.05,-0.08,-0.15,-0.18,-0.12,-0.05,0.07, + 0.12,0.16,0.14,0.11,0.05,0.01,0.04,0.12,0.14,0.08,0.02, + -0.01,0.8,0.19,0.15,0.12,0.05,-0.08,-0.15,-0.18,-0.12, + -0.05,0.07,0.12,0.16,0.14,0.11,0.05,0.01,0.04,0.12,0.14, + 0.08,0.02,-0.01 + }, + + // filter 2 + {0.19265,0.19265,0.19265,0.19265,0.19265,0.19265,0.19265, + 0.19265,0.19265,0.19265,0.19265,0.19265,0.19265,0.19265, + 0.19265,0.19265,0.19265,0.19265,0.19265,0.19265,0.19265, + 0.19265,0.19265,0.19265,0.19265,0.19265,0.19265,0.19265, + 0.19265,0.19265,0.19265,0.19265,0.19265,0.19265,0.19265, + 0.19265,0.19265,0.19265,0.19265,0.19265,0.19265,0.19265, + 0.19265,0.19265,0.19265 + }, + + // filter 3 + {-0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851, + -0.1111851,-0.1811851,-0.1811851,-0.1811851,-0.1811851 + }, + + // filter 4 + {-0.0400391, 0.0591736, 0.0404663, 0.065155, 0.065094, + 0.0524597, 0.0325012, -0.0254211, -0.0797119, -0.118561, + -0.192902, -0.1763, -0.169861, -0.0974426, 0.0567932, + 0.207458, 0.468079, 0.637085, 0.786072, 0.911835, 0.868347, + 0.873199, 0.720001, 0.598633, 0.416168, 0.24173, 0.0201416, + -0.177277, -0.397614, -0.538208, -0.64505, -0.582642, + -0.43161, -0.0495605, 0.361603, 0.724304, 0.981934, 0.953583, + 0.770233, 0.515625, 0.21106, -0.0998535, -0.162781, + -0.171173, 0.042572 + }, + + // filter 5 + {0.000610352, 0.00604248, 0.0153809, 0.0246277, 0.0340576, + 0.0418701, 0.0494385, 0.059082, 0.069458, 0.0871277, + 0.0636292, -0.0269165, -0.208862, -0.453522, -0.7146, + -0.915344, -0.999939, -0.938538, -0.752472, -0.494629, + -0.240662, -0.0461426, 0.0594788, 0.0810852, 0.0621643, + 0.0324707, 0.00180054, -0.0244751, -0.0487061, + -0.0654602, -0.0780334, -0.0823669, -0.0776978, -0.0677185, + -0.0529175, -0.0342102, -0.0135803, 0.00839233, 0.0301208, + 0.053833, 0.0252563, 0.0058252, 0.002138, 0.0012851, 0.0009252 + }, + + // filter 6 + {-0.0573425, 0.0429382, 0.1698, 0.325623, 0.496429, + 0.673615, 0.831726, 0.948944, 0.999939, 0.962616, + 0.822021, 0.57666, 0.25769, -0.091156, -0.393341, + -0.568726, -0.545746, -0.315643, 0.052948, 0.422028, + 0.634552, 0.612579, 0.383606, 0.0856323, -0.142151, + -0.233185, -0.185608, -0.0593262, 0.0916748, 0.228333, + 0.302521, 0.295105, 0.226959, 0.130402, 0.0578308, + 0.0231018, 0.0189514, 0.0299988, 0.0453186, 0.0602722, + 0.079834, 0.092804, 0.0980225, 0.0977783, 0.0834351 + }, +}; + +inline void convolver_filter(float* input, float* output, int sf, unsigned int iconvolvefilter) +{ + if (iconvolvefilter >= sizeof(filters) / sizeof(filters[0])) { + iconvolvefilter = 0; + } + for (int i=0; i < 45; i++) { + result[i] = result[sf+i]; + } + for (int i=45; i < sf+46; i++) { + result[i] = 0; + } + +// Do convolution: + for (int i = 0; i < sf; i++) { + for (int j = 0; j < 45; j++) { + result[i+j] += input[i] * filters[iconvolvefilter][j]; + } + } + for (int i = 0; i < sf; i++) { + *output++ = result[i]; + } +} + +inline void moving_filter(float* input, float* output, int sf) +{ + assert(input != output); + *output++ = (input[0]+input[1])*0.5; + for (int i=1; i audio.fnglevel * 0.01) { + return 1; // -75db 0.001 = 65db + } else if (ngate > 0.01) { + return ngate * 0.996; + } else { + return ngate; + } +} + +inline void over_sample(int sf, float *input, float *output) +{ + static float old = 0; + for (int i = 0; i < sf; i++) { + float x = *input++; + *output++ = (old + x) * 0.5; + *output++ = x; + old = x; + } +} + +inline void down_sample(int sf, float *input, float *output) +{ + for (int i=0; i 0) { + if (gx_gui::shownote == 0) { + gx_gui::shownote = -1; + } else { + pitch_tracker.add(count, input); + //moving_filter(input, checkfreq, count); + (void)memcpy(checkfreq, input, sizeof(float)*count); + } + } + memcpy(output0, input, count*sizeof(float)); + IF_HS(HighShelf::compute(count, input, output0)); + + if (audio.feq) { + if(audio.witcheq)selecteq::compute(count, output0, output0); + else eq::compute(count, output0, output0); + } + if (audio.fnoise_g) { + feed::ngate = noise_gate(count,output0, feed::ngate); + } else { + feed::ngate = 1; + } + if (audio.fng) { + noise_shaper::compute(count, output0, output0); + } + if (audio.fcheckbox1 && !audio.famp2) { + preamp::compute(count, output0, output0); + } + if (audio.fbiquad) { + biquad::compute(count, output0, output0); + } + EXPERIMENTAL_PROCESSING; + + // *** Start (maybe) oversampled processing *** + static int fupsample_old = 0; // startup always initialises with SR + static int t_upsample_old = 0; + static int t_upsample = 0; + int ovs_count, ovs_sr; + float *ovs_buffer; + if (audio.fupsample) { + // *oversample + t_upsample = min(8,audio.upsample_mode+1); + if (t_upsample != t_upsample_old) { + t_upsample_old = t_upsample; + fupsample_old = audio.fupsample; + //FIXME non-rt + resampTube.setup(gx_jack::jack_sr, t_upsample); + + amp2::init(t_upsample * gx_jack::jack_sr); + osc_tube::init(t_upsample * gx_jack::jack_sr); + + resampDist.setup(gx_jack::jack_sr, t_upsample); + distortion1::init(t_upsample * gx_jack::jack_sr); + distortion::init(t_upsample * gx_jack::jack_sr); + } + resampTube.up(count, output0, oversample); + ovs_sr = t_upsample * gx_jack::jack_sr; + ovs_count = t_upsample * count; + ovs_buffer = oversample; + } else { + ovs_sr = gx_jack::jack_sr; + ovs_count = count; + ovs_buffer = output0; + } + if (audio.fupsample != fupsample_old) { + fupsample_old = audio.fupsample; + + amp2::init(ovs_sr); + osc_tube::init(ovs_sr); + + distortion1::init(ovs_sr); + distortion::init(ovs_sr); + } + if (audio.antialis0) { + AntiAlias::compute(ovs_count, ovs_buffer, ovs_buffer); + } + if(audio.famp2) { + amp2::compute(ovs_count, ovs_buffer, ovs_buffer); + } else { + if (audio.ftube) { + tube::compute(ovs_count, ovs_buffer, ovs_buffer); + } + if (audio.ftube3) { + osc_tube::compute(ovs_count, ovs_buffer, ovs_buffer); + //reso_tube::compute(ovs_count, ovs_buffer, ovs_buffer); + } + if (audio.fprdr) { + drive::compute(ovs_count, ovs_buffer, ovs_buffer); + } + } + if (audio.fupsample) { + resampTube.down(count, oversample, output0); + } + //*** End (maybe) oversampled processing *** + + if (audio.fconvolve) { + convolver_filter(output0, output0, count, (unsigned int)audio.convolvefilter); + } + inputgain::compute(count, output0, output0); + tonestack::compute(count, output0, output0); + if (audio.fresoon && !audio.famp2) { + tubevibrato::compute(count, output0, output0); + } + if(audio.fcab) { + if (!cab_conv.compute(count, output0)) + cout << "overload" << endl; + //FIXME error message?? + } + + for (int m = 0; m < 8; m++) { + if (audio.posit0 == m && audio.fcheckbox5 && !audio.fautowah) { + crybaby::compute(count, output0, output0); + } else if (audio.posit0 == m && audio.fcheckbox5 && audio.fautowah) { + autowah::compute(count, output0, output0); + } else if (audio.posit5 == m && audio.fcheckboxcom1) { + compressor::compute(count, output0, output0); + } else if (audio.posit1 == m && audio.foverdrive4) { + overdrive::compute(count, output0, output0); + } else if (audio.posit2 == m && audio.fcheckbox4) { + if (audio.fupsample) { + // 2*oversample + //over_sample(count, output0, oversample); + resampDist.up(count, output0, oversample); + if(audio.witchdistortion) distortion1::compute(ovs_count, oversample, oversample); + else distortion::compute(ovs_count, oversample, oversample); + resampDist.down(count, oversample, output0); + //down_sample(count, oversample, output0); + } else { + if(audio.witchdistortion) distortion1::compute(count, output0, output0); + else distortion::compute(count, output0, output0); + } + } else if (audio.posit3 == m && audio.fcheckbox6) { + freeverb::compute(count, output0, output0); + } else if (audio.posit6 == m && audio.fcheckbox7 && echo::is_inited()) { + echo::compute(count, output0, output0); + } else if (audio.posit4 == m && audio.fcheckbox8) { + impulseresponse::compute(count, output0, output0); + } else if (audio.posit7 == m && audio.fdelay && delay::is_inited()) { + delay::compute(count, output0, output0); + } + } + + // Multibandfilter + if (audio.fmultifilter) { + multifilter::compute(count, output0, output0); + } + + outputgain::compute(count, output0, output0); + + if (audio.fboost) { + bassbooster::compute(count, output0, output0); + } + if(audio.famp2) { + stage3::compute(count, output0, output0); + } else if (audio.ftube3e) { + tube3::compute(count, output0, output0); + } + if (audio.fsloop && sloop::is_inited()) { + sloop::compute(count, output0, output0); + } +} + +void process_insert_buffers (int count, float* input1, float* output0, float* output1) +{ + memcpy(output0, input1, count*sizeof(float)); + feed::compute(count, output0, output0, output1); + + if (audio.fchorus and chorus::is_inited()) { + chorus::compute(count, output0, output1, output0, output1); + } + if (audio.fflanger) { + flanger::compute(count, output0, output1, output0, output1); + } + + if (conv.is_runnable()) { + // reuse oversampling buffer + float *conv_out0 = oversample; + float *conv_out1 = oversample+count; + if (!conv.compute(count, output0, output1, conv_out0, conv_out1)) { + gx_jconv::GxJConvSettings::checkbutton7 = 0; + cout << "overload" << endl; + //FIXME error message?? + } else if (jconv_post::is_inited()) { + jconv_post::compute(count, output0, output1, conv_out0, conv_out1, output0, output1); + } + } else { + balance::compute(count, output0, output1, output0, output1); + } + if (audio.fmoog) { + moog::compute(count, output0, output1, output0, output1); + } + (void)memcpy(get_frame, output0, sizeof(float)*count); + (void)memcpy(get_frame1, output1, sizeof(float)*count); +} + +} // namespace gx_engine + diff --git a/src/gx_engine_midi.cpp b/src/gx_engine_midi.cpp new file mode 100644 index 0000000..dd212cb --- /dev/null +++ b/src/gx_engine_midi.cpp @@ -0,0 +1,627 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the Guitarix MIDI Engine NOT using a ring buffer + * + * + * -------------------------------------------------------------------------- + */ + +#include "guitarix.h" + +namespace gx_engine +{ + +MidiVariables::MidiVariables() +{ + gx_gui::registerParam("midi_out.channel_1.velocity", "velocity", &fslider26, 64.f, 0.f, 127.f, 1.f); + gx_gui::registerParam("midi_out.channel_1.volume", "volume", &fslider46, 64.f, 0.f, 127.f, 1.f); + gx_gui::registerParam("midi_out.channel_1.autogain", "autogain", &fautogain); + gx_gui::registerParam("midi_out.channel_1.channel", "channel 1", &fslider30, 0.f, 0.f, 16.f, 1.f); + gx_gui::registerParam("midi_out.channel_1.program", "program", &fslider31, 0.f, 0.f, 248.f, 1.f); + gx_gui::registerParam("midi_out.channel_1.oktave", "oktave", &fslider29, 0.f, -2.f, 2.f, 1.f); + gx_gui::registerParam("midi_out.channel_1.sensity", "sensity", &fslider27, 20.f, 1.f, 500.f, 1.f); + gx_gui::registerParam("midi_out.channel_1.auto_pitch", "auto pitch", &fpitch); + + gx_gui::registerParam("midi_out.channel_2.on_off", "on/off", &fcheckbox10, 0); + gx_gui::registerParam("midi_out.channel_2.velocity", "velocity", &fslider32, 64.f, 0.f, 127.f, 1.f); + gx_gui::registerParam("midi_out.channel_2.volume", "volume", &fslider47, 64.f, 0.f, 127.f, 1.f); + gx_gui::registerParam("midi_out.channel_2.autogain", "autogain", &fautogain1); + gx_gui::registerParam("midi_out.channel_2.channel", "channel 2", &fslider35, 0.f, 0.f, 16.f, 1.f); + gx_gui::registerParam("midi_out.channel_2.program", "program", &fslider36, 0.f, 0.f, 248.f, 1.f); + gx_gui::registerParam("midi_out.channel_2.oktave", "oktave", &fslider34, 0.f, -2.f, 2.f, 1.f); + gx_gui::registerParam("midi_out.channel_2.sensity", "sensity", &fslider33, 20.f, 1.f, 500.f, 1.f); + gx_gui::registerParam("midi_out.channel_2.auto_pitch", "auto pitch", &fpitch1); + + gx_gui::registerParam("midi_out.channel_3.on_off", "on/off", &fcheckbox11, 0); + gx_gui::registerParam("midi_out.channel_3.velocity", "velocity", &fslider40, 64.f, 0.f, 127.f, 1.f); + gx_gui::registerParam("midi_out.channel_3.volume", "volume", &fslider48, 64.f, 0.f, 127.f, 1.f); + gx_gui::registerParam("midi_out.channel_3.autogain", "autogain", &fautogain2); + gx_gui::registerParam("midi_out.channel_3.channel", "channel 3", &fslider44, 0.f, 0.f, 16.f, 1.f); + gx_gui::registerParam("midi_out.channel_3.program", "program", &fslider43, 0.f, 0.f, 248.f, 1.f); + gx_gui::registerParam("midi_out.channel_3.oktave", "oktave", &fslider42, 0.f, -2.f, 2.f, 1.f); + gx_gui::registerParam("midi_out.channel_3.sensity", "sensity", &fslider41, 20.f, 1.f, 500.f, 1.f); + gx_gui::registerParam("midi_out.channel_3.auto_pitch", "auto pitch", &fpitch2); + + gx_gui::registerParam("beat_detector.stepper", "stepper", &fslider39, 1.f, 1.f, 32.f, 1.f); + gx_gui::registerParam("beat_detector.note_off", "note off", &fslider37, 2.f, 1.f, 127.f, 1.f); + gx_gui::registerParam("beat_detector.atack_gain", "atack gain", &fslider45, 5.f, 1.f, 127.f, 1.f); + gx_gui::registerParam("beat_detector.beat_gain", "beat gain", &fslider38, 1.f, 0.0f, 127.f, 1.f); + gx_gui::registerParam("beat_detector.midi_gain", "midi gain", &midi_gain, 0.f, -20.f, 60.f, 1.f); +} + +MidiVariables midi; + +/* +float fslider45; +float fslider38; +float fslider31; +float fslider27; +float fslider29; +float fslider30; +float fslider26; +float fslider33; +float fslider34; +float fslider35; +float fslider36; +float fslider42; +float fslider43; +float fslider40; +float fslider41; +float fslider44; +float fslider37; +float fslider39; +float fslider46; +float fslider47; +float fslider48; +float fConsta4; +float fConstlog; +float fConstlog2; +float beat0; +float midi_gain; +float fConstun0; +int weg; +int program; +unsigned char* midi_send; +int send; +float fautogain; +int volume; +float fpitch; +int noten; +float fslider32; +float cache_note; +int fcheckbox10; +int program1; +int send1; +int noten1; +float fautogain1; +int volume1; +unsigned char* midi_send1; +int send2; +int noten2; +float fpitch1; +float fpitch2; +int fcheckbox11; +int program2; +int volume2; +int Beat_is; +unsigned char* midi_send2; +float fautogain2; +*/ + +void MidiVariables::init(int samplingFreq) +{ + fConstlog = log(1.055)*0.5;; + fConstlog2 = 6/log(2)*-1; + midi_gain = 1.0; + fConstun0 = (0.001*300*samplingFreq)*36; + BeatFilterk =1.0/(gx_jack::jack_sr*(1.0f/(2.0f*M_PI*1250.0f))); + BeatFilter1 =0.0; + BeatFilter2 =0.0; +} + +//----- jack process callback for the midi input +void compute_midi_in(void* midi_input_port_buf) +{ + jack_midi_event_t in_event; + jack_nframes_t event_count = jack_midi_get_event_count(midi_input_port_buf); + unsigned int i; + for (i=0; i 0.00001) + { + //----- convert the audio gain to midi gain value + midi_db = (log(fabs(audio_db))*midi.fConstlog2); + midi.beat0 = 254- floor(exp(midi.fConstlog*midi_db)*127)+ midi.midi_gain; + rms = midi.beat0; + } + //----- check gain value and run only when gain is higher then the selected value + if (( midi.beat0 >= fTemps45) && (gx_jack::jcpu_load < 65.0)) + { + + //----- rms the gain for a smother output + if (cs == int(midi.fConstun0*stepper)) + { + cs = 0; + sum = 0; + } + else + { + cs += 1; + sum += sqrf(rms); + } + + midi.beat0 = sqrtf(sum/cs); + //set the value for the tuner + //audio.fConsta1 = fnote; + //set timeout for tuner fallback + midi.weg = 0; + + + + + //----- start the midi output + if (isMidiOn() == true) + { + // channel0 + if (midi.program != iTemps31) + { + midi.program = iTemps31; + audio.midistat += 1.0f; + midi.midi_send = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 2); + + if (midi.midi_send) + { + midi.midi_send[1] = (int)iTemps31; // program value + midi.midi_send[0] = 0xC0 | (int)iTemps30; // controller+ channel + } + } + + if (midi.send > iTemps27) //20 + { + if (int(midi.fautogain) == 1) + { + iTemps46 = midi.beat0; + if ( iTemps46 < 0) iTemps46 = 0; + else if ( iTemps46 > 127) iTemps46 = 127; + midi.fslider46 = iTemps46; + } + if (midi.volume != iTemps46) + { + midi.volume = iTemps46; + audio.midistat += 1.0f; + midi.midi_send = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send) + { + midi.midi_send[2] = (int)iTemps46; // volume value + midi.midi_send[1] = 0x07; // set controler volume + midi.midi_send[0] = 0xB0 | (int)iTemps30; // controller + channel + } + } + + midi.noten = preNote + iTemps29; + midi.send = 0; + audio.midistat += 1.0f; + + if (( midi.noten>=0)&&(midi.noten<=127)) + { + // pitch wheel clear + if (midi.fpitch == 1.0) + { + midi.midi_send = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + if (midi.midi_send) + { + midi.midi_send[2] = 0x40; // pitch value + midi.midi_send[1] = 0x00 ; // pitch value + midi.midi_send[0] = 0xE0 | (int)iTemps30; // controller + channel + } + } + midi.midi_send = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + if (midi.midi_send) + { + midi.midi_send[2] = (int)iTemps26; // velocity + midi.midi_send[1] = midi.noten ; // note + midi.midi_send[0] = 0x90 | (int)iTemps30; // controller + channel + } + + // pitch wheel set auto + if (midi.fpitch == 1.0) + { + if (piwe < 0) piwe = 0; + if (fConsta2 > 0x3fff) piwe = 0x3fff; + midi.midi_send = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send) + { + midi.midi_send[2] = (piwe >> 7) & 0x7f; // pitch + midi.midi_send[1] = piwe & 0x7f ; // pitch + midi.midi_send[0] = 0xE0 | (int)iTemps30; // controller + channel + } + } + } + } + + // channel1 + if (midi.fcheckbox10) + { + if (midi.program1 != iTemps36) + { + midi.program1 = iTemps36; + audio.midistat += 1.0f; + midi.midi_send1 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 2); + + if (midi.midi_send1) + { + midi.midi_send1[1] = (int)iTemps36; // program value + midi.midi_send1[0] = 0xC0 | (int)iTemps35; // controller+ channel + } + } + + if (midi.send1 > iTemps33) + { + if (int(midi.fautogain1) == 1) + { + iTemps47 = midi.beat0; + if ( iTemps47 < 0) iTemps47 = 0; + else if ( iTemps47 > 127) iTemps47 = 127; + + midi.fslider47 = iTemps47; + } + + if (midi.volume1 != iTemps47) + { + midi.volume1 = iTemps47; + audio.midistat += 1.0f; + midi.midi_send1 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + if (midi.midi_send1) + { + midi.midi_send1[2] = (int)iTemps47; // volume value + midi.midi_send1[1] = 0x07; // set controler channel volume + midi.midi_send1[0] = 0xB0 | (int)iTemps35; // controller + channel + } + } + + midi.noten1 = preNote + iTemps34; + midi.send1 = 0; + audio.midistat += 1.0f; + if ((midi.noten1>=0)&&(midi.noten1<=127)) + { + // pitch wheel clear + if (midi.fpitch1 == 1.0) + { + midi.midi_send1 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + if (midi.midi_send1) + { + midi.midi_send1[2] = 0x40; // pitch value + midi.midi_send1[1] = 0x00 ; // pitch value + midi.midi_send1[0] = 0xE0 | (int)iTemps35; // controller + channel + } + } + midi.midi_send1 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send1) + { + midi.midi_send1[2] = (int)iTemps32; // velocity + midi.midi_send1[1] = midi.noten1; // note + midi.midi_send1[0] = 0x90 | (int)iTemps35; // note on + channel + } + + // pitch wheel set auto + if (midi.fpitch1 == 1.0) + { + if (piwe < 0) piwe = 0; + if (fConsta2 > 0x3fff) piwe = 0x3fff; + midi.midi_send1 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send1) + { + midi.midi_send1[2] = (piwe >> 7) & 0x7f; // pitch + midi.midi_send1[1] = piwe & 0x7f ; // pitch + midi.midi_send1[0] = 0xE0 | (int)iTemps35; // controller + channel + } + } + } + } + } + + if (midi.fcheckbox11) + { + if (midi.program2 != iTemps43) + { + midi.program2 = iTemps43; + audio.midistat += 1.0f; + midi.midi_send2 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 2); + + if (midi.midi_send2) + { + midi.midi_send2[1] = (int)iTemps43; // program value + midi.midi_send2[0] = 0xC0 | (int)iTemps44; // controller + } + } + + if (midi.send2 > iTemps41) //20 + { + if (int(midi.fautogain2) == 1) + { + iTemps48 = midi.beat0; + if ( iTemps48 < 0) iTemps48 = 0; + else if ( iTemps48 > 127) iTemps48 = 127; + midi.fslider48 = iTemps48; + } + + if (midi.volume2 != iTemps48) + { + midi.volume2 = iTemps48; + audio.midistat += 1.0f; + midi.midi_send2 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + if (midi.midi_send2) + { + midi.midi_send2[2] = (int)iTemps48; // volume value + midi.midi_send2[1] = 0x07; // set controler channel volume + midi.midi_send2[0] = 0xB0 | (int)iTemps44; // controller + channel + } + } + + // pitch wheel clear + if (midi.fpitch2 == 1.0) + { + midi.midi_send2 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + if (midi.midi_send2) + { + midi.midi_send2[2] = 0x40; // pitch value + midi.midi_send2[1] = 0x00 ; // pitch value + midi.midi_send2[0] = 0xE0 | (int)iTemps44; // controller + channel + } + } + + midi.noten2 = preNote + iTemps42; + midi.send2 = 0; + audio.midistat += 1.0f; + + if ((midi.noten2>=0)&&(midi.noten2<=127)) + { + midi.midi_send2 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send2) + { + midi.midi_send2[2] = (int)iTemps40; // velocity + midi.midi_send2[1] = midi.noten2; // note + midi.midi_send2[0] = 0x90 | (int)iTemps44; // note on + channel + } + + // pitch wheel set auto + if (midi.fpitch2 == 1.0) + { + if (piwe < 0) piwe = 0; + if (fConsta2 > 0x3fff) piwe = 0x3fff; + midi.midi_send2 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + if (midi.midi_send2) + { + midi.midi_send2[2] = (piwe >> 7) & 0x7f; // pitch + midi.midi_send2[1] = piwe & 0x7f ; // pitch + midi.midi_send2[0] = 0xE0 | (int)iTemps44; // controller + channel + } + } + } + } + } + + if ( rms >= (midi.Beat_is + fTemps38)) + { + //midi.Beat_is = rms; + midi.Beat_is += rms*0.1; + midi.send+=step; + if (midi.fcheckbox10 ) midi.send1+=step; + if (midi.fcheckbox11 ) midi.send2+=step; + midi.weg -= step; + } + // else midi.weg +=step; + } + + // end if playmidi = 1 + } + else + { + if (isMidiOn() == true) + { + if ((midi.weg > iTemps37) || (gx_jack::jcpu_load > 64.0)) + { + midi.send = midi.send1 = midi.send2 = 0; + midi.Beat_is = fTemps45; + if (midi.weg < iTemps37a) // 5.0 + { + audio.midistat += 1.0f; + midi.midi_send = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send) + { + midi.midi_send[2] = (int)iTemps26; // velocity + midi.midi_send[1] = 123; // fix me all notes off + midi.midi_send[0] = 0xB0 | (int)iTemps30 ; // controller + } + + if (midi.fcheckbox10) + { + audio.midistat += 1.0f; + midi.midi_send1 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send1) + { + midi.midi_send1[2] = (int)iTemps32; // velocity + midi.midi_send1[1] = 123; // fix me all notes off + midi.midi_send1[0] = 0xB0 | (int)iTemps35; // controller + //fprintf(stderr, "Send %i , %i, %i.\n",iTemps32,123,0xB0 | iTemps35); + } + } + + if (midi.fcheckbox11) + { + audio.midistat += 1.0f; + midi.midi_send2 = jack_midi_event_reserve(gx_jack::midi_port_buf, i, 3); + + if (midi.midi_send2) + { + midi.midi_send2[2] = (int)iTemps40; // velocity + midi.midi_send2[1] = 123; // fix me all notes off + midi.midi_send2[0] = 0xB0 | (int)iTemps44; // controller + } + } + audio.midistat = 0.0f; + } + } + midi.weg+=step; + } + + /*if (gx_gui::shownote == 1) + { + if (midi.weg > (int)gx_jack::jack_sr / 2) + { + audio.fConsta1 = 2000.0f; + } + midi.weg+=step; + }*/ + } + + } + } +} + +} /* end of gx_engine namespace */ diff --git a/src/gx_engine_midi_ringbuf.cpp b/src/gx_engine_midi_ringbuf.cpp new file mode 100644 index 0000000..b946382 --- /dev/null +++ b/src/gx_engine_midi_ringbuf.cpp @@ -0,0 +1,392 @@ +/* + * Copyright (C) 2009 Hermann Meyer and James Warden + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the Guitarix MIDI Engine using a ring buffer + * + * + * -------------------------------------------------------------------------- + */ + +struct MidiMessage ev; + +void GxEngine::queue_message(struct MidiMessage *ev) +{ + int space; + space = jack_ringbuffer_write_space( jack_ringbuffer); + + if (space > int(sizeof(*ev)+2)) + { + int written; + written = jack_ringbuffer_write(jack_ringbuffer, (char *)ev, sizeof(*ev)); + + if (written != sizeof(*ev)) + gx_print_warning("MIDI engine", "Not enough space in the ringbuffer, NOTE LOST."); + } +} + +/****************************************************************************** + Thanks Edward for your friendly permision + Edward Tomasz Napierala . +******************************************************************************/ + + +void GxEngine::compute_midi( int len) +{ + TBeatDetector myTBeatDetector; + + + float fConsta2 = 0; + int preNote = 0; + float fTemps45 = fslider45; + int iTemps31 = int(fslider31); + int iTemps30 = int(fslider30); + int iTemps27 = int(fslider27); + int iTemps29 = int(fslider29)*12; + int iTemps26 = int(fslider26); + int iTemps36 = int(fslider36); + int iTemps35 = int(fslider35); + int iTemps33 = int(fslider33); + int iTemps34 = int(fslider34)*12; + int iTemps32 = int(fslider32); + int iTemps43 = int(fslider43); + int iTemps44 = int(fslider44); + int iTemps41 = int(fslider41); + int iTemps42 = int(fslider42)*12; + int iTemps40 = int(fslider40); + int step = fslider39; + double stepper = 1./step; + int iTemps37 = int(fSamplingFreq/fslider37); + int iTemps37a = int(fSamplingFreq/fslider37) +step+5; + float fTemps38 = fslider38; + float rms = 0; + float midi_db = 0; + int iTemps46 = int(fslider46); + int iTemps47 = int(fslider47); + int iTemps48 = int(fslider48); + int piwe = 0; + int cs = 0; + float sum = 0; + float *audiodata = checkfreq; + + if ((gx_ui::GxMainInterface::shownote == 1) || (dsp::isMidiOn() == true)) + { + for (int i=0; i= fTemps45) && (cpu_load < 65.0)) + { + + if (cs == int(fConstun0*stepper)) + { + cs = 0; + sum = 0; + } + else + { + cs += 1; + sum += sqrf(rms); + } + beat0 = sqrtf(sum/cs); + + fConsta1 = 12 * log2f(2.272727e-03f * fConsta4); + preNote = round(fConsta1)+57; + fConsta2 = fConsta1 - (preNote - 57); + piwe = (fConsta2+1) * 8192; // pitch wheel value + weg = 0; + + if (dsp::isMidiOn() == true) + { + // channel0 + if (program != iTemps31) + { + program = iTemps31; + midistat += 1.0f; + ev.len = 2; + ev.data[0] = 0xC0 | iTemps30; // controller+ channel + ev.data[1] = iTemps31; // program value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + if (send > iTemps27) //20 + { + if (int(fautogain) == 1) + { + iTemps46 = beat0; + if ( iTemps46 < 0) iTemps46 = 0; + else if ( iTemps46 > 127) iTemps46 = 127; + fslider46 = iTemps46; + } + if (volume != iTemps46) + { + volume = iTemps46; + midistat += 1.0f; + ev.len = 3; + ev.data[0] = 0xB0 | iTemps30; // controller + channel + ev.data[1] = 0x07; // set controler volume + ev.data[2] = iTemps46; // volume value + ev.time = jack_frame_time(client); + // ev.framenum = i; + queue_message(&ev); + } + + noten = preNote + iTemps29; + send = 0; + midistat += 1.0f; + if (( noten>=0)&&(noten<=127)) + { + // pitch wheel clear + if (fpitch == 1.0) + { + ev.len = 3; + ev.data[0] = 0xE0 | iTemps30; // controller + channel + ev.data[1] = 0x00 ; // pitch value + ev.data[2] = 0x40; // pitch value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + ev.len = 3; + ev.data[0] = 0x90 | iTemps30; // controller + channel + ev.data[1] =noten ; // note + ev.data[2] = iTemps26; // velocity + ev.time = jack_frame_time(client); + queue_message(&ev); + + // pitch wheel set auto + if (fpitch == 1.0) + { + if (piwe < 0) piwe = 0; + if (fConsta2 > 0x3fff) piwe = 0x3fff; + ev.len = 3; + ev.data[0] = 0xE0 | iTemps30; // controller + channel + ev.data[1] = piwe & 0x7f ; // pitch + ev.data[2] = (piwe >> 7) & 0x7f; // pitch + ev.time = jack_frame_time(client); + queue_message(&ev); + } + } + } + // channel1 + if (fcheckbox10 == 1.0) + { + if (program1 != iTemps36) + { + program1 = iTemps36; + midistat += 1.0f; + ev.len = 2; + ev.data[0] = 0xC0 | iTemps35; // controller+ channel + ev.data[1] = iTemps36; // program value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + if (send1 > iTemps33) + { + if (int(fautogain1) == 1) + { + iTemps47 = beat0; + if ( iTemps47 < 0) iTemps47 = 0; + else if ( iTemps47 > 127) iTemps47 = 127; + fslider47 = iTemps47; + } + if (volume1 != iTemps47) + { + volume1 = iTemps47; + midistat += 1.0f; + ev.len = 3; + ev.data[0] = 0xB0 | iTemps35; // controller + channel + ev.data[1] = 0x07; // set controler channel volume + ev.data[2] = iTemps47; // volume value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + + noten1 = preNote + iTemps34; + send1 = 0; + midistat += 1.0f; + if ((noten1>=0)&&(noten1<=127)) + { + // pitch wheel clear + if (fpitch1 == 1.0) + { + ev.len = 3; + ev.data[0] = 0xE0 | iTemps35; // controller + channel + ev.data[1] = 0x00 ; // pitch value + ev.data[2] = 0x40; // pitch value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + ev.len = 3; + ev.data[0] = 0x90 | iTemps35; // note on + channel + ev.data[1] = noten1; // note + ev.data[2] = iTemps32; // velocity + ev.time = jack_frame_time(client); + queue_message(&ev); + + // pitch wheel set auto + if (fpitch1 == 1.0) + { + if (piwe < 0) piwe = 0; + if (fConsta2 > 0x3fff) piwe = 0x3fff; + ev.len = 3; + ev.data[0] = 0xE0 | iTemps35; // controller + channel + ev.data[1] = piwe & 0x7f ; // pitch + ev.data[2] = (piwe >> 7) & 0x7f; // pitch + ev.time = jack_frame_time(client); + queue_message(&ev); + } + } + } + } + if (fcheckbox11 == 1.0) + { + if (program2 != iTemps43) + { + program2 = iTemps43; + midistat += 1.0f; + ev.len = 2; + ev.data[0] = 0xC0 | iTemps44; // controller + ev.data[1] = iTemps43; // program value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + if (send2 > iTemps41) //20 + { + if (int(fautogain2) == 1) + { + iTemps48 = beat0; + if ( iTemps48 < 0) iTemps48 = 0; + else if ( iTemps48 > 127) iTemps48 = 127; + fslider48 = iTemps48; + } + if (volume2 != iTemps48) + { + volume2 = iTemps48; + midistat += 1.0f; + ev.len = 3; + ev.data[0] = 0xB0 | iTemps44; // controller + channel + ev.data[1] = 0x07; // set controler channel volume + ev.data[2] = iTemps48; // volume value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + + // pitch wheel clear + if (fpitch2 == 1.0) + { + ev.len = 3; + ev.data[0] = 0xE0 | iTemps44; // controller + channel + ev.data[1] = 0x00 ; // pitch value + ev.data[2] = 0x40; // pitch value + ev.time = jack_frame_time(client); + queue_message(&ev); + } + noten2 = preNote + iTemps42; + send2 = 0; + midistat += 1.0f; + if ((noten2>=0)&&(noten2<=127)) + { + ev.len = 3; + ev.data[0] = 0x90 | iTemps44; // note on + channel + ev.data[1] = noten2; // note + ev.data[2] = iTemps40; // velocity + ev.time = jack_frame_time(client); + queue_message(&ev); + + // pitch wheel set auto + if (fpitch2 == 1.0) + { + if (piwe < 0) piwe = 0; + if (fConsta2 > 0x3fff) piwe = 0x3fff; + ev.len = 3; + ev.data[0] = 0xE0 | iTemps44; // controller + channel + ev.data[1] = piwe & 0x7f ; // pitch + ev.data[2] = (piwe >> 7) & 0x7f; // pitch + ev.time = jack_frame_time(client); + queue_message(&ev); + } + } + } + } + myTBeatDetector.setSampleRate (fSamplingFreq*stepper); + myTBeatDetector.AudioProcess (rms, fTemps38); + if (myTBeatDetector.BeatPulse == TRUE) + { + send+=step; + if (fcheckbox10 == 1.0) send1+=step; + if (fcheckbox11 == 1.0) send2+=step; + } + } + // end if isMidiOn() = true + } + else + { + if (dsp::isMidiOn() == true) + { + if ((weg > iTemps37) || (cpu_load > 64.0)) + { + if (weg < iTemps37a) // 5.0 + { + midistat += 1.0f; + ev.len = 3; + ev.data[0] = 0xB0 | iTemps30 ; // controller + ev.data[1] = 123; // all notes off + ev.data[2] = iTemps26; // velocity + ev.time = jack_frame_time(client); + queue_message(&ev); + if (fcheckbox10 == 1.0) + { + midistat += 1.0f; + ev.len = 3; + ev.data[0] = 0xB0 | iTemps35; // controller + ev.data[1] = 123; // all notes off + ev.data[2] = iTemps32; // velocity + ev.time = jack_frame_time(client); + queue_message(&ev); + } + if (fcheckbox11 == 1.0) + { + midistat += 1.0f; + ev.len = 3; + ev.data[0] = 0xB0 | iTemps44; // controller + ev.data[1] = 123; // all notes off + ev.data[2] = iTemps40; // velocity + ev.time = jack_frame_time(client); + queue_message(&ev); + } + midistat = 0.0f; + } + } + weg+=step; + } + if (GTKUI::shownote == 1) + { + if (weg > (fSamplingFreq)/2) + { + fConsta1 = 2000.0f; + } + weg+=step; + } + } + + } + } +}; diff --git a/src/gx_engine_tubetable.cc b/src/gx_engine_tubetable.cc new file mode 100644 index 0000000..d6a3656 --- /dev/null +++ b/src/gx_engine_tubetable.cc @@ -0,0 +1,866 @@ +/* + * Copyright (C) 2009-2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 file is part of the Guitarix Audio Engine + * + * + * -------------------------------------------------------------------------- + */ + + + +#define TAB_SIZE (2001) + + + +struct table1d { + float low; + float high; + float istep; + float data[TAB_SIZE]; +}; + +struct table1d tubetable[] = { + { // Ri = 68k + -5,5,200, { + 249.98706929,249.986851225,249.986629489,249.986404021,249.986174757, + 249.985941635,249.985704589,249.985463554,249.985218463,249.984969247, + 249.984715838,249.984458166,249.984196158,249.983929743,249.983658846, + 249.983383392,249.983103306,249.982818508,249.982528921,249.982234464, + 249.981935056,249.981630613,249.981321052,249.981006287,249.98068623, + 249.980360793,249.980029887,249.979693419,249.979351296,249.979003424, + 249.978649708,249.978290048,249.977924346,249.9775525,249.977174409, + 249.976789967,249.976399069,249.976001606,249.97559747,249.975186548, + 249.974768727,249.974343893,249.973911927,249.973472711,249.973026125, + 249.972572044,249.972110345,249.9716409,249.971163579,249.970678252, + 249.970184785,249.969683043,249.969172887,249.968654177,249.968126772, + 249.967590526,249.967045292,249.96649092,249.965927258,249.965354153, + 249.964771446,249.964178978,249.963576587,249.962964107,249.962341372, + 249.961708211,249.96106445,249.960409914,249.959744424,249.959067797, + 249.95837985,249.957680393,249.956969237,249.956246188,249.955511048, + 249.954763616,249.95400369,249.953231063,249.952445523,249.951646857, + 249.950834849,249.950009276,249.949169916,249.94831654,249.947448916, + 249.946566809,249.945669979,249.944758184,249.943831177,249.942888706, + 249.941930516,249.940956349,249.93996594,249.938959023,249.937935324, + 249.936894568,249.935836475,249.934760758,249.933667127,249.932555289, + 249.931424944,249.930275788,249.929107511,249.9279198,249.926712337, + 249.925484796,249.92423685,249.922968162,249.921678394,249.9203672, + 249.91903423,249.917679127,249.916301529,249.914901069,249.913477372, + 249.912030061,249.910558748,249.909063042,249.907542547,249.905996856, + 249.904425561,249.902828244,249.901204482,249.899553844,249.897875894, + 249.896170188,249.894436274,249.892673696,249.890881989,249.889060679, + 249.887209288,249.885327328,249.883414305,249.881469716,249.879493052, + 249.877483793,249.875441414,249.87336538,249.87125515,249.869110171, + 249.866929885,249.864713724,249.86246111,249.860171458,249.857844173, + 249.855478652,249.853074281,249.850630438,249.848146491,249.845621799, + 249.843055711,249.840447565,249.837796689,249.835102404,249.832364016, + 249.829580824,249.826752115,249.823877166,249.820955243,249.8179856, + 249.81496748,249.811900117,249.80878273,249.80561453,249.802394713, + 249.799122465,249.795796959,249.792417358,249.788982809,249.785492449, + 249.781945403,249.778340779,249.774677678,249.770955183,249.767172365, + 249.763328284,249.759421981,249.75545249,249.751418824,249.747319988, + 249.743154968,249.738922738,249.734622257,249.730252468,249.725812301, + 249.72130067,249.716716471,249.712058589,249.70732589,249.702517225, + 249.697631429,249.692667321,249.687623703,249.682499361,249.677293063, + 249.672003562,249.666629592,249.661169871,249.655623098,249.649987954, + 249.644263106,249.638447197,249.632538857,249.626536694,249.620439299, + 249.614245244,249.607953082,249.601561346,249.59506855,249.588473189, + 249.581773739,249.574968653,249.568056367,249.561035295,249.553903831, + 249.546660348,249.5393032,249.531830718,249.524241211,249.516532969, + 249.508704259,249.500753327,249.492678397,249.48447767,249.476149326, + 249.467691521,249.459102391,249.450380046,249.441522576,249.432528047, + 249.423394501,249.414119957,249.404702411,249.395139834,249.385430176, + 249.37557136,249.365561287,249.355397831,249.345078845,249.334602156, + 249.323965565,249.313166851,249.302203767,249.291074039,249.27977537, + 249.268305439,249.256661896,249.244842368,249.232844458,249.220665739, + 249.208303762,249.195756051,249.183020104,249.170093394,249.156973366, + 249.143657441,249.130143014,249.116427453,249.102508098,249.088382267, + 249.074047249,249.059500307,249.044738677,249.029759572,249.014560175, + 248.999137645,248.983489114,248.967611688,248.951502446,248.935158442, + 248.918576704,248.901754233,248.884688005,248.867374969,248.84981205, + 248.831996145,248.813924127,248.795592843,248.776999115,248.75813974, + 248.739011488,248.719611106,248.699935316,248.679980814,248.659744274, + 248.639222342,248.618411645,248.597308781,248.575910327,248.554212837, + 248.532212841,248.509906845,248.487291335,248.464362771,248.441117595, + 248.417552224,248.393663055,248.369446462,248.344898801,248.320016406, + 248.29479559,248.269232647,248.243323852,248.217065459,248.190453706, + 248.163484811,248.136154974,248.108460379,248.080397191,248.05196156, + 248.02314962,247.993957487,247.964381265,247.934417041,247.904060889, + 247.87330887,247.84215703,247.810601403,247.778638011,247.746262866, + 247.713471967,247.680261303,247.646626855,247.612564592,247.578070476, + 247.543140461,247.507770494,247.471956513,247.435694453,247.398980241, + 247.3618098,247.32417905,247.286083906,247.247520279,247.208484082, + 247.168971222,247.128977607,247.088499146,247.047531747,247.00607132, + 246.964113777,246.921655031,246.878691002,246.835217611,246.791230785, + 246.746726457,246.701700566,246.656149058,246.610067887,246.563453015, + 246.516300414,246.468606066,246.420365964,246.371576111,246.322232524, + 246.272331232,246.221868279,246.170839722,246.119241634,246.067070104, + 246.014321237,245.960991157,245.907076004,245.852571939,245.79747514, + 245.74178181,245.685488167,245.628590455,245.571084939,245.512967907, + 245.454235672,245.394884569,245.334910961,245.274311236,245.213081807, + 245.151219115,245.08871963,245.02557985,244.9617963,244.897365536, + 244.832284146,244.766548747,244.700155987,244.633102547,244.565385141, + 244.497000515,244.427945449,244.358216758,244.287811291,244.216725932, + 244.144957602,244.072503257,243.999359889,243.92552453,243.850994248, + 243.775766147,243.699837372,243.623205106,243.545866572,243.467819032, + 243.389059786,243.309586179,243.229395592,243.148485449,243.066853216, + 242.984496398,242.901412546,242.817599248,242.733054138,242.647774892, + 242.561759227,242.475004906,242.387509732,242.299271553,242.210288262, + 242.120557793,242.030078124,241.938847279,241.846863324,241.754124371, + 241.660628575,241.566374134,241.471359294,241.375582341,241.279041608, + 241.181735472,241.083662355,240.984820721,240.885209081,240.784825989, + 240.683670043,240.581739885,240.479034203,240.375551726,240.271291229, + 240.166251531,240.060431493,239.95383002,239.846446061,239.738278607, + 239.629326695,239.5195894,239.409065844,239.29775519,239.185656641, + 239.072769446,238.959092892,238.84462631,238.729369072,238.61332059, + 238.496480317,238.378847747,238.260422414,238.141203892,238.021191795, + 237.900385775,237.778785524,237.656390773,237.533201291,237.409216884, + 237.284437398,237.158862715,237.032492753,236.905327469,236.777366855, + 236.648610938,236.519059783,236.388713489,236.257572188,236.125636051, + 235.992905278,235.859380107,235.725060807,235.58994768,235.454041062, + 235.31734132,235.179848852,235.041564089,234.902487493,234.762619556, + 234.6219608,234.480511776,234.338273067,234.195245283,234.051429062, + 233.906825072,233.761434008,233.615256591,233.468293572,233.320545726, + 233.172013855,233.022698786,232.872601372,232.721722492,232.570063047, + 232.417623965,232.264406196,232.110410713,231.955638512,231.800090614, + 231.643768059,231.48667191,231.328803251,231.170163188,231.010752847, + 230.850573373,230.689625933,230.527911712,230.365431915,230.202187764, + 230.0381805,229.873411384,229.707881693,229.541592719,229.374545774, + 229.206742186,229.038183299,228.868870471,228.698805078,228.527988509, + 228.356422169,228.184107477,228.011045867,227.837238785,227.662687692, + 227.487394061,227.311359378,227.134585141,226.957072863,226.778824064, + 226.59984028,226.420123056,226.239673947,226.058494521,225.876586355, + 225.693951036,225.510590161,225.326505336,225.141698178,224.956170309, + 224.769923365,224.582958985,224.39527882,224.206884527,224.017777772, + 223.827960226,223.637433569,223.446199487,223.254259674,223.061615828, + 222.868269655,222.674222866,222.479477179,222.284034315,222.087896002, + 221.891063973,221.693539966,221.495325721,221.296422987,221.096833513, + 220.896559053,220.695601367,220.493962216,220.291643365,220.088646583, + 219.884973642,219.680626315,219.475606381,219.269915618,219.063555809, + 218.856528737,218.64883619,218.440479954,218.231461819,218.021783577, + 217.811447019,217.600453941,217.388806137,217.176505402,216.963553533, + 216.749952328,216.535703584,216.3208091,216.105270675,215.889090106, + 215.672269193,215.454809735,215.23671353,215.017982376,214.798618071, + 214.578622412,214.357997196,214.136744219,213.914865275,213.692362159, + 213.469236664,213.245490582,213.021125704,212.796143819,212.570546714, + 212.344336178,212.117513994,211.890081946,211.662041815,211.433395383, + 211.204144425,210.97429072,210.74383604,210.512782158,210.281130844, + 210.048883865,209.816042987,209.582609974,209.348586585,209.113974579, + 208.878775712,208.642991738,208.406624407,208.169675468,207.932146665, + 207.694039743,207.455356441,207.216098496,206.976267643,206.735865613, + 206.494894135,206.253354936,206.011249738,205.76858026,205.52534822, + 205.281555332,205.037203306,204.792293851,204.54682867,204.300809466, + 204.054237936,203.807115776,203.559444679,203.311226332,203.062462422, + 202.813154631,202.563304638,202.312914121,202.06198475,201.810518197, + 201.558516128,201.305980206,201.05291209,200.799313438,200.545185904, + 200.290531137,200.035350786,199.779646493,199.5234199,199.266672645, + 199.009406363,198.751622683,198.493323236,198.234509646,197.975183536, + 197.715346523,197.455000226,197.194146256,196.932786223,196.670921736, + 196.408554398,196.145685811,195.882317572,195.618451279,195.354088524, + 195.089230896,194.823879985,194.558037374,194.291704646,194.024883381, + 193.757575156,193.489781546,193.221504124,192.952744459,192.68350412, + 192.413784672,192.143587679,191.872914702,191.601767301,191.330147033, + 191.058055454,190.785494118,190.512464577,190.238968382,189.965007082, + 189.690582224,189.415695355,189.14034802,188.864541763,188.588278126, + 188.311558653,188.034384883,187.756758358,187.478680617,187.200153199, + 186.921177645,186.641755492,186.36188828,186.081577548,185.800824834, + 185.519631679,185.237999622,184.955930205,184.673424969,184.390485457, + 184.107113213,183.823309782,183.539076713,183.254415552,182.969327853, + 182.683815168,182.397879052,182.111521065,181.824742767,181.537545724, + 181.249931504,180.961901678,180.673457823,180.384601519,180.095334351, + 179.805657909,179.515573788,179.225083588,178.934188917,178.642891387, + 178.351192617,178.059094236,177.766597877,177.473705181,177.1804178, + 176.886737393,176.592665628,176.298204182,176.003354745,175.708119016, + 175.412498704,175.116495531,174.820111234,174.523347558,174.226206264, + 173.92868913,173.630797944,173.332534512,173.033900658,172.734898219, + 172.435529055,172.13579504,171.835698069,171.53524006,171.234422948, + 170.933248694,170.631719279,170.32983671,170.027603019,169.725020263, + 169.422090529,169.118815931,168.815198611,168.511240746,168.206944541, + 167.902312237,167.597346111,167.292048474,166.986421676,166.680468107, + 166.374190197,166.06759042,165.760671293,165.453435381,165.145885296, + 164.8380237,164.529853307,164.221376886,163.912597261,163.603517315, + 163.294139991,162.984468296,162.674505303,162.36425415,162.05371805, + 161.742900285,161.431804217,161.120433284,160.808791007,160.496880994, + 160.184706939,159.872272629,159.559581944,159.246638866,158.933447477, + 158.620011964,158.306336627,157.992425878,157.678284247,157.363916386, + 157.049327076,156.734521226,156.419503883,156.104280235,155.788855613, + 155.473235502,155.15742554,154.841431529,154.525259436,154.2089154, + 153.89240574,153.575736958,153.258915746,152.941948993,152.624843791, + 152.307607442,151.990247462,151.672771591,151.3551878,151.037504296, + 150.719729528,150.4018722,150.083941272,149.765945972,149.4478958, + 149.129800541,148.811670267,148.493515348,148.17534646,147.857174591, + 147.539011052,147.220867482,146.90275586,146.584688509,146.266678104, + 145.948737684,145.630880657,145.313120806,144.995472301,144.677949704, + 144.360567975,144.043342481,143.726289002,143.409423738,143.092763314, + 142.776324787,142.46012565,142.144183838,141.828517734,141.513146167, + 141.198088421,140.883364237,140.56899381,140.254997798,139.941397314, + 139.628213931,139.31546968,139.003187046,138.691388964,138.380098818, + 138.069340432,137.759138065,137.449516402,137.140500548,136.832116012, + 136.524388701,136.217344903,135.911011273,135.605414819,135.300582882, + 134.99654312,134.693323486,134.390952204,134.089457749,133.788868823, + 133.489214324,133.190523322,132.89282503,132.596148773,132.300523955, + 132.005980028,131.712546456,131.420252683,131.129128093,130.839201977, + 130.550503492,130.263061625,129.97690515,129.692062595,129.408562198, + 129.126431866,128.845699141,128.566391153,128.288534586,128.012155639, + 127.737279983,127.463932729,127.19213839,126.921920841,126.653303293, + 126.386308253,126.120957494,125.857272028,125.595272075,125.334977038, + 125.076405477,124.819575089,124.564502686,124.311204176,124.059694549, + 123.809987864,123.562097233,123.316034816,123.071811813,122.829438459, + 122.588924021,122.3502768,122.113504129,121.878612383,121.645606978, + 121.414492385,121.185272137,120.957948844,120.732524201,120.508999009, + 120.287373188,120.067645798,119.849815055,119.633878355,119.419832294, + 119.207672691,118.997394612,118.788992394,118.582459671,118.377789395, + 118.174973871,117.974004772,117.774873176,117.577569586,117.382083958, + 117.188405731,116.996523847,116.806426787,116.618102586,116.431538869, + 116.246722869,116.063641457,115.882281163,115.702628206,115.524668508, + 115.348387726,115.173771271,115.000804328,114.82947188,114.659758727, + 114.491649506,114.325128711,114.160180708,113.996789759,113.834940032, + 113.674615621,113.515800563,113.358478849,113.20263444,113.048251282, + 112.895313317,112.743804495,112.593708787,112.445010196,112.297692766, + 112.151740591,112.007137828,111.863868702,111.721917517,111.581268659, + 111.441906608,111.303815943,111.166981347,111.031387613,110.897019652, + 110.763862493,110.63190129,110.501121329,110.371508026,110.243046933, + 110.115723745,109.989524294,109.864434561,109.740440669,109.617528892, + 109.495685656,109.374897534,109.255151254,109.1364337,109.018731905, + 108.902033061,108.786324515,108.671593767,108.557828476,108.445016453, + 108.333145667,108.222204241,108.112180452,108.003062732,107.894839664, + 107.787499986,107.681032587,107.575426505,107.470670928,107.366755194, + 107.263668787,107.161401337,107.059942619,106.959282552,106.859411195, + 106.760318751,106.661995559,106.564432098,106.467618982,106.37154696, + 106.276206914,106.181589858,106.087686935,105.994489418,105.901988705, + 105.81017632,105.719043911,105.628583246,105.538786217,105.44964483, + 105.361151211,105.273297602,105.186076356,105.09947994,105.013500931, + 104.928132016,104.843365988,104.759195746,104.675614294,104.592614738, + 104.510190286,104.428334244,104.347040018,104.266301109,104.186111115, + 104.106463726,104.027352725,103.948771984,103.870715468,103.793177227, + 103.716151398,103.639632204,103.563613952,103.48809103,103.41305791, + 103.33850914,103.26443935,103.190843246,103.117715611,103.045051301, + 102.972845249,102.901092457,102.829788,102.758927024,102.688504742, + 102.618516438,102.54895746,102.479823222,102.411109205,102.342810952, + 102.274924068,102.207444221,102.140367139,102.07368861,102.007404481, + 101.941510654,101.876003092,101.810877811,101.746130883,101.681758433, + 101.617756641,101.554121738,101.490850007,101.427937781,101.365381444, + 101.303177428,101.241322214,101.179812331,101.118644352,101.057814898, + 100.997320637,100.937158279,100.877324577,100.817816329,100.758630377, + 100.6997636,100.641212922,100.582975306,100.525047756,100.467427312, + 100.410111057,100.353096108,100.296379621,100.23995879,100.183830844, + 100.127993045,100.072442696,100.017177128,99.9621937113,99.9074898464, + 99.8530629679,99.7989105427,99.7450300696,99.6914190787,99.6380751312, + 99.5849958187,99.5321787628,99.4796216147,99.4273220547,99.3752777916, + 99.3234865625,99.2719461323,99.2206542933,99.1696088648,99.1188076924, + 99.0682486481,99.0179296296,98.9678485599,98.918003387,98.8683920837, + 98.8190126467,98.769863097,98.7209414788,98.6722458598,98.6237743302, + 98.5755250031,98.5274960135,98.4796855184,98.4320916962,98.3847127468, + 98.3375468908,98.2905923695,98.2438474444,98.1973103972,98.1509795293, + 98.1048531614,98.0589296337,98.013207305,97.9676845528,97.922359773, + 97.8772313798,97.8322978049,97.7875574979,97.7430089255,97.6986505718, + 97.6544809376,97.6104985402,97.5667019136,97.5230896077,97.4796601886, + 97.4364122381,97.3933443532,97.3504551465,97.3077432458,97.2652072933, + 97.2228459464,97.1806578767,97.1386417702,97.0967963268,97.0551202605, + 97.0136122989,96.9722711833,96.931095668,96.8900845209,96.8492365225, + 96.8085504664,96.7680251586,96.7276594179,96.687452075,96.6474019731, + 96.6075079673,96.5677689244,96.528183723,96.4887512533,96.4494704166, + 96.4103401258,96.3713593045,96.3325268876,96.2938418206,96.2553030595, + 96.2169095712,96.1786603327,96.1405543314,96.1025905648,96.0647680402, + 96.0270857751,95.9895427965,95.9521381411,95.9148708551,95.8777399941, + 95.840744623,95.8038838156,95.767156655,95.7305622332,95.6940996508, + 95.6577680174,95.621566451,95.5854940781,95.5495500336,95.5137334607, + 95.4780435108,95.4424793434,95.4070401257,95.3717250333,95.3365332491, + 95.3014639639,95.2665163763,95.231689692,95.1969831244,95.1623958942, + 95.1279272293,95.0935763647,95.0593425426,95.0252250121,94.9912230293, + 94.957335857,94.9235627648,94.889903029,94.8563559325,94.8229207645, + 94.7895968211,94.7563834042,94.7232798225,94.6902853904,94.6573994289, + 94.6246212649,94.5919502312,94.5593856666,94.5269269159,94.4945733296, + 94.4623242638,94.4301790804,94.398137147,94.3661978366,94.3343605276, + 94.3026246041,94.2709894553,94.2394544758,94.2080190654,94.1766826291, + 94.145444577,94.1143043243,94.0832612913,94.052314903,94.0214645895, + 93.9907097857,93.9600499313,93.9294844707,93.899012853,93.8686345319, + 93.8383489659,93.8081556177,93.7780539548,93.7480434489,93.7181235762, + 93.6882938173,93.658553657,93.6289025843,93.5993400927,93.5698656795, + 93.5404788464,93.5111790989,93.4819659468,93.4528389037,93.4237974873, + 93.3948412191,93.3659696245,93.3371822327,93.3084785767,93.2798581933, + 93.2513206229,93.2228654096,93.1944921013,93.1662002492,93.1379894083, + 93.109859137,93.0818089971,93.0538385542,93.0259473769,92.9981350374, + 92.9704011112,92.9427451771,92.9151668171,92.8876656167,92.8602411644, + 92.8328930518,92.8056208739,92.7784242286,92.7513027171,92.7242559433, + 92.6972835146,92.670385041,92.6435601356,92.6168084145,92.5901294966, + 92.5635230038,92.5369885607,92.5105257949,92.4841343366,92.4578138189, + 92.4315638777,92.4053841514,92.3792742812,92.353233911,92.3272626873, + 92.3013602592,92.2755262785,92.2497603994,92.2240622787,92.1984315757, + 92.1728679522,92.1473710724,92.1219406032,92.0965762136,92.0712775751, + 92.0460443617,92.0208762495,91.9957729173,91.9707340457,91.9457593182, + 91.9208484199,91.8960010388,91.8712168645,91.8464955894,91.8218369075, + 91.7972405155,91.7727061118,91.7482333973,91.7238220746,91.6994718488, + 91.6751824268,91.6509535176,91.6267848322,91.6026760837,91.5786269871, + 91.5546372594,91.5307066197,91.5068347888,91.4830214895,91.4592664466, + 91.4355693866,91.4119300382,91.3883481315,91.3648233988,91.3413555741, + 91.3179443931,91.2945895935,91.2712909146,91.2480480975,91.224860885, + 91.2017290219,91.1786522542,91.1556303301,91.1326629992,91.1097500128, + 91.086891124,91.0640860873,91.041334659,91.0186365969,90.9959916605, + 90.9733996109,90.9508602106,90.9283732238,90.9059384162,90.883555555, + 90.8612244091,90.8389447485,90.8167163451,90.7945389721,90.7724124041, + 90.7503364174,90.7283107894,90.7063352991,90.6844097271,90.6625338551, + 90.6407074663,90.6189303453,90.5972022781,90.5755230521,90.5538924558, + 90.5323102793,90.510776314,90.4892903525,90.4678521887,90.4464616179, + 90.4251184365,90.4038224425,90.3825734349,90.3613712139,90.3402155812, + 90.3191063395,90.2980432928,90.2770262463,90.2560550065,90.2351293809, + 90.2142491783,90.1934142087,90.1726242833,90.1518792142,90.131178815, + 90.1105229001,90.0899112853,90.0693437874,90.0488202242,90.0283404148, + 90.0079041793,89.9875113389,89.9671617157,89.9468551333,89.9265914158, + 89.9063703888,89.8861918787,89.866055713,89.8459617203,89.8259097301, + 89.8058995729,89.7859310803,89.7660040849,89.7461184201,89.7262739206, + 89.7064704217,89.68670776,89.6669857728,89.6473042984,89.6276631762, + 89.6080622464,89.5885013501,89.5689803294,89.5494990274,89.5300572878, + 89.5106549554,89.491291876,89.4719678961,89.4526828632,89.4334366256, + 89.4142290324,89.3950599338,89.3759291805,89.3568366244,89.3377821181, + 89.3187655149,89.2997866691,89.2808454357,89.2619416708,89.2430752308, + 89.2242459734,89.2054537569,89.1866984403,89.1679798834,89.1492979471, + 89.1306524926,89.1120433822,89.0934704789,89.0749336464,89.056432749, + 89.0379676522,89.0195382218,89.0011443245,88.9827858277,88.9644625997, + 88.9461745092,88.927921426,88.9097032202,88.8915197629,88.8733709258, + 88.8552565813,88.8371766024,88.8191308631,88.8011192377,88.7831416014, + 88.7651978299,88.7472877998,88.7294113881,88.7115684728,88.6937589321, + 88.6759826453,88.658239492,88.6405293526,88.6228521081,88.6052076403, + 88.5875958312,88.5700165638,88.5524697217,88.5349551889,88.5174728502, + 88.5000225908,88.4826042967,88.4652178545,88.4478631512,88.4305400746, + 88.413248513,88.3959883551,88.3787594905,88.3615618091,88.3443952016, + 88.3272595591,88.3101547733,88.2930807364,88.2760373414,88.2590244815, + 88.2420420507,88.2250899434,88.2081680546,88.1912762799,88.1744145152, + 88.1575826573,88.1407806031,88.1240082504,88.1072654973,88.0905522424, + 88.0738683849,88.0572138245,88.0405884613,88.0239921962,88.0074249301, + 87.9908865649,87.9743770026,87.9578961459,87.941443898,87.9250201625, + 87.9086248434,87.8922578454,87.8759190734,87.859608433,87.8433258301, + 87.8270711713,87.8108443633,87.7946453135,87.7784739298,87.7623301204, + 87.746213794,87.7301248597,87.7140632271,87.6980288064,87.6820215078, + 87.6660412424,87.6500879215,87.6341614567,87.6182617604,87.6023887451, + 87.5865423238,87.57072241,87.5549289176,87.5391617608,87.5234208543, + 87.5077061131,87.4920174528,87.4763547894,87.4607180389,87.4451071183, + 87.4295219444,87.4139624349,87.3984285076,87.3829200807,87.3674370729, + 87.3519794032,87.3365469909,87.321139756,87.3057576185,87.2904004989, + 87.2750683183,87.2597609977,87.2444784589,87.2292206238,87.2139874149, + 87.1987787547,87.1835945665,87.1684347736,87.1532992998,87.1381880693, + 87.1231010065,87.1080380363,87.0929990838,87.0779840746,87.0629929344, + 87.0480255896,87.0330819666,87.0181619923,87.0032655939,86.988392699, + 86.9735432353,86.9587171311,86.9439143149,86.9291347155,86.9143782621, + 86.899644884,86.8849345112,86.8702470738,86.855582502,86.8409407267, + 86.8263216789,86.81172529,86.7971514915,86.7826002155,86.7680713942, + 86.7535649602,86.7390808462,86.7246189855,86.7101793115,86.695761758, + 86.681366259,86.6669927487,86.6526411619,86.6383114334,86.6240034983, + 86.6097172923,86.5954527509,86.5812098103,86.5669884067,86.5527884768, + 86.5386099573,86.5244527855,86.5103168987,86.4962022346,86.4821087312, + 86.4680363266,86.4539849594,86.4399545682,86.4259450922,86.4119564705, + 86.3979886428,86.3840415487,86.3701151284,86.356209322,86.3423240703, + 86.328459314,86.3146149941,86.3007910521,86.2869874293,86.2732040677, + 86.2594409093,86.2456978963,86.2319749714,86.2182720773,86.204589157, + 86.1909261539,86.1772830113,86.1636596731,86.1500560831,86.1364721857, + 86.1229079253,86.1093632464,86.0958380941,86.0823324135,86.0688461498, + 86.0553792488,86.0419316561,86.0285033179,86.0150941804,86.0017041901, + 85.9883332936,85.9749814379,85.9616485701,85.9483346376,85.935039588, + 85.9217633689,85.9085059285,85.8952672149,85.8820471765,85.868845762, + 85.8556629201,85.8424986001,85.829352751,85.8162253223,85.8031162638, + 85.7900255253,85.7769530568,85.7638988086,85.7508627312,85.7378447752, + 85.7248448915,85.7118630312,85.6988991455,85.6859531858,85.6730251039, + 85.6601148515,85.6472223807,85.6343476437,85.6214905929,85.608651181, + 85.5958293606,85.5830250847,85.5702383066,85.5574689796,85.5447170572, + 85.531982493,85.5192652411,85.5065652554,85.4938824903,85.4812169001, + 85.4685684394,85.4559370631,85.4433227262,85.4307253837,85.4181449909, + 85.4055815034,85.3930348768,85.380505067,85.36799203,85.3554957218, + 85.3430160989,85.3305531178,85.3181067352,85.3056769079,85.2932635929, + 85.2808667474,85.2684863287,85.2561222943,85.243774602,85.2314432095, + 85.2191280748,85.2068291561,85.1945464117,85.1822798,85.1700292797, + 85.1577948095,85.1455763484,85.1333738555,85.1211872901,85.1090166115, + 85.0968617793,85.0847227531,85.0725994929,85.0604919587,85.0484001106, + 85.036323909,85.0242633142,85.0122182869,85.0001887879,84.988174778, + 84.9761762183,84.96419307,84.9522252944,84.940272853,84.9283357074, + 84.9164138193,84.9045071507,84.8926156637,84.8807393203,84.8688780829, + 84.8570319141,84.8452007763,84.8333846323,84.821583445,84.8097971774, + 84.7980257927,84.7862692541,84.7745275251,84.7628005691,84.7510883499, + 84.7393908313,84.7277079772,84.7160397517,84.7043861189,84.6927470434, + 84.6811224894,84.6695124216,84.6579168048,84.6463356037,84.6347687833, + 84.6232163088,84.6116781453,84.6001542582,84.588644613,84.5771491752, + 84.5656679107,84.5542007852,84.5427477647,84.5313088153,84.5198839031, + 84.5084729946,84.4970760562,84.4856930544,84.4743239558,84.4629687274, + 84.4516273361,84.4402997488,84.4289859327,84.4176858551,84.4063994834, + 84.395126785,84.3838677276,84.372622279,84.3613904068,84.3501720792, + 84.3389672641,84.3277759297,84.3165980443,84.3054335764,84.2942824943, + 84.2831447667,84.2720203625,84.2609092503,84.2498113991,84.238726778, + 84.2276553561,84.2165971027,84.2055519872,84.194519979,84.1835010476, + 84.1724951629,84.1615022946,84.1505224125,84.1395554866,84.1286014871, + 84.1176603842,84.1067321481,84.0958167492,84.0849141581,84.0740243453, + 84.0631472816,84.0522829378,84.0414312847,84.0305922934,84.0197659349, + 84.0089521804,83.9981510014,83.987362369,83.9765862548,83.9658226305, + 83.9550714676,83.944332738,83.9336064135,83.922892466,83.9121908677, + 83.9015015907,83.8908246072,83.8801598895,83.8695074102,83.8588671416, + 83.8482390564,83.8376231274,83.8270193272,83.8164276289,83.8058480053, + 83.7952804295,83.7847248747,83.774181314,83.763649721,83.7531300688, + 83.7426223311,83.7321264815,83.7216424936,83.7111703411,83.700709998, + 83.6902614382,83.6798246356,83.6693995644,83.6589861988,83.648584513, + 83.6381944814,83.6278160785,83.6174492788,83.6070940568,83.5967503873, + 83.586418245,83.5760976048,83.5657884417,83.5554907305,83.5452044465, + 83.5349295648,83.5246660606,83.5144139094,83.5041730864,83.4939435673, + 83.4837253275,83.4735183427,83.4633225887,83.4531380413,83.4429646763, + 83.4328024696,83.4226513974,83.4125114358,83.4023825609,83.392264749, + 83.3821579764,83.3720622196,83.361977455,83.3519036592,83.3418408089, + 83.3317888807,83.3217478514,83.3117176979,83.3016983972,83.2916899262, + 83.281692262,83.2717053817,83.2617292627,83.251763882,83.2418092172, + 83.2318652457,83.2219319449,83.2120092924,83.2020972659,83.1921958431, + 83.1823050018,83.1724247198,83.162554975,83.1526957454,83.1428470091, + 83.1330087443,83.123180929,83.1133635416,83.1035565603,83.0937599636, + 83.08397373,83.0741978379,83.064432266,83.0546769929,83.0449319973, + 83.035197258,83.0254727539,83.0157584639,83.006054367,82.9963604422, + 82.9866766686,82.9770030254,82.9673394918,82.9576860472,82.9480426709, + 82.9384093423,82.9287860409,82.9191727463,82.9095694381,82.8999760959, + 82.8903926995,82.8808192286,82.8712556633,82.8617019832,82.8521581685, + 82.8426241992,82.8331000553,82.8235857171,82.8140811647,82.8045863785, + 82.7951013386,82.7856260257,82.77616042,82.7667045022,82.7572582527, + 82.7478216522,82.7383946815,82.7289773211,82.719569552,82.710171355, + 82.700782711,82.6914036009,82.6820340059,82.6726739069,82.6633232851, + 82.6539821217,82.644650398,82.6353280953,82.6260151948,82.6167116781, + 82.6074175266,82.5981327217,82.5888572452,82.5795910786,82.5703342036, + 82.5610866019,82.5518482554,82.5426191458,82.5333992551,82.5241885652, + 82.5149870582,82.505794716,82.4966115208,82.4874374547,82.4782724999, + 82.4691166388,82.4599698535,82.4508321266,82.4417034403,82.4325837772, + 82.4234731197,82.4143714505,82.4052787521,82.3961950073,82.3871201986, + 82.378054309,82.3689973211,82.3599492179,82.3509099823,82.3418795973, + 82.3328580457,82.3238453108,82.3148413756,82.3058462233,82.296859837, + 82.2878822 + }}, + { // Ri = 250k + -5,5,200, { + 249.98706929,249.986851225,249.986629489,249.986404021,249.986174757, + 249.985941635,249.985704589,249.985463554,249.985218463,249.984969247, + 249.984715838,249.984458166,249.984196158,249.983929743,249.983658846, + 249.983383392,249.983103306,249.982818508,249.982528921,249.982234464, + 249.981935056,249.981630613,249.981321052,249.981006287,249.98068623, + 249.980360793,249.980029887,249.979693419,249.979351296,249.979003424, + 249.978649708,249.978290048,249.977924346,249.9775525,249.977174409, + 249.976789967,249.976399069,249.976001606,249.97559747,249.975186548, + 249.974768727,249.974343893,249.973911927,249.973472711,249.973026125, + 249.972572044,249.972110345,249.9716409,249.971163579,249.970678252, + 249.970184785,249.969683043,249.969172887,249.968654177,249.968126772, + 249.967590526,249.967045292,249.96649092,249.965927258,249.965354153, + 249.964771446,249.964178978,249.963576587,249.962964107,249.962341372, + 249.961708211,249.96106445,249.960409914,249.959744424,249.959067797, + 249.95837985,249.957680393,249.956969237,249.956246188,249.955511048, + 249.954763616,249.95400369,249.953231063,249.952445523,249.951646857, + 249.950834849,249.950009276,249.949169916,249.94831654,249.947448916, + 249.946566809,249.945669979,249.944758184,249.943831177,249.942888706, + 249.941930516,249.940956349,249.93996594,249.938959023,249.937935324, + 249.936894568,249.935836475,249.934760758,249.933667127,249.932555289, + 249.931424944,249.930275788,249.929107511,249.9279198,249.926712337, + 249.925484796,249.92423685,249.922968162,249.921678394,249.9203672, + 249.91903423,249.917679127,249.916301529,249.914901069,249.913477372, + 249.912030061,249.910558748,249.909063042,249.907542547,249.905996856, + 249.904425561,249.902828244,249.901204482,249.899553844,249.897875894, + 249.896170188,249.894436274,249.892673696,249.890881989,249.889060679, + 249.887209288,249.885327328,249.883414305,249.881469716,249.879493052, + 249.877483793,249.875441414,249.87336538,249.87125515,249.869110171, + 249.866929885,249.864713724,249.86246111,249.860171458,249.857844173, + 249.855478652,249.853074281,249.850630438,249.848146491,249.845621799, + 249.843055711,249.840447565,249.837796689,249.835102404,249.832364016, + 249.829580824,249.826752115,249.823877166,249.820955243,249.8179856, + 249.81496748,249.811900117,249.80878273,249.80561453,249.802394713, + 249.799122465,249.795796959,249.792417358,249.788982809,249.785492449, + 249.781945403,249.778340779,249.774677678,249.770955183,249.767172365, + 249.763328284,249.759421981,249.75545249,249.751418824,249.747319988, + 249.743154968,249.738922738,249.734622257,249.730252468,249.725812301, + 249.72130067,249.716716471,249.712058589,249.70732589,249.702517225, + 249.697631429,249.692667321,249.687623703,249.682499361,249.677293063, + 249.672003562,249.666629592,249.661169871,249.655623098,249.649987954, + 249.644263106,249.638447197,249.632538857,249.626536694,249.620439299, + 249.614245244,249.607953082,249.601561346,249.59506855,249.588473189, + 249.581773739,249.574968653,249.568056367,249.561035295,249.553903831, + 249.546660348,249.5393032,249.531830718,249.524241211,249.516532969, + 249.508704259,249.500753327,249.492678397,249.48447767,249.476149326, + 249.467691521,249.459102391,249.450380046,249.441522576,249.432528047, + 249.423394501,249.414119957,249.404702411,249.395139834,249.385430176, + 249.37557136,249.365561287,249.355397831,249.345078845,249.334602156, + 249.323965565,249.313166851,249.302203767,249.291074039,249.27977537, + 249.268305439,249.256661896,249.244842368,249.232844458,249.220665739, + 249.208303762,249.195756051,249.183020104,249.170093394,249.156973366, + 249.143657441,249.130143014,249.116427453,249.102508098,249.088382267, + 249.074047249,249.059500307,249.044738677,249.029759572,249.014560175, + 248.999137645,248.983489114,248.967611688,248.951502446,248.935158442, + 248.918576704,248.901754233,248.884688005,248.867374969,248.84981205, + 248.831996145,248.813924127,248.795592843,248.776999115,248.75813974, + 248.739011488,248.719611106,248.699935316,248.679980814,248.659744274, + 248.639222342,248.618411645,248.597308781,248.575910327,248.554212837, + 248.532212841,248.509906845,248.487291335,248.464362771,248.441117595, + 248.417552224,248.393663055,248.369446462,248.344898801,248.320016406, + 248.29479559,248.269232647,248.243323852,248.217065459,248.190453706, + 248.163484811,248.136154974,248.108460379,248.080397191,248.05196156, + 248.02314962,247.993957487,247.964381265,247.934417041,247.90406089, + 247.87330887,247.84215703,247.810601403,247.778638011,247.746262866, + 247.713471967,247.680261304,247.646626855,247.612564592,247.578070476, + 247.543140462,247.507770494,247.471956513,247.435694453,247.398980241, + 247.361809801,247.32417905,247.286083906,247.24752028,247.208484082, + 247.168971222,247.128977608,247.088499147,247.047531748,247.006071321, + 246.964113777,246.921655032,246.878691002,246.835217611,246.791230786, + 246.746726458,246.701700567,246.656149059,246.610067888,246.563453016, + 246.516300415,246.468606067,246.420365965,246.371576112,246.322232525, + 246.272331233,246.22186828,246.170839723,246.119241635,246.067070105, + 246.014321238,245.960991158,245.907076005,245.85257194,245.797475142, + 245.741781811,245.685488168,245.628590456,245.57108494,245.512967909, + 245.454235673,245.394884571,245.334910963,245.274311238,245.213081809, + 245.151219118,245.088719633,245.025579852,244.961796302,244.897365539, + 244.832284149,244.76654875,244.70015599,244.633102551,244.565385144, + 244.497000518,244.427945453,244.358216762,244.287811295,244.216725936, + 244.144957607,244.072503262,243.999359895,243.925524536,243.850994253, + 243.775766153,243.699837378,243.623205113,243.545866579,243.467819039, + 243.389059794,243.309586187,243.2293956,243.148485458,243.066853225, + 242.984496408,242.901412556,242.817599259,242.733054149,242.647774903, + 242.561759239,242.475004919,242.387509745,242.299271568,242.210288277, + 242.120557808,242.03007814,241.938847296,241.846863343,241.75412439, + 241.660628595,241.566374155,241.471359316,241.375582364,241.279041632, + 241.181735498,241.083662381,240.984820749,240.88520911,240.78482602, + 240.683670075,240.581739919,240.479034238,240.375551763,240.271291268, + 240.166251571,240.060431535,239.953830064,239.846446107,239.738278656, + 239.629326745,239.519589453,239.4090659,239.297755248,239.185656702, + 239.072769509,238.959092958,238.84462638,238.729369145,238.613320666, + 238.496480396,238.37884783,238.260422501,238.141203983,238.02119189, + 237.900385875,237.778785628,237.656390882,237.533201405,237.409217004, + 237.284437524,237.158862846,237.03249289,236.905327613,236.777367005, + 236.648611095,236.519059947,236.38871366,236.257572368,236.125636239, + 235.992905475,235.859380313,235.725061022,235.589947905,235.454041297, + 235.317341565,235.179849108,235.041564357,234.902487774,234.762619849, + 234.621961106,234.480512096,234.338273402,234.195245633,234.051429428, + 233.906825454,233.761434407,233.615257009,233.468294009,233.320546182, + 233.172014331,233.022699284,232.872601892,232.721723035,232.570063615, + 232.417624559,232.264406816,232.110411361,231.955639189,231.800091321, + 231.643768797,231.486672681,231.328804057,231.17016403,231.010753726, + 230.850574292,230.689626893,230.527912715,230.365432962,230.202188857, + 230.038181642,229.873412577,229.707882938,229.541594019,229.374547132, + 229.206743604,229.038184779,228.868872017,228.698806692,228.527990194, + 228.356423928,228.184109314,228.011047785,227.837240787,227.662689782, + 227.487396243,227.311361655,227.134587519,226.957075345,226.778826655, + 226.599842984,226.420125878,226.239676893,226.058497596,225.876589564, + 225.693954385,225.510593656,225.326508984,225.141701984,224.956174281, + 224.769927509,224.58296331,224.395283333,224.206889237,224.017782686, + 223.827965353,223.637438918,223.446205069,223.254265497,223.061621903, + 222.868275994,222.674229479,222.479484077,222.284041512,222.08790351, + 221.891071805,221.693548135,221.495334244,221.296431876,221.096842785, + 220.896568725,220.695611455,220.493972738,220.29165434,220.08865803, + 219.88498558,219.680638766,219.475619366,219.269929161,219.063569932, + 218.856543466,218.648851549,218.440495971,218.231478522,218.021800994, + 217.811465182,217.60047288,217.388825884,217.176525993,216.963575003, + 216.749974714,216.535726925,216.320833437,216.105296048,215.88911656, + 215.672296774,215.45483849,215.236743508,215.018013629,214.798650652, + 214.578656378,214.358032605,214.136781131,213.914903754,213.692402271, + 213.469278477,213.245534168,213.021171136,212.796191175,212.570596077, + 212.344387629,212.117567622,211.890137843,211.662100076,211.433456105, + 211.204207714,210.974356681,210.743904787,210.512853806,210.281205515, + 210.048961685,209.816124088,209.582694492,209.348674664,209.114066368, + 208.878871366,208.643091418,208.406728281,208.169783711,207.93225946, + 207.694157278,207.455478915,207.216226114,206.97640062,206.736004172, + 206.49503851,206.253505367,206.011406477,205.768743571,205.525518376, + 205.281732618,205.037388018,204.792486297,204.547029172,204.301018358, + 204.054455568,203.80734251,203.559680893,203.31147242,203.062718793, + 202.813421712,202.563582874,202.313203973,202.062286701,201.810832747, + 201.558843799,201.306321542,201.053267658,200.799683826,200.545571726, + 200.290933032,200.035769418,199.780082556,199.523874114,199.26714576, + 199.00989916,198.752135977,198.493857873,198.235066508,197.97576354, + 197.715950626,197.455629421,197.19480158,196.933468754,196.671632596, + 196.409294756,196.146456882,195.883120624,195.619287629,195.354959544, + 195.090138015,194.824824689,194.559021212,194.292729229,194.025950385, + 193.758686328,193.490938703,193.222709157,192.953999338,192.684810894, + 192.415145475,192.145004731,191.874390314,191.603303879,191.331747082, + 191.059721579,190.787229033,190.514271105,190.240849462,189.966965773, + 189.69262171,189.417818949,189.14255917,188.866844059,188.590675304, + 188.314054599,188.036983645,187.759464146,187.481497813,187.203086365, + 186.924231527,186.64493503,186.365198614,186.085024028,185.804413028, + 185.523367379,185.241888858,184.95997925,184.677640352,184.394873972, + 184.11168193,183.828066057,183.544028199,183.259570217,182.974693983, + 182.689401387,182.403694334,182.117574747,181.831044563,181.544105742, + 181.25676026,180.969010115,180.680857324,180.392303929,180.103351992, + 179.814003602,179.524260869,179.234125934,178.943600962,178.652688148, + 178.361389716,178.069707923,177.777645057,177.485203439,177.192385426, + 176.899193414,176.605629834,176.311697159,176.017397903,175.722734622, + 175.42770992,175.132326446,174.836586898,174.540494025,174.244050629, + 173.947259568,173.650123755,173.352646164,173.054829832,172.756677859, + 172.458193411,172.159379726,171.860240112,171.560777954,171.260996712, + 170.960899932,170.660491239,170.359774348,170.058753063,169.757431286, + 169.455813011,169.153902337,168.851703468,168.549220714,168.246458503, + 167.943421374,167.640113993,167.336541149,167.032707762,166.728618886, + 166.424279716,166.119695592,165.814872003,165.509814594,165.204529171, + 164.899021704,164.593298336,164.287365388,163.981229364,163.674896958, + 163.36837506,163.061670761,162.754791362,162.447744379,162.140537551, + 161.833178847,161.525676469,161.218038867,160.91027474,160.602393044, + 160.294403003,159.986314114,159.678136154,159.369879193,159.061553594, + 158.753170027,158.444739474,158.13627324,157.827782957,157.519280595, + 157.21077847,156.90228925,156.593825964,156.285402011,155.977031166, + 155.668727586,155.360505823,155.052380826,154.744367948,154.436482957, + 154.128742038,153.821161801,153.513759285,153.206551968,152.899557763, + 152.592795032,152.286282581,151.980039672,151.674086016,151.368441781, + 151.063127591,150.758164527,150.453574123,150.149378371,149.84559971, + 149.542261029,149.239385659,148.936997368,148.635120356,148.333779243, + 148.032999061,147.732805244,147.433223619,147.134280384,146.836002101, + 146.538415678,146.241548349,145.945427656,145.650081429,145.355537765, + 145.061825,144.768971689,144.477006578,144.185958573,143.895856717, + 143.606730155,143.318608101,143.031519811,142.745494544,142.460561528, + 142.176749925,141.894088794,141.612607053,141.33233344,141.053296478, + 140.775524432,140.499045269,140.223886626,139.950075761,139.677639521, + 139.406604303,139.13699601,138.86884002,138.602161147,138.336983605, + 138.073330973,137.811226163,137.550691387,137.291748127,137.034417106, + 136.778718261,136.524670718,136.272292766,136.021601842,135.772614503, + 135.525346418,135.279812345,135.036026122,134.79400066,134.553747926, + 134.315278945,134.078603792,133.843731591,133.610670518,133.379427799, + 133.150009719,132.922421627,132.696667945,132.472752176,132.25067692, + 132.030443888,131.812053912,131.595506968,131.380802191,131.167937895, + 130.956911595,130.747720026,130.540359167,130.334824266,130.13110986, + 129.929209804,129.729117294,129.53082489,129.334324549,129.139607641, + 128.946664984,128.755486867,128.566063074,128.378382911,128.192435235, + 128.008208475,127.82569066,127.644869442,127.465732122,127.288265674, + 127.112456765,126.938291784,126.765756859,126.594837879,126.425520519, + 126.257790258,126.091632396,125.92703208,125.763974314,125.602443985, + 125.442425874,125.283904673,125.126865007,124.971291439,124.817168494, + 124.664480664,124.51321243,124.363348265,124.214872655,124.067770102, + 123.922025141,123.777622345,123.634546339,123.492781803,123.352313488, + 123.213126215,123.075204892,122.938534511,122.803100162,122.668887034, + 122.535880424,122.404065739,122.273428504,122.143954363,122.015629084, + 121.888438563,121.76236883,121.637406044,121.513536504,121.390746648, + 121.269023054,121.148352444,121.028721683,120.910117783,120.792527903, + 120.675939349,120.560339577,120.445716191,120.332056945,120.219349742, + 120.107582636,119.996743831,119.886821679,119.777804682,119.669681491, + 119.562440905,119.45607187,119.350563481,119.245904975,119.142085739, + 119.039095299,118.936923328,118.835559639,118.734994187,118.635217064, + 118.536218503,118.437988872,118.340518677,118.243798555,118.147819277, + 118.052571748,117.958046998,117.864236189,117.771130609,117.678721671, + 117.587000912,117.495959991,117.405590688,117.315884902,117.226834649, + 117.138432063,117.050669391,116.963538993,116.87703334,116.791145014, + 116.705866704,116.621191207,116.537111424,116.453620361,116.370711124, + 116.288376922,116.206611062,116.125406949,116.044758083,115.964658061, + 115.885100572,115.806079397,115.727588408,115.649621564,115.572172916, + 115.495236596,115.418806826,115.342877908,115.267444229,115.192500255, + 115.118040534,115.04405969,114.970552425,114.89751352,114.824937826, + 114.752820271,114.681155856,114.60993965,114.539166794,114.4688325, + 114.398932045,114.329460774,114.260414097,114.191787491,114.123576494, + 114.055776708,113.988383796,113.921393483,113.854801553,113.788603846, + 113.722796265,113.657374766,113.592335361,113.527674118,113.463387161, + 113.399470663,113.335920853,113.27273401,113.209906463,113.147434593, + 113.085314829,113.023543648,112.962117574,112.901033179,112.840287082, + 112.779875944,112.719796474,112.660045423,112.600619585,112.541515797, + 112.482730939,112.42426193,112.36610573,112.308259341,112.250719802, + 112.19348419,112.136549623,112.079913253,112.023572271,111.967523904, + 111.911765414,111.856294098,111.801107289,111.746202353,111.691576689, + 111.637227729,111.583152939,111.529349816,111.475815888,111.422548715, + 111.369545886,111.316805023,111.264323773,111.212099817,111.160130862, + 111.108414643,111.056948924,111.005731497,110.954760178,110.904032814, + 110.853547274,110.803301456,110.75329328,110.703520696,110.653981674, + 110.60467421,110.555596324,110.50674606,110.458121485,110.409720688, + 110.361541782,110.313582902,110.265842202,110.218317863,110.171008082, + 110.123911081,110.077025099,110.030348399,109.983879261,109.937615986, + 109.891556896,109.845700329,109.800044645,109.754588221,109.709329453, + 109.664266754,109.619398556,109.57472331,109.530239481,109.485945553, + 109.441840028,109.397921423,109.354188272,109.310639125,109.267272548, + 109.224087122,109.181081447,109.138254133,109.095603809,109.053129118, + 109.010828717,108.968701278,108.926745487,108.884960045,108.843343665, + 108.801895077,108.760613021,108.719496253,108.67854354,108.637753663, + 108.597125417,108.556657609,108.516349056,108.476198591,108.436205057, + 108.39636731,108.356684217,108.317154657,108.277777521,108.238551712, + 108.199476141,108.160549735,108.121771427,108.083140165,108.044654905, + 108.006314614,107.96811827,107.930064861,107.892153386,107.854382852, + 107.816752278,107.77926069,107.741907128,107.704690637,107.667610274, + 107.630665104,107.593854203,107.557176653,107.520631548,107.48421799, + 107.447935087,107.41178196,107.375757736,107.339861549,107.304092545, + 107.268449875,107.2329327,107.197540188,107.162271514,107.127125864, + 107.092102428,107.057200405,107.022419004,106.987757437,106.953214926, + 106.9187907,106.884483995,106.850294054,106.816220127,106.78226147, + 106.748417348,106.714687031,106.681069796,106.647564927,106.614171713, + 106.580889453,106.547717448,106.514655009,106.48170145,106.448856093, + 106.416118267,106.383487304,106.350962545,106.318543335,106.286229026, + 106.254018974,106.221912543,106.189909101,106.158008021,106.126208684, + 106.094510473,106.06291278,106.031414999,106.000016532,105.968716784, + 105.937515166,105.906411094,105.87540399,105.844493279,105.813678393, + 105.782958766,105.752333841,105.721803061,105.691365878,105.661021745, + 105.630770122,105.600610472,105.570542264,105.540564971,105.51067807, + 105.480881041,105.451173372,105.421554551,105.392024073,105.362581436, + 105.333226143,105.3039577,105.274775617,105.245679411,105.216668597, + 105.1877427,105.158901246,105.130143764,105.101469788,105.072878857, + 105.04437051,105.015944294,104.987599757,104.959336451,104.931153932, + 104.903051759,104.875029495,104.847086706,104.819222962,104.791437835, + 104.763730902,104.736101743,104.708549941,104.681075081,104.653676754, + 104.626354551,104.599108068,104.571936905,104.544840663,104.517818946, + 104.490871364,104.463997527,104.437197048,104.410469545,104.383814638, + 104.357231948,104.330721102,104.304281728,104.277913457,104.251615922, + 104.225388761,104.199231613,104.173144119,104.147125925,104.121176677, + 104.095296026,104.069483624,104.043739125,104.018062189,103.992452474, + 103.966909643,103.941433361,103.916023296,103.890679118,103.865400498, + 103.840187112,103.815038637,103.789954751,103.764935137,103.739979478, + 103.715087461,103.690258774,103.665493107,103.640790154,103.616149609, + 103.59157117,103.567054536,103.542599408,103.51820549,103.493872487, + 103.469600108,103.445388062,103.42123606,103.397143817,103.373111047, + 103.34913747,103.325222804,103.301366771,103.277569095,103.253829501, + 103.230147716,103.206523469,103.182956493,103.159446518,103.13599328, + 103.112596516,103.089255964,103.065971363,103.042742456,103.019568986, + 102.996450698,102.97338734,102.950378659,102.927424406,102.904524334, + 102.881678195,102.858885746,102.836146742,102.813460943,102.790828108, + 102.768247999,102.74572038,102.723245015,102.700821671,102.678450115, + 102.656130116,102.633861446,102.611643877,102.589477183,102.567361139, + 102.545295522,102.523280109,102.501314681,102.479399019,102.457532905, + 102.435716122,102.413948457,102.392229695,102.370559624,102.348938035, + 102.327364716,102.305839461,102.284362062,102.262932314,102.241550013, + 102.220214956,102.198926941,102.177685768,102.156491237,102.135343152, + 102.114241314,102.093185529,102.072175603,102.051211342,102.030292555, + 102.009419051,101.98859064,101.967807134,101.947068347,101.926374091, + 101.905724182,101.885118436,101.864556671,101.844038704,101.823564356, + 101.803133447,101.782745799,101.762401235,101.742099578,101.721840653, + 101.701624287,101.681450305,101.661318537,101.641228811,101.621180958, + 101.601174808,101.581210193,101.561286947,101.541404903,101.521563896, + 101.501763763,101.482004341,101.462285466,101.442606979,101.422968719, + 101.403370526,101.383812242,101.36429371,101.344814774,101.325375276, + 101.305975064,101.286613983,101.267291879,101.248008601,101.228763999, + 101.20955792,101.190390216,101.171260738,101.152169339,101.133115871, + 101.114100189,101.095122146,101.076181599,101.057278403,101.038412416, + 101.019583497,101.000791503,100.982036294,100.96331773,100.944635673, + 100.925989984,100.907380526,100.888807163,100.870269758,100.851768177, + 100.833302284,100.814871947,100.796477033,100.778117409,100.759792944, + 100.741503507,100.723248969,100.705029199,100.68684407,100.668693453, + 100.650577222,100.632495249,100.614447409,100.596433577,100.578453629, + 100.56050744,100.542594887,100.524715848,100.506870202,100.489057826, + 100.471278601,100.453532406,100.435819123,100.418138632,100.400490816, + 100.382875557,100.365292739,100.347742246,100.330223961,100.312737771, + 100.29528356,100.277861215,100.260470623,100.243111672,100.225784249, + 100.208488243,100.191223543,100.17399004,100.156787623,100.139616184, + 100.122475614,100.105365804,100.088286649,100.07123804,100.054219871, + 100.037232038,100.020274434,100.003346955,99.9864494965,99.9695819554, + 99.9527442284,99.935936213,99.9191578071,99.9024089092,99.8856894183, + 99.8689992338,99.8523382559,99.8357063851,99.8191035222,99.8025295689, + 99.7859844271,99.7694679993,99.7529801885,99.7365208981,99.7200900321, + 99.7036874949,99.6873131914,99.6709670269,99.6546489073,99.6383587388, + 99.6220964281,99.6058618826,99.5896550097,99.5734757178,99.5573239152, + 99.5411995111,99.5251024149,99.5090325364,99.492989786,99.4769740745, + 99.460985313,99.4450234132,99.4290882872,99.4131798474,99.3972980067, + 99.3814426785,99.3656137764,99.3498112147,99.3340349078,99.3182847708, + 99.3025607191,99.2868626683,99.2711905347,99.2555442348,99.2399236857, + 99.2243288047,99.2087595095,99.1932157183,99.1776973497,99.1622043225, + 99.146736556,99.1312939699,99.1158764842,99.1004840195,99.0851164964, + 99.0697738362,99.0544559603,99.0391627907,99.0238942497,99.0086502598, + 98.993430744,98.9782356258,98.9630648287,98.9479182768,98.9327958945, + 98.9176976065,98.902623338,98.8875730143,98.8725465613,98.857543905, + 98.8425649718,98.8276096887,98.8126779826,98.7977697811,98.7828850119, + 98.7680236031,98.7531854831,98.7383705808,98.7235788251,98.7088101455, + 98.6940644717,98.6793417336,98.6646418617,98.6499647867,98.6353104394, + 98.6206787511,98.6060696534,98.5914830783,98.5769189578,98.5623772246, + 98.5478578113,98.533360651,98.5188856772,98.5044328236,98.490002024, + 98.4755932127,98.4612063243,98.4468412937,98.4324980559,98.4181765464, + 98.4038767008,98.3895984552,98.3753417457,98.361106509,98.3468926817, + 98.332700201,98.3185290043,98.3043790291,98.2902502133,98.2761424952, + 98.2620558131,98.2479901058,98.2339453121,98.2199213714,98.205918223, + 98.1919358068,98.1779740627,98.164032931,98.1501123522,98.136212267, + 98.1223326165,98.108473342,98.0946343849,98.080815687,98.0670171904, + 98.0532388372,98.03948057,98.0257423315,98.0120240648,97.9983257129, + 97.9846472195,97.9709885281,97.9573495827,97.9437303276,97.930130707, + 97.9165506656,97.9029901484,97.8894491003,97.8759274667,97.8624251931, + 97.8489422254,97.8354785095,97.8220339916,97.8086086182,97.795202336, + 97.7818150918,97.7684468328,97.7550975062,97.7417670596,97.7284554407, + 97.7151625976,97.7018884783,97.6886330313,97.6753962052,97.6621779488, + 97.648978211,97.6357969412,97.6226340887,97.6094896032,97.5963634346, + 97.5832555327,97.570165848,97.5570943308,97.5440409318,97.5310056019, + 97.5179882919,97.5049889533,97.4920075374,97.4790439958,97.4660982804, + 97.4531703431,97.4402601362,97.427367612,97.4144927232,97.4016354224, + 97.3887956627,97.3759733971,97.3631685791,97.350381162,97.3376110997, + 97.3248583459,97.3121228548,97.2994045805,97.2867034775,97.2740195003, + 97.2613526038,97.2487027429,97.2360698727,97.2234539485,97.2108549257, + 97.1982727601,97.1857074075,97.1731588237,97.1606269651,97.1481117878, + 97.1356132485,97.1231313037,97.1106659104,97.0982170254,97.0857846061, + 97.0733686096,97.0609689935,97.0485857155,97.0362187333,97.0238680049, + 97.0115334885,96.9992151424,96.9869129251,96.974626795,96.9623567111, + 96.9501026322,96.9378645174,96.925642326,96.9134360174,96.901245551, + 96.8890708866,96.8769119841,96.8647688034,96.8526413048,96.8405294484, + 96.8284331947,96.8163525044,96.8042873382,96.792237657,96.7802034217, + 96.7681845937,96.7561811342,96.7441930046,96.7322201667,96.7202625821, + 96.7083202128,96.6963930208,96.6844809683,96.6725840175,96.660702131, + 96.6488352713,96.6369834012,96.6251464835,96.6133244813,96.6015173576, + 96.5897250758,96.5779475993,96.5661848916,96.5544369164,96.5427036375, + 96.5309850188,96.5192810244,96.5075916186,96.4959167655,96.4842564298, + 96.472610576,96.4609791688,96.449362173,96.4377595536,96.4261712758, + 96.4145973047,96.4030376057,96.3914921443,96.379960886,96.3684437966, + 96.3569408419,96.3454519879,96.3339772007,96.3225164464,96.3110696914, + 96.2996369022,96.2882180452,96.2768130873,96.2654219951,96.2540447357, + 96.242681276,96.2313315832,96.2199956245,96.2086733674,96.1973647793, + 96.1860698279,96.1747884809,96.1635207061,96.1522664715,96.1410257451, + 96.1297984951,96.1185846898,96.1073842976,96.096197287,96.0850236266, + 96.0738632851,96.0627162315,96.0515824345,96.0404618634,96.0293544871, + 96.018260275,96.0071791965,95.9961112211,95.9850563182,95.9740144577, + 95.9629856092,95.9519697427,95.9409668282,95.9299768358,95.9189997356, + 95.908035498,95.8970840934,95.8861454923,95.8752196653,95.8643065831, + 95.8534062165,95.8425185365,95.8316435139,95.82078112,95.8099313258, + 95.7990941028,95.7882694223,95.7774572558,95.7666575748,95.7558703512, + 95.7450955566,95.7343331628,95.723583142,95.7128454661,95.7021201073, + 95.6914070379,95.6807062301,95.6700176564,95.6593412894,95.6486771016, + 95.6380250658,95.6273851547,95.6167573413,95.6061415985,95.5955378994, + 95.5849462171,95.5743665249,95.5637987962,95.5532430042,95.5426991226, + 95.532167125,95.521646985,95.5111386764,95.500642173,95.4901574488, + 95.4796844778,95.4692232342,95.4587736921,95.4483358257,95.4379096096, + 95.4274950181,95.4170920257,95.406700607,95.3963207368,95.3859523898, + 95.375595541,95.3652501651,95.3549162373,95.3445937326,95.3342826263, + 95.3239828935,95.3136945097,95.3034174503,95.2931516907,95.2828972066, + 95.2726539735,95.2624219673,95.2522011637,95.2419915386,95.231793068, + 95.221605728,95.2114294947,95.2012643442,95.1911102528,95.1809671969, + 95.1708351529,95.1607140973,95.1506040066,95.1405048576,95.1304166269, + 95.1203392913,95.1102728277,95.100217213,95.0901724243,95.0801384386, + 95.070115233,95.0601027849,95.0501010715,95.0401100701,95.0301297583, + 95.0201601135,95.0102011132,95.0002527353,94.9903149573,94.9803877571, + 94.9704711125,94.9605650015,94.950669402,94.9407842921,94.93090965, + 94.9210454538,94.9111916818,94.9013483124,94.8915153239,94.8816926949, + 94.8718804038,94.8620784292,94.8522867499,94.8425053445,94.8327341919, + 94.8229732708,94.8132225604,94.8034820394,94.793751687,94.7840314824, + 94.7743214046,94.7646214329,94.7549315467,94.7452517252,94.7355819481, + 94.7259221946,94.7162724445,94.7066326772,94.6970028726,94.6873830104, + 94.6777730702,94.6681730321,94.658582876,94.6490025817,94.6394321295, + 94.6298714993,94.6203206714,94.610779626,94.6012483433,94.5917268037, + 94.5822149877,94.5727128756,94.563220448,94.5537376855,94.5442645687, + 94.5348010783,94.525347195,94.5159028997,94.5064681732,94.4970429965, + 94.4876273505,94.4782212162,94.4688245748,94.4594374074,94.4500596952, + 94.4406914195,94.4313325615,94.4219831026,94.4126430243,94.403312308, + 94.3939909353,94.3846788878,94.375376147,94.3660826947,94.3567985126, + 94.3475235826,94.3382578864,94.329001406,94.3197541234,94.3105160205, + 94.3012870794,94.2920672823,94.2828566112,94.2736550485,94.2644625763, + 94.255279177,94.2461048331,94.2369395268,94.2277832407,94.2186359572, + 94.2094976591,94.2003683288,94.1912479492,94.1821365028,94.1730339724, + 94.163940341,94.1548555913,94.1457797063,94.136712669,94.1276544623, + 94.1186050694,94.1095644733,94.1005326572,94.0915096044,94.082495298, + 94.0734897214,94.064492858,94.0555046911,94.0465252043,94.0375543809, + 94.0285922045,94.0196386587,94.0106937272,94.0017573936,93.9928296417, + 93.9839104552,93.974999818,93.9660977138,93.9572041267,93.9483190405, + 93.9394424393,93.9305743071,93.921714628,93.9128633861,93.9040205657, + 93.8951861508,93.8863601258,93.8775424751,93.8687331828,93.8599322335, + 93.8511396116,93.8423553016,93.8335792879,93.8248115552,93.816052088, + 93.8073008711,93.798557889,93.7898231266,93.7810965686,93.7723781999, + 93.7636680053 + }} +}; + + +inline float Ftube(int table, float Vgk) +{ + struct table1d& tab = tubetable[table]; + float f = (Vgk - tab.low) * tab.istep; + int i = int(f); + if (i < 0) + return tab.data[0]; + if (i >= TAB_SIZE-1) + return tab.data[TAB_SIZE-1]; + f -= i; + return tab.data[i]*(1-f) + tab.data[i+1]*f; +} + + + + diff --git a/src/gx_faust_includes.cc b/src/gx_faust_includes.cc new file mode 100644 index 0000000..248689a --- /dev/null +++ b/src/gx_faust_includes.cc @@ -0,0 +1,435 @@ +/* + * Copyright (C) 2009-2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -------------------------------------------------------------------------- + * + * + * definitions for code generated with faust / dsp2cc + * part of gx_engine_audio.cpp + * + * -------------------------------------------------------------------------- + */ + +/**************************************************************** + ** functions and variables used by faust dsp files + */ + +inline float sigmoid(float x) +{ + return x*(1.5f - 0.5f*x*x); +} + +inline float saturate(float x, float t) +{ + if (fabs(x) 0.f) + return t + (1.f-t)*sigmoid((x-t)/((1-t)*1.5f)); + else + return -(t + (1.f-t)*sigmoid((-x-t)/((1-t)*1.5f))); + } +} + +inline float hard_cut(float in, float threshold) +{ + if ( in > threshold) { + in = threshold; + } else if ( in < -threshold) { + in = -threshold; + } + + return in; +} + +inline float foldback(float in, float threshold) +{ + if (threshold == 0) threshold = 0.01f; + + if (fabs(in) > threshold) { + in = fabs(fabs(fmod(in - threshold, threshold*4)) - threshold*2) - threshold; + } + return in; +} + +inline float fold(float threshold, float v) +{ + // switch between hard_cut or foldback distortion, or plain output + switch ((int)audio.ffuse) { + case 0: + break; + case 1: + v = hard_cut(saturate(v,threshold),threshold); + break; + case 2: + v = foldback(v,threshold); + break; + } + return v; +} + +inline float add_dc (float val) +{ + return val + 1e-20; // avoid denormals +} + +// foreign variable added to faust module feed +// it's set in process_buffers() +namespace feed { float ngate = 1; } // noise-gate, modifies output gain + +/**************************************************************** + ** definitions for code generated with faust / dsp2cc + */ + +typedef void (*inifunc)(int); + +typedef struct { + inifunc func; + const char *name; +} inidef; + +list inilist; + +float& get_alias(const char *id) +{ + static float dummy; + if (!gx_gui::parameter_map.hasId(id)) { + gx_system::gx_print_error("engine", string("can't define alias for unknown (or not yet defined) parameter id: ") + id); + return dummy; + } else { + return gx_gui::parameter_map[id].getFloat().value; + } +} + +void registerVar(const char* id, const char* name, const char* tp, + const char* tooltip, float* var, float val=0, + float low=0, float up=0, float step=0, bool exp=false) +{ + if (!name[0]) { + assert(strrchr(id, '.')); + name = strrchr(id, '.')+1; + } + gx_gui::parameter_map.insert( + new gx_gui::FloatParameter( + id, name, gx_gui::Parameter::Continuous, true, *var, val, low, up, step, true, exp)); +} + +void registerEnumVar(const char *id, const char* name, const char* tp, + const char* tooltip, const char** values, float *var, float val, + float low=0, float up=0, float step=1, bool exp=false) +{ + if (!name[0]) { + assert(strrchr(id, '.')); + name = strrchr(id, '.')+1; + } + assert(low == 0.0 && step == 1.0); + gx_gui::FloatEnumParameter *p = new gx_gui::FloatEnumParameter( + id, name, values, true, *var, val, true, exp); + assert(up == p->upper); // calculated by constructor + gx_gui::parameter_map.insert(p); +} + +inline void registerIntParam(const char*a,const char*b,int*c,int std=0,int lower=0,int upper=1,bool exp=false) + { + gx_gui::parameter_map.insert(new gx_gui::IntParameter(a,b,gx_gui::Parameter::Enum,true,*c,std,lower,upper,true,exp)); + } + +void registerInit(const char *name, inifunc f) +{ + inidef i; + i.func = f; + i.name = name; + inilist.push_back(i); +} + +void jack_sync() +{ + while (sem_wait(&gx_jack::jack_sync_sem) == EINTR); +} + +#define max(x,y) (((x)>(y)) ? (x) : (y)) +#define min(x,y) (((x)<(y)) ? (x) : (y)) + +template inline float faustpower(float x) { return powf(x,N); } +template inline double faustpower(double x) { return pow(x,N); } +template inline int faustpower(int x) { return faustpower(x) * faustpower(x); } +template <> inline int faustpower<0>(int x) { return 1; } +template <> inline int faustpower<1>(int x) { return x; } +#define FAUSTFLOAT float + +/**************************************************************** + ** include faust/dsp2cc generated files + */ + +// amp +#include "faust-cc/amp2.cc" +#include "faust-cc/stage3.cc" +#include "faust-cc/preamp.cc" +#include "faust-cc/inputgain.cc" +#include "faust-cc/noise_shaper.cc" +#include "faust-cc/AntiAlias.cc" +#include "faust-cc/HighShelf.cc" +#include "faust-cc/drive.cc" +#include "faust-cc/osc_tube.cc" +#include "faust-cc/reso_tube.cc" +#include "faust-cc/tube.cc" +#include "faust-cc/tubevibrato.cc" +#include "faust-cc/tonestack.cc" +#include "faust-cc/multifilter.cc" +#include "faust-cc/bassbooster.cc" +#include "faust-cc/feed.cc" +#include "faust-cc/outputgain.cc" +#include "faust-cc/balance.cc" +#include "faust-cc/jconv_post.cc" +#include "faust-cc/balance1.cc" +#include "faust-cc/eq.cc" +#include "faust-cc/tube3.cc" + + +// effects +#include "faust-cc/overdrive.cc" +#include "faust-cc/compressor.cc" +#include "faust-cc/crybaby.cc" +#include "faust-cc/autowah.cc" +#include "faust-cc/echo.cc" +#include "faust-cc/delay.cc" +#include "faust-cc/distortion.cc" +#include "faust-cc/distortion1.cc" +#include "faust-cc/freeverb.cc" +#include "faust-cc/impulseresponse.cc" +#include "faust-cc/chorus.cc" +#include "faust-cc/moog.cc" +#include "faust-cc/biquad.cc" +#include "faust-cc/flanger.cc" +#include "faust-cc/selecteq.cc" +#include "faust-cc/sloop.cc" + +static void activate_callback(float val, void *data) +{ + ((void (*)(bool,int))data)(!(val == 0.0), gx_jack::jack_sr); +} + +static void faust_add_callback(const char* id, void (*func)(bool,int)) +{ + new gx_ui::GxUiCallbackItem(gx_gui::GxMainInterface::instance(), + (float*)gx_gui::parameter_map[id].zone(), + activate_callback, (void*)func); +} + +void faust_init(int samplingFreq) +{ + faust_add_callback("SampleLooper.on_off", sloop::activate); + faust_add_callback("delay.on_off", delay::activate); + faust_add_callback("echo.on_off", echo::activate); + faust_add_callback("chorus.on_off", chorus::activate); + faust_add_callback("jconv.on_off", jconv_post::activate); + for (list::iterator i = inilist.begin(); i != inilist.end(); i++) { + try { + i->func(samplingFreq); + } catch (bad_alloc) { + string name = gx_gui::param_group(i->name, true); + gx_system::gx_print_error("DSP Module", (boost::format("not enough memory to initialize module %1%") % i->name).str()); + } + } +} + + + +#ifdef EXPERIMENTAL +/**************************************************************** + ** Support for experimental faust dsp files + */ + +#define EXPERIMENTAL_PROCESSING \ + if (exp_on) { \ + static int exp_upsample_old = 0; \ + int ovs_exp_count, ovs_exp_sr; \ + float *ovs_exp_buffer; \ + if (exp_upsample_on) { \ + exp_upsample = min(8,audio.upsample_mode+1); \ + if (exp_upsample != exp_upsample_old) { \ + exp_upsample_old = exp_upsample; \ + /*FIXME non-rt*/ \ + resampExp.setup(gx_jack::jack_sr, exp_upsample); \ + Exp::init(exp_upsample * gx_jack::jack_sr); \ + } \ + resampExp.up(count, output0, oversample); \ + ovs_exp_sr = exp_upsample * gx_jack::jack_sr; \ + ovs_exp_count = exp_upsample * count; \ + ovs_exp_buffer = oversample; \ + } \ + else { \ + ovs_exp_sr = gx_jack::jack_sr; \ + ovs_exp_count = count; \ + ovs_exp_buffer = output0; \ + } \ + \ + Exp::compute(ovs_exp_count, ovs_exp_buffer, ovs_exp_buffer);\ + \ + if (exp_upsample_on) { \ + resampExp.down(count, oversample, output0); \ + } \ + } + +/**************************************************************** + ** the Eperimental widget + */ + +typedef void (*setupfunc)(GtkWidget *); +list setuplist; + +void registerSetup(setupfunc f) +{ + setuplist.push_back(f); +} + +#define registerVar(id,name,tp,tooltip,var,val,low,up,step) registerVar(id,name,tp,tooltip,var,val,low,up,step,true) + +#include "faust-cc/Exp.cc" + +#undef registerVar + +static GtkWidget *exp_window = 0; + +static gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + gtk_widget_hide(widget); + return TRUE; +} + +static void on_show(GtkWidget *widget, gpointer data) +{ + gx_gui::parameter_map["system.show_exp_window"].getSwitch().set(true); +} + +static void on_hide(GtkWidget *widget, gpointer data) +{ + gx_gui::parameter_map["system.show_exp_window"].getSwitch().set(false); +} + +volatile int exp_upsample; +volatile int exp_upsample_on; +volatile int exp_on; +volatile bool exp_hs; +GtkWidget *exp_sample_spin; +SimpleResampler resampExp; + +static void exp_sr_changed(GtkWidget *widget, gpointer data) +{ + exp_upsample = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); +} + +static void exp_hs_toggled(GtkWidget *widget, gpointer data) +{ + exp_hs = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + +static void exp_up_toggled(GtkWidget *widget, gpointer data) +{ + exp_upsample_on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + +static void exp_on_toggled(GtkWidget *widget, gpointer data) +{ + exp_on = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); +} + +static gboolean set_transient(gpointer data) +{ + GtkWindow *exp_window = GTK_WINDOW(data); + if (GTK_WIDGET_REALIZED (GTK_WIDGET(gx_gui::fWindow))) { + // replaced for GTK-2.13 + //if (gtk_widget_get_realized(GTK_WIDGET(gx_gui::fWindow))) { + gtk_window_set_transient_for(exp_window, GTK_WINDOW(gx_gui::fWindow)); + } + return FALSE; +} + +void faust_setup() +{ + registerIntParam("test.upsample", "Upsample", (int*)&exp_upsample, 4, 1, 8, true); + gx_gui::registerParam("test.highshelf", "HighShelf", (bool*)&exp_hs, true, true); + exp_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW(exp_window), "Experimental"); + if (GTK_WIDGET_REALIZED (gx_gui::fWindow)) { + // replaced for GTK-2.13 + //if (gtk_widget_get_realized(gx_gui::fWindow)) { + gtk_window_set_transient_for(GTK_WINDOW(exp_window), GTK_WINDOW(gx_gui::fWindow)); + } else { + //this is a HACK. recall_state constructs this window before the main window is realized + g_idle_add(set_transient, exp_window); + } + //FIXME prevents digit entry (-> preset selection) + //gtk_window_add_accel_group(GTK_WINDOW(exp_window), + // gx_gui::GxMainInterface::instance()->fAccelGroup); + gtk_signal_connect (GTK_OBJECT (exp_window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL); + gtk_signal_connect (GTK_OBJECT (exp_window), "hide", GTK_SIGNAL_FUNC(on_hide), NULL); + gtk_signal_connect (GTK_OBJECT (exp_window), "show", GTK_SIGNAL_FUNC(on_show), NULL); + GtkWidget *vbox = gtk_vbox_new(false, 10); + g_signal_connect(vbox, "expose-event", G_CALLBACK(gx_cairo::AmpBox_expose), NULL); + gtk_widget_show(vbox); + GtkWidget *hbox = gtk_hbox_new(false, 10); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, 0, 0, 5); + GtkWidget *w = gtk_label_new("Select:"); + gtk_widget_show(w); + gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5); + GtkObject *adj = gtk_adjustment_new(4, 1, 8, 1, 2, 0); + exp_sample_spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 0); + gtk_signal_connect (GTK_OBJECT(exp_sample_spin), "value-changed", GTK_SIGNAL_FUNC(exp_sr_changed), NULL); + gtk_widget_show(exp_sample_spin); + w = gtk_check_button_new_with_label("enable"); + gtk_signal_connect(GTK_OBJECT(w), "toggled", GTK_SIGNAL_FUNC(exp_on_toggled), NULL); + gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5); + gtk_widget_show(w); + w = gtk_check_button_new_with_label("upsample"); + gtk_signal_connect(GTK_OBJECT(w), "toggled", GTK_SIGNAL_FUNC(exp_up_toggled), NULL); + gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 5); + gtk_widget_show(w); + w = gtk_check_button_new_with_label("HighShelf"); + gtk_widget_show(w); + gtk_box_pack_start(GTK_BOX(hbox), w, 0, 0, 20); + gtk_signal_connect(GTK_OBJECT(w), "toggled", GTK_SIGNAL_FUNC(exp_hs_toggled), NULL); + hbox = gtk_hbox_new(false, 10); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(vbox), hbox, 0, 0, 5); + gtk_container_add(GTK_CONTAINER(exp_window), vbox); + gtk_window_set_type_hint (GTK_WINDOW(exp_window), GDK_WINDOW_TYPE_HINT_UTILITY); + for (list::iterator i = setuplist.begin(); i != setuplist.end(); i++) { + (*i)(hbox); + } +} + +void toggle_exp_window(bool v) +{ + if (v) { + if (!GTK_WIDGET_VISIBLE(exp_window)) { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(exp_sample_spin), exp_upsample); + gtk_window_present(GTK_WINDOW(exp_window)); + } + } else { + if (GTK_WIDGET_VISIBLE(exp_window)) { + gtk_widget_hide(exp_window); + } + } +} + + +#define IF_HS(fn) {if (exp_hs) { fn; }} +#else +#define EXPERIMENTAL_PROCESSING +#define IF_HS(fn) {fn;} +#endif // EXPERIMENTAL diff --git a/src/gx_globals.cpp b/src/gx_globals.cpp new file mode 100644 index 0000000..8728f4c --- /dev/null +++ b/src/gx_globals.cpp @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix global variable definitions for all namespaces + * + * -------------------------------------------------------------------------- + */ + +#include "guitarix.h" + +/* ------------------------------------------------------------------------- */ + +/* ----- main engine ----- */ +namespace gx_engine +{ +float checky = 1.0; +float* get_frame = NULL; +float* get_frame1 = NULL; +float* checkfreq = NULL; +float* oversample = NULL; +float* result = NULL ; + +/* latency warning switch */ +float fwarn; +float fwarn_swap; + +/* engine init state */ +bool initialized = false; + +/* engine init state */ +bool pt_initialized = false; + +/* buffer ready state */ +bool buffers_ready = false; + +} + + +/* ------------------------------------------------------------------------- */ + +/* ----- jack namespace ----- */ +namespace gx_jack +{ +const int nIPorts = 3; // mono input + jconv +const int nOPorts = 4; // stereo output + jconv +int NO_CONNECTION = 1; + +/* variables */ +jack_nframes_t jack_sr; // jack sample rate +jack_nframes_t jack_bs; // jack buffer size +float jcpu_load; // jack cpu_load +float xdel; // last xrun delay +int is_rt; + +jack_client_t* client ; +jack_client_t* client_insert ; +jack_port_t* output_ports[nOPorts]; +jack_port_t* input_ports [nIPorts]; +void* midi_input_port_buf; +void* midi_port_buf; + +jack_port_t* midi_input_port; + +jack_port_t* midi_output_ports; +jack_nframes_t time_is; + +bool jack_is_down = false; +bool jack_is_exit = false; +GxJackLatencyChange change_latency; + +#ifdef USE_RINGBUFFER +struct MidiMessage ev; +jack_ringbuffer_t* jack_ringbuffer; +#endif + +string client_name = "guitarix_amp"; +string client_insert_name = "guitarix_fx"; +string client_instance = "guitarix"; + +string client_out_graph = ""; + +string gx_port_names[] = +{ + "in_0", + "out_0", + "out_1", + "midi_in_1", + "out_3" +}; + +} + +/* ------------------------------------------------------------------------- */ + +/* ----- JConv namespace ----- */ +namespace gx_jconv +{ +/* some global vars */ +float checkbox7; +GtkWidget* mslider; +} + +/* ------------------------------------------------------------------------- */ + +/* ----- system namespace ----- */ +namespace gx_system +{ +/* variables and constants */ +const int SYSTEM_OK = 0; + +string rcpath; + +const char* guitarix_dir = ".guitarix"; +const char* jcapsetup_file = "ja_ca_ssetrc"; +const char* jcapfile_wavbase = "guitarix_session"; + +const string gx_pixmap_dir = string(GX_PIXMAPS_DIR) + "/"; +const string gx_style_dir = string(GX_STYLE_DIR) + "/"; +const string gx_user_dir = string(getenv ("HOME")) + string("/") + string(guitarix_dir) + "/"; + +string gx_builder_dir = string(GX_BUILDER_DIR) + "/"; + +/* shell variable names */ +const char* shell_var_name[] = +{ + "GUITARIX2JACK_INPUTS", + "GUITARIX2JACK_OUTPUTS1", + "GUITARIX2JACK_OUTPUTS2", + "GUITARIX2JACK_MIDI", + "GUITARIX_RC_STYLE", + "GUITARIX2JACK_UUID", + "GUITARIX_LOAD_FILE" +}; +} + + +/* ------------------------------------------------------------------------- */ + +/* ----- preset namespace ----- */ +namespace gx_preset +{ +/* global var declarations */ + +gx_gui::FileParameter gx_preset_file("system.current_preset_file"); + + +GdkModifierType list_mod[] = +{ + GDK_NO_MOD_MASK, + GDK_CONTROL_MASK, + GDK_MOD1_MASK, + GdkModifierType(GDK_CONTROL_MASK|GDK_MOD1_MASK) +}; + +const char* preset_accel_path[] = +{ + "/Load", + "/Save", + "/Rename", + "/Delete" +}; + +const char* preset_menu_name[] = +{ + "_Load Preset...", + "_Save Preset...", + "_Rename Preset...", + "_Delete Preset..." +}; + +//map preset_list[GX_NUM_OF_PRESET_LISTS]; + +string gx_current_preset; +string old_preset_name; + +GtkWidget* presmenu[GX_NUM_OF_PRESET_LISTS]; +GtkWidget* presMenu[GX_NUM_OF_PRESET_LISTS]; + +vector plist; +vector pm_list[GX_NUM_OF_PRESET_LISTS]; + +bool setting_is_preset = false; + +GCallback preset_action_func[] = +{ + G_CALLBACK(gx_load_preset), + G_CALLBACK(gx_save_oldpreset), + G_CALLBACK(gx_rename_preset_dialog), + G_CALLBACK(gx_delete_preset_dialog) +}; +} + +/* ------------------------------------------------------------------------- */ + +/* ----- GUI namespace ----- */ +namespace gx_gui +{ + +/* wave view global */ +bool new_wave_view; + +/* global GUI widgets */ +GtkWidget* fWindow; +GtkWidget* menuh; +GtkWidget* pb; +GtkWidget* midibox; +GtkWidget* fbutton; +GtkWidget* record_button; +GtkWidget* jc_dialog; +GtkWidget* patch_info; + +/* wave view widgets */ +GtkWidget* livewa; +GdkPixbuf* ib; +GdkPixbuf* ibm; +GdkPixbuf* ibr; +GdkPixbuf* bbr; + + +/* jack server status icons */ +GtkWidget* gx_jackd_on_image; +GtkWidget* gx_jackd_off_image; + +/* engine status images */ +GtkWidget* gx_engine_on_image; +GtkWidget* gx_engine_off_image; +GtkWidget* gx_engine_bypass_image; +GtkWidget* gx_engine_item; + +/* some more widgets. Note: change names please! */ +GtkWidget* label1; +GtkWidget* label6; + +GtkStatusIcon* status_icon; + +int showwave = 0; +int shownote = -1; +int smoth_tuner = 0; +float show_patch_info = 0; + +/* skin handling */ +vector skin_list; +gint gx_current_skin = 0; +int last_skin = 0; +int no_opt_skin = 0; +int set_knob = 0; + +int g_threads[4]={0,0,0,0}; + +/* for level display */ +int meter_falloff = 27; // in dB/sec. +int meter_display_timeout = 60; // in millisec + +/* midi_in preset switch */ +volatile gint program_change = -1; +sem_t program_change_sem; + +int show_eq; + +} + +/* ------------------------------------------------------------------------- */ + +/* ----- cairo namespace ----- */ +namespace gx_cairo +{ +GdkPixbuf *tribeimage; +GdkPixbuf *tribeimage1; +GdkPixbuf *tribeimage2; +} diff --git a/src/gx_gui_helpers.cpp b/src/gx_gui_helpers.cpp new file mode 100644 index 0000000..70c2f1b --- /dev/null +++ b/src/gx_gui_helpers.cpp @@ -0,0 +1,1018 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix GUI related functionality + * + * ---------------------------------------------------------------------------- + */ + +#include +#include +#include "guitarix.h" + +using namespace gx_system; +using namespace gx_preset; +using namespace gx_cairo; + +/* --------------------------- gx_gui namespace ------------------------ */ +namespace gx_gui +{ + +/* ----- Menu check item signaled from parameter ------ */ + +void MenuCheckItem::set(bool v) +{ + assert(item); // assign an item before calling + gtk_check_menu_item_set_active(item, v); +} + +void MenuCheckItem::activateMenuSetSwitch(GtkWidget *w, gpointer data) +{ + SwitchParameter *p = (SwitchParameter*)data; + p->set(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); +} + +void MenuCheckItem::init(GtkCheckMenuItem *it, SwitchParameter *p) +{ + item = it; + parameter_map.insert(p); + p->changed.connect(sigc::mem_fun(*this, &MenuCheckItem::set)); + g_signal_connect(GTK_OBJECT(item), "activate", + G_CALLBACK(activateMenuSetSwitch), p); +} + + +/* ----- load a top level window from gtk builder file ------ */ + +GtkWidget *load_toplevel(GtkBuilder *builder, const char* filename, const char* windowname) +{ + string fname = gx_builder_dir+filename; + GError *err = NULL; + if (!gtk_builder_add_from_file(builder,fname.c_str(), &err)) { + g_object_unref(G_OBJECT(builder)); + gx_print_fatal("gtk builder", err->message); + g_error_free(err); + return NULL; + } + GtkWidget *w = GTK_WIDGET(gtk_builder_get_object(builder, windowname)); + if (!w) { + g_object_unref(G_OBJECT(builder)); + gx_print_fatal("gtk builder", string(windowname)+" not found in "+fname); + return NULL; + } + gtk_builder_connect_signals(builder, 0); + return w; +} + +/* --------- menu function triggering engine on/off/bypass --------- */ +void gx_engine_switch (GtkWidget* widget, gpointer arg) +{ + gx_engine::GxEngineState estate = + (gx_engine::GxEngineState)gx_engine::checky; + + switch (estate) + { + case gx_engine::kEngineOn: + estate = gx_engine::kEngineOff; + if (arg) + { + // need to activate item + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(gx_engine_item), TRUE + ); + estate = gx_engine::kEngineBypass; + } + + break; + + case gx_engine::kEngineOff: + if (!arg) + estate = gx_engine::kEngineOn; + break; + + default: + estate = gx_engine::kEngineOn; + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(gx_engine_item), TRUE + ); + } + + gx_engine::checky = (float)estate; + gx_refresh_engine_status_display(); +} + +/* -------------- refresh engine status display ---------------- */ +void gx_refresh_engine_status_display() +{ + gx_engine::GxEngineState estate = + (gx_engine::GxEngineState)gx_engine::checky; + + string state; + + switch (estate) + { + + case gx_engine::kEngineOff: + gtk_widget_show(gx_engine_off_image); + gtk_widget_hide(gx_engine_on_image); + gtk_widget_hide(gx_engine_bypass_image); + + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(gx_engine_item), FALSE + ); + state = "OFF"; + break; + + case gx_engine::kEngineBypass: + gtk_widget_show(gx_engine_bypass_image); + gtk_widget_hide(gx_engine_off_image); + gtk_widget_hide(gx_engine_on_image); + + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(gx_gui::gx_engine_item), TRUE + ); + state = "BYPASSED"; + break; + + case gx_engine::kEngineOn: + default: // ON + gtk_widget_show(gx_engine_on_image); + gtk_widget_hide(gx_engine_off_image); + gtk_widget_hide(gx_engine_bypass_image); + + gtk_check_menu_item_set_active( + GTK_CHECK_MENU_ITEM(gx_gui::gx_engine_item), TRUE + ); + state = "ON"; + } + + gx_print_info("Engine State: ", state); +} + + +// get the last used skin as default +void gx_set_skin_change(float fskin) +{ + last_skin = int(fskin); +} + +// save the current used skin as default +void gx_get_skin_change(float *fskin) +{ + *fskin = float(gx_current_skin); +} + +void gx_jack_is_down() +{ + /* FIXME send to ui thread + gx_print_warning("Jack Shutdown", + "jack has bumped us out!!"); + */ + cout << "jack has bumped us out!!" << endl; + g_timeout_add_full(G_PRIORITY_LOW,200, gx_threads::gx_survive_jack_shutdown, 0, NULL); +} + +void gx_jack_report_xrun() +{ + g_threads[2] = 0; + if (g_threads[2] == 0 ||g_main_context_find_source_by_id(NULL, g_threads[2]) == NULL) + g_threads[2] =g_idle_add(gx_threads::gx_xrun_report,gpointer (NULL)); +} + +//----menu function gx_show_oscilloscope +void gx_show_oscilloscope (GtkCheckMenuItem *menuitem, gpointer checkplay) +{ + if (gtk_check_menu_item_get_active(menuitem) == TRUE) + { + showwave = 1; + g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, 60, gx_threads::gx_refresh_oscilloscope, 0, NULL); + GtkWidget * parent = gtk_widget_get_parent(GTK_WIDGET(livewa)); + gtk_widget_show(parent); + gtk_widget_show(livewa); + } + else + { + showwave = 0; + GtkWidget * parent = gtk_widget_get_parent(GTK_WIDGET(livewa)); + gtk_widget_hide(parent); + gtk_widget_hide(livewa); + } +} + +//----menu function gx_tuner +void gx_tuner (GtkCheckMenuItem *menuitem, gpointer checkplay) +{ + if (gtk_check_menu_item_get_active(menuitem) == TRUE) { + shownote = 1; + gtk_widget_show(pb); + //tuner_expose(pb,NULL,NULL); + } else { + shownote = 0; + gtk_widget_hide(pb); + } +} + +//----menu function gx_tuner +void gx_patch(GtkCheckMenuItem *menuitem, gpointer checkplay) +{ + gtk_widget_show_all(patch_info); +} + +//---- menu function gx_midi_out +void gx_midi_out (GtkCheckMenuItem *menuitem, gpointer checkplay) +{ + if (gtk_check_menu_item_get_active(menuitem) == TRUE) + { + gx_engine::turnOnMidi(); + gtk_widget_show(midibox); + } + else + { + gx_engine::turnOffMidi(); + gtk_widget_hide(midibox); + } +} + +//---- menu function gx_midi_out +void gx_log_window (GtkWidget* menuitem, gpointer arg) +{ + GtkExpander* const exbox = GxMainInterface::instance()->getLoggingBox(); + + // we could be called before UI is built up + if (!exbox) return; + + bool expanded = gtk_expander_get_expanded(exbox); + bool checked = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)); + if (!(expanded ^ checked)) { + return; + } + gtk_signal_emit_by_name(GTK_OBJECT(exbox), "activate"); +} + +//----menu funktion about +void gx_show_about( GtkWidget *widget, gpointer data ) +{ + static string about; + if (about.empty()) + { + about += + "\n This Aplication is to a large extent provided" + "\n with the marvelous faust compiler.Yann Orlary" + "\n " + "\n A large part is based on the work of Julius Orion Smith" + "\n " + "\n and Albert Graef\n " + "\n\n\n guitarix "; + + about += GX_VERSION; + + about += + " use jack_capture >= 0.9.30for record" + "\n by Kjetil S. Matheussen " + "\n http://old.notam02.no/arkiv/src/?M=D" + "\n it will allways record to ~/guitarix_sessionX.xxx " + "\n for impulse response it use zita-convolver " + "\n byFons Adriaensen " + "\n http://www.kokkinizita.net/linuxaudio/index.html " + "\n\n authors: Hermann Meyer " + "\n authors: James Warden " + "\n authors: Andreas Degert " + "\n home: http://guitarix.sourceforge.net/\n"; + } + + gx_message_popup(about.c_str()); +} + + +//----- change the jack buffersize on the fly is still experimental, give a warning +gint gx_wait_latency_warn() +{ + GtkWidget* warn_dialog = gtk_dialog_new(); + gtk_window_set_destroy_with_parent(GTK_WINDOW(warn_dialog), TRUE); + + GtkWidget* box = gtk_vbox_new (0, 4); + GtkWidget* labelt = gtk_label_new("\nWARNING\n"); + GtkWidget* labelt1 = gtk_label_new("CHANGING THE JACK_BUFFER_SIZE ON THE FLY \n" + "MAY CAUSE UNPREDICTABLE EFFECTS \n" + "TO OTHER RUNNING JACK APPLICATIONS. \n" + "DO YOU WANT TO PROCEED ?"); + GdkColor colorGreen; + gdk_color_parse("#969292", &colorGreen); + gtk_widget_modify_fg (labelt1, GTK_STATE_NORMAL, &colorGreen); + + GtkStyle *style1 = gtk_widget_get_style(labelt1); + pango_font_description_set_size(style1->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(style1->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(labelt1, style1->font_desc); + + gdk_color_parse("#ffffff", &colorGreen); + gtk_widget_modify_fg (labelt, GTK_STATE_NORMAL, &colorGreen); + style1 = gtk_widget_get_style(labelt); + pango_font_description_set_size(style1->font_desc, 14*PANGO_SCALE); + pango_font_description_set_weight(style1->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(labelt, style1->font_desc); + + GtkWidget* button1 = + gtk_dialog_add_button(GTK_DIALOG (warn_dialog), + "Yes", gx_jack::kChangeLatency); + + GtkWidget* button2 = + gtk_dialog_add_button(GTK_DIALOG (warn_dialog), + "No", gx_jack::kKeepLatency); + + + GtkWidget* box1 = gtk_hbox_new (0, 4); + GtkWidget* box2 = gtk_hbox_new (0, 4); + + GtkWidget* disable_warn = gtk_check_button_new(); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(disable_warn), FALSE); + g_signal_connect(disable_warn, "clicked", + G_CALLBACK(gx_user_disable_latency_warn), NULL); + + GtkWidget * labelt2 = + gtk_label_new ("Don't bother me again with such a question, " + "I know what I am doing"); + + gtk_container_add (GTK_CONTAINER(box), labelt); + gtk_container_add (GTK_CONTAINER(box), labelt1); + gtk_container_add (GTK_CONTAINER(box), box2); + gtk_container_add (GTK_CONTAINER(box), box1); + gtk_container_add (GTK_CONTAINER(box1), disable_warn); + gtk_container_add (GTK_CONTAINER(box1), labelt2); + gtk_container_add (GTK_CONTAINER(GTK_DIALOG(warn_dialog)->vbox), box); + + gtk_widget_modify_fg (labelt2, GTK_STATE_NORMAL, &colorGreen); + + GtkStyle *style = gtk_widget_get_style(labelt2); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(labelt2, style->font_desc); + + g_signal_connect_swapped(button1, "clicked", + G_CALLBACK (gtk_widget_destroy), warn_dialog); + g_signal_connect_swapped(button2, "clicked", + G_CALLBACK (gtk_widget_destroy), warn_dialog); + + gtk_widget_show_all(box); + + return gtk_dialog_run (GTK_DIALOG (warn_dialog)); +} + +// check user's decision to turn off latency change warning +void gx_user_disable_latency_warn(GtkWidget* wd, gpointer arg) +{ + GtkToggleButton* button = GTK_TOGGLE_BUTTON(wd); + gx_engine::fwarn = (int)gtk_toggle_button_get_active(button); +} + +void gx_reset_effects( GtkWidget *widget, gpointer data ) +{ + string pos(".position"); + for (ParamMap::iterator i = parameter_map.begin(); i != parameter_map.end(); i++) { + string id = i->first; + if (id.size() > pos.size() && + id.compare(id.size()-pos.size(), pos.size(), pos) == 0) { + i->second->set_std_value(); + } + } +} + +// reset the extended sliders to default settings +void gx_reset_units( GtkWidget *widget, gpointer data ) +{ + string group_id = string((const char*)data) + "."; + string on_off = group_id + "on_off"; + for (ParamMap::iterator i = parameter_map.begin(); i != parameter_map.end(); i++) { + if (i->first.compare(0, group_id.size(), group_id) == 0) { + if (i->second->isControllable()) { + string id = i->first; + if (i->first != on_off) { + i->second->set_std_value(); + } + } + } + } +} + +/* +// FIXME add some presets for the eq +void gx_reset_eq( GtkWidget *widget, gpointer data ) +{ + string group_id = string((const char*)data) + "."; + string on_off = group_id + "on_off"; + + string presetfile = gx_user_dir + "eq_rc"; + + ifstream ofile(presetfile.c_str()); + JsonParser jp(ofile); + + try { + jp.next(JsonParser::begin_array); + readHeader(jp); + + while (jp.peek() != JsonParser::end_array) { + jp.next(JsonParser::value_string); + read_preset(jp); + } + jp.next(JsonParser::end_array); + jp.next(JsonParser::end_token); + }catch (JsonException& e) { + gx_print_error("load preset", "invalid preset file: " + presetfile); + } + +} +*/ + +//----- show extendend settings slider +void gx_show_extended_settings(GtkWidget *widget, gpointer data) +{ + if (gtk_range_get_value(GTK_RANGE(widget))) + { + gtk_widget_show(GTK_WIDGET(data)); + gint root_x, root_y; + gtk_window_get_position (GTK_WINDOW(data), &root_x, &root_y); + if (root_y>160)root_y -= 120; + else root_y +=120; + gtk_window_move(GTK_WINDOW(data), root_x, root_y); + } + + else gtk_widget_hide(GTK_WIDGET(data)); +} + +//----- hide the extendend settings slider +void gx_hide_extended_settings( GtkWidget *widget, gpointer data ) +{ + + if (gdk_window_get_state(fWindow->window) + & (GDK_WINDOW_STATE_ICONIFIED|GDK_WINDOW_STATE_WITHDRAWN)) { + gtk_window_present(GTK_WINDOW(fWindow)); + } else { + gtk_widget_hide(fWindow); + //gtk_window_iconify(GTK_WINDOW(fWindow)); + } +} + +/**----------------------------- cabinet impulse response data --------------------------------**/ +int cab_ir_count = 1000; +int cab_ir_sr = 48000; +float cab_ir_data[] = { +0.0210554,0.0750885,0.139243,0.180713,0.184139,0.144903,0.0686037,-0.0185033,-0.0886042,-0.12552, +-0.121363,-0.0787852,-0.0213013,0.0229356,0.0411458,0.0370145,0.0195269,-0.00133213,-0.0152812,-0.0145159, +-0.00183383,0.0137818,0.0256187,0.0286779,0.0207782,0.0077942,-0.00120299,-0.0031918,-0.00206098,-0.00135227, +-0.00140983,-0.00497816,-0.0130377,-0.0218103,-0.0277226,-0.0286464,-0.0215221,-0.00951618,-0.00086607,0.0013951, +4.17435e-05,-0.00319773,-0.00740044,-0.00716618,-0.00255126,0.00219789,0.00519503,0.00521192,0.000273707,-0.00618929, +-0.00908,-0.010311,-0.0123735,-0.0142287,-0.017697,-0.0241029,-0.0284137,-0.0277091,-0.0227469,-0.0152625, +-0.00519387,0.00359817,0.00729039,0.00671523,0.00318916,-0.00156796,-0.0063908,-0.00976712,-0.0129904,-0.017544, +-0.022616,-0.0259348,-0.0261542,-0.0244839,-0.0203182,-0.0130093,-0.00603727,-0.0032797,-0.00488236,-0.00846209, +-0.0130562,-0.0172578,-0.019061,-0.0178728,-0.0150705,-0.0105603,-0.00434051,0.000776129,0.00313197,0.00289589, +0.00099021,-0.00304687,-0.00856731,-0.0134404,-0.0173033,-0.019982,-0.0200995,-0.0189035,-0.0176908,-0.0158077, +-0.0144982,-0.0144288,-0.0148401,-0.0143923,-0.0124568,-0.00914924,-0.00554664,-0.00161911,0.00204186,0.00466298, +0.00609433,0.00586043,0.00444049,0.00230369,-0.000460247,-0.00331487,-0.00620476,-0.00860464,-0.00977339,-0.0103904, +-0.010582,-0.010316,-0.00959965,-0.0079265,-0.00490751,-0.000773675,0.00326292,0.0060596,0.00712823,0.0062126, +0.00304346,-0.00120159,-0.00554078,-0.00940086,-0.0116814,-0.0115473,-0.00920741,-0.00570695,-0.00192381,0.00131636, +0.00313601,0.00310522,0.0019866,0.00024603,-0.00151895,-0.00254442,-0.00257635,-0.00162088,0.000189493,0.00233523, +0.00431406,0.00546426,0.00550678,0.00412306,0.00163322,-0.00135299,-0.00397516,-0.00564887,-0.00616138,-0.00556616, +-0.00411866,-0.00213908,-0.000414186,0.000858571,0.00146968,0.00134177,0.000706731,0.000101598,-2.74503e-05,0.000216126, +0.000921334,0.00170689,0.00206986,0.00178904,0.00108999,0.000418435,-0.000329494,-0.00108679,-0.00160318,-0.00186207, +-0.00184908,-0.00174925,-0.0017532,-0.00168678,-0.00128635,-0.000532894,0.000551346,0.00173037,0.00285549,0.00381329, +0.00444954,0.00483888,0.00505528,0.00517976,0.00536394,0.00566848,0.00582878,0.00582337,0.00573454,0.00568407, +0.005573,0.00543545,0.00536728,0.00536814,0.00553587,0.00596405,0.00663779,0.00725726,0.00749624,0.00707181, +0.00588561,0.00408059,0.00192134,3.47446e-05,-0.00100598,-0.000915017,4.2448e-05,0.00134795,0.00249509,0.00322568, +0.0035816,0.00386374,0.00451921,0.00540239,0.0062616,0.00694728,0.0072783,0.00703991,0.00629145,0.00535576, +0.00433242,0.0032916,0.00256128,0.00234155,0.00256369,0.00301814,0.00356167,0.00389767,0.00377937,0.00333664, +0.00305993,0.00308825,0.00323129,0.00347644,0.00368722,0.00369027,0.0035434,0.0033256,0.00313601,0.00318107, +0.00358381,0.00415188,0.00472327,0.00508203,0.00512893,0.00469563,0.00385072,0.00285837,0.00193384,0.0011745, +0.000625585,0.000444931,0.000447908,0.000509171,0.000766472,0.00131361,0.00198278,0.00252006,0.00288339,0.00305278, +0.00301612,0.00284385,0.0027595,0.0028841,0.00307673,0.00335143,0.00374592,0.00420453,0.00472283,0.00537605, +0.00605867,0.00667969,0.0071488,0.00726939,0.00694415,0.00626471,0.00550721,0.0049613,0.00471663,0.00477505, +0.00498066,0.00516581,0.00520946,0.00505574,0.00483425,0.00468391,0.00466834,0.00471656,0.00470018,0.00453961, +0.0042108,0.00375276,0.00315533,0.00236797,0.00148797,0.000770994,0.000356717,0.000263414,0.000411073,0.00065758, +0.000956942,0.00116598,0.00118259,0.0010794,0.00090411,0.000730068,0.000713639,0.00101561,0.00158903,0.0022272, +0.00269874,0.00283804,0.00266545,0.00230882,0.00195122,0.00177202,0.0018221,0.00198835,0.00219707,0.0024585, +0.00262623,0.00258478,0.00247114,0.00236725,0.00229178,0.00227378,0.00223327,0.0020942,0.0018775,0.00165049, +0.00145125,0.0013392,0.00133322,0.0013771,0.00146459,0.00154074,0.00148781,0.00131534,0.00115589,0.00110735, +0.00111562,0.00117102,0.0011977,0.00112514,0.000940195,0.000626312,0.000241008,-0.000110301,-0.000294454,-0.00026455, +-3.9153e-05,0.000364625,0.000848391,0.00124397,0.00133727,0.00111349,0.00081935,0.000737272,0.000979052,0.00152794, +0.00229764,0.00300549,0.00349459,0.00378848,0.00383738,0.00362037,0.00319689,0.00261696,0.00202673,0.00153753, +0.0010692,0.000529509,-3.48582e-05,-0.000518806,-0.000836461,-0.000893089,-0.000683757,-0.00041539,-0.000240531,-0.000199855, +-0.00040037,-0.000829803,-0.00130214,-0.00175941,-0.00214005,-0.00239538,-0.00255126,-0.00260319,-0.00258167,-0.00258312, +-0.00261625,-0.00257821,-0.00243703,-0.00224874,-0.002035,-0.0018443,-0.00177327,-0.00182376,-0.00196122,-0.00222559, +-0.00246046,-0.0023872,-0.00200267,-0.00146368,-0.000895475,-0.000426638,-0.000116391,8.54413e-05,0.000229487,0.000434546, +0.000783401,0.00125185,0.00170428,0.00195945,0.00191818,0.00165093,0.0013,0.000928947,0.00048422,-4.45158e-05, +-0.000552028,-0.000942422,-0.00123235,-0.00149559,-0.00177645,-0.00204586,-0.00228739,-0.00245312,-0.00249216,-0.00238563, +-0.00216864,-0.00195288,-0.00184076,-0.0018401,-0.00190445,-0.00195077,-0.0018578,-0.00162677,-0.00132209,-0.00103643, +-0.000946898,-0.00112221,-0.00150406,-0.00195615,-0.00229437,-0.00239499,-0.00218277,-0.0017268,-0.00124285,-0.00091104, +-0.000849391,-0.00104366,-0.00129184,-0.00138022,-0.00126944,-0.00107845,-0.000937854,-0.000922902,-0.00107965,-0.00139665, +-0.00174952,-0.00198203,-0.00202984,-0.00187962,-0.0015708,-0.00124176,-0.00109158,-0.00130834,-0.0019349,-0.00284735, +-0.00377169,-0.00432535,-0.00427272,-0.00367104,-0.00275803,-0.00184037,-0.00124326,-0.00112073,-0.00138117,-0.00175739, +-0.00199908,-0.00197451,-0.00163986,-0.00107954,-0.000508739,-0.000136274,-2.69049e-05,-0.000195924,-0.000604997,-0.00107277, +-0.00139074,-0.00147588,-0.00138458,-0.00119441,-0.00105561,-0.00112623,-0.00139983,-0.00174871,-0.00207738,-0.00232496, +-0.00235838,-0.00213469,-0.00182601,-0.00162957,-0.00156907,-0.00164833,-0.00185294,-0.00208449,-0.002181,-0.00207736, +-0.00181851,-0.00145291,-0.00105886,-0.000777402,-0.000693301,-0.000780538,-0.000966736,-0.00110846,-0.00100441,-0.000639605, +-0.000167997,0.000278684,0.000595589,0.000718707,0.000677736,0.000535644,0.000359331,0.000214058,0.000116118,-2.04741e-05, +-0.000248734,-0.000545983,-0.00088025,-0.00122061,-0.0015376,-0.00175523,-0.00175457,-0.00148886,-0.00107979,-0.000750293, +-0.000715752,-0.00112187,-0.0019394,-0.0029335,-0.00377016,-0.00421975,-0.00417837,-0.00370331,-0.00304405,-0.00245053, +-0.00210699,-0.00207797,-0.0022711,-0.00249086,-0.00253708,-0.00230403,-0.00181831,-0.00124433,-0.000780152,-0.000599361, +-0.00073175,-0.00104361,-0.00127435,-0.00119859,-0.000762859,-8.26917e-05,0.000629675,0.00112308,0.00126592,0.0011715, +0.00103854,0.000983915,0.00102964,0.00109781,0.00111035,0.000980961,0.000642923,0.000128366,-0.000457361,-0.000965123, +-0.00129109,-0.00143212,-0.00144318,-0.0014024,-0.00139796,-0.00148234,-0.00166874,-0.00191579,-0.00211699,-0.00215912, +-0.0020502,-0.00183696,-0.00155674,-0.00122281,-0.000867206,-0.000589227,-0.000474017,-0.000498718,-0.000541393,-0.000489083, +-0.000283456,6.39901e-05,0.000442908,0.000769699,0.000966486,0.000987869,0.000807193,0.000472449,6.91029e-05,-0.000300749, +-0.000520124,-0.000506989,-0.000277707,-7.49884e-07,0.000197924,0.000303067,0.000322268,0.000290614,0.000293023,0.000353695, +0.000410527,0.000420457,0.000342197,0.000133297,-0.000165088,-0.000453839,-0.000679258,-0.000834689,-0.000952602,-0.00110901, +-0.00138581,-0.00176734,-0.00213167,-0.00235534,-0.00238038,-0.0022105,-0.0018848,-0.00142392,-0.000878386,-0.000337561, +0.000124526,0.000442113,0.000576183,0.000579069,0.000590295,0.000704595,0.000887021,0.00101477,0.0010045,0.000847664, +0.000575138,0.000306771,0.000121299,3.08588e-05,9.36218e-06,-8.68729e-05,-0.000309611,-0.000568184,-0.000781879,-0.00090086, +-0.000816373,-0.000530804,-0.00015868,0.000212172,0.000470813,0.000541848,0.000420117,0.000213262,5.74002e-05,5.44461e-05, +0.000231169,0.000503149,0.000735295,0.000831939,0.000801057,0.00070564,0.000658602,0.000765108,0.00102202,0.00132866, +0.00158623,0.00171223,0.00161877,0.00138119,0.00109374,0.000773789,0.000429865,0.000119368,-0.000121345,-0.000232623, +-0.000125412,0.000170474,0.000515011,0.000714866,0.000659852,0.000381759,2.34736e-05,-0.000255279,-0.000353581,-0.00027348, +-8.40097e-05,0.000180108,0.000442772,0.000595703,0.00059443,0.000443181,0.00020006,-4.72427e-05,-0.000237849,-0.000336152, +-0.000260891,-1.77245e-06,0.000308816,0.000549233,0.000726773,0.000843596,0.000880568,0.000881363,0.000886135,0.000917471, +0.000981234,0.00105438,0.00110092,0.0011346,0.00116191,0.00120611,0.00130918,0.00150924,0.00173518,0.00188839, +0.0019312,0.00182619,0.00154596,0.00111546,0.000674054,0.000338175,0.000137615,6.37174e-05,9.953e-05,0.000188198, +0.000251211,0.000265322,0.000236736,0.000180904,0.000111483,2.96318e-05,-4.73336e-05,-8.53731e-05,-1.88834e-05,0.000190425, +0.000533576,0.000938581,0.00131834,0.00155549,0.00158925,0.00148725,0.0013572,0.00129875,0.00134022,0.00146789, +0.00163836,0.00174532,0.00169876,0.00147691,0.00111449,0.000735204,0.000492014,0.000435092,0.000515761,0.000663783, +0.000799262,0.00084905,0.000801557,0.000690779,0.000557527,0.000428524,0.000314815,0.00019497,5.04922e-05,-0.000104847, +-0.000234282,-0.000318564,-0.000372079,-0.000385258,-0.00035599,-0.0003227,-0.000303067,-0.000293341,-0.000320655,-0.000354127, +-0.000328881,-0.000232259,-0.000107938,1.18163e-05,0.000143091,0.000270049,0.000361626,0.000452498,0.00056314,0.000661147, +0.000724365,0.000744134,0.000727273,0.00072107,0.000736863,0.000779379,0.000855094,0.000962941,0.00110471,0.00125183, +0.001321,0.00125508,0.00107511,0.000815532,0.000494719,0.000180608,-4.70381e-05,-0.000147682,-0.000113164,2.06559e-05, +0.000179654,0.000301226,0.00036008,0.000352877,0.000314178,0.000264527,0.000197424,0.000127707,7.75789e-05,3.03816e-05, +-4.49248e-05,-0.000123981,-0.000188198,-0.000230032,-0.000205332,-9.22811e-05,8.61003e-05,0.000310111,0.000546188,0.00074752, +0.000886044,0.000967781,0.000983915,0.000906905,0.000743066,0.000538462,0.000377373,0.000343151,0.000430569,0.000540598, +0.000564958,0.000431751,0.000133502,-0.000251643,-0.000614836,-0.000844801,-0.00086966,-0.000704595,-0.000452021,-0.000232532, +-0.00011021,-9.40536e-05,-0.000144818,-0.000166747,-0.000102916,5.03785e-05,0.000256278,0.000434682,0.000496309,0.000419026, +0.000240804,4.47203e-05,-9.02133e-05,-0.000122117,-6.04452e-05,1.82926e-05,5.15602e-05,1.39297e-05,-0.00012089,-0.00033004, +-0.000557345,-0.000726751,-0.000759268,-0.000650285,-0.000450657,-0.00021608,3.68579e-05,0.000297704,0.000538644,0.000710049, +0.00077363,0.000723092,0.000614791,0.000532167,0.000514057,0.00058116,0.000682076,0.00072566,0.000673282,0.000508217, +0.000270299,6.37401e-05,-5.79001e-05,-0.000104257,-9.17585e-05,-6.15359e-05,-5.7741e-05,-7.34204e-05,-8.94407e-05,-0.000104779, +-0.00013891,-0.000166588,-0.000132638,-2.27237e-05,0.000174609,0.00045193,0.00072032,0.000864434,0.000871569,0.000768994, +0.00059284,0.00041948,0.000294795,0.000222579,0.000194515,0.000144409,-1.60202e-05,-0.000275753,-0.000566662,-0.00085005, +-0.00107913,-0.00119302,-0.00120593,-0.00115421,-0.00108797,-0.00107377,-0.00112567,-0.00117748,-0.00117754,-0.00112203, +-0.00103152,-0.000931128,-0.000873637,-0.000869274,-0.000861684,-0.000822599,-0.000761041,-0.000649717,-0.000460974,-0.000247598, +-6.14223e-05,9.10313e-05,0.000194265,0.000208968,0.000170814,0.000139069,0.000142114,0.000191107,0.000249529,0.000275162, +0.000279048,0.000277048,0.000268231,0.000283933,0.000336425,0.000397711,0.000432933,0.0004093,0.00032804,0.000203196, +6.06951e-05,-4.35841e-05,-8.5464e-05,-7.4602e-05,-3.88122e-05,-4.04483e-05,-0.000130343,-0.00030134,-0.000497514,-0.000679258, +-0.000815623,-0.000864775,-0.000821327,-0.000721615,-0.000589863,-0.000465223,-0.000387599,-0.000366648,-0.000385849,-0.000436 +}; +/**----------------------------- cabinet impulse response data end --------------------------------**/ + +void gx_cab_res(GtkWidget *widget, gpointer obj) +{ + GtkWidget *wid = (GtkWidget *)obj; + if (!gtk_range_get_value(GTK_RANGE(wid))) { + gx_engine::cab_conv.stop(); + } else { + bool rc = gx_engine::cab_conv.configure(cab_ir_count, cab_ir_data, cab_ir_sr); + if (!rc || !gx_engine::cab_conv.start()) { + gtk_range_set_value(GTK_RANGE(wid), 0); + } + } + +} + +//----- systray menu +void gx_systray_menu( GtkWidget *widget, gpointer data ) +{ + guint32 tim = gtk_get_current_event_time (); + gtk_menu_popup (GTK_MENU(menuh),NULL,NULL,NULL,(gpointer) menuh,2,tim); +} + +//---- choice dialog without text entry +gint gx_nchoice_dialog_without_entry ( + const char* window_title, + const char* msg, + const guint nchoice, + const char* label[], + const gint resp[], + const gint default_response + ) +{ + GtkWidget* dialog = gtk_dialog_new(); + GtkWidget* text_label = gtk_label_new (msg); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), text_label); + + GdkColor colorGreen; + gdk_color_parse("#969292", &colorGreen); + gtk_widget_modify_fg (text_label, GTK_STATE_NORMAL, &colorGreen); + + GdkColor colorBlack; + gdk_color_parse("#000000", &colorBlack); + gtk_widget_modify_bg (dialog, GTK_STATE_NORMAL, &colorBlack); + + GtkStyle* text_style = gtk_widget_get_style(text_label); + pango_font_description_set_size(text_style->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(text_style->font_desc, PANGO_WEIGHT_BOLD); + + gtk_widget_modify_font(text_label, text_style->font_desc); + + for (guint i = 0; i < nchoice; i++) + { + GtkWidget* button = + gtk_dialog_add_button(GTK_DIALOG (dialog), label[i], resp[i]); + + gdk_color_parse("#555555", &colorBlack); + gtk_widget_modify_bg(button, GTK_STATE_NORMAL, &colorBlack); + + g_signal_connect_swapped(button, "clicked", G_CALLBACK (gtk_widget_destroy), dialog); + } + + // set default + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), TRUE); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); + gtk_window_set_title(GTK_WINDOW(dialog), window_title); + + gtk_widget_show(text_label); + + //--- run dialog and check response + gint response = gtk_dialog_run (GTK_DIALOG (dialog)); + return response; +} + +//---- choice dialog without text entry +gint gx_choice_dialog_without_entry ( + const char* window_title, + const char* msg, + const char* label1, + const char* label2, + const gint resp1, + const gint resp2, + const gint default_response + ) +{ + const guint nchoice = 2; + const char* labels[] = {label1, label2}; + const gint responses[] = {resp1, resp2}; + + return gx_nchoice_dialog_without_entry( + window_title, + msg, + nchoice, + labels, + responses, + default_response); +} + +//---- get text entry from dialog +void gx_get_text_entry(GtkEntry* entry, string& output) +{ + if (gtk_entry_get_text(entry)[0]) + output = gtk_entry_get_text(entry); +} + +//---- choice dialog with text entry +gint gx_choice_dialog_with_text_entry ( + const char* window_title, + const char* msg, + const char* label1, + const char* label2, + const gint resp1, + const gint resp2, + const gint default_response, + GCallback func + ) +{ + GtkWidget *dialog, *button1, *button2; + dialog = gtk_dialog_new(); + button1 = gtk_dialog_add_button(GTK_DIALOG (dialog), label1, resp1); + button2 = gtk_dialog_add_button(GTK_DIALOG (dialog), label2, resp2); + + GtkWidget* text_label = gtk_label_new (msg); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), text_label); + + + GtkWidget* gtk_entry = gtk_entry_new_with_max_length(32); + gtk_entry_set_text(GTK_ENTRY(gtk_entry), ""); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), gtk_entry); + + g_signal_connect_swapped (button1, "clicked", G_CALLBACK (func), gtk_entry); + + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), TRUE); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); + gtk_entry_set_activates_default(GTK_ENTRY(gtk_entry), TRUE); + GTK_BOX(GTK_DIALOG(dialog)->action_area)->spacing = 4; + + // some display style + GdkColor colorGreen; + gdk_color_parse("#969292", &colorGreen); + gtk_widget_modify_fg (text_label, GTK_STATE_NORMAL, &colorGreen); + + GdkColor colorBlack; + gdk_color_parse("#000000", &colorBlack); + gtk_widget_modify_bg (dialog, GTK_STATE_NORMAL, &colorBlack); + + GtkStyle* text_style = gtk_widget_get_style(text_label); + pango_font_description_set_size(text_style->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(text_style->font_desc, PANGO_WEIGHT_BOLD); + + gtk_widget_modify_font(text_label, text_style->font_desc); + + gdk_color_parse("#555555", &colorBlack); + gtk_widget_modify_bg (button1, GTK_STATE_NORMAL, &colorBlack); + + gdk_color_parse("#555555", &colorBlack); + gtk_widget_modify_bg (button2, GTK_STATE_NORMAL, &colorBlack); + + // display extra stuff + gtk_widget_show (text_label); + gtk_widget_show (gtk_entry); + gtk_window_set_title(GTK_WINDOW(dialog), window_title); + + // run the dialog and wait for response + gint response = gtk_dialog_run (GTK_DIALOG(dialog)); + + if (dialog) gtk_widget_destroy(dialog); + + return response; +} + +//---- retrive skin array index from skin name +void gx_actualize_skin_index(const string& skin_name) +{ + for (guint s = 0; s < skin_list.size(); s++) { + if (skin_name == skin_list[s]) { + gx_current_skin = s; + return; + } + } +} + +//------- count the number of available skins +unsigned int gx_fetch_available_skins() +{ + DIR *d; + d = opendir(gx_style_dir.c_str()); + if (!d) { + return 0; + } + // look for guitarix_*.rc and extract *-part + struct dirent *de; + while ((de = readdir(d)) != 0) { + char *p = de->d_name; + if (strncmp(p, "guitarix_", 9) != 0) { + continue; + } + p += 9; + int n = strlen(p) - 3; + if (strcmp(p+n, ".rc") != 0) { + continue; + } + skin_list.push_back(string(p, n)); + sort(skin_list.begin(), skin_list.end()); + } + closedir(d); + return skin_list.size(); +} + +// ----- skin change +void gx_change_skin(GtkCheckMenuItem *menuitem, gpointer arg) +{ + // no action needed on false + if (gtk_check_menu_item_get_active(menuitem) == FALSE) + return; + + // update the skin to the one picked by user + const int idx = (int)GPOINTER_TO_INT(arg); + + (void)gx_update_skin(idx, "gx_change_skin"); +} + +// ----- cycling through skin +void gx_cycle_through_skin(GtkWidget *widget, gpointer arg) +{ + + gint idx = gx_current_skin + 1; + idx %= skin_list.size(); + + // did it work ? if yes, update current skin + if (gx_update_skin(idx, "gx_cycle_through_skin")) + gx_current_skin = idx; + + // update menu item state + gx_update_skin_menu_item(gx_current_skin); +} + +// ----- cycling through skin +void gx_update_skin_menu_item(const int index) +{ + // update menu item state + GxMainInterface* gui = GxMainInterface::instance(); + GtkWidget* skinmenu = gui->getMenu("Skin"); + + GList* list = gtk_container_get_children(GTK_CONTAINER(skinmenu)); + GtkWidget* item = (GtkWidget*)g_list_nth_data(list, index); + g_list_free(list); + if (item) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); +} + +// ---- skin changer, used internally frm callbacks +bool gx_update_skin(const gint idx, const char* calling_func) +{ + // check skin validity + if (idx < 0 || idx >= (gint)skin_list.size()) + { + gx_print_warning(calling_func, "skin index out of range, keeping actual skin"); + return false; + } + + string rcfile = GX_STYLE_DIR + string("/") + "guitarix_"; + rcfile += skin_list[idx]; + rcfile += ".rc"; + + gtk_rc_parse(rcfile.c_str()); + gtk_rc_reset_styles(gtk_settings_get_default()); + + gx_current_skin = idx; + + // refresh wave view + gx_waveview_refresh (GTK_WIDGET(livewa), NULL); + if (int(float(gx_current_skin)==0)) + { + if (set_knob !=1) + { + GtkRegler::gtk_regler_init_pixmaps(1); + set_knob = 1; + } + } + else if (int(float(gx_current_skin)==1)) + { + if (set_knob !=2) + { + GtkRegler::gtk_regler_init_pixmaps(2); + set_knob = 2; + } + } + + else if (int(float(gx_current_skin)==3)) + { + if (set_knob !=3) + { + GtkRegler::gtk_regler_init_pixmaps(3); + set_knob = 3; + } + } + else if (int(float(gx_current_skin)==5)) + { + if (set_knob !=4) + { + GtkRegler::gtk_regler_init_pixmaps(4); + set_knob = 4; + } + } + else if (int(float(gx_current_skin)==4)) + { + if (set_knob !=5) + { + GtkRegler::gtk_regler_init_pixmaps(5); + set_knob = 5; + } + } + else if (int(float(gx_current_skin)==8)) + { + if (set_knob !=3) + { + GtkRegler::gtk_regler_init_pixmaps(3); + set_knob = 3; + } + } + else + { + GtkRegler::gtk_regler_init_pixmaps(0); + set_knob = 0; + } + + // refresh latency check menu + GxMainInterface* gui = GxMainInterface::instance(); + GtkWidget* wd = gui->getJackLatencyItem(gx_jack::jack_bs); + if (wd) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wd), TRUE); + + return true; +} + +// ---- set last used skin as default +bool gx_set_skin(GtkWidget *widget, gpointer data) +{ + return gx_update_skin(last_skin, "Set Skin"); +} + +//---- popup warning +int gx_message_popup(const char* msg) +{ + // check msg validity + if (!msg) + { + gx_print_warning("Message Popup", + string("warning message does not exist")); + return -1; + } + + // build popup window + GtkWidget *about; + GtkWidget *label; + GtkWidget *ok_button; + + about = gtk_dialog_new(); + ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); + + label = gtk_label_new (msg); + + GtkStyle *style = gtk_widget_get_style(label); + + pango_font_description_set_size(style->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + + gtk_widget_modify_font(label, style->font_desc); + + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(about)->vbox), label); + + GTK_BOX(GTK_DIALOG(about)->action_area)->spacing = 3; + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(about)->action_area), ok_button); + + g_signal_connect_swapped (ok_button, "clicked", + G_CALLBACK (gtk_widget_destroy), about); + + g_signal_connect(label, "expose-event", G_CALLBACK(conv_widget_expose), NULL); + gtk_widget_show (ok_button); + gtk_widget_show (label); + return gtk_dialog_run (GTK_DIALOG(about)); +} + +/* meter button release */ +void gx_meter_button_release(GdkEventButton* ev, gpointer arg) +{ + if (ev->button == 1) + { + cerr << " button event " << endl; + GxMainInterface* gui = GxMainInterface::instance(); + + GtkWidget* const* meters = gui->getLevelMeters(); + + for (int i = 0; i < 2; i++) { + if (meters[i]) { + gtk_fast_meter_clear(GTK_FAST_METER(meters[i])); + } + } + } +} + + + +/* ----- delete event ---- */ +gboolean gx_delete_event( GtkWidget *widget, gpointer data ) +{ + gtk_range_set_value(GTK_RANGE(widget), 0); + return TRUE; +} + +gboolean gx_hide_eq( GtkWidget *widget, gpointer obj ) +{ + show_eq = (int) GTK_ADJUSTMENT (widget)->value; + GtkWidget *wi = (GtkWidget *)obj; + GtkWidget *box1 = gtk_widget_get_parent(GTK_WIDGET(wi)); + GtkWidget *box = gtk_widget_get_parent(GTK_WIDGET(box1)); + GList* child_list = gtk_container_get_children(GTK_CONTAINER(box)); + GtkWidget *parent_eq = (GtkWidget *) g_list_nth_data(child_list,1); + g_list_free(child_list); + box = gtk_widget_get_parent(GTK_WIDGET(livewa)); + box1 = gtk_widget_get_parent(GTK_WIDGET(box1)); + + // gtk_widget_set_size_request (parent_eq, 280,80); + if (show_eq) + { + gtk_widget_show(parent_eq); + //gtk_widget_set_size_request (box, -1, -1); + if (GDK_IS_WINDOW (box1->window)) + gdk_window_invalidate_rect(GDK_WINDOW(box1->window),NULL,TRUE); + } + else + { + gtk_widget_hide(parent_eq); + //gtk_widget_set_size_request (box, -1,-1); + if (GDK_IS_WINDOW (box1->window)) + gdk_window_invalidate_rect(GDK_WINDOW(box1->window),NULL,TRUE); + } + + return false; +} + + +} /* end of gx_gui namespace */ diff --git a/src/gx_interface_builder.cpp b/src/gx_interface_builder.cpp new file mode 100644 index 0000000..c55dadb --- /dev/null +++ b/src/gx_interface_builder.cpp @@ -0,0 +1,1779 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix interface builder, + * it's a part of the class GxMainInterface + * + * ---------------------------------------------------------------------------- + */ + +#include "guitarix.h" + +//-------- the guitarix user interface build instruktions + +namespace gx_gui +{ + +#ifndef NDEBUG +// debug_check +inline void all_midi_params_assigned() +{ + for (ParamMap::iterator i = parameter_map.begin(); i != parameter_map.end(); i++) { + if (i->second->isControllable() && ! i->second->isUsed() && ! i->second->isExperimental()) + gx_system::gx_print_error("Debug Check", + "midi-parameter not assigned in ui: " + i->first); + } +} +#endif + +/* -------- user interface builder ---------- */ +void GxMainInterface::setup() +{ + //----- the main box, all visible widgets are a child of this box + openVerticalBox(""); + + //----- add the menubar on top + { + addMainMenu(); + + //----- this is a dummy widget, only for save settings for the latency warning dialog + openWarningBox("WARNING", &gx_engine::audio.fwarn); + setSkinBox("SKIN", &gx_engine::audio.fskin); + closeBox(); + + //----- the upper box, + openVerticalBox(""); + { + openEventBox(" "); + openPaintBox2(""); + { + openHorizontalBox(""); + { + + //----- the tuner widget + openVerticalBox(""); + { + addNumDisplay("", &gx_engine::audio.fConsta1t); + } + closeBox(); + + //----- the balance widget + openVerticalBox(""); + { + addslider("amp.balance", "balance"); + } + closeBox(); + + //----- the jconv widget on the main window + openFrameBox(""); + { + openExpanderBox(" convolver ", &gx_engine::audio.fexpand2); + { + openHandleBox(" "); + { + openVerticalBox(""); + { + openHorizontalBox(""); + { + openDialogBox("jconv", &gx_engine::audio.fdialogboxj,(int*)&gx_jconv::GxJConvSettings::checkbutton7); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox(""); + { + openHorizontalTableBox(""); + { + addbigregler("jconv.left_gain"," left gain "); + addregler("jconv.left_delay"," left delay "); + addbigregler("jconv.right_gain"," right gain "); + addregler("jconv.right_delay"," right delay "); + } + closeBox(); + } + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + addslider("jconv.wet_dry"); + } + closeBox(); + + openVerticalBox(""); + { + addJConvButton("convolver settings", &gx_engine::audio.filebutton); + addJToggleButton("run convolver", &gx_jconv::GxJConvSettings::checkbutton7); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + //----- end of the upper box + + //----- the middle box, + openExpanderBox(" CONTROLS ", &gx_engine::audio.fexpand); + { + //----- a handle box is a vertical box + openHandleBox(" "); + { + //----- arange all widgets in a horizontal scale + openHorizontalBox(""); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + //----- arange all widgets in a vertical scale + openPaintBox1(""); + { + //----- the left widget side, volume, tone, fuzz + openHorizontalBox(""); + { + //----- open a box for the volume controllers + openFrameBox(""); + closeBox(); + openVerticalBox(""); + { + openFrameBox(""); + closeBox(); + openHorizontalBox(""); + { + openFrameBox(""); + closeBox(); + // add a meter level box: out of box stack, no need to closeBox + openLevelMeterBox("Signal Level"); + openFrameBox(""); + closeBox(); + } + closeBox(); + openVerticalBox(""); + { + openSpaceBox(""); + closeBox(); + addselector("eqt.onetwo",""); + openHorizontalBox(""); + { + openSpaceBox(""); + closeBox(); + addminiswitch("eq.on_off", "EQ"); + openVerticalSwitchBox(" ",0, 1, &gx_engine::audio.witcheq); + { + + openDialogBox("eq", &gx_engine::audio.fdialogbox_eq, &gx_engine::audio.feq); + { + openPlugBox(""); + { + openVerticalBox(""); + { + openHorizontalTableBox(""); + { + addVerticalSlider("eq.f31_25","31,25"); + addVerticalSlider("eq.f62_5"," 62,5"); + addVerticalSlider("eq.f125"," 125 "); + addVerticalSlider("eq.f250"," 250 "); + addVerticalSlider("eq.f500"," 500 "); + addVerticalSlider("eq.f1k"," 1k "); + addVerticalSlider("eq.f2k"," 2k "); + addVerticalSlider("eq.f4k"," 4k "); + addVerticalSlider("eq.f8k"," 8k "); + addVerticalSlider("eq.f16k"," 16k "); + } + closeBox(); + openHorizontalTableBox(""); + { + addregler("eq.Q31_25"," Q "); + addregler("eq.Q62_5","Q"); + addregler("eq.Q125","Q"); + addregler("eq.Q250","Q"); + addregler("eq.Q500","Q"); + addregler("eq.Q1k","Q"); + addregler("eq.Q2k","Q"); + addregler("eq.Q4k","Q"); + addregler("eq.Q8k","Q"); + addregler("eq.Q16k","Q"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + openVerticalSwitchBox(" ",1, 1, &gx_engine::audio.witcheq); + { + openDialogBox("eqs", &gx_engine::audio.fdialogbox_eqs, &gx_engine::audio.feq); + { + openPlugBox(""); + { + openVerticalBox(""); + { + openHorizontalTableBox(""); + { + addSpinValueBox("eqs.freq31_25" ,""); + addSpinValueBox("eqs.freq62_5" ,""); + addSpinValueBox("eqs.freq125" ,""); + addSpinValueBox("eqs.freq250" ,""); + addSpinValueBox("eqs.freq500" ,""); + addSpinValueBox("eqs.freq1k" ,""); + addSpinValueBox("eqs.freq2k" ,""); + addSpinValueBox("eqs.freq4k" ,""); + addSpinValueBox("eqs.freq8k" ,""); + addSpinValueBox("eqs.freq16k" ,""); + + } + closeBox(); + openHorizontalTableBox(""); + { + addVerticalSlider("eqs.fs31_25",""); + addVerticalSlider("eqs.fs62_5",""); + addVerticalSlider("eqs.fs125",""); + addVerticalSlider("eqs.fs250",""); + addVerticalSlider("eqs.fs500",""); + addVerticalSlider("eqs.fs1k",""); + addVerticalSlider("eqs.fs2k",""); + addVerticalSlider("eqs.fs4k",""); + addVerticalSlider("eqs.fs8k",""); + addVerticalSlider("eqs.fs16k",""); + } + closeBox(); + openHorizontalTableBox(""); + { + addregler("eqs.Qs31_25"," Q "); + addregler("eqs.Qs62_5","Q"); + addregler("eqs.Qs125","Q"); + addregler("eqs.Qs250","Q"); + addregler("eqs.Qs500","Q"); + addregler("eqs.Qs1k","Q"); + addregler("eqs.Qs2k","Q"); + addregler("eqs.Qs4k","Q"); + addregler("eqs.Qs8k","Q"); + addregler("eqs.Qs16k","Q"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + } + closeBox(); + } + closeBox(); + } + closeBox(); + openFrameBox(""); + closeBox(); + + openVerticalBox(""); + { + + openFlipLabelBox("volume"); + { + openHorizontalBox(""); + { + openSpaceBox(""); + closeBox(); + addbigregler("amp.in_level"); + openSpaceBox(""); + closeBox(); + addbigregler("amp.out_master"); + openSpaceBox(""); + closeBox(); + } + closeBox(); + openSpaceBox(""); + closeBox(); + } + closeBox(); + //----- volume controll ready + + //----- open a box for the tone and the fuzz controllers + openFlipLabelBox("tone"); + { + openHorizontalBox(""); + { + openSpaceBox(""); + closeBox(); + addregler("amp.tonestack.Bass"); + openSpaceBox(""); + closeBox(); + addregler("amp.tonestack.Middle"); + openSpaceBox(""); + closeBox(); + addregler("amp.tonestack.Treble"); + openSpaceBox(""); + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + addminiswitch("amp.bass_boost.on_off", "bass boost "); + openSpaceBox(""); + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + addselector("amp.tonestack.select",""); + openVerticalBox1(""); + closeBox(); + } + closeBox(); + openSpaceBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + + } + closeBox(); + //----- end tone and fuzz controll + + openHorizontalBox(""); + { + openVerticalBox("shaper "); + { + addswitch("shaper.on_off", ""); + openFrameBox(""); + { + addHorizontalWheel("shaper.sharper"); + } + closeBox(); + } + closeBox(); + openVerticalBox(" noise gate "); + { + addswitch("noise_gate.on_off", ""); + openFrameBox(""); + { + addHorizontalWheel("noise_gate.threshold"," threshold "); + } + closeBox(); + } + closeBox(); + openVerticalBox("anti aliase"); + { + addswitch("anti_aliase.on_off", ""); + openFrameBox(""); + { + addHorizontalWheel("anti_aliase.feedback", " feedback "); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + //----- the next part in the vertical box, + openExpanderBox(" amplifier", &gx_engine::audio.fampexpand); + { + openAmpBox(""); + { + openAmpBox(" "); + { + openHorizontalBox(""); + { + //openSpaceBox(""); + //closeBox(); + openVerticalBox1("model "); + { + openVerticalBox1(""); + closeBox(); + addselector("amp.model",""); + } + closeBox(); + + openVerticalBox1(""); + { + addminiswitch("amp.oversample.on_off", "oversample "); + const char* labels[8] ={" 1x"," 2x", " 3x"," 4x"," 5x", " 6x", " 7x", " 8x"}; + addselector("amp.select","",8,labels); //FIXME FIX formatting issue + } + closeBox(); + + /*openVerticalBox1(""); + { + addminiswitch("amp.bass_boost.on_off", "bass boost "); + openSpaceBox(""); + closeBox(); + openVerticalBox1(""); + closeBox(); + } + closeBox();*/ + + openVerticalBox1(""); + { + addminiswitch("convolve.on_off", "amp tune "); + addselector("convolve.select",""); + + } + closeBox(); + } + closeBox(); + } + closeBox(); + //----- the second part in the vertical box + openAmpBox(" "); + { + openVerticalSwitchBox(" ",0, 2, &gx_engine::audio.witchamp); + { + openHorizontalBox(""); + { + openVerticalBox(""); + { + openVerticalBox(""); + { + addswitch("preamp.on_off", "preamp"); + addHorizontalWheel("preamp.atan"); + } + closeBox(); + openFrameBox(""); + { + } + closeBox(); + openVerticalBox(""); + { + addswitch("drive.on_off", "drive"); + addHorizontalWheel("drive.value", "drive"); + } + closeBox(); + } + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox(""); + { + openVerticalBox(""); + { + addswitch("tube.on_off", "tube"); + addHorizontalWheel("tube.fuzzy"); + } + closeBox(); + openFrameBox(""); + { + } + closeBox(); + openVerticalBox(""); + { + addswitch("tube.vibrato.on_off", "vibrato"); + addHorizontalWheel("tube.vibrato", "vibrato"); + } + closeBox(); + + } + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox(""); + { + openVerticalBox(""); + { + addswitch("tube2.on_off", "tube2"); + openFrameBox(""); + { + addHorizontalWheel("tube2.fuzzy"); + } + closeBox(); + } + closeBox(); + openVerticalBox(""); + { + openVerticalBox1("resonanz"); + { + addHorizontalWheel("tube2.resonanz", "reso"); + } + closeBox(); + openVerticalBox1("vibrato"); + { + addHorizontalWheel("tube2.vibrato"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openFrameBox(""); + closeBox(); + + openVerticalBox(""); + { + openVerticalBox(""); + { + addswitch("tube3.on_off", "tube3"); + openFrameBox(""); + { + addHorizontalWheel("tube3.g"); + } + closeBox(); + + } + closeBox(); + openVerticalBox(""); + { + openVerticalBox1("dist"); + { + addHorizontalWheel("tube3.dist", "dist"); + } + closeBox(); + openVerticalBox1("level"); + { + addHorizontalWheel("tube3.q", "level"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + openVerticalSwitchBox(" ",1, 2, &gx_engine::audio.witchamp); + { + openHorizontalBox(""); + { + openVerticalBox(""); + { + openVerticalBox(""); + { + addtoggle1("amp2.preamp.ON", "preamp"); + openSpaceBox(""); + closeBox(); + addregler("amp2.preamp.Pregain",""); + } + closeBox(); + + } + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox(""); + { + openVerticalBox(""); + { + addtoggle1("amp2.stage1.ON", "tube"); + openSpaceBox(""); + closeBox(); + addregler("amp2.stage1.gain1",""); + } + closeBox(); + + } + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox(""); + { + openVerticalBox(""); + { + addtoggle1("amp2.stage2.ON", "tube2"); + openSpaceBox(""); + closeBox(); + addregler("amp2.stage2.gain2",""); + } + closeBox(); + + } + closeBox(); + openFrameBox(""); + closeBox(); + + openVerticalBox(""); + { + openVerticalBox(""); + { + addtoggle1("stage3.ON", "tube3"); + openSpaceBox(""); + closeBox(); + addregler("stage3.gain3",""); + } + closeBox(); + + } + closeBox(); + } + closeBox(); + + } + closeBox(); + + + } + closeBox(); + + } + closeBox(); + } + closeBox(); + //openpaintampBox(""); + //closeBox(); + } + closeBox(); + //----- end + openFrameBox(""); + closeBox(); + //----- this box include all effects and the osccilloscope + openHorizontalBox(""); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox1(""); + { + openHorizontalBox(""); + { + } + closeBox(); + + //----- this box include only the effects + openScrollBox(""); + { + openHorizontalBox(""); + { + openHorizontalTableBox(""); + { + //----- the compressor + openHorizontalOrderBox("", &gx_engine::audio.posit5); + { + openVerticalBox("compressor"); + { + openSpaceBox(""); + closeBox(); + addregler("compressor.ratio"); + openHorizontalBox(""); + { + addtoggle("compressor.on_off", ""); + //----- open a dialogbox(toplevel widget) and put the advanced controlls in it + openDialogBox("compressor", &gx_engine::audio.fdialogbox8, &gx_engine::audio.fcheckboxcom1); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox("compressor"); + { + openHorizontalBox(""); + { + addregler("compressor.knee"); + addregler("compressor.ratio"); + addregler("compressor.threshold"); + } + closeBox(); + openVerticalBox("envelop"); + { + addslider("compressor.attack"); + addslider("compressor.release"); + } + closeBox(); + } + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + //----- end advanced settings widget + closeBox(); + } + closeBox(); + //----- end compressor + } + closeBox(); + openHorizontalOrderBox("", &gx_engine::audio.posit1); + { + //----- overdrive + openVerticalBox("overdrive"); + { + openSpaceBox(""); + closeBox(); + addregler("overdrive.drive"," drive "); + addtoggle("overdrive.on_off", ""); + } + closeBox(); + //-----end overdrive + } + closeBox(); + + openHorizontalOrderBox("", &gx_engine::audio.posit2); + { + //----- distortion + openVerticalBox("distortion"); + { + addselector("distortiont.onetwo",""); + //addswitch("distortion.onetwo", ""); + openVerticalSwitchBox(" ",0, 0, &gx_engine::audio.witchdistortion); + { + addregler("distortion.drive"," drive "); + openHorizontalBox(""); + { + addtoggle("distortion.on_off", ""); + + //----- open a dialogbox(toplevel widget) and put the advanced controlls in it + + openDialogBox("distortion", &gx_engine::audio.fdialogbox1, &gx_engine::audio.fcheckbox4); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openHorizontalBox(""); + { + openVerticalBox(""); + { + openHorizontalBox(""); + { + openVerticalBox1(""); + { + addbigregler("distortion.drive"," drive "); + addregler("distortion.level"," level "); + addregler("distortion.gain"," gain "); + } + closeBox(); + openVerticalBox1(""); + { + openHorizontalBox(""); + { + openVerticalBox1(""); + { + addregler("distortion.low_drive"," low drive "); + addregler("distortion.low_gain"," low gain "); + } + closeBox(); + openVerticalBox1(""); + { + addregler("distortion.middle_drive"," middle drive "); + addregler("distortion.middle_gain"," middle gain "); + } + closeBox(); + openVerticalBox1(""); + { + addregler("distortion.high_drive"," high drive "); + addregler("distortion.high_gain"," high gain "); + } + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + addslider("distortion.split_low_freq", "split low freq"); + addslider("distortion.split_high_freq", "split high freq"); + openSpaceBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openHorizontalTableBox(""); + { + openVerticalBox("low/highpass"); + { + addregler("distortion.low_highpass.high_freq","high-pass "); + addregler("distortion.low_highpass.low_freq"," low-pass "); + addtoggle("distortion.low_highpass.on_off", ""); + } + closeBox(); + openVerticalBox("low/highcut"); + { + addregler("distortion.low_highcutoff.low_freq"," low-cut "); + addregler("distortion.low_highcutoff.high_freq","high-cut "); + addtoggle("distortion.low_highcutoff.on_off",""); + } + closeBox(); + openVerticalBox("resonator"); + { + addregler("distortion.trigger","trigger "); + addregler("distortion.vibrato"," vibrato "); + addtoggle("distortion.resonator.on_off",""); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + //----- end advanced settings widget + closeBox(); + } + closeBox(); + //----- end distortion + } + closeBox();//end switchbox + + openVerticalSwitchBox(" ",1, 0, &gx_engine::audio.witchdistortion); + { + addregler("distortion1.drive"," drive "); + openHorizontalBox(""); + { + addtoggle("distortion.on_off", ""); + openDialogBox("distortion1", &gx_engine::audio.fdis1, &gx_engine::audio.fcheckbox4); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openHorizontalBox(""); + { + openHorizontalTableBox(""); + { + addbigregler("distortion1.drive"," drive "); + addregler("distortion1.level","\n\n level"); + addregler("distortion1.gain","\n\n gain"); + } + closeBox(); + openHorizontalTableBox(""); + { + openVerticalBox("low/highpass"); + { + openHorizontalBox(""); + { + addregler("distortion1.low_highpass.high_freq","high-freq "); + addregler("distortion1.low_highpass.low_freq"," low-freq "); + } + closeBox(); + addtoggle("distortion1.low_highpass.on_off", ""); + } + closeBox(); + openVerticalBox("low/highcutoff"); + { + openHorizontalBox(""); + { + addregler("distortion1.low_highcutoff.high_freq","high-freq "); + addregler("distortion1.low_highcutoff.low_freq"," low-freq "); + } + closeBox(); + + addtoggle("distortion1.low_highcutoff.on_off",""); + } + closeBox(); + openVerticalBox("resonanz"); + { + openHorizontalBox(""); + { + addregler("distortion1.trigger","trigger "); + addregler("distortion1.vibrato"," vibrato "); + } + closeBox(); + addtoggle("distortion1.resonator.on_off",""); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + openHorizontalOrderBox("", &gx_engine::audio.posit3); + { + //----- freeverb + openVerticalBox(" freeverb"); + { + openSpaceBox(""); + closeBox(); + addregler("freeverb.RoomSize"); + openHorizontalBox(""); + { + addtoggle("freeverb.on_off",""); + //----- open a dialogbox(toplevel widget) and put the advanced controlls in it + openDialogBox("freeverb", &gx_engine::audio.fdialogbox2, &gx_engine::audio.fcheckbox6); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openHorizontalTableBox(""); + { + addbigregler("freeverb.RoomSize"); + addregler("freeverb.damp"); + addregler("freeverb.wet_dry"); + } + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + //----- end advanced settings widget + closeBox(); + } + closeBox(); + //----- end freeverb + } + closeBox(); + + openHorizontalOrderBox("", &gx_engine::audio.posit4); + { + //----- IR + openVerticalBox("IR"); + { + addselector("IR.auto_freq",""); + openHorizontalBox(""); + { + addregler("IR.freq"," freq "); + //addregler("IR.peak"," peak "); + } + closeBox(); + openHorizontalBox(""); + { + addtoggle("", &gx_engine::audio.fcheckbox8); + //----- open a dialogbox(toplevel widget) and put the advanced controlls in it + openDialogBox("IR", &gx_engine::audio.fdialogbox3, &gx_engine::audio.fcheckbox8); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openVerticalBox1(""); + { + + openHorizontalBox(""); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openHorizontalTableBox(""); + { + addbigregler("IR.freq"," freq "); + addregler("IR.peak"," peak "); + addregler("IR.bandwidth"," bandwidth "); + } + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + + } + closeBox(); + openHorizontalBox(""); + { + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + addselector("IR.auto_freq",""); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + } + closeBox(); + openSpaceBox(""); + closeBox(); + + } + closeBox(); + + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + //----- end advanced settings widget + closeBox(); + } + closeBox(); + //----- end IR + } + closeBox(); + + openHorizontalOrderBox("", &gx_engine::audio.posit0); + { + //----- crybaby + openVerticalBox("crybaby"); + { + addselector("crybaby.autowah",""); + //addminiswitch("crybaby.autowah"," autowah"); + addregler("crybaby.wah"," wah "); + openHorizontalBox(""); + { + addtoggle("", &gx_engine::audio.fcheckbox5); + //----- open a dialogbox(toplevel widget) and put the advanced controlls in it + openDialogBox("crybaby", &gx_engine::audio.fdialogbox4, &gx_engine::audio.fcheckbox5); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox(""); + { + openHorizontalTableBox(""); + { + addbigregler("crybaby.wah"," wah "); + addregler("crybaby.level"," level "); + addregler("crybaby.wet_dry","wet/dry"); + } + closeBox(); + openHorizontalBox(""); + { + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + addselector("crybaby.autowah",""); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + } + closeBox(); + openSpaceBox(""); + closeBox(); + + } + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + //----- end advanced settings widget + closeBox(); + } + closeBox(); + //----- end crybaby + } + closeBox(); + + openHorizontalOrderBox("", &gx_engine::audio.posit6); + { + //----- echo + openVerticalBox("echo"); + { + openSpaceBox(""); + closeBox(); + openHorizontalBox(""); + { + + addregler("echo.time"," time "); + } + closeBox(); + openHorizontalBox(""); + { + addtoggle("echo.on_off",""); + openDialogBox("echo", &gx_engine::audio.fdialogbox_echo, (int*)&gx_engine::audio.fcheckbox7); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openVerticalBox(""); + { + openHorizontalBox(""); + { + addregler("echo.time"," time "); + addregler("echo.percent"," % "); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + //----- end echo + openHorizontalOrderBox("", &gx_engine::audio.posit7); + { + openVerticalBox("delay"); + { + openSpaceBox(""); + closeBox(); + openHorizontalBox(""); + { + addregler("delay.delay"," delay "); + + } + closeBox(); + openHorizontalBox(""); + { + addtoggle("delay.on_off",""); + + openDialogBox("delay", &gx_engine::audio.fdialogbox_delay, (int*)&gx_engine::audio.fdelay); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openVerticalBox(""); + { + openHorizontalBox(""); + { + addregler("delay.delay"," delay "); + addregler("delay.gain"," gain "); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + //----- chorus + openHorizontalRestetBox("", &gx_engine::audio.posit8); + { + openVerticalBox("chorus"); + { + openSpaceBox(""); + closeBox(); + addregler("chorus.level"); + openHorizontalBox(""); + { + addtoggle("chorus.on_off",""); + openDialogBox("chorus", &gx_engine::audio.fchorusbox, &gx_engine::audio.fchorus); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openVerticalBox(""); + { + openHorizontalTableBox(""); + { + addbigregler("chorus.level"," level "); + addregler("chorus.delay"," delay "); + addregler("chorus.depth"," depth "); + addregler("chorus.freq"," freq "); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + //end chorus + + openHorizontalRestetBox("", &gx_engine::audio.posit9); + { + openVerticalBox("flanger"); + { + addselector("flanger.invert",""); + addregler("flanger.level"); + openHorizontalBox(""); + { + addtoggle("flanger.on_off",""); + openDialogBox("flanger", &gx_engine::audio.fflangerbox, &gx_engine::audio.fflanger); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openVerticalBox(""); + { + openHorizontalTableBox(""); + { + addbigregler("flanger.level"," level "); + addregler("flanger.feedback gain"," feedback gain "); + addregler("flanger.depth"," depth "); + addregler("flanger.flange delay"," delay "); + addregler("flanger.flange delay offset"," delay offset"); + addregler("flanger.LFO freq"," LFO freq "); + + } + closeBox(); + openHorizontalBox(""); + { + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + addselector("flanger.invert",""); + openSpaceBox(""); + closeBox(); + openSpaceBox(""); + closeBox(); + } + closeBox(); + openSpaceBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + } + closeBox(); + } + closeBox(); + //----- close vertical effect box + + //----- open a box for the oscilloscope + openVerticalBox1(""); + { + openHorizontalBox(""); + { + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openVerticalBox1(""); + { + openHorizontalBox(""); + { + //----- the oscilloscope + addLiveWaveDisplay(" ", &gx_engine::audio.viv , &gx_engine::audio.vivi); + } + closeBox(); + openVerticalBox1(""); + { + openHorizontalBox(""); + { + openSlooperBox("slooper"); + { + openVerticalBox1(""); + { + + + addregler("SampleLooper.gain"," gain "); + + openHorizontalBox(""); + { + openSpaceBox(""); + closeBox(); + addminiswitch("SampleLooper.on_off",""); + + addRecButton("SampleLooper.Capture","capture "); + addPlayButton("SampleLooper.Play"," play "); + openSpaceBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + //addtoggle("SampleLooper.on_off",""); + } + closeBox(); + openPaintBox(""); + { + openHorizontalBox(""); + { + addminieqswitch("biquad.on_off"," BiQuad Filter "); + openDialogBox("biquad", &gx_engine::audio.fbiquadbox, (int*)&gx_engine::audio.fbiquad); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openVerticalBox(""); + { + openHorizontalBox(""); + { + addregler("biquad.Freq"," Hz "); + + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + addminieqswitch("MultiBandFilter.on_off"," MultiBandFilter"); + openDialogBox("MultiBandFilter", &gx_engine::audio.fdialogbox_mbf, &gx_engine::audio.fmultifilter); + { + openPlugBox(""); + { + openVerticalBox(""); + { + openHorizontalTableBox(""); + { + addVerticalSlider("MultiBandFilter.f31_25","31,25"); + addVerticalSlider("MultiBandFilter.f62_5"," 62,5"); + addVerticalSlider("MultiBandFilter.f125"," 125 "); + addVerticalSlider("MultiBandFilter.f250"," 250 "); + addVerticalSlider("MultiBandFilter.f500"," 500 "); + addVerticalSlider("MultiBandFilter.f1k"," 1k "); + addVerticalSlider("MultiBandFilter.f2k"," 2k "); + addVerticalSlider("MultiBandFilter.f4k"," 4k "); + addVerticalSlider("MultiBandFilter.f8k"," 8k "); + addVerticalSlider("MultiBandFilter.f16k"," 16k "); + } + closeBox(); + openHorizontalTableBox(""); + { + addregler("MultiBandFilter.Q31_25"," Q "); + addregler("MultiBandFilter.Q62_5","Q"); + addregler("MultiBandFilter.Q125","Q"); + addregler("MultiBandFilter.Q250","Q"); + addregler("MultiBandFilter.Q500","Q"); + addregler("MultiBandFilter.Q1k","Q"); + addregler("MultiBandFilter.Q2k","Q"); + addregler("MultiBandFilter.Q4k","Q"); + addregler("MultiBandFilter.Q8k","Q"); + addregler("MultiBandFilter.Q16k","Q"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + addminieqswitch("moog.on_off"," Moog Filter "); + openDialogBox("moog", &gx_engine::audio.fdialogbox_moo, (int*)&gx_engine::audio.fmoog); + { + openPlugBox(""); + { + openHandleBox(" "); + { + openVerticalBox(""); + { + openHorizontalBox(""); + { + addregler("moog.Q"," Q "); + addregler("moog.fr"," Hz "); + + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + addminicabswitch("cab.on_off"," Cab-ImpResp "); + } + closeBox(); + openSlooperBox("limiter"); + { + + + addregler("amp.fuzz"); + + const char* lab[3] = {" off"," clip","foldback"}; + addselector("amp.threshold",(const char*)0,3,lab); //FIXME FIX formatting issue + openSpaceBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openVerticalBox1(""); + closeBox(); + } + closeBox(); + //----- fill empty space + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + } + //----- close ocsilloscope box + closeBox(); + openHorizontalBox(""); + closeBox(); + openHorizontalBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + openFrameBox(""); + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + //----- close the vertical box for effects and oscilloscope + + //----- open the 3. box on botton of the main widget + openEventBox(" FEEDBACK "); + { + openHorizontalBox(""); + { + openVerticalBox(""); + { + //----- the midi widget + openVerticalMidiBox(""); + { + openHorizontalBox("midi_out"); + { + //----- create the midi settings dialog + openDialogBox("midi_out", &gx_engine::audio.fdialogbox6, (int*)&gx_engine::audio.midistat); + { + openPlugBox(""); + { + openTabBox(""); + { + openVerticalBox("channel1"); + { + openEventBox(" "); + { + openHorizontalBox(""); + { + addregler("midi_out.channel_1.velocity"); + openVerticalBox(""); + { + addregler("midi_out.channel_1.volume"); + addCheckButton("midi_out.channel_1.autogain"); + } + closeBox(); + openVerticalBox(""); + { + addNumEntry("midi_out.channel_1.channel"); + addNumEntry("midi_out.channel_1.program"); + } + closeBox(); + addregler("midi_out.channel_1.oktave"); + addregler("midi_out.channel_1.sensity"); + } + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + openHorizontalBox(" "); + closeBox(); + openHorizontalBox(" "); + { + addPToggleButton("midi_out.channel_1.auto_pitch"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openVerticalBox("channel2"); + { + openEventBox(" "); + { + openHorizontalBox(""); + { + addregler("midi_out.channel_2.velocity"); + openVerticalBox(""); + { + addregler("midi_out.channel_2.volume"); + addCheckButton("midi_out.channel_2.autogain"); + } + closeBox(); + openVerticalBox(""); + { + addNumEntry("midi_out.channel_2.channel"); + addNumEntry("midi_out.channel_2.program"); + } + closeBox(); + addregler("midi_out.channel_2.oktave"); + addregler("midi_out.channel_2.sensity"); + } + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + addtoggle("midi_out.channel_2.on_off", ""); + openHorizontalBox(" "); + { + addPToggleButton("midi_out.channel_2.auto_pitch"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openVerticalBox("channel3"); + { + openEventBox(" "); + openHorizontalBox(""); + { + addregler("midi_out.channel_3.velocity"); + openVerticalBox(""); + { + addregler("midi_out.channel_3.volume"); + addCheckButton("midi_out.channel_3.autogain"); + } + closeBox(); + openVerticalBox(""); + { + addNumEntry("midi_out.channel_3.channel"); + addNumEntry("midi_out.channel_3.program"); + } + closeBox(); + addregler("midi_out.channel_3.oktave"); + addregler("midi_out.channel_3.sensity"); + } + closeBox(); + } + closeBox(); + openHorizontalBox(""); + { + addtoggle("midi_out.channel_3.on_off", ""); + openHorizontalBox(" "); + { + addPToggleButton("midi_out.channel_3.auto_pitch"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + + openVerticalBox("beat_detector"); + { + openEventBox(" "); + { + openHorizontalBox(""); + { + addregler("beat_detector.stepper"); + addregler("beat_detector.note_off"); + addregler("beat_detector.atack_gain"); + addregler("beat_detector.beat_gain"); + } + closeBox(); + } + closeBox(); + addStatusDisplay("", &gx_engine::audio.midistat); + openVerticalBox("Midi gain"); + { + addHorizontalWheel("beat_detector.midi_gain"); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + } + closeBox(); + openVerticalBox(""); + { + //----- add the controlers for feedback feedforward to the bottob box + addslider("amp.feedback"," feedback"); + } + closeBox(); + openVerticalBox(""); + { + addslider("amp.feedforward"," feedforward"); + } + closeBox(); + //----- the toggle button to start/stop jack_capture + openFrameBox(""); + { + addToggleButton("record", 0); + } + closeBox(); + //----- end jack_capture + } + closeBox(); + //----- close botton box + } + closeBox(); + //----- close main box + // add a log message box: out of box stack, no need to closeBox + openTextLoggingBox("Logging Window"); + closeBox(); + // add a Patch Info widget + openPatchInfoBox(&gx_gui::show_patch_info); + + debug_check(all_midi_params_assigned); +} + +} diff --git a/src/gx_jack.cpp b/src/gx_jack.cpp new file mode 100644 index 0000000..eb9982c --- /dev/null +++ b/src/gx_jack.cpp @@ -0,0 +1,917 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix interface to the jackd audio / midi server + * + * -------------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include "guitarix.h" + +#ifdef HAVE_JACK_SESSION +#include +#endif + +using namespace gx_system; +using namespace gx_engine; +using namespace gx_jconv; +using namespace gx_child_process; + +namespace gx_jack +{ + +sem_t jack_sync_sem; + +//----- pop up a dialog for starting jack +bool gx_jack_init( const string *optvar ) +{ + jack_status_t jackstat; + client_name = "guitarix_amp"; + client_insert_name = "guitarix_fx"; + client_instance = "guitarix"; + + AVOIDDENORMALS; + + sem_init(&jack_sync_sem, 0, 0); + + // init the pointer to the jackbuffer + for (int i=0; i < nOPorts; i++) output_ports[i] = 0; + for (int i=0; i < nIPorts; i++) input_ports [i] = 0; + +#ifdef HAVE_JACK_SESSION + // try to open jack client + if (! optvar[JACK_UUID].empty()) { + + client = jack_client_open (client_name.c_str(), jack_options_t(JackNoStartServer | JackSessionID), &jackstat, optvar[JACK_UUID].c_str()); + } else { + client = jack_client_open (client_name.c_str(), JackNoStartServer, &jackstat); + } +#else + client = jack_client_open (client_name.c_str(), JackNoStartServer, &jackstat); +#endif + // ----- only start the insert client when the amp client is true + if (client) { + client_insert = jack_client_open (client_insert_name.c_str(), JackNoStartServer, &jackstat); + } + if (client == 0) { + // skip useless message + //gx_print_warning("Jack Init", "not yet a jack client"); + + // if jackd is running, let's call ourselves again + if (gx_system_call("pgrep", "jackd", true) == SYSTEM_OK) { + gx_print_warning("Jack Init", "jackd OK, trying to be a client"); + usleep(500000); + return gx_jack_init( optvar ); + } + + // start a dialog + if (gx_start_jack_dialog()) + { + // so let's try to be a jack client again + client = jack_client_open (client_name.c_str(), JackNoStartServer, &jackstat); + client_insert = jack_client_open (client_insert_name.c_str(), JackNoStartServer, &jackstat); + + if (!client) + { + gx_print_error("main", + string("I really tried to get jack up and running, sorry ... ")); + return false; + } + } + + else // we give up + { + gx_print_error("main", + string("Ignoring jackd ...")); + return false; + } + } + + // ---------------------------------- + jack_is_down = false; + is_rt = jack_is_realtime (client); + + // it is maybe not the 1st guitarix instance ? + if (jackstat & JackNameNotUnique) { + client_name = jack_get_client_name (client); + client_insert_name = jack_get_client_name (client_insert); + assert(client_name.substr(0,12) == "guitarix_amp"); + client_instance = client_name.substr(0,8) + client_name.substr(12); + } + +#ifdef USE_RINGBUFFER + jack_ringbuffer = jack_ringbuffer_create(2048*sizeof(struct MidiMessage)); + + if (jack_ringbuffer == NULL) + { + g_critical("Cannot create JACK ringbuffer."); + gx_clean_exit(NULL, NULL); + } + + jack_ringbuffer_reset(jack_ringbuffer); + jack_ringbuffer_mlock(jack_ringbuffer); + +#endif + + jack_sr = jack_get_sample_rate (client); // jack sample rate + ostringstream s; + s << "The jack sample rate is " << jack_sr << "/sec"; + gx_print_info("Jack init", s.str().c_str()); + + jack_bs = jack_get_buffer_size (client); // jack buffer size + s.str(""); + s << "The jack buffer size is " << jack_bs << "/frames ... "; + + gx_print_info("Jack init", s.str()); + + + if (gx_gui::fWindow) { + string window_name = "guitarix"; + gtk_window_set_title (GTK_WINDOW (gx_gui::fWindow), window_name.c_str()); + } + + return true; +} + +struct PortConnData +{ + string name_a, name_b; + int connect; + PortConnData(string a, string b, int conn): name_a(a), name_b(b), connect(conn) {} +}; + +static gboolean gx_jack_portconn_helper(gpointer data) +{ + PortConnData *pc = (PortConnData*)data; + if (gx_gui::PortMapWindow::instance) { + gx_gui::PortMapWindow::instance->connection_changed(pc->name_a, pc->name_b, pc->connect); + } + delete pc; + return FALSE; +} + +static void gx_jack_portconn_callback(jack_port_id_t a, jack_port_id_t b, int connect, void*) +{ + if (!client) { + return; + } + jack_port_t* port_a = jack_port_by_id(client, a); + jack_port_t* port_b = jack_port_by_id(client, b); + if (!port_a || !port_b) { + return; + } + gtk_idle_add(gx_jack_portconn_helper, + new PortConnData(jack_port_name(port_a), jack_port_name(port_b), + connect)); + // check if we are connected + const char** port = jack_port_get_connections(input_ports[0]); + if (port) { // might be 0 (e.g. due to race conditions) + + NO_CONNECTION = 0; + free(port); + } + else { + NO_CONNECTION = 1; + } +} + + +//----- set client callbacks and activate client +// Note: to be called after gx_engine::gx_engine_init() +void gx_jack_callbacks_and_activate() +{ + //----- set the jack callbacks + jack_set_xrun_callback(client, gx_jack_xrun_callback, NULL); + jack_set_sample_rate_callback(client, gx_jack_srate_callback, 0); + jack_on_shutdown(client, gx_jack_shutdown_callback, NULL); + jack_set_buffer_size_callback (client, gx_jack_buffersize_callback, 0); + jack_set_process_callback(client, gx_jack_process, 0); + jack_set_process_callback(client_insert, gx_jack_insert_process, 0); + jack_set_port_registration_callback(client, gx_jack_portreg_callback, 0); + jack_set_port_connect_callback(client, gx_jack_portconn_callback, 0); +#ifdef HAVE_JACK_SESSION + if (jack_set_session_callback) { + jack_set_session_callback (client, gx_jack_session_callback, 0); + } +#endif + + //----- register the midi input channel + midi_input_port = + jack_port_register(client, "midi_in_1", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); + + //----- register the input channel + input_ports[0] = + jack_port_register(client, "in_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + input_ports[1] = + jack_port_register(client_insert, "in_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + + //----- register the midi output channel + midi_output_ports = + jack_port_register(client, "midi_out_1", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); + + //----- register the audio output channels + for (int i = 0; i < 1; i++) { + ostringstream buf; + buf << "out_" << i; + output_ports[i] = + jack_port_register(client, buf.str().c_str(), + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + //----- register the audio fx output channels + for (int i = 2; i < 4; i++) { + ostringstream buf; + buf << "out_" << i-2; + output_ports[i] = + jack_port_register(client_insert, buf.str().c_str(), + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + + //----- ready to go + if (jack_activate(client)) + { + gx_print_error("Jack Activation", + string("Can't activate JACK client")); + gx_clean_exit(NULL, NULL); + } + if (jack_activate(client_insert)) + { + gx_print_error("Jack Activation", + string("Can't activate JACK client")); + gx_clean_exit(NULL, NULL); + } +} + +//----- connect ports if we know them +void gx_jack_init_port_connection(const string* optvar) +{ + // set autoconnect capture to user capture port + if (!optvar[JACK_INP].empty()) + { + jack_connect(client, optvar[JACK_INP].c_str(), + jack_port_name(input_ports[0])); + } else { + list& l = jack_connection_lists[kAudioInput]; + for (list::iterator i = l.begin(); i != l.end(); i++) { + jack_connect(client, i->c_str(), jack_port_name(input_ports[0])); + } + } + + // set autoconnect midi to user midi port + if (midi_input_port && !optvar[JACK_MIDI].empty()) + { + jack_connect(client, optvar[JACK_MIDI].c_str(), + jack_port_name(midi_input_port)); + } else { + list& l = jack_connection_lists[kMidiInput]; + for (list::iterator i = l.begin(); i != l.end(); i++) { + jack_connect(client, i->c_str(), jack_port_name(midi_input_port)); + } + } + + // set autoconnect to user playback ports + if (optvar[JACK_OUT1].empty() && optvar[JACK_OUT2].empty()) { + list& l1 = jack_connection_lists[kAudioOutput1]; + for (list::iterator i = l1.begin(); i != l1.end(); i++) { + jack_connect(client_insert, jack_port_name(output_ports[2]), i->c_str()); + } + list& l2 = jack_connection_lists[kAudioOutput2]; + for (list::iterator i = l2.begin(); i != l2.end(); i++) { + jack_connect(client_insert, jack_port_name(output_ports[3]), i->c_str()); + } + } else { + int idx = JACK_OUT1; + for (int i = 2; i < 4; i++) { + if (!optvar[idx].empty()) { + jack_connect(client_insert, + jack_port_name(output_ports[i]), optvar[idx].c_str()); + } + idx++; + } + } + + // autoconnect midi output port + list& lmo = jack_connection_lists[kMidiOutput]; + for (list::iterator i = lmo.begin(); i != lmo.end(); i++) { + jack_connect(client, jack_port_name(midi_output_ports), i->c_str()); + } + + // autoconnect to insert ports + list& lins_in = jack_connection_lists[kAudioInsertIn]; + list& lins_out = jack_connection_lists[kAudioInsertOut]; + bool ifound = false, ofound = false; + for (list::iterator i = lins_in.begin(); i != lins_in.end(); i++) { + int rc = jack_connect(client_insert, i->c_str(), jack_port_name(input_ports[1])); + if (rc == 0 || rc == EEXIST) { + ifound = true; + } + } + for (list::iterator i = lins_out.begin(); i != lins_out.end(); i++) { + int rc = jack_connect(client, jack_port_name(output_ports[0]), i->c_str()); + if (rc == 0 || rc == EEXIST) { + ofound = true; + } + } + if (!ifound || !ofound) { + jack_connect(client_insert, jack_port_name(output_ports[0]), (client_insert_name+":in_0").c_str()); + } +} + +//----- pop up a dialog for starting jack +bool gx_start_jack_dialog() +{ + //--- run dialog and check response + const guint nchoices = 3; + + const char* labels[] = + { + "Start Jack", "Ignore Jack", "Exit" + }; + + const gint responses[] = + { + GTK_RESPONSE_YES, GTK_RESPONSE_NO, GTK_RESPONSE_CANCEL + }; + + gint response = + gx_gui::gx_nchoice_dialog_without_entry ( + " Jack Starter ", + "\n WARNING \n\n" + " The jack server is not currently running\n" + " You can choose to activate it or terminate guitarix \n\n" + " 1) activate jack \n" + " 2) ignore jack, start guitarix anyway \n" + " 3) exit guitarix \n", + nchoices, + labels, + responses, + GTK_RESPONSE_YES + ); + + // we are cancelling + bool retstat = false; + + switch (response) + { + case GTK_RESPONSE_NO: + jack_is_down = true; + break; + + case GTK_RESPONSE_CANCEL: + gx_abort(NULL); + break; + + default: + case GTK_RESPONSE_YES: + retstat = gx_start_jack(NULL); + break; + } + + // start jack + return retstat; +} + + +//----start jack if possible +bool gx_start_jack(void* arg) +{ + // first, let's try via qjackctl + if (gx_system_call("which", "qjackctl", true) == SYSTEM_OK) + { + if (gx_system_call("qjackctl", "--start", true, true) == SYSTEM_OK) + { + sleep(5); + + // let's check it is really running + if (gx_system_call("pgrep", "jackd", true) == SYSTEM_OK) + { + return true; + } + } + } + + // qjackctl not found or not started, let's try .jackdrc + string jackdrc = "$HOME/.jackdrc"; + if (gx_system_call("ls", jackdrc.c_str(), true, false) == SYSTEM_OK) + { + // open it + jackdrc = string(getenv("HOME")) + string("/") + ".jackdrc"; + string cmdline = ""; + + ifstream f(jackdrc.c_str()); + if (f.good()) + { + // should contain only one command line + getline(f, cmdline); + f.close(); + } + + // launch jackd + if (!cmdline.empty()) + if (gx_system_call(cmdline.c_str(), "", true, true) == SYSTEM_OK) + { + sleep(2); + + // let's check it is really running + if (gx_system_call("pgrep", "jackd", true) == SYSTEM_OK) + { + return true; + } + } + + } + + return false; +} + +static gboolean gx_ports_refresh(gpointer data) +{ + // reload ports for portmap widget when needed + if (gx_gui::PortMapWindow::instance) { + gx_gui::PortMapWindow::instance->refresh(); + } + return false; +} + +//---- Jack server connection / disconnection +void gx_jack_connection(GtkCheckMenuItem *menuitem, gpointer arg) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM (menuitem)) == TRUE) { + if (!client) { + string optvar[NUM_SHELL_VAR]; + gx_assign_shell_var(shell_var_name[JACK_INP], optvar[JACK_INP] ); + gx_assign_shell_var(shell_var_name[JACK_MIDI], optvar[JACK_MIDI] ); + gx_assign_shell_var(shell_var_name[JACK_OUT1], optvar[JACK_OUT1]); + gx_assign_shell_var(shell_var_name[JACK_OUT2], optvar[JACK_OUT2]); + gx_assign_shell_var(shell_var_name[JACK_UUID], optvar[JACK_UUID]); + + if (gx_jack_init(optvar)) { + + // initialize guitarix engine if necessary + if (!gx_engine::initialized) { + gx_engine::gx_engine_init( optvar ); + } + gx_jack_callbacks_and_activate(); + gx_jack_init_port_connection(optvar); + + // refresh latency check menu + gx_gui::GxMainInterface* gui = gx_gui::GxMainInterface::instance(); + GtkWidget* wd = gui->getJackLatencyItem(gx_jack::jack_bs); + if (wd) { + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wd), TRUE); + } + if (!gx_engine::pt_initialized) { + sleep(5); + // -------- pitch tracker (needs jack thread running) ------------- + gx_engine::pitch_tracker.init(); + } + } + } + + if (client) { + if (gx_gui::gx_jackd_on_image) { + gtk_widget_show(gx_gui::gx_jackd_on_image); + gtk_widget_hide(gx_gui::gx_jackd_off_image); + } + jack_is_exit = false; + + gx_print_info("Jack Server", "Connected to Jack Server"); + } + } else { + gx_jack_cleanup(); + + // we bring down jack capture and meterbridge + Meterbridge::stop(); + JackCapture::stop(); + + if (gx_gui::gx_jackd_on_image) { + gtk_widget_hide(gx_gui::gx_jackd_on_image); + gtk_widget_show(gx_gui::gx_jackd_off_image); + } + + // engine buffers no longer ready + gx_engine::buffers_ready = false; + + gx_print_warning("Jack Server", "Disconnected from Jack Server"); + } + g_idle_add(gx_ports_refresh,NULL); +} + +//----jack latency change +void gx_set_jack_buffer_size(GtkCheckMenuItem* menuitem, gpointer arg) +{ + // are we a proper jack client ? + if (!client) + { + gx_print_error( + "Jack Buffer Size setting", + "we are not a jack client, server may be down" + ); + + return; + } + + // ----- if check button triggered menually + + // let's avoid triggering the jack server on "inactive" + if (gtk_check_menu_item_get_active(menuitem) == false) + return; + + // requested latency + jack_nframes_t buf_size = (jack_nframes_t)GPOINTER_TO_INT(arg); + + // if the actual buffer size is the same, no need further action + if (buf_size == jack_get_buffer_size(client)) + return; + + + // first time useage warning + GxJackLatencyChange change_latency = kChangeLatency; + + // if user still wants to be given a choice, let's trigger dialog + if (fwarn == 0.0) + change_latency = (GxJackLatencyChange)gx_gui::gx_wait_latency_warn(); + + // let's see + if (change_latency == kChangeLatency) + { + int jcio = 0; + if (conv.is_runnable()) + { + jcio = 1; + gx_jconv::GxJConvSettings::checkbutton7 = 0; + gx_jconv::checkbox7 = 0.0; + gx_gui::gx_start_stop_jconv(NULL, NULL); + } + + // let's resize the buffer + if (jack_set_buffer_size (client, buf_size) != 0) + gx_print_warning("Setting Jack Buffer Size", + "Could not change latency"); + + if (jcio == 1) + { + jcio = 0; + gx_jconv::GxJConvSettings::checkbutton7 = 1; + gx_jconv::checkbox7 = 1.0; + gx_gui::gx_start_stop_jconv(NULL, NULL); + } + } + else // restore latency status + { + // refresh latency check menu + gx_gui::GxMainInterface* gui = gx_gui::GxMainInterface::instance(); + GtkWidget* wd = gui->getJackLatencyItem(jack_bs); + if (wd) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wd), TRUE); + } + + gx_print_info("Jack Buffer Size", + string("latency is ") + + gx_i2a(jack_get_buffer_size(client))); +} + +//-----Function that cleans the jack stuff on shutdown +void gx_jack_cleanup() +{ + if (client && !jack_is_down) { + jack_is_exit = true; + // disable input ports + jack_port_unregister(client, input_ports[0]); + jack_port_unregister(client_insert, input_ports[1]); + if (midi_input_port != NULL) { + jack_port_unregister(client, midi_input_port); + } + for (int i = 0; i < 1; i++) { + jack_port_unregister(client, output_ports[i]); + } + for (int i = 2; i < 4; i++) { + jack_port_unregister(client_insert, output_ports[i]); + } + if (midi_output_ports != NULL) { + jack_port_unregister(client, midi_output_ports); + } +#ifdef USE_RINGBUFFER + jack_ringbuffer_free(jack_ringbuffer); +#endif + + jack_deactivate(client); + jack_client_close(client); + client = NULL; + jack_deactivate(client_insert); + jack_client_close(client_insert); + client_insert = NULL; + } +} + +//----jack sample rate change callback +int gx_jack_srate_callback(jack_nframes_t frames, void* arg) +{ + /* Note: just reporting log for now */ + + /* ostringstream s; + s << " jack sample rate changed to " << frames; + gx_print_warning("Jack sample rate", s.str()); */ + + return 0; +} + +//---- jack shutdown callback in case jackd shuts down on us +void gx_jack_shutdown_callback(void *arg) +{ + // global var to let all know that jack is down + jack_is_down = true; + // helper funktion to start gx_survive_jack_shutdown thread + gx_gui::gx_jack_is_down(); + +} + +//---- jack xrun callback +int gx_jack_xrun_callback (void* arg) +{ + xdel = jack_get_xrun_delayed_usecs(client); + gx_gui::gx_jack_report_xrun(); + return 0; +} + +//---- jack buffer size change callback +int gx_jack_buffersize_callback (jack_nframes_t nframes,void* arg) +{ + GxEngineState estate = (GxEngineState)checky; + + // turn off engine + // Note: simply changing checky is enough to "stop" processing + // incoming jack buffers. The mydsp::compute method is owned by + // the jack audio thread. It always runs as long as jack runs + // independently of the non-RT GUI thread. The value of + // checky is checked at each jack cycle in mydsp::compute + // so changing it here affects the behavior of mydsp::compute + // immediately during the jack_processing of jack cycles. + + if (estate != kEngineOff) + checky = (float)kEngineOff; + + jack_bs = nframes; + + + if (checkfreq) delete[] checkfreq; + if (get_frame) delete[] get_frame; + if (get_frame1) delete[] get_frame1; + if (oversample) delete[] oversample; + if (result) delete[] result; + + get_frame = new float[jack_bs]; + (void)memset(get_frame, 0, sizeof(float)*jack_bs); + + get_frame1 = new float[jack_bs]; + (void)memset(get_frame1, 0, sizeof(float)*jack_bs); + + checkfreq = new float[jack_bs]; + (void)memset(checkfreq, 0, sizeof(float)*jack_bs); + + oversample = new float[jack_bs*MAX_UPSAMPLE]; + (void)memset(oversample, 0, sizeof(float)*jack_bs*MAX_UPSAMPLE); + + result = new float[jack_bs+46]; + (void)memset(result, 0, sizeof(float)*jack_bs+46); + + // restore previous state + checky = (float)estate; + // return 0 to jack + return 0; + +} + +//---- jack midi control input processing +int gx_jack_midi_input_process(jack_nframes_t nframes, void *arg) +{ + if (midi_input_port != NULL) + { + midi_input_port_buf = jack_port_get_buffer(midi_input_port, nframes); + compute_midi_in(midi_input_port_buf); + } + return 0; +} + +//---- jack midi processing +#ifndef USE_RINGBUFFER +int gx_jack_midi_process (jack_nframes_t nframes, void *arg) +{ + if (midi_output_ports != NULL) + { + AVOIDDENORMALS; + + midi_port_buf = jack_port_get_buffer(midi_output_ports, nframes); + jack_midi_clear_buffer(midi_port_buf); + + if ((isMidiOn() == true) || (gx_gui::showwave == 1)) + jcpu_load = jack_cpu_load(client); + + compute_midi(nframes); + } + return 0; +} + +#else +int gx_jack_midi_process_ringbuffer (jack_nframes_t nframes, void *arg) +{ + + /************************************************************************* + The code for the jack_ringbuffer is take from + jack-keyboard 2.4, a virtual keyboard for JACK MIDI. + from Edward Tomasz Napierala . + **************************************************************************/ + int read, t; + unsigned char* buffer ; + + jack_nframes_t last_frame_time = jack_last_frame_time(client); + + midi_port_buf = jack_port_get_buffer(midi_output_ports, nframes); + jack_midi_clear_buffer( midi_port_buf); + + if (dsp::playmidi == 1) jcpu_load = jack_cpu_load(client); + GxEngine::instance()->compute_midi(nframes); + + while (jack_ringbuffer_read_space(jack_ringbuffer)) + { + read = jack_ringbuffer_peek(jack_ringbuffer, (char *)&ev, sizeof(ev)); + + if (read != sizeof(ev)) + { + // fprintf(stderr, " Short read from the ringbuffer, possible note loss.\n"); + continue; + } + + t = ev.time + nframes - last_frame_time; + if ((t >= (int)nframes) || (cpu_load > 75.0)) + break; + + if (t < 0) + t = 0; + + jack_ringbuffer_read_advance(jack_ringbuffer, sizeof(ev)); + + if (jack_midi_max_event_size(midi_port_buf) > sizeof(ev)) + buffer = jack_midi_event_reserve(midi_port_buf, t, ev.len); + else + break; + + if (ev.len > 2) + buffer[2] = ev.data[2]; + if (ev.len > 1) + buffer[1] = ev.data[1]; + + buffer[0] = ev.data[0]; + } + + /******************************************************************** + Thanks Edward for your friendly permision + Edward Tomasz Napierala . + *********************************************************************/ + return 0; +} +#endif + +// ----- main jack process method +int gx_jack_process (jack_nframes_t nframes, void *arg) +{ + int val; + measure_start(); + if (sem_getvalue(&jack_sync_sem, &val) == 0 && val == 0) { + sem_post(&jack_sync_sem); + } + if (!jack_is_exit) { + AVOIDDENORMALS; + + // retrieve buffers at jack ports + float *input = (float *)jack_port_get_buffer(input_ports[0], nframes); + float *output0 = (float *)jack_port_get_buffer(output_ports[0], nframes); + //float *output1 = (float *)jack_port_get_buffer(output_ports[1], nframes); + + // guitarix DSP computing + compute(nframes, input, output0); + + // ready to go for e.g. level display + gx_engine::buffers_ready = true; + + // midi input processing + gx_jack_midi_input_process(nframes, 0); + + // midi processing +#ifdef USE_RINGBUFFER + gx_jack_midi_process_ringbuffer(nframes, 0); +#else + gx_jack_midi_process(nframes, 0); +#endif + + // some info display + if (gx_gui::showwave == 1) { + time_is = jack_frame_time (client); + } + } else { + gx_engine::buffers_ready = false; + } + //measure_stop(); + return 0; +} + +// ----- main jack process method +int gx_jack_insert_process (jack_nframes_t nframes, void *arg) +{ + //measure_start(); + if (!jack_is_exit) { + AVOIDDENORMALS; + + float *input1 = (float *)jack_port_get_buffer(input_ports[1], nframes); + float *output2 = (float *)jack_port_get_buffer(output_ports[2], nframes); + float *output3 = (float *)jack_port_get_buffer(output_ports[3], nframes); + // guitarix DSP computing + compute_insert(nframes, input1, output2, output3); + } + measure_stop(); + return 0; +} + +struct PortRegData +{ + string name; + const char *tp; + int jackflags; + int reg; + PortRegData(string nm, const char *t, int flags, int r): name(nm), tp(t), jackflags(flags), reg(r) {} +}; + +static gboolean gx_jack_portreg_helper(gpointer data) +{ + //PortRegData *pm = (PortRegData*)data; + if (gx_gui::PortMapWindow::instance) { + gx_gui::PortMapWindow::instance->refresh(); + //gx_gui::PortMapWindow::instance->port_changed(pm->name, pm->tp, pm->jackflags, pm->reg); + } + //delete pm; + return FALSE; +} + +//----- fetch available jack ports other than guitarix ports +void gx_jack_portreg_callback(jack_port_id_t pid, int reg, void* arg) +{ + if (!client) { + return; + } + jack_port_t* port = jack_port_by_id(client, pid); + if (!port || jack_port_is_mine(client, port)) { + return; + } + gtk_idle_add(gx_jack_portreg_helper, + new PortRegData(jack_port_name(port), jack_port_type(port), + jack_port_flags(port), reg)); +} + +#ifdef HAVE_JACK_SESSION +static int gx_jack_session_callback_helper(gpointer data) { + jack_session_event_t *event = (jack_session_event_t *) data; + string fname( event->session_dir ); + fname += "guitarix.state"; + string cmd( "guitarix -U " ); + cmd += event->client_uuid; + cmd += " -f ${SESSION_DIR}guitarix.state"; + + saveStateToFile(fname); + + event->command_line = strdup(cmd.c_str()); + + jack_session_reply(client, event); + + if (event->type == JackSessionSaveAndQuit) { + gtk_main_quit(); + } + jack_session_event_free(event); + + return 0; +} + +void gx_jack_session_callback(jack_session_event_t *event, void *arg) +{ + gtk_idle_add(gx_jack_session_callback_helper, (void *)event); +} +#endif + +} /* end of gx_jack namespace */ + diff --git a/src/gx_jconv_settings.cpp b/src/gx_jconv_settings.cpp new file mode 100644 index 0000000..4278d4e --- /dev/null +++ b/src/gx_jconv_settings.cpp @@ -0,0 +1,736 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the JConv settings handler class used by guitarix + * There can only be one instance at all time. To get a pointer + * to the unique instance, simply call + * + * GxJConvSettings* jcset = GxJConvSettings::instance(); + * + * throughout the entire program. + * + * This class belongs to the gx_jconv namespace + * + * -------------------------------------------------------------------------- + */ +#include +#include "guitarix.h" + +using namespace gx_system; +using namespace gx_sndfile; +using namespace gx_jack; +using namespace gx_child_process; +using namespace gx_preset; + +namespace gx_jconv +{ + +// --------------- static vars +float GxJConvSettings::checkbutton7 = 0.; + +// --------------- constructor +GxJConvSettings::GxJConvSettings() +{ + // default parameters + fIRDir = getenv("HOME"); + fIRFile = "nofile"; + + fGain = 0.2; + flGain = 0.2; + fMem = 8000; + fMode = kJConvCopy; + fBufferSize = gx_jack::jack_bs; + fOffset = 0; + fLength = 0; + fDelay = 0; + flDelay = 0; + if (gx_jack::jack_bs == 0) { + fBufferSize = 128; + } + // invalidate due to no IR + invalidate(); +} + +// --------------- reset internal setting +void GxJConvSettings::resetSetting() +{ + // default parameters + fIRDir = getenv("HOME"); + fIRFile = "nofile"; + + fGain = 0.2; + flGain = 0.2; + fMem = 8000; + fMode = kJConvCopy; + fBufferSize = gx_jack::jack_bs; + fOffset = 0; + fLength = 0; + fDelay = 0; + flDelay = 0; + if (gx_jack::jack_bs == 0) { + fBufferSize = 128; + } + // invalidate due to no IR + invalidate(); +} + +// --------------- attempt to validate the settings +// Note: for now, simply check that the IR file is a wav file +void GxJConvSettings::validate() +{ + gx_engine::Audiofile audio; + fValidSettings = (audio.open_read(getFullIRPath()) == 0 && + audio.type() == gx_engine::Audiofile::TYPE_WAV); +} + + +// --------------- invalidate the settings via IR file +inline void GxJConvSettings::invalidate() +{ + fIRFile = "nofile"; + fValidSettings = false; +} + +void GxJConvSettings::writeJSON(JsonWriter& w) +{ + w.begin_object(true); + w.write_key("jconv.IRFile"); w.write(fIRFile, true); + w.write_key("jconv.IRDir"); w.write(fIRDir, true); + w.write_key("jconv.Gain"); w.write(fGain, true); + w.write_key("jconv.lGain"); w.write(flGain, true); + w.write_key("jconv.Mem"); w.write(fMem, true); + w.write_key("jconv.Mode"); w.write(fMode, true); + w.write_key("jconv.BufferSize"); w.write(fBufferSize, true); + w.write_key("jconv.Offset"); w.write(fOffset, true); + w.write_key("jconv.Length"); w.write(fLength, true); + w.write_key("jconv.Delay"); w.write(fDelay, true); + w.write_key("jconv.lDelay"); w.write(flDelay, true); + w.end_object(true); +} + +GxJConvSettings::GxJConvSettings(JsonParser& jp) +{ + jp.next(JsonParser::begin_object); + do { + jp.next(JsonParser::value_key); + if (jp.current_value() == "jconv.IRFile") { + jp.next(JsonParser::value_string); + fIRFile = jp.current_value(); + } else if (jp.current_value() == "jconv.IRDir") { + jp.next(JsonParser::value_string); + fIRDir = jp.current_value(); + } else if (jp.current_value() == "jconv.Gain") { + jp.next(JsonParser::value_number); + fGain = jp.current_value_float(); + } else if (jp.current_value() == "jconv.lGain") { + jp.next(JsonParser::value_number); + flGain = jp.current_value_float(); + } else if (jp.current_value() == "jconv.Mem") { + jp.next(JsonParser::value_number); + fMem = jp.current_value_int(); + } else if (jp.current_value() == "jconv.Mode") { + jp.next(JsonParser::value_number); + fMode = (GxJConvMode)jp.current_value_int(); //FIXME check + } else if (jp.current_value() == "jconv.BufferSize") { + jp.next(JsonParser::value_number); + fBufferSize = jp.current_value_int(); + } else if (jp.current_value() == "jconv.Offset") { + jp.next(JsonParser::value_number); + fOffset = jp.current_value_int(); + } else if (jp.current_value() == "jconv.Length") { + jp.next(JsonParser::value_number); + fLength = jp.current_value_int(); + } else if (jp.current_value() == "jconv.Delay") { + jp.next(JsonParser::value_number); + fDelay = jp.current_value_int(); + } else if (jp.current_value() == "jconv.lDelay") { + jp.next(JsonParser::value_number); + flDelay = jp.current_value_int(); + } else { + jp.skip_object(); + gx_print_warning("jconv settings", "unknown key: " + jp.current_value()); + } + } while (jp.peek() == JsonParser::value_key); + jp.next(JsonParser::end_object); +} + +// --------------------- dump parameters on demand to a string +void GxJConvSettings::dumpParameters() +{ + static string tab = " "; + static ostringstream dump; + dump.str(""); + + dump << "--- JConv is using IR " << endl + << getFullIRPath() << endl + << " in mode " << (fMode == kJConvCopy ? "'copy'" : "'read'") << endl + + << tab << "buffer size: " << fBufferSize << tab + << tab << "memory: " << fMem << endl + + << tab << "gain: " << fGain << tab + << tab << "left gain: " << flGain << tab + << tab << "delay: " << fDelay << tab + << tab << "left delay: " << flDelay << tab + << tab << "offset: " << fOffset << tab + << tab << "length: " << fLength << tab; + + gx_print_info("Saving JConv parameters to file", dump.str().c_str()); +} + +//----- show the jconv settings widget +void gx_show_jconv_dialog_gui(GtkWidget *widget, gpointer data) +{ + gtk_widget_show_all(gx_gui::jc_dialog); + +} + +//----- disable the right gain and delay when run in copy mode +void gx_set_sensitive(GtkWidget *gwidget, gpointer obj) +{ + GtkWidget *widget = (GtkWidget *)obj; + GxJConvSettings* jcset = GxJConvSettings::instance(); + switch (jcset->getMode()) + { + case kJConvRead: + gtk_widget_set_sensitive(GTK_WIDGET(widget),TRUE); + break; + + case kJConvCopy: + default: + gtk_widget_set_sensitive(GTK_WIDGET(widget),FALSE); + break; + } + + +} + +//----- refresh jcconv settings GUI +void gx_reload_jcgui() +{ + gtk_widget_destroy(gx_gui::jc_dialog); + + gx_setting_jconv_dialog_gui(gx_gui::jc_dialog,NULL); + +} + + +//----- hide the jconv settings widget +gboolean gx_delete_event( GtkWidget *widget, gpointer data ) +{ + gtk_widget_hide(gx_gui::jc_dialog); + return TRUE; +} + +//------- idle thread to reset the file chooser filter +gboolean gx_set_file_filter(gpointer data) +{ + GxJConvSettings* jcset = GxJConvSettings::instance(); + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gx_gui::fbutton), + jcset->getIRDir().c_str()); + return false; + +} + +//----- show value to a label +void gx_set_value(GtkObject * widget, gpointer obj) +{ + GtkWidget *lw = (GtkWidget *)obj; + float v = GTK_ADJUSTMENT (widget)->value; + int fPrecision = GTK_ADJUSTMENT (widget)->step_increment; + char s[64]; + if (fPrecision >= 1) + snprintf(s, 63, "%d", int(v)); + + else if (fPrecision == 0) + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[2-1], v); + } + gtk_label_set_text(GTK_LABEL(lw), s); +} + +//----- create knobs/sliders with labels +GtkWidget * gx_knob(const char* label,int mode, float init, float min, float max, float step) +{ + + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + GtkWidget* lw = gtk_label_new(""); + GtkWidget* lwl = gtk_label_new(label); + gtk_widget_set_name (lw,"value_label"); + gtk_widget_set_name (lwl,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + gtk_widget_modify_font(lwl, style->font_desc); + GtkWidget* slider; + + GtkRegler myGtkRegler; + if(!mode) slider = myGtkRegler.gtk_regler_new_with_adjustment(GTK_ADJUSTMENT(adj)); + else slider = myGtkRegler.gtk_vslider_new_with_adjustment(GTK_ADJUSTMENT(adj)); + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + gx_set_value(GTK_OBJECT(adj), lw); + // connect label with value + g_signal_connect(GTK_OBJECT(adj), "value-changed", + G_CALLBACK(gx_set_value), + (gpointer)lw); + + GtkWidget* box = gtk_vbox_new (FALSE, 1); + gtk_container_set_border_width (GTK_CONTAINER (box), 1); + + gtk_container_add (GTK_CONTAINER (box), lwl); + gtk_container_add (GTK_CONTAINER (box), slider); + gtk_container_add (GTK_CONTAINER (box), lw); + + gtk_widget_show(lwl); + gtk_widget_show(slider); + gtk_widget_show(lw); + gtk_widget_show(box); + + return slider; + +} + +// --------------------- The JConv setting dialog GUI +void gx_setting_jconv_dialog_gui(GtkWidget *widget, gpointer data) +{ + GxJConvSettings* jcset = GxJConvSettings::instance(); + + // -- main window + gx_gui::jc_dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_decorated(GTK_WINDOW(gx_gui::jc_dialog), TRUE); + gtk_window_set_resizable(GTK_WINDOW(gx_gui::jc_dialog), FALSE); + gtk_window_set_gravity(GTK_WINDOW(gx_gui::jc_dialog), GDK_GRAVITY_SOUTH); + gtk_window_set_transient_for (GTK_WINDOW(gx_gui::jc_dialog), GTK_WINDOW(gx_gui::fWindow)); + gtk_window_set_position (GTK_WINDOW(gx_gui::jc_dialog), GTK_WIN_POS_MOUSE); + gtk_window_set_keep_below (GTK_WINDOW(gx_gui::jc_dialog), FALSE); + gtk_window_set_title (GTK_WINDOW (gx_gui::jc_dialog), "Convolver Settings"); + gtk_window_set_destroy_with_parent(GTK_WINDOW(gx_gui::jc_dialog), TRUE); + + // -- labels + GtkWidget* label = gtk_label_new ("\n Convolver Settings \n" + "\n"); + gx_gui::label1 = gtk_label_new (" \n"); + gtk_widget_set_name (gx_gui::label1,"effekt_label"); + + GtkWidget* label2 = gtk_label_new (" partition size"); + GtkWidget* label5 = gtk_label_new (" mode "); + + GdkColor colorGreen; + gdk_color_parse("#969292", &colorGreen); + gtk_widget_modify_fg (label2, GTK_STATE_NORMAL, &colorGreen); + gtk_widget_modify_fg (label5, GTK_STATE_NORMAL, &colorGreen); + GtkStyle *style = gtk_widget_get_style(label2); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(label2, style->font_desc); + gtk_widget_modify_font(label5, style->font_desc); + gtk_widget_modify_font(label, style->font_desc); + + // -- OK button + GtkWidget* ok_button = gtk_button_new_with_label("OK"); + + + // ----- setting GUI stuff with current initial values + + ostringstream lab; // label text + + // -- wave file info + int chans = 0; // channels + int sr = 0; // sample rate + int framecount = 0; // number of frames + SNDFILE* sf = NULL; + + // try to open IR file + jcset->validate(); + + if (jcset->isValid()) + { + sf = openInputSoundFile(jcset->getFullIRPath().c_str(), + &chans, &sr, &framecount); + closeSoundFile(sf); + + // display IR file info + lab.str(""); + lab << "IR file info: " << endl + << chans << " channel(s) " + << sr << " Sample rate " + << framecount << " Samples "; + + gtk_label_set_text(GTK_LABEL(gx_gui::label1), lab.str().c_str()); + } + if (chans == 1) jcset->setMode ( kJConvCopy); + + // -- Delay + GtkWidget* dslider = gx_knob ("left delay ",0,jcset->getDelay(), 0, 6000, 1); + GtkAdjustment *dadj = gtk_range_get_adjustment(GTK_RANGE(dslider)); + + GtkWidget * dslider_box = gtk_widget_get_parent(GTK_WIDGET(dslider)); + jcset->setDelay(gtk_adjustment_get_value(GTK_ADJUSTMENT(dadj))); + // -- Delay + GtkWidget* dlslider = gx_knob ("right delay ",0,jcset->getlDelay(), 0, 6000, 1); + GtkAdjustment *dladj = gtk_range_get_adjustment(GTK_RANGE(dlslider)); + + GtkWidget * dlslider_box = gtk_widget_get_parent(GTK_WIDGET(dlslider)); + jcset->setlDelay(gtk_adjustment_get_value(GTK_ADJUSTMENT(dladj))); + + // -- GAIN + GtkWidget* gslider = gx_knob ("left gain",0,jcset->getGain(), 0.0, 5.0, 0.01); + GtkAdjustment *gadj = gtk_range_get_adjustment(GTK_RANGE(gslider)); + + GtkWidget * gslider_box = gtk_widget_get_parent(GTK_WIDGET(gslider)); + jcset->setGain(gtk_adjustment_get_value(GTK_ADJUSTMENT(gadj))); + // -- GAIN + GtkWidget* glslider = gx_knob ("right gain",0,jcset->getlGain(), 0.0, 5.0, 0.01); + GtkAdjustment *gladj = gtk_range_get_adjustment(GTK_RANGE(glslider)); + + GtkWidget * glslider_box = gtk_widget_get_parent(GTK_WIDGET(glslider)); + jcset->setlGain(gtk_adjustment_get_value(GTK_ADJUSTMENT(gladj))); + + // -- MEMORY + mslider = gx_knob ("max mem",1,jcset->getMem(), 32, 400000, 1000); + GtkAdjustment *madj = gtk_range_get_adjustment(GTK_RANGE(mslider)); + gtk_range_set_value(GTK_RANGE(mslider), framecount ); + + GtkWidget * mslider_box = gtk_widget_get_parent(GTK_WIDGET(mslider)); + jcset->setMem(gtk_adjustment_get_value(GTK_ADJUSTMENT(madj))); + + // -- READ MODE + GtkWidget* jcmode_combo = gtk_combo_box_new_text(); + string buffer = "/impulse/copy"; + gtk_combo_box_append_text(GTK_COMBO_BOX(jcmode_combo), buffer.c_str()); + + buffer = "/impulse/read"; + gtk_combo_box_append_text(GTK_COMBO_BOX(jcmode_combo), buffer.c_str()); + + // turn on default + gtk_combo_box_set_active(GTK_COMBO_BOX(jcmode_combo), (gint)jcset->getMode()); + + // -- BUFFER SIZE + GtkWidget* bs_combo = gtk_combo_box_new_text(); + const int min_pow = 6; // 2**6 = 64 + const int max_pow = 12; // 2**12 = 4096 + + for (int i = min_pow; i <= max_pow; i++) + { + ostringstream s; + jack_nframes_t bs = (jack_nframes_t)pow(2.,i); + s << bs; + gtk_combo_box_append_text(GTK_COMBO_BOX(bs_combo), s.str().c_str()); + + if (bs == jcset->getBufferSize()) + gtk_combo_box_set_active(GTK_COMBO_BOX(bs_combo), i - min_pow); + } + + // -- IR File Chooser + gx_gui::fbutton = + gtk_file_chooser_button_new ("Select a *.wav file", GTK_FILE_CHOOSER_ACTION_OPEN); + + gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER (gx_gui::fbutton), true); + gtk_file_chooser_set_show_hidden (GTK_FILE_CHOOSER (gx_gui::fbutton),false); + + GtkFileFilter* filter = gtk_file_filter_new (); + gtk_file_filter_add_pattern (GTK_FILE_FILTER(filter), "*.wav"); + gtk_file_filter_add_pattern (GTK_FILE_FILTER(filter), "*.WAV"); + gtk_file_filter_add_pattern (GTK_FILE_FILTER(filter), "*.Wav"); + gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (gx_gui::fbutton), GTK_FILE_FILTER(filter)); + + // label for display the filename + gx_gui::label6 = gtk_label_new(jcset->getIRFile().c_str()); + + // display wave view of IR file + GtkWidget* waveview = gx_wave_view(); + gtk_widget_set_size_request (GTK_WIDGET(waveview), 300.0, 200.0); + + // scrolled window + GtkWidget* scrlwd = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrlwd), + GTK_POLICY_ALWAYS,GTK_POLICY_NEVER); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrlwd), + GTK_SHADOW_IN); + + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrlwd), waveview); + gtk_widget_set_size_request (GTK_WIDGET(scrlwd), 304.0, -1); + + //----- arrange widgets + GtkWidget* box = gtk_vbox_new (FALSE, 4); + GtkWidget* box1 = gtk_vbox_new (TRUE, 4); + GtkWidget* box2 = gtk_hbox_new (FALSE, 0); + GtkWidget* box3 = gtk_vbox_new (FALSE, 4); + GtkWidget* box4 = gtk_vbox_new (FALSE, 4); + GtkWidget* box5 = gtk_hbox_new (FALSE, 4); + GtkWidget* box6 = gtk_hbox_new (TRUE, 4); + GtkWidget* box7 = gtk_hbox_new (FALSE, 8); + GtkWidget* box8 = gtk_vbox_new (FALSE, 0); + GtkWidget* box9 = gtk_hbox_new (FALSE, 8); + GtkWidget* box10 = gtk_vbox_new (FALSE, 0); + GtkWidget* box11 = gtk_vbox_new (TRUE, 0); + // GtkWidget* box12 = gtk_vbox_new (FALSE, 4); + GtkWidget* viewbox = gtk_event_box_new (); + + gtk_container_set_border_width (GTK_CONTAINER (box7), 8); + gtk_container_set_border_width (GTK_CONTAINER (viewbox), 8); + gtk_container_set_border_width (GTK_CONTAINER (box9), 14); + gtk_container_set_border_width (GTK_CONTAINER (box6), 4); + gtk_container_set_border_width (GTK_CONTAINER (box2), 2); + + gtk_container_add (GTK_CONTAINER (box4), label); + gtk_container_add (GTK_CONTAINER (box4), viewbox); + gtk_container_add (GTK_CONTAINER (viewbox), scrlwd); + gtk_container_add (GTK_CONTAINER (gx_gui::jc_dialog), box7); + gtk_container_add (GTK_CONTAINER (box7), box9); + gtk_container_add (GTK_CONTAINER (box9), box4); + gtk_container_add (GTK_CONTAINER (box5), gx_gui::label6); + gtk_container_add (GTK_CONTAINER (box5), gx_gui::fbutton); + gtk_container_add (GTK_CONTAINER (box4), box5); + gtk_container_add (GTK_CONTAINER (box4), gx_gui::label1); + gtk_container_add (GTK_CONTAINER (box4), box6); + gtk_container_add (GTK_CONTAINER (box4), box2); + gtk_container_add (GTK_CONTAINER (box2), box8); + gtk_container_add (GTK_CONTAINER (box8), gslider_box); + gtk_container_add (GTK_CONTAINER (box8), glslider_box); + gtk_container_add (GTK_CONTAINER (box2), box10); + gtk_container_add (GTK_CONTAINER (box10), dslider_box); + gtk_container_add (GTK_CONTAINER (box10), dlslider_box); + gtk_container_add (GTK_CONTAINER (box2), box11); + gtk_container_add (GTK_CONTAINER (box11), mslider_box); + //gtk_container_add (GTK_CONTAINER (box11), box12); + gtk_container_add (GTK_CONTAINER (box2), box1); + //gtk_container_add (GTK_CONTAINER (box1), box3); //FIXME mode (read/copy) remove after jconvolver transition + gtk_container_add (GTK_CONTAINER (box3), label5); + gtk_container_add (GTK_CONTAINER (box3), jcmode_combo); + gtk_container_add (GTK_CONTAINER (box1), box); + gtk_box_pack_start(GTK_BOX(box), label2, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(box), bs_combo, FALSE, FALSE, 0); + gtk_container_add (GTK_CONTAINER (box4), ok_button); + + //----- connect signals to callback cairo funcs + g_signal_connect(box9, "expose-event", G_CALLBACK(gx_cairo::conv_widget_expose), NULL); + g_signal_connect(box7, "expose-event", G_CALLBACK(gx_cairo::rectangle_expose), NULL); + g_signal_connect(box2, "expose-event", G_CALLBACK(gx_cairo::rectangle_skin_color_expose), NULL); + g_signal_connect(gx_gui::label6, "expose-event", G_CALLBACK(gx_cairo::rectangle_skin_color_expose), NULL); + g_signal_connect(label, "expose-event", G_CALLBACK(gx_cairo::convolver_icon_expose), NULL); + + // IR file select + g_signal_connect (gx_gui::fbutton, "file-set", + G_CALLBACK(gx_select_and_draw_jconv_ir), (gpointer) jcmode_combo); + + // confirm and save setting + g_signal_connect_swapped(ok_button, "clicked", + G_CALLBACK(gx_delete_event), gx_gui::jc_dialog); + g_signal_connect_swapped (G_OBJECT (gx_gui::jc_dialog), "delete_event", + G_CALLBACK (gx_delete_event), (gpointer) ok_button); + + + // gain setting + g_signal_connect(GTK_OBJECT(gadj), "value-changed", + G_CALLBACK(gx_acquire_jconv_value), + (gpointer)kJConvGain); + // gain setting + g_signal_connect(GTK_OBJECT(gladj), "value-changed", + G_CALLBACK(gx_acquire_jconv_value), + (gpointer)kJConvlGain); + + // memory + g_signal_connect(GTK_OBJECT(madj), "value-changed", + G_CALLBACK(gx_acquire_jconv_value), + (gpointer)kJConvMem); + + // buffer size + g_signal_connect(GTK_OBJECT (bs_combo), "changed", + G_CALLBACK(gx_acquire_jconv_value), + (gpointer)kJConvBuffersize); + + // read mode + g_signal_connect(GTK_OBJECT (jcmode_combo), "changed", + G_CALLBACK(gx_acquire_jconv_value), + (gpointer)kJConvMode); + g_signal_connect(GTK_OBJECT (jcmode_combo), "changed", + G_CALLBACK(gx_set_sensitive), + (gpointer)glslider); + g_signal_connect(GTK_OBJECT (jcmode_combo), "changed", + G_CALLBACK(gx_set_sensitive), + (gpointer)dlslider); + + // delay setting + g_signal_connect(GTK_OBJECT(dadj), "value-changed", + G_CALLBACK(gx_acquire_jconv_value), + (gpointer)kJConvDelay); + // delay setting + g_signal_connect(GTK_OBJECT(dladj), "value-changed", + G_CALLBACK(gx_acquire_jconv_value), + (gpointer)kJConvlDelay); + + // set courent folder to file chooser + g_idle_add(gx_set_file_filter,NULL); + + //----- load file to wave view + gx_waveview_set_value(GTK_WIDGET(gx_gui::fbutton),NULL); +} + + +// --------------- retrieve a setting value +void gx_acquire_jconv_value(GtkWidget *widget, gpointer data ) +{ + GxJConvSettings* jcset = GxJConvSettings::instance(); + + GxJConvParamType ptype = (GxJConvParamType)GPOINTER_TO_INT(data); + string s; + + switch (ptype) + { + case kJConvGain: + jcset->setGain(gtk_adjustment_get_value(GTK_ADJUSTMENT(widget))); + break; + + case kJConvlGain: + jcset->setlGain(gtk_adjustment_get_value(GTK_ADJUSTMENT(widget))); + break; + + case kJConvMem: + jcset->setMem((guint)gtk_adjustment_get_value(GTK_ADJUSTMENT(widget))); + break; + + case kJConvBuffersize: + s = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)); + jcset->setBufferSize((jack_nframes_t)atoi(s.c_str())); + break; + + case kJConvMode: + s = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)); + jcset->setMode(((int)s.find("copy") != -1 ? kJConvCopy : kJConvRead)); + break; + + case kJConvDelay: + jcset->setDelay(gtk_adjustment_get_value(GTK_ADJUSTMENT(widget))); + break; + + case kJConvlDelay: + jcset->setlDelay(gtk_adjustment_get_value(GTK_ADJUSTMENT(widget))); + break; + + case kJConvOffset: + case kJConvLength: + + default: // do nothing + break; + } +} + + +// --------------- IR file processing +void gx_select_and_draw_jconv_ir(GtkWidget* widget, gpointer obj) +{ + // get the chosen file from the file chooser + gchar * _file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); + // return when file is empty + if (!_file) { + g_free(_file); + return; + } + GxJConvSettings* jcset = GxJConvSettings::instance(); + GtkWidget *combo = (GtkWidget *)obj; + + string file = _file; + g_free(_file); + string folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); + + if (!file.empty()) { + // let's save it into the JConv settings + string tmp_file = basename((char*)file.c_str()); + jcset->setIRFile(tmp_file); + jcset->setIRDir(folder); + + // let's validate it + jcset->validate(); + + if (jcset->isValid()) { + g_idle_add(gx_set_file_filter,NULL); + + //----- get name from used wav file + gtk_label_set_text(GTK_LABEL(gx_gui::label6), + jcset->getIRFile().c_str()); + + //----- get snd info from IR file + int chans, sr, framescount; + + SNDFILE* sf = openInputSoundFile(file.c_str(), + &chans, &sr, &framescount); + closeSoundFile(sf); + + /* We set the sndfile info here to the label, if resampling is needed/done. */ + //----- set label text + ostringstream lab; + lab.str(""); + lab << "IR file info: " << endl + << chans << " channel(s) " + << sr << " Sample rate " + << framescount << " Samples "; + gtk_label_set_text(GTK_LABEL(gx_gui::label1), lab.str().c_str()); + + /* Note, resample the file didn't change the samples, so we could draw it here + already, independend from the result of resampling. Also a no resampled file could be used + if the user wish so.*/ + + //----- draw the wave file + gx_waveview_set_value(widget, NULL); + gtk_range_set_value(GTK_RANGE(mslider), framescount ); + + //----- set mode chooser to copy and disable it when a 1 channel file is loaded + if(chans == 1) { + jcset->setMode ( kJConvCopy); + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + gtk_widget_set_sensitive(GTK_WIDGET(combo),FALSE); + } else if (chans == 2) { + gtk_widget_set_sensitive(GTK_WIDGET(combo),TRUE); + } else if (chans > 2) { + ostringstream msg; + msg << "Error opening file " << jcset->getIRFile() << "\n have more then 2 Channels"; + (void)gx_gui::gx_message_popup(msg.str().c_str()); + + jcset->invalidate(); + // force the wave view to draw a red X + gx_waveview_set_value(widget, NULL); + // set label text + gtk_label_set_text(GTK_LABEL(gx_gui::label1), "IR file empty\n"); + gtk_label_set_text(GTK_LABEL(gx_gui::label6), "empty"); + return; + } + } else { // end of if (file is wave audio) + jcset->invalidate(); + gx_print_error("IR File Processing", + jcset->getIRFile() + + string(" is not a WAVE Audio file! Invalidating ... ")); + // force the wave view to draw a red X + gx_waveview_set_value(widget, NULL); + // set label text + gtk_label_set_text(GTK_LABEL(gx_gui::label1), "IR file empty\n"); + gtk_label_set_text(GTK_LABEL(gx_gui::label6), "empty"); + } + } else { // end of if (!file.empty()) + gx_print_error("IR File Processing", + "Filename empty, you probably need to re-pick a file"); + gx_waveview_set_value(widget, NULL); + gtk_label_set_text(GTK_LABEL(gx_gui::label1), "No file name\n"); + gtk_label_set_text(GTK_LABEL(gx_gui::label6), "empty"); + } +} + +} /* end of gx_jconv namespace */ diff --git a/src/gx_main.cpp b/src/gx_main.cpp new file mode 100644 index 0000000..c5e064c --- /dev/null +++ b/src/gx_main.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * --------------------------------------------------------------------------- + * + * name : "guitarix" + * version : "0.04.7" + * authors : "hermann meyer" & "james warden" + * contributors : "Julius O. Smith (jos at ccrma.stanford.edu)" + * license : "GPL" + * copyright : "(c)brummer 2008" + * reference : "http://ccrma.stanford.edu/realsimple/faust_strings/" + * + * Code prototype generated with Faust 0.9.9.4f (http://faust.grame.fr) + * ---------------------------------------------------------------------------- + * + * This is guitarix main. + * + * ---------------------------------------------------------------------------- + */ + +#include "giomm/init.h" +#include "gtkmm/main.h" +#include "guitarix.h" + +using namespace gx_system; + + +void init_unix_signal_handlers() +{ + /* ----- block signal USR1 --------- + ** inherited by all threads which are created later + ** USR1 is processed synchronously by gx_signal_helper_thread + */ + sigset_t waitset; + sigemptyset(&waitset); + sigaddset(&waitset, SIGUSR1); + sigaddset(&waitset, SIGCHLD); + sigprocmask(SIG_BLOCK, &waitset, NULL); + + //----- set unix signal handlers for proper shutdown + signal(SIGQUIT, gx_signal_handler); + signal(SIGTERM, gx_signal_handler); + signal(SIGHUP, gx_signal_handler); + signal(SIGINT, gx_signal_handler); + //signal(SIGSEGV, gx_signal_handler); // no good, quits application silently +} + +/* --------- Guitarix main ---------- */ +int main(int argc, char *argv[]) +{ + init_unix_signal_handlers(); + + // ----------------------- init basic subsystems ---------------------- + Glib::thread_init(); + Glib::init(); + + // ------ initialize parameter list ------ + gx_preset::init(); + gx_gui::parameter_map.set_init_values(); + + // ---------------------- user options handling ------------------ + string optvar[NUM_SHELL_VAR]; + gx_process_cmdline_options(argc, argv, optvar); + Gtk::Main main(argc, argv); + + // ---------------- Check for working user directory ------------- + gx_system::gx_version_check(); + + // ------ time measurement (debug) ------ +#ifndef NDEBUG + add_time_measurement(); +#endif + + // ----------------------- init GTK interface---------------------- + gx_gui::GxMainInterface* gui = gx_gui::GxMainInterface::instance("guitarix"); + gui->setup(); +#ifdef EXPERIMENTAL + gx_engine::faust_setup(); +#endif + + // ---------------------- initialize jack client ------------------ + if (gx_jack::gx_jack_init(optvar)) + { + // -------- initialize guitarix engine -------------------------- + gx_engine::gx_engine_init(optvar); + + // -------- set jack callbacks and activation ------------------- + gx_jack::gx_jack_callbacks_and_activate(); + + // -------- init port connections + gx_jack::gx_jack_init_port_connection(optvar); + } + + // ----------------------- run GTK main loop ---------------------- + gx_set_override_options(optvar); + gx_ui::GxUI::updateAllGuis(); + gui->show(); + + if (gx_jack::client) { + // -------- pitch tracker (needs jack thread running) ------------- + gx_engine::pitch_tracker.init(); + } + + gui->run(); + + // ------------- shut things down + gx_system::gx_clean_exit(NULL, NULL); + + return 0; +} diff --git a/src/gx_main_interface.cpp b/src/gx_main_interface.cpp new file mode 100644 index 0000000..4c94523 --- /dev/null +++ b/src/gx_main_interface.cpp @@ -0,0 +1,3318 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix GUI main class + * + * ---------------------------------------------------------------------------- + */ + +#include +#include +#include +#include "guitarix.h" + +using namespace gx_system; +using namespace gx_child_process; +using namespace gx_preset; +using namespace gx_cairo; +using namespace gx_threads; + +namespace gx_gui +{ + +/**************************************************************** + ** format controller values + */ + +int precision(double n) +{ + if (n < 0.009999) return 3; + else if (n < 0.099999) return 2; + else if (n < 0.999999) return 1; + else return 0; +} + +string fformat(float value, float step) +{ + ostringstream buf; + buf << fixed << setprecision(precision(step)) << value; + return buf.str(); +} + +/**************************************************************** + ** GxMidiController definitions and connecting method + */ + +#include "gx_main_midi.cc" + +/**************************************************************** + ** GxMainInterface widget and method definitions + */ + +// static member +bool GxMainInterface::fInitialized = false; +#ifndef NDEBUG +static pthread_t ui_thread; +#endif + +GxMainInterface::GxMainInterface(const char * name) +{ + highest_unseen_msg_level = -1; + + /*-- set rc file overwrite it with export--*/ + gtk_rc_parse(rcpath.c_str()); + + /*-- Declare the GTK Widgets --*/ + fWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); + + /*---------------- set window defaults ----------------*/ + gtk_window_set_resizable(GTK_WINDOW (fWindow) , FALSE); + gtk_window_set_title (GTK_WINDOW (fWindow), name); + gtk_window_set_gravity(GTK_WINDOW(fWindow), GDK_GRAVITY_NORTH_WEST); + + /*---------------- singnals ----------------*/ + g_signal_connect (GTK_OBJECT (fWindow), "destroy", + G_CALLBACK (gx_clean_exit), NULL); + + /*---------------- status icon ----------------*/ + if (gx_pixmap_check() == 0) { + status_icon = gtk_status_icon_new_from_pixbuf (GDK_PIXBUF(ib)); + gtk_window_set_icon(GTK_WINDOW (fWindow), GDK_PIXBUF(ib)); + g_signal_connect (G_OBJECT (status_icon), "activate", G_CALLBACK (gx_hide_extended_settings), NULL); + g_signal_connect (G_OBJECT (status_icon), "popup-menu", G_CALLBACK (gx_systray_menu), NULL); + } + else + { + gx_print_error("Main Interface Constructor", + "pixmap check failed, giving up"); + gx_clean_exit(NULL, (gpointer)1); + } + + /*-- create accelerator group for keyboard shortcuts --*/ + fAccelGroup = gtk_accel_group_new(); + gtk_window_add_accel_group(GTK_WINDOW(fWindow), fAccelGroup); + + /*---------------- create boxes ----------------*/ + fTop = 0; + fBox[fTop] = gtk_vbox_new (homogene, 4); + fMode[fTop] = kBoxMode; + + /*---------------- add mainbox to main window ---------------*/ + gtk_container_add (GTK_CONTAINER (fWindow), fBox[fTop]); + + fStopped = false; +} + +//------- create or retrieve unique instance +GxMainInterface* GxMainInterface::instance(const char* name) +{ + static GxMainInterface maingui(name); + return &maingui; +} + +/**************************************************************** + ** virtual GUI discriptions + */ + +//------- retrieve jack latency menu item +GtkWidget* const +GxMainInterface::getJackLatencyItem(jack_nframes_t bufsize) const +{ + if (bufsize & (bufsize-1)) { + return NULL; // not power of 2 + } + const int minbuf = 5; // 2**5 = 32 //FIXME magic value + int index = -(minbuf+1); + while (bufsize) { + bufsize >>= 1; + index++; + } + if (index >= 0 && index < NJACKLAT) { + return fJackLatencyItem[index]; + } + return NULL; +} + +//------- box stacking up +void GxMainInterface::pushBox(int mode, GtkWidget* w) +{ + ++fTop; + assert(fTop < stackSize); + fMode[fTop] = mode; + fBox[fTop] = w; +} + +void GxMainInterface::closeBox() +{ + --fTop; + assert(fTop >= 0); +} + +//-------- different box styles +void GxMainInterface::openFrameBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 2); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + g_signal_connect(box, "expose-event", G_CALLBACK(vbox_expose), NULL); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_frame_new (label)); + gtk_frame_set_shadow_type(GTK_FRAME(frame),GTK_SHADOW_NONE); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } + +} + +void GxMainInterface::openTabBox(const char* label) +{ + pushBox(kTabMode, addWidget(label, gtk_notebook_new ())); +} + +static void logging_set_color(GtkWidget *w, gpointer data) +{ + GxMainInterface *p = (GxMainInterface*)data; + if (gtk_expander_get_expanded(GTK_EXPANDER(w)) == FALSE) { + // expander will be opened + p->highest_unseen_msg_level = kMessageTypeCount; + p->set_logging_expander_color("#ffffff"); + } else { + p->highest_unseen_msg_level = -1; + } +} + +void GxMainInterface::openTextLoggingBox(const char* label) +{ + GtkWidget* box = gtk_hbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + + GtkWidget * scrollbox = gtk_scrolled_window_new(NULL,NULL); + fLoggingVAdjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrollbox)); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrollbox), + GTK_POLICY_NEVER,GTK_POLICY_AUTOMATIC); + + GtkWidget* frame = addWidget(label, gtk_expander_new(label)); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(frame); + gtk_expander_set_expanded(GTK_EXPANDER(frame), FALSE); + fLoggingBox = GTK_EXPANDER(frame); + + // create text buffer + GtkTextBuffer* buffer = gtk_text_buffer_new(NULL); + + GtkWidget* tbox = gtk_text_view_new_with_buffer(buffer); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tbox), GTK_WRAP_WORD_CHAR); + gtk_container_set_border_width (GTK_CONTAINER (tbox), 0); + gtk_text_view_set_editable(GTK_TEXT_VIEW(tbox), FALSE); + gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(tbox), FALSE); + gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW(tbox), 0); + gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW(tbox), 2); + gtk_text_view_set_justification(GTK_TEXT_VIEW(tbox), GTK_JUSTIFY_LEFT); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(tbox), 5); + gtk_text_view_set_indent(GTK_TEXT_VIEW(tbox), 0); + + gtk_container_add (GTK_CONTAINER(box), scrollbox); + gtk_container_add(GTK_CONTAINER(scrollbox),GTK_WIDGET(tbox)); + gtk_widget_show(tbox); + gtk_widget_show(scrollbox); + fLoggingWindow = GTK_TEXT_VIEW(tbox); + gtk_widget_set_size_request(tbox, -1, 100); + g_signal_connect(fLoggingBox, "activate", G_CALLBACK(logging_set_color), this); + + gtk_widget_show(box); +} + +void GxMainInterface::set_logging_expander_color(const char *color) +{ + GtkExpander* exbox = getLoggingBox(); + if (gtk_expander_get_expanded(exbox) == FALSE) { + GdkColor c; + gdk_color_parse(color, &c); + gtk_widget_modify_fg(GTK_WIDGET(exbox), GTK_STATE_NORMAL, &c); + gtk_widget_modify_fg(gtk_expander_get_label_widget(exbox), GTK_STATE_NORMAL, &c); + } +} + +void GxMainInterface::show_msg(string msgbuf, gx_system::GxMsgType msgtype) +{ + // color depending on msg type + // initialize static tag table + static struct tab_table { + const char *tagname; + const char *tag_color; + GtkTextTag *tag; + } tags[kMessageTypeCount] = { + {"colinfo", "#00ced1"}, + {"colwarn", "#ff8800"}, + {"colerr", "#ff0000"}, + }; + + assert(0 <= msgtype && msgtype < kMessageTypeCount); + assert(pthread_equal(pthread_self(), ui_thread)); + + // retrieve gtk text buffer + GtkTextBuffer* buffer = gtk_text_view_get_buffer(getLoggingWindow()); + + if (!tags[0].tag) { // fill static table + for (int i = 0; i < kMessageTypeCount; i++) { + tags[i].tag = gtk_text_buffer_create_tag(buffer, tags[i].tagname, "foreground", + tags[i].tag_color, NULL); + } + } + + // how many lines to keep + const int nlines = 50; + + // delete first line when window filled up + int linecount = gtk_text_buffer_get_line_count(buffer); // empty buffer == 1 line + if (linecount >= nlines) { + GtkTextIter iter1; + GtkTextIter iter2; + gtk_text_buffer_get_iter_at_line(buffer, &iter1, 0); + gtk_text_buffer_get_iter_at_line(buffer, &iter2, 1); + gtk_text_buffer_delete(buffer, &iter1, &iter2); + } + GtkTextIter iter; + gtk_text_buffer_get_end_iter(buffer, &iter); + if (gtk_text_buffer_get_char_count(buffer) > 0) { + gtk_text_buffer_insert(buffer, &iter, "\n", -1); + } + + gtk_text_buffer_insert_with_tags(buffer, &iter, msgbuf.c_str(), -1, + tags[msgtype].tag, NULL); + gtk_adjustment_set_value(fLoggingVAdjustment, 10000); // scroll to end (big value, gets clamped to max) + + // modify expander bg color is closed + if (msgtype > highest_unseen_msg_level) { + set_logging_expander_color(tags[msgtype].tag_color); + highest_unseen_msg_level = msgtype; + } +} + + +void GxMainInterface::openLevelMeterBox(const char* label) +{ + GtkWidget* box1 = addWidget(label, gtk_alignment_new (0.5, 0.5, 0, 0)); + GtkWidget* box = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER(box1), box); + + gint boxheight = 135; + gint boxwidth = 47; + + gtk_container_set_border_width (GTK_CONTAINER (box), 3); + gtk_box_set_spacing(GTK_BOX(box), 1); + + gtk_widget_set_size_request (GTK_WIDGET(box), boxwidth, boxheight); + g_signal_connect(box, "expose-event", G_CALLBACK(level_meter_expose), NULL); + g_signal_connect(GTK_CONTAINER(box), "check-resize", + G_CALLBACK(level_meter_expose), NULL); + + // meter level colors + int base = 0x00380800; + int mid = 0x00ff0000; + int top = 0xff000000; + int clip = 0xff000000; + + // width of meter + int width = 8; + + // how long we hold the peak bar = hold * thread call timeout + + // Note: 30 * 80 = 2.4 sec + int hold = 20; + + // guitarix output levels + GtkWidget* gxbox = gtk_hbox_new (FALSE, 0); + gtk_container_set_border_width (GTK_CONTAINER (gxbox), 0); + gtk_box_set_spacing(GTK_BOX(gxbox), 25); + + for (int i = 0; i < 2; i++) + { + fLevelMeters[i] = 0; + + GtkWidget* meter = + gtk_fast_meter_new(hold, width, boxheight, + base, mid, top, clip); + + gtk_widget_add_events(meter, GDK_BUTTON_RELEASE_MASK); + g_signal_connect(G_OBJECT(meter), "button-release-event", + G_CALLBACK(gx_meter_button_release), 0); + + gtk_box_pack_start(GTK_BOX(gxbox), meter, FALSE, TRUE, 0); + gtk_widget_show(meter); + + GtkTooltips* tooltips = gtk_tooltips_new (); + gtk_tooltips_set_tip(tooltips, meter, "guitarix output", " "); + fLevelMeters[i] = meter; + } + + gtk_box_pack_start(GTK_BOX(box), gxbox, FALSE, TRUE, 0); + gtk_widget_show(gxbox); + + // show main box + gtk_widget_show(box); + gtk_widget_show(box1); +} + +void GxMainInterface::openHorizontalBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_frame_new (label)); + gtk_frame_set_shadow_type(GTK_FRAME(frame),GTK_SHADOW_NONE); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openHorizontalhideBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + // gtk_widget_set_size_request (box, 270, 75); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_frame_new (label)); + gtk_frame_set_shadow_type(GTK_FRAME(frame),GTK_SHADOW_NONE); + gtk_container_add (GTK_CONTAINER(frame), box); + + pushBox(kBoxMode, box); + gtk_widget_hide(box); + } + else + { + + pushBox(kBoxMode, addWidget(label, box)); + gtk_widget_hide(box); + } +} + +void GxMainInterface::openHorizontalTableBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_frame_new (label)); + gtk_frame_set_shadow_type(GTK_FRAME(frame),GTK_SHADOW_NONE); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + + + +struct uiOrderButton : public gx_ui::GxUiItem +{ + GtkButton* fButton; + uiOrderButton (gx_ui::GxUI* ui, float* zone, GtkButton* b) : gx_ui::GxUiItem(ui, zone), fButton(b) {} + + // box move to the right + static void pressed_right( GtkWidget *widget, gpointer data ) + { + GtkWidget *box1 = gtk_widget_get_parent(GTK_WIDGET(widget)); + GtkWidget * box = gtk_widget_get_parent(GTK_WIDGET(box1)); + GtkWidget * parent = gtk_widget_get_parent(GTK_WIDGET(box)); + GValue pos = {0}; + g_value_init (&pos, G_TYPE_INT); + + gtk_container_child_get_property(GTK_CONTAINER(parent),GTK_WIDGET(box),"position", &pos); + guint per = g_value_get_int(&pos); + if (per<7) //FIXME (magic value) + { + GList* child_list = gtk_container_get_children(GTK_CONTAINER(parent)); + GtkWidget *obi = (GtkWidget *) g_list_nth_data(child_list,per+1); + child_list = gtk_container_get_children(GTK_CONTAINER(obi)); + GtkWidget *obib = (GtkWidget *) g_list_nth_data(child_list,1); + child_list = gtk_container_get_children(GTK_CONTAINER(obib)); + GtkWidget *obibi = (GtkWidget *) g_list_nth_data(child_list,0); + + gtk_box_reorder_child (GTK_BOX(parent),GTK_WIDGET(box),per +1); + ((gx_ui::GxUiItem*)data)->modifyZone(per+1); + if(GTK_IS_BUTTON (obibi)) + gtk_button_clicked(GTK_BUTTON(obibi)); + else { + child_list = gtk_container_get_children(GTK_CONTAINER(obi)); + obib = (GtkWidget *) g_list_nth_data(child_list,2); + child_list = gtk_container_get_children(GTK_CONTAINER(obib)); + obibi = (GtkWidget *) g_list_nth_data(child_list,0); + if(GTK_IS_BUTTON (obibi)) + gtk_button_clicked(GTK_BUTTON(obibi)); + } + + g_list_free(child_list); + } + + } + // box move to the left + static void pressed_left( GtkWidget *widget, gpointer data ) + { + + GtkWidget *box1 = gtk_widget_get_parent(GTK_WIDGET(widget)); + GtkWidget * box = gtk_widget_get_parent(GTK_WIDGET(box1)); + GtkWidget * parent = gtk_widget_get_parent(GTK_WIDGET(box)); + GValue pos = {0}; + g_value_init (&pos, G_TYPE_INT); + + gtk_container_child_get_property(GTK_CONTAINER(parent),GTK_WIDGET(box),"position", &pos); + guint per = g_value_get_int(&pos); + if (per>0) + { + GList* child_list = gtk_container_get_children(GTK_CONTAINER(parent)); + GtkWidget *obi = (GtkWidget *) g_list_nth_data(child_list,per-1); + child_list = gtk_container_get_children(GTK_CONTAINER(obi)); + GtkWidget *obib = (GtkWidget *) g_list_nth_data(child_list,1); + child_list = gtk_container_get_children(GTK_CONTAINER(obib)); + GtkWidget *obibi = (GtkWidget *) g_list_nth_data(child_list,1); + + gtk_box_reorder_child (GTK_BOX(parent),GTK_WIDGET(box),per -1); + ((gx_ui::GxUiItem*)data)->modifyZone(per-1); + if(GTK_IS_BUTTON (obibi)) + gtk_button_clicked(GTK_BUTTON(obibi)); + else { + child_list = gtk_container_get_children(GTK_CONTAINER(obi)); + obib = (GtkWidget *) g_list_nth_data(child_list,2); + child_list = gtk_container_get_children(GTK_CONTAINER(obib)); + obibi = (GtkWidget *) g_list_nth_data(child_list,0); + if(GTK_IS_BUTTON (obibi)) + gtk_button_clicked(GTK_BUTTON(obibi)); + } + + g_list_free(child_list); + } + + + } + // resize the effect box + static void resize( GtkWidget *widget, gpointer data ) + { + GtkWidget *box1 = gtk_widget_get_parent(GTK_WIDGET(widget)); + GList* child_list = gtk_container_get_children(GTK_CONTAINER(box1)); + GtkWidget *parent = (GtkWidget *) g_list_nth_data(child_list,1); + child_list = gtk_container_get_children(GTK_CONTAINER(parent)); + box1 = (GtkWidget *) g_list_nth_data(child_list,0); + child_list = gtk_container_get_children(GTK_CONTAINER(box1)); + box1 = (GtkWidget *) g_list_nth_data(child_list,0); + child_list = gtk_container_get_children(GTK_CONTAINER(box1)); + box1 = (GtkWidget *) g_list_nth_data(child_list,0); + child_list = gtk_container_get_children(GTK_CONTAINER(box1)); + box1 = (GtkWidget *) g_list_nth_data(child_list,0); + child_list = gtk_container_get_children(GTK_CONTAINER(box1)); + box1 = (GtkWidget *) g_list_nth_data(child_list,0); + g_list_free(child_list); + + int width, height; + gtk_widget_get_size_request (parent, &width, &height); + if (width!=-1) + { + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(parent),GTK_POLICY_NEVER,GTK_POLICY_NEVER); + gtk_widget_set_size_request (parent, -1, -1); + } + else + { + width= box1->allocation.width; + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(parent),GTK_POLICY_AUTOMATIC,GTK_POLICY_NEVER); + gtk_widget_set_size_request (parent, width*5, -1); + } + } + + // save order for neigbor box + static void clicked( GtkWidget *widget, gpointer data ) + { + GtkWidget *box1 = gtk_widget_get_parent(GTK_WIDGET(widget)); + GtkWidget * box = gtk_widget_get_parent(GTK_WIDGET(box1)); + GtkWidget * parent = gtk_widget_get_parent(GTK_WIDGET(box)); + GValue pos = {0}; + g_value_init (&pos, G_TYPE_INT); + + gtk_container_child_get_property(GTK_CONTAINER(parent),GTK_WIDGET(box),"position", &pos); + guint per = g_value_get_int(&pos); + gtk_box_reorder_child (GTK_BOX(parent),GTK_WIDGET(box),per); + + ((gx_ui::GxUiItem*)data)->modifyZone(per); + } + // set the init order + virtual void reflectZone() + { + + float v = *fZone; + fCache = v; + GValue pos = {0}; + + g_value_init (&pos, G_TYPE_INT); + g_value_set_int(&pos,(gint)fCache); + + GtkWidget *box1 = gtk_widget_get_parent(GTK_WIDGET(fButton)); + GtkWidget * box = gtk_widget_get_parent(GTK_WIDGET(box1)); + GtkWidget * parent = gtk_widget_get_parent(GTK_WIDGET(box)); + + gtk_container_child_set_property(GTK_CONTAINER(parent),GTK_WIDGET(box),"position", &pos); + guint per = g_value_get_int(&pos); + gtk_box_reorder_child (GTK_BOX(parent),GTK_WIDGET(box),per); + + } +}; + +//----- boxes to move inside a other box +void GxMainInterface::openHorizontalOrderBox(const char* label, float* posit) +{ + GtkWidget * box = gtk_vbox_new (homogene, 0); + GtkWidget * box1 = gtk_fixed_new (); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + g_signal_connect(box, "expose-event", G_CALLBACK(tribal_box_expose), NULL); + + GtkWidget* button = gtk_button_new (); + GtkWidget* button1 = gtk_button_new (); + GtkWidget* lw = gtk_label_new(">"); + GtkWidget* lw1 = gtk_label_new("<"); + gtk_container_add (GTK_CONTAINER(button), lw); + gtk_container_add (GTK_CONTAINER(button1), lw1); + gtk_widget_set_size_request (GTK_WIDGET(button), 20.0, 15.0); + gtk_widget_set_size_request (GTK_WIDGET(button1), 20.0, 15.0); + + gtk_widget_set_name (lw,"effekt_label"); + gtk_widget_set_name (lw1,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 6*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + gtk_widget_modify_font(lw1, style->font_desc); + + uiOrderButton* c = new uiOrderButton(this, posit, GTK_BUTTON(button)); + + g_signal_connect (box, "expose-event", + G_CALLBACK(vbox_expose), NULL); + g_signal_connect (GTK_OBJECT (button), "pressed", + G_CALLBACK (uiOrderButton::pressed_right), (gpointer) c); + g_signal_connect (GTK_OBJECT (button1), "pressed", + G_CALLBACK (uiOrderButton::pressed_left), (gpointer) c); + g_signal_connect (GTK_OBJECT (button), "clicked", + G_CALLBACK (uiOrderButton::clicked), (gpointer) c); + g_signal_connect (GTK_OBJECT (button1), "clicked", + G_CALLBACK (uiOrderButton::clicked), (gpointer) c); + + + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_fixed_put (GTK_FIXED(box1), button1, 15, 1); + gtk_fixed_put (GTK_FIXED(box1), button, 35, 1); + gtk_box_pack_end (GTK_BOX(box), box1, expand, fill, 0); + gtk_widget_show_all(button); + gtk_widget_show_all(button1); + gtk_widget_show(box); + gtk_widget_show(box1); + pushBox(kBoxMode, box); + +} + +void GxMainInterface::openHorizontalRestetBox(const char* label,float* posit) +{ + GtkWidget * box = gtk_vbox_new (homogene, 0); + g_signal_connect(box, "expose-event", G_CALLBACK(tribal_box_expose), NULL); + GtkWidget * box1 = gtk_fixed_new (); + g_signal_connect(box1, "expose-event", G_CALLBACK(vbox_expose), NULL); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + GtkWidget* button = gtk_button_new (); + GtkWidget* lw = gtk_label_new(""); + gtk_container_add (GTK_CONTAINER(button), lw); + + gtk_widget_set_name (lw,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 6*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + + gtk_widget_set_size_request (GTK_WIDGET(button), 45.0, 15.0); + + uiOrderButton* c = new uiOrderButton(this, posit, GTK_BUTTON(button)); + + + g_signal_connect (GTK_OBJECT (button), "clicked", + G_CALLBACK (uiOrderButton::clicked), (gpointer) c); + g_signal_connect (GTK_OBJECT (button), "pressed", + G_CALLBACK (gx_reset_effects), (gpointer) c); + + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_fixed_put (GTK_FIXED(box1), button, 10, 1); + gtk_box_pack_end (GTK_BOX(box), box1, expand, fill, 0); + + gtk_widget_show_all(button); + gtk_widget_show(box); + gtk_widget_show(box1); + pushBox(kBoxMode, box); + +} + +void GxMainInterface::openHandleBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_handle_box_new ()); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openEventBox(const char* label) +{ + GtkWidget * box = gtk_hbox_new (homogene, 4); + + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * e_box = gtk_event_box_new (); + GtkWidget * frame = addWidget(label, e_box); + gtk_widget_set_name (e_box,"osc_box"); + gtk_container_add (GTK_CONTAINER(frame), box); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +struct uiExpanderBox : public gx_ui::GxUiItem +{ + GtkExpander* fButton; + uiExpanderBox(gx_ui::GxUI* ui, float* zone, GtkExpander* b) : gx_ui::GxUiItem(ui, zone), fButton(b) {} + static void expanded (GtkWidget *widget, gpointer data) + { + float v = gtk_expander_get_expanded (GTK_EXPANDER(widget)); + + if (v == 1.000000) + v = 0; + else v = 1; + + ((gx_ui::GxUiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_expander_set_expanded(GTK_EXPANDER(fButton), v); + } +}; + +void GxMainInterface::openExpanderBox(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget * box = gtk_hbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_expander_new (label)); + gtk_container_add (GTK_CONTAINER(frame), box); + uiExpanderBox* c = new uiExpanderBox(this, zone, GTK_EXPANDER(frame)); + g_signal_connect (GTK_OBJECT (frame), "activate", G_CALLBACK (uiExpanderBox::expanded), (gpointer)c); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openVerticalBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + g_signal_connect(box, "expose-event", G_CALLBACK(vbox_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget* lw = gtk_label_new(label); + + + gtk_widget_set_name (lw,"beffekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + + gtk_container_add (GTK_CONTAINER(box), lw); + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(lw); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openSlooperBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + g_signal_connect(box, "expose-event", G_CALLBACK(slooper_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget* lw = gtk_label_new(label); + + + gtk_widget_set_name (lw,"beffekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + + gtk_container_add (GTK_CONTAINER(box), lw); + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(lw); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openFlipLabelBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + g_signal_connect(box, "expose-event", G_CALLBACK(vbox_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * hbox = gtk_hbox_new (homogene, 0); + GtkWidget * vbox = gtk_vbox_new (homogene, 0); + GtkWidget* lw = gtk_label_new(label); + gtk_label_set_angle (GTK_LABEL(lw),90); + + gtk_widget_set_name (lw,"beffekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + + gtk_container_add (GTK_CONTAINER(hbox), lw); + gtk_container_add (GTK_CONTAINER(hbox), vbox); + gtk_container_add (GTK_CONTAINER(box), hbox); + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + + gtk_widget_show_all(box); + pushBox(kBoxMode, vbox); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openSpaceBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 2); + gtk_container_set_border_width (GTK_CONTAINER (box), 4); + + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openAmpBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 2); + gtk_container_set_border_width (GTK_CONTAINER (box), 4); + g_signal_connect(box, "expose-event", G_CALLBACK(AmpBox_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openPlugBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 10); + g_signal_connect(box, "expose-event", G_CALLBACK(plug_box_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openPaintBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 2); + gtk_container_set_border_width (GTK_CONTAINER (box), 4); + g_signal_connect(box, "expose-event", G_CALLBACK(filter_box_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openpaintampBox(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 2); + gtk_container_set_border_width (GTK_CONTAINER (box), 4); + g_signal_connect(box, "expose-event", G_CALLBACK(eq_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openPaintBox1(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 2); + gtk_container_set_border_width (GTK_CONTAINER (box), 8); + g_signal_connect(box, "expose-event", G_CALLBACK(amp_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openPaintBox2(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 2); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + g_signal_connect(box, "expose-event", G_CALLBACK(upper_widget_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openVerticalBox1(const char* label) +{ + GtkWidget * box = gtk_vbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget* lw = gtk_label_new(label); + + gtk_widget_set_name (lw,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + gtk_container_add (GTK_CONTAINER(box), lw); + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(lw); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openVerticalMidiBox(const char* label) +{ + midibox = gtk_vbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (midibox), 2); + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget * frame = addWidget(label, gtk_frame_new (label)); + gtk_container_add (GTK_CONTAINER(frame), midibox); + gtk_widget_show(midibox); + pushBox(kBoxMode, midibox); + } + else + { + pushBox(kBoxMode, addWidget(label, midibox)); + } + gtk_widget_hide(midibox); +} + +void GxMainInterface::openToolBar(const char* label) +{ + GtkWidget * box = gtk_toolbar_new (); + + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + GtkWidget* lw = gtk_label_new(label); + + gtk_widget_set_name (lw,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + gtk_container_add (GTK_CONTAINER(box), lw); + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_widget_show(lw); + gtk_widget_show(box); + pushBox(kBoxMode, box); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +void GxMainInterface::openScrollBox(const char* label) +{ + GtkWidget * scrollbox = gtk_scrolled_window_new(NULL,NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrollbox),GTK_POLICY_AUTOMATIC,GTK_POLICY_NEVER); + gtk_widget_set_size_request (scrollbox, 338, -1); + GtkWidget * box = gtk_vbox_new (homogene, 0); + GtkWidget * box1 = gtk_hbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + g_signal_connect(box, "expose-event", G_CALLBACK(rectangle_skin_color_expose), NULL); + + GtkWidget* button = gtk_button_new (); + + g_signal_connect (GTK_OBJECT (button), "clicked", + G_CALLBACK (uiOrderButton::resize), NULL); + + gtk_widget_set_size_request (GTK_WIDGET(button), 10.0, -1.0); + gtk_container_add (GTK_CONTAINER(box1), button); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollbox),GTK_WIDGET(box)); + gtk_container_add (GTK_CONTAINER(box1), scrollbox); + gtk_container_add (GTK_CONTAINER(fBox[fTop]), box1); + gtk_widget_show_all(box1); + pushBox(kBoxMode, box); + +} + +struct uiSwitchDISTBox : public gx_ui::GxUiItem +{ + GtkWidget* fbox; + + uiSwitchDISTBox(gx_ui::GxUI* ui, float* zone, GtkWidget* box) + : gx_ui::GxUiItem(ui, zone), fbox(box) {} + + virtual void reflectZone() + { + GList* child_list = gtk_container_get_children(GTK_CONTAINER(fbox)); + + GtkWidget *box0 = (GtkWidget *) g_list_nth_data(child_list,0); + GtkWidget *box1 = (GtkWidget *) g_list_nth_data(child_list,1); + fCache = *fZone; + if (fCache == 1) + { + if(gx_engine::audio.fdialogbox1 ==1) + gx_engine::audio.fdis1 = 1; + gtk_widget_hide(box0); + + gx_engine::audio.fdialogbox1 = 0; + gtk_widget_show(box1); + } + else if (fCache == 0) + { + if(gx_engine::audio.fdis1 ==1) + gx_engine::audio.fdialogbox1 = 1; + gtk_widget_hide(box1); + + gx_engine::audio.fdis1 = 0; + gtk_widget_show(box0); + } + } +}; + +struct uiSwitchEQBox : public gx_ui::GxUiItem +{ + GtkWidget* fbox; + + uiSwitchEQBox(gx_ui::GxUI* ui, float* zone, GtkWidget* box) + : gx_ui::GxUiItem(ui, zone), fbox(box) {} + + virtual void reflectZone() + { + GList* child_list = gtk_container_get_children(GTK_CONTAINER(fbox)); + + GtkWidget *box0 = (GtkWidget *) g_list_nth_data(child_list,0); + GtkWidget *box1 = (GtkWidget *) g_list_nth_data(child_list,1); + if(fCache != *fZone) { + fCache = *fZone; + if (fCache == 1) + { + if(gx_engine::audio.fdialogbox_eq ==1) + gx_engine::audio.fdialogbox_eqs = 1; + gtk_widget_hide(box0); + + gx_engine::audio.fdialogbox_eq = 0; + gtk_widget_show(box1); + } + else if (fCache == 0) + { + if(gx_engine::audio.fdialogbox_eqs ==1) + gx_engine::audio.fdialogbox_eq = 1; + gtk_widget_hide(box1); + + gx_engine::audio.fdialogbox_eqs = 0; + gtk_widget_show(box0); + } + } + } +}; + +struct uiSwitchAMPBox : public gx_ui::GxUiItem +{ + GtkWidget* fbox; + + uiSwitchAMPBox(gx_ui::GxUI* ui, float* zone, GtkWidget* box) + : gx_ui::GxUiItem(ui, zone), fbox(box) {} + + virtual void reflectZone() + { + GList* child_list = gtk_container_get_children(GTK_CONTAINER(fbox)); + + GtkWidget *box0 = (GtkWidget *) g_list_nth_data(child_list,0); + GtkWidget *box1 = (GtkWidget *) g_list_nth_data(child_list,1); + if(fCache != *fZone) { + fCache = *fZone; + if (fCache == 1) + { + //if(gx_engine::audio.fdialogbox_eq ==1) + // gx_engine::audio.fdialogbox_eqs = 1; + gtk_widget_hide(box0); + gx_engine::audio.famp2 = 1; + // gx_engine::audio.fdialogbox_eq = 0; + gtk_widget_show(box1); + } + else if (fCache == 0) + { + // if(gx_engine::audio.fdialogbox_eqs ==1) + // gx_engine::audio.fdialogbox_eq = 1; + gtk_widget_hide(box1); + gx_engine::audio.famp2 = 0; + // gx_engine::audio.fdialogbox_eqs = 0; + gtk_widget_show(box0); + } + } + } +}; + +void GxMainInterface::openVerticalSwitchBox(const char* label, int state, int wit, float* zone) +{ + GtkWidget * box = gtk_vbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + g_signal_connect(box, "expose-event", G_CALLBACK(vbox_expose), NULL); + + if (fMode[fTop] != kTabMode && label[0] != 0) + { + + if(wit == 0) new uiSwitchDISTBox(this, zone, GTK_WIDGET(box)); + else if(wit == 1) new uiSwitchEQBox(this, zone, GTK_WIDGET(box)); + else if(wit == 2) new uiSwitchAMPBox(this, zone, GTK_WIDGET(box)); + //GtkWidget* lw = gtk_label_new(label); + GtkWidget * box0 = gtk_vbox_new (homogene, 0); + GtkWidget * box1 = gtk_vbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box0), 0); + gtk_container_set_border_width (GTK_CONTAINER (box1), 0); + //gtk_container_add (GTK_CONTAINER(box), lw); + gtk_box_pack_start (GTK_BOX(fBox[fTop]), box, expand, fill, 0); + gtk_container_add (GTK_CONTAINER(box), box0); + gtk_container_add (GTK_CONTAINER(box), box1); + + gtk_widget_hide(box0); + gtk_widget_hide(box1); + gtk_widget_show(box); + //addWidget(label, box); + if(state == 0) pushBox(kBoxMode, box0); + else pushBox(kBoxMode, box1); + } + else + { + pushBox(kBoxMode, addWidget(label, box)); + } +} + +GtkWidget* GxMainInterface::addWidget(const char* label, GtkWidget* w) +{ + switch (fMode[fTop]) + { + case kSingleMode : + gtk_container_add (GTK_CONTAINER(fBox[fTop]), w); + break; + case kBoxMode : + gtk_box_pack_start (GTK_BOX(fBox[fTop]), w, expand, fill, 0); + break; + case kTabMode : + gtk_notebook_append_page (GTK_NOTEBOOK(fBox[fTop]), w, gtk_label_new(label)); + break; + } + gtk_widget_show (w); + return w; +} + +// --------------------------- Press button --------------------------- + +struct uiButton : public gx_ui::GxUiItem +{ + GtkButton* fButton; + uiButton (gx_ui::GxUI* ui, float* zone, GtkButton* b) : gx_ui::GxUiItem(ui, zone), fButton(b) {} + static void pressed( GtkWidget *widget, gpointer data ) + { + gx_ui::GxUiItem* c = (gx_ui::GxUiItem*) data; + c->modifyZone(1.0); + } + + static void released( GtkWidget *widget, gpointer data ) + { + gx_ui::GxUiItem* c = (gx_ui::GxUiItem*) data; + c->modifyZone(0.0); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + if (v > 0.0) gtk_button_pressed(fButton); + else gtk_button_released(fButton); + } +}; + +void GxMainInterface::addJConvButton(const char* label, float* zone) +{ + *zone = 0.0; + GtkWidget* button = gtk_button_new (); + + GtkWidget* lab = gtk_label_new(label); + GtkStyle *style = gtk_widget_get_style(lab); + pango_font_description_set_size(style->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lab, style->font_desc); + gtk_container_add (GTK_CONTAINER(button), lab); + + gtk_widget_set_name (lab,"beffekt_label"); + addWidget(label, button); + gtk_widget_show (lab); + + uiButton* c = new uiButton(this, zone, GTK_BUTTON(button)); + g_signal_connect (GTK_OBJECT (button), "clicked", + G_CALLBACK (gx_jconv::gx_show_jconv_dialog_gui), + (gpointer) c); + +} + +// --------------------------- Toggle Buttons --------------------------- + +struct uiToggleButton : public gx_ui::GxUiItem +{ + GtkToggleButton* fButton; + uiToggleButton(gx_ui::GxUI* ui, float* zone, GtkToggleButton* b) : gx_ui::GxUiItem(ui, zone), fButton(b) {} + static void toggled (GtkWidget *widget, gpointer data) + { + float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0; + ((gx_ui::GxUiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_toggle_button_set_active(fButton, v > 0.0); + } +}; + +void GxMainInterface::addToggleButton(const char* label, float* zone) +{ + GdkColor colorRed; + GdkColor colorOwn; + gdk_color_parse ("#d56161", &colorRed); + gdk_color_parse ("#7f7f7f", &colorOwn); + GtkWidget* button = gtk_toggle_button_new(); + GtkWidget* lab = gtk_label_new(label); + GtkStyle *style = gtk_widget_get_style(lab); + pango_font_description_set_size(style->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lab, style->font_desc); + gtk_container_add (GTK_CONTAINER(button), lab); + + gtk_widget_set_name (lab,"beffekt_label"); + addWidget(label, button); + + gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &colorOwn); + gtk_widget_modify_bg (button, GTK_STATE_ACTIVE, &colorRed); + + g_signal_connect (GTK_OBJECT (button), "toggled", G_CALLBACK (JackCapture::start_stop), NULL); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE); + gtk_widget_add_accelerator(button, "activate", fAccelGroup, GDK_r, GDK_NO_MOD_MASK, GTK_ACCEL_VISIBLE); + gtk_widget_show (lab); + record_button = button; +} + +void GxMainInterface::addPToggleButton(const char* label, float* zone) +{ + GdkColor colorRed; + GdkColor colorOwn; + GdkColor colorwn; + gdk_color_parse ("#58b45e", &colorRed); + gdk_color_parse ("#000000", &colorwn); + gdk_color_parse ("#7f7f7f", &colorOwn); + *zone = 0.0; + GtkWidget* button = gtk_toggle_button_new(); + GtkWidget* lab = gtk_label_new(label); + GtkStyle *style = gtk_widget_get_style(lab); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lab, style->font_desc); + gtk_container_add (GTK_CONTAINER(button), lab); + gtk_widget_set_size_request (GTK_WIDGET(button), 60.0, 20.0); + GtkWidget * box = gtk_hbox_new (homogene, 4); + GtkWidget * box1 = gtk_vbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 0); + gtk_container_set_border_width (GTK_CONTAINER (box1), 0); + gtk_container_add (GTK_CONTAINER(box), box1); + GtkWidget * box2 = gtk_vbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box2), 0); + gtk_widget_set_size_request (GTK_WIDGET(box2), 6.0, 20.0); + gtk_container_add (GTK_CONTAINER(box), button); + gtk_container_add (GTK_CONTAINER(box), box2); + gtk_widget_set_size_request (GTK_WIDGET(box1), 6.0, 20.0); + gtk_widget_show (button); + gtk_widget_show (box1); + gtk_widget_show (box2); + gtk_widget_show (lab); + gtk_widget_show (box); + gtk_container_add (GTK_CONTAINER(fBox[fTop]), box); + uiToggleButton* c = new uiToggleButton(this, zone, GTK_TOGGLE_BUTTON(button)); + gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &colorOwn); + gtk_widget_modify_bg (button, GTK_STATE_ACTIVE, &colorRed); + gtk_widget_set_name (lab,"beffekt_label"); + g_signal_connect (GTK_OBJECT (button), "toggled", G_CALLBACK (uiToggleButton::toggled), (gpointer) c); + connect_midi_controller(button, zone); +} + +void gx_start_stop_jconv(GtkWidget *widget, gpointer data) +{ + if (gx_jconv::GxJConvSettings::checkbutton7 == 0) { + gx_engine::conv.stop(); + } else { + gx_jconv::GxJConvSettings* jcset = gx_jconv::GxJConvSettings::instance(); + bool rc = gx_engine::conv.configure( + gx_jack::jack_bs, gx_jack::jack_sr, jcset->getIRDir()+"/"+jcset->getIRFile(), + jcset->getGain(), jcset->getlGain(), jcset->getDelay(), jcset->getlDelay(), + jcset->getOffset(), jcset->getLength(), jcset->getMem(), jcset->getBufferSize()); + if (!rc || !gx_engine::conv.start()) { + gx_jconv::GxJConvSettings::checkbutton7 = 0; + } + } + //if(GDK_WINDOW(gx_gui::patch_info->window)) gdk_window_invalidate_rect(GDK_WINDOW(patch_info->window),NULL,false); +} + +void GxMainInterface::addJToggleButton(const char* label, float* zone) +{ + GdkColor colorRed; + GdkColor colorOwn; + + + gdk_color_parse ("#58b45e", &colorRed); + + gdk_color_parse ("#7f7f7f", &colorOwn); + + *zone = 0.0; + + GtkWidget* button = gtk_toggle_button_new(); + GtkWidget* lab = gtk_label_new(label); + gtk_widget_set_name (lab,"beffekt_label"); + GtkStyle *style = gtk_widget_get_style(lab); + + pango_font_description_set_size(style->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lab, style->font_desc); + gtk_container_add (GTK_CONTAINER(button), lab); + addWidget(label, button); + gtk_widget_show (lab); + + uiToggleButton* c = + new uiToggleButton(this, zone, GTK_TOGGLE_BUTTON(button)); + + gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &colorOwn); + gtk_widget_modify_bg (button, GTK_STATE_ACTIVE, &colorRed); + + + g_signal_connect (GTK_OBJECT (button), "toggled", + G_CALLBACK (uiToggleButton::toggled), (gpointer) c); + + g_signal_connect (GTK_OBJECT (button), "toggled", + G_CALLBACK (gx_start_stop_jconv), (gpointer)c); + connect_midi_controller(button, zone); +} + +// --------------------------- Check Button --------------------------- + +struct uiCheckButton : public gx_ui::GxUiItem +{ + GtkToggleButton* fButton; + uiCheckButton(gx_ui::GxUI* ui, float* zone, GtkToggleButton* b) : gx_ui::GxUiItem(ui, zone), fButton(b) {} + static void toggled (GtkWidget *widget, gpointer data) + { + float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0; + ((gx_ui::GxUiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_toggle_button_set_active(fButton, v > 0.0); + } +}; + +void GxMainInterface::addCheckButton(const char* label, float* zone) +{ + GdkColor colorRed; + GdkColor colorOwn; + GdkColor colorba; + gdk_color_parse ("#000000", &colorRed); + gdk_color_parse ("#4c5159", &colorOwn); + gdk_color_parse ("#c4c0c0", &colorba); + GtkWidget* lab = gtk_label_new(label); + GtkWidget* button = gtk_check_button_new (); + gtk_container_add (GTK_CONTAINER(button), lab); + addWidget(label, button); + gtk_widget_modify_bg (button, GTK_STATE_PRELIGHT, &colorOwn); + gtk_widget_modify_fg (button, GTK_STATE_PRELIGHT, &colorRed); + gtk_widget_modify_text (button, GTK_STATE_NORMAL, &colorRed); + gtk_widget_modify_base (button, GTK_STATE_NORMAL, &colorba); + GtkStyle *style = gtk_widget_get_style(lab); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lab, style->font_desc); + uiCheckButton* c = new uiCheckButton(this, zone, GTK_TOGGLE_BUTTON(button)); + g_signal_connect (GTK_OBJECT (button), "toggled", G_CALLBACK(uiCheckButton::toggled), (gpointer) c); + connect_midi_controller(button, zone); + gtk_widget_show (lab); +} + +// --------------------------- Adjustmenty based widgets --------------------------- + +struct uiAdjustment : public gx_ui::GxUiItem +{ + GtkAdjustment* fAdj; + uiAdjustment(gx_ui::GxUI* ui, float* zone, GtkAdjustment* adj) : gx_ui::GxUiItem(ui, zone), fAdj(adj) {} + static void changed (GtkWidget *widget, gpointer data) + { + float v = GTK_ADJUSTMENT (widget)->value; + ((gx_ui::GxUiItem*)data)->modifyZone(v); + } + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + gtk_adjustment_set_value(fAdj, v); + } + +}; + +// -------------------------- Horizontal Slider ----------------------------------- + +void GxMainInterface::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_mini_slider_new_with_adjustment (GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + addWidget(label, slider); +} + +void GxMainInterface::addHorizontalWheel(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addHorizontalWheel(label, &p.value, p.std_value, p.lower, p.upper, p.step); +} + + +void GxMainInterface::addHorizontalWheel(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_wheel_new_with_adjustment (GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + addWidget(label, slider); +} + +struct uiValueDisplay : public gx_ui::GxUiItem +{ + GtkLabel* fLabel; + int fPrecision ; + + uiValueDisplay(gx_ui::GxUI* ui, float* zone, GtkLabel* label, int precision) + : gx_ui::GxUiItem(ui, zone), fLabel(label), fPrecision(precision) {} + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + char s[64]; + if (fPrecision <= 0) + snprintf(s, 63, "%d", int(v)); + + else if (fPrecision > 3) + snprintf(s, 63, "%f", v); + + else if (fPrecision == 1) + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[1-1], v); + } + else if (fPrecision == 2) + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[2-1], v); + } + else + { + const char* format[] = {"%.1f", "%.2f", "%.3f"}; + snprintf(s, 63, format[3-1], v); + } + gtk_label_set_text(fLabel, s); + } +}; + +// -------------------------- Vertical Slider ----------------------------------- + +void GxMainInterface::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_eq_slider_new_with_adjustment (GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + GtkWidget* lw = gtk_label_new(""); + + gtk_widget_set_name (lw,"value_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 6*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + + new uiValueDisplay(this, zone, GTK_LABEL(lw),precision(step)); + + openVerticalBox1(label); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); +} + + +void GxMainInterface::addregler(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + + GtkWidget* box1 = addWidget(label, gtk_alignment_new (0.5, 0.5, 0, 0)); + GtkWidget* box = gtk_vbox_new (FALSE, 0); + GtkWidget* box2 = gtk_hbox_new (FALSE, 0); + GtkWidget* box3 = gtk_vbox_new (FALSE, 0); + GtkWidget* box4 = gtk_vbox_new (FALSE, 0); + + GtkRegler myGtkRegler; + GtkWidget* lw = myGtkRegler.gtk_value_display(GTK_ADJUSTMENT(adj)); + gtk_widget_set_name (lw,"value_label"); + + if (label[0] != 0) { + GtkWidget* lwl = gtk_label_new(label); + gtk_widget_set_name (lwl,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lwl); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lwl, style->font_desc); + gtk_container_add (GTK_CONTAINER(box), lwl); + } + + GtkWidget* slider = myGtkRegler.gtk_regler_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + + gtk_container_add (GTK_CONTAINER(box1), box); + gtk_container_add (GTK_CONTAINER(box), slider); + gtk_container_add (GTK_CONTAINER(box2), box3); + gtk_container_add (GTK_CONTAINER(box2), lw); + gtk_container_add (GTK_CONTAINER(box2), box4); + gtk_container_add (GTK_CONTAINER(box), box2); + gtk_widget_show_all(box1); + +} + +void GxMainInterface::addSpinValueBox(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + + GtkRegler myGtkRegler; + GtkWidget* lw = myGtkRegler.gtk_value_display(GTK_ADJUSTMENT(adj)); + + GtkWidget* lwl = gtk_label_new(label); + gtk_widget_set_name (lwl,"effekt_label"); + GtkStyle *style = gtk_widget_get_style(lwl); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lwl, style->font_desc); + + connect_midi_controller(lw, zone); + gtk_range_set_inverted (GTK_RANGE(lw), TRUE); + + GtkWidget* box1 = addWidget(label, gtk_alignment_new (0.5, 0.5, 0, 0)); + GtkWidget* box = gtk_vbox_new (FALSE, 0); + GtkWidget* box2 = gtk_hbox_new (FALSE, 0); + GtkWidget* box3 = gtk_vbox_new (FALSE, 0); + GtkWidget* box4 = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER(box1), box); + gtk_container_add (GTK_CONTAINER(box), lwl); + gtk_container_add (GTK_CONTAINER(box2), box3); + gtk_container_add (GTK_CONTAINER(box2), lw); + gtk_container_add (GTK_CONTAINER(box2), box4); + gtk_container_add (GTK_CONTAINER(box), box2); + gtk_widget_show_all(box1); + +} + +void GxMainInterface::addbigregler(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addbigregler(label, &p.value, p.std_value, p.lower, p.upper, p.step); +} + +void GxMainInterface::addslider(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addslider(label, &p.value, p.std_value, p.lower, p.upper, p.step); +} + +void GxMainInterface::addregler(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addregler(label, &p.value, p.std_value, p.lower, p.upper, p.step); +} + +void GxMainInterface::addSpinValueBox(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addSpinValueBox(label, &p.value, p.std_value, p.lower, p.upper, p.step); +} + +void GxMainInterface::addswitch(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const IntParameter &p = parameter_map[id].getInt(); + if (!label) { + label = p.name().c_str(); + } + addswitch(label, &p.value); +} + +void GxMainInterface::addminiswitch(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + Parameter& p = parameter_map[id]; + if (!label) { + label = p.name().c_str(); + } + if (p.isFloat()) { + addminiswitch(label, &p.getFloat().value); + } else { + addminiswitch(label, &p.getInt().value); + } +} + +void GxMainInterface::addselector(string id, const char* label, int nvalues, const char** pvalues) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + assert(p.getControlType() == Parameter::Enum); + if (nvalues) { + assert(p.upper+1 == nvalues); + } else { + nvalues = p.upper+1; + pvalues = p.getValueNames(); + } + addselector(label, &p.value, nvalues, pvalues); +} + +void GxMainInterface::addtoggle(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + Parameter& p = parameter_map[id]; + if (!label) { + label = p.name().c_str(); + } + if (p.isFloat()) { + addtoggle(label, &p.getFloat().value); + } else { + addtoggle(label, &p.getInt().value); + } +} + +void GxMainInterface::addtoggle1(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + Parameter& p = parameter_map[id]; + if (!label) { + label = p.name().c_str(); + } + if (p.isFloat()) { + addtoggle1(label, &p.getFloat().value); + } +} + +void GxMainInterface::addbtoggle(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + Parameter& p = parameter_map[id]; + if (!label) { + label = p.name().c_str(); + } + if (p.isFloat()) { + addbtoggle(label, &p.getFloat().value); + } else { + addbtoggle(label, &p.getInt().value); + } +} + +void GxMainInterface::addRecButton(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + Parameter& p = parameter_map[id]; + if (!label) { + label = p.name().c_str(); + } + + addRecButton(label, &p.getFloat().value); + +} + +void GxMainInterface::addPlayButton(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + Parameter& p = parameter_map[id]; + if (!label) { + label = p.name().c_str(); + } + + addPlayButton(label, &p.getFloat().value); + +} + +void GxMainInterface::addminieqswitch(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const IntParameter &p = parameter_map[id].getInt(); + if (!label) { + label = p.name().c_str(); + } + addminieqswitch(label, &p.value); +} + +void GxMainInterface::addminicabswitch(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const IntParameter &p = parameter_map[id].getInt(); + if (!label) { + label = p.name().c_str(); + } + addminicabswitch(label, &p.value); +} + +void GxMainInterface::addVerticalSlider(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addVerticalSlider(label, &p.value, p.std_value, p.lower, p.upper, p.step); +} + +void GxMainInterface::addCheckButton(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addCheckButton(label, &p.value); +} + +void GxMainInterface::addNumEntry(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addNumEntry(label, &p.value, p.std_value, p.lower, p.upper, p.step); +} + +void GxMainInterface::addPToggleButton(string id, const char* label) +{ + if (!parameter_map.hasId(id)) { + return; + } + const FloatParameter &p = parameter_map[id].getFloat(); + if (!label) { + label = p.name().c_str(); + } + addPToggleButton(label, &p.value); +} + +void GxMainInterface::addbigregler(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + + GtkRegler myGtkRegler; + GtkWidget* lw = myGtkRegler.gtk_value_display(GTK_ADJUSTMENT(adj)); + GtkWidget* lwl = gtk_label_new(label); + + gtk_widget_set_name (lw,"value_label"); + gtk_widget_set_name (lwl,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lwl); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lwl, style->font_desc); + + GtkWidget* slider = myGtkRegler.gtk_big_regler_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + GtkWidget* box1 = addWidget(label, gtk_alignment_new (0.5, 0.5, 0, 0)); + GtkWidget* box = gtk_vbox_new (FALSE, 0); + GtkWidget* box2 = gtk_hbox_new (FALSE, 4); + GtkWidget* box3 = gtk_vbox_new (FALSE, 0); + GtkWidget* box4 = gtk_vbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER(box1), box); + gtk_container_add (GTK_CONTAINER(box), lwl); + gtk_container_add (GTK_CONTAINER(box), slider); + gtk_container_add (GTK_CONTAINER(box2), box3); + gtk_container_add (GTK_CONTAINER(box2), lw); + gtk_container_add (GTK_CONTAINER(box2), box4); + gtk_container_add (GTK_CONTAINER(box), box2); + gtk_widget_show_all(box1); +} + +void GxMainInterface::addslider(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkWidget* lw = gtk_label_new(""); + GtkWidget* lwl = gtk_label_new(label); + + gtk_widget_set_name (lw,"value_label"); + gtk_widget_set_name (lwl,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + gtk_widget_modify_font(lwl, style->font_desc); + + new uiValueDisplay(this, zone, GTK_LABEL(lw),precision(step)); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_hslider_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + gtk_range_set_inverted (GTK_RANGE(slider), TRUE); + GtkWidget* box = addWidget(label,gtk_vbox_new (FALSE, 0)); + gtk_container_add (GTK_CONTAINER(box), lwl); + gtk_container_add (GTK_CONTAINER(box), slider); + gtk_container_add (GTK_CONTAINER(box), lw); + gtk_widget_show_all(box); +} + +void GxMainInterface::addtoggle(const char* label, int* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this,(float*) zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + addWidget(label, slider); +} + +void GxMainInterface::addtoggle(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + addWidget(label, slider); +} + +void GxMainInterface::addbtoggle(const char* label, int* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this,(float*) zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_button_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + addWidget(label, slider); +} + +void GxMainInterface::addbtoggle(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_button_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + addWidget(label, slider); +} + +void GxMainInterface::addRecButton(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_button_rec_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + addWidget(label, slider); +} + +void GxMainInterface::addPlayButton(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_button_play_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + addWidget(label, slider); +} + +void GxMainInterface::addswitch(const char* label, int* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this,(float*) zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_switch_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + openVerticalBox(""); + string laba = label; + if (laba !="")addWidget(label, lw); + addWidget(label, slider); + closeBox(); +} + +void GxMainInterface::addtoggle1(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_switch_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + openVerticalBox(""); + string laba = label; + if (laba !="")addWidget(label, lw); + addWidget(label, slider); + closeBox(); +} + +void GxMainInterface::addselector(const char* label, float* zone, int maxv, const char** labels) +{ + GtkObject* adjs = gtk_adjustment_new(0, 0, maxv-1, 1, 10*1, 0); + uiAdjustment* cs = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adjs)); + g_signal_connect (GTK_OBJECT (adjs), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) cs); + + GtkRegler myGtkRegler; + GtkWidget* ser = myGtkRegler.gtk_selector_new_with_adjustment(GTK_ADJUSTMENT(adjs), maxv, labels); + connect_midi_controller(ser, zone); + + openHorizontalBox(""); + addWidget(label, ser); + closeBox(); +} + +void GxMainInterface::addminiswitch(const char* label, int* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this,(float*) zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_mini_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + openHorizontalBox(""); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); +} + +void GxMainInterface::addminiswitch(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_mini_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lw, style->font_desc); + openHorizontalBox(""); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); +} + +void GxMainInterface::addminieqswitch(const char* label, int* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this,(float*) zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + + + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_mini_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + //g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (gx_hide_eq), (gpointer) slider); + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + openHorizontalBox(""); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); +} + +void GxMainInterface::addminicabswitch(const char* label, int* zone) +{ + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this,(float*) zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + + + GtkRegler myGtkRegler; + GtkWidget* slider = myGtkRegler.gtk_mini_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + connect_midi_controller(slider, zone); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (gx_cab_res), (gpointer) slider); + GtkWidget* lw = gtk_label_new(label); + gtk_widget_set_name (lw,"effekt_label"); + + GtkStyle *style = gtk_widget_get_style(lw); + pango_font_description_set_size(style->font_desc, 8*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lw, style->font_desc); + openHorizontalBox(""); + addWidget(label, slider); + addWidget(label, lw); + closeBox(); +} + +void GxMainInterface::addNumEntry(const char* label, float* zone, float init, float min, float max, float step) +{ + *zone = init; + GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkWidget* spinner = gtk_spin_button_new (GTK_ADJUSTMENT(adj), step, precision(step)); + connect_midi_controller(spinner, zone); + openFrameBox(label); + addWidget(label, spinner); + closeBox(); +} + +void GxMainInterface::openWarningBox(const char* label, float* zone) +{ + GtkWidget* button = gtk_check_button_new (); + uiCheckButton* c = new uiCheckButton(this, zone, GTK_TOGGLE_BUTTON(button)); + g_signal_connect (GTK_OBJECT (button), "toggled", G_CALLBACK(uiCheckButton::toggled), (gpointer) c); +} + +void GxMainInterface::setSkinBox(const char* label, float* zone) +{ + GtkObject* adj = gtk_adjustment_new(99, 0, 100, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (gx_set_skin), (gpointer) c); +} + +void GxMainInterface::openDialogBox(const char* id, float* zone, int * z1) +{ + const char *label = param_group(id).c_str(); + GtkWidget * dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_decorated(GTK_WINDOW(dialog), TRUE); + gtk_window_set_icon(GTK_WINDOW (dialog), GDK_PIXBUF(ib)); + gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); + gtk_window_set_gravity(GTK_WINDOW(dialog), GDK_GRAVITY_SOUTH); + gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(fWindow)); + gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); + gtk_window_set_keep_below (GTK_WINDOW(dialog), FALSE); + gtk_window_set_title (GTK_WINDOW (dialog), label); + gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_UTILITY); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + GtkWidget * box = gtk_hbox_new (homogene, 8); + GtkWidget * box4 = gtk_vbox_new (homogene, 4); + GtkWidget * box5 = gtk_hbox_new (homogene, 4); + gtk_container_set_border_width (GTK_CONTAINER (box), 2); + gtk_container_set_border_width (GTK_CONTAINER (box4), 8); + g_signal_connect(box4, "expose-event", G_CALLBACK(rectangle_expose), NULL); + GdkColor colorRed; + GdkColor colorOwn; + gdk_color_parse ("#000094", &colorRed); + gdk_color_parse ("#7f7f7f", &colorOwn); + *zone = 0.0; + + GtkObject* adj = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + g_signal_connect (GTK_OBJECT (adj), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) c); + GtkRegler myGtkRegler; + GtkWidget* button = myGtkRegler.gtk_button_toggle_new_with_adjustment(GTK_ADJUSTMENT(adj)); + + GtkWidget * box3 = gtk_hbox_new (homogene, 0); + gtk_container_set_border_width (GTK_CONTAINER (box3), 0); + gtk_container_add (GTK_CONTAINER(box3), button); + gtk_widget_show (button); + gtk_widget_show (box3); + gtk_container_add (GTK_CONTAINER(fBox[fTop]), box3); + gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &colorOwn); + gtk_widget_modify_bg (button, GTK_STATE_ACTIVE, &colorRed); + g_signal_connect (GTK_OBJECT (button), "value-changed", G_CALLBACK (gx_show_extended_settings), (gpointer) dialog); + g_signal_connect_swapped (G_OBJECT (dialog), "delete_event", G_CALLBACK (gx_delete_event), (gpointer) button); + GtkWidget * frame = gtk_frame_new (label); + GtkWidget* lab = gtk_label_new("reset"); + GtkWidget* button1 = gtk_button_new(); + gtk_container_add (GTK_CONTAINER(button1), lab); + + GtkStyle *style = gtk_widget_get_style(lab); + pango_font_description_set_size(style->font_desc, 10*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_NORMAL); + gtk_widget_modify_font(lab, style->font_desc); + + GtkObject* adjl = gtk_adjustment_new(0, 0, 1, 1, 10*1, 0); + uiAdjustment* cl = new uiAdjustment(this,(float*) z1, GTK_ADJUSTMENT(adjl)); + g_signal_connect (GTK_OBJECT (adjl), "value-changed", G_CALLBACK (uiAdjustment::changed), (gpointer) cl); + + + + GtkWidget* led = myGtkRegler.gtk_led_new_with_adjustment(GTK_ADJUSTMENT(adjl)); + + //connect_midi_controller(slider, zone); + gtk_container_add (GTK_CONTAINER(box5), led); + gtk_container_add (GTK_CONTAINER(box5), frame); + gtk_container_add (GTK_CONTAINER(box5), button1); + g_signal_connect (GTK_OBJECT (button1), "pressed", G_CALLBACK (gx_reset_units), (gpointer) id); + gtk_container_add (GTK_CONTAINER(box4), box5); + gtk_container_add (GTK_CONTAINER(box4), box); + gtk_container_add (GTK_CONTAINER(dialog), box4); + // gtk_widget_show(dialog); + gtk_widget_show(lab); + gtk_widget_show(led); + gtk_widget_show(frame); + gtk_widget_show(button1); + gtk_widget_show(box); + gtk_widget_show(box4); + gtk_widget_show(box5); + pushBox(kBoxMode, box); +} +//-------- collect patch info for stage display +struct uiPatchDisplay : public gx_ui::GxUiItem +{ + GtkWidget* fdialog; + + uiPatchDisplay(gx_ui::GxUI* ui, float* zone, GtkWidget* dialog) + : gx_ui::GxUiItem(ui, zone), fdialog(dialog) {} + + virtual void reflectZone() + { + GList* child_list = gtk_container_get_children(GTK_CONTAINER(fdialog)); + GtkWidget *parent = (GtkWidget *) g_list_nth_data(child_list,0); + if(GDK_WINDOW(parent->window)) { + if (fCache != *fZone) { + char s[64]; + gdk_window_invalidate_rect(GDK_WINDOW(parent->window),NULL,false); + child_list = gtk_container_get_children(GTK_CONTAINER(parent)); + parent = (GtkWidget *) g_list_nth_data(child_list,1); + GtkWidget *pchild = (GtkWidget *) g_list_nth_data(child_list,2); + gx_jconv::GxJConvSettings* jcset = gx_jconv::GxJConvSettings::instance(); + + if(gx_jconv::GxJConvSettings::checkbutton7 == 1) { + snprintf(s, 63, "convolve %s",jcset->getIRFile().c_str()); + gtk_label_set_text(GTK_LABEL(pchild),s); + }else { + snprintf(s, 63, "convolver off"); + gtk_label_set_text(GTK_LABEL(pchild),s); + } + + if(setting_is_preset ) { + snprintf(s, 63, " %i%s%s ", int(show_patch_info),". ",gx_current_preset.c_str()); + gtk_label_set_text(GTK_LABEL(parent), s); + } + else { + show_patch_info = 0; + snprintf(s, 63, " %i%sMain Setting ", int(show_patch_info),". "); + gtk_label_set_text(GTK_LABEL(parent), s); + } + fCache = *fZone; + } + } + } +}; + +//----- hide the jconv settings widget +gboolean gx_delete_pi( GtkWidget *widget, gpointer data ) +{ + gtk_widget_hide(patch_info); + return TRUE; +} + +void GxMainInterface::openPatchInfoBox(float* zone) +{ + patch_info = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_decorated(GTK_WINDOW(patch_info), TRUE); + gtk_window_set_icon(GTK_WINDOW (patch_info), GDK_PIXBUF(ib)); + gtk_window_set_resizable(GTK_WINDOW(patch_info), FALSE); + gtk_window_set_gravity(GTK_WINDOW(patch_info), GDK_GRAVITY_SOUTH); + gtk_window_set_transient_for (GTK_WINDOW(patch_info), GTK_WINDOW(fWindow)); + gtk_window_set_position (GTK_WINDOW(patch_info), GTK_WIN_POS_MOUSE); + gtk_window_set_keep_below (GTK_WINDOW(patch_info), FALSE); + gtk_window_set_title (GTK_WINDOW (patch_info), "Patch Info"); + gtk_window_set_type_hint (GTK_WINDOW (patch_info), GDK_WINDOW_TYPE_HINT_UTILITY); + gtk_window_set_destroy_with_parent(GTK_WINDOW(patch_info), TRUE); + GtkWidget * box = gtk_vbox_new (homogene, 8); + const char *labe = ""; + GtkWidget* la = gtk_label_new(labe); + GtkWidget* lab = gtk_label_new(labe); + GtkWidget* label = gtk_label_new(labe); + new uiPatchDisplay(this, zone, GTK_WIDGET(patch_info)); + g_signal_connect_swapped (G_OBJECT (patch_info), "delete_event", G_CALLBACK (gx_delete_pi), NULL); + g_signal_connect(box, "expose-event", G_CALLBACK(info_box_expose), NULL); + gtk_container_set_border_width (GTK_CONTAINER (box), 8); + + GtkStyle *style = gtk_widget_get_style(lab); + pango_font_description_set_size(style->font_desc, 30*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(lab, style->font_desc); + + gtk_container_add (GTK_CONTAINER(box), la); + gtk_container_add (GTK_CONTAINER(box), lab); + gtk_container_add (GTK_CONTAINER(box), label); + gtk_container_add (GTK_CONTAINER(patch_info), box); + + gtk_widget_hide(patch_info); +} + +// ------------------------------ Num Display ----------------------------------- + +struct uiNumDisplay : public gx_ui::GxUiItem +{ + GtkWidget* fLabel; + + uiNumDisplay(gx_ui::GxUI* ui, float* zone, GtkWidget* label) + : gx_ui::GxUiItem(ui, zone), fLabel(label) {} + + virtual void reflectZone() + { + + fCache = *fZone; + if (shownote == 1) + { + /*static int tx = pb->allocation.x + (pb->allocation.width - 100) * 0.5; + static int ty = pb->allocation.y + (pb->allocation.height - 90) * 0.5; + static const GdkRectangle rect = {tx,ty,100,60}; + gdk_window_invalidate_rect(GDK_WINDOW(pb->window),&rect,TRUE);*/ + gx_tuner_refresh(pb,NULL); + } + else if (shownote == 0) + { + shownote = -1; + } + } +}; + + +void GxMainInterface::addNumDisplay(const char* label, float* zone ) +{ + openEventBox(label); + + pb = gx_tuner_view (); + // g_signal_connect(pb, "expose-event", G_CALLBACK(tuner_expose), NULL); + + new uiNumDisplay(this, zone, GTK_WIDGET(pb)); + gtk_widget_set_size_request(pb, 100.0, 90.0); + + addWidget(label, pb); + gtk_widget_hide(pb); + closeBox(); +} + +struct uiStatusDisplay : public gx_ui::GxUiItem +{ + GtkLabel* fLabel; + int fPrecision; + + uiStatusDisplay(gx_ui::GxUI* ui, float* zone, GtkLabel* label) + : gx_ui::GxUiItem(ui, zone), fLabel(label) {} + + virtual void reflectZone() + { + float v = *fZone; + fCache = v; + if ((gx_engine::isMidiOn() == true) && + (gx_jack::jcpu_load < 65.0)) + { + if (v > 0.0f) gtk_status_icon_set_from_pixbuf ( GTK_STATUS_ICON(status_icon), GDK_PIXBUF(ibm)); + else gtk_status_icon_set_from_pixbuf ( GTK_STATUS_ICON(status_icon), GDK_PIXBUF(ib)); + } + else if (gx_engine::isMidiOn() == false) + { + gtk_status_icon_set_from_pixbuf ( GTK_STATUS_ICON(status_icon), GDK_PIXBUF(ib)); + } + else gtk_status_icon_set_from_pixbuf ( GTK_STATUS_ICON(status_icon), GDK_PIXBUF(ibr)); + } +}; + +void GxMainInterface::addStatusDisplay(const char* label, float* zone ) +{ + GtkWidget* lw = gtk_label_new(""); + new uiStatusDisplay(this, zone, GTK_LABEL(lw)); + openFrameBox(label); + addWidget(label, lw); + closeBox(); + gtk_widget_hide(lw); +} + +void GxMainInterface::addLiveWaveDisplay(const char* label, float* zone , float* zone1) +{ + GtkObject* adj = gtk_adjustment_new(0.0, -1.0, 1.0, 0.0009, 10*0.0009, 0); + new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj)); + + livewa = gx_wave_live_view(zone,zone1,GTK_ADJUSTMENT(adj)); + GtkWidget * box = gtk_vbox_new (false, 4); + GtkWidget * e_box = gtk_event_box_new (); + g_signal_connect(box, "expose-event", G_CALLBACK(conv_widget_expose), NULL); + gtk_widget_set_size_request (box, 303, 82); + gtk_widget_set_size_request (e_box, 280, 50); + gtk_container_set_border_width (GTK_CONTAINER (box), 12); + gtk_container_add (GTK_CONTAINER(e_box),livewa ); + gtk_container_add (GTK_CONTAINER(box),e_box ); + addWidget(label, box); + gtk_widget_show(box); + gtk_widget_hide(e_box); + gtk_widget_hide(livewa); +} + +//----------------------------- main menu ---------------------------- +void GxMainInterface::addMainMenu() +{ + /*-- Declare the GTK Widgets used in the menu --*/ + GtkWidget* menucont; // menu container + GtkWidget* menupix; // menu container + GtkWidget* hbox; // top menu bar box container + + /*------------------ TOP Menu BAR ------------------*/ + hbox = gtk_hbox_new(FALSE, 0); + + /*-- Create the menu bar --*/ + menucont = gtk_menu_bar_new(); + gtk_box_pack_start(GTK_BOX(hbox), menucont, TRUE, TRUE, 0); + + /*-- Create the pixmap menu bar --*/ + menupix = gtk_menu_bar_new(); + gtk_box_pack_end(GTK_BOX(hbox), menupix, TRUE, TRUE, 0); + + /*-- set packdirection for pixmaps from right to left --*/ + gtk_menu_bar_set_pack_direction(GTK_MENU_BAR(menupix),GTK_PACK_DIRECTION_RTL); + + /*-- Engine on/off and status --*/ + // set up ON image: shown by default + string img_path = gx_pixmap_dir + "gx_on.png"; + + gx_engine_on_image = gtk_image_menu_item_new_with_label(""); + GtkWidget* engineon = gtk_image_new_from_file(img_path.c_str()); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gx_engine_on_image),engineon); + gtk_menu_bar_append (GTK_MENU_BAR(menupix), gx_engine_on_image); + GtkTooltips* comandlin = gtk_tooltips_new (); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (comandlin), + gx_engine_on_image, "engine is on", "engine state."); + gtk_widget_show(gx_engine_on_image); + + // set up OFF image: hidden by default + img_path = gx_pixmap_dir + "gx_off.png"; + + gx_engine_off_image = gtk_image_menu_item_new_with_label(""); + GtkWidget* engineoff = gtk_image_new_from_file(img_path.c_str()); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gx_engine_off_image),engineoff); + gtk_menu_bar_append (GTK_MENU_BAR(menupix), gx_engine_off_image); + gtk_tooltips_set_tip(GTK_TOOLTIPS (comandlin), + gx_engine_off_image, "engine is off", "engine state."); + gtk_widget_hide(gx_engine_off_image); + + // set up BYPASS image: hidden by default + img_path = gx_pixmap_dir + "gx_bypass.png"; + + gx_engine_bypass_image = gtk_image_menu_item_new_with_label(""); + GtkWidget* engineby = gtk_image_new_from_file(img_path.c_str()); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gx_engine_bypass_image),engineby); + gtk_menu_bar_append (GTK_MENU_BAR(menupix), gx_engine_bypass_image); + gtk_tooltips_set_tip(GTK_TOOLTIPS (comandlin), + gx_engine_bypass_image, "engine is in bypass mode", "engine state."); + gtk_widget_hide(gx_engine_bypass_image); + + + /*-- Jack server status image --*/ + // jackd ON image + img_path = gx_pixmap_dir + "jackd_on.png"; + + gx_jackd_on_image = gtk_image_menu_item_new_with_label(""); + GtkWidget* jackstateon = gtk_image_new_from_file(img_path.c_str()); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gx_jackd_on_image),jackstateon); + gtk_menu_bar_append (GTK_MENU_BAR(menupix), gx_jackd_on_image); + + GtkTooltips* comandline = gtk_tooltips_new (); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (comandline), + gx_jackd_on_image, "jack server is connectet", "jack server state."); + + gtk_widget_show(gx_jackd_on_image); + + // jackd OFF image: hidden by default + img_path = gx_pixmap_dir + "jackd_off.png"; + + gx_jackd_off_image = gtk_image_menu_item_new_with_label(""); + GtkWidget* jackstateoff = gtk_image_new_from_file(img_path.c_str()); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gx_jackd_off_image),jackstateoff); + gtk_menu_bar_append (GTK_MENU_BAR(menupix), gx_jackd_off_image); + gtk_tooltips_set_tip(GTK_TOOLTIPS (comandline), + gx_jackd_off_image, "jack server is unconnectet", "jack server state."); + gtk_widget_hide(gx_jackd_off_image); + + + /* ----------------------------------------------------------- */ + fMenuList["Top"] = menucont; + + addEngineMenu(); + addPresetMenu(); + //addPluginMenu(); + addOptionMenu(); + addAboutMenu(); + + /*---------------- add menu to main window box----------------*/ + gtk_box_pack_start (GTK_BOX (fBox[fTop]), hbox , FALSE, FALSE, 0); + gtk_widget_show(menucont); + gtk_widget_show(menupix); + gtk_widget_show(hbox); +} + +//----------------------------- engine menu ---------------------------- +void GxMainInterface::addEngineMenu() +{ + GtkWidget* menulabel; // menu label + //GtkWidget* menucont; // menu container use menuh for systray menu here + GtkWidget* menuitem; // menu item + GSList * group = NULL; + + /*---------------- Create Engine menu items ------------------*/ + menuh = fMenuList["Top"]; + + menulabel = gtk_menu_item_new_with_mnemonic ("_Engine"); + gtk_menu_bar_append (GTK_MENU_BAR(menuh), menulabel); + gtk_widget_show(menulabel); + + /*-- Create Engine submenu --*/ + menuh = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menuh); + gtk_widget_show(menuh); + fMenuList["Engine"] = menuh; + + /*-- Create Engine start / stop item --*/ + group = NULL; + + menuitem = gtk_check_menu_item_new_with_mnemonic ("Engine _Start / _Stop"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_space, GDK_NO_MOD_MASK, GTK_ACCEL_VISIBLE); + + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), menuitem); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), TRUE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_engine_switch), (gpointer)0); + gx_engine_item = menuitem; // save into global var + gtk_widget_show (menuitem); + + /*-- Create Engine bypass item --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("Engine _Bypass"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_b, GDK_NO_MOD_MASK, GTK_ACCEL_VISIBLE); + + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), menuitem); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_engine_switch), (gpointer)1); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + GtkWidget* sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), sep); + gtk_widget_show (sep); + + /*---------------- Create Jack Server menu --------------------*/ + addJackServerMenu(); + + /*---------------- End Jack server menu declarations ----------------*/ + +#ifdef EXPERIMENTAL + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), sep); + gtk_widget_show (sep); + menuitem = gtk_check_menu_item_new_with_mnemonic ("_Experimental"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_e, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + gtk_widget_show(menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), menuitem); + SwitchParameter *p = new SwitchParameter("system.show_exp_window"); + fShowExpWindow.init(GTK_CHECK_MENU_ITEM(menuitem), p); + p->changed.connect(ptr_fun(gx_engine::toggle_exp_window)); +#endif + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), sep); + gtk_widget_show (sep); + + /*-- create Midi Controller Table menu item --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("M_idi Controller"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_i, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect ( + GTK_OBJECT (menuitem), "activate", + G_CALLBACK (MidiControllerTable::toggle), menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), menuitem); + gtk_widget_show (menuitem); + + /*-- Create Open check menu item under Engine submenu --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("_Midi Out "); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_m, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_midi_out), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), menuitem); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), sep); + gtk_widget_show (sep); + + /*-- Create Exit menu item under Engine submenu --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("_Quit"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect(G_OBJECT (menuitem), "activate", + G_CALLBACK (gx_clean_exit), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), menuitem); + gtk_widget_show (menuitem); + + /*---------------- End Engine menu declarations ----------------*/ +} + +//----------------------------- preset menu ---------------------------- +void GxMainInterface::addPresetMenu() +{ + GtkWidget* menulabel; // menu label + GtkWidget* menucont; // menu container + GtkWidget* menuitem; // menu item + + menucont = fMenuList["Top"]; + + /*---------------- Create Presets menu items --------------------*/ + menulabel = gtk_menu_item_new_with_mnemonic ("_Presets"); + gtk_menu_bar_append (GTK_MENU_BAR(menucont), menulabel); + gtk_widget_show(menulabel); + + /*-- Create Presets submenus --*/ + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menucont); + gtk_widget_show(menucont); + fMenuList["Presets"] = menucont; + + /* special treatment of preset lists, from gx_preset namespace */ + for (int i = 0; i < GX_NUM_OF_PRESET_LISTS; i++) + { + GtkWidget* menuItem = + gtk_menu_item_new_with_mnemonic (preset_menu_name[i]); + gtk_menu_shell_append (GTK_MENU_SHELL(menucont), menuItem); + + GtkWidget* menu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuItem), menu); + + gtk_menu_set_accel_path(GTK_MENU(menu), preset_accel_path[i]); + + presmenu[i] = menu; + presMenu[i] = menuItem; + } + + + /*-- add New Preset saving under Save Presets menu */ + menuitem = gtk_menu_item_new_with_mnemonic ("New _Preset"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_save_newpreset_dialog), NULL); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_p, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_insert(GTK_MENU_SHELL(presmenu[SAVE_PRESET_LIST]), menuitem, 0); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + GtkWidget* sep = gtk_separator_menu_item_new(); + gtk_menu_shell_insert(GTK_MENU_SHELL(presmenu[SAVE_PRESET_LIST]), sep, 1); + gtk_widget_show (sep); + + /*-- initial preset list --*/ + gx_preset::gx_refresh_preset_menus(); + + for (int i = 0; i < GX_NUM_OF_PRESET_LISTS; i++) + gtk_widget_show(presMenu[i]); + + /* ------------------- */ + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create patch info menu item under Options submenu --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("P_atch Info"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_a, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_patch), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create load presetfile menu --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("Load Preset-_file"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_f, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_load_preset_file), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + /*-- Create save as presetfile menu--*/ + menuitem = gtk_menu_item_new_with_mnemonic ("E_xport Preset-file"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_x, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_save_preset_file), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create Main setting submenu --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("Recall Main _Setting"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_recall_main_setting), NULL); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_s, GDK_NO_MOD_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + menuitem = gtk_menu_item_new_with_mnemonic ("_Save As Main _Setting"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_save_main_setting), NULL); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_s, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create sub menu More Preset Action --*/ + menulabel = gtk_menu_item_new_with_mnemonic("More Preset Options..."); + gtk_menu_shell_append (GTK_MENU_SHELL(menucont), menulabel); + gtk_widget_show(menulabel); + + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menucont); + gtk_widget_show(menucont); + fMenuList["ExtraPresets"] = menucont; + + /*--------------- Extra preset menu */ + addExtraPresetMenu(); +} + + +//------------------------ extra preset menu ---------------------------- +void GxMainInterface::addExtraPresetMenu() +{ + GtkWidget* menucont; // menu container + GtkWidget* menuitem; // menu item + + menucont = fMenuList["ExtraPresets"]; + + /*---------------- Create Presets menu items --------------------*/ + + /* forward preset */ + menuitem = gtk_menu_item_new_with_mnemonic("Next _Preset"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_next_preset), NULL); + gtk_widget_add_accelerator(menuitem, "activate", + fAccelGroup, GDK_Page_Down, + GDK_NO_MOD_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show(menuitem); + + /* rewind preset */ + menuitem = gtk_menu_item_new_with_mnemonic("Previous _Preset"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_previous_preset), NULL); + gtk_widget_add_accelerator(menuitem, "activate", + fAccelGroup, GDK_Page_Up, + GDK_NO_MOD_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show(menuitem); + + /*-- add a separator line --*/ + GtkWidget* sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create menu item Delete Active preset --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("_Save _Active Preset"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_save_oldpreset), (gpointer)1); + gtk_widget_add_accelerator(menuitem, "activate", + fAccelGroup, GDK_s, + GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + menuitem = gtk_menu_item_new_with_mnemonic ("_Rename _Active Preset"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_rename_active_preset_dialog), NULL); + gtk_widget_add_accelerator(menuitem, "activate", + fAccelGroup, GDK_r, + GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + menuitem = gtk_menu_item_new_with_mnemonic ("_Delete Active Preset"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_delete_active_preset_dialog), NULL); + gtk_widget_add_accelerator(menuitem, "activate", + fAccelGroup, GDK_Delete, + GDK_NO_MOD_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create menu item Delete All presets --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("_Delete All Presets"); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_delete_all_presets_dialog), NULL); + gtk_widget_add_accelerator(menuitem, "activate", + fAccelGroup, GDK_d, + GdkModifierType(GDK_CONTROL_MASK|GDK_SHIFT_MASK), GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + +} + +//----------------------------- option menu ---------------------------- + +void reset_all_parameters(GtkWidget*, gpointer) +{ + for (ParamMap::iterator i = parameter_map.begin(); i != parameter_map.end(); i++) { + i->second->set_std_value(); + } +} +/* +void GxMainInterface::addPluginMenu() +{ + GtkWidget* menulabel; // menu label + GtkWidget* menucont; // menu container + GtkWidget* menuitem; // menu item + + menucont = fMenuList["Top"]; + + + menulabel = gtk_menu_item_new_with_mnemonic ("Plu_gins"); + gtk_menu_bar_append (GTK_MENU_BAR(menucont), menulabel); + gtk_widget_show(menulabel); + + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menucont); + gtk_widget_show(menucont); + fMenuList["Plugins"] = menucont; + + menuitem = gtk_menu_item_new_with_mnemonic ("_add"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_a, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menucont); + gtk_widget_show(menucont); + fMenuList["Plugins_add"] = menucont; + + menucont =fMenuList["Plugins"]; + menuitem = gtk_menu_item_new_with_mnemonic ("_remove"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_r, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menucont); + gtk_widget_show(menucont); + fMenuList["Plugins_remove"] = menucont; + + +}*/ + +void GxMainInterface::addOptionMenu() +{ + GtkWidget* menulabel; // menu label + GtkWidget* menucont; // menu container + GtkWidget* menuitem; // menu item + + menucont = fMenuList["Top"]; + + /*---------------- Create Options menu items ------------------*/ + menulabel = gtk_menu_item_new_with_mnemonic ("_Options"); + gtk_menu_bar_append (GTK_MENU_BAR(menucont), menulabel); + gtk_widget_show(menulabel); + + /*-- Create Options submenu --*/ + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menucont); + gtk_widget_show(menucont); + fMenuList["Options"] = menucont; + + /*-- Create oscilloscope check menu item under Options submenu --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("_Oscilloscope"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_o, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_show_oscilloscope), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + fShowWaveView.init(GTK_CHECK_MENU_ITEM(menuitem), + new SwitchParameter("system.show_wave_view")); + + /*-- Create tuner check menu item under Options submenu --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("_Tuner"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_t, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_tuner), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + fShowTuner.init(GTK_CHECK_MENU_ITEM(menuitem), + new SwitchParameter("system.show_tuner")); + + /*-- Create log window check menu item under Options submenu --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("Open/Close _Log message"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_l, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_log_window), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (menuitem), FALSE); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + GtkWidget* sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create Open check menu item under Options submenu --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("_Meterbridge"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_m, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (Meterbridge::start_stop), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + /*-- Create Open check menu item under Options submenu --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("_Jack Capture Settings"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_j, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + g_signal_connect(GTK_OBJECT (menuitem), "activate", + G_CALLBACK (JackCaptureGui::start_stop), NULL); + gtk_widget_show (menuitem); + + /*-- add a separator line --*/ + sep = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), sep); + gtk_widget_show (sep); + + /*-- Create skin menu under Options submenu--*/ + addGuiSkinMenu(); + + /*-- create option for saving midi controller settings in presets --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("Include MIDI in _presets"); + gtk_widget_show (menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + fMidiInPreset.init( + GTK_CHECK_MENU_ITEM(menuitem), new SwitchParameter("system.midi_in_preset")); + + /*-- create option for resetting guitarix settings --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("Reset _All Parameters"); + gtk_widget_show (menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + g_signal_connect(GTK_OBJECT(menuitem), "activate", + G_CALLBACK(reset_all_parameters), NULL); +} + + +//----------------------------- skin menu ---------------------------- +void GxMainInterface::addGuiSkinMenu() +{ + GtkWidget* menulabel; // menu label + GtkWidget* menucont; // menu container + GtkWidget* menuitem; // menu item + GSList * group = NULL; + + menucont = fMenuList["Options"]; + + /*---------------- Create skin menu items ------------------*/ + menulabel = gtk_menu_item_new_with_mnemonic ("_Skin..."); + gtk_menu_append (GTK_MENU(menucont), menulabel); + gtk_widget_show(menulabel); + + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menucont); + gtk_widget_show(menucont); + fMenuList["Skin"] = menucont; + + /* Create black skin item under skin submenu --*/ + guint idx = 0; + + while (idx < skin_list.size()) + { + menuitem = + gtk_radio_menu_item_new_with_label (group, skin_list[idx].c_str()); + + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem)); + + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM (menuitem), FALSE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_change_skin), GINT_TO_POINTER(idx)); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + idx++; + } + + menucont = fMenuList["Options"]; + + menuitem = gtk_menu_item_new(); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_s, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_cycle_through_skin), NULL); + gtk_menu_append (GTK_MENU(menucont), menuitem); + gtk_widget_show (menuitem); + + /*-- End skin menu declarations --*/ +} + +//----------------------------- about menu ---------------------------- +static void set_tooltips(bool v) +{ + gtk_settings_set_long_property( + gtk_settings_get_default(),"gtk-enable-tooltips",v, + "guitarix menu-option"); +} + +void GxMainInterface::addAboutMenu() +{ + GtkWidget* menulabel; // menu label + GtkWidget* menucont; // menu container + GtkWidget* menuitem; // menu item + + menucont = fMenuList["Top"]; + + /*---------------- Start About menu declarations ----------------*/ + menulabel = gtk_menu_item_new_with_mnemonic ("_About"); + gtk_menu_bar_append (GTK_MENU_BAR(menucont), menulabel); + gtk_widget_show(menulabel); + + /*-- Create About submenu --*/ + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menucont); + + /*-- Create About menu item under About submenu --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("_About"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_a, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + g_signal_connect(GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_show_about), NULL); + gtk_widget_show (menuitem); + + /*-- Create Help menu item under About submenu --*/ + menuitem = gtk_menu_item_new_with_mnemonic ("_Help"); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_h, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + // g_signal_connect(GTK_OBJECT (menuitem), "activate", G_CALLBACK (gx_show_about), NULL); + gtk_widget_show (menuitem); + + /*-- Create menu item to control tooltip display --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("Show _Tooltips"); + gtk_widget_show (menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + SwitchParameter *p = new SwitchParameter("system.show_tooltips"); + fShowTooltips.init(GTK_CHECK_MENU_ITEM(menuitem), p); + p->changed.connect(ptr_fun(set_tooltips)); + + /*---------------- End About menu declarations ----------------*/ +} + +/*---------------- Jack Server Menu ----------------*/ +void GxMainInterface::addJackServerMenu() +{ + GtkWidget* menulabel; // menu label + GtkWidget* menucont; // menu container + GtkWidget* menuitem; // menu item + GSList * group = NULL; + + menucont = fMenuList["Engine"]; + + /*-- Create Jack Connection toggle button --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("Jack Server _Connection "); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_c, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_jack::gx_jack_connection), NULL); + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + + gtk_widget_show (menuitem); + fJackConnectItem = menuitem; + + /*-- create Jack Ports menu item --*/ + menuitem = gtk_check_menu_item_new_with_mnemonic ("Jack _Ports "); + gtk_widget_add_accelerator(menuitem, "activate", fAccelGroup, + GDK_p, GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (PortMapWindow::toggle), menuitem); + gtk_menu_shell_append(GTK_MENU_SHELL(menuh), menuitem); + gtk_widget_show (menuitem); + + /*-- Create Latency submenu under Jack Server submenu --*/ + menulabel = gtk_menu_item_new_with_mnemonic ("_Latency"); + gtk_menu_append (GTK_MENU(menucont), menulabel); + gtk_widget_show(menulabel); + + menucont = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menulabel), menucont); + + /*-- Create menu item under Latency submenu --*/ + gchar buf_size[8]; + const int min_pow = 5; // 2**5 = 32 + const int max_pow = 13; // 2**13 = 8192 + group = NULL; + + for (int i = min_pow; i <= max_pow; i++) + { + int jack_buffer_size = (int)pow(2.,i); + (void)snprintf(buf_size, 5, "%d", jack_buffer_size); + menuitem = gtk_radio_menu_item_new_with_label (group, buf_size); + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem)); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem), FALSE); + + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (gx_jack::gx_set_jack_buffer_size), + GINT_TO_POINTER(jack_buffer_size)); + + // display actual buffer size as default + gtk_menu_shell_append(GTK_MENU_SHELL(menucont), menuitem); + gtk_widget_show (menuitem); + + fJackLatencyItem[i-min_pow] = menuitem; + } +} + +//---- show main GUI +void GxMainInterface::show() +{ +#ifndef NDEBUG + ui_thread = pthread_self(); +#endif + assert(fTop == 0); + gx_init_pixmaps(); + fInitialized = true; + + if (gx_jack::client) { + // refresh some GUI stuff + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(fJackConnectItem), TRUE); + + GtkWidget* wd = getJackLatencyItem(gx_jack::jack_bs); + if (wd) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wd), TRUE); + + //string window_name = "guitarix"; FIXME is set by recall settings + //gtk_window_set_title (GTK_WINDOW (fWindow), window_name.c_str()); + + } else { + gtk_widget_hide(gx_gui::gx_jackd_on_image); + gtk_widget_show(gx_gui::gx_jackd_off_image); + } + + gtk_widget_show (fBox[0]); + gtk_widget_show (fWindow); + gx_jconv::gx_setting_jconv_dialog_gui(NULL,NULL); +} + +//---- show main GUI thread and more +void GxMainInterface::run() +{ + //----- set the state for the latency change warning widget + gx_engine::set_latency_warning_change(); + + //----- set the last used skin when no cmd is given + int skin_index = gx_current_skin; + if (no_opt_skin == 1) + skin_index = gx_engine::audio.fskin; + + gx_set_skin_change(skin_index); + gx_update_skin_menu_item(skin_index); + + /* timeout in milliseconds */ + g_threads[0] = g_timeout_add(40, gx_update_all_gui, 0); + // Note: meter display timeout is a global var in gx_gui namespace + g_threads[1] = g_timeout_add(meter_display_timeout, gx_refresh_meter_level, 0); + + GError* err = NULL; + // -------------- start helper thread for ladi signal USR1 ------------ + if (g_thread_create(gx_signal_helper_thread, NULL, FALSE, &err) == NULL) { + gx_print_fatal("system startup", string("Thread create failed (signal): ") + err->message); + g_error_free(err); + return; + } + + // -------------- start helper thread for midi control ------------ + sem_init (&program_change_sem, 0, 0); + + if (g_thread_create(gx_program_change_helper_thread, NULL, FALSE, &err) == NULL) { + gx_print_fatal("system startup", string("Thread create failed (midi): ") + err->message); + g_error_free(err); + return; + } + + gtk_main(); + + stop(); +} + +} /* end of gx_gui namespace */ diff --git a/src/gx_main_midi.cc b/src/gx_main_midi.cc new file mode 100644 index 0000000..88c01d3 --- /dev/null +++ b/src/gx_main_midi.cc @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 file is part of the guitarix GUI main class + * + * ---------------------------------------------------------------------------- + */ + + +/**************************************************************** + ** MidiControllerTable + */ + +class MidiControllerTable: public sigc::trackable +{ +private: + enum {RESPONSE_DELETE_SELECTED}; + static GtkWidget *window; // there can only be 1 window + GtkToggleButton *togglebutton; + GtkTreeSelection *selection; + GtkListStore *store; + GtkCheckMenuItem *menuitem; + static void response_cb(GtkWidget *widget, gint response_id, gpointer data); + static void edited_cb(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer data); + static void destroy_cb(GtkWidget*, gpointer data); + static void toggleButtonSetSwitch(GtkWidget *w, gpointer data); + void set(bool); + void load(); + MidiControllerTable(GtkCheckMenuItem *item); + ~MidiControllerTable(); +public: + static void toggle(GtkWidget* widget, gpointer data); +}; + +GtkWidget *MidiControllerTable::window = 0; + +void MidiControllerTable::response_cb(GtkWidget *widget, gint response_id, gpointer data) +{ + MidiControllerTable& m = *(MidiControllerTable*)data; + if (response_id == RESPONSE_DELETE_SELECTED) { + GtkTreeModel *model; + GList *list = gtk_tree_selection_get_selected_rows(m.selection, &model); + gtk_tree_selection_unselect_all(m.selection); + for (GList *p = g_list_last(list); p; p = g_list_previous(p)) { + GtkTreeIter iter; + gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, (GtkTreePath*)p->data); + const char* id; + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 7, &id, -1); + controller_map.deleteParameter(parameter_map[id], true); + gtk_tree_path_free((GtkTreePath*)p->data); + } + g_list_free (list); + m.load(); + return; + } + gtk_check_menu_item_set_active(m.menuitem, FALSE); +} + +void MidiControllerTable::destroy_cb(GtkWidget*, gpointer data) +{ + delete (MidiControllerTable*)data; +} + +void MidiControllerTable::edited_cb( + GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer data) +{ + GtkListStore *store = GTK_LIST_STORE(data); + GtkTreeIter iter; + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path); + int ctrl; + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &ctrl, -1); + midi_std_ctr.replace(ctrl, new_text); + bool valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); + const char *name = midi_std_ctr[ctrl].c_str(); + while (valid) { + int n; + gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 0, &n, -1); + if (n == ctrl) { + gtk_list_store_set(store, &iter, 1, name, -1); + } + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter); + } +} + +void MidiControllerTable::toggleButtonSetSwitch(GtkWidget *w, gpointer data) +{ + SwitchParameter *p = (SwitchParameter*)data; + p->set(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))); +} + +void MidiControllerTable::set(bool v) +{ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(togglebutton), v); +} + +void MidiControllerTable::load() +{ + GtkTreeIter iter; + gtk_list_store_clear(store); + for (int i = 0; i < controller_map.size(); i++) { + midi_controller_list& cl = controller_map[i]; + for (midi_controller_list::iterator j = cl.begin(); j != cl.end(); j++) { + Parameter& p = j->getParameter(); + string low, up; + const char *tp; + float step = p.getStepAsFloat(); + if (p.getControlType() == Parameter::Continuous) { + tp = "Scale"; + low = fformat(j->lower(), step); + up = fformat(j->upper(), step); + } else if (p.getControlType() == Parameter::Enum) { + tp = "Select"; + low = fformat(j->lower(), step); + up = fformat(j->upper(), step); + } else if (p.getControlType() == Parameter::Switch) { + tp = "Switch"; + low = up = ""; + } else { + tp = "??"; + assert(false); + } + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, + 0, i, + 1, midi_std_ctr[i].c_str(), + 2, p.group().c_str(), + 3, p.name().c_str(), + 4, tp, + 5, low.c_str(), + 6, up.c_str(), + 7, p.id().c_str(), + -1); + } + } +} + +void MidiControllerTable::toggle(GtkWidget* widget, gpointer data) +{ + if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(data))) { + if (window) { + gtk_widget_destroy(window); + } + } else { + if (!window) { + new MidiControllerTable(GTK_CHECK_MENU_ITEM(data)); + } + } +} + +MidiControllerTable::~MidiControllerTable() +{ + window = NULL; + gtk_widget_unref(GTK_WIDGET(menuitem)); +} + +MidiControllerTable::MidiControllerTable(GtkCheckMenuItem *item) +{ + menuitem = item; + gtk_widget_ref(GTK_WIDGET(item)); + + GtkBuilder * builder = gtk_builder_new(); + window = load_toplevel(builder, "midi.glade", "MidiControllerTable"); + store = GTK_LIST_STORE(gtk_builder_get_object(builder, "liststore1")); + togglebutton = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "save_controller")); + + SwitchParameter& param = parameter_map["system.midi_in_preset"].getSwitch(); + gtk_toggle_button_set_active(togglebutton, param.get()); + param.changed.connect(sigc::mem_fun(*this, &MidiControllerTable::set)); + g_signal_connect(GTK_OBJECT(togglebutton), "toggled", + G_CALLBACK(toggleButtonSetSwitch), (gpointer)¶m); + selection = gtk_tree_view_get_selection( + GTK_TREE_VIEW(gtk_builder_get_object(builder, "treeview1"))); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); + + load(); + + g_signal_connect(window, "destroy", G_CALLBACK(destroy_cb), this); + g_signal_connect(window, "response", G_CALLBACK(response_cb), this); + g_signal_connect(G_OBJECT(gtk_builder_get_object(builder, "cellrenderertext2")), + "edited", G_CALLBACK(edited_cb), store); + + gtk_window_add_accel_group(GTK_WINDOW(window), + GxMainInterface::instance()->fAccelGroup); + + gtk_widget_show(window); + g_object_unref(G_OBJECT(builder)); + controller_map.changed.connect(sigc::mem_fun(*this, &MidiControllerTable::load)); +} + + +/***************************************************************** + ** Midi Control + */ + +class MidiConnect +{ +private: + enum { RESPONSE_DELETE = 1 }; + Parameter ¶m; + GtkAdjustment* adj_lower; + GtkAdjustment* adj_upper; + GtkWidget* dialog; + GtkWidget* entry_new; + GtkWidget* label_desc; + int current_control; + static string ctr_desc(int ctr); + static const char *ctl_to_str(int n); +public: + MidiConnect(GdkEventButton *event, Parameter& param); + static void midi_response_cb(GtkWidget *widget, gint response_id, gpointer data); + static void midi_destroy_cb(GtkWidget *widget, gpointer data); + static gboolean check_midi_cb(gpointer); + static void changed_text_handler (GtkEditable *entry, gpointer data); +}; + +string MidiConnect::ctr_desc(int ctr) +{ + string p = midi_std_ctr[ctr]; + if (p.empty()) + return p; + return "(" + p + ")"; +} + + +void MidiConnect::midi_response_cb(GtkWidget *widget, gint response_id, gpointer data) +{ + MidiConnect* m = (MidiConnect*)data; + switch (response_id) { + case GTK_RESPONSE_OK: + if (m->param.getControlType() == Parameter::Continuous || + m->param.getControlType() == Parameter::Enum) { + assert(m->adj_lower); + assert(m->adj_upper); + float lower = gtk_adjustment_get_value(m->adj_lower); + float upper = gtk_adjustment_get_value(m->adj_upper); + controller_map.modifyCurrent(m->param, lower, upper); + } else { + controller_map.modifyCurrent(m->param, 0, 0); + } + break; + case RESPONSE_DELETE: + controller_map.deleteParameter(m->param); + break; + } + gtk_widget_destroy(m->dialog); +} + +void MidiConnect::midi_destroy_cb(GtkWidget *widget, gpointer data) +{ + MidiConnect *m = (MidiConnect*)data; + controller_map.set_config_mode(false); + delete m; +} + +const char* MidiConnect::ctl_to_str(int n) +{ + static char buf[12]; + if (n < 0) + strcpy(buf, "---"); + else + snprintf(buf, sizeof(buf), "%3d", n); + return buf; +} + +gboolean MidiConnect::check_midi_cb(gpointer data) +{ + MidiConnect *m = (MidiConnect*)data; + if (!controller_map.get_config_mode()) + return FALSE; + int ctl = controller_map.get_current_control(); + if (m->current_control == ctl) + return TRUE; + m->current_control = ctl; + gtk_entry_set_text(GTK_ENTRY(m->entry_new), ctl_to_str(ctl)); + return TRUE; +} + +void MidiConnect::changed_text_handler (GtkEditable *editable, gpointer data) +{ + MidiConnect *m = (MidiConnect*)data; + gchar *p = gtk_editable_get_chars(editable, 0, -1); + ostringstream buf; + for (const char *q = p; *q; q++) { + if (isdigit(*q)) { + buf << *q; + } + } + string str = buf.str(); + int n = -1; + if (!str.empty()) { + istringstream i(buf.str()); + i >> n; + if (n > 127) { + n = 127; + } + ostringstream b; + b << n; + str = b.str().substr(0,3); + } + // prevent infinite loop because after it has changed the text + // the handler will be called again (and make sure the text + // tranformation in this handler is idempotent!) + if (str == p) { + if (str.empty()) { + gtk_dialog_set_response_sensitive(GTK_DIALOG(m->dialog), GTK_RESPONSE_OK, FALSE); + gtk_dialog_set_default_response(GTK_DIALOG(m->dialog), GTK_RESPONSE_CANCEL); + } else { + gtk_dialog_set_response_sensitive(GTK_DIALOG(m->dialog), GTK_RESPONSE_OK, TRUE); + gtk_dialog_set_default_response(GTK_DIALOG(m->dialog), GTK_RESPONSE_OK); + } + gtk_label_set_text(GTK_LABEL(m->label_desc), ctr_desc(n).c_str()); + controller_map.set_current_control(n); + m->current_control = n; + return; + } + gtk_editable_delete_text(editable, 0, -1); + gint position = 0; + gtk_editable_insert_text(editable, str.c_str(), str.size(), &position); +} + + +MidiConnect::MidiConnect(GdkEventButton *event, Parameter ¶m): + param(param), + current_control(-1) +{ + GtkBuilder * builder = gtk_builder_new(); + dialog = load_toplevel(builder, "midi.glade", "MidiConnect"); + GtkWidget *zn = GTK_WIDGET(gtk_builder_get_object(builder, "zone_name")); + GtkStyle *style = gtk_widget_get_style(zn); + pango_font_description_set_size(style->font_desc, 12*PANGO_SCALE); + pango_font_description_set_weight(style->font_desc, PANGO_WEIGHT_BOLD); + gtk_widget_modify_font(zn, style->font_desc); + gtk_label_set_text(GTK_LABEL(zn), (param.group() + ": " + param.name()).c_str()); + const MidiController *pctrl; + int nctl = controller_map.param2controller(param, &pctrl); + if (param.getControlType() == Parameter::Continuous || + param.getControlType() == Parameter::Enum) { + float lower = param.getLowerAsFloat(); + float upper = param.getUpperAsFloat(); + float step = param.getStepAsFloat(); + GtkSpinButton *spinner; + adj_lower = GTK_ADJUSTMENT(gtk_adjustment_new(lower, lower, upper, step, 10*step, 0)); + spinner = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "lower")); + float climb_rate = 0.0; + gtk_spin_button_configure(spinner, adj_lower, climb_rate, precision(step)); + adj_upper = GTK_ADJUSTMENT(gtk_adjustment_new(upper, lower, upper, step, 10*step, 0)); + spinner = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "upper")); + gtk_spin_button_configure(spinner, adj_upper, climb_rate, precision(step)); + if (nctl != -1) { + gtk_adjustment_set_value(adj_lower, pctrl->lower()); + gtk_adjustment_set_value(adj_upper, pctrl->upper()); + } + } else { + adj_lower = adj_upper = 0; + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(builder, "range_label"))); + gtk_widget_hide(GTK_WIDGET(gtk_builder_get_object(builder, "range_box"))); + } + entry_new = GTK_WIDGET(gtk_builder_get_object(builder, "new")); + label_desc = GTK_WIDGET(gtk_builder_get_object(builder, "new_desc")); + g_signal_connect(dialog, "response", G_CALLBACK(midi_response_cb), this); + g_signal_connect(dialog, "destroy", G_CALLBACK(midi_destroy_cb), this); + g_signal_connect(entry_new, "changed", G_CALLBACK(changed_text_handler), this); + if (nctl == -1) { + gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), RESPONSE_DELETE, FALSE); + gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, FALSE); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL); + } + controller_map.set_config_mode(true, nctl); + check_midi_cb(this); + gtk_widget_show(dialog); + g_timeout_add(40, check_midi_cb, this); + g_object_unref(G_OBJECT(builder)); + return; +} + +gboolean button_press_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) +{ + if (event->button != 2) + return FALSE; + if (controller_map.get_config_mode()) + return TRUE; + new MidiConnect(event, *(Parameter*)data); + return TRUE; +} diff --git a/src/gx_paramtable.cpp b/src/gx_paramtable.cpp new file mode 100644 index 0000000..526d9b0 --- /dev/null +++ b/src/gx_paramtable.cpp @@ -0,0 +1,1024 @@ +/* + * Copyright (C) 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * --------------------------------------------------------------------------- + * + * parameter and midi data + * + * ---------------------------------------------------------------------------- + */ + +#include +#include "guitarix.h" + +namespace gx_gui +{ + +/**************************************************************** + ** Global Variables + */ + +/* Midi */ +MidiStandardControllers midi_std_ctr; // map ctrl num -> standard name +MidiControllerList controller_map; // map ctrl num -> controlled parameters + +/* Parameters */ +ParamMap parameter_map; // map id -> parameter, zone -> parameter + + +/**************************************************************** + ** Midi + */ + +static struct midi_std_init { + int ctrl; + const char *name; +} midi_std_itab[] = { + { 0, "Bank Select MSB"}, + { 1, "Modulation MSB"}, + { 2, "Breath Contoller"}, + + { 4, "Foot Controller MSB"}, + { 5, "Portamento Time MSB"}, + { 6, "Data Entry MSB"}, + { 7, "Main Volume"}, + { 8, "Balance"}, + + {10, "Pan"}, + {11, "Expression"}, + {12, "Effect Control 1"}, + {13, "Effect Control 2"}, + + {32, "Bank Select LSB"}, + + {64, "Sustain"}, + {65, "Portamento"}, + {66, "Sostenuto"}, + {67, "Soft Pedal"}, + {68, "Legato Footswitch"}, + {69, "Hold 2"}, + {70, "Sound Contr. 1"}, // default: Sound Variation + {71, "Sound Contr. 2"}, // default: Timbre/Harmonic Content + {72, "Sound Contr. 3"}, // default: Release Time + {73, "Sound Contr. 4"}, // default: Attack Time + {74, "Sound Contr. 5"}, // default: Brightness + {75, "Sound Contr. 6"}, + {76, "Sound Contr. 7"}, + {77, "Sound Contr. 8"}, + {78, "Sound Contr. 9"}, + {79, "Sound Contr. 10"}, + + {84, "Portamento Control"}, + + {91, "Eff. 1 Depth"}, + {92, "Eff. 2 Depth"}, + {93, "Eff. 3 Depth"}, + {94, "Eff. 4 Depth"}, + {95, "Eff. 5 Depth"}, + {96, "Data Inc"}, + {97, "Data Dec"}, + {98, "NRPN LSB"}, + {99, "NRPN MSB"}, + {100, "RPN LSB"}, + {101, "RPN MSB"}, + + {120, "All Sounds Off"}, + {121, "Controller Reset"}, + {122, "Local Control"}, + {123, "All Notes Off"}, + {124, "Omni Off"}, + {125, "Omni On"}, + {126, "Mono On (Poly Off)"}, + {127, "Poly On (Mono Off)"}, +}; + +MidiStandardControllers::MidiStandardControllers() +{ + for (unsigned int i = 0; i < sizeof(midi_std_itab)/sizeof(midi_std_itab[0]); i++) { + m.insert(pair(midi_std_itab[i].ctrl, modstring(midi_std_itab[i].name))); + } +} + +void MidiStandardControllers::replace(int ctr, string name) +{ + map::iterator i = m.find(ctr); + if (name.empty()) { + if (i != m.end()) { + if (i->second.modified) { + if (i->second.std) { + i->second.name = m[ctr].std; + m[ctr].modified = false; + } else { + m.erase(i); + } + } + } + } else { + if (i == m.end()) { + m[ctr] = modstring(name, true, 0); + } else { + i->second.modified = true; + i->second.name = name; + } + } +} + +void MidiStandardControllers::writeJSON(gx_system::JsonWriter& jw) const +{ + jw.begin_object(true); + for (map::const_iterator i = m.begin(); i != m.end(); i++) { + if (i->second.modified) { + ostringstream ostr; + ostr << i->first; + jw.write_key(ostr.str()); + jw.write(i->second.name, true); + } + } + jw.end_object(true); +} + +void MidiStandardControllers::readJSON(gx_system::JsonParser& jp) +{ + jp.next(gx_system::JsonParser::begin_object); + while (jp.peek() == gx_system::JsonParser::value_key) { + jp.next(); + istringstream istr(jp.current_value()); + int ctl; + istr >> ctl; + if (istr.fail()) { + throw gx_system::JsonException("midi standard controllers: number expected"); + } + jp.next(); + replace(ctl, jp.current_value()); + } + jp.next(gx_system::JsonParser::end_object); +} + +void MidiController::writeJSON(gx_system::JsonWriter& jw) const +{ + jw.begin_array(); + jw.write(param.id()); + if (param.getControlType() == Parameter::Continuous || + param.getControlType() == Parameter::Enum) { + jw.write(_lower); + jw.write(_upper); + } else { + assert(param.getControlType() == Parameter::Switch); + } + jw.end_array(); +} + +MidiController *MidiController::readJSON(gx_system::JsonParser& jp) +{ + jp.next(gx_system::JsonParser::begin_array); + jp.next(gx_system::JsonParser::value_string); + string id = jp.current_value(); + if (!parameter_map.hasId(id)) { + gx_system::gx_print_warning("Midi controller settings", + "unknown parameter: " + id); + while (jp.next() != gx_system::JsonParser::end_array); + return 0; + } + Parameter& param = parameter_map[id]; + float lower = 0, upper = 0; + bool bad = false; + bool chg = false; + if (param.getControlType() == Parameter::Continuous || + param.getControlType() == Parameter::Enum) { + if (jp.peek() != gx_system::JsonParser::end_array) { + float pmin, pmax; + if (param.hasRange()) { + pmin = param.getLowerAsFloat(); + pmax = param.getUpperAsFloat(); + } else { + bad = true; + pmin = pmax = 0; + } + jp.next(gx_system::JsonParser::value_number); + lower = jp.current_value_float(); + jp.next(gx_system::JsonParser::value_number); + upper = jp.current_value_float(); + if (lower > pmax) { + lower = pmax; + chg = true; + } else if (lower < pmin) { + lower = pmin; + chg = true; + } + if (upper > pmax) { + upper = pmax; + chg = true; + } else if (upper < pmin) { + upper = pmin; + chg = true; + } + } else { + bad = true; + } + } else { + if (param.getControlType() != Parameter::Switch) { + bad = true; + } + } + while (jp.next() != gx_system::JsonParser::end_array); // be tolerant + if (bad) { + gx_system::gx_print_warning( + "recall MIDI state", + "invalid format, Parameter skipped: " + id); + return 0; + } + if (chg) { + gx_system::gx_print_warning( + "recall MIDI state", + "Parameter range outside bounds, changed: " + id); + } + return new MidiController(param, lower, upper); +} + +MidiControllerList::MidiControllerList(): + map(controller_array_size), + midi_config_mode(false), + last_midi_control(-1) +{ +} + +void MidiControllerList::set_config_mode(bool mode, int ctl) +{ + assert(mode != midi_config_mode); + if (mode) + last_midi_control = ctl; + midi_config_mode = mode; +} + +int MidiControllerList::param2controller(Parameter& param, const MidiController** p) +{ + for (controller_array::size_type n = 0; n < map.size(); n++) { + const midi_controller_list& cl = map[n]; + for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); i++) { + if (i->hasParameter(param)) { + if (p) { + *p = &(*i); + } + return n; + } + } + } + return -1; +} + +void MidiControllerList::deleteParameter(Parameter& p, bool quiet) +{ + bool mode = get_config_mode(); + if (!mode) { + set_config_mode(true); // keep rt thread away from table + } + bool found = false; + for (controller_array::iterator pctr = map.begin(); pctr != map.end(); pctr++) { + for (midi_controller_list::iterator i = pctr->begin(); i != pctr->end(); i++) { + if (i->hasParameter(p)) { + pctr->erase(i); + found = true; + break; + } + } + } + if (found && !quiet) { + changed(); + } + if (!mode) { + set_config_mode(false); + } +} + +void MidiControllerList::modifyCurrent(Parameter ¶m, + float lower, float upper) +{ + assert(midi_config_mode == true); // keep rt thread away from table + // maximal one controller for a zone allowed + deleteParameter(param); + if (last_midi_control == -1) + return; + // add zone to controller + map[last_midi_control].push_front(MidiController(param, lower, upper)); + changed(); +} + +void MidiControllerList::set(int ctr, int val) +{ + if (midi_config_mode) + { + last_midi_control = ctr; + last_midi_control_value = val; + } + else { + midi_controller_list& ctr_list = map[ctr]; + for (midi_controller_list::iterator i = ctr_list.begin(); i != ctr_list.end(); i++) + i->set(val); + } +} + +void MidiControllerList::writeJSON(gx_system::JsonWriter& w) +{ + w.begin_array(true); + for (unsigned int n = 0; n < map.size(); n++) + { + const midi_controller_list& cl = map[n]; + if (cl.empty()) + continue; + w.write(n); + w.begin_array(); + for (midi_controller_list::const_iterator i = cl.begin(); i != cl.end(); i++) + i->writeJSON(w); + w.end_array(true); + } + w.newline(); + w.end_array(true); +} + +void MidiControllerList::readJSON(gx_system::JsonParser& jp, controller_array& m) +{ + jp.next(gx_system::JsonParser::begin_array); + while (jp.peek() != gx_system::JsonParser::end_array) { + jp.next(gx_system::JsonParser::value_number); + midi_controller_list& l = m[jp.current_value_int()]; + jp.next(gx_system::JsonParser::begin_array); + while (jp.peek() != gx_system::JsonParser::end_array) { + MidiController *p = MidiController::readJSON(jp); + if (p) { + l.push_front(*p); + } + } + jp.next(gx_system::JsonParser::end_array); + } + jp.next(gx_system::JsonParser::end_array); +} + +void MidiControllerList::set_controller_array(const controller_array& m) +{ + bool mode = get_config_mode(); + if (!mode) { + set_config_mode(true); // keep rt thread away from table + } + map = m; + if (!mode) { + set_config_mode(false); + } + changed(); +} + +void MidiControllerList::remove_controlled_parameters(paramlist& plist, const controller_array *new_m) +{ + std::set pset; + for (unsigned int i = 0; i < map.size(); i++) { + midi_controller_list& ctr = map[i]; + for (midi_controller_list::iterator j = ctr.begin(); j != ctr.end(); j++) { + if (new_m) { + const midi_controller_list& ctr_new = (*new_m)[i]; + for (midi_controller_list::const_iterator jn = ctr_new.begin(); jn != ctr_new.end(); jn++) { + if (j->getParameter() == jn->getParameter()) { + pset.insert(&j->getParameter()); + break; + } + } + } else { + pset.insert(&j->getParameter()); + } + } + } + for (paramlist::iterator n = plist.begin(); n != plist.end(); ) { + paramlist::iterator n1 = n++; + if (pset.find(*n1) != pset.end()) { + plist.erase(n1); + } + } +} + +/**************************************************************** + ** Parameter Groups + */ + +class ParameterGroups +{ +private: + map groups; + +#ifndef NDEBUG + map used; + + void group_exists(string id) + { + if (groups.find(id) == groups.end()) { + gx_system::gx_print_error("Debug Check", "Group does not exist: " + id); + } else { + used[id] = true; + } + } + void group_is_new(string id) + { + if (groups.find(id) != groups.end()) { + gx_system::gx_print_error("Debug Check", "Group already exists: " + id); + } + } + + ~ParameterGroups() + { + for (map::iterator i = used.begin(); i != used.end(); i++) { + if (!i->second) { + gx_system::gx_print_error("Debug Check", "Group not used: " + i->first); + } + } + } + friend string param_group(string id, bool nowarn); +#endif + +public: + ParameterGroups(); + + inline string get(string id) { return groups[id]; } + inline string operator[](string id) + { + debug_check(group_exists, id); return groups[id]; + } + inline void insert(string id, string group) + { + debug_check(group_is_new, id); + groups.insert(pair(id, group)); + } +}; + +ParameterGroups::ParameterGroups() +{ + insert("jconv","Convolver"); + insert("eq", "EQ"); + insert("eqs", "Scaleable EQ"); + insert("eqt", "Scwitch EQ"); + insert("amp","Amplifier"); + insert("amp2","Amplifier2"); + insert("amp2.preamp","Preamp"); + insert("amp2.stage1","Tube1"); + insert("amp2.stage2","Tube2"); + insert("stage3","Amplifier2"); + insert("stage3.gain3","Tube3"); + insert("shaper","Shaper"); + insert("noise_gate","Noise Gate"); + insert("anti_aliase","Anti Alias"); + insert("amp.oversample","Oversampling"); + insert("amp.bass_boost","Bass Boost"); + insert("convolve","Amp Model"); + insert("preamp","Pre-Amp"); + insert("drive","Drive"); + insert("tube","Tube 1"); + insert("tube.vibrato","Tube 1 Vibrato"); + insert("tube2","Tube 2"); + insert("tube3","Tube 3"); + insert("amp.tonestack","Tonestack"); + insert("compressor","Compressor"); + insert("overdrive","Overdrive"); + insert("distortion","Multi Band Distortion"); + insert("distortion.low_highpass","Distortion low/highpass"); + insert("distortion.low_highcutoff","Distortion low/highcutoff"); + insert("distortion.resonator","Distortion resonator"); + insert("distortion1","Single Band Distortion"); + insert("distortion1.low_highpass","Distortion low/highpass"); + insert("distortion1.low_highcutoff","Distortion low/highcutoff"); + insert("distortion1.resonator","Distortion resonator"); + insert("distortiont","Switch Distortion"); + insert("freeverb","Freeverb"); + insert("IR","ImpulseResponse"); + insert("crybaby","Crybaby"); + insert("echo","Echo"); + insert("delay","Delay"); + insert("chorus","Chorus"); + insert("MultiBandFilter","Multiband Filter"); + insert("moog","Moog Filter"); + insert("biquad","BiQuad Filter"); + insert("flanger","Flanger"); + insert("SampleLooper","Sample Looper"); + insert("cab","Cab-ImpResp"); + insert("midi_out","Midi Out"); + insert("midi_out.channel_1","Midi Out 1"); + insert("midi_out.channel_2","Midi Out 2"); + insert("midi_out.channel_3","Midi Out 3"); + insert("beat_detector","Beat Detector"); + insert("ui","User Interface"); + insert("system", "System"); +} + +string param_group(string id, bool nowarn) +{ + static ParameterGroups groups = ParameterGroups(); + const string& group_id = id.substr(0, id.find_last_of(".")); + if (nowarn) { + return groups.get(group_id); + } else { + return groups[group_id]; + } +} + +/**************************************************************** + ** Parameter + */ + +static int get_upper(const char **vn) +{ + for (int n = 0; ; n++) { + if (!vn[n]) { + return n - 1; + } + } +} + +bool Parameter::hasRange() const +{ + return false; +} + +float Parameter::getStepAsFloat() const +{ + return 1; +} + +float Parameter::getLowerAsFloat() const +{ + return 0; +} + +float Parameter::getUpperAsFloat() const +{ + return 0; +} + +const char **Parameter::getValueNames() const +{ + return 0; +} + + +/* FloatParameter */ + +void *FloatParameter::zone() +{ + return &value; +} + +void FloatParameter::set(int n, int high, float llimit, float ulimit) +{ + switch (c_type) { + case Continuous: + assert(n >= 0 && n <= high); + value = llimit + ((float)(n) / (high)) * (ulimit - llimit); + break; + case Switch: + value = (2*n > high ? 1.0 : 0.0); + break; + case Enum: + value = lower + min((float)n, upper-lower); + break; + default: + assert(false); + break; + } +} + +void FloatParameter::set_std_value() +{ + value = std_value; +} + +void FloatParameter::writeJSON(gx_system::JsonWriter& jw) +{ + jw.write_key(_id.c_str()); + jw.write(value); +} + +void FloatParameter::readJSON_value(gx_system::JsonParser& jp) +{ + jp.next(gx_system::JsonParser::value_number); + json_value = jp.current_value_float(); +} + +void FloatParameter::setJSON_value() +{ + set(json_value); +} + +bool FloatParameter::hasRange() const +{ + return true; +} + +float FloatParameter::getLowerAsFloat() const +{ + return lower; +} + +float FloatParameter::getUpperAsFloat() const +{ + return upper; +} + +float FloatParameter::getStepAsFloat() const +{ + return step; +} + + +/* FloatEnumParameter */ + +FloatEnumParameter::FloatEnumParameter(string id, string name, const char** vn, bool preset, + float &v, int sv, bool ctrl, bool exp): + FloatParameter(id, name, Enum, preset, v, sv, 0, get_upper(vn), 1, ctrl, exp), + value_names(vn) +{ +} + +const char **FloatEnumParameter::getValueNames() const +{ + return value_names; +} + +void FloatEnumParameter::writeJSON(gx_system::JsonWriter& jw) +{ + jw.write_key(_id.c_str()); + jw.write(value_names[(int)round(value)]); +} + +void FloatEnumParameter::readJSON_value(gx_system::JsonParser& jp) +{ + gx_system::JsonParser::token tok = jp.next(); + if (tok == gx_system::JsonParser::value_number) { + // old version compatability + json_value = jp.current_value_int(); + return; + } + jp.check_expect(gx_system::JsonParser::value_string); + int up = round(upper); + int n = 0; + for (; n <= up; n++) { + if (jp.current_value() == value_names[n]) { + break; + } + } + if (n > up) { + gx_system::gx_print_warning( + "read parameter", (boost::format("parameter %1%: unknown enum value: %2%") + % _id % jp.current_value()).str()); + n = 0; + } + json_value = n; +} + +/* IntParameter */ + +void *IntParameter::zone() +{ + return &value; +} + +void IntParameter::set(int n, int high, float llimit, float ulimit) +{ + switch (c_type) { + case Continuous: + assert(false); // not implemented + break; + case Switch: + value = (2*n > high ? 1065353216 : 0); // FIXME float/int problem + break; + case Enum: + assert(false); // not implemented + break; + default: + assert(false); + break; + } +} + +void IntParameter::set_std_value() +{ + value = std_value; +} + +void IntParameter::writeJSON(gx_system::JsonWriter& jw) +{ + jw.write_key(_id.c_str()); + jw.write(value); +} + +void IntParameter::readJSON_value(gx_system::JsonParser& jp) +{ + jp.next(gx_system::JsonParser::value_number); + json_value = jp.current_value_int(); +} + +void IntParameter::setJSON_value() +{ + set(json_value); +} + +bool IntParameter::hasRange() const +{ + return true; +} + +float IntParameter::getLowerAsFloat() const +{ + return lower; +} + +float IntParameter::getUpperAsFloat() const +{ + return upper; +} + + +/* EnumParameter */ + +EnumParameter::EnumParameter(string id, string name, const char** vn, bool preset, + int &v, int sv, bool ctrl, bool exp): + IntParameter(id, name, Enum, preset, v, sv, 0, get_upper(vn), ctrl, exp), + value_names(vn) +{ +} + +const char **EnumParameter::getValueNames() const +{ + return value_names; +} + +void EnumParameter::writeJSON(gx_system::JsonWriter& jw) +{ + jw.write_key(_id.c_str()); + jw.write(value_names[value]); +} + +void EnumParameter::readJSON_value(gx_system::JsonParser& jp) +{ + gx_system::JsonParser::token tok = jp.next(); + if (tok == gx_system::JsonParser::value_number) { + // old version compatability + json_value = jp.current_value_int(); + return; + } + jp.check_expect(gx_system::JsonParser::value_string); + int n = 0; + for (; n <= upper; n++) { + if (jp.current_value() == value_names[n]) { + break; + } + } + if (n > upper) { + gx_system::gx_print_warning( + "read parameter", (boost::format("parameter %1%: unknown enum value: %2%") + % _id % jp.current_value()).str()); + n = 0; + } + json_value = n; +} + + +/* BoolParameter */ + +void *BoolParameter::zone() +{ + return &value; +} + +void BoolParameter::set(int n, int high, float llimit, float ulimit) +{ + switch (c_type) { + case Switch: + value = (2*n > high); + default: + assert(false); + break; + } +} + +void BoolParameter::set_std_value() +{ + value = std_value; +} + +void BoolParameter::writeJSON(gx_system::JsonWriter& jw) +{ + jw.write_key(_id.c_str()); + jw.write(value); +} + +void BoolParameter::readJSON_value(gx_system::JsonParser& jp) +{ + jp.next(gx_system::JsonParser::value_number); + json_value = jp.current_value_int(); +} + +void BoolParameter::setJSON_value() +{ + set(json_value); +} + + +/* SwitchParameter */ + +void SwitchParameter::set(bool val) +{ + if (val != value){ + value = val; + changed(value); + } +} + +void *SwitchParameter::zone() +{ + return &value; +} + +void SwitchParameter::set_std_value() +{ + set(std_value); +} + +void SwitchParameter::set(int n, int high, float llimit, float ulimit) +{ + assert(false); +} + +void SwitchParameter::writeJSON(gx_system::JsonWriter& jw) +{ + jw.write_key(_id.c_str()); + jw.write(value); +} + +void SwitchParameter::readJSON_value(gx_system::JsonParser& jp) +{ + jp.next(gx_system::JsonParser::value_number); + json_value = jp.current_value_int(); +} + +void SwitchParameter::setJSON_value() +{ + set(json_value); +} + + +/* FileParameter */ + +void FileParameter::set_path(const string& path) +{ + value = Gio::File::create_for_path(path); +} + +void FileParameter::set(const Glib::RefPtr& val) +{ + value = val; +} + +void FileParameter::set_standard(const string& filename) +{ + std_value = Gio::File::create_for_path(filename); + if (!value) { + value = std_value->dup(); + } +} + +void FileParameter::set_std_value() +{ + set(std_value->dup()); +} + +void *FileParameter::zone() +{ + return &value; +} + +void FileParameter::set(int n, int high, float llimit, float ulimit) +{ + assert(false); +} + +void FileParameter::writeJSON(gx_system::JsonWriter& jw) +{ + jw.write_key(_id.c_str()); + jw.write(get_path()); +} + +void FileParameter::readJSON_value(gx_system::JsonParser& jp) +{ + jp.next(gx_system::JsonParser::value_string); + json_value = Gio::File::create_for_path(jp.current_value()); +} + +void FileParameter::setJSON_value() +{ + set(json_value); +} + +static string get_file_id(const Glib::RefPtr& f) +{ + return f->query_info(G_FILE_ATTRIBUTE_ID_FILE)->get_attribute_string(G_FILE_ATTRIBUTE_ID_FILE); +} + +bool FileParameter::is_standard() const +{ + string id; + try { + id = get_file_id(value); + } catch (Gio::Error ex) { + return false; // FIXME check type of exception + } + return id == get_file_id(std_value); +} + +string FileParameter::get_path() +{ + return value->get_path(); +} + +string FileParameter::get_directory_path() +{ + return value->get_parent()->get_path(); +} + +string FileParameter::get_parse_name() +{ + return value->get_parse_name(); +} + +string FileParameter::get_display_name() +{ + return value->query_info(G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)->get_display_name(); +} + +void FileParameter::copy(const string& destination) +{ + value->copy(Gio::File::create_for_path(destination)); +} + +/**************************************************************** + ** Parameter Map + */ + +#ifndef NDEBUG +void ParamMap::unique_zone(Parameter* param) +{ + if (addr_map.find(param->zone()) != addr_map.end()) { + gx_system::gx_print_error("Debug Check", "zone registered twice (id: " + param->id() +")"); + } +} + +void ParamMap::unique_id(Parameter* param) +{ + if (id_map.find(param->id()) != id_map.end()) { + gx_system::gx_print_error("Debug Check", "id registered twice: " + param->id()); + } +} + +void ParamMap::check_addr(const void *p) +{ + if (!hasZone(p)) { + cerr << "zone not found: " << p << endl; + } +} +void ParamMap::check_id(string id) +{ + if (!hasId(id)) { + cerr << "string-id not found: " << id << endl; + } +} + +void ParamMap::check_p(const char *p) +{ + if (!hasId(p)) { + cerr << "char-id not found: " << p << endl; + } +} +#endif + +void ParamMap::insert(Parameter* param) +{ + debug_check(unique_zone, param); + addr_map.insert(pair(param->zone(), param)); + debug_check(unique_id, param); + id_map.insert(pair(param->id(), param)); +} + +void ParamMap::set_init_values() +{ + for (iterator i = id_map.begin(); i != id_map.end(); i++) { + i->second->set_std_value(); + } +} + +} // namespace gx_gui diff --git a/src/gx_pitch_tracker.cpp b/src/gx_pitch_tracker.cpp new file mode 100644 index 0000000..13b5d20 --- /dev/null +++ b/src/gx_pitch_tracker.cpp @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix tuner, part of gx_engine_audio.cpp ------- */ + +#include +#include +#include "guitarix.h" + +/**************************************************************** + ** Pitch Tracker + ** + ** some code and ideas taken from K4Guitune (William Spinelli) + ** + */ + +namespace gx_engine { + +const int DOWNSAMPLE = 16; // downsampling factor +const int ZERO_PADDING_FACTOR = 64; // Number of times that the FFT is zero-padded to increase frequency resolution. +const float SIGNAL_THRESHOLD_ON = 0.001; // Value of the threshold above which the processing is activated. +const float SIGNAL_THRESHOLD_OFF = 0.0009; // Value of the threshold below which the input audio signal is deactivated. +const float TRACKER_PERIOD = 0.1; // Time between frequency estimates (in seconds) + +void *PitchTracker::static_run(void *p) +{ + ((PitchTracker *)p)->run(); + return NULL; +} + +PitchTracker::PitchTracker(): + error(false), + busy(false), + tick(0), + m_pthr(0), + m_buffer(new float[MAX_FFT_SIZE]), + m_bufferIndex(0), + m_audioLevel(false), + m_fftwPlanFFT(0), + m_fftwPlanIFFT(0) +{ + const int fftw_buffer_size = MAX_FFT_SIZE * ZERO_PADDING_FACTOR; + m_fftwBufferTime = (float*)fftwf_malloc(fftw_buffer_size * sizeof(float)); + m_fftwBufferFreq = (fftwf_complex*)fftwf_malloc(fftw_buffer_size * sizeof(fftwf_complex)); + + memset(m_buffer, 0, MAX_FFT_SIZE * sizeof(float)); + memset(m_fftwBufferTime, 0, fftw_buffer_size * sizeof(float)); + memset(m_fftwBufferFreq, 0, fftw_buffer_size * sizeof(fftwf_complex)); + + sem_init(&m_trig, 0, 0); + + if (!m_buffer || !m_fftwBufferTime || !m_fftwBufferFreq) { + error = true; + } +} + + +PitchTracker::~PitchTracker() +{ + fftwf_destroy_plan(m_fftwPlanFFT); + fftwf_destroy_plan(m_fftwPlanIFFT); + fftwf_free(m_fftwBufferTime); + fftwf_free(m_fftwBufferFreq); + delete[] m_buffer; +} + + +bool PitchTracker::setParameters(int sampleRate, int fftSize) +{ + assert(fftSize <= MAX_FFT_SIZE); + + if (error) { + return false; + } + m_sampleRate = sampleRate / DOWNSAMPLE; + resamp.setup(sampleRate, m_sampleRate, 1, 16); // 16 == least quality + + if (m_fftSize != fftSize) { + m_fftSize = fftSize; + fftwf_destroy_plan(m_fftwPlanFFT); + fftwf_destroy_plan(m_fftwPlanIFFT); + m_fftwPlanFFT = fftwf_plan_dft_r2c_1d( + m_fftSize, m_fftwBufferTime, m_fftwBufferFreq, FFTW_ESTIMATE); // FFT + m_fftwPlanIFFT = fftwf_plan_dft_c2r_1d( + ZERO_PADDING_FACTOR * m_fftSize, m_fftwBufferFreq, m_fftwBufferTime, FFTW_ESTIMATE); // IFFT zero-padded + } + + if (!m_fftwPlanFFT || !m_fftwPlanIFFT) { + error = true; + return false; + } + + if (!m_pthr) { + start_thread(); + } + pt_initialized = true; + return !error; +} + +void PitchTracker::start_thread() +{ + int min, max; + pthread_attr_t attr; + struct sched_param spar; + int priority, policy; + pthread_getschedparam(jack_client_thread_id(gx_jack::client), &policy, &spar); + priority = spar.sched_priority; + min = sched_get_priority_min(policy); + max = sched_get_priority_max(policy); + priority -= 6; // zita-convoler uses 5 levels + if (priority > max) priority = max; + if (priority < min) priority = min; + spar.sched_priority = priority; + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setschedpolicy (&attr, policy); + pthread_attr_setschedparam (&attr, &spar); + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED); + //pthread_attr_setstacksize (&attr, 0x10000); + if (pthread_create (&m_pthr, &attr, static_run, (void*)this)) { + error = true; + } + pthread_attr_destroy (&attr); +} + +int PitchTracker::find_minimum() +{ + const int peakwidth = 3; + float *p = &m_fftwBufferTime[peakwidth]; + for ( ; p < &m_fftwBufferTime[ZERO_PADDING_FACTOR * m_fftSize / 2 + 1 - peakwidth]; p++) { + int i; + for (i = -peakwidth; i <= peakwidth; i++) { + if (*p > p[i]) { + break; + } + } + if (i > peakwidth) { + break; + } + } + return (int)(p - m_fftwBufferTime); +} + +int PitchTracker::find_maximum(int l) +{ + float maxAutocorr = 0.0; + int maxAutocorrIndex = 0; + while ( l < ZERO_PADDING_FACTOR * m_fftSize / 2 + 1) { + if (m_fftwBufferTime[l] > maxAutocorr) { + maxAutocorr = m_fftwBufferTime[l]; + maxAutocorrIndex = l; + } + ++l; + } + if (maxAutocorr == 0.0) { + return -1; + } + return maxAutocorrIndex; +} + +float show_level(int n, float *buf) +{ + float sum = 0.0; + for (int k = 0; k < n; ++k) { + sum += fabs(buf[k]); + } + return sum; +} + +void PitchTracker::add(int count, float* input) +{ + if (error) { + return; + } + resamp.inp_count = count; + resamp.inp_data = input; + for (;;) { + resamp.out_data = &m_buffer[m_bufferIndex]; + int n = MAX_FFT_SIZE - m_bufferIndex; + resamp.out_count = n; + resamp.process(); + n -= resamp.out_count; // n := number of output samples + if (!n) { // all soaked up by filter + return; + } + m_bufferIndex = (m_bufferIndex + n) % MAX_FFT_SIZE; + if (resamp.inp_count == 0) { + break; + } + } + if (++tick * count >= m_sampleRate * DOWNSAMPLE * TRACKER_PERIOD) { + if (busy) { + return; + } + tick = 0; + copy(); + sem_post(&m_trig); + } +} + +void PitchTracker::copy() +{ + int start = (MAX_FFT_SIZE + m_bufferIndex - m_fftSize) % MAX_FFT_SIZE; + int end = (MAX_FFT_SIZE + m_bufferIndex) % MAX_FFT_SIZE; + int cnt = 0; + if (start >= end) { + cnt = MAX_FFT_SIZE - start; + memcpy(m_fftwBufferTime, &m_buffer[start], cnt * sizeof(float)); + start = 0; + } + memcpy(&m_fftwBufferTime[cnt], &m_buffer[start], (end - start) * sizeof(float)); +} + +void PitchTracker::run() +{ + for (;;) { + busy = false; + sem_wait(&m_trig); + busy = true; + if (error) { + continue; + } + float sum = 0.0; + for (int k = 0; k < m_fftSize; ++k) { + sum += fabs(m_fftwBufferTime[k]); + } + float threshold = (m_audioLevel ? SIGNAL_THRESHOLD_OFF : SIGNAL_THRESHOLD_ON); + m_audioLevel = (sum / m_fftSize >= threshold); + if ( m_audioLevel == false ) { + setEstimatedFrequency(0.0); + continue; + } + + /* Compute the transform of the autocorrelation given in time domain by + * k=-N + * r[t] = sum( x[k] * x[t-k] ) + * N + * or in the frequency domain (for a real signal) by + * R[f] = X[f] * X[f]' = |X[f]|^2 = Re(X[f])^2 + Im(X[f])^2 + * When computing the FFT with fftwf_plan_dft_r2c_1d there are only N/2+1 + * significant samples, so |.|^2 is computed for m_fftSize/2+1 samples only + */ + int fftRSize = m_fftSize/2 + 1; + fftwf_execute(m_fftwPlanFFT); + for (int k = 0; k < fftRSize; ++k) { + fftwf_complex& v = m_fftwBufferFreq[k]; + v[0] = v[0]*v[0] + v[1]*v[1]; + v[1] = 0.0; + } + + // pad the FFT with zeros to increase resolution in time domain after IFFT + int size_with_padding = ZERO_PADDING_FACTOR * m_fftSize - fftRSize; + memset(&m_fftwBufferFreq[fftRSize][0], 0, size_with_padding * sizeof(fftwf_complex)); + fftwf_execute(m_fftwPlanIFFT); + + // search for a minimum and then for the next maximum to get the estimated frequency + int maxAutocorrIndex = find_maximum(find_minimum()); + + // compute the frequency of the maximum considering the padding factor + if (maxAutocorrIndex >= 0) { + setEstimatedFrequency(ZERO_PADDING_FACTOR * m_sampleRate / (float)maxAutocorrIndex); + } else { + setEstimatedFrequency(0.0); + } + busy = false; + } +} + +void PitchTracker::setEstimatedFrequency(float freq) +{ + midi.fConsta4 = freq; + audio.fConsta1t = (freq == 0.0 ? 1000.0 : 12 * log2f(2.272727e-03f * freq)); +} + +PitchTracker pitch_tracker; + +} + + diff --git a/src/gx_portmap.cpp b/src/gx_portmap.cpp new file mode 100644 index 0000000..0c1ea97 --- /dev/null +++ b/src/gx_portmap.cpp @@ -0,0 +1,717 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * --------------------------------------------------------------------------- + * + * guitarix portmap window + * + * ---------------------------------------------------------------------------- + */ + +#include +#include +#include "guitarix.h" + +/**************************************************************** + ** PortMapWindow + */ + +namespace gx_gui +{ + +PortAttr guitarix_ports[] = { + //client_num, is_insert, port_name, is_input, port_type + { 0, false, "in_0", true, JACK_DEFAULT_AUDIO_TYPE }, + { 1, false, "out_0", false, JACK_DEFAULT_AUDIO_TYPE }, + { 1, false, "out_1", false, JACK_DEFAULT_AUDIO_TYPE }, + { 0, false, "midi_in_1", true, JACK_DEFAULT_MIDI_TYPE }, + { 0, false, "midi_out_1", false, JACK_DEFAULT_MIDI_TYPE }, + { 1, true, "in_0", true, JACK_DEFAULT_AUDIO_TYPE }, + { 0, true, "out_0", false, JACK_DEFAULT_AUDIO_TYPE }, +}; + +#define ALSA_PCM "alsa_pcm" // special alsa sequencer client + + +/**************************************************************** +** ClientList +** +** (helper to convert the jack port list into a sorted list with sub-lists) +*/ + +struct ClientPortList { + const char *client; + int len; + list ports; + ClientPortList(const char *p); + inline void add(const char *p) { ports.push_back(p); } + inline bool sameclient(const char *p) { return strncmp(client, p, len) == 0; } + string clientname() { return string(*ports.begin()).substr(0,len-1); } +}; + +ClientPortList::ClientPortList(const char *p) +{ + client = p; + const char *q = strchr(p, ':'); + if (q) { + len = (q - p) + 1; + if (strncmp(p, (ALSA_PCM ":"), 9) == 0) { + q = strchr(p+len, '/'); + if (q) { + len = (q - p) + 1; + } else { + len = strlen(p); + } + } + } else { // should not happen + len = strlen(p); + } +} + +struct ClientList: list +{ + static bool str_compare(const char *a, const char *b); + ClientList(const char**); + ~ClientList(); + void remove(string excl); +}; + +bool ClientList::str_compare(const char *a, const char *b) +{ + return strcmp(b, a) > 0; +} + +ClientList::ClientList(const char **ports) +{ + list l; + for (int i = 0; ports[i]; i++) { + l.push_back(ports[i]); + } + l.sort(str_compare); + if (l.empty()) { + return; + } + ClientPortList *cp = new ClientPortList(*l.begin()); + for (list::iterator j = l.begin(); j != l.end(); j++) { + if (!cp->sameclient(*j)) { + push_back(cp); + cp = new ClientPortList(*j); + } + cp->add(*j); + } + push_back(cp); +} + +ClientList::~ClientList() +{ + for (list::iterator i = begin(); i != end(); i++) { + delete *i; + } +} + +void ClientList::remove(string excl) +{ + for (list::iterator i = begin(); i != end();) { + if ((*i)->sameclient(excl.c_str())) { + list::iterator n = i++; + delete *n; + erase(n); + break; + } else { + i++; + } + } +} + + +/**************************************************************** +** PortMapWindow +*/ + +GtkWidget *PortMapWindow::window = 0; +PortMapWindow *PortMapWindow::instance = 0; + +/* +** port registration / removal +*/ + +static string client_from_port(const string& port) +{ + size_t pos = port.find_first_of(':'); + if (pos == string::npos) { + return port; + } + string s = port.substr(0, pos); + if (s.compare(ALSA_PCM) != 0) { + return s; + } + size_t p2 = port.find_first_of('/', 9); + if (p2 == string::npos) { + return port; + } + return port.substr(0, p2); +} + +static bool compare_client(const string& name, const char *p) +{ + if (name.compare(0, name.size(), p, name.size()) == 0) { + if (p[name.size()] == ':' || p[name.size()] == '\0') { + return true; + } + } + if (strncmp(p, (ALSA_PCM ":"), 9) == 0) { + p += 9; + if (name.compare(0, name.size(), p, name.size()) == 0) { + if (p[name.size()] == '/' || p[name.size()] == '\0') { + return true; + } + } + } + return false; +} + +static bool compare_port(const string& name, const char *p) +{ + return name.compare(p) == 0; +} + +bool PortMapWindow::walk_remove(GtkTreeStore *ts, bool (*compare)(const string&, const char*), string data) +{ + bool changed = false; + GtkTreeIter p_iter; + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ts), &p_iter)) { + return changed; + } + while (true) { + gboolean is_port; + gtk_tree_model_get(GTK_TREE_MODEL(ts), &p_iter, 2, &is_port, -1); + if (is_port) { + gchararray p; + gtk_tree_model_get(GTK_TREE_MODEL(ts), &p_iter, 0, &p, -1); + if (compare(data, p)) { + changed = true; + if (!gtk_tree_store_remove(ts, &p_iter)) { + break; + } + continue; + } + } else { + GtkTreeIter c_iter; + gtk_tree_model_iter_children(GTK_TREE_MODEL(ts), &c_iter, &p_iter); + while (true) { + gchararray p; + gtk_tree_model_get(GTK_TREE_MODEL(ts), &c_iter, 0, &p, -1); + if (compare(data, p)) { + changed = true; + if (!gtk_tree_store_remove(ts, &c_iter)) { + break; + } + continue; + } + if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(ts), &c_iter)) { + break; + } + } + if (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(ts), &p_iter)) { + changed = true; + if (!gtk_tree_store_remove(ts, &p_iter)) { + break; + } + continue; + } + } + if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(ts), &p_iter)) { + break; + } + } + return changed; +} + +void PortMapWindow::walk_insert(GtkTreeStore *ts, string name) +{ + GtkTreeIter p_iter; // clients and ports on top level + if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ts), &p_iter)) { + while (true) { + gboolean is_port; + gchararray p; + gtk_tree_model_get(GTK_TREE_MODEL(ts), &p_iter, 0, &p, 2, &is_port, -1); + if (name.compare(p) == 0) { + return; + } + if (!is_port && compare_client(client_from_port(name), p)) { + GtkTreeIter c_iter; // ports of a client, 2nd level + if (gtk_tree_model_iter_children(GTK_TREE_MODEL(ts), &c_iter, &p_iter)) { + while (true) { + // if we already have the port get out + gtk_tree_model_get(GTK_TREE_MODEL(ts), &c_iter, 0, &p, -1); + if (name.compare(p) == 0) { + return; + } + if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(ts), &c_iter)) { + break; + } + } + } + gtk_tree_store_insert_with_values(ts, 0, &p_iter, 0, + 0, name.c_str(), + 1, false, + 2, true, + -1); + return; + } + if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(ts), &p_iter)) { + break; + } + } + } + gtk_tree_store_insert_with_values(ts, 0, 0, 0, + 0, name.c_str(), + 1, false, + 2, true, + -1); +} + +void PortMapWindow::port_changed(string name, const char *tp, int flags, bool reg) +{ + if (reg == 0) { + for (int i = 0; i < number_of_ports; i++) { + PortSection *p = &portsection[i]; + if (walk_remove(p->treestore, compare_port, name)) { + update_summary(p); + } + } + } else { + for (list::iterator j = excluded_clients.begin(); j != excluded_clients.end(); j++) { + if (name.compare(0, j->size(), *j) == 0) { + return; + } + } + for (int i = 0; i < number_of_ports; i++) { + PortSection *p = &portsection[i]; + if (strcmp(p->port_attr->port_type, tp) != 0) { + continue; + } + if (p->port_attr->is_input) { + if (! (flags & JackPortIsOutput)) { + continue; + } + } else { + if (! (flags & JackPortIsInput)) { + continue; + } + } + walk_insert(p->treestore, name); + } + } +} + + +/* +** port connection change +*/ + +list PortMapWindow::walk(GtkTreeStore *ts, string *port, int connect) +{ + list l; + GtkTreeIter p_iter; + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ts), &p_iter)) { + return l; + } + do { + gboolean is_port, is_connected; + gchararray p; + gtk_tree_model_get(GTK_TREE_MODEL(ts), &p_iter, 0, &p, 1, &is_connected, 2, &is_port, -1); + if (is_port) { + if (port && port->compare(p) == 0) { + is_connected = connect; + gtk_tree_store_set(ts, &p_iter, 1, is_connected, -1); + } + if (is_connected) { + l.push_back(p); + } + } else { + GtkTreeIter c_iter; + gtk_tree_model_iter_children(GTK_TREE_MODEL(ts), &c_iter, &p_iter); + do { + gchararray p; + gtk_tree_model_get(GTK_TREE_MODEL(ts), &c_iter, 0, &p, 1, &is_connected, -1); + if (port && port->compare(p) == 0) { + is_connected = connect; + gtk_tree_store_set(ts, &c_iter, 1, is_connected, -1); + } + if (is_connected) { + l.push_back(p); + } + } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(ts), &c_iter)); + } + } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(ts), &p_iter)); + return l; +} + +void PortMapWindow::update_summary(PortSection *p, string *port, bool conn) +{ + list l = walk(p->treestore, port, conn); + if (!p->expander) { + return; + } + string q; + list::iterator i = l.begin(); + if (i != l.end()) { + q = *i++; + } + for (; i != l.end(); i++) { + q += "\n" + *i; + } + gtk_label_set_text(p->label, q.c_str()); + g_idle_add(redraw_expander, p->expander); +} + +void PortMapWindow::connection_changed(string port1, string port2, bool conn) +{ + for (int i = 0; i < number_of_ports; i++) { + PortSection *p = &portsection[i]; + + string s = (p->port_attr->client_num == 0 ? gx_jack::client_name : gx_jack::client_insert_name) + + ":" + p->port_attr->port_name; + if (s.compare(port1) == 0) { + update_summary(p, &port2, conn); + } + else if (s.compare(port2) == 0) { + update_summary(p, &port1, conn); + } + } +} + + +/* +** gtk callback functions +*/ + +void PortMapWindow::on_check_resize(GtkWidget *widget, gpointer data) +{ + // cf. comment at the end of on_expander() + PortMapWindow *p = (PortMapWindow*)data; + if (p->monitored_expander_child && + !gtk_widget_get_child_visible(p->monitored_expander_child)) { + p->monitored_expander_child = 0; + gint width; + gdk_window_get_geometry(window->window, 0, 0, &width, 0, 0); + gtk_window_resize(GTK_WINDOW(window), width, 1); + } +} + +void PortMapWindow::on_expander(GtkWidget *widget, gpointer data) +{ + PortMapWindow *p = (PortMapWindow*)data; + gboolean expanded = gtk_expander_get_expanded(GTK_EXPANDER(widget)); + if (expanded) { + // close all other expanders and unset their expand child property + for (int i = 0; i < number_of_ports; i++) { + GtkWidget *w = GTK_WIDGET(p->portsection[i].expander); + if (widget != w) { + GValue v = {0}; + g_value_init(&v, G_TYPE_BOOLEAN); + g_value_set_boolean(&v, FALSE); + gtk_container_child_set_property(GTK_CONTAINER(gtk_widget_get_parent(w)), w, "expand", &v); + gtk_expander_set_expanded(GTK_EXPANDER(w), FALSE); + } + } + } + // set the expand child property of the current expander if its expanded + GValue value = {0}; + g_value_init(&value, G_TYPE_BOOLEAN); + g_value_set_boolean(&value, expanded); + gtk_container_child_set_property(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget, "expand", &value); + if (!expanded) { + // when the expander is explicitely closed (so all expanders are + // closed now) we want to shrink the portmap window with + // gtk_window_resize(). + // But GtkExpander uses a timer before the child is made + // unvisible and a resize of the window is triggered. + // So we defer resizing to the "check-resize"-signal handler + p->monitored_expander_child = gtk_bin_get_child(GTK_BIN(widget)); + } +} + +void PortMapWindow::response_cb(GtkWidget *widget, gint response_id, gpointer data) +{ + PortMapWindow& m = *(PortMapWindow*)data; + gtk_check_menu_item_set_active(m.menuitem, FALSE); +} + +void PortMapWindow::destroy_cb(GtkWidget*, gpointer data) +{ + delete (PortMapWindow*)data; +} + +void PortMapWindow::toggle(GtkWidget* widget, gpointer data) +{ + if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(data))) { + if (window) { + gtk_widget_destroy(window); + } + } else { + if (!window) { + new PortMapWindow(GTK_CHECK_MENU_ITEM(data)); + } + } +} + +gboolean PortMapWindow::redraw_expander(gpointer data) +{ + gtk_widget_queue_draw(GTK_WIDGET(data)); + return FALSE; +} + +void PortMapWindow::on_cell_toggle(GtkCellRendererToggle *widget, gchar *path, gpointer data) +{ + PortSection *p = (PortSection*)data; + + GtkTreeIter iter; + gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(p->treestore), &iter, path); + gboolean v; + const char *q1, *q2; + gtk_tree_model_get(GTK_TREE_MODEL(p->treestore), &iter, 0, &q1, 1, &v, -1); + string gcln; + jack_client_t *gcl; + if (p->port_attr->client_num == 0) { + gcl = gx_jack::client; + gcln = gx_jack::client_name; + } else { + gcl = gx_jack::client_insert; + gcln = gx_jack::client_insert_name; + } + string s = gcln + ":" + p->port_attr->port_name; + q2 = s.c_str(); + if (!p->port_attr->is_input) { + const char *sw = q1; + q1 = q2; + q2 = sw; + } + + v = !v; + int ret; + + if (v) { + ret = jack_connect(gcl, q1, q2); + } else { + ret = jack_disconnect(gcl, q1, q2); + } + + if (ret != 0) { + ostringstream buf; + buf << "couldn't " << (v ? "" : "dis") << "connect " << q2 << " -> " << q1; + gx_system::gx_print_error("port connection", buf.str()); + return; + } + gtk_tree_store_set(GTK_TREE_STORE(p->treestore), &iter, 1, v, -1); + update_summary(p); +} + + +/* +** constuctor / destructor +*/ + +inline bool getnumber(gchararray p, long *pi) +{ + char *q; + *pi = strtol(p, &q, 10); + return !*q; +} + +static gint sort_func(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data) +{ + gchararray pa, pb; + gtk_tree_model_get(model, a, 0, &pa, -1); + gtk_tree_model_get(model, b, 0, &pb, -1); + int i = 0; + for (; ; i++) { + if (pa[i] != pb[i]) { + break; + } + if (!pa[i]) { + return 0; + } + } + long ia, ib; + if (getnumber(&pa[i],&ia) && getnumber(&pb[i],&ib)) { + return ia - ib; + } + return strcmp(pa, pb); +} + +void PortMapWindow::load(int sect, jack_port_t *jack_port) +{ + if (gx_jack::client) { + const unsigned int max_items_unfolded = 1; + PortSection& ps = portsection[sect]; + GtkTreeStore *tree = ps.treestore; + assert(tree); + assert(GTK_IS_TREE_STORE(tree)); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tree), 0, sort_func, 0, 0); + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tree), 0, GTK_SORT_ASCENDING); + gtk_tree_store_clear(tree); + const char **ports; + jack_client_t *gcl = (ps.port_attr->client_num == 0 ? gx_jack::client : gx_jack::client_insert); + ports = jack_get_ports(gcl, NULL, ps.port_attr->port_type, + (ps.port_attr->is_input ? JackPortIsOutput : JackPortIsInput)); + if (!ports) { + return; + } + const char** conn_ports = jack_port_get_connections(jack_port); + ClientList cl(ports); + // the following loop depends on the first 2 entries being client_name and client_insert_name + int idx = 0; + for (list::iterator j = excluded_clients.begin(); j != excluded_clients.end(); j++, idx++) { + if (!ps.port_attr->is_insert || ps.port_attr->client_num != idx) { + cl.remove(*j); + } + } + GtkTreeIter iter, parent, *parentp; + for (ClientList::iterator i = cl.begin(); i != cl.end(); i++) { + ClientPortList *p = *i; + if (cl.size() > 1 && p->ports.size() > max_items_unfolded) { + gtk_tree_store_append(tree, &parent, 0); + gtk_tree_store_set(tree, &parent, + 0, p->clientname().c_str(), + 1, false, + 2, false, + -1); + parentp = &parent; + } else { + parentp = 0; + } + for (list::iterator j = p->ports.begin(); j != p->ports.end(); j++) { + bool conn = false; + if (conn_ports) { + for (const char** q = conn_ports; *q; q++) { + if (strcmp(*q, *j) == 0) { + conn = true; + break; + } + } + } + gtk_tree_store_append(tree, &iter, parentp); + gtk_tree_store_set(tree, &iter, + 0, *j, + 1, conn, + 2, true, + -1); + } + } + free(conn_ports); + free(ports); + update_summary(&portsection[sect]); + } +} + +void PortMapWindow::load_all() +{ +#define uslp() usleep(10); // prevents xruns?? (bug in jackd?) + load(0, gx_jack::input_ports[0]); + uslp(); + load(1, gx_jack::output_ports[2]); + uslp(); + load(2, gx_jack::output_ports[3]); + uslp(); + load(3, gx_jack::midi_input_port); + uslp(); + load(4, gx_jack::midi_output_ports); + uslp(); + load(5, gx_jack::input_ports[1]); + uslp(); + load(6, gx_jack::output_ports[0]); +#undef uslp +} + +PortMapWindow::PortMapWindow(GtkCheckMenuItem *item) +{ + monitored_expander_child = 0; + menuitem = item; + gtk_widget_ref(GTK_WIDGET(item)); + + // order of first 2 entries is important (check load()) + excluded_clients.push_back(string(gx_jack::client_insert_name) + ":"); + excluded_clients.push_back(string(gx_jack::client_name) + ":"); + excluded_clients.push_back(string(gx_jack::client_instance) + "_meterbridge:"); + excluded_clients.push_back(string("jack_capture:")); + + GtkBuilder * builder = gtk_builder_new(); + window = load_toplevel(builder, "ports.glade", "PortMapWindow"); + gtk_window_set_icon(GTK_WINDOW (window), GDK_PIXBUF(ib)); + memset(portsection, 0, sizeof(portsection)); + for (int i = 0; i < number_of_ports; i++) { + portsection[i].port_attr = &guitarix_ports[i]; + char name[30]; + snprintf(name, sizeof(name), "scrolledwindow%d", i+1); + portsection[i].scrolled_window = GTK_SCROLLED_WINDOW(gtk_builder_get_object(builder, name)); + snprintf(name, sizeof(name), "treestore%d", i+1); + portsection[i].treestore = GTK_TREE_STORE(gtk_builder_get_object(builder, name)); + snprintf(name, sizeof(name), "cellrenderertoggle%d", i+1); + g_signal_connect(gtk_builder_get_object(builder, name), "toggled", G_CALLBACK(on_cell_toggle), &portsection[i]); + snprintf(name, sizeof(name), "expander%d", i+1); + GObject *w = gtk_builder_get_object(builder, name); + if (w) { + portsection[i].expander = GTK_EXPANDER(w); + g_signal_connect_after(portsection[i].expander, "activate", G_CALLBACK(on_expander), this); + snprintf(name, sizeof(name), "port%d", i+1); + portsection[i].label = GTK_LABEL(gtk_builder_get_object(builder, name)); + } + } + + load_all(); + + g_signal_connect(window, "destroy", G_CALLBACK(destroy_cb), this); + g_signal_connect(window, "response", G_CALLBACK(response_cb), this); + gtk_window_add_accel_group(GTK_WINDOW(window), + GxMainInterface::instance()->fAccelGroup); + g_signal_connect_after(window, "check-resize", G_CALLBACK(on_check_resize), this); + gtk_widget_show(window); + g_object_unref(G_OBJECT(builder)); + instance = this; +} + +// refresh portmap widget when connect/disconnect with jack server +void PortMapWindow::refresh() +{ + if(window) { + if(!gx_jack::client) { + for(int i = 0; i< number_of_ports;i++){ + PortSection& ps = portsection[i]; + GtkTreeStore *tree = ps.treestore; + assert(tree); + assert(GTK_IS_TREE_STORE(tree)); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(tree), 0, sort_func, 0, 0); + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tree), 0, GTK_SORT_ASCENDING); + gtk_tree_store_clear(tree); + update_summary(&portsection[i]); + } + } else { + load_all(); + } + } +} + +PortMapWindow::~PortMapWindow() +{ + instance = 0; + window = NULL; + monitored_expander_child = 0; + gtk_widget_unref(GTK_WIDGET(menuitem)); +} + +} // namespace gui diff --git a/src/gx_preset.cpp b/src/gx_preset.cpp new file mode 100644 index 0000000..13fd8d1 --- /dev/null +++ b/src/gx_preset.cpp @@ -0,0 +1,1013 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix preset handling functions + + ---------------------------------------------------------------------------*/ + +#include +#include +#include +#include "guitarix.h" + + +using namespace gx_system; + +#define _(x) (x) + +namespace gx_preset +{ + +/* get the accel path to connect the mnemonic key on the fly + this is a replacement for gtk_widget_get_accel_path() + witch is not avaluable in <= Gtk+2.12 */ +string gx_get_accel_path(int lindex) +{ + + // set accel_path + string label ; + switch (lindex) + { + case 0: + label = "Load"; + break; + case 1: + label = "Save"; + break; + case 2: + label = "Rename"; + break; + case 3: + label = "Delete"; + break; + + } + //string acc_path = gtk_menu_get_accel_path(GTK_MENU(menu)); + string acc_path = "/"; + acc_path += label; + acc_path += "/"; + + return acc_path; +} + +//----- create a empty preset file +void gx_empty_preset_file(const char* filename) +{ + ofstream nfile(filename); + JsonWriter jw(nfile); + jw.begin_array(); + writeHeader(jw); + jw.end_array(true); + jw.close(); + nfile.close(); +} + +//----- modify (add/sub/change) a existing preset file +bool gx_modify_preset(const char* presname, const char* newname=0, bool remove=false, bool rewrite=false) +{ + string tmpfile = gx_preset_file.get_path() + "_tmp"; + ifstream ofile(gx_preset_file.get_path().c_str()); + ofstream nfile(tmpfile.c_str()); + JsonParser jp(ofile); + JsonWriter jw(nfile); + + bool found = false; + try { + jp.next(JsonParser::begin_array); + jw.begin_array(); + int major, minor; + if (!readHeader(jp, &major, &minor)) { + if (rewrite) { + if (major == 0 && minor == 0) { + gx_print_info("loading presets","rewriting convertet presets"); + } else { + const char *s; + if (major != majorversion) { + s = _("major version mismatch in %1%: found %2%.%3%, expected %4%.%5%"); + } else { + assert(minor != minorversion); + s = _("minor version mismatch in %1%: found %2%.%3%, expected %4%.%5%"); + } + gx_print_warning( + _("recall settings"), + (boost::format(s) % gx_preset_file.get_parse_name() % major % minor % majorversion % minorversion).str()); + } + } + } + writeHeader(jw); + + while (jp.peek() != JsonParser::end_array) { + jp.next(JsonParser::value_string); + if (rewrite) { + jw.write(jp.current_value()); + gx_gui::parameter_map.set_init_values(); + bool has_midi; + read_preset(jp, &has_midi); + write_preset(jw,false,has_midi); + } else if (jp.current_value() == presname) { + found = true; + if (newname) { + jw.write(newname); + jp.copy_object(jw); + } else if (remove) { + jp.skip_object(); + } else { + jw.write(presname); + write_preset(jw); + jp.skip_object(); + } + } else { + jw.write(jp.current_value().c_str()); + jp.copy_object(jw); + } + } + jp.next(JsonParser::end_array); + jp.next(JsonParser::end_token); + + if (!found && !remove && !newname && !rewrite) { + jw.write(presname); + write_preset(jw); + } + jw.end_array(true); + jw.close(); + nfile.close(); + ofile.close(); + if (!nfile.good()) { + gx_print_error("save preset","couldn't write " + tmpfile); + return false; + } + + int rc = rename(tmpfile.c_str(), gx_preset_file.get_path().c_str()); + if (rc != 0) { + gx_print_error("save preset","couldn't rename " + + tmpfile + " to " + gx_preset_file.get_parse_name()); + return false; + } + } catch (gx_system::JsonException& e) { + gx_print_error("save/modify preset", "invalid preset file: " + gx_preset_file.get_parse_name()); + } + return found; +} + +//---- parsing preset file to build up a string vector of preset names +static bool gx_build_preset_list() +{ + // initialize list + plist.clear(); + // initialize menu pointer list + for (int i = 0; i < GX_NUM_OF_PRESET_LISTS; i++) + pm_list[i].clear(); + + // parse it if any + ifstream f(gx_preset_file.get_path().c_str()); + if (f.good()) { + try { + JsonParser jp(f); + jp.next(JsonParser::begin_array); + int samevers = readHeader(jp); + while (jp.peek() == JsonParser::value_string) { + jp.next(); + plist.push_back(jp.current_value()); + jp.skip_object(); + } + jp.next(JsonParser::end_array); + jp.next(JsonParser::end_token); + f.close(); + // ---- how many did we get ? + gx_print_info("Preset List Building", + gx_i2a(plist.size()) + string(" presets found")); + if (!samevers) { + gx_modify_preset(0,0,false,true); + } + return true; + } catch (gx_system::JsonException& e) { + gx_system::gx_print_warning(gx_preset_file.get_parse_name().c_str(), "parse error"); + return false; + } + } + if (gx_preset_file.is_standard()) { + gx_print_info("empty preset File ", gx_preset_file.get_display_name()); + gx_empty_preset_file(gx_preset_file.get_path().c_str()); + return true; + } else { + string msg = (boost::format(_("preset File %1% doesn't exist")) + % gx_preset_file.get_parse_name()).str(); + gx_print_error(_("Load preset file"), msg); + gx_gui::gx_message_popup(msg.c_str()); + return false; + } +} + +// ----------- add new preset to menus +void gx_add_preset_to_menus(const string& presname) +{ + for (int i = 0; i < GX_NUM_OF_PRESET_LISTS; i++) + gx_add_single_preset_menu_item(presname, i, preset_action_func[i]); +} + +//---- add a single preset to a given preset menu +void gx_add_single_preset_menu_item(const string& presname, + const gint lindex, + GCallback func) +{ + // menu + GtkWidget* menu = presmenu[lindex]; + + // index for keyboard shortcut (can take any list) + vector::iterator its; + int pos = 0; + for (its = pm_list[lindex].begin() ; its < pm_list[lindex].end(); its++ ) + { + pos++; + } + pos += 1; + + // add small mnemonic + string name("_"); + if (pos > 9) name = ""; + name += gx_i2a(pos) + " "; + name += presname; + + // GDK numbers + guint accel_key = GDK_1 + pos - 1; + + // create item + GtkWidget* menuitem = gtk_menu_item_new_with_mnemonic (name.c_str()); + g_signal_connect (GTK_OBJECT (menuitem), "activate", + G_CALLBACK (func), + NULL); + + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + // get accel_path for menuitem + string acc_path = gx_get_accel_path(lindex); + acc_path += gx_i2a(accel_key); + + if (pos < 10) + { + if (!gtk_accel_map_lookup_entry(acc_path.c_str(), NULL)) + gtk_accel_map_add_entry(acc_path.c_str(), accel_key, list_mod[lindex]); + + gtk_widget_set_accel_path(menuitem, acc_path.c_str(), + gx_gui::GxMainInterface::instance()->fAccelGroup); + } + + its = pm_list[lindex].end(); + // add a pointer to the menuitem to the preset menu list + pm_list[lindex].insert(its,GTK_MENU_ITEM(menuitem)); + gtk_widget_show (menuitem); +} + + +//----- get the preset number by name from preset list +int gx_get_single_preset_menu_pos(const string& presname, const gint lindex) +{ + vector::iterator its; + int pos = 0; + for (its = plist.begin() ; its < plist.end(); its++ ) + { + pos++; + if( presname == *its) + return pos; + } + return 0; +} + +//----- get pointer to the menuitem +GtkMenuItem* const gx_get_preset_item_from_name(int lindex, const string& name) +{ + vector::iterator its; + vector::iterator it = pm_list[lindex].begin(); + int pos = 0; + for (its = plist.begin() ; its < plist.end(); its++ ) + { + pos++; + if( name == *its) + return *it; + it++; + } + return NULL; +} + +// ----------- update preset numbering in menus +void gx_refresh_preset_menus() +{ + for (int i = 0; i < GX_NUM_OF_PRESET_LISTS; i++) { + vector::iterator it = pm_list[i].begin(); + for (it = pm_list[i].begin(); it != pm_list[i].end(); it++) { + gtk_widget_destroy(GTK_WIDGET(*it)); + } + } + + if (!gx_build_preset_list()) { + gx_print_warning(_("Load preset file"), _("selecting default preset bank")); + gx_preset_file.set_std_value(); + gx_build_preset_list(); + } + vector::iterator its; + for (its = plist.begin() ; its < plist.end(); its++) { + gx_add_preset_to_menus(*its); + } +} + +// ---------- load nth preset (return true if successful) +bool gx_nth_preset(unsigned char n) +{ + // check that we do have presets + if (!pm_list[LOAD_PRESET_LIST].size()) + { + gx_print_warning("Preset Switching", + "Preset list is empty, make some :)"); + return false; + } + vector::iterator it = pm_list[LOAD_PRESET_LIST].begin(); + while (n > 0) { + it++; + if (it == pm_list[LOAD_PRESET_LIST].end()) + return false; + n--; + } + + // load the preset + gx_load_preset(*it, NULL); + return true; +} + +// ---------- switch to next preset in queue +void gx_next_preset(GtkWidget* item, gpointer arg) +{ + // check that we do have presets + if (!pm_list[LOAD_PRESET_LIST].size()) + { + gx_print_warning("Preset Switching", + "Preset list is empty, make some :)"); + return; + } + + // start from this element + vector::iterator it = pm_list[LOAD_PRESET_LIST].begin(); + if (setting_is_preset) + { + GtkMenuItem* const itemi = + gx_get_preset_item_from_name(LOAD_PRESET_LIST, gx_current_preset); + for (it = pm_list[LOAD_PRESET_LIST].begin() ; it < pm_list[LOAD_PRESET_LIST].end(); it++ ) + { + if( itemi == *it) + break; + } + it++; + } + // check if we are on edge + if (it == pm_list[LOAD_PRESET_LIST].end()) + it = pm_list[LOAD_PRESET_LIST].begin(); + + // load the preset + gx_load_preset(*it, NULL); +} + +// ---------- switch to next preset in queue +void gx_previous_preset(GtkWidget* item, gpointer arg) +{ + // check that we do have presets + if (!pm_list[LOAD_PRESET_LIST].size()) + { + gx_print_warning("Preset Switching", + "Preset list is empty, make some :)"); + return; + } + + // start from this element + vector::iterator it = pm_list[LOAD_PRESET_LIST].end(); + if (setting_is_preset) + { + GtkMenuItem* const itemi = + gx_get_preset_item_from_name(LOAD_PRESET_LIST, gx_current_preset); + for (it = pm_list[LOAD_PRESET_LIST].begin() ; it < pm_list[LOAD_PRESET_LIST].end(); it++ ) + { + if( itemi == *it) + break; + } + } + + // check if we are on edge + if (it == pm_list[LOAD_PRESET_LIST].begin()) + it = pm_list[LOAD_PRESET_LIST].end(); + + // decrement iterator and load preset + it--; + + // load the preset + gx_load_preset(*it, NULL); +} + +// ---------- +void gx_delete_active_preset_dialog(GtkWidget* item, gpointer arg) +{ + if (!setting_is_preset || gx_current_preset.empty()) + { + gx_print_warning("Deleting Active Preset", + "No active preset, this is the main setting"); + return; + } + + // tmp store + string presname = gx_current_preset; + + // call dialog + gx_delete_preset_dialog (NULL, NULL); + + if (gx_current_preset.empty() && !setting_is_preset) + gx_print_info("Deleting Active Preset", + string("Deleted preset ") + presname + + string(", recalled main setting")); +} + + +//----preset deletion dialog +void gx_delete_preset_dialog (GtkMenuItem *menuitem, gpointer arg) +{ + string presname = gx_current_preset; + + string msg = " Are you sure you want to delete preset "; + msg += presname; + msg += " ?? "; + + string title = "Deleting preset "; + title += presname; + + //--- run dialog and check response + gint response = + gx_gui::gx_choice_dialog_without_entry ( + title.c_str(), msg.c_str(), + "Delete Preset", "Keep Preset", + GTK_RESPONSE_YES, GTK_RESPONSE_CANCEL, GTK_RESPONSE_YES + ); + + // we are cancelling + if (response == GTK_RESPONSE_CANCEL) + { + gx_print_warning("Preset Deleting", + string(" Deletion of preset ") + presname + + string(" has been cancelled")); + return; + } + + // we want to delete the bugger! + gx_delete_preset (menuitem, arg); +} + +//----delete all presets dialog +void gx_delete_all_presets_dialog (GtkMenuItem *menuitem, gpointer arg) +{ + //--- if no presets, then just pop up some info + if (pm_list[LOAD_PRESET_LIST].empty()) { + gx_print_warning("Delete All Presets Dialog", + string("There is no presets to delete")); + return; + } + + //--- run dialog and check response + gint response = + gx_gui::gx_choice_dialog_without_entry ( + "Deleting ALL Presets! ", + " Are you sure you want to delete ALL your cool presets ? ", + "Yes, DO IT NOW!", "Maybe Later ...", + GTK_RESPONSE_YES, GTK_RESPONSE_CANCEL, GTK_RESPONSE_YES + ); + + // we are cancelling + if (response == GTK_RESPONSE_CANCEL) + { + gx_print_warning("Delete All Presets Dialog", + "All Presets deletion has been cancelled"); + return; + } + // we want to delete all the buggers! + gx_delete_all_presets (); +} + +//----delete all presets +void gx_delete_all_presets() +{ + // this function will simply delete the preset file, + // clear the preset list and refresh the menus + + // write empty preset file + ofstream f(gx_preset_file.get_path().c_str()); + JsonWriter jw(f); + jw.begin_array(); + writeHeader(jw); + jw.end_array(true); + jw.close(); + f.close(); + + // clear list + gx_refresh_preset_menus(); + gx_print_info("All Presets Deleting", string("deleted ALL presets!")); +} + +bool gx_load_preset_from_file(const char* presname) +{ + ifstream ofile(gx_preset_file.get_path().c_str()); + JsonParser jp(ofile); + + try { + jp.next(JsonParser::begin_array); + readHeader(jp); + + bool found = false; + while (jp.peek() != JsonParser::end_array) { + jp.next(JsonParser::value_string); + if (jp.current_value() == presname) { + found = true; + read_preset(jp); + return true; + } else { + jp.skip_object(); + } + } + jp.next(JsonParser::end_array); + jp.next(JsonParser::end_token); + } catch (JsonException& e) { + gx_print_error("load preset", "invalid preset file: " + gx_preset_file.get_parse_name()); + } + return false; +} + +//----preset deletion +void gx_delete_preset (GtkMenuItem* item, gpointer arg) +{ + + // delete it via interface + const string presname = gx_current_preset; + + (void)gx_modify_preset(presname.c_str(), NULL, true); + + // update menu + gx_refresh_preset_menus(); + + // recalling main setting + gx_recall_settings_file(); // FIXME (wrong when loaded with -f ?) + + gx_print_warning("Preset Deleting", + string("Deleted preset ") + + presname + string(", recalled main setting")); +} + +// ---------- +void gx_rename_active_preset_dialog(GtkWidget* item, gpointer arg) +{ + if (!setting_is_preset || gx_current_preset.empty()) + { + gx_print_warning("Renaming Active Preset", + "This is the main setting, " + "load a preset first"); + return; + } + + string presname = gx_current_preset; + + // get current preset menu item + GtkMenuItem* const rnm_item = + gx_get_preset_item_from_name(RENAME_PRESET_LIST, presname); + + // call delete dialog + if (rnm_item) + gx_rename_preset_dialog (rnm_item, NULL); + + if (presname == gx_current_preset) + { + gx_print_warning("Renaming Active Preset", + "The preset name is unchanged"); + return; + } + + if (!gx_current_preset.empty() && setting_is_preset) + gx_print_info("Renaming Active Preset", + string("Renamed preset ") + presname + + string(" to ") + gx_current_preset); +} + +static gboolean gx_convolver_restart(gpointer data) +{ + gx_engine::conv.stop(); + while (gx_engine::conv.is_runnable()) gx_engine::conv.checkstate(); + gx_jconv::GxJConvSettings* jcset = gx_jconv::GxJConvSettings::instance(); + bool rc = gx_engine::conv.configure( + gx_jack::jack_bs, gx_jack::jack_sr, jcset->getIRDir()+"/"+jcset->getIRFile(), + jcset->getGain(), jcset->getlGain(), jcset->getDelay(), jcset->getlDelay(), + jcset->getOffset(), jcset->getLength(), jcset->getMem(), jcset->getBufferSize()); + + if (!rc || !gx_engine::conv.start()) { + gx_jconv::GxJConvSettings::checkbutton7 = 0; + } + return false; +} + +static gboolean gx_rename_main_widget(gpointer data) +{ + // refresh main window name + string title = string("guitarix ") + gx_current_preset; + gtk_window_set_title (GTK_WINDOW (gx_gui::fWindow), title.c_str()); + // reload convolver settings widget + gx_jconv::gx_reload_jcgui(); + return false; +} + +//----menu funktion load +void gx_load_preset (GtkMenuItem *menuitem, gpointer load_preset) +{ + // check that we do have presets + if (!pm_list[LOAD_PRESET_LIST].size()) + { + gx_print_warning("Preset Loading", + "Preset list is empty, make some :)"); + return; + } + + // retrieve preset name + vector::iterator it = pm_list[LOAD_PRESET_LIST].begin(); + vector::iterator its = plist.begin() ;; + for (it = pm_list[LOAD_PRESET_LIST].begin() ; it < pm_list[LOAD_PRESET_LIST].end(); it++ ) + { + if( menuitem == *it) + break; + its++; + } + + string preset_name = *its; + + // recall preset by name + // Note: the UI does not know anything about guitarix's directory stuff + // Need to pass it on + bool preset_ok = gx_load_preset_from_file(preset_name.c_str()); + + // check result + if (!preset_ok) + { + gx_print_error("Preset Loading", string("Could not load preset ") + preset_name); + return; + } + + // print out info + gx_print_info("Preset Loading", string("loaded preset ") + preset_name); + setting_is_preset = true; + + gx_current_preset = preset_name; + + /* do some GUI stuff*/ + g_idle_add(gx_rename_main_widget,NULL); + + /* reset convolver buffer for preset change*/ + if (gx_engine::conv.is_runnable() && gx_jconv::GxJConvSettings::checkbutton7 == 1) { + gx_engine::conv.stop(); + gx_gui::g_threads[3] = g_idle_add_full(G_PRIORITY_HIGH_IDLE+20,gx_convolver_restart,NULL,NULL); + } + + /* collect info for stage info display*/ + gx_gui::show_patch_info = gx_get_single_preset_menu_pos(gx_current_preset, 0); +} + +//---- funktion save +void gx_save_preset (const char* presname, bool expand_menu) +{ + bool found = gx_modify_preset(presname); + + // update preset menus if needed + if (expand_menu == found) { + assert(false); + } + if (expand_menu) + gx_add_preset_to_menus(string(presname)); + + gx_refresh_preset_menus(); + + // refresh display + string ttle = string("guitarix ") + presname; + gtk_window_set_title (GTK_WINDOW (gx_gui::fWindow), (gchar*)ttle.c_str()); + + // we are now in a preset setting + setting_is_preset = true; + gx_current_preset = presname; + + gx_print_info("Preset Saving", string("saved preset ") + string(presname)); + gx_jconv::gx_reload_jcgui(); //FIXME why reload after saving? +} + +// load a preset file +void gx_recall_settings_file(const string *filename) +{ + if (!filename) { + string fname = gx_user_dir + gx_jack::client_instance + "_rc"; + gx_system::recallState(fname); + gx_print_info( + _("Main Setting recalling"), + (boost::format(_("Called back main setting %1%")) % fname).str()); + } else { + gx_system::recallState(*filename); + gx_print_info( + _("loading Settings file"), + (boost::format(_("loaded settings file %1%")) % *filename).str()); + } + gtk_window_set_title(GTK_WINDOW(gx_gui::fWindow), gx_jack::client_instance.c_str()); + setting_is_preset = false; + gx_current_preset = ""; + gx_gui::show_patch_info = 0; + gx_refresh_preset_menus(); +} + +// ----- select a external preset file +void gx_load_preset_file(const char* presname, bool expand_menu) +{ + Gtk::FileChooserDialog file_chooser( + *Glib::wrap(GTK_WINDOW(gx_gui::fWindow)), + "Select a preset *_rc file", + Gtk::FILE_CHOOSER_ACTION_OPEN); + file_chooser.add_button(GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + file_chooser.add_button(GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT); + file_chooser.set_filename(gx_preset_file.get_path()); + file_chooser.set_show_hidden(true); + file_chooser.set_select_multiple(false); + Gtk::FileFilter filter; + filter.add_pattern("*_rc"); + filter.set_name("*_rc"); + file_chooser.add_filter(filter); + Gtk::FileFilter filter1; + filter1.add_pattern("*"); + filter1.set_name("all"); + file_chooser.add_filter(filter1); + file_chooser.set_filter(filter); + if (file_chooser.run() == Gtk::RESPONSE_ACCEPT) { + gx_preset_file.set_path(file_chooser.get_filename()); + setting_is_preset = false; + gx_current_preset = ""; + gx_gui::show_patch_info = 0; + gx_refresh_preset_menus(); + } +} + +// ----- export preset file +void gx_save_preset_file(const char* presname, bool expand_menu) +{ + Gtk::FileChooserDialog file_chooser( + *Glib::wrap(GTK_WINDOW(gx_gui::fWindow)), + "Save a preset *_rc File", + Gtk::FILE_CHOOSER_ACTION_SAVE); + file_chooser.add_button(GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); + file_chooser.add_button(GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT); + file_chooser.set_do_overwrite_confirmation(true); + file_chooser.set_show_hidden(true); + Gtk::FileFilter filter; + filter.add_pattern("*_rc"); + file_chooser.set_filter(filter); + file_chooser.set_current_folder(gx_preset_file.get_directory_path()); + file_chooser.set_current_name("Untitled_rc"); + if (file_chooser.run() == Gtk::RESPONSE_ACCEPT) { + string save_file = file_chooser.get_filename(); + int n = save_file.length() - 3; + if (!(n >= 0 && save_file.substr(n) == "_rc")) { //FIXME: use a real extension + save_file += "_rc"; + } + try { + gx_preset_file.copy(save_file); + } catch(const Glib::Exception& ex) { + gx_print_error("Export preset", ex.what()); + } + } +} + +//----menu funktion save +void gx_save_oldpreset (GtkMenuItem *menuitem, gpointer arg) +{ + guint save_active = GPOINTER_TO_UINT(arg); + string presname; + vector::iterator its = plist.begin() ; + + // are saving an active preset + if (save_active) { + if (gx_current_preset.empty()) { + gx_print_warning("Saving Active Preset", + "We are in main setting, load a preset first"); + return; + } + presname = gx_current_preset; + + } else { // we are saving another preset from the menu + + vector::iterator it; + + for (it = pm_list[SAVE_PRESET_LIST].begin() ; it < pm_list[LOAD_PRESET_LIST].end(); it++ ) { + if( menuitem == *it) { + break; + } + its++; + } + + } + presname = *its;; + gx_save_preset(presname.c_str(), false); +} + +//----clean up preset name given by user +void gx_cleanup_preset_name(string& presname) +{ + gx_nospace_in_name(presname, "-"); +} + +//----menu funktion save +void gx_save_newpreset (GtkEntry* entry) +{ + string presname; + gx_gui::gx_get_text_entry(entry, presname); + + // no text ? + if (presname.empty()) + { + gx_print_error("Saving new preset", "no preset name given"); + return; + } + + // replace spaces by - + gx_cleanup_preset_name(presname); + + // is the name alrady taken ? + vector::iterator its; + vector::iterator it = pm_list[SAVE_PRESET_LIST].begin(); + + for (its = plist.begin() ; its < plist.end(); its++ ) + { + // found a match + if (presname == *its) + { + gx_print_error("New Preset Saving", + string("preset name ") + + presname + + string(" already in use, choose another one")); + gx_save_newpreset_dialog(*it, NULL); + return; + } + it++; + } + + // finally save to preset file + gx_save_preset(presname.c_str(), true); + gx_jconv::gx_reload_jcgui(); +} + +// read name for preset +void gx_recall_main_setting(GtkMenuItem* item, gpointer) +{ + gx_recall_settings_file(); // FIXME (wrong when loaded with -f ?) +} + +// ----- save current setting as main setting +void gx_save_main_setting(GtkMenuItem* item, gpointer arg) +{ + if (! saveStateToFile(gx_user_dir + gx_jack::client_instance + "_rc")) { + gx_print_error("Main Setting","can't save main setting"); + } else if (setting_is_preset) { + gx_print_info("Main Setting", + "Saved current preset into main setting"); + } else { + gx_print_info("Main Setting", "Saved main setting"); + } + gtk_window_set_title(GTK_WINDOW(gx_gui::fWindow), gx_jack::client_instance.c_str()); + setting_is_preset = false; + gx_jconv::gx_reload_jcgui(); +} + +//----menu function save new preset +void gx_save_newpreset_dialog (GtkMenuItem *menuitem, gpointer save_preset) +{ + // preset name to save + string presname; + + // running dialog and get response + gint response = + gx_gui::gx_choice_dialog_with_text_entry ( + "Save new preset ... ", + "\n Please enter a valid preset name: \n", + "Save Preset", "Cancel", + GTK_RESPONSE_YES, GTK_RESPONSE_CANCEL, GTK_RESPONSE_YES, + G_CALLBACK(gx_save_newpreset) + ); + + // check response + if (response == GTK_RESPONSE_CANCEL) + { + gx_print_warning("Saving New Preset Dialog", + " Preset saving has been cancelled"); + return; + } +} + + +//----preset renaming +void gx_rename_preset (GtkEntry* entry) +{ + // rename preset + string newname; + gx_gui::gx_get_text_entry(entry, newname); + + if (newname.empty()) + { + gx_print_error("Preset Renaming", "no preset name given"); + old_preset_name = ""; + return; + } + + // replace spaces by - + gx_cleanup_preset_name(newname); + + // get the UI to manipulate the preset file + if (!gx_modify_preset(old_preset_name.c_str(), newname.c_str())) { + gx_print_error("Preset Renaming", + string("Could not rename preset ") + old_preset_name); + old_preset_name = ""; + return; + } + + // if jconv file + string jc_preset = gx_user_dir + string("jconv_") + old_preset_name + ".conf "; + string jc_file = gx_user_dir + string("jconv_") + newname + ".conf "; + string file_move = jc_preset + jc_file; + (void)gx_system_call("mv", file_move.c_str(), true); + + // refresh the menus + gx_refresh_preset_menus(); + + if (setting_is_preset) + { + string jname = "guitarix "; + string title = jname + newname; + gtk_window_set_title (GTK_WINDOW (gx_gui::fWindow), title.c_str()); + + gx_current_preset = newname; + } + gx_jconv::gx_reload_jcgui(); +} + +//----preset renaming dialog +void gx_rename_preset_dialog (GtkMenuItem *menuitem, gpointer arg) +{ + vector::iterator its = plist.begin(); + vector::iterator it = pm_list[RENAME_PRESET_LIST].begin(); + for (it = pm_list[RENAME_PRESET_LIST].begin() ; it < pm_list[RENAME_PRESET_LIST].end(); it++ ) + { + if( menuitem == *it) + break; + its++; + } + + static string title; + if (menuitem) + { + title = "Renaming preset "; + title += *its; + } + + old_preset_name = *its; + // running dialog and get response + gint response = gx_gui::gx_choice_dialog_with_text_entry ( + title.c_str(), + " Please enter a valid preset name: ", + "Validate", "Cancel", + GTK_RESPONSE_YES, GTK_RESPONSE_CANCEL, GTK_RESPONSE_YES, + G_CALLBACK(gx_rename_preset) + ); + + if (response == GTK_RESPONSE_CANCEL) + { + gx_print_warning("Rename Preset Dialog", + " Preset renaming has been cancelled"); + old_preset_name = ""; + return; + } +} + +void init() +{ + gx_preset_file.set_standard(gx_system::gx_user_dir + "guitarixpre_rc"); + gx_gui::parameter_map.insert(&gx_preset_file); +} + +/* ----------------------------------------------------------------*/ +} /* end of gx_preset namespace */ diff --git a/src/gx_resampler.cpp b/src/gx_resampler.cpp new file mode 100644 index 0000000..0b84d3e --- /dev/null +++ b/src/gx_resampler.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2009-2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the Guitarix resampler + * to use zita-resampler + * + * -------------------------------------------------------------------------- + */ + +#include "guitarix.h" + +namespace gx_resample { + +void SimpleResampler::setup(int sampleRate, unsigned int fact) +{ + assert(fact <= MAX_UPSAMPLE); + m_fact = fact; + const int qual = 16; // resulting in a total delay of 2*qual (0.7ms @44100) + // upsampler + r_up.setup(sampleRate, sampleRate*fact, 1, qual); + // k == filtlen() == 2 * qual + // pre-fill with k-1 zeros + r_up.inp_count = r_up.filtlen() - 1; + r_up.out_count = 1; + r_up.inp_data = r_up.out_data = 0; + r_up.process(); + // downsampler + r_down.setup(sampleRate*fact, sampleRate, 1, qual); + // k == filtlen() == 2 * qual * fact + // pre-fill with k-1 zeros + r_down.inp_count = r_down.filtlen() - 1; + r_down.out_count = 1; + r_down.inp_data = r_down.out_data = 0; + r_down.process(); +} + +void SimpleResampler::up(int count, float *input, float *output) +{ + r_up.inp_count = count; + r_up.inp_data = input; + r_up.out_count = count * m_fact; + r_up.out_data = output; + r_up.process(); + assert(r_up.inp_count == 0); + assert(r_up.out_count == 0); +} + +void SimpleResampler::down(int count, float *input, float *output) +{ + r_down.inp_count = count * m_fact; + r_down.inp_data = input; + r_down.out_count = count+1; // +1 == trick to drain input + r_down.out_data = output; + r_down.process(); + assert(r_down.inp_count == 0); + assert(r_down.out_count == 1); +} + +SimpleResampler resampTube, resampDist; + + +float *BufferResampler::process(int fs_inp, int ilen, float *input, int fs_outp, int& olen) +{ + const int qual = 32; + if (setup(fs_inp, fs_outp, 1, qual) != 0) { + return 0; + } + // pre-fill with k/2-1 zeros + int k = filtlen(); + inp_count = k/2-1; + inp_data = 0; + out_count = 1; // must be at least 1 to get going + out_data = 0; + if (Resampler::process() != 0) { + return 0; + } + inp_count = ilen; + int nout = out_count = (ilen * ratio_b() + ratio_a() - 1) / ratio_a(); + inp_data = input; + float *p = out_data = new float[out_count]; + if (Resampler::process() != 0) { + delete out_data; + return 0; + } + inp_data = 0; + inp_count = k/2; + if (Resampler::process() != 0) { + delete out_data; + return 0; + } + assert(inp_count == 0); + assert(out_count <= 1); + olen = nout - out_count; + return p; +} + +bool StreamingResampler::setup(int srcRate, int dstRate, int nchan) +{ + const int qual = 32; + if (Resampler::setup(srcRate, dstRate, nchan, qual) != 0) { + return false; + } + inp_count = filtlen()/2-1; + inp_data = 0; + out_count = 1; // must be at least 1 to get going + out_data = 0; + if (Resampler::process() != 0) { + return false; + } + assert(inp_count == 0); + assert(out_count == 1); + return true; +} + +int StreamingResampler::process(int count, float *input, float *output) +{ + inp_count = count; + int olen = out_count = get_max_out_size(count); + inp_data = input; + out_data = output; + if (Resampler::process() != 0) { + return 0; + } + assert(inp_count == 0); + return olen - out_count; +} + +int StreamingResampler::flush(float *output) +{ + // maximum data written to output: + // srcRate > dstRate: ~ 2 * qual + // srcRate < dstRate: ~ 2 * qual * dstRate/srcRate + inp_data = 0; + inp_count = filtlen()/2; + out_data = output; + int olen = out_count = get_max_out_size(inp_count); + if (Resampler::process() != 0) { + return 0; + } + assert(inp_count == 0); + return olen - out_count; +} + +} // namespace gx_engine diff --git a/src/gx_sndfile.cpp b/src/gx_sndfile.cpp new file mode 100644 index 0000000..de260b8 --- /dev/null +++ b/src/gx_sndfile.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -------------------------------------------------------------------------- + */ + +/************************************************************** + gx_sndfile.cpp + +***************************************************************/ + +// ------------ This is the gx_sdnfile namespace --------------- +// This namespace mainly wraps around sndfile's functions +// And has some native functionality + +#include "guitarix.h" + +using namespace gx_system; + +namespace gx_sndfile +{ + +// --------------- sf_open writer wrapper : returns file desc. and audio file info +SNDFILE* openOutputSoundFile(const char* name, int chans, int sr) +{ + // initialise the SF_INFO structure + SF_INFO info; + + info.samplerate = sr; + info.channels = chans; + info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; + + return sf_open(name, SFM_WRITE, &info); +} + +// --------------- sf_open reader wrapper : returns file desc. and audio file info +SNDFILE* openInputSoundFile(const char* name, int* chans, int* sr, int* length) +{ + SF_INFO info; + SNDFILE *sf = sf_open(name, SFM_READ, &info); + + *sr = info.samplerate; + *chans = info.channels; + *length = info.frames; + + return sf; +} + +// --------------- sf_writer wrapper +sf_count_t writeSoundOutput(SNDFILE *pOutput, float *buffer, int vecsize) +{ + return sf_writef_float(pOutput, buffer, vecsize); +} + +// --------------- sf_reader wrapper +sf_count_t readSoundInput(SNDFILE *pInput, float *buffer, int vecsize) +{ + return sf_readf_float(pInput, buffer, vecsize); +} + +// --------------- audio resampler +GxResampleStatus resampleSoundFile(const char* pInputi, + const char* pOutputi, + int jackframe) +{ + int chans, length=0, length2=0, sr; + GxResampleStatus status = kNoError; + + // Note: what is length used for ? only length2 used + + // --- open audio files + SNDFILE* pInput = openInputSoundFile (pInputi, &chans, &sr, &length2); + SNDFILE* pOutput = openOutputSoundFile(pOutputi, chans, jackframe); + + // check input + if (!pInput) + { + ostringstream msg; + msg << "Error opening input file " << pInputi; + (void)gx_gui::gx_message_popup(msg.str().c_str()); + status = kErrorInput; + } + + // check input + else if (!pOutput) + { + ostringstream msg; + msg << "Error opening output file " << pOutputi; + (void)gx_gui::gx_message_popup(msg.str().c_str()); + status = kErrorOutput; + } + else + { + const int vecsize=64; + float* sig = new float[vecsize*2]; + int counter = 0; + + // note: what is the length variable doing ?? + while (counter < length+length2-1) + { + readSoundInput (pInput, sig, vecsize); + writeSoundOutput (pOutput, sig, vecsize); + counter += vecsize; + } + + // close files + sf_close(pInput); + sf_close(pOutput); + + delete[] sig; + + ostringstream lab; + lab << "fileinfo: " << endl + << chans << " channel(s) " + << jackframe << " Sample rate " + << length2 << " Frames "; + + gtk_label_set_text(GTK_LABEL(gx_gui::label1), lab.str().c_str()); + } + + return status; +} + +// --------------- sf_close wrapper +void closeSoundFile(SNDFILE *psf_in) +{ + sf_close(psf_in); +} + +} /* end of gx_sndfile namespace */ diff --git a/src/gx_system.cpp b/src/gx_system.cpp new file mode 100644 index 0000000..7e5d8b5 --- /dev/null +++ b/src/gx_system.cpp @@ -0,0 +1,1470 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix system interface + * + * ---------------------------------------------------------------------------- + */ + +#include +#include +#include +#include +#include +#include +#include "guitarix.h" + +using namespace gx_engine; +using namespace gx_jack; +using namespace gx_preset; + +namespace gx_system +{ + +/**************************************************************** + ** JsonWriter + */ + +JsonWriter::JsonWriter(ostream &o): + os(o), + first(true), + deferred_nl(false), + indent("") +{ +} + +inline void JsonWriter::komma() +{ + if (first) + first = false; + else if (!deferred_nl) + os << ", "; + else + os << ","; + flush(); +} + +inline void JsonWriter::space() +{ + if (first) + first = false; + else if (!deferred_nl) + os << " "; + flush(); +} + +inline void JsonWriter::iplus() +{ + indent += " "; +} + +inline void JsonWriter::iminus() +{ + if (!indent.empty()) { + indent = indent.substr(0, indent.size() - 2); + } +} + +void JsonWriter::write(float v, bool nl) +{ + komma(); + os << v; + snl(nl); +} + +void JsonWriter::write(double v, bool nl) +{ + komma(); + os << v; + snl(nl); +} + +void JsonWriter::write(int i, bool nl) +{ + komma(); + os << i; + snl(nl); +} + +void JsonWriter::write(unsigned int i, bool nl) +{ + komma(); + os << i; + snl(nl); +} + +void JsonWriter::write_lit(string s, bool nl) +{ + komma(); + os << s; + snl(nl); +} + +void JsonWriter::write(const char* p, bool nl) +{ + komma(); + os << '"'; + while (*p) { + switch (*p) { + case '\\': case '"': os << '\\'; break; + case '\b': os << '\\'; os << 'b'; continue; + case '\f': os << '\\'; os << 'f'; continue; + case '\n': os << '\\'; os << 'n'; continue; + case '\r': os << '\\'; os << 'r'; continue; + case '\t': os << '\\'; os << 't'; continue; + } + os << *p++; + } + os << '"'; + snl(nl); +} + +void JsonWriter::begin_object(bool nl) +{ + komma(); + os << '{'; + snl(nl); + first = true; + iplus(); +} + +void JsonWriter::end_object(bool nl) +{ + iminus(); + flush(); + os << '}'; + snl(nl); +} + +void JsonWriter::begin_array(bool nl) +{ + komma(); + os << '['; + snl(nl); + first = true; + iplus(); +} + +void JsonWriter::end_array(bool nl) +{ + iminus(); + flush(); + first = false; + os << ']'; + snl(nl); +} + +void JsonWriter::write_key(const char* p, bool nl) +{ + write(p, nl); + os << ": "; + first = true; +} + +void JsonWriter::write_key(string p, bool nl) +{ + write(p, nl); + os << ": "; + first = true; +} + +// called before output of next element +void JsonWriter::flush() +{ + if (deferred_nl) { + os << endl; + deferred_nl = false; + os << indent; + } +} + + +/**************************************************************** + ** JsonParser + */ + +const char* JsonParser::token_names[] = { + "no_token", "end_token", "begin_object", "end_object", + "begin_array", "end_array", "value_string", "value_number", + "value_key" }; + +JsonException::JsonException(const char* desc) +{ + what_str = string("Json parse error: ") + desc; +} + +JsonParser::JsonParser(istream& i): + is(i), + depth(0), + cur_tok(no_token), + nl(false), + next_depth(0), + next_tok(no_token) +{ +} + +void JsonParser::throw_unexpected(token expect) +{ + ostringstream b; + b << "unexpected token: " << token_names[cur_tok] + << " (expected: " << token_names[expect] << ")" + << endl; + throw JsonException(b.str().c_str()); +} + +const char* unicode2utf8(unsigned int input) +{ + const int maskbits = 0x3F; + const int maskbyte = 0x80; + const int mask2bytes = 0xC0; + const int mask3bytes = 0xE0; + static char result[4]; + int n = 0; + // 0xxxxxxx + if (input < 0x80) { + result[n++] = (char)input; + } + // 110xxxxx 10xxxxxx + else if (input < 0x800) { + result[n++] = ((char)(mask2bytes | (input >> 6))); + result[n++] = ((char)(maskbyte | (input & maskbits))); + } + // 1110xxxx 10xxxxxx 10xxxxxx + else { + result[n++] = ((char)(mask3bytes | (input >> 12))); + result[n++] = ((char)(maskbyte | ((input >> 6) & maskbits))); + result[n++] = ((char)(maskbyte | (input & maskbits))); + } + result[n++] = '\0'; + return result; +} + +const char* JsonParser::readcode() +{ + int code = 0; + for (int i = 0; i < 4; i++) { + int n = is.get(); + if (!is.good()) + throw JsonException("eof"); + if ('0' <= n && n <= '9') + n = n - '0'; + else + n = 10 + (toupper(n) - 'A'); + code = code * 16 + n; + } + return unicode2utf8(code); +} + +string JsonParser::readstring() +{ + ostringstream os(""); + char c; + do { + is.get(c); + if (!is.good()) + return ""; + if (c == '\\') { + is.get(c); + if (!is.good()) + return ""; + switch (c) { + case 'b': os << '\b'; break; + case 'f': os << '\f'; break; + case 'n': os << '\n'; break; + case 'r': os << '\r'; break; + case 't': os << '\t'; break; + case 'u': os << readcode(); break; + default: is.get(c); os << c; break; + } + } + else if (c == '"') + return os.str(); + else + os << c; + } while (true); +} + +string JsonParser::readnumber(char c) +{ + ostringstream os(""); + do { + os << c; + c = is.peek(); + switch (c) { + case '+': case '-': case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': case 'e': case 'E': + case '.': + break; + default: + return os.str(); + } + is.get(c); + } while (is.good()); + return ""; +} + +void JsonParser::read_next() +{ + if (next_tok == end_token) + return; + if (next_tok != no_token and next_depth == 0) { + next_tok = end_token; + return; + } + char c; + nl = false; + while (true) { + do { + is.get(c); + if (!is.good()) + throw JsonException("eof"); + if (c == '\n') + nl = true; + } while (c == ' ' || c == '\t' || c == '\r' || c == '\n'); + switch (c) { + case '[': next_tok = begin_array; next_depth++; break; + + case ']': next_tok = end_array; next_depth--; break; + + case '{': next_tok = begin_object; next_depth++; break; + + case '}': next_tok = end_object; next_depth--; break; + + case ',': continue; + + case '"': + next_str = readstring(); + is >> c; + if (!is.good()) + throw JsonException("eof"); + if (c == ':') + next_tok = value_key; + else { + is.unget(); + next_tok = value_string; + } + break; + + case '-': case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + next_str = readnumber(c); + next_tok = value_number; + break; + + default: + throw JsonException("bad token"); + } + break; + } +} + +JsonParser::token JsonParser::next(token expect) +{ + if (cur_tok != end_token) { + if (next_tok == no_token) + read_next(); + depth = next_depth; + cur_tok = next_tok; + str = next_str; + if (next_tok != end_token) + read_next(); + } + if (expect != no_token) + check_expect(expect); + return cur_tok; +} + + +void JsonParser::copy_object(JsonWriter& jw) +{ + int curdepth = depth; + do { + switch (next()) { + case begin_object: + jw.begin_object(nl); + break; + case end_object: + jw.end_object(nl); + break; + case begin_array: + jw.begin_array(nl); + break; + case end_array: + jw.end_array(nl); + break; + case value_string: + jw.write(current_value(),nl); + break; + case value_number: + jw.write_lit(current_value(),nl); + break; + case value_key: + jw.write_key(current_value().c_str(),nl); + break; + default: + throw JsonException("unexpected token"); + } + } while (curdepth != depth); +} + +void JsonParser::skip_object() +{ + int curdepth = depth; + do { + if (next() == end_token) { + throw JsonException("unexpected eof"); + } + } while (curdepth != depth); +} + + +/**************************************************************** + ** loading of saving application data + */ + +static void write_parameters(JsonWriter &w, bool preset) +{ + w.begin_object(true); + for (gx_gui::ParamMap::iterator i = gx_gui::parameter_map.begin(); i != gx_gui::parameter_map.end(); i++) { + gx_gui::Parameter *param = i->second; + if ((preset and param->isInPreset()) or (!preset and !param->isInPreset())) { + param->writeJSON(w); + w.newline(); + } + } + w.end_object(true); +} + +static void read_parameters(JsonParser &jp, gx_gui::paramlist& plist, bool preset) +{ + jp.next(JsonParser::begin_object); + do { + jp.next(JsonParser::value_key); + if (!gx_gui::parameter_map.hasId(jp.current_value())) { + gx_print_warning("recall settings", "unknown parameter: "+jp.current_value()); + jp.skip_object(); + continue; + } + gx_gui::Parameter& param = gx_gui::parameter_map[jp.current_value()]; + if (!preset and param.isInPreset()) { + gx_print_warning("recall settings", "preset-parameter "+param.id()+" in settings"); + jp.skip_object(); + continue; + } else if (preset and !param.isInPreset()) { + gx_print_warning("recall settings", "non preset-parameter "+param.id()+" in preset"); + jp.skip_object(); + continue; + } + param.readJSON_value(jp); + plist.push_back(¶m); + } while (jp.peek() == JsonParser::value_key); + jp.next(JsonParser::end_object); +} + +void write_preset(JsonWriter &w, bool write_midi, bool force_midi) +{ + w.begin_object(true); + w.write_key("engine"); + write_parameters(w, true); + w.write_key("jconv"); + gx_jconv::GxJConvSettings::instance()->writeJSON(w); + if (force_midi || (write_midi && gx_gui::parameter_map["system.midi_in_preset"].getSwitch().get())) { + w.write_key("midi_controller"); + gx_gui::controller_map.writeJSON(w); + } + w.newline(); + w.end_object(true); +} + +void read_preset(JsonParser &jp, bool *has_midi) +{ + gx_gui::paramlist plist; + if (has_midi) { + *has_midi = false; + } + gx_gui::MidiControllerList::controller_array *m = 0; + jp.next(JsonParser::begin_object); + do { + jp.next(JsonParser::value_key); + if (jp.current_value() == "engine") { + read_parameters(jp, plist, true); + } else if (jp.current_value() == "jconv") { + *gx_jconv::GxJConvSettings::instance() = gx_jconv::GxJConvSettings(jp); + } else if (jp.current_value() == "midi_controller") { + if (has_midi || gx_gui::parameter_map["system.midi_in_preset"].getSwitch().get()) { + m = new gx_gui::MidiControllerList::controller_array(gx_gui::MidiControllerList::controller_array_size); + gx_gui::controller_map.readJSON(jp, *m); + if (has_midi) { + *has_midi = true; + } + } else { + jp.skip_object(); + } + } else { + gx_print_warning("recall settings", + "unknown preset section: " + jp.current_value()); + } + } while (jp.peek() == JsonParser::value_key); + jp.next(JsonParser::end_object); + gx_gui::controller_map.remove_controlled_parameters(plist, m); + for (gx_gui::paramlist::iterator i = plist.begin(); i != plist.end(); i++) { + (*i)->setJSON_value(); + } + if (m) { + gx_gui::controller_map.set_controller_array(*m); + delete m; + } +} + +void writeHeader(JsonWriter& jw) +{ + jw.write("guitarix_file_version"); + jw.begin_array(); + jw.write(majorversion); // major format version + jw.write(minorversion); // minor format version + jw.write(GX_VERSION); + jw.end_array(true); +} + +bool readHeader(JsonParser& jp, int *major, int *minor) +{ + jp.next(JsonParser::value_string); + if (jp.current_value() != "guitarix_file_version") { + throw JsonException("invalid guitarix file header"); + } + jp.next(JsonParser::begin_array); + jp.next(JsonParser::value_number); + int m = jp.current_value_int(); + if (major) { + *major = m; + } + jp.next(JsonParser::value_number); // minorversion + int n = jp.current_value_int(); + if (minor) { + *minor = n; + } + jp.next(JsonParser::value_string); // guitarix version + jp.next(JsonParser::end_array); + return m == majorversion && n == minorversion; +} + +static void write_jack_port_connections(JsonWriter& w, const char *key, jack_port_t *port) +{ + w.write_key(key); + w.begin_array(); + const char** pl = jack_port_get_connections(port); + if (pl) { + for (const char **p = pl; *p; p++) { + w.write(*p); + } + free(pl); + } + w.end_array(true); +} + +void write_jack_connections(JsonWriter& w) +{ + w.begin_object(true); + write_jack_port_connections(w, "input", input_ports[0]); + write_jack_port_connections(w, "output1", output_ports[2]); + write_jack_port_connections(w, "output2", output_ports[3]); + write_jack_port_connections(w, "midi_input", midi_input_port); + write_jack_port_connections(w, "midi_output", midi_output_ports); + write_jack_port_connections(w, "insert_out", output_ports[0]); + write_jack_port_connections(w, "insert_in", input_ports[1]); + w.end_object(true); +} + +// -- save state including current preset data +bool saveStateToFile( const string &filename ) +{ + gx_print_info( "wrinting to ", filename.c_str() ); + string tmpfile = filename + "_tmp"; + ofstream f(tmpfile.c_str()); + JsonWriter w(f); + + w.begin_array(); + writeHeader(w); + + w.write("settings"); + write_parameters(w, false); + + w.write("midi_controller"); + gx_gui::controller_map.writeJSON(w); + + w.write("midi_ctrl_names"); + gx_gui::midi_std_ctr.writeJSON(w); + + w.write("current_preset"); + write_preset(w, false); + + w.write("jack_connections"); + write_jack_connections(w); + + w.newline(); + w.end_array(true); + w.close(); + f.close(); + if (!f.good()) { + return false; + } + int rc = rename(tmpfile.c_str(), filename.c_str()); + return rc == 0; +} + +list jack_connection_lists[7]; + +static void read_jack_connections(JsonParser& jp) +{ + jp.next(JsonParser::begin_object); + while (jp.peek() == JsonParser::value_key) { + int i; + jp.next(JsonParser::value_key); + if (jp.current_value() == "input") { + i = kAudioInput; + } else if (jp.current_value() == "output1") { + i = kAudioOutput1; + } else if (jp.current_value() == "output2") { + i = kAudioOutput2; + } else if (jp.current_value() == "midi_input") { + i = kMidiInput; + } else if (jp.current_value() == "midi_output") { + i = kMidiOutput; + } else if (jp.current_value() == "insert_out") { + i = kAudioInsertOut; + } else if (jp.current_value() == "insert_in") { + i = kAudioInsertIn; + } else { + gx_print_warning("recall state","unknown jack ports sections" + jp.current_value()); + jp.skip_object(); + continue; + } + jp.next(JsonParser::begin_array); + while (jp.peek() == JsonParser::value_string) { + jp.next(); + jack_connection_lists[i].push_back(jp.current_value()); + } + jp.next(JsonParser::end_array); + } + jp.next(JsonParser::end_object); +} + +// -- recallState(filename) : load state from file +bool recallState( const string &filename ) +{ + ifstream f(filename.c_str()); + if (!f.good()) { + return false; + } + gx_gui::paramlist plist; + gx_gui::MidiControllerList::controller_array m(gx_gui::MidiControllerList::controller_array_size); + gx_system::JsonParser jp(f); + try { + jp.next(JsonParser::begin_array); + + int major; + readHeader(jp, &major); + if (major != majorversion) { + if (major == 0) { + gx_print_info("recall settings", "loading converted state"); + } else { + stringstream s; + s << "major version mismatch in "+filename+": found " + << major << ", expected " << majorversion << endl; + gx_print_warning("recall settings", s.str()); + } + } + + // other sections (settings, current_preset) + do { + jp.next(JsonParser::value_string); + if (jp.current_value() == "settings") { + read_parameters(jp, plist, false); + } else if (jp.current_value() == "current_preset") { + read_preset(jp); + } else if (jp.current_value() == "midi_controller") { + gx_gui::controller_map.readJSON(jp, m); + } else if (jp.current_value() == "midi_ctrl_names") { + gx_gui::midi_std_ctr.readJSON(jp); + } else if (jp.current_value() == "jack_connections") { + read_jack_connections(jp); + } else { + gx_print_warning("recall settings", + "unknown section: " + jp.current_value()); + jp.skip_object(); + } + } while (jp.peek() == JsonParser::value_string); + jp.next(JsonParser::end_array); + jp.next(JsonParser::end_token); + } catch (JsonException& e) { + gx_print_error("recall settings", "invalid settings file: " + filename); + return false; + } + for (gx_gui::paramlist::iterator i = plist.begin(); i != plist.end(); i++) { + (*i)->setJSON_value(); + } + gx_gui::controller_map.set_controller_array(m); + return true; +} + +/**************************************************************** + ** Measuring times (only when debugging) + */ + +#ifndef NDEBUG + +/* return time difference in ns, fail if > sec (doesn't fit int 32 bit int) */ +int Measure::ts_diff(struct timespec ts1, struct timespec ts2) +{ + time_t df = ts1.tv_sec - ts2.tv_sec; + if (abs(df) > 2) { + return -1; // failed + } + return df * 1000000000 + (ts1.tv_nsec - ts2.tv_nsec); +} + +void Measure::print_accum(Accum& accum, const char* prefix, bool verbose, int total) +{ + cout << prefix << "mean: " << fixed << setprecision(4) << ns2ms(accum.mean()); + if (total > 0) { + cout << " (" << setprecision(2) << 100.0*accum.mean()/float(total) << "%)"; + } + cout << ", min: " << setprecision(4) << ns2ms(accum.minimum()) + << ", max: " << ns2ms(accum.maximum()); + if (total > 0) { + cout << " (" << setprecision(2) << 100.0*accum.maximum()/float(total) << "%)"; + } + if (verbose) { + cout << ", stddev: " << setprecision(4) << ns2ms(accum.stddev()) + << ", n: " << accum.count(); + } + cout << endl; +} + +void Measure::print(bool verbose) +{ + if (verbose) { + print_accum(period, "period ", verbose); + } + print_accum(duration, "duration ", verbose, period.mean()); +} + +void MeasureThreadsafe::print(bool verbose) +{ + Measure *p = pmeasure; + Measure *pn; + if (p == m) { + pn = m+1; + } else { + pn = m; + } + g_atomic_pointer_set(&pmeasure, pn); + p->print(verbose); + p->reset(); +} + +MeasureThreadsafe measure; + +static int print_measures(gpointer data) +{ + bool verbose = GPOINTER_TO_INT(data); + measure.print(verbose); + return TRUE; +} + +void add_time_measurement() +{ + char *p = getenv("GUITARIX_MEASURE"); + if (!p) { + return; + } + bool verbose = false; + if (strcmp(p, "1") == 0) { + verbose = true; + } + g_timeout_add(1000, print_measures, (gpointer)verbose); +} + +#endif + + +/**************************************************************** + ** OS functions and helper + */ + +// ---- retrieve and store the shell variable if not NULL +void gx_assign_shell_var(const char* name, string& value) +{ + const char* val = getenv(name); + value = (val != NULL) ? val : "" ; +} + +// ---- OS signal handler ----- +void gx_signal_handler(int sig) +{ + // print out a warning + string msg = string("signal ") + gx_i2a(sig) + " received, exiting ..."; + gx_print_warning("signal_handler", msg); + + gx_clean_exit(NULL, NULL); +} + +// ---- ladi signal handler ----- +gboolean gx_ladi_handler(gpointer) +{ + gx_print_warning("signal_handler", "signal USR1 received, save settings"); + + saveStateToFile(gx_user_dir + client_instance + "_rc"); + return false; +} + +bool terminal = true; // make messages before main() appear on terminal + +// ---- command line options +void gx_process_cmdline_options(int& argc, char**& argv, string* optvar) +{ + // store shell variable content + for (int i = 0; i < NUM_SHELL_VAR; i++) { + gx_assign_shell_var(shell_var_name[i], optvar[i]); + } + // initialize number of skins. We just count the number of rc files + unsigned int n = gx_gui::gx_fetch_available_skins(); + if (n < 1) { + gx_print_error("main", string("number of skins is 0, aborting ...")); + exit(1); + } + + // ---- parse command line arguments + bool version = false; + Glib::OptionContext opt_context; + opt_context.set_summary( + "All parameters are optional. Examples:\n" + "\tguitarix\n" + "\tguitarix -r black -i system:capture_3\n" + "\tguitarix -c -o system:playback_1 -o system:playback_2"); + Glib::OptionEntry opt_version; + opt_version.set_short_name('v'); + opt_version.set_long_name("version"); + opt_version.set_description("Print version string and exit"); + Glib::OptionGroup main_group("bla1","bla2","bla3"); + main_group.add_entry(opt_version, version); + opt_context.set_main_group(main_group); + + // GTK options: rc style (aka skin) + string opskin("Style to use"); + + vector::iterator it; + + for (it = gx_gui::skin_list.begin(); it != gx_gui::skin_list.end(); it++) { + opskin += ", '" + *it + "'"; + } + + bool clear = false; + Glib::ustring rcset; + Glib::OptionGroup optgroup_gtk( + "gtk", + "\033[1;32mGTK configuration options\033[0m", + "\033[1;32mGTK configuration options\033[0m"); + Glib::OptionEntry opt_clear; + opt_clear.set_short_name('c'); + opt_clear.set_long_name("clear"); + opt_clear.set_description("Use 'default' GTK style"); + Glib::OptionEntry opt_rcset; + opt_rcset.set_short_name('r'); + opt_rcset.set_long_name("rcset"); + opt_rcset.set_description(opskin); + opt_rcset.set_arg_description("STYLE"); + optgroup_gtk.add_entry(opt_clear, clear); + optgroup_gtk.add_entry(opt_rcset, rcset); + + // JACK options: input and output ports + Glib::ustring jack_input; + Glib::ustring jack_midi; + vector jack_outputs; + Glib::ustring jack_uuid; + Glib::OptionGroup optgroup_jack( + "jack", + "\033[1;32mJACK configuration options\033[0m", + "\033[1;32mJACK configuration options\033[0m"); + Glib::OptionEntry opt_jack_input; + opt_jack_input.set_short_name('i'); + opt_jack_input.set_long_name("jack-input"); + opt_jack_input.set_description("Guitarix JACK input"); + opt_jack_input.set_arg_description("PORT"); + Glib::OptionEntry opt_jack_output; + opt_jack_output.set_short_name('o'); + opt_jack_output.set_long_name("jack-output"); + opt_jack_output.set_description("Guitarix JACK outputs"); + opt_jack_output.set_arg_description("PORT"); + Glib::OptionEntry opt_jack_midi; + opt_jack_midi.set_short_name('m'); + opt_jack_midi.set_long_name("jack-midi"); + opt_jack_midi.set_description("Guitarix JACK midi control"); + opt_jack_midi.set_arg_description("PORT"); + Glib::OptionEntry opt_jack_uuid; + opt_jack_uuid.set_short_name('U'); + opt_jack_uuid.set_long_name("jack-uuid"); + opt_jack_uuid.set_description("JackSession ID"); + optgroup_jack.add_entry(opt_jack_input, jack_input); + optgroup_jack.add_entry(opt_jack_output, jack_outputs); + optgroup_jack.add_entry(opt_jack_midi, jack_midi); + optgroup_jack.add_entry(opt_jack_uuid, jack_uuid); + + // FILE options + string load_file; + + Glib::OptionGroup optgroup_file( + "file", + "\033[1;32mFile options\033[0m", + "\033[1;32mFile options\033[0m"); + Glib::OptionEntry opt_load_file; + opt_load_file.set_short_name('f'); + opt_load_file.set_long_name("load-file"); + opt_load_file.set_description("load state file on startup"); + opt_load_file.set_arg_description("FILE"); + optgroup_file.add_entry_filename(opt_load_file, load_file); + + // DEBUG options + string builder_dir; + bool lterminal = false; + Glib::OptionGroup optgroup_debug( + "debug", + "\033[1;32mDebug options\033[0m", + "\033[1;32mDebug options\033[0m"); + Glib::OptionEntry opt_debug; + opt_debug.set_short_name('B'); + opt_debug.set_long_name("builder-dir"); + opt_debug.set_description("directory from which .glade files are loaded"); + opt_debug.set_arg_description("DIR"); + optgroup_debug.add_entry_filename(opt_debug, builder_dir); + Glib::OptionEntry opt_log_terminal; + opt_log_terminal.set_short_name('t'); + opt_log_terminal.set_long_name("log-terminal"); + opt_log_terminal.set_description("print log on terminal"); + optgroup_debug.add_entry(opt_log_terminal, lterminal); + + // collecting all option groups + opt_context.add_group(optgroup_gtk); + opt_context.add_group(optgroup_jack); + opt_context.add_group(optgroup_file); + opt_context.add_group(optgroup_debug); + + // parsing command options + try { + opt_context.parse(argc, argv); + } catch (Glib::OptionError ex) { + gx_print_error("main", "Error in user options! " + ex.what()); + exit(1); + } + + + // ----------- processing user options ----------- + + terminal = lterminal; + + // *** display version if requested + if (version) { + cout << "Guitarix version \033[1;32m" + << GX_VERSION << endl + << "\033[0m Copyright " << (char)0x40 << " 2010 " + << "Hermman Meyer - James Warden - Andreas Degert" + << endl; + exit(0); + } + + // *** process GTK rc style + bool previous_conflict = false; + if (!rcset.empty()) { + // retrieve user value + string tmp = rcset; + + // check contradiction (clear and rcset cannot be used in the same call) + if (clear) { + gx_print_error("main", + string("-c and -r cannot be used together, defaulting to 'default' style")); + tmp = "default"; + previous_conflict = true; + } + + // if garbage, let's initialize to guitarix_default.rc + guint s = 0; + while (s < gx_gui::skin_list.size()) { + if (tmp == gx_gui::skin_list[s]) + break; + s++; + } + + if (s == gx_gui::skin_list.size()) { + gx_print_error("main", + string("rcset value is garbage, defaulting to 'default' style")); + tmp = "default"; + } + optvar[RC_STYLE] = tmp; + } + + // else, if no shell var defined for it, defaulting to guitarix_default.rc + else if (optvar[RC_STYLE].empty()) { + optvar[RC_STYLE] = "default"; + // enable set last used skin + gx_gui::no_opt_skin = 1; + } + + // *** process GTK clear + if (clear) { + // check contradiction (clear and rcset cannot be used in the same call) + if (rcset != NULL && !previous_conflict) + gx_print_error("main", + string("-c and -r cannot be used together, defaulting to 'default' style")); + + optvar[RC_STYLE] = "default"; + } + + // *** process builder_dir + if (!builder_dir.empty()) { + gx_builder_dir = builder_dir; + if (gx_builder_dir[gx_builder_dir.size()-1] != '/') { + gx_builder_dir += "/"; + } + } + + // *** process jack input + if (!jack_input.empty()) { + optvar[JACK_INP] = jack_input; + } + + // *** process jack midi + if (!jack_midi.empty()) { + optvar[JACK_MIDI] = jack_midi; + } + + optvar[JACK_UUID] = jack_uuid; + + // *** process jack outputs + if (!jack_outputs.empty()) { + int idx = JACK_OUT1; + for (unsigned int i = 0; i < jack_outputs.size(); i++, idx++) { + if (i >= 2) { + gx_print_warning("main", + "Warning --> provided more than 2 output ports, ignoring extra ports"); + break; + } + optvar[idx] = jack_outputs[i]; + } + } else { + if (optvar[JACK_OUT1].empty()) { + optvar[JACK_OUT1] = ""; + } + if (optvar[JACK_OUT2].empty()) { + optvar[JACK_OUT2] = ""; + } + } + + optvar[LOAD_FILE] = load_file; + + rcpath = GX_STYLE_DIR + string("/") + string("guitarix_") + optvar[RC_STYLE] + ".rc"; +} + +void gx_set_override_options(string* optvar) +{ + if (!gx_gui::no_opt_skin) { + gx_gui::gx_actualize_skin_index(optvar[RC_STYLE]); + audio.fskin = gx_gui::last_skin = gx_gui::gx_current_skin; + } +} + +struct logmsg { + string msg; + GxMsgType msgtype; + logmsg(string m, GxMsgType t): msg(m), msgtype(t) {} +}; + +// ---- log message handler +void gx_print_logmsg(const char* func, const string& msg, GxMsgType msgtype) +{ + static list msglist; + + // timestamp + time_t now; + time(&now); + struct tm *tm_now = localtime (&now); + ostringstream msgbuf; + msgbuf << "[" << setfill('0') + << setw(2) << tm_now->tm_hour << ":" + << setw(2) << tm_now->tm_min << ":" + << setw(2) << tm_now->tm_sec << "]" + << " " << func << " *** " << msg; + + // log the stuff to the log message window if possible + bool written = false; + if (gx_gui::GxMainInterface::fInitialized) { + gx_gui::GxMainInterface* interface = gx_gui::GxMainInterface::instance(); + + if (interface->getLoggingWindow()) { + if (!msglist.empty()) { + for (list::iterator i = msglist.begin(); i != msglist.end(); i++) { + interface->show_msg(i->msg, i->msgtype); + } + msglist.clear(); + } + interface->show_msg(msgbuf.str(), msgtype); + written = true; + } + } + + if (!written) { // queue the messages + msglist.push_back(logmsg(msgbuf.str(), msgtype)); + } + if (terminal) { + cerr << msgbuf.str() << endl; + } +} + + +// warning +void gx_print_warning(const char* func, const string& msg) +{ + gx_print_logmsg(func, msg, kWarning); +} + +// error +void gx_print_error(const char* func, const string& msg) +{ + gx_print_logmsg(func, msg, kError); +} + +// fatal error +void gx_print_fatal(const char* func, const string& msg) +{ + string msgbuf = string("fatal system error: ") + func + " *** " + msg + "\n"; + cerr << msgbuf; + GtkWidget* widget = gtk_message_dialog_new(NULL, + GtkDialogFlags(GTK_DIALOG_MODAL| + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, + "%s", msgbuf.c_str()); + gtk_window_set_title(GTK_WINDOW(widget), "guitarix"); + gtk_dialog_run(GTK_DIALOG(widget)); + gx_clean_exit(NULL, (gpointer)1); +} + +// info +void gx_print_info(const char* func, const string& msg) +{ + gx_print_logmsg(func, msg, kInfo); +} + + +// ---- check version and if directory exists and create it if it not exist +bool gx_version_check() +{ + struct stat my_stat; + + //----- this check dont need to be against real version, we only need to know + //----- if the presethandling is working with the courent version, we only count this + //----- string when we must remove the old preset files. + string rcfilename = + gx_user_dir + string("version-") + string("0.03.3") ; + + if (stat(gx_user_dir.c_str(), &my_stat) == 0) // directory exists + { + // check which version we're dealing with + if (stat(rcfilename.c_str(), &my_stat) != 0) + { + // current version not there, let's create it and refresh the whole shebang + string oldfiles = gx_user_dir + string("guitarix*rc"); + (void)gx_system_call ("rm -f", oldfiles.c_str(), false); + + oldfiles = gx_user_dir + string("version*"); + (void)gx_system_call ("rm -f", oldfiles.c_str(), false); + + oldfiles = gx_user_dir + string("*.conf"); + (void)gx_system_call ("rm -f", oldfiles.c_str(), false); + + // setting file for current version + ofstream f(rcfilename.c_str()); + string cim = string("guitarix-") + GX_VERSION; + f << cim <", + tmpstr.c_str(), + false + ); */ + } + } + else // directory does not exist + { + // create .guitarix directory + (void)gx_system_call("mkdir -p", gx_user_dir.c_str(), false); + + // setting file for current version + ofstream f(rcfilename.c_str()); + string cim = string("guitarix-") + GX_VERSION; + f << cim <", + tmpstr.c_str(), + false + ); */ + + // --- version file + //same here, we only change this file, when the presethandling is broken, + // otherwise we can let it untouched + tmpstr = gx_user_dir + string("version-") + string("0.03.3"); + (void)gx_system_call("touch", tmpstr.c_str(), false); + + cim = string("echo 'guitarix-") + string(GX_VERSION) + "' >"; + (void)gx_system_call(cim.c_str(), tmpstr.c_str(), false); + + + } + + return TRUE; +} + +//----- we must make sure that the images for the status icon be there +int gx_pixmap_check() +{ + struct stat my_stat; + + string gx_pix = gx_pixmap_dir + "guitarix.png"; + string midi_pix = gx_pixmap_dir + "guitarix-midi.png"; + string warn_pix = gx_pixmap_dir + "guitarix-warn.png"; + + if ((stat(gx_pix.c_str(), &my_stat) != 0) || + (stat(midi_pix.c_str(), &my_stat) != 0) || + (stat(warn_pix.c_str(), &my_stat) != 0)) + + { + gx_print_error("Pixmap Check", " cannot find installed pixmaps! giving up ..."); + + // giving up + return 1; + } + + GtkWidget *ibf = gtk_image_new_from_file (gx_pix.c_str()); + gx_gui::ib = gtk_image_get_pixbuf (GTK_IMAGE(ibf)); + + GtkWidget *stim = gtk_image_new_from_file (midi_pix.c_str()); + gx_gui::ibm = gtk_image_get_pixbuf (GTK_IMAGE(stim)); + + GtkWidget *stir = gtk_image_new_from_file (warn_pix.c_str()); + gx_gui::ibr = gtk_image_get_pixbuf (GTK_IMAGE(stir)); + + return 0; +} + +//----convert int to string +void gx_IntToString(int i, string & s) +{ + s = ""; + + int abs_i = abs(double(i)); + do + { + // note: using base 10 since 10 digits (0123456789) + char c = static_cast(ASCII_START+abs_i%10); + s.insert(0, &c, 1); + } + while ((abs_i /= 10) > 0); + if (i < 0) s.insert(0, "-"); +} + +const string& gx_i2a(int i) +{ + static string str; + gx_IntToString(i, str); + + return str; +} + +//----clean up preset name given by user +void gx_nospace_in_name(string& name, const char* subs) +{ + int p = name.find(' ', 0); + while (p != -1) + { + name.replace(p++, 1, subs); + p = name.find(' ', p); + } +} + +//----abort guitarix +void gx_abort(void* arg) +{ + gx_print_warning("gx_abort", "Aborting guitarix, ciao!"); + exit(1); +} + +//---- guitarix system function +int gx_system_call(const char* name1, + const char* name2, + const bool devnull, + const bool escape) +{ + string str(name1); + str.append(" "); + str.append(name2); + + if (devnull) + str.append(" 1>/dev/null 2>&1"); + + if (escape) + str.append("&"); + + // cerr << " ********* \n system command = " << str.c_str() << endl; + + sigset_t waitset; + sigemptyset(&waitset); + sigaddset(&waitset, SIGCHLD); + sigprocmask(SIG_UNBLOCK, &waitset, NULL); + int rc = system(str.c_str()); + sigprocmask(SIG_BLOCK, &waitset, NULL); + return rc; +} + +// polymorph1 +int gx_system_call(const char* name1, + const string& name2, + const bool devnull, + const bool escape) +{ + return gx_system_call(name1, name2.c_str(), devnull, escape); +} + +// polymorph2 +// int gx_system_call(const string& name1, +// const string& name2, +// const bool devnull, +// const bool escape) +// { +// return gx_system_call(name1.c_str(), name2.c_str(), devnull, escape); +// } + +// polymorph3 +int gx_system_call(const string& name1, + const char* name2, + const bool devnull, + const bool escape) +{ + return gx_system_call(name1.c_str(), name2, devnull, escape); +} + + +//----- clean up when shut down +void gx_destroy_event() +{ + // remove image buffers + if (G_IS_OBJECT(gx_gui::ib)) + g_object_unref(gx_gui::ib); + + if (G_IS_OBJECT(gx_gui::ibm)) + g_object_unref(gx_gui::ibm); + + if (G_IS_OBJECT(gx_gui::ibr)) + g_object_unref(gx_gui::ibr); + + if (G_IS_OBJECT(gx_cairo::tribeimage)) + g_object_unref(gx_cairo::tribeimage); + + if (G_IS_OBJECT(gx_cairo::tribeimage1)) + g_object_unref(gx_cairo::tribeimage1); + + if (G_IS_OBJECT(gx_cairo::tribeimage2)) + g_object_unref(gx_cairo::tribeimage2); + + // remove threads from main GTK thread + for (unsigned int i = 0; i < sizeof(gx_gui::g_threads)/sizeof(gx_gui::g_threads[0]); i++) { + if(gx_gui::g_threads[i] > 0) { + g_source_remove(gx_gui::g_threads[i]); + } + } + + GtkRegler::gtk_regler_destroy(); + + gx_waveview_destroy(GTK_WIDGET(gx_gui::livewa), NULL); + + gtk_main_quit(); +} + +//-----Function that must be called before complete shutdown +void gx_clean_exit(GtkWidget* widget, gpointer data) +{ + // save DSP state + if (isInitialized()) { + get_latency_warning_change(); + gx_gui::gx_get_skin_change(&audio.fskin); + + // only save if we are not in a preset context + if (!setting_is_preset && gx_jack::client) { + saveStateToFile(gx_user_dir + client_instance + "_rc"); + } + } + + gx_gui::shownote = -1; + gx_gui::showwave = 0; + gx_jack::NO_CONNECTION = 1; + + turnOffMidi(); + + // clean jack client stuff + gx_jack_cleanup(); + + // clean GTK stuff + if (gx_gui::fWindow) { + gx_destroy_event(); + } + // delete the locked mem buffers + if (checkfreq) { + delete[] checkfreq; + checkfreq = NULL; + } + if (get_frame) { + delete[] get_frame; + get_frame = NULL; + } + if (get_frame1) { + delete[] get_frame1; + get_frame1 = NULL; + } + if (oversample) { + delete[] oversample; + oversample = NULL; + } + if (result) { + delete[] result; + result = NULL; + } + + printf(" guitarix exit *** ciao . . \n"); + exit(GPOINTER_TO_INT(data)); +} + + +} /* end of gx_system namespace */ diff --git a/src/gx_threads.cpp b/src/gx_threads.cpp new file mode 100644 index 0000000..8e1ff21 --- /dev/null +++ b/src/gx_threads.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 are the guitarix multithreads related functionality + * + * ---------------------------------------------------------------------------- + */ + +#include +#include +#include "guitarix.h" + +using namespace gx_system; +using namespace gx_child_process; +using namespace gx_gui; + +namespace gx_threads +{ +static const float falloff = meter_falloff * meter_display_timeout * 0.001; + +/* ----------------- refresh GX level display function ---------------- */ +gboolean gx_refresh_meter_level(gpointer args) +{ + if (gx_jack::client && gx_engine::buffers_ready) { + gx_gui::GxMainInterface* gui = gx_gui::GxMainInterface::instance(); + + // data holders for meters + // Note: removed RMS calculation, we will only focus on max peaks + float max_level [2]; + (void)memset(max_level, 0, sizeof(max_level)); + + static float old_peak_db [2] = {-INFINITY, -INFINITY}; + + jack_nframes_t nframes = gx_jack::jack_bs; + + // retrieve meter widgets + GtkWidget* const* meters = gui->getLevelMeters(); + + // fill up from engine buffers + for (int c = 0; c < 2; c++) { + // guitarix output levels + float data[nframes]; + + // need to differentiate between channels due to stereo + switch (c) { + default: + case 0: + (void)memcpy(data, gx_engine::get_frame, sizeof(data)); + break; + + case 1: + (void)memcpy(data, gx_engine::get_frame1, sizeof(data)); + break; + } + + // calculate max peak + for (guint f = 0; f < nframes; f++) { + max_level[c] = max(max_level[c], abs(data[f])); + } + + // update meters (consider falloff as well) + if (meters[c]) { + // calculate peak dB and translate into meter + float peak_db = -INFINITY; + if (max_level[c] > 0.) peak_db = power2db(max_level[c]); + + // retrieve old meter value and consider falloff + if (peak_db < old_peak_db[c]) + peak_db = old_peak_db[c] - falloff; + + gtk_fast_meter_set(GTK_FAST_METER(meters[c]), log_meter(peak_db)); + old_peak_db[c] = max(peak_db, -INFINITY); + } + } + } + // run thread again + return TRUE; +} + +/* -------------- refresh oscilloscope function -------------- */ +gboolean gx_refresh_oscilloscope(gpointer args) +{ + // repaint the oscilloscope without involve updateAllGui(). + // if ((showwave == 1) && ((gx_engine::GxEngineState)gx_engine::checky) &&(!gx_jack::NO_CONNECTION )) + gdk_window_invalidate_rect(GDK_WINDOW(livewa->window),NULL,TRUE); + //gx_engine::GxEngine::instance()->viv *= -1; + // run thread again when needed + if(showwave) return TRUE; + else return FALSE; +} + +gboolean gx_xrun_report(gpointer arg) +{ + usleep(40); + ostringstream s; + s << " delay of at least " << gx_jack::xdel << " microsecs"; + gx_print_warning("Jack XRun", s.str()); + + return FALSE; +} + +/* --------- load preset triggered by midi program change --------- */ +gboolean gx_do_program_change(gpointer arg) +{ + int pgm = GPOINTER_TO_INT(arg); + gx_engine::GxEngineState estate = + (gx_engine::GxEngineState)gx_engine::checky; + if (gx_preset::gx_nth_preset(pgm)) + { + if (estate == gx_engine::kEngineBypass) + // engine bypass but preset found -> engine on + gx_engine_switch ((GtkWidget*)0, (gpointer)1); + } + else + { + if (estate == gx_engine::kEngineOn) + // engine on but preset not found -> engine bypass + gx_engine_switch ((GtkWidget*)0, (gpointer)1); + } + // mainloop idle callback: do not call again + return FALSE; +} + +/* -------------- for thread that checks jackd liveliness -------------- */ +gboolean gx_survive_jack_shutdown(gpointer arg) +{ + GtkWidget* wd = gx_gui::GxMainInterface::instance()->getJackConnectItem(); + + // return if jack is not down + if (gx_system_call("pgrep", "jackd", true) == SYSTEM_OK) + { + if (gx_jack::jack_is_down) + { + // let's make sure we get out of here + if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(wd))) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wd), TRUE); + + // run only one time whem jackd is running + return false; + } + } + else + { + // set jack client to NULL + gx_jack::client = 0; + + // refresh some stuff. Note that it can be executed + // more than once, no harm here + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(wd), FALSE); + gx_jconv::GxJConvSettings::checkbutton7 = 0; + gx_jack::jack_is_down = true; + } + // run as long jackd is down + return true; +} + +/* Update all user items reflecting zone z */ +gboolean gx_update_all_gui(gpointer) +{ + // the general Gui update handler + gx_ui::GxUI::updateAllGuis(); + return TRUE; +} + +/** ----------- Glibc THREADS RUNNING BY GUITARIX ----------------- **/ +/** ----------- -------------------------------- ------------------ **/ + + +//--- wait for USR1 signal to arrive and invoke ladi handler via mainloop +gpointer gx_signal_helper_thread(gpointer data) +{ + int sig; + int ret; + sigset_t waitset; + guint source_id = 0; + sigemptyset(&waitset); + sigaddset(&waitset, SIGUSR1); + sigaddset(&waitset, SIGCHLD); + sigprocmask(SIG_BLOCK, &waitset, NULL); + while (true) { + ret = sigwait(&waitset, &sig); + if (ret == 0) { + if (sig == SIGUSR1) { + // do not add a new call if another one is already pending + if (source_id == 0 || g_main_context_find_source_by_id(NULL, source_id) == NULL) + source_id = g_idle_add(gx_ladi_handler, NULL); + } else { + assert(sig == SIGCHLD); + source_id = g_idle_add(gx_child_process::gx_sigchld_handler, NULL); + } + } else { + assert(errno == EINTR); + } + } + //notreached + return NULL; +} + +//---- feed a midi program change from realtime thread to ui thread +gpointer gx_program_change_helper_thread(gpointer data) +{ + gint pgm; + while (TRUE) + { + // wait for a semaphore post from jack realtime thread + sem_wait(&program_change_sem); + // atomic read and reset the variable + do + { + pgm = g_atomic_int_get(&program_change); + } + while (!g_atomic_int_compare_and_exchange(&program_change, pgm, -1)); + assert(pgm != -1); + // get the work done by ui thread + g_idle_add(gx_do_program_change, (gpointer)pgm); + } + //notreached + return NULL; +} + +/** ------------------- Glibc THREADS END ------------------------- **/ +/** ----------- -------------------------------- ------------------ **/ + +} diff --git a/src/gx_ui.cpp b/src/gx_ui.cpp new file mode 100644 index 0000000..41e3881 --- /dev/null +++ b/src/gx_ui.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -------------------------------------------------------------------------- + * + * + * + * GRAPHIC USER INTERFACE (v2) + * This is the Guitarix Engine GUI builder + * + * + * -------------------------------------------------------------------------- + */ + +using namespace std; +#include "gx_ui.h" + +namespace gx_ui +{ +list GxUI::fGuiList; + +// constructor +GxUI::GxUI() : fStopped(false) +{ + fGuiList.push_back(this); +} + +// -- registerZone(z,c) : zone management +void GxUI::registerZone(float* z, GxUiItem* c) +{ + if (fZoneMap.find(z) == fZoneMap.end()) fZoneMap[z] = new clist(); + fZoneMap[z]->push_back(c); +} + +void GxUI::updateAllGuis() +{ + list::iterator g; + for (g = fGuiList.begin(); g != fGuiList.end(); g++) + { + (*g)->updateAllZones(); + } +} + +// Update all user items reflecting zone z +inline void GxUI::updateZone(float* z) +{ + float v = *z; + clist* l = fZoneMap[z]; + for (clist::iterator c = l->begin(); c != l->end(); c++) + if ((*c)->cache() != v) (*c)->reflectZone(); +} + +// Update all user items not up to date +inline void GxUI::updateAllZones() +{ + for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) + { + float* z = m->first; + clist* l = m->second; + float v = *z; + for (clist::iterator c = l->begin(); c != l->end(); c++) { + if ((*c)->cache() != v) (*c)->reflectZone(); + } + } +} + +// add a callback item +inline void GxUI::addCallback(float* zone, GxUiCallback foo, void* data) +{ + new GxUiCallbackItem(this, zone, foo, data); +} + + +/* ---------------- GxUiItem stuff --------------- */ +GxUiItem::GxUiItem (GxUI* ui, float* zone) + : fGUI(ui), fZone(zone), fCache(-123456.654321) +{ + ui->registerZone(zone, this); +} + +// modify zone +void GxUiItem::modifyZone(float v) +{ + fCache = v; + if (*fZone != v) + { + *fZone = v; + fGUI->updateZone(fZone); + } +} + +// item cache +float GxUiItem::cache() +{ + return fCache; +} + +/* ----------------- GxUiCallbackItem stuff ---------------- */ +GxUiCallbackItem::GxUiCallbackItem(GxUI* ui, float* zone, GxUiCallback foo, void* data) + : GxUiItem(ui, zone), fCallback(foo), fData(data) {} + +// reflect zone +void GxUiCallbackItem::reflectZone() +{ + float v = *fZone; + fCache = v; + fCallback(v, fData); +} + +} /* end of guitarix namespace */ diff --git a/src/headers/GtkFastMeter.h b/src/headers/GtkFastMeter.h new file mode 100644 index 0000000..3cb63a5 --- /dev/null +++ b/src/headers/GtkFastMeter.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * -------------------------------------------------------------------------- + * + * Class declaration for a level display + * + * (Code shamelessly stolen from Ardour by Paul Davis, thanks man!) + * + * -------------------------------------------------------------------------- + */ + +#ifndef __GTK_FAST_METER_H__ +#define __GTK_FAST_METER_H__ + + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GTK_TYPE_FAST_METER (gtk_fast_meter_get_type()) +#define GTK_FAST_METER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_FAST_METER, GtkFastMeter)) +#define GTK_IS_FAST_METER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_FAST_METER)) +#define GTK_FAST_METER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_FAST_METER, GtkFastMeterClass)) +#define GTK_IS_FAST_METER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_FAST_METER)) + + + typedef struct _GtkFastMeter GtkFastMeter; + typedef struct _GtkFastMeterClass GtkFastMeterClass; + + struct _GtkFastMeter + { + GtkWidget widget; + + GdkPixbuf* pixbuf; + gint pixheight; + gint pixwidth; + + GdkRectangle pixrect; + GdkRectangle last_peak_rect; + + gint request_width; + gint request_height; + + unsigned long hold_cnt; + unsigned long hold_state; + + float current_level; + float current_peak; + float current_user_level; + + static int min_v_pixbuf_size; + static int max_v_pixbuf_size; + static int rgb0, rgb1, rgb2, rgb3; + + }; + + struct _GtkFastMeterClass + { + GtkWidgetClass parent_class; + }; + + GType gtk_fast_meter_get_type (void); + + /* --------- public exposed API --------- */ + GtkWidget* gtk_fast_meter_new (long, + unsigned long, + int, + int, + int, + int, + int); + + void gtk_fast_meter_destroy (GtkObject* object); + + void gtk_fast_meter_set (GtkFastMeter*, float); + void gtk_fast_meter_clear (GtkFastMeter*); + + float gtk_fast_meter_get_level (GtkFastMeter*); + float gtk_fast_meter_get_user_level (GtkFastMeter*); + float gtk_fast_meter_get_peak (GtkFastMeter*); + + long gtk_fast_meter_hold_count (GtkFastMeter*); + void gtk_fast_meter_set_hold_count (GtkFastMeter*, long); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_FAST_METER_H__ */ diff --git a/src/headers/GtkRegler.h b/src/headers/GtkRegler.h new file mode 100644 index 0000000..82d5b4b --- /dev/null +++ b/src/headers/GtkRegler.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// ***** GtkRegler.h ***** +/****************************************************************************** +part of guitarix, use knobs with Gtk +******************************************************************************/ +#pragma once + +class GtkRegler +{ +private: + +public: + GtkRange parent; + int regler_type; + int last_quadrant; + const char* labels[12]; + double start_x, start_y, max_value; + + GtkRegler(); + ~GtkRegler(); + + static void gtk_regler_destroy ( ); + static void gtk_regler_init_pixmaps(int change_knob); + GtkWidget *gtk_hslider_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_vslider_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_mini_slider_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_eq_slider_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_toggle_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_switch_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_regler_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_big_regler_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_mini_toggle_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_wheel_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_button_toggle_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_led_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_value_display(GtkAdjustment *_adjustment); + GtkWidget *gtk_button_rec_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_button_play_new_with_adjustment(GtkAdjustment *_adjustment); + GtkWidget *gtk_selector_new_with_adjustment(GtkAdjustment *_adjustment,int maxv, const char* []); +}; + diff --git a/src/headers/GtkWaveView.h b/src/headers/GtkWaveView.h new file mode 100644 index 0000000..ce4ab1f --- /dev/null +++ b/src/headers/GtkWaveView.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// ***** GtkWaveView.h ***** +/****************************************************************************** +part of guitarix, plot a wave with Gtk +******************************************************************************/ +#pragma once + +/* internal enum sets */ +typedef enum { + kWvTypeJConv = 0, + kWvTypeLive, + kWvTypeTuner +} GxWaveviewType; + +class GtkWaveView +{ +private: + +public: + inline GtkWaveView() {}; + inline ~GtkWaveView() {}; + + GtkRange parent; + double start_x, start_y, start_value; + GxWaveviewType waveview_type; + + + virtual void gtk_waveview_destroy (GtkWidget*, gpointer); + virtual gboolean gtk_waveview_refresh (GtkWidget*, gpointer); + virtual gboolean gtk_waveview_set_value (GtkWidget*, gpointer); + virtual gboolean gtk_tuner_refresh (GtkWidget*, gpointer); + + + virtual GtkWidget* gtk_wave_view(); + virtual GtkWidget* gtk_wave_live_view(float*, float*, GtkAdjustment*); + virtual GtkWidget* gtk_tuner_view(); +}; + + +/* prototype functions wrapping around class methods */ +void gx_waveview_set_value(GtkWidget*, gpointer); +void gx_waveview_destroy(GtkWidget*, gpointer); +void gx_waveview_refresh(GtkWidget*, gpointer); +void gx_tuner_refresh(GtkWidget*, gpointer); + +GtkWidget* gx_wave_view(); +GtkWidget* gx_tuner_view(); +GtkWidget* gx_wave_live_view(float*, float*, GtkAdjustment*); diff --git a/src/headers/guitarix.h b/src/headers/guitarix.h new file mode 100644 index 0000000..4921bab --- /dev/null +++ b/src/headers/guitarix.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the main guitarix header file. It simply contains the + * more specific headers. Note that each header is trying to be + * self-contained, i.e. only depends on system declarations. Let's + * try to keep it that way. + * + * + * -------------------------------------------------------------------------- + */ + +#pragma once + +/* system header files */ +#include + +/* waf generated defines */ +#include "config.h" + +using namespace std; + +/* guitarix declarations */ +#include "gx_globals.h" +#include "gx_system.h" +#include "gx_jack.h" +#include "gx_child_process.h" +#include "gx_sndfile.h" +#include "gx_ui.h" +#include "gx_convolver.h" +#include "gx_pitch_tracker.h" +#include "gx_resampler.h" +#include "gx_engine.h" +#include "gx_parameter.h" +#include "gx_preset.h" +#include "gx_jconv_settings.h" +#include "gx_threads.h" +#include "gx_cairo_callbacks.h" +#include "gx_gui_helpers.h" +#include "gx_main_interface.h" + +/* special "home-made" GTK classes */ +#include "GtkRegler.h" +#include "GtkWaveView.h" +#include "GtkFastMeter.h" diff --git a/src/headers/gx_cairo_callbacks.h b/src/headers/gx_cairo_callbacks.h new file mode 100644 index 0000000..5280bfc --- /dev/null +++ b/src/headers/gx_cairo_callbacks.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the cairo namespace ------- */ + +#pragma once + +namespace gx_cairo +{ + +extern "C" { + gboolean filter_box_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean vbox_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean tribal_box_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean AmpBox_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean level_meter_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean zac_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean convolver_icon_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean rectangle_skin_color_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean rectangle_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean upper_widget_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean conv_widget_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean amp_expose (GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean boxamp_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean eq_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean plug_box_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean info_box_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); + gboolean slooper_expose(GtkWidget *wi, GdkEventExpose *ev, gpointer user_data); +} + +void gx_init_pixmaps(); + +} diff --git a/src/headers/gx_child_process.h b/src/headers/gx_child_process.h new file mode 100644 index 0000000..bad11cc --- /dev/null +++ b/src/headers/gx_child_process.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the Child Processes namespace ------- */ + +#pragma once + +#include + +namespace gx_child_process +{ + +class GxChild +{ +public: + sigc::signal terminated; + bool kill(); + bool hasPid(pid_t pid) { return pid == m_pid; } + bool hasName(string name) { return name == m_name; } + +private: + string m_name; + int m_killsignal; + int m_pid; + GxChild(string name, int killsignal, int pid): m_name(name), m_killsignal(killsignal), m_pid(pid) {} + friend class GxChildProcs; +}; + +class GxChildProcs +{ +private: + list children; + +public: + ~GxChildProcs(); + bool killall(); + bool kill(string name); + GxChild *find(string name); + GxChild *launch(string name, const char* const args[], int killsignal); + GxChild *launch(string name, list args, int killsignal); + friend gboolean gx_sigchld_handler(gpointer); +}; + +extern GxChildProcs childprocs; +gboolean gx_sigchld_handler(gpointer); + + +/**************************************************************** + ** classes for UI callbacks + */ + +class JackCaptureGui: public sigc::trackable +{ +private: + GtkCheckMenuItem *item; + void terminated(bool pgm_found); + JackCaptureGui(GxChild *p, GtkCheckMenuItem *i); +public: + static void start_stop(GtkCheckMenuItem *menuitem, gpointer); +}; + +class JackCapture: public sigc::trackable +{ +private: + GtkToggleButton *button; + void terminated(bool pgm_found); + static string make_fname(string buf, size_t j, size_t i, int n); + static list capture_command(int& seq); + JackCapture(GxChild *p, GtkToggleButton *b); +public: + static void start_stop(GtkWidget *widget, gpointer data); + static void stop(); +}; + +class Meterbridge: public sigc::trackable +{ +private: + GtkCheckMenuItem *item; + void terminated(bool pgm_found); + Meterbridge(GxChild *p, GtkCheckMenuItem *i); +public: + static void start_stop(GtkCheckMenuItem *menuitem, gpointer); + static void stop(); +}; + +/* -------------------------------------------------------------------------- */ +} /* end of gx_child_process namespace */ diff --git a/src/headers/gx_convolver.h b/src/headers/gx_convolver.h new file mode 100644 index 0000000..d25785a --- /dev/null +++ b/src/headers/gx_convolver.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix convolution Engine ------- */ + +#pragma once + +#include + +namespace gx_engine +{ + +/* GxConvolver */ + +class Audiofile +{ +public: + + enum { + TYPE_OTHER, + TYPE_CAF, + TYPE_WAV, + TYPE_AMB + }; + + enum { + FORM_OTHER, + FORM_16BIT, + FORM_24BIT, + FORM_32BIT, + FORM_FLOAT + }; + + enum { + ERR_NONE = 0, + ERR_MODE = -1, + ERR_TYPE = -2, + ERR_FORM = -3, + ERR_OPEN = -4, + ERR_SEEK = -5, + ERR_DATA = -6, + ERR_READ = -7, + ERR_WRITE = -8 + }; + + Audiofile (void); + ~Audiofile (void); + + //int mode(void) const { return _mode; } + int type(void) const { return _type; } + //int form(void) const { return _form; } + int rate(void) const { return _rate; } + int chan(void) const { return _chan; } + uint32_t size(void) const { return _size; } + + int open_read (string name); + int close (void); + + int seek(uint32_t posit); + int read(float *data, uint32_t frames); + +private: + + void reset(void); + + SNDFILE *_sndfile; + int _mode; + int _type; + int _form; + int _rate; + int _chan; + uint32_t _size; +}; + +class GxConvolverBase: protected Convproc +{ +protected: + bool ready; + void adjust_values(unsigned int audio_size, unsigned int& count, unsigned int& offset, + unsigned int& delay, unsigned int& ldelay, unsigned int& length, + unsigned int& size, unsigned int& bufsize); + GxConvolverBase(): ready(false) {} +public: + void checkstate(); + bool is_runnable() { return ready; } + bool start(); + void stop() { stop_process(); } +}; + +class GxConvolver: public GxConvolverBase +{ +private: + bool read_sndfile (Audiofile& audio, int nchan, int samplerate, const float *gain, + unsigned int *delay, unsigned int offset, unsigned int length); +public: + bool configure( + unsigned int count, int samplerate, string fname, float gain=1.0, float lgain=1.0, + unsigned int delay=0, unsigned int ldelay=0, unsigned int offset=0, + unsigned int length=0, unsigned int size=0, unsigned int bufsize=0); + bool compute(int count, float* input1, float *input2, float *output1, float *output2); +}; + +extern GxConvolver conv; + +class GxSimpleConvolver: public GxConvolverBase +{ +private: +public: + bool configure(int count, float *impresp, unsigned int samplerate); + bool compute(int count, float* input, float *output); + bool compute(int count, float* buffer) { return is_runnable() ? compute(count, buffer, buffer) : true; } +}; + +extern GxSimpleConvolver cab_conv; + +} /* end of gx_engine namespace */ + diff --git a/src/headers/gx_engine.h b/src/headers/gx_engine.h new file mode 100644 index 0000000..d1c3205 --- /dev/null +++ b/src/headers/gx_engine.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix Engine namespace ------- */ + +#pragma once + +// --- defines the processing type +#define ZEROIZE_BUFFERS (0) +#define JUSTCOPY_BUFFERS (1) +#define PROCESS_BUFFERS (2) + +namespace gx_engine +{ + + +/* -- guitarix main engine -- */ + +class AudioVariables +{ +public: + GxMidiState midistate; + int fnoise_g; + int fng; + float fnglevel; + int fcheckbox1; + int fupsample; + int antialis0; + int ftube; + int ftube3; + int fprdr; + int fconvolve; + float convolvefilter; + int fresoon; + float posit0; + int fcheckbox5; + float fautowah; + int fcheckboxcom1; + float posit1; + float posit2; + float posit3; + float posit4; + float posit5; + float posit6; + float posit7; + float posit8; + float posit9; + int foverdrive4; + int fcheckbox4; + int fcheckbox6; + int fcheckbox7; + int fcheckbox8; + int fdelay; + int fmultifilter; + int fboost; + int fchorus; + float ffuse; + float fdialogbox1; + float fdialogbox2; + float fdialogbox3; + float fdialogbox4; +//float fdialogbox5; + float fdialogbox6; + float fdialogbox8; + float fdialogboxj; + float fexpand; + float fexpand2; + float fwarn; + float fwarn_swap; + float fskin; + float viv; + float vivi; + float fchorusbox; + float filebutton; + float fConsta1t; + float midistat; + int feq; + float fdialogbox_eq; + float fdialogbox_eqs; + float fdialogbox_mbf; + float fdialogbox_moo; + int fmoog; + int fflanger; + float fflangerbox; + int fbiquad; + float fbiquadbox; + int ftube3e; + float upsample_mode; + float fampexpand; + int fsloop; + float witchdistortion; + float fdis1; + int fcab; + float fdialogbox_echo; + float fdialogbox_delay; + float witcheq; + float witchamp; + int famp2; + + AudioVariables(); +}; + +extern AudioVariables audio; + + +class MidiVariables { +public: + float fslider45; + float fslider38; + float fslider31; + float fslider27; + float fslider29; + float fslider30; + float fslider26; + float fslider33; + float fslider34; + float fslider35; + float fslider36; + float fslider42; + float fslider43; + float fslider40; + float fslider41; + float fslider44; + float fslider37; + float fslider39; + float fslider46; + float fslider47; + float fslider48; + float fConsta4; + float fConstlog; + float fConstlog2; + float beat0; + float midi_gain; + float fConstun0; + int weg; + int program; + unsigned char* midi_send; + int send; + float fautogain; + int volume; + float fpitch; + int noten; + float fslider32; + int fcheckbox10; + int program1; + int send1; + int noten1; + float fautogain1; + int volume1; + unsigned char* midi_send1; + int send2; + int noten2; + float fpitch1; + float fpitch2; + int fcheckbox11; + int program2; + int volume2; + int Beat_is; + unsigned char* midi_send2; + float fautogain2; + float BeatFilter1; + float BeatFilter2; + float BeatFilterk; + + MidiVariables(); + void init(int samplingFreq); +}; + +extern MidiVariables midi; + + +/* square function */ +inline double sqrf(float x) { return x * x; } + +// wrap the state of the latency change warning (dis/enable) to +// the interface settings to load and save it +inline void set_latency_warning_change() { audio.fwarn_swap = audio.fwarn; } +inline void get_latency_warning_change() { audio.fwarn = audio.fwarn_swap; } + +inline bool isMidiOn() { return (audio.midistate == kMidiOn ? true : false); } +inline void turnOffMidi() { audio.midistate = kMidiOff; } +inline void turnOnMidi() { audio.midistate = kMidiOn; } + +/* function declarations */ +void gx_engine_init( const string *optvar ); +void gx_engine_reset(); +void faust_init(int samplingFreq); +void compute_midi(int len); +void compute_midi_in(void* midi_input_port_buf); +void process_midi(int count); +void compute (int count, float* input, float* output0); +void compute_insert (int count, float* input1, float* output2, float* output3); + +void convolver_filter(float* input, float* output, int sf, int iconvolvefilter); +void moving_filter(float* input, float* output, int sf); +void process_buffers(int count, float* input, float* output0); +void process_insert_buffers (int count, float* input1, float* output0, float* output1); + +#ifdef EXPERIMENTAL +void faust_setup(); +void toggle_exp_window(bool v); +#endif + +/* ------------------------------------------------------------------- */ +} /* end of gx_engine namespace */ diff --git a/src/headers/gx_globals.h b/src/headers/gx_globals.h new file mode 100644 index 0000000..fe9caa5 --- /dev/null +++ b/src/headers/gx_globals.h @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix global variable declarations for all namespaces + * These global vars are created / initialized in gx_globals.cpp + * + * -------------------------------------------------------------------------- + */ + +#pragma once + +#include +#include +#include + +/* ----- main engine ----- */ +namespace gx_engine +{ +/* engine state : can be on or off or bypassed */ +typedef enum { + kEngineOff = 0, + kEngineOn = 1, + kEngineBypass = 2 +} GxEngineState; + +typedef enum { + kMidiOff = 0, + kMidiOn = 1 +} GxMidiState; + +/* global var declarations */ +extern float checky; +extern float* get_frame; +extern float* get_frame1; +extern float* checkfreq; +extern float* oversample; +extern float* result; + +/* latency warning switch */ +extern float fwarn; + +/* engine init state */ +extern bool initialized; +inline bool isInitialized() { return initialized; } + +/* pitchtracker init state */ +extern bool pt_initialized; + +/* buffer ready state */ +extern bool buffers_ready; + +} + +/* -------------------------------------------------------------------------- */ + +/* ----- jack namespace ----- */ +namespace gx_jack +{ +/* latency change confirmation */ +typedef enum { + kChangeLatency = 1, + kKeepLatency = 2 +} GxJackLatencyChange; + +extern const int nIPorts; // mono input +extern const int nOPorts; // stereo output + jconv +extern int NO_CONNECTION; + +/* variables */ +extern jack_nframes_t jack_sr; // jack sample rate +extern jack_nframes_t jack_bs; // jack buffer size +extern float jcpu_load; // jack cpu_load +extern float xdel; // last xrun delay +extern int is_rt; // jack is realtime ? + +extern jack_client_t* client ; +extern jack_client_t* client_insert ; +extern jack_port_t* output_ports[]; +extern jack_port_t* input_ports []; + +extern void* midi_input_port_buf; +extern void* midi_port_buf; + +extern GxJackLatencyChange change_latency; + +#ifdef USE_RINGBUFFER +extern struct MidiMessage ev; +extern jack_ringbuffer_t* jack_ringbuffer; +#endif + +extern jack_port_t* midi_input_port; +extern jack_port_t* midi_output_ports; +extern jack_nframes_t time_is; +extern bool jack_is_down; +extern bool jack_is_exit; +extern string client_name; +extern string client_insert_name; +extern string client_instance; + +extern string client_out_graph; +extern string gx_port_names[]; + +/* lists of jack port types for menu items */ +enum { + kAudioInput = 0, + kAudioOutput1 = 1, + kAudioOutput2 = 2, + kMidiInput = 3, + kMidiOutput = 4, + kAudioInsertIn = 5, + kAudioInsertOut= 6 +}; +} + +/* -------------------------------------------------------------------------- */ + +/* ----- JConv namespace ----- */ +namespace gx_jconv +{ +/* some global vars */ +extern float checkbox7; +extern GtkWidget* mslider; +} + +/* -------------------------------------------------------------------------- */ + +/* ----- preset namespace ----- */ +namespace gx_preset +{ +/* global var declarations */ +extern GdkModifierType list_mod[]; +extern const char* preset_accel_path[]; +extern const char* preset_menu_name[]; +//extern map preset_list[]; + +extern string gx_current_preset; +extern string old_preset_name; + +extern GtkWidget* presmenu[]; +extern GtkWidget* presMenu[]; + +extern vector plist; +extern vector pm_list[]; +extern bool setting_is_preset; + +extern GCallback preset_action_func[]; +} + +/* -------------------------------------------------------------------------- */ + +/* ----- system namespace ----- */ +namespace gx_system +{ +/* message handling */ +typedef enum { + kInfo, + kWarning, + kError, + kMessageTypeCount // just count, must be last +} GxMsgType; + +/* variables and constants */ +extern const int SYSTEM_OK; + +extern string rcpath; + +extern const char* jcapsetup_file; +extern const char* jcapfile_wavbase; +extern const string gx_pixmap_dir; +extern const string gx_style_dir; +extern const string gx_user_dir; +extern string gx_builder_dir; + +/* shell variable names */ +extern const char* shell_var_name[]; +} + +/* -------------------------------------------------------------------------- */ + +/* ----- GUI namespace ----- */ +namespace gx_gui +{ +typedef enum { + kWvMode1 = 1, + kWvMode2, + kWvMode3 +} GxWaveviewMode; + +/* wave view global */ +extern bool new_wave_view; + +/* global GUI widgets */ +extern GtkWidget* fWindow; +extern GtkWidget* menuh; +extern GtkWidget* pb; +extern GtkWidget* midibox; +extern GtkWidget* fbutton; +extern GtkWidget* record_button; +extern GtkWidget* jc_dialog; +extern GtkWidget* patch_info; + +/* wave view widgets */ +extern GtkWidget* livewa; +extern GdkPixbuf* ib; +extern GdkPixbuf* ibm; +extern GdkPixbuf* ibr; + +/* jack server status */ +extern GtkWidget* gx_jackd_on_image; +extern GtkWidget* gx_jackd_off_image; + +/* engine status images */ +extern GtkWidget* gx_engine_on_image; +extern GtkWidget* gx_engine_off_image; +extern GtkWidget* gx_engine_bypass_image; +extern GtkWidget* gx_engine_item; + +/* some more widgets */ +extern GtkWidget* label6; +extern GtkWidget* label1; +extern GtkStatusIcon* status_icon; + +/* tuner and osilloscope*/ +extern int showwave; +extern int shownote; +extern float show_patch_info; + +/* skin handling */ +extern vector skin_list; +extern gint gx_current_skin; +extern int last_skin; +extern int no_opt_skin; +extern int set_knob; + +/* for level display */ +extern int meter_falloff; +extern int meter_display_timeout; + +/*midi_in preset switch */ +extern volatile gint program_change; +extern sem_t program_change_sem; + +extern int show_eq; + +extern int g_threads[4]; + +} + +/* -------------------------------------------------------------------------- */ + +/* ----- cairo namespace ----- */ +namespace gx_cairo +{ +extern GdkPixbuf *tribeimage; +extern GdkPixbuf *tribeimage1; +extern GdkPixbuf *tribeimage2; +} diff --git a/src/headers/gx_gui_helpers.h b/src/headers/gx_gui_helpers.h new file mode 100644 index 0000000..5c021e3 --- /dev/null +++ b/src/headers/gx_gui_helpers.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the GUI namespace ------- */ + +#pragma once + +namespace gx_gui +{ + +/* ---- linking menu items and parameter ---- */ +class MenuCheckItem: public sigc::trackable +{ +private: + GtkCheckMenuItem *item; + static void activateMenuSetSwitch(GtkWidget *w, gpointer data); +public: + MenuCheckItem(): item(0) {} + void init(GtkCheckMenuItem *item, SwitchParameter *p); + void set(bool v); +}; + + +/* -------------- function declarations ---------------- */ +GtkWidget *load_toplevel(GtkBuilder *builder, const char* filename, const char* windowname); +gboolean gx_hide_eq( GtkWidget *widget, gpointer data ); + +/* guitarix skin related functions */ +unsigned int gx_fetch_available_skins(); + +void gx_change_skin(GtkCheckMenuItem *menuitem, gpointer arg); +void gx_cycle_through_skin(GtkWidget *widget, gpointer arg); +bool gx_update_skin(const gint idx, const char* calling_func); +void gx_update_skin_menu_item(const int); +void gx_actualize_skin_index(const string& skin_name); +bool gx_set_skin(GtkWidget *widget, gpointer data); +void gx_get_skin_change(float* fskin); +void gx_set_skin_change(float fskin); + +/* engine status and switch */ +void gx_refresh_engine_status_display(); +void gx_engine_switch (GtkWidget* widget, gpointer arg); + + +/* jack client and port mapping functions */ +void gx_jack_is_down(); +void gx_jack_report_xrun(); + +/* choice dialog windows */ +void gx_get_text_entry(GtkEntry*, string&); + +gint gx_choice_dialog_with_text_entry ( + const char* window_title, + const char* msg, + const char* label1, + const char* label2, + const gint resp1, + const gint resp2, + const gint default_response, + GCallback func + ); + +gint gx_choice_dialog_without_entry ( + const char* window_title, + const char* msg, + const char* label1, + const char* label2, + const gint resp1, + const gint resp2, + const gint default_response + ); + +gint gx_nchoice_dialog_without_entry ( + const char* window_title, + const char* msg, + const guint nchoice, + const char* label[], + const gint resp[], + const gint default_response + ); + +/* extra GUI helpers */ +void gx_show_oscilloscope (GtkCheckMenuItem*, gpointer); +void gx_tuner (GtkCheckMenuItem*, gpointer); +void gx_midi_out (GtkCheckMenuItem*, gpointer); +void gx_log_window (GtkWidget*, gpointer); +void gx_patch (GtkCheckMenuItem*, gpointer ); + + +void gx_systray_menu (GtkWidget*, gpointer); +void gx_reset_units (GtkWidget*, gpointer); +void gx_reset_effects (GtkWidget*, gpointer); +void gx_show_about (GtkWidget*, gpointer); + +void gx_show_extended_settings (GtkWidget*, gpointer); +void gx_hide_extended_settings (GtkWidget*, gpointer); +void gx_cab_res (GtkWidget*, gpointer); +void gx_user_disable_latency_warn (GtkWidget*, gpointer); +gint gx_wait_latency_warn (); +int gx_message_popup (const char*); + +gboolean gx_delete_event (GtkWidget*, gpointer); + +void gx_meter_button_release(GdkEventButton* ev, gpointer arg); + + +/* -------------------------------------------------------------------------- */ +} /* end of gx_gui namespace */ + diff --git a/src/headers/gx_jack.h b/src/headers/gx_jack.h new file mode 100644 index 0000000..874b5d8 --- /dev/null +++ b/src/headers/gx_jack.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the JACK namespace ------- */ + +#pragma once + +/* On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero) + flags to avoid costly denormals */ +#ifdef __SSE__ +#include +#ifdef __SSE2__ +#define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040) +#else +#define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000) +#endif +#else +#define AVOIDDENORMALS +#endif + +#ifdef HAVE_JACK_SESSION +#include +#endif + +namespace gx_jack +{ +#ifdef USE_RINGBUFFER +typedef struct +{ + jack_nframes_t time; + int len; /* Length of MIDI message, in bytes. */ + unsigned char data[3]; +} MidiMessage; +#endif + +extern sem_t jack_sync_sem; + +/* -------- functions ---------- */ +bool gx_jack_init( const string *optvar ); +void gx_jack_callbacks_and_activate(); + +bool gx_start_jack_dialog(); +bool gx_start_jack(void* arg); + +void gx_set_jack_buffer_size(GtkCheckMenuItem*, gpointer); +void gx_jack_connection(GtkCheckMenuItem*, gpointer); +void gx_jack_cleanup(); + +/* client callbacks */ +int gx_jack_srate_callback (jack_nframes_t, void*); +void gx_jack_shutdown_callback (void*); +int gx_jack_xrun_callback (void*); +int gx_jack_buffersize_callback (jack_nframes_t, void*); +void gx_jack_portreg_callback (jack_port_id_t, int, void*); +void gx_jack_init_port_connection(const string*); +#ifdef HAVE_JACK_SESSION +void gx_jack_session_callback(jack_session_event_t *event, void *arg); +#endif + +/* processing */ +int gx_jack_process (jack_nframes_t, void*); +int gx_jack_insert_process (jack_nframes_t, void*); + +#ifndef USE_RINGBUFFER +int gx_jack_midi_process(jack_nframes_t, void*); +#else +int gx_jack_midi_process_ringbuffer(jack_nframes_t, void*); +#endif +int gx_jack_midi_input_process(jack_nframes_t, void*); + +} /* end of jack namespace */ diff --git a/src/headers/gx_jconv_settings.h b/src/headers/gx_jconv_settings.h new file mode 100644 index 0000000..a97daf6 --- /dev/null +++ b/src/headers/gx_jconv_settings.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the JConv settings handler class used by guitarix + * There can only be one instance at all time. To get a pointer + * to the unique instance, simply call + * + * GxJConvSettings* jcset = GxJConvSettings::instance(); + * + * throughout the entire program. + * + * This class belongs to the gx_jconv namespace + * + * -------------------------------------------------------------------------- + */ + +#pragma once + +namespace gx_jconv +{ +// read mode +typedef enum { + kJConvCopy = 0, + kJConvRead = 1 +} GxJConvMode; + +// parameter type +typedef enum { + kJConvGain = 0, + kJConvlGain, + kJConvMem, + kJConvBuffersize, + kJConvMode, + kJConvOffset, + kJConvLength, + kJConvDelay, + kJConvlDelay +} GxJConvParamType; + +/* GUI stuff */ +void gx_reload_jcgui(); +void gx_show_jconv_dialog_gui (GtkWidget *, gpointer ); +void gx_setting_jconv_dialog_gui(GtkWidget*, gpointer); +void gx_acquire_jconv_value (GtkWidget*, gpointer); +void gx_resample_jconv_ir (GtkWidget*, gpointer); +void gx_select_and_draw_jconv_ir(GtkWidget*, gpointer); + +/* main class */ +class GxJConvSettings +{ +private: + // main jconv setting + string fIRFile; + string fIRDir; + + float fGain; // jconv gain + float flGain; // jconv left gain + guint fMem; // memory partition + GxJConvMode fMode; // mode (copy or read) + jack_nframes_t fBufferSize; // frag + guint fOffset; // offset in IR where to start comvolution + guint fLength; // length of the IR to use for convolution + guint fDelay; // delay when to apply reverb + guint flDelay; // left channel delay when to apply reverb + + // private constructor (don't call it, call instance()) + GxJConvSettings(); + + // invalid IR + bool fValidSettings; + +public: + GxJConvSettings(gx_system::JsonParser& jp); + + // getters and setters + inline string getIRFile() const { return fIRFile; } + inline string getIRDir () const { return fIRDir; } + + inline string getFullIRPath() const { + static string slash = "/"; + return fIRDir + slash + fIRFile; + } + + inline float getGain () const { return fGain; } + inline float getlGain () const { return flGain; } + inline guint getMem () const { return fMem; } + inline GxJConvMode getMode () const { return fMode; } + inline jack_nframes_t getBufferSize() const { return fBufferSize; } + inline guint getOffset () const { return fOffset; } + inline guint getLength () const { return fLength; } + inline guint getDelay () const { return fDelay; } + inline guint getlDelay () const { return flDelay; } + + inline void setIRFile (string name) { fIRFile = name; } + inline void setIRDir (string name) { fIRDir = name; } + inline void setGain (float gain) + { + gain = round(gain*100); + fGain = gain*0.01; + } + inline void setlGain (float gain) + { + gain = round(gain*100); + flGain = gain*0.01; + } + inline void setMem (guint mem ) { fMem = mem; } + inline void setMode (GxJConvMode mode) { fMode = mode; } + inline void setBufferSize(jack_nframes_t bs) { fBufferSize = bs; } + inline void setOffset (guint offs) { fOffset = offs; } + inline void setLength (guint leng) { fLength = leng; } + inline void setDelay (guint del) { fDelay = del; } + inline void setlDelay (guint del) { flDelay = del; } + + // internal setting manipulation + inline bool isValid() { return fValidSettings; } + void validate(); + void invalidate(); + void resetSetting(); + + + // --------------- instanciation of jconv handler + static inline GxJConvSettings* instance() + { + static GxJConvSettings jcset; + + // return static instance + return &jcset; + } + + + // checkbutton state + static float checkbutton7; + + // dump parameters on demand to stderr + void dumpParameters(); + + void writeJSON(gx_system::JsonWriter& w); +}; +} /* end of gx_jconv namespace*/ + diff --git a/src/headers/gx_main_interface.h b/src/headers/gx_main_interface.h new file mode 100644 index 0000000..b4f8902 --- /dev/null +++ b/src/headers/gx_main_interface.h @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the GUI namespace ------- */ +// Note: this header file depends on gx_engine.h + +#pragma once + +#include + +#ifndef NJACKLAT +#define NJACKLAT (9) +#endif + +namespace gx_gui +{ + +/**************************************************************** + ** PortMapWindow + */ + +enum { + number_of_ports = 7 +}; + +struct PortAttr { + const int client_num; + const bool is_insert; + const char *port_name; + bool is_input; + const char *port_type; +}; + +extern PortAttr guitarix_ports[number_of_ports]; + +struct PortSection +{ + GtkTreeStore *treestore; + GtkScrolledWindow *scrolled_window; + GtkExpander *expander; + GtkLabel *label; + PortAttr *port_attr; +}; + +class PortMapWindow +{ +private: + PortSection portsection[number_of_ports]; + GtkCheckMenuItem *menuitem; + list excluded_clients; + GtkWidget *monitored_expander_child; + static void on_expander(GtkWidget *widget, gpointer data); + static void on_check_resize(GtkWidget *widget, gpointer data); + static void response_cb(GtkWidget *widget, gint response_id, gpointer data); + static void destroy_cb(GtkWidget*, gpointer data); + static void on_cell_toggle(GtkCellRendererToggle *widget, gchar *path, gpointer data); + static void update_summary(PortSection* p, string *port=0, bool connect=false); + static gboolean redraw_expander(gpointer data); + static list walk(GtkTreeStore *ts, string *port, int connect); + bool walk_remove(GtkTreeStore *ts, bool (*compare)(const string&, const char*), string data); + void walk_insert(GtkTreeStore *ts, string data); + void load(int sect, jack_port_t*); + void load_all(); + PortMapWindow(GtkCheckMenuItem *item); + ~PortMapWindow(); +public: + static GtkWidget *window; // there can only be 1 window + static PortMapWindow* instance; + void client_removed(string name); + void refresh(); + void port_changed(string name, const char *tp, int flags, bool reg); + void connection_changed(string port1, string port2, bool conn); + static void toggle(GtkWidget* widget, gpointer data); +}; + +/**************************************************************** + ** + ** ---------------- the main GUI class ---------------- + ** + */ + +void gx_start_stop_jconv(GtkWidget*, gpointer); + +class GxMainInterface : public gx_ui::GxUI +{ +private: + // private constructor + GxMainInterface(const char* name); + + void addMainMenu(); + + void addEngineMenu(); + void addJackServerMenu(); + + void addPresetMenu(); + void addExtraPresetMenu(); + + //void addPluginMenu(); + + void addOptionMenu(); + void addGuiSkinMenu(); + + void addAboutMenu(); + +protected : + int fTop; + GtkWidget* fBox[stackSize]; + int fMode[stackSize]; + bool fStopped; + GtkTextView* fLoggingWindow; + GtkExpander* fLoggingBox; + GtkAdjustment* fLoggingVAdjustment; + GtkWidget* fLevelMeters[2]; + + GtkWidget* fSignalLevelBar; + + // menu items + map fMenuList; + MenuCheckItem fMidiInPreset; + MenuCheckItem fShowTooltips; + MenuCheckItem fShowTuner; + MenuCheckItem fShowWaveView; +#ifdef EXPERIMENTAL + MenuCheckItem fShowExpWindow; +#endif + + // jack menu widgets + GtkWidget* fJackConnectItem; + GtkWidget* fJackLatencyItem[NJACKLAT]; + + GtkWidget* addWidget(const char* label, GtkWidget* w); + virtual void pushBox(int mode, GtkWidget* w); + +public : + static bool fInitialized; + int highest_unseen_msg_level; + + static const gboolean expand = TRUE; + static const gboolean fill = TRUE; + static const gboolean homogene = FALSE; + + static GxMainInterface* instance(const char* name = ""); + + // for key acclerators + GtkAccelGroup* fAccelGroup; + + // -- acquire a pointer to the logging window + GtkTextView* const getLoggingWindow() const { return fLoggingWindow; } + GtkExpander* const getLoggingBox() const { return fLoggingBox; } + + GtkWidget* const getJackConnectItem() const { return fJackConnectItem; } + + GtkWidget* const* getLevelMeters() const { return fLevelMeters; } + + GtkWidget* const getJackLatencyItem(const jack_nframes_t bufsize) const; + + GtkWidget* const getMenu(const string name) const { return fMenuList.at(name); } + + // -- layout groups + virtual void openHorizontalOrderBox(const char* label, float* posit); + virtual void openHorizontalTableBox(const char* label); + virtual void openHorizontalRestetBox(const char* label, float* posit); + virtual void openFrameBox(const char* label); + virtual void openHorizontalBox(const char* label = ""); + virtual void openHorizontalhideBox(const char* label = ""); + virtual void openVerticalBox(const char* label = ""); + virtual void openVerticalBox1(const char* label = ""); + virtual void openFlipLabelBox(const char* = ""); + virtual void openVerticalSwitchBox(const char* label, int state, int wit, float* zone); + virtual void openVerticalMidiBox(const char* label = ""); + virtual void openDialogBox(const char* label, float* zone, int * z1); + virtual void openPatchInfoBox(float* zone); + virtual void openWarningBox(const char* label, float* zone); + virtual void openEventBox(const char* label = ""); + virtual void openHandleBox(const char* label = ""); + virtual void openExpanderBox(const char* label, float* zone); + virtual void openTabBox(const char* label = ""); + virtual void openSpaceBox(const char* label = ""); + virtual void openAmpBox(const char* label = ""); + virtual void openSlooperBox(const char* label = ""); + virtual void openPlugBox(const char* label = ""); + virtual void openpaintampBox(const char* label = ""); + virtual void openPaintBox(const char* label = ""); + virtual void openPaintBox1(const char* label = ""); + virtual void openPaintBox2(const char* label = ""); + virtual void openScrollBox(const char* label = ""); + virtual void openTextLoggingBox(const char* label = ""); + virtual void openLevelMeterBox(const char* label); + virtual void openToolBar(const char* label = ""); + virtual void setSkinBox(const char* label, float* zone); + virtual void closeBox(); + + // -- active widgets + virtual void addJConvButton(const char* label, float* zone); + virtual void addToggleButton(const char* label, float* zone); + virtual void addPToggleButton(const char* label, float* zone); + virtual void addJToggleButton(const char* label, float* zone); + virtual void addCheckButton(const char* label, float* zone); + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step); + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step); + virtual void addHorizontalWheel(const char* label, float* zone, float init, float min, float max, float step); + virtual void addregler(const char* label, float* zone, float init, float min, float max, float step); + virtual void addbigregler(const char* label, float* zone, float init, float min, float max, float step); + virtual void addslider(const char* label, float* zone, float init, float min, float max, float step); + virtual void addSpinValueBox(const char* label, float* zone, float init, float min, float max, float step); + virtual void addtoggle(const char* label, int* zone); + virtual void addtoggle(const char* label, float* zone); + virtual void addtoggle1(const char* label, float* zone); + virtual void addbtoggle(const char* label, int* zone); + virtual void addbtoggle(const char* label, float* zone); + virtual void addRecButton(const char* label, float* zone); + virtual void addPlayButton(const char* label, float* zone); + virtual void addswitch(const char* label, int* zone); + virtual void addminiswitch(const char* label, int* zone); + virtual void addminiswitch(const char* label, float* zone); + virtual void addminieqswitch(const char* label, int* zone); + virtual void addminicabswitch(const char* label, int* zone); + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step); + virtual void addNumDisplay(const char* label, float* zone); + virtual void addLiveWaveDisplay(const char* label, float* zone , float* zone1); + virtual void addStatusDisplay(const char* label, float* zone ); + virtual void addselector(const char* label, float* zone,int maxv, const char* []); + void addbigregler(string id, const char* label=0); + void addHorizontalWheel(string id, const char* label=0); + void addslider(string id, const char* label=0); + void addregler(string id, const char* label=0); + void addSpinValueBox(string id, const char* label=0); + void addswitch(string id, const char* label=0); + void addminiswitch(string id, const char* label=0); + void addselector(string id, const char* label=0, int nvalues=0, const char **pvalues=0); + void addtoggle(string id, const char* label=0); + void addtoggle1(string id, const char* label=0); + void addbtoggle(string id, const char* label=0); + void addRecButton(string id, const char* label=0); + void addPlayButton(string id, const char* label=0); + void addminieqswitch(string id, const char* label=0); + void addminicabswitch(string id, const char* label=0); + void addVerticalSlider(string id, const char* label=0); + void addCheckButton(string id, const char* label=0); + void addNumEntry(string id, const char* label=0); + void addPToggleButton(string id, const char* label=0); + + // -- other + void show_msg(string msgbuf, gx_system::GxMsgType msgtype); + void set_logging_expander_color(const char *color); + + virtual void setup(); + virtual void show(); + virtual void run(); +}; + +gboolean button_press_cb (GtkWidget *widget, GdkEventButton *event, gpointer data); + +#ifndef NDEBUG +// debug_check +inline void check_zone(GtkWidget *w, void *zone) +{ + if (!parameter_map.hasZone(zone)) { + gchar *p; + gtk_widget_path(w, NULL, &p, NULL); + cerr << "zone not found in definition of widget: " + << p << endl; + g_free(p); + assert(false); + } + parameter_map[zone].setUsed(); +} +#endif + +inline void connect_midi_controller(GtkWidget *w, void *zone) +{ + debug_check(check_zone, w, zone); + g_signal_connect(w, "button_press_event", G_CALLBACK (button_press_cb), (gpointer)¶meter_map[zone]); +} + +/* -------------------------------------------------------------------------- */ +} /* end of gx_gui namespace */ + diff --git a/src/headers/gx_parameter.h b/src/headers/gx_parameter.h new file mode 100644 index 0000000..fdd30ba --- /dev/null +++ b/src/headers/gx_parameter.h @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * -------------------------------------------------------------------------- + */ + +#pragma once + +#include + +namespace gx_gui +{ + +#ifndef NDEBUG +#define debug_check(func, ...) func(__VA_ARGS__) +#else +#define debug_check(...) +#endif + +/**************************************************************** + ** + ** Parameter + ** + */ + +string param_group(string id, bool nowarn=false); + +/**************************************************************** + ** Parameter + */ + +class FloatParameter; +class FloatEnumParameter; +class IntParameter; +class EnumParameter; +class BoolParameter; +class SwitchParameter; +class FileParameter; + +class Parameter +{ +public: + enum ctrl_type { None, Continuous, Switch, Enum }; + +protected: + enum value_type { tp_float, tp_int, tp_bool, tp_switch, tp_file }; + string _id; + string _name, _group; + enum value_type v_type : 3; + enum ctrl_type c_type : 3; + bool save_in_preset : 1; + bool controllable : 1; + bool used : 1; // debug + bool experimental : 1; // experimental faust code, suppress warnings + +public: + Parameter(string id, string name, value_type vtp, ctrl_type ctp, bool preset, bool ctrl, bool exp=false): + _id(id), + _name(name), + _group(param_group(id, exp)), + v_type(vtp), + c_type(ctp), + save_in_preset(preset), + controllable(ctrl), + used(false), + experimental(exp) + {} + +#ifndef NDEBUG + bool isUsed() const { return used; } + void setUsed() { assert(controllable); used = true; } +#endif + + bool isFloat() const { return v_type == tp_float; } + bool isInt() const { return v_type == tp_int; } + bool isBool() const { return v_type == tp_bool; } + bool isSwitch() const { return v_type == tp_switch; } + bool isFile() const { return v_type == tp_file; } + ctrl_type getControlType() const { return c_type; } + bool isControllable() const { return controllable; } + bool isInPreset() const { return save_in_preset; } + bool isExperimental() const { return experimental; } + string id() const { return _id; } + string group() const { return _group; } + string name() const { return _name; } + bool operator==(const Parameter& p) const { return &p == this; } + virtual void *zone() = 0; + virtual void set_std_value() = 0; + virtual void set(int n, int high, float llimit, float ulimit) = 0; + virtual void writeJSON(gx_system::JsonWriter& jw) = 0; + virtual void readJSON_value(gx_system::JsonParser& jp) = 0; + virtual void setJSON_value() = 0; + virtual bool hasRange() const; + virtual float getLowerAsFloat() const; + virtual float getUpperAsFloat() const; + virtual float getStepAsFloat() const; + virtual const char **getValueNames() const; + FloatParameter& getFloat(); + IntParameter& getInt(); + BoolParameter& getBool(); + SwitchParameter& getSwitch(); + FileParameter &getFile(); +}; + +typedef list paramlist; + + +class FloatParameter: public Parameter +{ +protected: + float json_value; +public: + float &value; + float std_value; + float lower, upper, step; + void set(float val) const { value = min(max(val, lower), upper); } + virtual void *zone(); + virtual void set_std_value(); + virtual void set(int n, int high, float llimit, float ulimit); + virtual void writeJSON(gx_system::JsonWriter& jw); + virtual void readJSON_value(gx_system::JsonParser& jp); + virtual void setJSON_value(); + virtual bool hasRange() const; + virtual float getLowerAsFloat() const; + virtual float getUpperAsFloat() const; + virtual float getStepAsFloat() const; + FloatParameter(string id, string name, ctrl_type ctp, bool preset, + float &v, float sv, float lv, float uv, float tv, bool ctrl, bool exp=false): + Parameter(id, name, tp_float, ctp, preset, ctrl, exp), + value(v), std_value(sv), lower(lv), upper(uv), step(tv) + {} +}; + +class FloatEnumParameter: public FloatParameter +{ +private: + const char** value_names; +public: + virtual void writeJSON(gx_system::JsonWriter& jw); + virtual void readJSON_value(gx_system::JsonParser& jp); + virtual const char **getValueNames() const; + FloatEnumParameter(string id, string name, const char** vn, bool preset, float &v, + int sv, bool ctrl, bool exp=false); +}; + +class IntParameter: public Parameter +{ +protected: + int json_value; +public: + int &value; + int std_value; + int lower, upper; + void set(int val) const { value = min(max(val, lower), upper); } + virtual void *zone(); + virtual void set_std_value(); + virtual void set(int n, int high, float llimit, float ulimit); + virtual void writeJSON(gx_system::JsonWriter& jw); + virtual void readJSON_value(gx_system::JsonParser& jp); + virtual void setJSON_value(); + virtual bool hasRange() const; + virtual float getLowerAsFloat() const; + virtual float getUpperAsFloat() const; + IntParameter(string id, string name, ctrl_type ctp, bool preset, + int &v, int sv, int lv, int uv, bool ctrl, bool exp=false): + Parameter(id, name, tp_int, ctp, preset, ctrl, exp), + value(v), std_value(sv), lower(lv), upper(uv) + {} +}; + +class EnumParameter: public IntParameter +{ +private: + const char** value_names; +public: + virtual void writeJSON(gx_system::JsonWriter& jw); + virtual void readJSON_value(gx_system::JsonParser& jp); + virtual const char **getValueNames() const; + EnumParameter(string id, string name, const char** vn, bool preset, int &v, + int sv, bool ctrl, bool exp=false); +}; + +class BoolParameter: public Parameter +{ +private: + bool json_value; +public: + bool &value; + bool std_value; + void set(bool val) const { value = val; } + virtual void *zone(); + virtual void set_std_value(); + virtual void set(int n, int high, float llimit, float ulimit); + virtual void writeJSON(gx_system::JsonWriter& jw); + virtual void setJSON_value(); + virtual void readJSON_value(gx_system::JsonParser& jp); + BoolParameter(string id, string name, ctrl_type ctp, bool preset, + bool &v, bool sv, bool ctrl, bool exp=false): + Parameter(id, name, tp_float, ctp, preset, ctrl, exp), + value(v), std_value(sv) + {} +}; + +class SwitchParameter: public Parameter +{ +private: + bool value; + bool std_value; + bool json_value; +public: + sigc::signal changed; + void set(bool val); + bool get() const { return value; } + virtual void *zone(); + virtual void set_std_value(); + virtual void set(int n, int high, float llimit, float ulimit); + virtual void writeJSON(gx_system::JsonWriter& jw); + virtual void readJSON_value(gx_system::JsonParser& jp); + virtual void setJSON_value(); + SwitchParameter(string id, bool preset=false, bool sv=false): + Parameter(id, "", tp_switch, Switch, preset, false), + value(sv), std_value(sv) + {} +}; + +class FileParameter: public Parameter +{ +private: + Glib::RefPtr value; + Glib::RefPtr std_value; + Glib::RefPtr json_value; +public: + void set(const Glib::RefPtr& val); + void set_path(const string& path); + const Glib::RefPtr& get() const { return value; } + virtual void *zone(); + virtual void set_std_value(); + virtual void set(int n, int high, float llimit, float ulimit); + virtual void writeJSON(gx_system::JsonWriter& jw); + virtual void readJSON_value(gx_system::JsonParser& jp); + virtual void setJSON_value(); + FileParameter(string id, string filename, bool preset=false): + Parameter(id, "", tp_file, None, preset, false), + value(Gio::File::create_for_path(filename)), + std_value(value->dup()) + {} + FileParameter(string id, bool preset=false): + Parameter(id, "", tp_file, None, preset, false), + value(0), + std_value(0) + {} + void set_standard(const string& filename); + bool is_standard() const; + string get_path(); + string get_directory_path(); + string get_parse_name(); + string get_display_name(); + void copy(const string& destination); +}; + +inline FloatParameter &Parameter::getFloat() +{ + assert(isFloat()); + return static_cast(*this); +} + +inline IntParameter &Parameter::getInt() +{ + assert(isInt()); + return static_cast(*this); +} + +inline BoolParameter &Parameter::getBool() +{ + assert(isBool()); + return static_cast(*this); +} + +inline SwitchParameter &Parameter::getSwitch() +{ + assert(isSwitch()); + return static_cast(*this); +} + +inline FileParameter &Parameter::getFile() +{ + assert(isFile()); + return static_cast(*this); +} + +/**************************************************************** + ** ParamMap + */ + +class ParamMap +{ +private: + map id_map; + map addr_map; + +#ifndef NDEBUG + void unique_zone(Parameter* param); + void unique_id(Parameter* param); + void check_id(string id); + void check_p(const char *p); + void check_addr(const void *p); +#endif + +public: + typedef map::iterator iterator; + iterator begin() { return id_map.begin(); } + iterator end() { return id_map.end(); } + bool hasZone(const void *p) const { return addr_map.find(p) != addr_map.end(); } + bool hasId(string id) const { return id_map.find(id) != id_map.end(); } + bool hasId(const char *p) const { return id_map.find(p) != id_map.end(); } + Parameter& operator[](const void *p) { debug_check(check_addr, p); return *addr_map[p]; } + Parameter& operator[](string id) { debug_check(check_id, id); return *id_map[id]; } + Parameter& operator[](const char *p) { debug_check(check_p, p); return *id_map[p]; } + void insert(Parameter* param); + void set_init_values(); +}; + +extern ParamMap parameter_map; // map id -> parameter, zone -> parameter + +inline void registerParam(const char*a,const char*b,float*c,float std,float lower,float upper,float step) +{ + parameter_map.insert(new FloatParameter(a,b,Parameter::Continuous,true,*c,std,lower,upper,step,true)); +} + +inline void registerParam(const char*a,const char*b,float*c,float std=0) +{ + parameter_map.insert(new FloatParameter(a,b,Parameter::Switch,true,*c,std,0,1,1,true)); +} + +// should be bool +inline void registerParam(const char*a,const char*b,int*c,int d) +{ + parameter_map.insert(new IntParameter(a,b,Parameter::Switch,true,*c,d,0,1065353216,true)); //FIXME (see above float/int) +} + +inline void registerParam(const char*a,const char*b,bool*c,bool d=false, bool exp=false) +{ + parameter_map.insert(new BoolParameter(a,b,Parameter::Switch,true,*c,d,true,exp)); +} + +/**************************************************************** + ** + ** Midi + ** + */ + + +/* +** MidiStandardControllers +*/ + +class MidiStandardControllers +{ +private: + struct modstring { + string name; + bool modified; + const char *std; + modstring(string n, bool m, const char* s): name(n), modified(m), std(s) {} + modstring(const char* n): name(n), modified(false), std(n) {} + modstring(): name(""), modified(false), std(0) {} + }; + map m; + +public: + MidiStandardControllers(); + const string operator[](int ctr) { return m[ctr].name; } + void replace(int ctr, string name); + void writeJSON(gx_system::JsonWriter& jw) const; + void readJSON(gx_system::JsonParser& jp); +}; + +extern MidiStandardControllers midi_std_ctr; // map ctrl num -> standard name + + +/* +** MidiController +*/ + +class MidiController +{ +private: + Parameter ¶m; + float _lower, _upper; +public: + MidiController(Parameter &p, float l, float u): + param(p), _lower(l), _upper(u) + {} + float lower() const { return _lower; } + float upper() const { return _upper; } + void operator=(MidiController m) { param = m.param; _lower = m._lower; _upper = m._upper; } + bool hasParameter(const Parameter& p) const { return param == p; } + Parameter& getParameter() const { return param; } + static MidiController* readJSON(gx_system::JsonParser&); + void set(int n) { param.set(n, 127, _lower, _upper); } + void writeJSON(gx_system::JsonWriter& jw) const; +}; + +typedef list midi_controller_list; + + +/* +** MidiControllerList +*/ + +class MidiControllerList +{ +public: + typedef vector controller_array; + enum { controller_array_size = 128 }; +private: + controller_array map; + bool midi_config_mode; + int last_midi_control; + int last_midi_control_value; +public: + MidiControllerList(); + midi_controller_list& operator[](int n) { return map[n]; } + int size() { return map.size(); } + void set_config_mode(bool mode, int ctl=-1); + bool get_config_mode() { return midi_config_mode; } + int get_current_control() { return last_midi_control; } + void set_current_control(int ctl) { last_midi_control = ctl; } + void set(int ctr, int val); + void deleteParameter(Parameter& param, bool quiet=false); + void modifyCurrent(Parameter& param, float lower, float upper); + int param2controller(Parameter& param, const MidiController** p); + void writeJSON(gx_system::JsonWriter& jw); + void readJSON(gx_system::JsonParser& jp, controller_array& m); + void set_controller_array(const controller_array& m); + void remove_controlled_parameters(paramlist& plist, const controller_array *m); + sigc::signal changed; +}; + +void recall_midi_controller_map(); +bool save_midi_controller_map(); + +extern MidiControllerList controller_map; // map ctrl num -> controlled parameters + + +} // namespace gx_gui diff --git a/src/headers/gx_pitch_tracker.h b/src/headers/gx_pitch_tracker.h new file mode 100644 index 0000000..ef2ce1e --- /dev/null +++ b/src/headers/gx_pitch_tracker.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix Engine namespace ------- */ + +#pragma once + +#include + +namespace gx_engine +{ +/* ------------- Pitch Tracker ------------- */ + +const int MAX_FFT_SIZE = 512; // The size of the read buffer (max FFT window size). + +class PitchTracker +{ +public: + PitchTracker(); + ~PitchTracker(); + bool setParameters( int sampleRate, int fftSize ); + void init() { setParameters((int)gx_jack::jack_sr, MAX_FFT_SIZE); } + void add(int count, float *input); + float tuner_estimate(); + +private: + void run(); + static void *static_run(void*); + void setEstimatedFrequency(float freq); + int find_minimum(); + int find_maximum(int l); + void start_thread(); + void copy(); + bool error; + volatile bool busy; + int tick; + sem_t m_trig; + pthread_t m_pthr; + Resampler resamp; + int m_sampleRate; + int m_fftSize; // Size of the FFT window. + float *m_buffer; // The audio buffer that stores the input signal. + int m_bufferIndex; // Index of the first empty position in the buffer. + bool m_audioLevel; // Whether or not the input level is high enough. + float *m_fftwBufferTime; // Support buffer used to store signals in the time domain. + fftwf_complex *m_fftwBufferFreq; // Support buffer used to store signals in the frequency domain. + fftwf_plan m_fftwPlanFFT; // Plan to compute the FFT of a given signal. + fftwf_plan m_fftwPlanIFFT; // Plan to compute the IFFT of a given signal (with additional zero-padding). +}; + +extern PitchTracker pitch_tracker; + +} + diff --git a/src/headers/gx_preset.h b/src/headers/gx_preset.h new file mode 100644 index 0000000..1f7fffc --- /dev/null +++ b/src/headers/gx_preset.h @@ -0,0 +1,81 @@ +/* -*- mode: C++ -*- + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the preset namespace ------- */ + +#pragma once + +// number of preset action lists +#define GX_NUM_OF_PRESET_LISTS (3) + +// preset action index +#define LOAD_PRESET_LIST (0) +#define SAVE_PRESET_LIST (1) +#define RENAME_PRESET_LIST (2) +//#define DELETE_PRESET_LIST (3) + +namespace gx_preset +{ +extern gx_gui::FileParameter gx_preset_file; + +/* function declarations */ +string gx_get_accel_path(int lindex); + +void gx_save_newpreset_dialog (GtkMenuItem*, gpointer); +void gx_save_newpreset (GtkEntry*); +void gx_save_preset (const gchar*, bool); +void gx_save_oldpreset (GtkMenuItem*, gpointer); + +void gx_save_preset_file (const gchar*, bool); +void gx_load_preset_file (const gchar*, bool); + +void gx_load_preset (GtkMenuItem*, gpointer); +void gx_recall_settings_file(const string *filename = 0); +void gx_recall_main_setting(GtkMenuItem*, gpointer); +void gx_save_main_setting(GtkMenuItem*, gpointer); + +void gx_rename_preset (GtkEntry*); +void gx_rename_preset_dialog (GtkMenuItem*, gpointer); +void gx_rename_active_preset_dialog(GtkWidget*, gpointer); + +void gx_delete_preset(GtkMenuItem*, gpointer); +void gx_delete_preset_dialog (GtkMenuItem*, gpointer); +void gx_delete_active_preset_dialog(GtkWidget*, gpointer); + +void gx_delete_all_presets_dialog(GtkMenuItem*, gpointer); +void gx_delete_all_presets(); + +void gx_add_preset_to_menus(const string&); +void gx_add_single_preset_menu_item(const string&, + const gint, + GCallback); + +void gx_refresh_preset_menus(); +void gx_cleanup_preset_name(string& presname); + +bool gx_nth_preset(unsigned char pgm); +void gx_next_preset(GtkWidget*, gpointer); +void gx_previous_preset(GtkWidget*, gpointer); + +GtkMenuItem* const gx_get_preset_item_from_name(int, const string&); + +void init(); + +/* --------------------------------------------------------------------- */ +} /* end of gx_preset namespace */ diff --git a/src/headers/gx_resampler.h b/src/headers/gx_resampler.h new file mode 100644 index 0000000..3355887 --- /dev/null +++ b/src/headers/gx_resampler.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix resampler, to use zita-resampler ------- */ + +#pragma once + +#include + +namespace gx_resample +{ + +#define MAX_UPSAMPLE 8 + +class SimpleResampler +{ +private: + Resampler r_up, r_down; + int m_fact; +public: + void setup(int sampleRate, unsigned int fact); + void up(int count, float *input, float *output); + void down(int count, float *input, float *output); +}; + +extern SimpleResampler resampTube, resampDist; + +class BufferResampler: Resampler +{ +public: + float *process(int fs_inp, int ilen, float *input, int fs_outp, int& olen); +}; + +class StreamingResampler: Resampler +{ +public: + bool setup(int srcRate, int dstRate, int nchan); + int get_max_out_size(int i_size) { return (i_size * ratio_b() + ratio_a() - 1) / ratio_a(); } + int process(int count, float *input, float *output); + int flush(float *output); // check source for max. output size +}; + +} diff --git a/src/headers/gx_sndfile.h b/src/headers/gx_sndfile.h new file mode 100644 index 0000000..c8af60b --- /dev/null +++ b/src/headers/gx_sndfile.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the SNDFILE namespace ------- */ + +#pragma once + +#include + +namespace gx_sndfile +{ +// --------------- a simple resampling status +typedef enum { + kNoError = 0, + kErrorInput = 1, + kErrorOutput = 2 +} GxResampleStatus; + +SNDFILE* openOutputSoundFile(const char*, int, int); +SNDFILE* openInputSoundFile (const char*, int*, int*, int*); +void closeSoundFile (SNDFILE*); + +sf_count_t writeSoundOutput(SNDFILE*, float*, int); +sf_count_t readSoundInput (SNDFILE*, float*, int); + +GxResampleStatus resampleSoundFile(const char*, const char*, int); + +} /* end of gx_sndfile namespace */ diff --git a/src/headers/gx_system.h b/src/headers/gx_system.h new file mode 100644 index 0000000..5e96abf --- /dev/null +++ b/src/headers/gx_system.h @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the System namespace ------- */ + +#pragma once + +#include +#include +#include + +/* constant defines */ +#define ASCII_START (48) +#define GDK_NO_MOD_MASK (GdkModifierType)0 + +enum { + JACK_INP, + JACK_OUT1, + JACK_OUT2, + JACK_MIDI, + RC_STYLE, + JACK_UUID, + LOAD_FILE, + NUM_SHELL_VAR, +}; + +namespace gx_system +{ +/* classes for reading and writing JSON files */ +class JsonException: public exception +{ +private: + string what_str; +public: + JsonException(const char* desc); + ~JsonException() throw() { } + virtual const char* what() const throw() { return what_str.c_str(); } +}; + +class JsonWriter +{ +private: + ostream &os; + bool first; + bool deferred_nl; + string indent; + void snl(bool v) { deferred_nl = v; } + void komma(); + void space(); + void iplus(); + void iminus(); +public: + JsonWriter(ostream& o); + ~JsonWriter() { close(); } + bool good() { return os.good(); } + void flush(); + void close() { if (deferred_nl) os << endl; } + void write(float v, bool nl=false); + void write(double v, bool nl=false); + void write(int i, bool nl=false); + void write(unsigned int i, bool nl=false); + void write(const char* p, bool nl=false); + void write(string s, bool nl=false) { write(s.c_str(), nl); } + void write_lit(string s, bool nl=false); + void begin_object(bool nl=false); + void end_object(bool nl=false); + void begin_array(bool nl=false); + void end_array(bool nl=false); + void write_key(const char* p, bool nl=false); + void write_key(string p, bool nl=false); + void newline() { snl(true); } +}; + +class JsonParser +{ +public: + JsonParser(istream& i); + enum token { + no_token, end_token, begin_object, end_object, begin_array, end_array, + value_string, value_number, value_key }; + static const char* token_names[]; + bool good() { return is.good(); } + token next(token expect=no_token); + token peek() { return next_tok; } + void check_expect(token expect) { if (cur_tok != expect) throw_unexpected(expect); } + inline string current_value() const { return str; } + int current_value_int() { return atoi(str.c_str()); } + float current_value_float() { istringstream b(str); float f; b >> f; return f; } + double current_value_double() { istringstream b(str); double d; b >> d; return d; } + void copy_object(JsonWriter& jw); + void skip_object(); +private: + istream& is; + int depth; + token cur_tok; + string str; + bool nl; + int next_depth; + token next_tok; + string next_str; + const char* readcode(); + string readstring(); + string readnumber(char c); + void read_next(); + void throw_unexpected(token expect); +}; + +void writeHeader(JsonWriter& jw); +bool readHeader(JsonParser& jp, int *major=0, int *minor=0); +void write_preset(JsonWriter& w, bool write_midi = true, bool force_midi = false); +void read_preset(JsonParser &jp, bool *has_midi = 0); +bool saveStateToFile( const string & filename ); +bool recallState( const string & filename ); + +// file format versions +const int majorversion = 1; +const int minorversion = 1; + +/**************************************************************** + ** Measuring times + */ + +#ifndef NDEBUG + +class Accum +{ +private: + int n; + int mn; + int mx; + float sx; + float sx2; +public: + inline void reset() { n = 0; mn = 1e9; mx = 0; sx = 0; sx2 = 0; } + void add(int diff); + int count() const { return n; } + float mean() const { return sx / n; } + float stddev() const { return sqrt((n * sx2 - sx * sx) / (n * (n-1))); } + float minimum() const { return mn; } + float maximum() const { return mx; } +}; + +inline void Accum::add(int diff) +{ + n += 1; + sx += diff; + sx2 += float(diff) * diff; + mn = min(mn, diff); + mx = max(mx, diff); +} + + +class Measure +{ +private: + Accum period; + Accum duration; + timespec t; + static int ts_diff(struct timespec ts1, struct timespec ts2); + inline float ns2ms(int n) { return n * 1e-6; } + +public: + inline void reset() { period.reset(); duration.reset(); t.tv_sec = 0; t.tv_nsec = 0; } + Measure() { reset(); } + void start_process(); + void stop_process(); + void print_accum(Accum& accum, const char* prefix, bool verbose, int total=0); + void print(bool verbose); +}; + +inline void Measure::start_process() +{ + timespec n; + clock_gettime(CLOCK_MONOTONIC, &n); + if (!(t.tv_sec == 0 and t.tv_nsec == 0)) { + period.add(ts_diff(n, t)); + } + t = n; +} + +inline void Measure::stop_process() +{ + timespec n; + clock_gettime(CLOCK_MONOTONIC, &n); + duration.add(ts_diff(n, t)); +} + +class MeasureThreadsafe +{ +private: + Measure *pmeasure; + Measure m[2]; + inline Measure *access() { return (Measure*)g_atomic_pointer_get(&pmeasure); } +public: + MeasureThreadsafe(): pmeasure(m) {} + inline void start() { access()->start_process(); } + inline void stop() { access()->stop_process(); } + void print(bool verbose=false); +}; + +extern MeasureThreadsafe measure; + +void add_time_measurement(); + +inline void measure_start() { measure.start(); } +inline void measure_stop() { measure.stop(); } + +#else + +inline void measure_start() {} +inline void measure_stop() {} + +#endif + + +/**************************************************************** + ** misc function declarations + */ + +void gx_print_logmsg (const char*, const string&, GxMsgType); +void gx_print_warning(const char*, const string&); +void gx_print_error (const char*, const string&); +void gx_print_fatal (const char*, const string&); +void gx_print_info(const char*, const string&); + +void gx_process_cmdline_options(int&, char**&, string*); +void gx_set_override_options(string* optvar); +void gx_assign_shell_var(const char*, string&); +bool gx_shellvar_exists(const string&); +int gx_system_call(const char*, + const char*, + const bool devnull = false, + const bool escape = false); +int gx_system_call(const char*, + const string&, + const bool devnull = false, + const bool escape = false); +int gx_system_call(const string&, + const char*, + const bool devnull = false, + const bool escape = false); +// int gx_system_call(const string&, +// const string&, +// const bool devnull = false, +// const bool escape = false); + +extern list jack_connection_lists[7]; + +bool gx_version_check(); +int gx_pixmap_check(); +void gx_signal_handler(int); +gboolean gx_ladi_handler(gpointer); +void gx_abort(void* arg); +void gx_log_window(GtkWidget*, gpointer); +void gx_nospace_in_name(string& presname, const char* subs = "-"); +void gx_destroy_event(); +void gx_clean_exit(GtkWidget*, gpointer); + +/* wrapper that takes an int and returns a string */ +void gx_IntToString(int i, string & s); +const string& gx_i2a(int); + +/* ---------------------------------------------------------------- */ +} /* end of gx_system namespace */ diff --git a/src/headers/gx_threads.h b/src/headers/gx_threads.h new file mode 100644 index 0000000..a4b14d3 --- /dev/null +++ b/src/headers/gx_threads.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the threads namespace ------- */ + +#pragma once + +namespace gx_threads +{ + +/* -------------- function declarations ---------------- */ +/* slow GTK threads, see GxMainInterface::run() */ +gboolean gx_update_all_gui (gpointer args); +gboolean gx_refresh_meter_level (gpointer arg); +gboolean gx_refresh_oscilloscope (gpointer args); +gboolean gx_survive_jack_shutdown (gpointer arg); +gboolean gx_monitor_jack_clients (gpointer args); +gboolean gx_do_program_change (gpointer arg); +gboolean gx_xrun_report (gpointer xdel); +/* this are the glib threads*/ + +gpointer gx_signal_helper_thread (gpointer data); +gpointer gx_program_change_helper_thread (gpointer args); + + + +/* -------- helper for level meter display -------- */ +inline float +log_meter (float db) +{ + gfloat def = 0.0f; /* Meter deflection %age */ + + if (db < -70.0f) + { + def = 0.0f; + } + else if (db < -60.0f) + { + def = (db + 70.0f) * 0.25f; + } + else if (db < -50.0f) + { + def = (db + 60.0f) * 0.5f + 2.5f; + } + else if (db < -40.0f) + { + def = (db + 50.0f) * 0.75f + 7.5f; + } + else if (db < -30.0f) + { + def = (db + 40.0f) * 1.5f + 15.0f; + } + else if (db < -20.0f) + { + def = (db + 30.0f) * 2.0f + 30.0f; + } + else if (db < 6.0f) + { + def = (db + 20.0f) * 2.5f + 50.0f; + } + else + { + def = 115.0f; + } + + /* 115 is the deflection %age that would be + when db=6.0. this is an arbitrary + endpoint for our scaling. + */ + + return def/115.0f; +} + +/* --------- calculate power (percent) to decibel -------- */ +// Note: could use fast_log10 (see ardour code) to make it faster +inline float power2db(float power) +{ + return 20.*log10(power); +} + + +} diff --git a/src/headers/gx_ui.h b/src/headers/gx_ui.h new file mode 100644 index 0000000..7011aee --- /dev/null +++ b/src/headers/gx_ui.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 the guitarix UI, it belongs to the guitarix namespace ------ */ + +#pragma once + +#include +#include + +// --- interface defines +#define stackSize 256 +#define kSingleMode 0 +#define kBoxMode 1 +#define kTabMode 2 + +namespace gx_ui +{ +/* ------------- UI Classes ------------- */ +/* base interface classes interfacing with the GUI */ +class GxUI; + +/* --- GxUiItem (virtual class) --- */ +class GxUiItem +{ +protected : + GxUI* fGUI; + float* fZone; + float fCache; + + GxUiItem (GxUI* ui, float* zone); + +public : + virtual ~GxUiItem() {} + + void modifyZone(float v); + float cache(); + virtual void reflectZone() = 0; +}; + + +/* --- Callback Item --- */ +typedef void (*GxUiCallback)(float val, void* data); + +struct GxUiCallbackItem : public GxUiItem +{ + GxUiCallback fCallback; + void* fData; + + GxUiCallbackItem(GxUI* ui, float* zone, GxUiCallback foo, void* data); + virtual void reflectZone(); +}; + +/* --- Main UI base class --- */ +class GxUI +{ + typedef list< GxUiItem* > clist; + typedef map < float*, clist* > zmap; + +private: + static list fGuiList; + zmap fZoneMap; + bool fStopped; + +public: + GxUI(); + virtual ~GxUI() {} + + // public methods + void registerZone(float*, GxUiItem*); + void updateAllZones(); + void updateZone(float* z); + static void updateAllGuis(); + + // virtual GtkTextView* const getLoggingWindow() const { return NULL; } + + virtual void addMenu() {}; + virtual void addJConvButton(const char* label, float* zone) {}; + virtual void addToggleButton(const char* label, float* zone) {}; + virtual void addPToggleButton(const char* label, float* zone) {}; + virtual void addJToggleButton(const char* label, float* zone) {}; + virtual void addCheckButton(const char* label, float* zone) {}; + virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) {}; + virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) {}; + virtual void addHorizontalWheel(const char* label, float* zone, float init, float min, float max, float step){}; + virtual void addregler(const char* label, float* zone, float init, float min, float max, float step){}; + virtual void addbigregler(const char* label, float* zone, float init, float min, float max, float step) {}; + virtual void addSpinValueBox(const char* label, float* zone, float init, float min, float max, float step){}; + virtual void addslider(const char* label, float* zone, float init, float min, float max, float step){}; + virtual void addtoggle(const char* label, int* zone){}; + virtual void addtoggle1(const char* label, float* zone){}; + virtual void addtoggle(const char* label, float* zone){}; + virtual void addbtoggle(const char* label, int* zone){}; + virtual void addbtoggle(const char* label, float* zone){}; + virtual void addRecButton(const char* label, float* zone){}; + virtual void addPlayButton(const char* label, float* zone){}; + virtual void addswitch(const char* label, int* zone){}; + virtual void addswitch(const char* label, float* zone){}; + virtual void addminiswitch(const char* label, int* zone){}; + virtual void addminiswitch(const char* label, float* zone){}; + virtual void addminieqswitch(const char* label, float* zone){}; + virtual void addminicabswitch(const char* label, int* zone){}; + virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) {}; + virtual void addNumDisplay(const char* label, float* zone) {}; + virtual void addLiveWaveDisplay(const char* label, float* zone , float* zone1) {}; + virtual void addStatusDisplay(const char* label, float* zone ) {}; + virtual void addselector(const char* label, float* zone, int maxv, const char* []){}; + + + void addCallback(float* zone, GxUiCallback foo, void* data); + + // -- widget's layouts + virtual void openHorizontalOrderBox(const char* label, float* posit){}; + virtual void openHorizontalTableBox(const char* label){}; + virtual void openHorizontalRestetBox(const char* label, float* posit){}; + virtual void openFrameBox(const char* label) {}; + virtual void openHorizontalBox(const char* label) {}; + virtual void openHorizontalhideBox(const char* label) {}; + virtual void openVerticalBox(const char* label) {}; + virtual void openVerticalBox1(const char* label) {}; + virtual void openSlooperBox(const char* label){}; + virtual void openFlipLabelBox(const char* = ""){}; + virtual void openVerticalSwitchBox(const char* label,int state,int wit, float* zone){}; + virtual void openVerticalMidiBox(const char* label) {}; + virtual void openDialogBox(const char* label, float* zone) {}; + virtual void openPatchInfoBox(float* zone){}; + virtual void openWarningBox(const char* label, float* zone){}; + virtual void openEventBox(const char* label) {}; + virtual void openHandleBox(const char* label) {}; + virtual void openExpanderBox(const char* label, float* zone) {}; + virtual void openTabBox(const char* label) {}; + virtual void openSpaceBox(const char* label){}; + virtual void openAmpBox(const char* label){}; + virtual void openPlugBox(const char* label){}; + virtual void openpaintampBox(const char* label){}; + virtual void openPaintBox(const char* label){}; + virtual void openPaintBox1(const char* label){}; + virtual void openPaintBox2(const char* label){}; + virtual void openScrollBox(const char* label){}; + virtual void openTextLoggingBox(const char* label) {}; + virtual void openLevelMeterBox(const char* label) {}; + virtual void openJackClientBox(const char* label) {}; + virtual void openToolBar(const char* label){}; + virtual void setSkinBox(const char* label, float* zone){}; + virtual void closeBox() {}; + + virtual void setup() {}; + virtual void show() {}; + virtual void run() {}; + + void stop() { fStopped = true; } + bool stopped() { return fStopped; } + + virtual void declare(float* zone, const char* key, const char* value) {} +}; + +} /* end of gx_ui namespace */ diff --git a/src/midi.glade b/src/midi.glade new file mode 100644 index 0000000..21c07ad --- /dev/null +++ b/src/midi.glade @@ -0,0 +1,458 @@ + + + + + + 5 + guitarix: Set MIDI Controller + False + True + mouse + True + dialog + + + True + 2 + + + + True + + + False + 2 + + + + + True + operate a MIDI controller to set the controller number + + + 3 + + + + + True + 2 + 3 + 15 + 6 + + + True + 0 + Parameter Range + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + 0 + MIDI Controller Number + + + GTK_FILL + + + + + True + 15 + + + True + True + + True + True + + + False + 0 + + + + + True + True + + True + + + False + 1 + + + + + 1 + 3 + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + True + True + + True + 4 + 1 + + + 1 + 2 + + + + + + True + 0 + + + 2 + 3 + + + + + False + 5 + 4 + + + + + True + end + + + gtk-delete + True + True + True + True + + + False + False + 0 + + + + + gtk-cancel + True + True + True + True + True + + + False + False + 1 + + + + + gtk-ok + True + True + True + True + True + True + + + False + False + 2 + + + + + False + end + 0 + + + + + + button3 + button2 + button1 + + + + + + + + + + + + + + + + + + + + + + + + 5 + guitarix: MIDI Controller + 600 + 400 + True + dialog + + + True + 2 + + + + True + <big><b>MIDI Controller</b></big> + True + + + False + 1 + + + + + True + True + never + automatic + + + True + True + liststore1 + False + 0 + + + autosize + MIDI CC + True + True + 0 + + + 1 + + + 0 + + + + + + + autosize + MIDI Name + + + True + + + 1 + + + + + + + autosize + Group + True + 2 + + + + 2 + + + + + + + autosize + Parameter + True + 3 + + + + 3 + + + + + + + autosize + Type + + + + 4 + + + + + + + autosize + Range + + + 1 + + + 5 + + + + + + + + + 1 + + + 6 + + + + + + + + + 2 + + + + + True + 11 + + + True + + + True + Edit a MIDI name to choose you own + + + False + 0 + + + + + include MIDI controllers in _presets + True + True + False + When checked, MIDI controller settings are saved into a preset. +When a preset is loaded, controller settings are changed if +this button is checked and the preset actually contains +controller settings. +MIDI controller settings are always saved and loaded with the +main session. + True + True + + + False + end + 1 + + + + + + + False + 4 + + + + + True + + + _Delete Selected + True + True + True + image1 + True + + + False + False + 0 + + + + + gtk-close + True + True + True + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + button4 + button5 + + + + True + gtk-delete + + diff --git a/src/ports.glade b/src/ports.glade new file mode 100644 index 0000000..7da624e --- /dev/null +++ b/src/ports.glade @@ -0,0 +1,641 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + guitarix port connections + 320 + dialog + + + True + 2 + + + + True + True + True + + + True + 2 + 3 + 10 + + + 150 + True + True + never + automatic + + + True + True + treestore1 + False + False + treeviewcolumn1 + 0 + + + + + + 2 + 1 + + + + + + + column + + + + 0 + + + + + + + + + 1 + 2 + + + + + 150 + True + True + never + automatic + + + True + True + treestore2 + False + False + treeviewcolumn3 + 0 + + + column + + + + 2 + 1 + + + + + + + column + + + + 0 + + + + + + + + + 1 + 2 + 1 + 2 + + + + + 150 + True + True + never + automatic + + + True + True + treestore3 + False + False + treeviewcolumn5 + 0 + + + column + + + + 2 + 1 + + + + + + + column + + + + 0 + + + + + + + + + 2 + 3 + 1 + 2 + + + + + True + 0 + 50 + <b>_Input</b> + True + True + treeview1 + + + GTK_FILL + GTK_FILL + + + + + True + 0 + 50 + <b>Output _1</b> + True + True + treeview2 + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + 0 + 50 + <b>Output _2</b> + True + True + treeview3 + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + + + True + 20 + <b>_Audio</b> + True + True + + + False + + + + + True + 2 + 2 + 10 + + + 150 + True + True + never + automatic + + + True + True + treestore7 + False + False + treeviewcolumn13 + 0 + + + column + + + + 2 + 1 + + + + + + + column + + + + 0 + + + + + + + + + 1 + 2 + + + + + 150 + True + True + never + automatic + + + True + True + treestore6 + False + False + treeviewcolumn11 + 0 + + + + + + 2 + 1 + + + + + + + column + + + + 0 + + + + + + + + + 1 + 2 + 1 + 2 + + + + + True + 0 + 50 + <b>_Output</b> + True + True + scrolledwindow7 + + + GTK_FILL + GTK_FILL + + + + + True + 0 + 50 + <b>_Input</b> + True + True + scrolledwindow6 + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + 1 + + + + + True + <b>I_nsert</b> + True + True + + + 1 + False + + + + + True + 2 + 2 + 10 + + + 150 + True + True + never + automatic + + + True + True + treestore4 + False + False + treeviewcolumn7 + 0 + + + column + + + + 2 + 1 + + + + + + + column + + + + 0 + + + + + + + + + 1 + 2 + + + + + 150 + True + True + never + automatic + + + True + True + treestore5 + False + False + treeviewcolumn9 + 0 + + + column + + + + 2 + 1 + + + + + + + column + + + + 0 + + + + + + + + + 1 + 2 + 1 + 2 + + + + + True + 0 + 50 + <b>_Input (Control)</b> + True + True + treeview4 + + + GTK_FILL + GTK_FILL + + + + + True + 0 + 50 + <b>_Output</b> + True + True + treeview5 + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + 2 + + + + + True + 20 + <b>_Midi</b> + True + True + + + 2 + False + + + + + 1 + + + + + True + end + + + gtk-close + True + True + True + True + + + False + False + 0 + + + + + False + end + 0 + + + + + + button1 + + + diff --git a/src/wscript b/src/wscript new file mode 100644 index 0000000..0c99f64 --- /dev/null +++ b/src/wscript @@ -0,0 +1,58 @@ +#! /usr/bin/env python +# encoding: utf-8 + +def configure(conf): + pass + +def build(bld): + sources = [ + 'gx_globals.cpp', + 'gx_child_process.cpp', + 'gx_engine.cpp', + 'gx_engine_midi.cpp', + 'gx_convolver.cpp', + 'gx_pitch_tracker.cpp', + 'gx_resampler.cpp', + 'gx_engine_audio.cpp', + 'gx_main_interface.cpp', + 'gx_portmap.cpp', + 'gx_paramtable.cpp', + 'gx_interface_builder.cpp', + 'gx_cairo_callbacks.cpp', + 'gx_gui_helpers.cpp', + 'gx_threads.cpp', + 'gx_jack.cpp', + 'gx_jconv_settings.cpp', + 'gx_preset.cpp', + 'gx_sndfile.cpp', + 'gx_system.cpp', + 'gx_ui.cpp', + 'GtkFastMeter.cpp', + 'GtkRegler.cpp', + 'GtkWaveView.cpp', + 'gx_main.cpp', + ] + + builder_files = [ + 'midi.glade', + 'ports.glade', + ] + prog = bld.new_task_gen('cxx', 'program') + prog.includes = ['.','..','headers'] # need ".." for config.h + prog.cxxflags= bld.env['CXXFLAGS'] + if not bld.env['ZITA_RESAMPLER']: + sources.append('zita-resampler/zita-resampler.cc') + prog.includes.append('zita-resampler') + else: + prog.lib = 'zita-resampler'; + if not bld.env['INTERN_ZITA_CONVOLVER']: + sources.append('zita-convolver/zita-convolver.cc') + prog.includes.append('zita-convolver'); + prog.source = [] + sources + prog.uselib = ['JACK', 'SNDFILE', 'GTHREAD', 'GMODULE_EXPORT', + 'GTK2', 'GTKMM', 'ZITA_CONVOLVER', 'FFTW3'] + prog.target = bld.env['BIN_NAME'] + prog.chmod=0755 + prog.install_path = bld.env['BINDIR'] + + bld.install_files(bld.env['GX_BUILDER_DIR'], builder_files, chmod=0644) diff --git a/src/zita-convolver/README b/src/zita-convolver/README new file mode 100644 index 0000000..6295f28 --- /dev/null +++ b/src/zita-convolver/README @@ -0,0 +1,8 @@ +Files in this directory are from zita-convolver by +Fons Adriaensen + +Please refer to the version official archive +http://www.kokkinizita.net/linuxaudio/ + +These files are only included to ease compilation +and installion of Guitarix. Don't modify. diff --git a/src/zita-convolver/zita-convolver.cc b/src/zita-convolver/zita-convolver.cc new file mode 100644 index 0000000..9cb45ad --- /dev/null +++ b/src/zita-convolver/zita-convolver.cc @@ -0,0 +1,896 @@ +/* + Copyright (C) 2006-2009 Fons Adriaensen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You 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 "zita-convolver.h" + + + + +Convproc::Convproc (void) : + _state (ST_IDLE), + _flags (0), + _ninp (0), + _nout (0), + _nproc (0), + _fftwopt (FFTW_ESTIMATE), + _vectopt (0) +{ + memset (_inpbuff, 0, MAXINP * sizeof (float *)); + memset (_outbuff, 0, MAXOUT * sizeof (float *)); +} + + +Convproc::~Convproc (void) +{ + cleanup (); +} + + +int Convproc::configure (unsigned int ninp, + unsigned int nout, + unsigned int maxsize, + unsigned int quantum, + unsigned int minpart, + unsigned int maxpart) +{ + unsigned int offs, npar, size, pind, i, m, n, r; + int prio; + + if (_state != ST_IDLE) return Converror::BAD_STATE; + if ( (quantum & (quantum - 1)) + || (quantum < MINQUANT) + || (quantum > MAXQUANT) + || (minpart & (minpart - 1)) + || (minpart < MINPART) + || (minpart < quantum) + || (minpart > MAXDIVIS * quantum) + || (maxpart & (maxpart - 1)) + || (maxpart > MAXPART) + || (maxpart < minpart)) return Converror::BAD_PARAM; + + cleanup (); + + prio = 0; + size = quantum; + while (size < minpart) + { + prio -= 1; + size <<= 1; + } + if (size & PMASK2) + { + n = 2; + r = 1; + } + else if (size & PMASK4) + { + n = 6; + r = 2; + } + else return Converror::BAD_PARAM; + if (minpart == quantum) n++; + + try + { + for (offs = pind = 0; offs < maxsize; pind++) + { + npar = (maxsize - offs + size - 1) / size; + if (size < maxpart) + { + m = (ninp * nout < 16) ? n : n + 2; + if (npar > m) npar = n; + } + _procs [pind].configure (prio, offs, npar, size, _fftwopt, _vectopt); + offs += size * npar; + if (offs < maxsize) + { + prio -= r; + size <<= r; + n = 6; + r = 2; + } + } + + _ninp = ninp; + _nout = nout; + _nproc = pind; + _quantum = quantum; + _minpart = minpart; + _maxpart = size; + _inpsize = 2 * size; + + for (i = 0; i < ninp; i++) _inpbuff [i] = new float [_inpsize]; + for (i = 0; i < nout; i++) _outbuff [i] = new float [_minpart]; + } + catch (...) + { + cleanup (); + return Converror::MEM_ALLOC; + } + + _state = ST_STOP; + return 0; +} + + +int Convproc::reset (void) +{ + unsigned int i; + + if (_state == ST_IDLE) return Converror::BAD_STATE; + for (i = 0; i < _ninp; i++) memset (_inpbuff [i], 0, _inpsize * sizeof (float)); + for (i = 0; i < _nout; i++) memset (_outbuff [i], 0, _minpart * sizeof (float)); + for (i = 0; i < _nproc; i++) _procs [i].reset (); + + return 0; +} + + +int Convproc::impdata_create (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int ind0, + int ind1) +{ + unsigned int j; + + if (_state != ST_STOP) return Converror::BAD_STATE; + try + { + for (j = 0; j < _nproc; j++) + { + _procs [j].impdata_create (inp, out, step, data, ind0, ind1); + } + } + catch (...) + { + cleanup (); + return Converror::MEM_ALLOC; + } + return 0; +} + + +int Convproc::impdata_update (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int ind0, + int ind1) +{ + unsigned int j; + + if (_state < ST_STOP) return Converror::BAD_STATE; + for (j = 0; j < _nproc; j++) + { + _procs [j].impdata_update (inp, out, step, data, ind0, ind1); + } + return 0; +} + + +int Convproc::impdata_copy (unsigned int inp1, + unsigned int out1, + unsigned int inp2, + unsigned int out2) +{ + unsigned int j; + + if (_state != ST_STOP) return Converror::BAD_STATE; + try + { + for (j = 0; j < _nproc; j++) + { + _procs [j].impdata_copy (inp1, out1, inp2, out2); + } + } + catch (...) + { + cleanup (); + return Converror::MEM_ALLOC; + } + + return 0; +} + + +int Convproc::start_process (int maxprio, int schclass) +{ + unsigned int k; + + if (_state != ST_STOP) return Converror::BAD_STATE; + + _flags = 0; + _inpoffs = 0; + _outoffs = 0; + _procdel = 0; + _state = ST_PROC; + + for (k = 0; k < _nproc; k++) + { + _procs [k]._inpsize = _inpsize; + _procs [k]._outsize = _minpart; + _procs [k]._inpbuff = _inpbuff; + _procs [k]._outbuff = _outbuff; + } + + reset (); + + for (k = (_minpart == _quantum) ? 1 : 0; k < _nproc; k++) + { + _procs [k].start (maxprio, schclass); + } + + return 0; +} + + +int Convproc::stop_process (void) +{ + unsigned int k; + + if (_state != ST_PROC) return Converror::BAD_STATE; + + _state = ST_WAIT; + for (k = 0; k < _nproc; k++) _procs [k].stop (); + check (); + + return 0; +} + + +int Convproc::cleanup (void) +{ + unsigned int k; + + if (_state != ST_STOP) return Converror::BAD_STATE; + + for (k = 0; k < _ninp; k++) delete[] _inpbuff [k]; + for (k = 0; k < _nout; k++) delete[] _outbuff [k]; + for (k = 0; k < _nproc; k++) _procs [k].cleanup (); + memset (_inpbuff, 0, MAXINP * sizeof (float *)); + memset (_outbuff, 0, MAXOUT * sizeof (float *)); + + _ninp = 0; + _nout = 0; + _nproc = 0; + _minpart = 0; + _inpsize = 0; + _state = ST_IDLE; + + return 0; +} + + +void Convproc::process (bool skip) +{ + unsigned int f, k; + + if (_state != ST_PROC) return; + + _inpoffs += _quantum; + if (_inpoffs == _inpsize) _inpoffs = 0; + + _outoffs += _quantum; + if (_outoffs == _minpart) + { + _outoffs = f = 0; + for (k = 0; k < _nout; k++) memset (_outbuff [k], 0, _minpart * sizeof (float)); + for (k = 0; k < _nproc; k++) f |= _procs [k].readout (skip); + if (f) + { + _flags |= f; + if (++_procdel >= 3) + { + stop_process (); + _flags = FL_LOAD; + } + } + else _procdel = 0; + } +} + + +void Convproc::check (void) +{ + unsigned int k; + + for (k = 0; (k < _nproc) && _procs [k].idle (); k++); + if (k == _nproc) _state = ST_STOP; +} + + +void Convproc::print (void) +{ + unsigned int k; + + for (k = 0; k < _nproc; k++) _procs [k].print (); +} + + + +typedef float FV4 __attribute__ ((vector_size(16))); + + +Convlevel::Convlevel (void) : + _stat (ST_IDLE), + _npar (0), + _parsize (0), + _vectopt (0), + _pthr (0), + _inp_list (0), + _out_list (0), + _plan_r2c (0), + _plan_c2r (0), + _time_data (0), + _prep_data (0), + _freq_data (0) +{ +} + + +Convlevel::~Convlevel (void) +{ + cleanup (); +} + + +void *Convlevel::alloc_aligned (size_t size) +{ + void *p; + + if (posix_memalign (&p, 16, size)) throw (Converror (Converror::MEM_ALLOC)); + memset (p, 0, size); + return p; +} + + +void Convlevel::configure (int prio, + unsigned int offs, + unsigned int npar, + unsigned int parsize, + unsigned int fftwopt, + unsigned int vectopt) +{ + _prio = prio; + _offs = offs; + _npar = npar; + _parsize = parsize; + _vectopt = vectopt; + + _time_data = (float *)(alloc_aligned (2 * _parsize * sizeof (float))); + _prep_data = (float *)(alloc_aligned (2 * _parsize * sizeof (float))); + _freq_data = (fftwf_complex *)(alloc_aligned ((_parsize + 1) * sizeof (fftwf_complex))); + _plan_r2c = fftwf_plan_dft_r2c_1d (2 * _parsize, _time_data, _freq_data, fftwopt); + _plan_c2r = fftwf_plan_dft_c2r_1d (2 * _parsize, _freq_data, _time_data, fftwopt); + if (_plan_r2c && _plan_c2r) return; + throw (Converror (Converror::MEM_ALLOC)); +} + + +void Convlevel::impdata_create (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int i0, + int i1) +{ + unsigned int k; + int j, j0, j1, n; + float norm; + fftwf_complex *fftb; + Macnode *M; + + n = i1 - i0; + i0 = _offs - i0; + i1 = i0 + _npar * _parsize; + if ((i0 >= n) || (i1 <= 0)) return; + + M = findmacnode (inp, out, true); + if (! (M->_fftb)) + { + M->_fftb = new fftwf_complex * [_npar]; + memset (M->_fftb, 0, _npar * sizeof (fftwf_complex *)); + } + + norm = 0.5f / _parsize; + for (k = 0; k < _npar; k++) + { + i1 = i0 + _parsize; + if ((i0 < n) && (i1 > 0)) + { + if (! (M->_fftb [k])) + { + M->_fftb [k] = (fftwf_complex *)(alloc_aligned ((_parsize + 1) * sizeof (fftwf_complex))); + } + memset (_prep_data, 0, 2 * _parsize * sizeof (float)); + j0 = (i0 < 0) ? 0 : i0; + j1 = (i1 > n) ? n : i1; + for (j = j0; j < j1; j++) _prep_data [j - i0] = norm * data [j * step]; + fftwf_execute_dft_r2c (_plan_r2c, _prep_data, _freq_data); +#ifdef VECTORIZE + if (_vectopt) fftswap (_freq_data); +#endif + fftb = M->_fftb [k]; + for (j = 0; j <= (int)_parsize; j++) + { + fftb [j][0] += _freq_data [j][0]; + fftb [j][1] += _freq_data [j][1]; + } + } + i0 = i1; + } +} + + +void Convlevel::impdata_update (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int i0, + int i1) +{ + unsigned int k; + int j, j0, j1, n; + float norm; + fftwf_complex *fftb; + Macnode *M; + + M = findmacnode (inp, out, false); + if (! M) return; + + n = i1 - i0; + i0 = _offs - i0; + i1 = i0 + _npar * _parsize; + if ((i0 >= n) || (i1 <= 0)) return; + + norm = 0.5f / _parsize; + for (k = 0; k < _npar; k++) + { + i1 = i0 + _parsize; + fftb = M->_fftb [k]; + if (fftb && (i0 < n) && (i1 > 0)) + { + memset (_prep_data, 0, 2 * _parsize * sizeof (float)); + j0 = (i0 < 0) ? 0 : i0; + j1 = (i1 > n) ? n : i1; + for (j = j0; j < j1; j++) _prep_data [j - i0] = norm * data [j * step]; + fftwf_execute_dft_r2c (_plan_r2c, _prep_data, fftb); +#ifdef VECTORIZE + if (_vectopt) fftswap (fftb); +#endif + } + i0 = i1; + } +} + + +void Convlevel::impdata_copy (unsigned int inp1, + unsigned int out1, + unsigned int inp2, + unsigned int out2) +{ + Macnode *M1; + Macnode *M2; + + M1 = findmacnode (inp1, out1, false); + if (! M1) return; + M2 = findmacnode (inp2, out2, true); + if (M2->_fftb) return; + M2->_fftb = M1->_fftb; + M2->_copy = true; +} + + +void Convlevel::reset (void) +{ + unsigned int i; + Inpnode *X; + Outnode *Y; + + for (X = _inp_list; X; X = X->_next) + { + for (i = 0; i < _npar; i++) + { + memset (X->_ffta [i], 0, (_parsize + 1) * sizeof (fftwf_complex)); + } + } + for (Y = _out_list; Y; Y = Y->_next) + { + for (i = 0; i < 3; i++) + { + memset (Y->_buff [i], 0, _parsize * sizeof (float)); + } + } + if (_parsize == _outsize) + { + _outoffs = 0; + _inpoffs = 0; + } + else + { + _outoffs = _parsize / 2; + _inpoffs = _inpsize - _outoffs; + } + _bits = _parsize / _outsize; + _late = 0; + _ipar = 0; + _opi1 = 0; + _opi2 = 1; + _opi3 = 2; + sem_init (&_trig, 0, 0); +} + + +void Convlevel::start (int priority, int schclass) +{ + int min, max; + pthread_attr_t attr; + struct sched_param parm; + + _pthr = 0; + min = sched_get_priority_min (schclass); + max = sched_get_priority_max (schclass); + priority += _prio; + if (priority > max) priority = max; + if (priority < min) priority = min; + parm.sched_priority = priority; + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setschedpolicy (&attr, schclass); + pthread_attr_setschedparam (&attr, &parm); + pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setstacksize (&attr, 0x10000); + pthread_create (&_pthr, &attr, static_main, this); + pthread_attr_destroy (&attr); +} + + +void Convlevel::stop (void) +{ + if (_stat != ST_IDLE) + { + _stat = ST_TERM; + sem_post (&_trig); + } +} + + +void Convlevel::cleanup (void) +{ + unsigned int i; + Inpnode *X, *X1; + Outnode *Y, *Y1; + Macnode *M, *M1; + + X = _inp_list; + while (X) + { + for (i = 0; i < _npar; i++) free (X->_ffta [i]); + delete[] X->_ffta; + X1 = X->_next; + delete X; + X = X1; + } + _inp_list = 0; + + Y = _out_list; + while (Y) + { + M = Y->_list; + while (M) + { + if ((M->_fftb) && !(M->_copy)) + { + for (i = 0; i < _npar; i++) + { + free (M->_fftb [i]); + } + delete[] M->_fftb; + } + M1 = M->_next; + delete M; + M = M1; + } + for (i = 0; i < 3; i++) free (Y->_buff [i]); + Y1 = Y->_next; + delete Y; + Y = Y1; + } + _out_list = 0; + + fftwf_destroy_plan (_plan_r2c); + fftwf_destroy_plan (_plan_c2r); + free (_time_data); + free (_prep_data); + free (_freq_data); + _plan_r2c = 0; + _plan_c2r = 0; + _time_data = 0; + _prep_data = 0; + _freq_data = 0; +} + + +void *Convlevel::static_main (void *arg) +{ + ((Convlevel *) arg)->main (); + return 0; +} + + +void Convlevel::main (void) +{ + _stat = ST_PROC; + while (true) + { + sem_wait (&_trig); + if (_stat == ST_TERM) + { + _stat = ST_IDLE; + _pthr = 0; + return; + } + process (false); + } +} + + +void Convlevel::process (bool skip) +{ + unsigned int i, j, k; + unsigned int i1, n1, n2; + + Inpnode *X; + Macnode *M; + Outnode *Y; + fftwf_complex *ffta; + fftwf_complex *fftb; + float *inpd; + float *outd; + + i1 = _inpoffs; + n1 = _parsize; + n2 = 0; + _inpoffs = i1 + n1; + if (_inpoffs >= _inpsize) + { + _inpoffs -= _inpsize; + n2 = _inpoffs; + n1 -= n2; + } + + for (X = _inp_list; X; X = X->_next) + { + inpd = _inpbuff [X->_inp]; + if (n1) memcpy (_time_data, inpd + i1, n1 * sizeof (float)); + if (n2) memcpy (_time_data + n1, inpd, n2 * sizeof (float)); + memset (_time_data + _parsize, 0, _parsize * sizeof (float)); + fftwf_execute_dft_r2c (_plan_r2c, _time_data, X->_ffta [_ipar]); +#ifdef VECTORIZE + if (_vectopt) fftswap (X->_ffta [_ipar]); +#endif + } + + if (skip) + { + for (Y = _out_list; Y; Y = Y->_next) + { + outd = Y->_buff [_opi3]; + memset (outd, 0, _parsize * sizeof (float)); + } + } + else + { + for (Y = _out_list; Y; Y = Y->_next) + { + memset (_freq_data, 0, (_parsize + 1) * sizeof (fftwf_complex)); + for (M = Y->_list; M; M = M->_next) + { + X = M->_inpn; + i = _ipar; + for (j = 0; j < _npar; j++) + { + ffta = X->_ffta [i]; + fftb = M->_fftb [j]; + if (fftb) + { +#ifdef VECTORIZE + if (_vectopt) + { + FV4 *A = (FV4 *) ffta; + FV4 *B = (FV4 *) fftb; + FV4 *D = (FV4 *) _freq_data; + for (k = 0; k < _parsize; k += 4) + { + D [0] += A [0] * B [0] - A [1] * B [1]; + D [1] += A [0] * B [1] + A [1] * B [0]; + A += 2; + B += 2; + D += 2; + } + _freq_data [_parsize][0] += ffta [_parsize][0] * fftb [_parsize][0]; + _freq_data [_parsize][1] = 0; + } + else +#endif + { + for (k = 0; k <= _parsize; k++) + { + _freq_data [k][0] += ffta [k][0] * fftb [k][0] - ffta [k][1] * fftb [k][1]; + _freq_data [k][1] += ffta [k][0] * fftb [k][1] + ffta [k][1] * fftb [k][0]; + } + } + } + if (i == 0) i = _npar; + i--; + } + } + +#ifdef VECTORIZE + if (_vectopt) fftswap (_freq_data); +#endif + fftwf_execute_dft_c2r (_plan_c2r, _freq_data, _time_data); + outd = Y->_buff [_opi2]; + for (k = 0; k < _parsize; k++) outd [k] += _time_data [k]; + outd = Y->_buff [_opi3]; + memcpy (outd, _time_data + _parsize, _parsize * sizeof (float)); + } + } + + _ipar++; + if (_ipar == _npar) _ipar = 0; +} + + +int Convlevel::readout (bool skip) +{ + unsigned int k; + Outnode *Y; + float *p, *q; + + _outoffs += _outsize; + if (_outoffs == _parsize) + { + _outoffs = 0; + if (_stat == ST_PROC) + { + k = _opi1; + _opi1 = _opi2; + _opi2 = _opi3; + _opi3 = k; + sem_getvalue (&_trig, &_late); + sem_post (&_trig); + } + else + { + process (skip); + k = _opi1; + _opi1 = _opi2; + _opi2 = _opi3; + _opi3 = k; + } + } + + if (! skip) + { + for (Y = _out_list; Y; Y = Y->_next) + { + p = Y->_buff [_opi1] + _outoffs; + q = _outbuff [Y->_out]; + for (k = 0; k < _outsize; k++) q [k] += p [k]; + } + } + + return _late ? _bits : 0; +} + + +void Convlevel::print (void) +{ + printf ("prio = %4d, offs = %6d, parsize = %5d, npar = %3d\n", _prio, _offs, _parsize, _npar); +} + + +Macnode *Convlevel::findmacnode (unsigned int inp, unsigned int out, bool create) +{ + unsigned int i; + Inpnode *X; + Outnode *Y; + Macnode *M; + + for (X = _inp_list; X && (X->_inp != inp); X = X->_next); + if (! X) + { + if (! create) return 0; + X = new Inpnode; + X->_next = _inp_list; + _inp_list = X; + X->_inp = inp; + X->_ffta = new fftwf_complex * [_npar]; + memset (X->_ffta, 0, _npar * sizeof (fftw_complex *)); + for (i = 0; i < _npar; i++) + { + X->_ffta [i] = (fftwf_complex *)(alloc_aligned ((_parsize + 1) * sizeof (fftwf_complex))); + } + } + + for (Y = _out_list; Y && (Y->_out != out); Y = Y->_next); + if (! Y) + { + if (! create) return 0; + Y = new Outnode; + Y->_next = _out_list; + _out_list = Y; + Y->_out = out; + Y->_list = 0; + for (i = 0; i < 3; i++) + { + Y->_buff [i] = 0; + } + for (i = 0; i < 3; i++) + { + Y->_buff [i] = (float *)(alloc_aligned (_parsize * sizeof (float))); + } + } + + for (M = Y->_list; M && (M->_inpn != X); M = M->_next); + if (! M) + { + if (! create) return 0; + M = new Macnode; + M->_next = Y->_list; + Y->_list = M; + M->_inpn = X; + M->_fftb = 0; + M->_copy = false; + } + + return M; +} + + +#ifdef VECTORIZE + +void Convlevel::fftswap (fftwf_complex *p) +{ + unsigned int n = _parsize; + float a, b; + + while (n) + { + a = p [2][0]; + b = p [3][0]; + p [2][0] = p [0][1]; + p [3][0] = p [1][1]; + p [0][1] = a; + p [1][1] = b; + p += 4; + n -= 4; + } +} + +#endif + + diff --git a/src/zita-convolver/zita-convolver.h b/src/zita-convolver/zita-convolver.h new file mode 100644 index 0000000..cbc1e54 --- /dev/null +++ b/src/zita-convolver/zita-convolver.h @@ -0,0 +1,304 @@ +/* + Copyright (C) 2006-2009 Fons Adriaensen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You 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 _ZITA_CONVOLVER_H +#define _ZITA_CONVOLVER_H + +#define ZITA_CONVOLVER_MAJOR_VERSION 2 + +#include +#include +#include + + +class Inpnode +{ +private: + + friend class Convlevel; + + Inpnode *_next; + fftwf_complex **_ffta; + unsigned int _inp; +}; + + +class Macnode +{ +private: + + friend class Convlevel; + + Macnode *_next; + Inpnode *_inpn; + fftwf_complex **_fftb; + bool _copy; +}; + + +class Outnode +{ +private: + + friend class Convlevel; + + Outnode *_next; + Macnode *_list; + float *_buff [3]; + unsigned int _out; +}; + + +class Converror +{ +public: + + enum + { + BAD_STATE = -1, + BAD_PARAM = -2, + MEM_ALLOC = -3 + }; + +private: + + friend class Convlevel; + friend class Convproc; + + Converror (int error) : _error (error) {} + + int _error; +}; + + +class Convlevel +{ +private: + + friend class Convproc; + + enum { ST_IDLE, ST_TERM, ST_PROC }; + + Convlevel (void); + ~Convlevel (void); + + void *alloc_aligned (size_t size); + void start (int priority, int schclass); + void stop (void); + void configure (int prio, + unsigned int offs, + unsigned int npar, + unsigned int parsize, + unsigned int fftwopt, + unsigned int vectopt); + void impdata_create (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int ind0, + int ind1); + void impdata_update (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int ind0, + int ind1); + void impdata_copy (unsigned int inp1, + unsigned int out1, + unsigned int inp2, + unsigned int out2); + void reset (void); + void cleanup (void); + int readout (bool skip); + void fftswap (fftwf_complex *p); + bool idle (void) const { return _stat == ST_IDLE; } + void print (void); + + static void *static_main (void *arg); + void main (void); + void process (bool skip); + Macnode *findmacnode (unsigned int inp, unsigned int out, bool create); + + volatile unsigned int _stat; // current processing state + + int _prio; // relative priority + unsigned int _offs; // offset from start of impulse response + unsigned int _npar; // number of partitions + unsigned int _parsize; // partition and outbut buffer size + unsigned int _outsize; // step size for output buffer + unsigned int _outoffs; // offset into output buffer + unsigned int _inpsize; // size of shared input buffer + unsigned int _inpoffs; // offset into input buffer + unsigned int _vectopt; // vector optimisation options + unsigned int _ipar; // rotating partition index + unsigned int _opi1; // rotating output buffer indices + unsigned int _opi2; + unsigned int _opi3; + int _bits; + int _late; + pthread_t _pthr; + sem_t _trig; + + Inpnode *_inp_list; + Outnode *_out_list; + fftwf_plan _plan_r2c; + fftwf_plan _plan_c2r; + float *_time_data; + float *_prep_data; + fftwf_complex *_freq_data; + float **_inpbuff; + float **_outbuff; +}; + + +class Convproc +{ +public: + + Convproc (void); + ~Convproc (void); + + enum + { + ST_IDLE, + ST_STOP, + ST_WAIT, + ST_PROC + }; + + enum + { + FL_LATE = 0x0000FFFF, + FL_LOAD = 0x01000000 + }; + + enum + { + MAXINP = 64, + MAXOUT = 64, + MINPART = 64, + MAXPART = 8192, + MAXDIVIS = 16, + MINQUANT = 16, + MAXQUANT = 8192 + }; + + float *inpdata (unsigned int inp) + { + return _inpbuff [inp] + _inpoffs; + } + + float *outdata (unsigned int out) + { + return _outbuff [out] + _outoffs; + } + + unsigned int state (void) const + { + return _state; + } + + unsigned int flags (void) + { + unsigned int f = _flags; + _flags = 0; + return f; + } + + void set_fftwopt (unsigned int fftwopt) + { + _fftwopt = fftwopt; + } + + void set_vectopt (unsigned int vectopt) + { + _vectopt = vectopt; + } + + int configure (unsigned int ninp, + unsigned int nout, + unsigned int maxsize, + unsigned int quantum, + unsigned int minpart, + unsigned int maxpart); + + int impdata_create (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int ind0, + int ind1); + + int impdata_update (unsigned int inp, + unsigned int out, + unsigned int step, + float *data, + int ind0, + int ind1); + + int impdata_copy (unsigned int inp1, + unsigned int out1, + unsigned int inp2, + unsigned int out2); + + int reset (void); + + int start_process (int priority, int schclass = SCHED_FIFO); + + int stop_process (void); + + int cleanup (void); + + void check (void); + + void print (void); + + void process (bool skip = false); + +private: + + enum + { + NPROC = 5, + PMASK2 = 0x1540, + PMASK4 = 0x2A80 + }; + + unsigned int _state; + unsigned int _flags; + unsigned int _ninp; + unsigned int _nout; + unsigned int _nproc; + unsigned int _quantum; + unsigned int _minpart; + unsigned int _maxpart; + unsigned int _inpsize; + unsigned int _inpoffs; + unsigned int _outoffs; + unsigned int _fftwopt; + unsigned int _vectopt; + unsigned int _procdel; + Convlevel _procs [NPROC]; + float *_inpbuff [MAXINP]; + float *_outbuff [MAXOUT]; +}; + + +#endif + diff --git a/src/zita-resampler/README b/src/zita-resampler/README new file mode 100644 index 0000000..d303ccb --- /dev/null +++ b/src/zita-resampler/README @@ -0,0 +1,8 @@ +Files in this directory are from zita-resampler by +Fons Adriaensen + +Please refer to the version official archive +http://www.kokkinizita.net/linuxaudio/ + +These files are only included to ease compilation +and installion of Guitarix. Don't modify. diff --git a/src/zita-resampler/zita-resampler.cc b/src/zita-resampler/zita-resampler.cc new file mode 100644 index 0000000..3a536ca --- /dev/null +++ b/src/zita-resampler/zita-resampler.cc @@ -0,0 +1,360 @@ +//--------------------------------------------------------------------------------- +// +// Copyright (C) 2007 Fons Adriaensen +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You 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 "zita-resampler.h" + + +Resampler_table *Resampler_table::_list = 0; +Resampler_mutex Resampler_table::_mutex; + + +Resampler_table::Resampler_table (unsigned int ra, + unsigned int rb, + unsigned int hl, + unsigned int fr) : + _next (0), + _refc (0), + _ra (ra), + _rb (rb), + _hl (hl), + _fr (fr) +{ + unsigned int i, j; + double s, t, w; + float *p; + + _ctab = new float [hl * (rb + 1)]; + p = _ctab; + s = (double) rb / (double) ra; + w = 1e-4 * fr; + if (s < 1.0) w *= s; + for (j = 0; j <= rb; j++) + { + t = (double) j / (double) rb; + for (i = 0; i < hl; i++) + { + p [hl - i - 1] = (float)(w * sinc (t * w) * wind (t / hl)); + t += 1; + } + p += hl; + } +} + + +Resampler_table::~Resampler_table (void) +{ + delete[] _ctab; +} + + +double Resampler_table::sinc (double x) +{ + x = fabs (x); + if (x < 1e-6) return 1.0; + x *= M_PI; + return sin (x) / x; +} + + +double Resampler_table::wind (double x) +{ + x = fabs (x); + if (x >= 1.0) return 0.0f; + x *= M_PI; + return 0.384 + 0.500 * cos (x) + 0.116 * cos (2 * x); +} + + +Resampler_table *Resampler_table::create (unsigned int ra, + unsigned int rb, + unsigned int hl, + unsigned int fr) +{ + Resampler_table *P; + + _mutex.lock (); + P = _list; + while (P) + { + if ((ra == P->_ra) && (rb == P->_rb) && (hl == P->_hl) && (fr == P->_fr)) + { + P->_refc++; + _mutex.unlock (); + return P; + } + P = P->_next; + } + P = new Resampler_table (ra, rb, hl, fr); + P->_refc = 1; + P->_next = _list; + _list = P; + _mutex.unlock (); + return P; +} + + +void Resampler_table::destroy (Resampler_table *T) +{ + Resampler_table *P, *Q; + + _mutex.lock (); + if (T) + { + T->_refc--; + if (T->_refc == 0) + { + P = _list; + Q = 0; + while (P) + { + if (P == T) + { + if (Q) Q->_next = T->_next; + else _list = T->_next; + break; + } + Q = P; + P = P->_next; + } + delete T; + } + } + _mutex.unlock (); +} + + +void Resampler_table::print_list (void) +{ + Resampler_table *P; + + printf ("Resampler table\n----\n"); + for (P = _list; P; P = P->_next) + { + printf ("refc = %3d ra = %5d rb = %5d hl = %3d\n", P->_refc, P->_ra, P->_rb, P->_hl); + } + printf ("----\n\n"); +} + + + + +Resampler::Resampler (void) : + _table (0), + _buff (0), + _nchan (0) +{ + reset (); +} + + +Resampler::~Resampler (void) +{ + clear (); +} + + +void Resampler::clear (void) +{ + Resampler_table::destroy (_table); + delete[] _buff; + _buff = 0; + _table = 0; + _nchan = 0; + reset (); +} + + +int Resampler::setup (unsigned int fs_inp, + unsigned int fs_out, + unsigned int nchan, + unsigned int hlen) +{ + if ((hlen < 16) || (hlen > 96)) return 1; + return setup (fs_inp, fs_out, nchan, hlen, 10000 - 26000 / hlen); +} + + +int Resampler::setup (unsigned int fs_inp, + unsigned int fs_out, + unsigned int nchan, + unsigned int hlen, + unsigned int freq) +{ + unsigned int a, b, h, k = 0; + float *B = 0; + Resampler_table *T = 0; + + if (fs_inp && fs_out && nchan) + { + k = gcd (fs_inp, fs_out); + a = fs_inp / k; + b = fs_out / k; + if ((16 * a >= b) && (b <= 1000)) + { + h = hlen; + k = 250; + if (a > b) + { + h = (h * a + b - 1) / b; + k = (k * a + b - 1) / b; + } + T = Resampler_table::create (a, b, h, freq); + B = new float [nchan * (2 * h - 1 + k)]; + } + } + clear (); + if (T) + { + _table = T; + _buff = B; + _nchan = nchan; + _inmax = k; + return reset (); + } + else return 1; +} + + +int Resampler::reset (void) +{ + if (!_table) return 1; + + inp_count = 0; + out_count = 0; + inp_data = 0; + out_data = 0; + _index = 0; + _nread = 2 * _table->_hl; + _phase = 0; + return 0; +} + + +int Resampler::process (void) +{ + unsigned int hl, ra, rb, in, nr, ph, i, n, c; + float *p1, *p2; + + if (!_table) return 1; + + hl = _table->_hl; + ra = _table->_ra * hl; + rb = _table->_rb * hl; + in = _index; + nr = _nread; + ph = _phase; + n = (2 * hl - nr) * _nchan; + p1 = _buff + in * _nchan; + p2 = p1 + n; + + while (out_count) + { + if (nr) + { + if (inp_count == 0) break; + if (inp_data) + { + for (c = 0; c < _nchan; c++) p2 [c] = inp_data [c]; + inp_data += _nchan; + } + else + { + for (c = 0; c < _nchan; c++) p2 [c] = 0; + } + nr--; + p2 += _nchan; + inp_count--; + } + else + { + if (out_data) + { + float *c1 = _table->_ctab + ph; + float *c2 = _table->_ctab + rb - ph; + for (c = 0; c < _nchan; c++) + { + float *q1 = p1 + c; + float *q2 = p2 + c; + float s = 1e-20f; + for (i = 0; i < hl; i++) + { + q2 -= _nchan; + s += *q1 * c1 [i] + *q2 * c2 [i]; + q1 += _nchan; + } + *out_data++ = s - 1e-20f; + } + } + out_count--; + ph += ra; + if (ph >= rb) + { + nr = ph / rb; + ph -= nr * rb; + in += nr; + p1 += nr * _nchan;; + if (in >= _inmax) + { + n = (2 * hl - nr) * _nchan; + memcpy (_buff, p1, n * sizeof (float)); + in = 0; + p1 = _buff; + p2 = p1 + n; + } + } + } + } + + _index = in; + _nread = nr; + _phase = ph; + + return 0; +} + + +unsigned int Resampler::gcd (unsigned int a, unsigned int b) +{ + if (a == 0) return b; + if (b == 0) return a; + while (1) + { + if (a > b) + { + a = a % b; + if (a == 0) return b; + if (a == 1) return 1; + } + else + { + b = b % a; + if (b == 0) return a; + if (b == 1) return 1; + } + } + return 1; +} + + diff --git a/src/zita-resampler/zita-resampler.h b/src/zita-resampler/zita-resampler.h new file mode 100644 index 0000000..71164c4 --- /dev/null +++ b/src/zita-resampler/zita-resampler.h @@ -0,0 +1,113 @@ +//--------------------------------------------------------------------------------- +// +// Copyright (C) 2007 Fons Adriaensen +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You 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 __RESAMPLER_H +#define __RESAMPLER_H + +#include // for abort() +#include + +class Resampler_mutex +{ +private: + + friend class Resampler_table; + + Resampler_mutex (void) { if (pthread_mutex_init (&_mutex, 0)) abort (); } + ~Resampler_mutex (void) { pthread_mutex_destroy (&_mutex); } + void lock (void) { if (pthread_mutex_lock (&_mutex)) abort (); } + void unlock (void){ if (pthread_mutex_unlock (&_mutex)) abort (); } + + pthread_mutex_t _mutex; +}; + + +class Resampler_table +{ +public: + + static void print_list (void); + +private: + + Resampler_table (unsigned int ra, unsigned int rb, unsigned int hl, unsigned int fr); + ~Resampler_table (void); + + friend class Resampler; + + Resampler_table *_next; + unsigned int _refc; + float *_ctab; + unsigned int _ra; + unsigned int _rb; + unsigned int _hl; + unsigned int _fr; + + double sinc (double x); + double wind (double x); + + static Resampler_table *create (unsigned int ra, unsigned int rb, unsigned int hl, unsigned int fr); + static void destroy (Resampler_table *T); + + static Resampler_table *_list; + static Resampler_mutex _mutex; +}; + + + +class Resampler +{ +public: + + Resampler (void); + ~Resampler (void); + + int setup (unsigned int fs_inp, unsigned int fs_out, unsigned int nchan, unsigned int hlen); + int setup (unsigned int fs_inp, unsigned int fs_out, unsigned int nchan, unsigned int hlen, unsigned int freq); + void clear (void); + int reset (void); + int nchan (void) { return _nchan; } + int ratio_a (void) { return _table ? _table->_ra : 0; } + int ratio_b (void) { return _table ? _table->_rb : 0; } + int filtlen (void) { return _table ? (2 * _table->_hl) : 0; } + int process (void); + + unsigned int inp_count; + unsigned int out_count; + float *inp_data; + float *out_data; + +private: + + unsigned int gcd (unsigned int a, unsigned int b); + + Resampler_table *_table; + float *_buff; + unsigned int _nchan; + unsigned int _inmax; + unsigned int _index; + unsigned int _nread; + unsigned int _phase; +}; + + + +#endif diff --git a/tools/convert-0.06-format b/tools/convert-0.06-format new file mode 100644 index 0000000..7888983 --- /dev/null +++ b/tools/convert-0.06-format @@ -0,0 +1,297 @@ +#! /usr/bin/env python +import os +try: + import json +except ImportError: + raise SystemExit, "please install package python-simplejson" + +non_preset = set(( + "jconv.expander", + "crybaby.dialog", + "compressor.dialog", + "jconv.dialog", + "ui.skin", + "chorus.dialog", + "system.midistat", + "ui.main_expander", + "distortion.dialog", + "midi_out.dialog", + "IR.dialog", + "ui.latency_nowarn", + "system.waveview", + "jconv.filedialog", + "system.fConsta1t", + "freeverb.dialog", + )) + +old_vars = [ + "amp.feedback", + "amp.tone.treble", + "amp.tone.middle", + "preamp.on_off", + "amp.in_level", + "distortion.trigger", + "distortion.vibrato", + "distortion.low_highpass.low_freq", + "distortion.low_highpass.high_freq", + "distortion.low_highpass.on_off", + "distortion.low_highcutoff.high_freq", + "distortion.low_highcutoff.low_freq", + "distortion.low_highcutoff.on_off", + "distortion.level", + "distortion.drive", + "distortion.gain", + "distortion.on_off", + "crybaby.wah", + "crybaby.level", + "crybaby.wet_dry", + "crybaby.on_off", + "freeverb.wet_dry", + "freeverb.damp", + "freeverb.RoomSize", + "freeverb.on_off", + "amp.out_master", + "echo.time", + "echo.percent", + "echo.on_off", + "IR.bandwidth", + "IR.freq", + "IR.peak", + "IR.on_off", + "amp.feedforward", + "jconv.wet_dry", + "amp.balance", + "ui.main_expander", + "jconv.expander", + "jconv.filedialog", + "distortion.dialog", + "freeverb.dialog", + "IR.dialog", + "crybaby.dialog", + "midi_out.dialog", + "system.fConsta1t", + "midi_out.channel_1.velocity", + "midi_out.channel_1.sensity", + "midi_out.channel_1.oktave", + "midi_out.channel_1.channel", + "midi_out.channel_1.program", + "midi_out.channel_2.velocity", + "midi_out.channel_2.sensity", + "midi_out.channel_2.oktave", + "midi_out.channel_2.channel", + "midi_out.channel_2.program", + "midi_out.channel_2.on_off", + "beat_detector.note_off", + "beat_detector.beat_gain", + "beat_detector.stepper", + "midi_out.channel_3.velocity", + "midi_out.channel_3.sensity", + "midi_out.channel_3.oktave", + "midi_out.channel_3.program", + "midi_out.channel_3.channel", + "midi_out.channel_3.on_off", + "beat_detector.atack_gain", + "system.midistat", + "midi_out.channel_1.volume", + "midi_out.channel_2.volume", + "midi_out.channel_3.volume", + "midi_out.channel_1.auto_pitch", + "midi_out.channel_2.auto_pitch", + "midi_out.channel_3.auto_pitch", + "compressor.threshold", + "compressor.attack", + "compressor.release", + "compressor.knee", + "compressor.ratio", + "compressor.dialog", + "compressor.on_off", + "overdrive.drive", + "overdrive.on_off", + "system.waveview", + "anti_aliase.on_off", + "anti_aliase.feedback", + "tube.fuzzy", + "tube.on_off", + "drive.value", + "drive.on_off", + "midi_out.channel_1.autogain", + "midi_out.channel_2.autogain", + "midi_out.channel_3.autogain", + "tube.vibrato.on_off", + "tube.vibrato", + "preamp.atan", + "ui.latency_nowarn", + "amp.oversample.on_off", + "amp.threshold", + "amp.fuzz", + "tube2.on_off", + "tube2.resonanz", + "tube2.vibrato", + "tube2.fuzzy", + "amp.tone.bass", + "shaper.on_off", + "shaper.sharper", + "amp.bass_boost.on_off", + "noise_gate.on_off", + "noise_gate.threshold", + "crybaby.autowah", + "beat_detector.midi_gain", + "chorus.freq", + "chorus.depth", + "chorus.delay", + "chorus.level", + "chorus.on_off", + "chorus.dialog", + "jconv.left_gain", + "jconv.left_delay", + "jconv.right_delay", + "jconv.right_gain", + "jconv.dialog", + "crybaby.position", + "overdrive.position", + "distortion.position", + "freeverb.position", + "IR.position", + "compressor.position", + "echo.position", + "chorus.position", + "delay.position", + "delay.delay", + "delay.on_off", + "delay.gain", + "IR.auto_freq", + "MultiBandFilter.f16k", + "MultiBandFilter.f8k", + "MultiBandFilter.f4k", + "MultiBandFilter.f2k", + "MultiBandFilter.f1k", + "MultiBandFilter.f500", + "MultiBandFilter.f250", + "MultiBandFilter.f125", + "MultiBandFilter.f62_5", + "MultiBandFilter.f31_25", + "MultiBandFilter.on_off", + "convolve.on_off", + "convolve.select", + "ui.skin", + "jconv.on_off", + ] + +head = ["guitarix_file_version", [0, 0, "0.05.4-1"]] + +def int_list(l): + return [int(v) for v in l] + +def float_list(l): + return [float(v) for v in l] + +def add_jconv(fn, out_dict): + if not os.path.exists(fn): + return out_dict + d = {} + for line in file(fn): + a = line.split() + cmd = a[0] + if cmd == "/cd": + d["jconv.IRDir"] = a[1] + elif cmd == "/convolver/new": + d["jconv.BufferSize"], d["jconv.Mem"] = int_list(a[3:]) + elif cmd == "/impulse/read": + if a[1] == "1": + d["jconv.Gain"], d["jconv.Delay"], d["jconv.Offset"], d["jconv.Length"] = int_list(a[3:7]) + d["jconv.IRFile"] = a[8] + else: + d["jconv.lGain"], d["jconv.lDelay"] = int_list(a[3:5]) + d["jconv.Mode"] = 1 + elif cmd == "/impulse/copy": + d["jconv.Mode"] = 0 + out_dict["jconv"] = d + return out_dict + +def conv_varlist(l, preset): + d = {} + for k, v in zip(old_vars, float_list(l)): + if (preset and k in non_preset) or (not preset and k not in non_preset): + continue + d[k] = v + return d + +def convert_presets(): + fn = "guitarixprerc" + if not os.path.exists(fn): + print "no presets file" + return + presets = head[:] + names = [] + for line in file(fn): + a = line.split() + nm = a[0] + names.append(nm) + presets.append(nm) + d = dict(engine=conv_varlist(a[1:], True)) + presets.append(add_jconv("jconv_%s.conf" % nm, d)) + print "%d presets found: %s" % (len(names), ", ".join(names)) + json.dump(presets, file("guitarixpre_rc","w")) + +def load_corrupt_json_midi_file(f): + f.next() + for line in f: + if line.strip() == "]": + return + a = line.split(None, 1) + yield int(a[0].rstrip(", ")) + yield json.loads(a[1].rstrip(", \n")) + +def midi(fn): + if not os.path.exists(fn): + return [] + def ll(): + #l = json.load(file(fn)) + l = list(load_corrupt_json_midi_file(file(fn))) + for i in range(0, len(l), 2): + yield l[i], l[i+1] + outl = [] + for v1, v2 in ll(): + if v2[0][0] in ("T","C"): + ls = [] + for v in v2: + del v[0] + v[0] = old_vars[v[0]] + ls.append(v) + v2 = ls + outl.append(v1) + outl.append(v2) + return outl + +def convert_state(): + fn = "guitarixrc" + if not os.path.exists(fn): + print "no state file" + return + state = head[:] + l = file(fn).read().split() + dp = dict(engine=conv_varlist(l, True)) + add_jconv("jconv_set.conf", dp) + ds = conv_varlist(l, False) + state.extend(["current_preset", dp, + "settings", ds, + "midi_controller", midi("guitarix_midi_rc"), + ]) + json.dump(state, file("guitarix_rc","w")) + +def main(): + gxpath = os.path.join(os.environ["HOME"], ".guitarix") + if not os.path.exists(gxpath): + print "%s doesn't exist, nothing done" % gxpath + raise SystemExit + os.chdir(gxpath) + convert_presets() + convert_state() + print "done." + +def param_range(a, b): + for i in range(a+1, b): + print old_vars[i]; + +if __name__ == '__main__': + main() diff --git a/tools/dsp2cc b/tools/dsp2cc new file mode 100755 index 0000000..48496a0 --- /dev/null +++ b/tools/dsp2cc @@ -0,0 +1,369 @@ +#! /usr/bin/python +# -*- coding: utf-8 -*- + +import re, os, sys +from subprocess import Popen, PIPE +from optparse import OptionParser + + +num_re = r"(-?\d*\.?\d*e?[+-]?\d*f?)" + +class UIDefs(object): + + class UID(dict): + def write(self, fp, v): + if self.has_key("alias"): + return + self["tail"] = "".join([", "+x for x in self["value"]]) + if self.has_key("enum"): + enumvals = ",".join(['"%s"' % x for x in self["enum"].split("|")]+["0"]) + self["ename"] = ename = self["variable"] + "_values" + fp.write('\tstatic const char *%s[] = {%s};\n' % (ename, enumvals)) + fp.write('\tregisterEnumVar("%(id)s","%(name)s","%(type)s","%(tooltip)s",%(ename)s,&%(variable)s%(tail)s);\n' % self) + else: + fp.write('\tregisterVar("%(id)s","%(name)s","%(type)s","%(tooltip)s",&%(variable)s%(tail)s);\n' % self) + + def __getitem__(self, n): + try: + return dict.__getitem__(self, n) + except KeyError: + return "" + + def __init__(self): + self.ui = {} + + def add(self, element, key, value): + try: + uid = self.ui[element] + except KeyError: + self.ui[element] = uid = self.UID(variable=element) + uid[key] = value + + def get(self, element, key): + return self.ui[element][key] + + def has(self, element, key): + return self.ui[element].has_key(key) + + def var_filter(self): + s = "|".join([r"%s\s*=\s*%s" % (v, num_re) for v in self.ui.keys()]) + return re.compile(r"\s*("+s+");").match + + def write(self, fp): + for v, r in self.ui.items(): + r.write(fp, v) + +class Parser(object): + + def skip_until(self, exp): + r = re.compile(exp) + for line in self.lines: + m = r.match(line) + if m: + return m + return None + + def skip_while(self, exp): + m = re.compile(exp).match + for line in self.lines: + if not m(line): + return line + return "" + + def copy(self, exp, line=None): + cp = [] + if line: + cp.append(line) + m = re.compile(exp).match + for line in self.lines: + if m(line): + break + cp.append(line) + # remove indentation + m = re.compile(r"\t*").match + n = 10 + for l in cp: + if l != "\n": + n = min(n, len(m(l).group(0))) + return [l[n:] for l in cp] + + def get_section_list(self): + return "var-decl", "var-init", "var-free", "ui", "compute" + + def getIO(self, s): + e = r"\s*virtual int getNum%sputs\(\)\s*{\s*return\s*(\d+);\s*}" % s + for line in self.lines: + m = re.match(e, line) + if m: + return int(m.group(1)) + raise ValueError("getNum%sputs not found in source" % s) + + def readUI(self, exp): + stop = re.compile(exp).match + pre = r"\s*interface->" + nm = '"([^"]*)"' + vr = "([a-zA-Z_][0-9a-zA-Z_]*)" + sarg = (r"%s,\s*&%s,\s*%s,\s*%s,\s*%s,\s*%s" + % (nm, vr, num_re, num_re, num_re, num_re)) + openbox = re.compile(pre+r"open(Horizontal|Vertical)Box\(%s\);" % nm).match + closebox = re.compile(pre+r"closeBox\(\);").match + vslider = re.compile(pre+r"addVerticalSlider\(%s\);" % sarg).match + hslider = re.compile(pre+r"addHorizontalSlider\(%s\);" % sarg).match + numentry = re.compile(pre+r"addNumEntry\(%s\);" % sarg).match + checkbutton = re.compile(pre+r"addCheckButton\(%s,\s*&%s\);" % (nm, vr)).match + declare = re.compile(pre+r"declare\(&%s,\s*%s,\s*%s\);" % (vr, nm, nm)).match + stack = [] + def make_name(nm): + if nm.startswith("."): + nm = nm[1:] + else: + stack.append(nm) + nm = ".".join(stack) + stack.pop() + return nm + + for line in self.lines: + if stop(line): + return + m = openbox(line) + if m: + grp = m.group(2) + if not stack: + if self.toplevel and grp == self.modname: + grp = self.toplevel + if not self.topname: + self.topname = grp + stack.append(grp) + continue + if closebox(line): + stack.pop() + continue + m = vslider(line) or hslider(line) or numentry(line) + if m: + vn = m.group(2) + self.ui.add(vn, "type", "S") + self.ui.add(vn, "id", make_name(m.group(1))) + self.ui.add(vn, "value", m.groups()[2:]) + continue + m = checkbutton(line) + if m: + vn = m.group(2) + self.ui.add(vn, "type", "B") + self.ui.add(vn, "id", make_name(m.group(1))) + self.ui.add(vn, "value", ("0.0","0.0","1.0","1.0")) + continue + m = declare(line) + if m: + self.ui.add(m.group(1), m.group(2), m.group(3)) + continue + assert False, line + + def readMeta(self): + "only needed for faust 9.4; not used at the moment" + self.meta = {} + stop = re.compile(r'// Code generated with Faust').match + declare = re.compile(r'// ([^:]+):\s*"([^"]*)"\s*$').match + for line in self.lines: + if stop(line): + return + m = declare(line) + if m: + key = m.group(1) + value = m.group(2) + self.meta[key] = value + if key == "name": + self.toplevel = value + + def readMeta2(self, stop_expr): + self.meta = {} + stop = re.compile(stop_expr).match + declare = re.compile(r'\s*m->declare\s*\("([^"]+)"\s*,\s*"([^"]*)"\);').match + for line in self.lines: + if stop(line): + return + m = declare(line) + if m: + key = m.group(1) + value = m.group(2) + self.meta[key] = value + if key == "name": + self.toplevel = value + + def change_var_decl(self, lines): + param_matcher = re.compile(r"FAUSTFLOAT\s+([a-zA-Z_0-9]+);\n$").match + array_matcher = re.compile(r"(int|float|double)\s+([a-zA-Z_0-9]+)\s*\[\s*(\d+)\s*\]\s*;\n$").match + out = [] + for l in lines: + m = param_matcher(l); + if m: + var = m.group(1) + alias = self.ui.has(var,"alias") + if alias: + l = ('FAUSTFLOAT&\t%s = get_alias("%s");\n' + % (var, self.ui.get(var, "id"))) + if self.memory_threshold: + m = array_matcher(l) + if m: + sz = {"int": 4, "float": 4, "double": 8}[m.group(1)] + alen = int(m.group(3)) + if alen * sz > self.memory_threshold: + l = "%s *%s;\n" % (m.group(1), m.group(2)) + self.memlist.append((m.group(2), m.group(1), alen)) + out.append(l) + return out + + def add_var_alloc(self): + l = [] + for v, t, s in self.memlist: + l.append("if (!%s) %s = new %s[%d];\n" % (v, v, t, s)) + return l + + def add_var_free(self): + l = [] + for v, t, s in self.memlist: + l.append("if (%s) { delete %s; %s = 0; }\n" % (v, v, v)) + return l + + def __init__(self, lines, modname, memory_threshold): + self.lines = lines + self.modname = modname + self.memory_threshold = memory_threshold; + self.toplevel = None + self.topname = None + self.memlist = [] + s = {} + self.ui = UIDefs() + #self.readMeta() # (needed only for faust 9.4 + self.skip_until(r" private:") + var_decl = self.copy(r" public:") + self.skip_until(r"^\s*static\s+void\s+metadata\s*\(\s*Meta\s*\*\s*m\s*\)\s*{") + self.readMeta2(r"\s*}\s*\n$") + self.numInputs = self.getIO("In") + self.numOutputs = self.getIO("Out") + self.skip_until(r"\s*static void classInit") + s["var-init"] = self.copy(r"\s*}$") + self.skip_until(r"\s*virtual void instanceInit") + s["var-init"] += self.copy(r"\s*}$") + self.skip_until(r"\s*virtual void buildUserInterface") + s["ui"] = self.readUI(r"\s*}$") + s["var-decl"] = self.change_var_decl(var_decl) + s["var-init"] = self.add_var_alloc() + s["var-init"] + s["var-free"] = self.add_var_free() + self.skip_until(r"\s*virtual void compute") + iodef = r"\s*(float|FAUSTFLOAT)\s*\*\s*(in|out)put(\d+)\s*=\s*\2put\[\3\];" + s["compute"] = self.copy(iodef) + line = self.skip_while(iodef) + s["compute"] += self.copy("\s*}$", line) + self.sections = s + if self.topname is None: + self.topname = self.modname + # ignore any following definitions of static class members + + def getNumInputs(self): + return self.numInputs + + def getNumOutputs(self): + return self.numOutputs + + def __getitem__(self, n): + return self.sections[n] + + def write(self, fp, sect, indent=0, filt=lambda l: False): + pre = "\t" * indent + for l in self.sections[sect]: + if filt(l): + continue + fp.write(pre) + fp.write(l) + +activate = """ +void activate(bool start, int samplingFreq) +{ + if (start) { + if (!is_inited()) { + init(samplingFreq); + } + } else { + if (is_inited()) { + mem_free(); + } + } +} + +""" + +def output(fp, p, fname): + has_activate = len(p.memlist) > 0 + fp.write("namespace %s {\n" % p.modname) + fp.write("// generated from file '%s'\n\n" % fname) + if has_activate: + fp.write("volatile bool inited = false;\n") + p.write(fp, "var-decl") + fp.write("int\tfSamplingFreq;\n\n") + fp.write("void init(int samplingFreq)\n{\n") + p.write(fp, "var-init", 1, filt=p.ui.var_filter()) + if has_activate: + fp.write("\tinited = true;\n") + fp.write("}\n\n") + if has_activate: + fp.write("void mem_free()\n{\n") + fp.write("\tinited = false;\n") + fp.write("\tjack_sync();\n") + p.write(fp, "var-free", 1) + fp.write("}\n\n") + fp.write("inline bool is_inited()\n") + fp.write("{\n return inited;\n}\n\n") + fp.write(activate) + fp.write("void compute(int count%s%s)\n{\n" % ( + "".join([", float *input%d" % i for i in range(p.getNumInputs())]), + "".join([", float *output%d" % i for i in range(p.getNumOutputs())]))) + p.write(fp, "compute", 1) + fp.write("\t}\n}\n\n") + fp.write("static struct RegisterParams { RegisterParams(); } RegisterParams;\n") + fp.write("RegisterParams::RegisterParams()\n{\n") + p.ui.write(fp) + fp.write('\tregisterInit("%s", init);\n' % p.topname) + fp.write("}\n") + fp.write("\n} // end namespace %s\n" % p.modname) + +def main(): + op = OptionParser(usage="usage: %prog [options] ") + op.add_option("-o", "--output", dest="oname", + help="write c++ code to FILE", metavar="FILE") + op.add_option("-d", "--double", dest="faust", action="append", + help="additional faust options, build with double precision") + op.add_option("-f", "--float", dest="faustf", action="append", + help="additional faust options, build with single precision") + op.add_option("-s", "--memory-threshold", dest="memory_threshold", + default=0, type="int", + help="change static memory allocations above threshold to dynamic ones") + options, args = op.parse_args() + if len(args) != 1: + op.error("exactly one input filename expected\n") + fname = args[0] + if not os.path.exists(fname): + print "error: can't open '%s'" % fname + raise SystemExit, 1 + if options.faust: + precision = ' -double' + elif options.faustf: + precision = ' -single' + else: + precision = '' + faust = Popen("faust %s%s" % (fname, precision), shell=True, stdout=PIPE) + try: + parser = Parser(faust.stdout, + os.path.splitext(os.path.basename(fname))[0], + options.memory_threshold) + except ValueError, e: + if faust.wait() == 0: + print e + raise SystemExit, 1 + if options.oname: + outp = file(options.oname,"w") + else: + outp = sys.stdout + output(outp, parser, fname) + +if __name__ == "__main__": + main() diff --git a/tools/dsp2cc_exp b/tools/dsp2cc_exp new file mode 100755 index 0000000..b9cc885 --- /dev/null +++ b/tools/dsp2cc_exp @@ -0,0 +1,244 @@ +#! /usr/bin/python +# -*- coding: utf-8 -*- + +import sys, re, os, subprocess +from xml.etree.ElementTree import parse +from optparse import OptionParser + + +template = """\ +namespace %(modname)s { +// generated from file '%(fname)s' + +%(includeclass)s +struct DspBlock: mydsp +{ + DspBlock(); + static void static_init(int); +}; + +DspBlock instance; + +void init(int samplingRate) +{ + instance.init(samplingRate); +} + +#ifdef DSP_HAS_SETUP +void setup(GtkWidget *w) +{ + instance.setup(w); +} +#endif + +DspBlock::DspBlock() +{ +%(uidefs)s registerInit("Experimental", %(modname)s::init); +#ifdef DSP_HAS_SETUP + registerSetup(%(modname)s::setup); +#endif +} + +void compute(int len%(iargs)s%(oargs)s) +{ + FAUSTFLOAT* inputs[%(inputs)s] = { %(input_init)s }; + FAUSTFLOAT* outputs[%(outputs)s] = { %(output_init)s }; + instance.compute(len, inputs, outputs); +} + +} // end namespace %(modname)s +""" + +class Faust(object): + + def __init__(self, xml, cc, fname): + self.xml = parse(xml).getroot() + self.cc = list(cc) + self.fname = fname + self.modname = os.path.splitext(os.path.basename(fname))[0] + n = self.xml.find("name") + if n is None: + self.toplevel = None + else: + self.toplevel = n.text + self.widgets = {} + self.read_layout() + self.meta = self.read_meta() + + def xml_get_number(self, name): + return int(self.xml.find(name).text) + + def read_meta(self): + pre = r"\s*interface->" + nm = '"([^"]*)"' + vr = "([a-zA-Z_][0-9a-zA-Z_]*)" + declare = re.compile(pre+r"declare\(&%s,\s*%s,\s*%s\);" % (vr, nm, nm)).match + meta = {} + for line in self.cc: + m = declare(line) + if m: + vn = m.group(1) + if vn not in meta: + meta[vn] = {} + meta[vn][m.group(2)] = m.group(3) + return meta + + def group(self, g, stack): + grp = g.find("label").text + if not stack: + if self.toplevel and grp == self.modname: + grp = self.toplevel + if grp: + stack.append(grp) + for w in g.findall("widgetref"): + self.widgets[w.attrib["id"]] = stack[:] + for w in g.findall("group"): + self.group(w, stack) + if grp: + stack.pop() + + def read_layout(self): + stack = [] + self.group(self.xml.find("ui").find("layout").find("group"), stack) + + def make_name(self, w): + nm = w.find("label").text + stack = self.widgets[w.attrib["id"]] + if nm.startswith("."): + nm = nm[1:] + else: + stack.append(nm) + nm = ".".join(stack) + stack.pop() + return nm + + def uidefs(self): + vardict = {} + l = [] + for w in self.xml.find("ui").find("activewidgets").findall("widget"): + d = {} + d["id"] = self.make_name(w) + varname = w.find("varname").text + try: + if "alias" in self.meta[varname]: + continue + except KeyError: + pass + try: + d["name"] = self.meta[varname]["name"] + except KeyError: + d["name"] = "" + if w.attrib["type"] == "checkbox": + for n in "varname",: + d[n] = w.find(n).text + d["init"] = d["min"] = "0" + d["max"] = d["step"] = "1" + d["tp"] = "B" + else: + for n in "varname", "init", "min", "max", "step": + d[n] = w.find(n).text + d["tp"] = "S" + l.append('\tregisterVar("%(id)s","%(name)s","%(tp)s","",' + '&%(varname)s,%(init)s,%(min)s,%(max)s,%(step)s);\n' % d) + vardict[varname] = {} + vardict.update(self.meta) + return "".join(l), vardict + + def mod_cc(self, vardict): + """ + reworks the c++ output of faust: + - delete include-lines + - delete initialisation of parameters + - change private to protected + - change parameter declaration to a reference if "alias" is set + """ + num_re = r"(-?\d*\.?\d*e?[+-]?\d*f?)" + s = "|".join([r"%s\s*=\s*%s" % (v, num_re) for v in vardict.keys()]) + init_matcher = re.compile(r"\s*("+s+");").match + decl_matcher = re.compile("FAUSTFLOAT\s+([a-zA-Z_0-9]+);\n$").match + private_matcher = re.compile(r"(\s*)private:\s*\n$").match + sample_matcher = re.compile(r"^\s*int\s+fSamplingFreq;").match + l = [] + for line in self.cc: + if line.startswith("#include ") or init_matcher(line): + continue + m = private_matcher(line) + if m: + l.append(m.group(1) + "protected:\n") + continue + if sample_matcher(line): + l.append("\tfloat fSamplingFreq;\n") + continue + m = decl_matcher(line) + if m: + var = m.group(1) + try: + vd = vardict[var] + except KeyError: + pass + else: + if "alias" in vd: + line = ('FAUSTFLOAT&\t%s = get_alias("%s");\n' + % (var, vd["id"])) + l.append(line) + return "".join(l) + + def output(self, fp): + inputs = self.xml_get_number("inputs") + outputs = self.xml_get_number("outputs") + uidefs, vardict = self.uidefs() + d = dict( + modname = self.modname, + fname = self.fname, + includeclass = self.mod_cc(vardict), + uidefs = uidefs, + iargs = "".join([", FAUSTFLOAT *input%d" % i for i in range(inputs)]), + oargs = "".join([", FAUSTFLOAT *output%d" % i for i in range(outputs)]), + inputs = inputs, + outputs = outputs, + input_init = ",".join(["input%d" % i for i in range(inputs)]), + output_init = ",".join(["output%d" % i for i in range(outputs)]), + ) + fp.write(template % d) + + +def main(): + op = OptionParser(usage="usage: %prog [options] ") + op.add_option("-o", "--output", dest="oname", + help="write c++ code to FILE", metavar="FILE") + op.add_option("-a", "--architecture", dest="arch", + help="faust architecture file") + op.add_option("-f", "--faust", dest="faust", action="append", + help="additional faust options") + options, args = op.parse_args() + if len(args) != 1: + op.error("exactly one input filename expected\n") + fname = args[0] + if not os.path.exists(fname): + print "error: can't open '%s'" % fname + raise SystemExit, 1 + if options.oname: + outp = file(options.oname,"w") + else: + outp = sys.stdout + if options.arch: + arch = options.arch + else: + arch = "minimal.cpp" + pgm = ["faust","-xml","-a",arch,"-o",fname+".cc"] + if options.faust: + for v in options.faust: + pgm.extend(v.split()) + pgm.append(fname) + try: + subprocess.call(pgm) + Faust(file(fname+".xml"), file(fname+".cc"), fname).output(outp) + finally: + for ext in ".cc", ".xml": + try: + os.remove(fname+ext) + except OSError: + pass + +if __name__ == "__main__": + main() diff --git a/tools/freq-plot b/tools/freq-plot new file mode 100755 index 0000000..5330b1a --- /dev/null +++ b/tools/freq-plot @@ -0,0 +1,14 @@ +#! /bin/bash +[ "$1" = "" ] && { echo "usage: freq-plot {options}"; exit 1; } +[ -r "$1" ] || { echo "can't read input file $1"; exit 1; } +set -e +inp="$1" +shift +tmpdir=/tmp/freq-plot.$$ +trap "rm -rf $tmpdir" EXIT +mkdir $tmpdir +echo "process=1-1':component(\"$inp\");" | faust -a plot.cpp -o $tmpdir/plot_out.cpp /dev/fd/0 +cd $tmpdir +g++ plot_out.cpp -o plot_out +./plot_out "$@" > plot_out.mat +octave -q --persist --eval "load plot_out.mat; freqz(plot_out,1,[],[],44100)" diff --git a/tools/v12ax7_transfer.py b/tools/v12ax7_transfer.py new file mode 100644 index 0000000..1440d67 --- /dev/null +++ b/tools/v12ax7_transfer.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +# +# lots of hints and some numerical values taken from +# Virtual Air Guitar (Matti Karjalainen, Teemu Maki-Patola, Aki Kanerva, Antti Huovilainen) +# + +import sys +from pylab import * +from scipy.optimize import newton + +# +# o V+ +# | +# | +# | +# +-+ +# | | +# Rp | | +# | | Co +# +-+ +# | || +# +-----++---o Vo +# Vp | || +# | +# Ci --+-- +# Ri /--+-- +# || Vi +-----+ Vg / 12AX7 +# o---++--+-------| |-----+- - - - +# || | +-----+ \ +# | \/---- +# | /----- +# | / +# +-+ Vk | +# | | +------+ +# | | | | +# | | | | +# +-+ +-+ | +# | | | -+- +# | Rk | | -+- Ck +# | | | | +# ----- +-+ | +# --- | | +# o | | +# | | +# ----- ----- +# --- --- +# o o +# + +def Igk_Vgk(Vgk): + """gate current as function of gate-kathode voltage""" + return exp(7.75*Vgk-10.3) + +def Ipk(Vgk, Vpk): + """plate current as function of gate-kathode voltage and plate-kathode voltage""" + mu = 100.0 + kx = 1.4 + kg1 = 1060.0 + kp = 600.0 + kvb = 300.0 + E1 = Vpk/kp*log(1+exp(kp*(1/mu+Vgk/sqrt(kvb+Vpk*Vpk)))) + return 2*E1**kx/kg1*(E1>0.0) + +def Ftube(Vi, Ri, Ipk): + """calculate output voltage of a tube circuit as function of input voltage + Vi array of input voltages + Ri value of resistor Ri + Ipk plate current Ip as function of Vgk and Vpk + """ + def fi(Vgk, Vi, Ri): + return Vi - Vgk - Ri * Igk_Vgk(Vgk) # sum of voltages -> zero + Vgk = newton(fi, 1e-3, args=(Vi, Ri)) # Vgk(Vi) + def fp(Vpk, Vgk, Ipk): + return Vpk + 100e3 * Ipk(Vgk, Vpk) - 250 # Vp 250V, Rp 100k + + l = 110.0 # start value for iteration + return newton(fp, l, args=(Vgk, Ipk)) # Vpk(Vgk) + +def calc_ftube(Ri, st, en, cnt): + """calculate table Vp(Vi)""" + Vi = linspace(st,en,cnt) + Vp = zeros_like(Vi) + for i, v in enumerate(Vi): + Vp[i] = Ftube(v, Ri, Ipk) + return Vi, Vp + +def write_ftube_table(Ri, Vi, Vp): + """write C source""" + sys.stdout.write("\t{ // Ri = %dk\n" % (Ri/1e3)) + sys.stdout.write('\t%g,%g,%g, {' % (Vi[0], Vi[-1], (len(Vi)-1)/(Vi[-1]-Vi[0]))) + s = "" + for i, v in enumerate(Vi): + if i % 5 == 0: + sys.stdout.write(s+"\n\t") + s = "" + sys.stdout.write(s+str(Vp[i])) + s = "," + sys.stdout.write("\n\t}}") + +def write_tables(): + sys.stdout.write("struct table1d tubetable[] = {\n") + s = "" + for Ri in 68e3, 250e3: + sys.stdout.write(s) + s = ",\n" + Vi, Vp = calc_ftube(Ri, -5, 5, 2001) + write_ftube_table(Ri, Vi, Vp) + sys.stdout.write("\n};\n") + +def check_table_accuracy(Ri, st, en, cnt): + """maximal table error at half interval""" + Vi, Vp = calc_ftube(Ri, st, en, cnt) + d = zeros((len(Vp)-1,)) + for i in range(1,len(Vp)): + vi = (Vi[i-1]+Vi[i])/2 + v = Ftube(vi, Ri, Ipk) + d[i-1] = (0.5*(Vp[i-1]+Vp[i]) - v)/v + return max(d) + +def display_accuracy(): + for Ri in 250e3, 68e3: + print "Ri=%dk: %g" % (Ri/1e3, check_table_accuracy(Ri, -5, 5, 2001)) + +def plot_Ftube(): + Vi = linspace(-4,2) + Vp = zeros_like(Vi) + for Ri in 250e3, 68e3: + for i, v in enumerate(Vi): + Vp[i] = Ftube(v, Ri, Ipk) + plot(Vi, Vp, label="Ri=%dk" % (Ri/1e3)) + xlabel("Vik") + ylabel("Vp") + legend() + axis + show() + +def main(): + if len(sys.argv) == 2: + arg = sys.argv[1] + else: + arg = "" + if arg == "plot": + plot_Ftube() + elif arg == "accuracy": + display_accuracy() + elif arg == "table": + write_tables() + else: + print "usage: %s plot|accuracy|table" % sys.argv[0] + +if __name__ == "__main__": + main() diff --git a/waf b/waf new file mode 100755 index 0000000..30ac5a2 Binary files /dev/null and b/waf differ diff --git a/wscript b/wscript new file mode 100644 index 0000000..4440a97 --- /dev/null +++ b/wscript @@ -0,0 +1,410 @@ +#! /usr/bin/env python +# encoding: utf-8 + +import os +import Utils +import Options +import commands +g_maxlen = 40 +import shutil +import re +import Logs +import sys +from Constants import HEXVERSION +from Configure import ConfigurationError + +# used by waf dist and waf build +VERSION='0.10.0' +APPNAME='guitarix' + +good_faust_versions = ['0.9.10','0.9.17','0.9.22','0.9.23','0.9.24'] + +# these variables are mandatory ('/' are converted automatically) +srcdir = '.' +blddir = 'build' + +def faust_vers_str(): + if len(good_faust_versions) == 1: + return good_faust_versions[0] + else: + return "in [%s]" % ", ".join(good_faust_versions) + +# options defined for waf configure +def set_options(opt): + opt.tool_options('compiler_cxx') + + comp = opt.add_option_group("Compiler / Linker flags") + + comp.add_option('--debug', + action='store_const', + default=False, + const=True, + help='set compiler flags for a debug build') + + comp.add_option('--cxxflags-release', + type='string', + default=' -DNDEBUG', + dest='cxxflags_release', + help='additional C++ compiler flags for release version (not used if --debug) [Default: %default]') + + comp.add_option('--cxxflags-debug', + type='string', + default=' -g -fstack-protector-all', + dest='cxxflags_debug', + help='additional C++ compiler flags for debug version (only used if --debug) [Default: %default]') + + comp.add_option('--cxxflags', + type='string', + default='-Wall -O2', # -fomit-frame-pointer -ffast-math -fstrength-reduce -mmmx -mfpmath=sse -DUSE_XMMINTRIN -pipe + dest='cxxflags', + help='C++ base compiler flags [Default: %default]') + + comp.add_option('--optimization', + action='store_const', + default=False, #'-fomit-frame-pointer -ffast-math -fstrength-reduce -pipe', + const=True, + help='C++ optimization compiler flags [Default: %default]') + + comp.add_option('--experimental', + action='store_const', + default=False, + const=True, + help='build with support for experimental modules build with faust') + + comp.add_option('--includeresampler', + action='store_const', + default=False, + const=True, + help='build with included local zita-resample libary (Default NO)') + + comp.add_option('--includeconvolver', + action='store_const', + default=False, + const=True, + help='build with included local zita-convolver libary (Default NO)') + + faust = opt.add_option_group("faust-Compiler") + + faust.add_option('--faust', + action='store_const', + default=False, + const=True, + help=('build with faust even if the installed version is not %s' + % faust_vers_str())) + + faust.add_option('--no-faust', + action='store_const', + default=False, + const=True, + help="don't build with faust") + + faust.add_option('--faust-float', + action='store_const', + default=False, + const=True, + help="build with faust, single precision") + + ladspa = opt.add_option_group("other options") + + ladspa.add_option('--ladspadir', + type='string', + help='LADSPA plugin directory [Default: /lib/ladspa]') + + + +def check_comp(conf): + if Options.options.includeresampler: + define_name="ZITA_RESAMPLER" + conf.env['ZITARESAMPLER'] = True + conf.env['ZITA_RESAMPLER'] = None + + if Options.options.includeconvolver: + conf.env['ZITACONVOLVER'] = True + conf.env['INTERN_ZITA_CONVOLVER'] = None + conf.env['ZITA_CONVOLVER'] = None + +def check_faust(conf): + if Options.options.no_faust: + conf.env['FAUST'] = None + return + conf.find_program("faust", var='FAUST') + if not conf.env['FAUST']: + return + try: + s = Utils.cmd_output('%s --version' % conf.env['FAUST']) + except ValueError: + Logs.warn('count not execute faust') + return + m = re.match(r".*Version\s*(.*)", s) + if not m: + Logs.warn('could not determine faust version') + vers = m.group(1) + conf.env["FAUST_VERSION"] = vers + if vers not in good_faust_versions and not Options.options.faust: + conf.env['FAUST'] = None + conf.check_message_custom('faust','version',"can't use %s (check ./waf --help)" % vers,color='YELLOW') + else: + conf.check_message('faust','version',1,vers) + if Options.options.faust_float: + conf.env['FAUST_DOUBLE'] =None + else: + conf.env['FAUST_DOUBLE'] =True + + +def check_faust_cc(conf, cpy_dir): + if os.path.exists(cpy_dir): + return + if not conf.env['FAUST']: + raise ConfigurationError( + "directory %s doesn't exist and no faust compiler" + % cpy_dir) + try: + os.mkdir(cpy_dir) + except OSError, e: + raise ConfigurationError( + "directory %s doesn't exist and can't be created" + % cpy_dir) + Logs.info("directory %s created" % cpy_dir) + +def print_msg(msg, nl=True): + if HEXVERSION > 0x10500: + s = sys.stderr + else: + s = sys.stdout + if nl: + t = "\n" + else: + t = " " + s.write(msg+t) + +# a bit of waf display formatting +def display_msg(msg, status = None, color = None): + sr = msg + global g_maxlen + g_maxlen = max(g_maxlen, len(msg)) + if status: + print_msg("%s :" % msg.ljust(g_maxlen),False) + Utils.pprint(color, status) + else: + print_msg("%s" % msg.ljust(g_maxlen)) + +def error_msg(msg): + Utils.pprint('RED', msg) + +def display_feature(msg, build): + if build: + display_msg(msg, "yes", 'CYAN') + else: + display_msg(msg, "no", 'YELLOW') + +def append_optimization_flags(cxxflags): + cpu_model = None + x86_flags = None + try: + for line in file("/proc/cpuinfo"): + if cpu_model is None: + if line.startswith("model name"): + cpu_model = line.split(":",1)[1].strip() + elif x86_flags is None: + if line.startswith("flags"): + x86_flags = line.split(":",1)[1].strip() + else: + break + except IOError: + pass + if cpu_model is None or x86_flags is None: + display_msg("Checking CPU Architecture", + "cpu model not found in /proc/cpuinfo", + "YELLOW") + return None + model = cpu_model.split() + arch = os.uname()[4] + if "AMD" in model and "x86_64" in arch: + cxxflags.append ("-march=k8") + elif "AMD" in model and "Sempron(tm)" in model: + cxxflags.append ("-march=native") + elif "Geode" in model : + cxxflags.append ("-march=geode") + elif "Core" in model and "x86_64" in arch: + cxxflags.append ("-march=core2") + elif "i386" in arch: + cxxflags.append ("-march=i386") + elif "i486" in arch: + cxxflags.append ("-march=i486") + elif "i586" in arch: + cxxflags.append ("-march=i586") + elif "i686" in arch: + cxxflags.append ("-march=i686") + else: + cxxflags.append ("-march=native") + + if "mmx" in x86_flags: + cxxflags.append ("-mmmx") + if "3dnow" in x86_flags: + cxxflags.append ("-m3dnow") + + if "sse5" in x86_flags: + cxxflags.append ("-msse5") + cxxflags.append ("-mfpmath=sse") + elif "sse4_2" in x86_flags: + cxxflags.append ("-msse4.2") + cxxflags.append ("-mfpmath=sse") + elif "sse4_1" in x86_flags: + cxxflags.append ("-msse4.1") + cxxflags.append ("-mfpmath=sse") + elif "ssse3" in x86_flags: + cxxflags.append ("-mssse3") + cxxflags.append ("-mfpmath=sse") + elif "sse4" in x86_flags: + cxxflags.append ("-msse4") + cxxflags.append ("-mfpmath=sse") + elif "sse3" in x86_flags: + cxxflags.append ("-msse3") + cxxflags.append ("-mfpmath=sse") + elif "sse2" in x86_flags: + cxxflags.append ("-msse2") + cxxflags.append ("-mfpmath=sse") + #cxxflags.append ("-DUSE_XMMINTRIN") + elif "sse" in x86_flags: + cxxflags.append ("-msse") + cxxflags.append ("-mfpmath=sse") + # cxxflags.append ("-DUSE_XMMINTRIN") + + if not Options.options.debug: + cxxflags.append ("-fomit-frame-pointer") + cxxflags.append ("-ftree-loop-linear") + cxxflags.append ("-ffinite-math-only") + cxxflags.append ("-fno-math-errno") + cxxflags.append ("-fno-signed-zeros") + #cxxflags.append ("-ffast-math") # quicker but doesn't seem to work (difference in sound output) + #cxxflags.append ("-malign-double") + cxxflags.append ("-fstrength-reduce") + cxxflags.append ("-pipe") + return cpu_model + +# guitarix waf configuration +def configure(conf): + # compiler + conf.check_tool('compiler_cxx') + # needed libarys + try: + conf.check_cfg(package='jack', atleast_version='0.109.1', max_version='1.8.0', args='--cflags --libs', uselib_store='JACK', mandatory=1) + except ConfigurationError: + conf.check_cfg(package='jack', atleast_version='1.9.1', args='--cflags --libs', uselib_store='JACK', mandatory=1) + conf.check_cfg(package='sndfile', atleast_version='1.0.17', args='--cflags --libs', uselib_store='SNDFILE', mandatory=1) + conf.check_cfg(package='gmodule-export-2.0', args='--cflags --libs', uselib_store='GMODULE_EXPORT', mandatory=1) + conf.check_cfg(package='gtk+-2.0', atleast_version='2.12.0', args='--cflags --libs', uselib_store='GTK2', mandatory=1) + conf.check_cfg(package='gthread-2.0', atleast_version='2.10', args='--cflags --libs', uselib_store='GTHREAD', mandatory=1) + conf.check_cfg(package='gtkmm-2.4', args='--cflags --libs', uselib_store='GTKMM', mandatory=1) + conf.check_cfg(package='fftw3f', atleast_version='3.1.2', args='--cflags --libs', uselib_store='FFTW3', mandatory=1) + conf.check(header_name='ladspa.h', mandatory=1) + conf.check(header_name='boost/format.hpp', mandatory=1) + # convolver and resampler + if not Options.options.includeconvolver: + conf.check_cxx(header_name='zita-convolver.h', lib="zita-convolver", uselib_store='ZITA_CONVOLVER', + errmsg="not found, using local version", define_name="INTERN_ZITA_CONVOLVER") + if not Options.options.includeresampler: + conf.check(lib='zita-resampler', msg='Checking for zita-resampler', header_name='stdlib.h zita-resampler.h', + errmsg="not found, using local version", define_name="ZITA_RESAMPLER") + # faust + check_faust(conf) + check_faust_cc(conf, "src/faust-cc") + # directory + conf.env['SHAREDIR'] = conf.env['PREFIX'] + '/share' + # jack_session support + conf.check(header_name='jack/session.h', define_name='HAVE_JACK_SESSION') + + # defines for compilation + conf.define('GX_STYLE_DIR', os.path.normpath(os.path.join(conf.env['SHAREDIR'], 'guitarix','skins'))) + conf.define('GX_BUILDER_DIR', os.path.normpath(os.path.join(conf.env['SHAREDIR'], 'guitarix','builder'))) + conf.define('GX_PIXMAPS_DIR', os.path.normpath(os.path.join(conf.env['SHAREDIR'], 'pixmaps'))) + conf.define('GX_VERSION', VERSION) + if Options.options.experimental: + conf.define('EXPERIMENTAL', '') + + # writing config.h + conf.write_config_header('config.h') + + conf.define('LIBDIR', os.path.normpath(os.path.join(conf.env['PREFIX'], 'lib'))) + conf.define('LADSPADIR', os.path.normpath(os.path.join(conf.env['LIBDIR'], 'ladspa'))) + if Options.options.ladspadir: + conf.env['LADSPADIR'] = Options.options.ladspadir + + conf.define('BINDIR', os.path.normpath(os.path.join(conf.env['PREFIX'], 'bin'))) + conf.define('DESKAPPS_DIR', os.path.normpath(os.path.join(conf.env['SHAREDIR'], 'applications'))) + conf.define('BIN_NAME', APPNAME) + # g++ flags + cxxflags = Options.options.cxxflags.split() + if Options.options.debug: + cxxflags += Options.options.cxxflags_debug.split() + else: + cxxflags += Options.options.cxxflags_release.split() + cpu_model = None + if Options.options.optimization: + cpu_model = append_optimization_flags(cxxflags) + conf.env['CXXFLAGS'] = cxxflags + + # config subdirs + + conf.sub_config('src'); + if conf.env['FAUST']: + conf.sub_config('src/faust'); + conf.sub_config('ladspa'); + conf.sub_config('rcstyles'); + + # some output + print + display_msg("==================") + version_msg = "GUITARIX " + VERSION + print_msg(version_msg) + + print_msg("") + + if not conf.env['ZITA_RESAMPLER']: + conf.env['ZITARESAMPLER'] = True + check_comp(conf) + + if not conf.env['INTERN_ZITA_CONVOLVER']: + conf.env['ZITACONVOLVER'] = True + check_comp(conf) + + if cpu_model: + display_msg("CPU version" , "%s" % cpu_model, "CYAN") + display_msg("C++ flags", " ".join(conf.env['CXXFLAGS']), 'CYAN') + #display_msg("Compiler %s version" %conf.env["CXX"], "%s" % ".".join(conf.env["CC_VERSION"]), "CYAN") + display_feature("Use faust", conf.env['FAUST']) + if not Options.options.faust_float: + display_msg("Use faust precision", "double", 'CYAN') + else: + display_msg("Use faust precision", "single", 'CYAN') + display_feature("Use internal zita-resampler", conf.env['ZITARESAMPLER']) + display_feature("Use internal zita-convolver", conf.env['ZITACONVOLVER']) + display_feature("Experimental Extensions", conf.env['EXPERIMENTAL']=="") + display_msg("Install prefix", conf.env['PREFIX'], 'CYAN') + display_msg("Install binary", conf.env['BINDIR'], 'CYAN') + display_msg("Install ladspa", conf.env['LADSPADIR'], 'CYAN') + display_msg("Guitarix style directory", conf.env['GX_STYLE_DIR'], 'CYAN') + display_msg("Guitarix builder directory", conf.env['GX_BUILDER_DIR'], 'CYAN') + display_msg("Guitarix pixmaps directory", conf.env['GX_PIXMAPS_DIR'], 'CYAN') + if conf.env['g++']: + error_msg("ERROR !!! Compiler version is to old !!!") + + print_msg("") + +def build(bld): + # process subfolders from here + bld.add_subdirs('ladspa') + #bld.add_subdirs('lib') + bld.add_subdirs('src') + if bld.env['FAUST']: + bld.add_subdirs('src/faust') + bld.add_subdirs('rcstyles') + bld.add_subdirs('pixmaps') + + bld.install_files(bld.env['DESKAPPS_DIR'], 'guitarix.desktop', chmod=0644) + +def etags(ctx): + "Create an Emacs ETAGS file for the src directory" + cmd = "etags -o TAGS lib/*.cpp lib/*.cc lib/*.h src/*.cpp src/*.cc src/headers/*.h" + Logs.debug("runner: system command -> %s" % cmd) + Utils.exec_command(cmd)