summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrej Shadura <andrew.shadura@collabora.co.uk>2021-10-07 16:12:09 +0200
committerAndrej Shadura <andrew.shadura@collabora.co.uk>2021-10-07 16:12:09 +0200
commitd4700c96fd551eea539921572c03842ecdc6c8c3 (patch)
treeac37ec6ef7d954feab5ad47c427e849f051da604
Import Upstream version 0.2.0+hg20110905r195
-rw-r--r--.hgtags12
-rw-r--r--AUTHORS1
-rw-r--r--COPYING674
-rw-r--r--HACKING92
-rw-r--r--Makefile48
-rw-r--r--README12
-rw-r--r--TODO6
-rw-r--r--effects.c3317
-rw-r--r--effects.h114
-rw-r--r--gdigi.174
-rw-r--r--gdigi.c1241
-rw-r--r--gdigi.desktop7
-rw-r--r--gdigi.h1007
-rw-r--r--gtkknob.c919
-rw-r--r--gtkknob.h102
-rw-r--r--gui.c1265
-rw-r--r--gui.h30
-rw-r--r--knob.pngbin0 -> 63864 bytes
-rw-r--r--preset.c357
-rw-r--r--preset.h32
20 files changed, 9310 insertions, 0 deletions
diff --git a/.hgtags b/.hgtags
new file mode 100644
index 0000000..c44d01e
--- /dev/null
+++ b/.hgtags
@@ -0,0 +1,12 @@
+6defd1a8b4b499c46196b4112e8dff443c57609c 0.1
+2a58e6a931791cb369483dc6171d66a8a75f40f2 0.1.1
+7a31bc52075252647dd848eec6308a111d86776e 0.1.2
+5cc97dba5d412fd7d000ad0974682ed4e10c3326 0.1.3
+78367821f4f43f610edf53f5f732f74d0832f7c2 0.1.4
+45f897c02e72af5c73e0c27063f02728c0392e19 0.1.5
+80e56807413bc281b7e4331d98581ba874fb186d 0.1.6
+c622b5d3c3b3e08a87fd994ef855fba98128ed07 0.1.7
+5e6d6124b5f2860867e24cd2da033fbc6ad9d433 0.1.8
+d9a1510dc8feb81e7026882e8a7719a2ba7ff04c 0.2.0
+d9a1510dc8feb81e7026882e8a7719a2ba7ff04c 0.2.0
+6864af80db93f7dfef26c0f583ce7c60382b1142 0.2.0
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..85143a3
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Tomasz Moń <desowin@gmail.com>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU 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 Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/HACKING b/HACKING
new file mode 100644
index 0000000..3a0bc8b
--- /dev/null
+++ b/HACKING
@@ -0,0 +1,92 @@
+In general everything brings down to figure out:
+-ID
+-Position
+-Possible value range
+
+There seems to be three possible ways to figure that out.
+1) Use USB sniffer together with X-Edit
+ Once you set up X-Edit and usb sniffer, set some option.
+ USB sniffer should report something like this being sent to device:
+ (all numbers here are hex)
+ 04 F0 00 00 04 10 00 5E 04 02 41 00 04 30 09 00 07 00 34 F7
+
+ MIDI data is transferred over USB using 32-bit USB-MIDI Event Packets.
+ Byte 0 is Cable Number (high nibble) and Code Index Number (low nibble).
+ Bytes 1, 2 and 3 are data.
+ Every bulk transfer on USB MIDI endpoint contains atleast one such packet
+ (those are sent one after each other).
+ In case of Digitech devices, the Cable Number seems to be 0 (correct me,
+ if I'm wrong).
+ There are three different Code Index Numbers that are being used in this
+ particular case:
+ 0x4 - SysEx starts or continues (Byte 1, 2 and 3 from this packet are
+ part of our MIDI message)
+ 0x5 - SysEx ends with following single byte (we just need to take Byte 1
+ from this packet)
+ 0x6 - SysEx ends with following two bytes (we just need to take Byte 1 and 2
+ from this packet)
+ 0x7 - SysEx ends with following three bytes (we need to take Byte 1, 2 and 3
+ from this packet)
+
+ Unused bytes in USB-MIDI packets are supposed to be 0.
+
+ To get SysEx command out of it, apply above rules, so we have:
+ F0 00 00 10 00 5E 02 41 00 30 09 00 00 34 F7
+
+ SysEx message format seems to be formed like this:
+ SysEx start byte - F0
+ Manufacturer ID - 00 00 10
+ Device ID - 00
+ Family ID - 5E (RP)
+ Product ID - 02 (RP250)
+ Procedure - 41 (see MessageID in gdigi.h)
+
+ As MIDI messages must not contain bytes with MSB bit set, Digitech
+ devices use packing system.
+ First byte contains MSB bits from following 7 bytes (this scheme
+ continues as many times as needed) (see pack_data() and unpack_message() in
+ gdigi.c for details).
+
+ Assuming message has been unpacked, the meaning of next bytes:
+ ID - in this example 30 09
+ Position - in this example 00
+ Value - in this example 00 (can be more bytes long, see below)
+ Checksum - to calculate it, XOR all bytes (of packed message)
+ Every message ends with F7
+
+ So for above example:
+ ID = 3009 (hex) = 12297 (decimal)
+ Position = 0
+ One of possible values is 0. Usually value range is 0 to 99,
+ albeit in some cases it's different - you have to check what values can
+ X-Edit assign (there doesn't seem to be any sanity check in firmware)
+ This is especially needed for IDs that set some effect type.
+
+2) Save preset patch
+ Patches seem to be simple XML files.
+ Every parameter is written like this:
+ <Param>
+ <ID>65</ID>
+ <Position>2</Position>
+ <Value>0</Value>
+ <Name>Pickup Enable</Name>
+ <Text>Off</Text>
+ </Param>
+ ID is ID, Position is Position and Value is one of possible values.
+ To get all possible values you can:
+ do
+ change value to next one possible in X-Edit
+ (for example next effect type)
+ save new patch
+ check patch file and note the change
+ while you don't have all possible values
+3) Use gdigi
+ After starting gdigi turn the knobs on your device.
+ Check out console output, you should notice something like this:
+ ** Message: Received parameter change ID: 210 Position: 4 Value: 0
+ ID is ID, Position is Position and Value is one of possible values.
+ To get all possible values keep turning knobs and watch the output.
+ If you change effect type usually there's more messages - where,
+ usually the first one is type change, and rest are default values.
+ This way you *CANNOT* gather all information (there're X-Edit only
+ controlled values, check device manual for more information).
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..f46dd6a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,48 @@
+CC = gcc
+EXTRA_CFLAGS ?=
+EXTRA_LDFLAGS ?=
+CFLAGS := $(shell pkg-config --cflags glib-2.0 gio-2.0 gtk+-2.0) -Wall -g -ansi -std=c99 $(EXTRA_CFLAGS)
+LDFLAGS = $(EXTRA_LDFLAGS) -Wl,--as-needed
+LDADD := $(shell pkg-config --libs glib-2.0 gio-2.0 gtk+-2.0 gthread-2.0 alsa) -lexpat
+OBJECTS = gdigi.o gui.o effects.o preset.o gtkknob.o
+DEPFILES = $(foreach m,$(OBJECTS:.o=),.$(m).m)
+
+.PHONY : clean distclean all
+%.o : %.c
+ $(CC) $(CFLAGS) -c $<
+
+.%.m : %.c
+ $(CC) $(CFLAGS) -M -MF $@ -MG $<
+
+all: gdigi
+
+gdigi: $(OBJECTS)
+ $(CC) $(LDFLAGS) -o $@ $+ $(LDADD)
+
+knob.h: knob.png
+ gdk-pixbuf-csource --name=knob_pixbuf knob.png > $@
+
+clean:
+ rm -f *.o
+ rm -f knob.h
+
+distclean : clean
+ rm -f .*.m
+ rm -f gdigi
+
+install: gdigi
+ install gdigi $(DESTDIR)/usr/bin
+ install gdigi.desktop $(DESTDIR)/usr/share/applications/
+
+NODEP_TARGETS := clean distclean
+depinc := 1
+ifneq (,$(filter $(NODEP_TARGETS),$(MAKECMDGOALS)))
+depinc := 0
+endif
+ifneq (,$(fitler-out $(NODEP_TARGETS),$(MAKECMDGOALS)))
+depinc := 1
+endif
+
+ifeq ($(depinc),1)
+-include $(DEPFILES)
+endif
diff --git a/README b/README
new file mode 100644
index 0000000..0fa3ede
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+Requirments: alsa, gtk+, glib, expat
+
+Getting started guide:
+-to compile: make
+-to run: ./gdigi
+
+Commandline options:
+--device (-d)
+
+Example:
+gdigi -d hw:1,0,0
+gdigi --device=hw:1,0,0
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..6a1e154
--- /dev/null
+++ b/TODO
@@ -0,0 +1,6 @@
+-make complete gui (expression pedal settings, usb settings, effect level, preset level)
+-handling presets (saving, exporting to xml patches)
+-buildsystem (install knob.png to share dir, don't use inline knob pixbuf)
+-various fixes to MIDI IN messages handling
+-ask user which device to use if more than one DigiTech device is found
+-optimizations
diff --git a/effects.c b/effects.c
new file mode 100644
index 0000000..36649a2
--- /dev/null
+++ b/effects.c
@@ -0,0 +1,3317 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#include "gdigi.h"
+#include "effects.h"
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+static gchar *wave_labels[] = {
+ "Tri",
+ "Sine",
+ "Square",
+ NULL,
+};
+
+static gchar *whammy_labels[] = {
+ "OctUp",
+ "2OctUp",
+ "2ndDn",
+ "Rv2nd",
+ "4thDn",
+ "OctDn",
+ "2OctDn",
+ "DivBmb",
+ "M3>Ma3",
+ "2ndMa3",
+ "3rd4th",
+ "4th5th",
+ "5thOct",
+ "HOctUp",
+ "HOctDn",
+ "OctU>D",
+ NULL,
+};
+
+static gchar *ips_shift_labels[] = {
+ "Oct Dn",
+ "7th Dn",
+ "6th Dn",
+ "5th Dn",
+ "4th Dn",
+ "3rd Dn",
+ "2nd Dn",
+ "2nd Up",
+ "3rd Up",
+ "4th Up",
+ "5th Up",
+ "6th Up",
+ "7th Up",
+ "Oct Up",
+ NULL,
+};
+
+static gchar *ips_key_labels[] = {
+ "E",
+ "F",
+ "Gb",
+ "G",
+ "Ab",
+ "A",
+ "Bb",
+ "B",
+ "C",
+ "Db",
+ "D",
+ "Eb",
+ NULL,
+};
+
+static gchar *ips_scale_labels[] = {
+ "Major",
+ "Minor",
+ "Dorian",
+ "Mixolydian",
+ "Lydian",
+ "HMinor",
+ NULL,
+};
+
+static gchar *on_off_labels[] = {
+ "Off",
+ "On",
+ NULL,
+};
+
+static gchar *odd_even_labels[] = {
+ "Odd",
+ "Even",
+ NULL,
+};
+
+static gchar *chorus_vibrato_labels[] = {
+ "Chorus",
+ "Vibrato",
+ NULL,
+};
+
+static gchar *hp_lp_labels[] = {
+ "HP",
+ "LP",
+ NULL,
+};
+
+static gchar *loose_tight_labels[] = {
+ "Loose",
+ "Tight",
+ NULL,
+};
+
+static gchar *pickup_type_labels[] = {
+ "SC>HB",
+ "HB>SC",
+ NULL,
+};
+
+static gchar *fast_medium_slow_labels[] = {
+ "Fast",
+ "Medium",
+ "Slow",
+ NULL,
+};
+
+static gchar *comp_ratio_labels[] = {
+ "1.2:1",
+ "1.5:1",
+ "1.8:1",
+ "2.0:1",
+ "2.5:1",
+ "3:1",
+ "4:1",
+ "5:1",
+ "8:1",
+ "10:1",
+ "20:1",
+ "Inf:1",
+ NULL,
+};
+
+static gchar *eq_bandwidth_labels[] = {
+ "Wide",
+ "Medium",
+ "Narrow",
+ NULL,
+};
+
+static gchar *eq_low_freq_labels[] = {
+ "60Hz",
+ "63Hz",
+ "67Hz",
+ "71Hz",
+ "75Hz",
+ "80Hz",
+ "85Hz",
+ "90Hz",
+ "95Hz",
+ "100Hz",
+ "106Hz",
+ "112Hz",
+ "118Hz",
+ "125Hz",
+ "132Hz",
+ "140Hz",
+ "150Hz",
+ "160Hz",
+ "170Hz",
+ "180Hz",
+ "190Hz",
+ "200Hz",
+ "212Hz",
+ "224Hz",
+ "236Hz",
+ "250Hz",
+ "265Hz",
+ "280Hz",
+ "300Hz",
+ "315Hz",
+ "335Hz",
+ "355Hz",
+ "375Hz",
+ "400Hz",
+ "425Hz",
+ "450Hz",
+ "475Hz",
+ "500Hz",
+ NULL,
+};
+
+static gchar *eq_mid_freq_labels[] = {
+ "300Hz",
+ "315Hz",
+ "335Hz",
+ "355Hz",
+ "375Hz",
+ "400Hz",
+ "425Hz",
+ "450Hz",
+ "475Hz",
+ "500Hz",
+ "530Hz",
+ "560Hz",
+ "600Hz",
+ "630Hz",
+ "670Hz",
+ "710Hz",
+ "750Hz",
+ "800Hz",
+ "850Hz",
+ "900Hz",
+ "950Hz",
+ "1kHz",
+ "1.06kHz",
+ "1.12kHz",
+ "1.18kHz",
+ "1.25kHz",
+ "1.32kHz",
+ "1.4kHz",
+ "1.5kHz",
+ "1.6kHz",
+ "1.7kHz",
+ "1.8kHz",
+ "1.9kHz",
+ "2kHz",
+ "2.12kHz",
+ "2.24kHz",
+ "2.36kHz",
+ "2.5kHz",
+ "2.65kHz",
+ "2.8kHz",
+ "3kHz",
+ "3.15kHz",
+ "3.35kHz",
+ "3.55kHz",
+ "3.75kHz",
+ "4kHz",
+ NULL,
+};
+
+static gchar *eq_high_freq_labels[] = {
+ "2kHz",
+ "2.12kHz",
+ "2.24kHz",
+ "2.36kHz",
+ "2.5kHz",
+ "2.65kHz",
+ "2.8kHz",
+ "3kHz",
+ "3.15kHz",
+ "3.35kHz",
+ "3.55kHz",
+ "3.75kHz",
+ "4kHz",
+ "4.25kHz",
+ "4.5kHz",
+ "4.75kHz",
+ "5kHz",
+ "5.3kHz",
+ "5.6kHz",
+ "6kHz",
+ "6.3kHz",
+ "6.7kHz",
+ "7.1kHz",
+ "7.5kHz",
+ "8kHz",
+ NULL,
+};
+
+static gchar *amp_channel_labels[] = {
+ "1",
+ "2",
+ "Warped",
+ NULL,
+};
+
+static gchar *rhold_labels[] = {
+ "RHold",
+ NULL,
+};
+
+static EffectValues values_1_2_warp = {
+ .min = 0.0, .max = 2.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = amp_channel_labels,
+};
+
+static EffectValues values_0_to_99 = {
+ .min = 0.0, .max = 99.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_1_to_4 = {
+ .min = 0.0, .max = 3.0,
+ .type = VALUE_TYPE_OFFSET,
+ .offset = 1,
+};
+
+static EffectValues values_warp_0_to_98 = {
+ .min = 0.0, .max = 98.0,
+ .type = VALUE_TYPE_OFFSET,
+ .offset = 1,
+};
+
+static EffectValues values_0_to_9 = {
+ .min = 0.0, .max = 9.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_0_to_49 = {
+ .min = 0.0, .max = 49.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_0_to_12 = {
+ .min = 0.0, .max = 12.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_0_to_15 = {
+ .min = 0.0, .max = 15.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_0_to_20 = {
+ .min = 0.0, .max = 20.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_m12_to_12_semitones = {
+ /** \todo make this display properly (display range -12.0 to 12.0 semitones) */
+ .min = 0.0, .max = 48.0, .type = VALUE_TYPE_PLAIN,
+/* .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET,
+ .suffix = "semitones", .offset = -12, */
+};
+
+static EffectValues values_m24_to_24_step2 = {
+ .min = 0.0, .max = 24.0,
+ .type = VALUE_TYPE_OFFSET | VALUE_TYPE_STEP,
+ .offset = -12, .step = 2.0,
+};
+
+static EffectValues values_m24_to_24 = {
+ .min = 0.0, .max = 48.0,
+ .type = VALUE_TYPE_OFFSET,
+ .offset = -24,
+};
+
+static EffectValues values_m12_to_24 = {
+ .min = 0.0, .max = 36.0,
+ .type = VALUE_TYPE_OFFSET,
+ .offset = -12,
+};
+
+static EffectValues values_comp_ratio = {
+ .min = 0.0, .max = 12.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = comp_ratio_labels,
+};
+
+static EffectValues values_fast_medium_slow = {
+ .min = 0.0, .max = 2.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = fast_medium_slow_labels,
+};
+
+static EffectValues values_eq_db = {
+ .min = 0.0, .max = 24.0,
+ .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET,
+ .suffix = "dB", .offset = -12,
+};
+
+static EffectValues values_eq_bass_hz = {
+ .min = 0.0, .max = 250.0,
+ .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET,
+ .suffix = "hz", .offset = 50,
+};
+
+static EffectValues values_eq_mid_hz = {
+ .min = 0.0, .max = 4700.0,
+ .type = VALUE_TYPE_OFFSET,
+ .offset = 300,
+};
+
+static EffectValues values_eq_treb_hz = {
+ .min = 0.0, .max = 7500.0,
+ .type = VALUE_TYPE_OFFSET,
+ .offset = 500,
+};
+
+static EffectValues values_eq_bandwidth = {
+ .min = 0.0, .max = 2.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = eq_bandwidth_labels,
+};
+
+static EffectValues values_eq_low_freq = {
+ .min = 0.0, .max = 37.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = eq_low_freq_labels,
+};
+
+static EffectValues values_eq_mid_freq = {
+ .min = 0.0, .max = 45.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = eq_mid_freq_labels,
+};
+
+static EffectValues values_eq_high_freq = {
+ .min = 0.0, .max = 24.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = eq_high_freq_labels,
+};
+
+static EffectValues values_200hz_to_1_5khz = {
+ /** \todo make this display properly (display range 200 Hz to 1.5 kHz) */
+ .min = 0.0, .max = 130.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_waveform = {
+ .min = 0.0, .max = 2.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = wave_labels,
+};
+
+static EffectValues values_balance = {
+ /** \todo make this display properly */
+ 0.0, 198.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_synth_talk_release = {
+ /** \todo make last value display properly */
+ 0.0, 100.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_whammy_amount = {
+ .min = 0.0, .max = 15.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = whammy_labels,
+};
+
+static EffectValues values_ips_shift = {
+ .min = 0.0, .max = 13.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = ips_shift_labels,
+};
+
+static EffectValues values_ips_key = {
+ .min = 0.0, .max = 11.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = ips_key_labels,
+};
+
+static EffectValues values_ips_scale = {
+ .min = 0.0, .max = 5.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = ips_scale_labels,
+};
+
+static EffectValues values_predelay_time = {
+ .min = 0.0, .max = 19.0,
+ .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET,
+ .suffix = "ms", .offset = 1,
+};
+
+static EffectValues values_delay_time_extra = {
+ /* display as 1.0 sec (99) to 5.0 sec (139) */
+ .min = 99.0, .max = 139.0,
+ .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET |
+ VALUE_TYPE_STEP | VALUE_TYPE_DECIMAL,
+ .suffix = "sec", .offset = -89,
+ .step = 0.1, .decimal = 1,
+};
+
+static EffectValues values_delay_time = {
+ /* 0 to 139, extended by values_delay_time_extra */
+ .min = 0.0, .max = 98.0,
+ .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET |
+ VALUE_TYPE_STEP | VALUE_TYPE_EXTRA,
+ .suffix = "msec", .offset = 1,
+ .step = 10.0, .extra = &values_delay_time_extra,
+};
+
+static EffectValues values_delay_time_110_870 = {
+ .min = 0.0, .max = 760.0,
+ .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET,
+ .suffix = "ms", .offset = 110,
+};
+
+static EffectValues values_delay_time_0_2000 = {
+ /** \todo make this display properly */
+ 0.0, 2000.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_delay_time_0_4650 = {
+ /** \todo make this display properly */
+ 0.0, 4650.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_delay_time_0_4990 = {
+ /** \todo make this display properly */
+ 0.0, 4990.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_delay_time_0_5000 = {
+ /** \todo make this display properly */
+ 0.0, 5000.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_delay_repeats_extra = {
+ .min = 100.0, .max = 100.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = rhold_labels
+};
+
+static EffectValues values_delay_repeats = {
+ /* 0 to 100, extended by values_delay_repeats_extra */
+ .min = 0.0, .max = 99.0,
+ .type = VALUE_TYPE_EXTRA,
+ .extra = &values_delay_repeats_extra,
+};
+
+static EffectValues values_delay_thresh = {
+ /** \todo make last value display properly */
+ 0.0, 100.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_delay_repeat_rate_24_310 = {
+ .min = 0.0, .max = 286.0,
+ .type = VALUE_TYPE_SUFFIX | VALUE_TYPE_OFFSET,
+ .suffix = "ms", .offset = 24,
+};
+
+static EffectValues values_delay_spread_0_49 = {
+ /** \todo make this display properly */
+ 0.0, 49.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectValues values_on_off = {
+ .min = 0.0, .max = 1.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = on_off_labels,
+};
+
+static EffectValues values_odd_even = {
+ .min = 0.0, .max = 1.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = odd_even_labels,
+};
+
+static EffectValues values_chorus_vibrato = {
+ .min = 0.0, .max = 1.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = chorus_vibrato_labels,
+};
+
+static EffectValues values_hp_lp = {
+ .min = 0.0, .max = 1.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = hp_lp_labels,
+};
+
+static EffectValues values_loose_tight = {
+ .min = 0.0, .max = 1.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = loose_tight_labels,
+};
+
+static EffectValues values_pickup_type = {
+ .min = 0.0, .max = 1.0,
+ .type = VALUE_TYPE_LABEL,
+ .labels = pickup_type_labels,
+};
+
+static EffectValues values_1_to_10_step_0p1 = {
+ .min = 0.0, .max = 90.0,
+ .type = VALUE_TYPE_OFFSET | VALUE_TYPE_STEP | VALUE_TYPE_DECIMAL,
+ .offset = 10, .step = 0.1, .decimal = 1,
+};
+
+static EffectValues values_rp_mix = {
+ /** \todo make this display properly (USB 0, USB 1, USB 2 ... USB 49, USB RP, RP 49, RP 48 ... RP 1, RP 0) */
+ .min = 0.0, .max = 100.0, .type = VALUE_TYPE_PLAIN,
+};
+
+static EffectSettings usb_settings[] = {
+ {"USB/RP Mix", USB_AUDIO_PLAYBACK_MIX, USB_POSITION, &values_rp_mix},
+ {"USB Level", USB_AUDIO_LEVEL, USB_POSITION, &values_m12_to_24},
+};
+
+static EffectSettings misc_settings[] = {
+ {"Preset Level", PRESET_LEVEL, PRESET_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_wah_settings[] = {
+ {"Min", WAH_MIN, WAH_POSITION_MIN_MAX, &values_0_to_99},
+ {"Max", WAH_MAX, WAH_POSITION_MIN_MAX, &values_0_to_99},
+};
+
+static EffectSettings wah_settings[] = {
+ {"Min", WAH_MIN, WAH_POSITION_MIN_MAX, &values_0_to_99},
+ {"Max", WAH_MAX, WAH_POSITION_MIN_MAX, &values_0_to_99},
+ {"Level", WAH_LEVEL, WAH_POSITION, &values_0_to_12},
+};
+
+static EffectSettings gnx3k_whammy_settings[] = {
+ {"Shift Amount", WHAMMY_AMOUNT, GNX3K_WHAM_POSITION, &values_whammy_amount},
+ {"Pedal", WHAMMY_PEDAL, GNX3K_WHAM_POSITION, &values_0_to_99},
+ {"Mix", WHAMMY_MIX, GNX3K_WHAM_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_ips_settings[] = {
+ {"Shift Amount", IPS_SHIFT_AMOUNT, GNX3K_WHAM_POSITION, &values_ips_shift},
+ {"Scale", IPS_SCALE, GNX3K_WHAM_POSITION, &values_ips_scale},
+ {"Key", IPS_KEY, GNX3K_WHAM_POSITION, &values_ips_key},
+ {"Level", IPS_LEVEL, GNX3K_WHAM_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_detune_settings[] = {
+ {"Shift Amount", GNX3K_DETUNE_AMOUNT, GNX3K_WHAM_POSITION, &values_m24_to_24_step2},
+ {"Level", DETUNE_LEVEL, GNX3K_WHAM_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_pitch_settings[] = {
+ {"Shift Amount", GNX3K_PITCH_AMOUNT, GNX3K_WHAM_POSITION, &values_m24_to_24},
+ {"Level", GNX3K_PITCH_LEVEL, GNX3K_WHAM_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_talk_settings[] = {
+ {"Mic Level", GNX3K_TALK_LEVEL, GNX3K_WHAM_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_amp_channel_settings[] = {
+ {"Amp Channel", GNX_CHANNEL_AMP, GNX_CHANNEL_POSITION, &values_1_2_warp},
+ {"Warp", GNX_WARP, GNX_CHANNEL_POSITION, &values_warp_0_to_98},
+ {"Amp Warp", GNX_AMP_WARP, GNX_CHANNEL_POSITION, &values_warp_0_to_98},
+ {"Cabinet Warp", GNX_CABINET_WARP, GNX_CHANNEL_POSITION, &values_warp_0_to_98},
+};
+
+static EffectSettings gnx3k_preset_settings[] = {
+ {"Preset Level", PRESET_LEVEL, PRESET_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx_comp_settings[] = {
+ {"Attack", GNX3K_COMP_ATTACK, COMP_POSITION, &values_fast_medium_slow},
+ {"Ratio", GNX3K_COMP_RATIO, COMP_POSITION, &values_comp_ratio},
+ {"Threshold", GNX3K_COMP_THRESHOLD, COMP_POSITION, &values_0_to_99},
+ {"Gain", GNX3K_COMP_GAIN, COMP_POSITION, &values_0_to_20},
+};
+
+static EffectSettings comp_digi_settings[] = {
+ {"Sustain", COMP_SUSTAIN, COMP_POSITION, &values_0_to_99},
+ {"Tone", COMP_TONE, COMP_POSITION, &values_0_to_99},
+ {"Attack", COMP_ATTACK, COMP_POSITION, &values_0_to_99},
+ {"Level", COMP_LEVEL, COMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings comp_cs_settings[] = {
+ {"Sustain", COMP_SUSTAIN, COMP_POSITION, &values_0_to_99},
+ {"Attack", COMP_ATTACK, COMP_POSITION, &values_0_to_99},
+ {"Level", COMP_LEVEL, COMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings comp_dyna_settings[] = {
+ {"Sensitivity", COMP_SENSITIVITY, COMP_POSITION, &values_0_to_99},
+ {"Output", COMP_OUTPUT, COMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_screamer_settings[] = {
+ {"Drive", DIST_SCREAMER_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_SCREAMER_TONE, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_SCREAMER_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_808_settings[] = {
+ {"Overdrive", DIST_808_OVERDRIVE, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_808_TONE, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_808_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_ts_mod_settings[] = {
+ {"Drive", DIST_TS_MOD_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_TS_MOD_TONE, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_TS_MOD_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_sd_odrv_settings[] = {
+ {"Drive", DIST_SD_ODRV_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_SD_ODRV_TONE, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_SD_ODRV_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_od_odrv_settings[] = {
+ {"Overdrive", DIST_OD_ODRV_OVERDRIVE, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_OD_ODRV_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_sparkdrive_settings[] = {
+ {"Gain", DIST_SPARKDRIVE_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_SPARKDRIVE_TONE, DIST_POSITION, &values_0_to_99},
+ {"Clean", DIST_SPARKDRIVE_CLEAN, DIST_POSITION, &values_0_to_99},
+ {"Volume", DIST_SPARKDRIVE_VOLUME, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_guyod_settings[] = {
+ {"Drive", DIST_GUYOD_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_GUYOD_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_dod250_settings[] = {
+ {"Gain", DIST_DOD250_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_DOD250_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_redline_settings[] = {
+ {"Gain", DIST_REDLINE_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Low", DIST_REDLINE_LOW, DIST_POSITION, &values_0_to_99},
+ {"High", DIST_REDLINE_HIGH, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_REDLINE_LEVEL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_ampdrivr_settings[] = {
+ {"Gain", DIST_AMPDRIVR_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Mid Boost", DIST_AMPDRIVR_MIDBOOST, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_AMPDRIVR_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_oc_drive_settings[] = {
+ {"Drive", DIST_OC_DRIVE_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_OC_DRIVE_TONE, DIST_POSITION, &values_0_to_99},
+ {"HP/LP", DIST_OC_DRIVE_HP_LP, DIST_POSITION, &values_hp_lp},
+ {"Level", DIST_OC_DRIVE_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_rodent_settings[] = {
+ {"Dist", DIST_RODENT_DIST, DIST_POSITION, &values_0_to_99},
+ {"Filter", DIST_RODENT_FILTER, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_RODENT_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_mx_settings[] = {
+ {"Dist", DIST_MX_DIST, DIST_POSITION, &values_0_to_99},
+ {"Output", DIST_MX_OUTPUT, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_ds_settings[] = {
+ {"Gain", DIST_DS_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_DS_TONE, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_DS_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_grunge_settings[] = {
+ {"Grunge", DIST_GRUNGE_GRUNGE, DIST_POSITION, &values_0_to_99},
+ {"Face", DIST_GRUNGE_FACE, DIST_POSITION, &values_0_to_99},
+ {"Loud", DIST_GRUNGE_LOUD, DIST_POSITION, &values_0_to_99},
+ {"Butt", DIST_GRUNGE_BUTT, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_zone_settings[] = {
+ {"Gain", DIST_ZONE_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Low", DIST_ZONE_LOW, DIST_POSITION, &values_0_to_99},
+ {"Mid level", DIST_ZONE_MID_LVL, DIST_POSITION, &values_0_to_99},
+ {"Mid freq", DIST_ZONE_MID_FREQ, DIST_POSITION, &values_0_to_99},
+ {"High", DIST_ZONE_HIGH, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_ZONE_LEVEL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_death_settings[] = {
+ {"Low", DIST_DEATH_LOW, DIST_POSITION, &values_0_to_99},
+ {"Mid", DIST_DEATH_MID, DIST_POSITION, &values_0_to_99},
+ {"High", DIST_DEATH_HIGH, DIST_POSITION, &values_0_to_99},
+ {"Level", DIST_DEATH_LVL, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_gonk_settings[] = {
+ {"Gonk", DIST_GONK_GONK, DIST_POSITION, &values_0_to_99},
+ {"Smear", DIST_GONK_SMEAR, DIST_POSITION, &values_0_to_99},
+ {"Suck", DIST_GONK_SUCK, DIST_POSITION, &values_0_to_99},
+ {"Heave", DIST_GONK_HEAVE, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_8tavia_settings[] = {
+ {"Drive", DIST_8TAVIA_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Volume", DIST_8TAVIA_VOLUME, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_fuzzlator_settings[] = {
+ {"Fuzz", DIST_FUZZLATOR_FUZZ, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_FUZZLATOR_TONE, DIST_POSITION, &values_0_to_99},
+ {"LooseTight", DIST_FUZZLATOR_LOOSETIGHT, DIST_POSITION, &values_loose_tight},
+ {"Volume", DIST_FUZZLATOR_VOLUME, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_classic_fuzz_settings[] = {
+ {"Fuzz", DIST_CLASSIC_FUZZ_FUZZ, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_CLASSIC_FUZZ_TONE, DIST_POSITION, &values_0_to_99},
+ {"Volume", DIST_CLASSIC_FUZZ_VOLUME, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_fuzzy_settings[] = {
+ {"Fuzz", DIST_FUZZY_FUZZ, DIST_POSITION, &values_0_to_99},
+ {"Volume", DIST_FUZZY_VOLUME, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings dist_mp_settings[] = {
+ {"Sustain", DIST_MP_SUSTAIN, DIST_POSITION, &values_0_to_99},
+ {"Tone", DIST_MP_TONE, DIST_POSITION, &values_0_to_99},
+ {"Volume", DIST_MP_VOLUME, DIST_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp250_amp_settings[] = {
+ {"Gain", AMP_GAIN, AMP_POSITION, &values_0_to_99},
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp250_amp_settings2[] = {
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp355_amp_settings_A[] = {
+ {"Gain", AMP_GAIN, AMP_POSITION, &values_0_to_99},
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp355_amp_settings_B[] = {
+ {"Gain", AMP_GAIN, CH2_AMP_POSITION, &values_0_to_99},
+ {"Level", AMP_LEVEL, CH2_AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp355_amp_settings2_A[] = {
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp355_amp_settings2_B[] = {
+ {"Level", AMP_LEVEL, CH2_AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_amp_settings[] = {
+ {"Gain", AMP_GAIN, AMP_POSITION, &values_0_to_99},
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+ {"Bass", AMP_BASS, AMP_POSITION, &values_1_to_10_step_0p1},
+ {"Mid", AMP_MID, AMP_POSITION, &values_1_to_10_step_0p1},
+ {"Treble", AMP_TREBLE, AMP_POSITION, &values_1_to_10_step_0p1},
+};
+
+static EffectSettings rp500_amp_settings2[] = {
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+ {"Bass", AMP_BASS, AMP_POSITION, &values_1_to_10_step_0p1},
+ {"Mid", AMP_MID, AMP_POSITION, &values_1_to_10_step_0p1},
+ {"Treble", AMP_TREBLE, AMP_POSITION, &values_1_to_10_step_0p1},
+};
+
+static EffectSettings rp500_amp_settings3[] = {
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_ch1_cab_tuning_settings[] = {
+ {"Tuning", AMP_CAB_TUNING, AMP_CAB_POSITION, &values_m12_to_12_semitones},
+};
+
+static EffectSettings gnx3k_ch2_cab_tuning_settings[] = {
+ {"Tuning", AMP_CAB_TUNING, CH2_AMP_CAB_POSITION, &values_m12_to_12_semitones},
+};
+
+static EffectSettings gnx3k_ch1_amp_eq_settings[] = {
+ {"Gain", AMP_GAIN, AMP_POSITION, &values_0_to_99},
+ {"Bass Freq", AMP_BASS_FREQ, AMP_POSITION, &values_eq_bass_hz},
+ {"Bass Level", AMP_BASS_LEVEL, AMP_POSITION, &values_eq_db},
+ {"Mid Freq", AMP_MID_FREQ, AMP_POSITION, &values_eq_mid_hz},
+ {"Mid Level", AMP_MID_LEVEL, AMP_POSITION, &values_eq_db},
+ {"Treb Freq", AMP_TREBLE_FREQ, AMP_POSITION, &values_eq_treb_hz},
+ {"Treb Level", AMP_TREBLE_LEVEL, AMP_POSITION, &values_eq_db},
+ {"Presence", AMP_PRESENCE, AMP_POSITION, &values_eq_db},
+ {"Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_ch2_amp_eq_settings[] = {
+ {"Gain", AMP_GAIN, CH2_AMP_POSITION, &values_0_to_99},
+ {"Bass Freq", AMP_BASS_FREQ, CH2_AMP_POSITION, &values_eq_bass_hz},
+ {"Bass Level", AMP_BASS_LEVEL, CH2_AMP_POSITION, &values_eq_db},
+ {"Mid Freq", AMP_MID_FREQ, CH2_AMP_POSITION, &values_eq_mid_hz},
+ {"Mid Level", AMP_MID_LEVEL, CH2_AMP_POSITION, &values_eq_db},
+ {"Treb Freq", AMP_TREBLE_FREQ, CH2_AMP_POSITION, &values_eq_treb_hz},
+ {"Treb Level", AMP_TREBLE_LEVEL, CH2_AMP_POSITION, &values_eq_db},
+ {"Presence", AMP_PRESENCE, CH2_AMP_POSITION, &values_eq_db},
+ {"Level", AMP_LEVEL, CH2_AMP_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp250_eq_settings[] = {
+ {"Bass", EQ_BASS, EQ_POSITION, &values_eq_db},
+ {"Mid", EQ_MID, EQ_POSITION, &values_eq_db},
+ {"Treble", EQ_TREBLE, EQ_POSITION, &values_eq_db},
+ {"Mid Hz", EQ_MID_HZ, EQ_POSITION, &values_eq_mid_hz},
+ {"Treb Hz", EQ_TREBLE_HZ, EQ_POSITION, &values_eq_treb_hz},
+};
+
+static EffectSettings rp355_eq_settings_A[] = {
+ {"Bass", EQ_BASS, EQ_POSITION, &values_eq_db},
+ {"Mid", EQ_MID, EQ_POSITION, &values_eq_db},
+ {"Treble", EQ_TREBLE, EQ_POSITION, &values_eq_db},
+ {"Mid Hz", EQ_MID_HZ, EQ_POSITION, &values_eq_mid_hz},
+ {"Treb Hz", EQ_TREBLE_HZ, EQ_POSITION, &values_eq_treb_hz},
+ {"Presence", EQ_PRESENCE, EQ_POSITION, &values_eq_db},
+};
+
+static EffectSettings rp355_eq_settings_B[] = {
+ {"Bass", EQ_BASS, EQ_POSITION_B, &values_eq_db},
+ {"Mid", EQ_MID, EQ_POSITION_B, &values_eq_db},
+ {"Treble", EQ_TREBLE, EQ_POSITION_B, &values_eq_db},
+ {"Mid Hz", EQ_MID_HZ, EQ_POSITION_B, &values_eq_mid_hz},
+ {"Treb Hz", EQ_TREBLE_HZ, EQ_POSITION_B, &values_eq_treb_hz},
+ {"Presence", EQ_PRESENCE, EQ_POSITION_B, &values_eq_db},
+};
+
+static EffectSettings rp500_eq_settings[] = {
+ {"Low Level", EQ_LOW_LEVEL, EQ_POSITION, &values_eq_db},
+ {"Mid Level", EQ_MID_LEVEL, EQ_POSITION, &values_eq_db},
+ {"High Level", EQ_HIGH_LEVEL, EQ_POSITION, &values_eq_db},
+ {"Low Freq", EQ_LOW_FREQ, EQ_POSITION, &values_eq_low_freq},
+ {"Mid Freq", EQ_MID_FREQ, EQ_POSITION, &values_eq_mid_freq},
+ {"High Freq", EQ_HIGH_FREQ, EQ_POSITION, &values_eq_high_freq},
+ {"Low Bandwidth", EQ_LOW_BANDWIDTH, EQ_POSITION, &values_eq_bandwidth},
+ {"Mid Bandwidth", EQ_MID_BANDWIDTH, EQ_POSITION, &values_eq_bandwidth},
+ {"High Bandwidth", EQ_HIGH_BANDWIDTH, EQ_POSITION, &values_eq_bandwidth},
+};
+
+static EffectSettings noisegate_silencer_settings[] = {
+ {"Threshold", NOISEGATE_GATE_TRESHOLD, NOISEGATE_POSITION, &values_0_to_99},
+ {"Attack", GNX3K_GATE_ATTACK, NOISEGATE_POSITION, &values_0_to_9},
+};
+
+static EffectSettings noisegate_pluck_settings[] = {
+ {"Threshold", NOISEGATE_GATE_TRESHOLD, NOISEGATE_POSITION, &values_0_to_99},
+ {"Attack", GNX3K_GATE_ATTACK, NOISEGATE_POSITION, &values_0_to_9},
+ {"Sens", NOISEGATE_SWELL_SENS, NOISEGATE_POSITION, &values_0_to_99},
+};
+
+static EffectSettings noisegate_gate_settings[] = {
+ {"Treshold", NOISEGATE_GATE_TRESHOLD, NOISEGATE_POSITION, &values_0_to_99},
+ {"Attack", NOISEGATE_ATTACK, NOISEGATE_POSITION, &values_0_to_99},
+ {"Release", NOISEGATE_RELEASE, NOISEGATE_POSITION, &values_0_to_99},
+ {"Attn", NOISEGATE_ATTN, NOISEGATE_POSITION, &values_0_to_99},
+};
+
+static EffectSettings noisegate_swell_settings[] = {
+ {"Sens", NOISEGATE_SWELL_SENS, NOISEGATE_POSITION, &values_0_to_99},
+ {"Attack", NOISEGATE_ATTACK, NOISEGATE_POSITION, &values_0_to_99},
+ {"Release", NOISEGATE_RELEASE, NOISEGATE_POSITION, &values_0_to_99},
+ {"Attn", NOISEGATE_ATTN, NOISEGATE_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_chorus_settings[] = {
+ {"Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", CHORUS_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Predelay", CHORUS_PREDELAY, CHORUSFX_POSITION, &values_predelay_time},
+ {"Wave", CHORUS_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Balance", CHORUS_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Level", CHORUS_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_flanger_settings[] = {
+ {"Speed", FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", FLANGER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Regen", FLANGER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Waveform", FLANGER_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Balance", FLANGER_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Mix", FLANGER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_phaser_settings[] = {
+ {"Speed", PHASER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", PHASER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Regen", PHASER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Waveform", PHASER_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Balance", PHASER_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Level", PHASER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_trigflanger_settings[] = {
+ {"Speed", TRIG_FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Sens", TRIG_FLANGER_SENS, CHORUSFX_POSITION, &values_0_to_99},
+ {"Lfo Start", TRIG_FLANGER_LFO_START, CHORUSFX_POSITION, &values_0_to_99},
+ {"Mix", TRIG_FLANGER_MIX, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_trigphaser_settings[] = {
+ {"Speed", TRIG_PHASER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Sens", TRIG_PHASER_SENS, CHORUSFX_POSITION, &values_0_to_99},
+ {"Lfo Start", TRIG_PHASER_LFO_START, CHORUSFX_POSITION, &values_0_to_99},
+ {"Mix", TRIG_FLANGER_MIX, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_unovibe_settings[] = {
+ {"Chorus/Vibrato", UNOVIBE_CHORUS_VIBRATO, CHORUSFX_POSITION, &values_chorus_vibrato},
+ {"Intensity", UNOVIBE_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Pedal Speed", UNOVIBE_PEDAL_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_vibrato_settings[] = {
+ {"Speed", VIBRATO_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", VIBRATO_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Waveform", VIBRATO_WAVEFORM, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings gnx3k_rotary_settings[] = {
+ {"Speed", ROTARY_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", ROTARY_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Doppler", ROTARY_DOPPLER, CHORUSFX_POSITION, &values_0_to_99},
+ {"X-Over", ROTARY_CROSSOVER, CHORUSFX_POSITION, &values_200hz_to_1_5khz},
+ {"Balance", ROTARY_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Mix", ROTARY_MIX, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_autoya_settings[] = {
+ {"Speed", AUTOYA_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", AUTOYA_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", GNX3K_AUTOYA_RANGE, CHORUSFX_POSITION, &values_0_to_49},
+ {"Balance", AUTOYA_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Mix", AUTOYA_MIX, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_yaya_settings[] = {
+ {"Pedal", YAYA_PEDAL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", YAYA_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", GNX3K_YAYA_RANGE, CHORUSFX_POSITION, &values_0_to_49},
+ {"Balance", YAYA_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Mix", YAYA_MIX, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_synthtalk_settings[] = {
+ {"Attack", SYNTH_TALK_ATTACK, CHORUSFX_POSITION, &values_0_to_99},
+ {"Release", GNX3K_SYNTH_TALK_RELEASE, CHORUSFX_POSITION, &values_synth_talk_release},
+ {"Sens", SYNTH_TALK_SENS, CHORUSFX_POSITION, &values_0_to_99},
+ {"Vox", SYNTH_TALK_VOX, CHORUSFX_POSITION, &values_0_to_99},
+ {"Balance", SYNTH_TALK_BALANCE, CHORUSFX_POSITION, &values_balance},
+};
+
+static EffectSettings gnx3k_envelope_settings[] = {
+ {"Sensitivity", ENVELOPE_SENSITIVITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", ENVELOPE_RANGE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Balance", ENVELOPE_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Mix", ENVELOPE_MIX, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_mod_detune_settings[] = {
+ {"Shift Amount", DETUNE_AMOUNT, CHORUSFX_POSITION, &values_m24_to_24},
+ {"Balance", DETUNE_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Level", DETUNE_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_mod_pitch_settings[] = {
+ {"Shift Amount", PITCH_AMOUNT, CHORUSFX_POSITION, &values_m12_to_24},
+ {"Balance", PITCH_BALANCE, CHORUSFX_POSITION, &values_balance},
+ {"Level", GNX3K_PITCH_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_ce_settings[] = {
+ {"Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", CHORUS_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_tc_settings[] = {
+ {"Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Width", CHORUS_WIDTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", CHORUS_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_dual_settings[] = {
+ {"Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", CHORUS_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Level", CHORUS_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Wave", CHORUS_WAVE, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings chorusfx_glisten_settings[] = {
+ {"Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", CHORUS_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Level", CHORUS_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_multi_settings[] = {
+ {"Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", CHORUS_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Level", CHORUS_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Wave", CHORUS_WAVE, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings chorusfx_voo_doo_settings[] = {
+ {"Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", CHORUS_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_clone_settings[] = {
+ {"Rate", CHORUS_RATE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", CHORUS_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_flanger_settings[] = {
+ {"Speed", FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", FLANGER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Regen", FLANGER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Level", FLANGER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Wave", FLANGER_WAVE, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings chorusfx_trig_flanger_settings[] = {
+ {"Speed", TRIG_FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Sens", TRIG_FLANGER_SENS, CHORUSFX_POSITION, &values_0_to_99},
+ {"Lfo Start", TRIG_FLANGER_LFO_START, CHORUSFX_POSITION, &values_0_to_99},
+ {"Level", TRIG_FLANGER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_fltflanger_settings[] = {
+ {"Speed", FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", FLANGER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Regen", FLANGER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Frequency", FLTFLANGER_FREQ, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_mxr_flanger_settings[] = {
+ {"Speed", FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Width", MXR_FLANGER_WIDTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Regen", FLANGER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Manual", MXR_FLANGER_MANUAL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_eh_flanger_settings[] = {
+ {"Rate", EH_FLANGER_RATE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", EH_FLANGER_RANGE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Color", EH_FLANGER_COLOR, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_ad_flanger_settings[] = {
+ {"Speed", FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Enhance", AD_FLANGER_ENHANCE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", EH_FLANGER_RANGE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Harmonics", AD_FLANGER_HARMONICS, CHORUSFX_POSITION, &values_odd_even},
+ {"Manual", MXR_FLANGER_MANUAL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_phaser_settings[] = {
+ {"Speed", PHASER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", PHASER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Regen", PHASER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Level", PHASER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Wave", PHASER_WAVE, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings chorusfx_trig_phaser_settings[] = {
+ {"Speed", TRIG_PHASER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Sens", TRIG_PHASER_SENS, CHORUSFX_POSITION, &values_0_to_99},
+ {"Lfo Start", TRIG_PHASER_LFO_START, CHORUSFX_POSITION, &values_0_to_99},
+ {"Level", TRIG_PHASER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_mx_phaser_settings[] = {
+ {"Speed", PHASER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", MX_PHASER_INTENSITY, CHORUSFX_POSITION, &values_1_to_4},
+};
+
+static EffectSettings chorusfx_eh_phaser_settings[] = {
+ {"Rate", EH_PHASER_RATE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Color", EH_PHASER_COLOR, CHORUSFX_POSITION, &values_on_off},
+};
+
+static EffectSettings chorusfx_vibrato_settings[] = {
+ {"Speed", VIBRATO_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", VIBRATO_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_rotary_settings[] = {
+ {"Speed", ROTARY_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", ROTARY_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Doppler", ROTARY_DOPPLER, CHORUSFX_POSITION, &values_0_to_99},
+ {"Crossover", ROTARY_CROSSOVER, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_vibropan_settings[] = {
+ {"Speed", VIBROPAN_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", VIBROPAN_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Vibra", VIBROPAN_VIBRA, CHORUSFX_POSITION, &values_0_to_99},
+ {"Wave", VIBROPAN_WAVE, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings chorusfx_unovibe_settings[] = {
+ {"Pedal Speed", UNOVIBE_PEDAL_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", UNOVIBE_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Chorus/Vibrato", UNOVIBE_CHORUS_VIBRATO, CHORUSFX_POSITION, &values_chorus_vibrato},
+ {"Volume", UNOVIBE_VOLUME, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_tremolo_settings[] = {
+ {"Speed", TREMOLO_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", TREMOLO_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Wave", TREMOLO_WAVE, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings chorusfx_trem_settings[] = {
+ {"Speed", TREMOLO_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", TREMOLO_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_panner_settings[] = {
+ {"Speed", PANNER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Depth", PANNER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Wave", PANNER_WAVE, CHORUSFX_POSITION, &values_waveform},
+};
+
+static EffectSettings chorusfx_envelope_settings[] = {
+ {"Sensitivity", ENVELOPE_SENSITIVITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", ENVELOPE_RANGE, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_fx25_settings[] = {
+ {"Sensitivity", ENVELOPE_SENSITIVITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", ENVELOPE_RANGE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Blend", ENVELOPE_BLEND, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_autoya_settings[] = {
+ {"Speed", AUTOYA_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", AUTOYA_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", AUTOYA_RANGE, CHORUSFX_POSITION, &values_0_to_49},
+};
+
+static EffectSettings chorusfx_yaya_settings[] = {
+ {"Pedal", YAYA_PEDAL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", YAYA_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Range", YAYA_RANGE, CHORUSFX_POSITION, &values_0_to_49},
+};
+
+static EffectSettings chorusfx_synth_talk_settings[] = {
+ {"Attack", SYNTH_TALK_ATTACK, CHORUSFX_POSITION, &values_0_to_99},
+ {"Release", SYNTH_TALK_RELEASE, CHORUSFX_POSITION, &values_0_to_99},
+ {"Sens", SYNTH_TALK_SENS, CHORUSFX_POSITION, &values_0_to_99},
+ {"Vox", SYNTH_TALK_VOX, CHORUSFX_POSITION, &values_0_to_99},
+ {"Balance", SYNTH_TALK_BALANCE, CHORUSFX_POSITION, &values_balance},
+};
+
+static EffectSettings chorusfx_step_filter_settings[] = {
+ {"Speed", STEP_FILTER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", STEP_FILTER_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_sample_hold_settings[] = {
+ {"Speed", SAMPLE_HOLD_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Intensity", SAMPLE_HOLD_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_whammy_settings[] = {
+ {"Pedal", WHAMMY_PEDAL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Mix", WHAMMY_MIX, CHORUSFX_POSITION, &values_0_to_99},
+ {"Amount", WHAMMY_AMOUNT, CHORUSFX_POSITION, &values_whammy_amount},
+};
+
+static EffectSettings chorusfx_pitch_shift_settings[] = {
+ {"Amount", PITCH_AMOUNT, CHORUSFX_POSITION, &values_m24_to_24},
+ {"Mix", PITCH_MIX, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_detune_settings[] = {
+ {"Amount", DETUNE_AMOUNT, CHORUSFX_POSITION, &values_m24_to_24},
+ {"Level", DETUNE_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_ips_settings[] = {
+ {"Shift", IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, &values_ips_shift},
+ {"Key", IPS_KEY, CHORUSFX_POSITION, &values_ips_key},
+ {"Scale", IPS_SCALE, CHORUSFX_POSITION, &values_ips_scale},
+ {"Level", IPS_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings chorusfx_octaver_settings[] = {
+ {"Octave 1", OCTAVER_OCTAVE1, CHORUSFX_POSITION, &values_0_to_99},
+ {"Octave 2", OCTAVER_OCTAVE2, CHORUSFX_POSITION, &values_0_to_99},
+ {"Dry Level", OCTAVER_DRY_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_delay_settings[] = {
+ {"Time", GNX3K_DELAY_TIME, DELAY_POSITION, &values_delay_time_0_2000},
+ {"Feedback", GNX3K_DELAY_FEEDBACK, DELAY_POSITION, &values_delay_repeats},
+ {"Thresh", GNX3K_DELAY_DUCK_THRESH, DELAY_POSITION, &values_delay_thresh},
+ {"Atten", GNX3K_DELAY_DUCK_ATTEN, DELAY_POSITION, &values_0_to_99},
+ {"Balance", GNX3K_DELAY_BALANCE, DELAY_POSITION, &values_balance},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_delay_spread_settings[] = {
+ {"Time", GNX3K_DELAY_TIME, DELAY_POSITION, &values_delay_time_0_2000},
+ {"Feedback", GNX3K_DELAY_FEEDBACK, DELAY_POSITION, &values_delay_repeats},
+ {"Thresh", GNX3K_DELAY_DUCK_THRESH, DELAY_POSITION, &values_delay_thresh},
+ {"Atten", GNX3K_DELAY_DUCK_ATTEN, DELAY_POSITION, &values_0_to_99},
+ {"Spread", GNX3K_DELAY_SPREAD, DELAY_POSITION, &values_delay_spread_0_49},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings delay_analog_settings[] = {
+ {"Time", DELAY_TIME, DELAY_POSITION, &values_delay_time},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+};
+
+static EffectSettings delay_dm_settings[] = {
+ {"Repeat Rate", DELAY_REPEAT_RATE_DM, DELAY_POSITION, &values_0_to_99},
+ {"Echo", DELAY_ECHO, DELAY_POSITION, &values_0_to_99},
+ {"Intensity", DELAY_INTENSITY, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings delay_digital_settings[] = {
+ {"Time", DELAY_TIME, DELAY_POSITION, &values_delay_time},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Ducker thresh", DELAY_DUCK_THRESH, DELAY_POSITION, &values_0_to_99},
+ {"Ducker level", DELAY_DUCK_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings delay_modulated_settings[] = {
+ {"Time", DELAY_TIME, DELAY_POSITION, &values_delay_time},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Depth", DELAY_DEPTH, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings delay_pong_settings[] = {
+ {"Time", DELAY_TIME, DELAY_POSITION, &values_delay_time},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Ducker thresh", DELAY_DUCK_THRESH, DELAY_POSITION, &values_0_to_99},
+ {"Ducker level", DELAY_DUCK_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings delay_tape_settings[] = {
+ {"Time", DELAY_TIME, DELAY_POSITION, &values_delay_time},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Wow", DELAY_TAPE_WOW, DELAY_POSITION, &values_0_to_99},
+ {"Flutter", DELAY_TAPE_FLUTTER, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings delay_echoplex_settings[] = {
+ {"Time", DELAY_ECHOPLEX_TIME, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS_0_99, DELAY_POSITION, &values_0_to_99},
+ {"Volume", DELAY_VOLUME, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_digital_settings[] = {
+ {"Tap Time", DELAY_TAP_TIME, DELAY_POSITION, &values_delay_time_0_5000},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Duck Thresh", DELAY_DUCK_THRESH, DELAY_POSITION, &values_0_to_99},
+ {"Duck Level", DELAY_DUCK_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_analog_settings[] = {
+ {"Tap Time", DELAY_TAP_TIME, DELAY_POSITION, &values_delay_time_0_5000},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_dm_settings[] = {
+ {"Repeat Rate", DELAY_REPEAT_RATE, DELAY_POSITION, &values_delay_repeat_rate_24_310},
+ {"Echo", DELAY_ECHO, DELAY_POSITION, &values_0_to_99},
+ {"Intensity", DELAY_INTENSITY, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_echoplex_settings[] = {
+ {"Time", DELAY_TIME_0_760, DELAY_POSITION, &values_delay_time_110_870},
+ {"Volume", DELAY_VOLUME, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS_0_99, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_modulated_settings[] = {
+ {"Tap Time", DELAY_TAP_TIME_0_4990, DELAY_POSITION, &values_delay_time_0_4990},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Depth", DELAY_DEPTH, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_pong_settings[] = {
+ {"Tap Time", DELAY_TAP_TIME, DELAY_POSITION, &values_delay_time_0_5000},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Duck Thresh", DELAY_DUCK_THRESH, DELAY_POSITION, &values_0_to_99},
+ {"Duck Level", DELAY_DUCK_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_reverse_settings[] = {
+ {"Time", DELAY_TIME_0_4650, DELAY_POSITION, &values_delay_time_0_4650},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Mix", DELAY_MIX, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp500_delay_tape_settings[] = {
+ {"Tap Time", DELAY_TAP_TIME_0_4990, DELAY_POSITION, &values_delay_time_0_4990},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Tape Wow", DELAY_TAPE_WOW, DELAY_POSITION, &values_0_to_99},
+ {"Tape Flutter", DELAY_TAPE_FLUTTER, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp1000_delay_lo_fi_settings[] = {
+ {"Time", DELAY_TAP_TIME, DELAY_POSITION, &values_delay_time_0_5000},
+ {"Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Repeats", DELAY_REPEATS_0_99, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings rp1000_delay_2_tap_settings[] = {
+ {"Time", DELAY_TAP_TIME, DELAY_POSITION, &values_delay_time_0_5000},
+ {"Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Ratio", DELAY_TAP_RATIO, DELAY_POSITION, &values_delay_repeats},
+ {"Mix", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+};
+
+static EffectSettings reverb_twin_settings[] = {
+ {"Reverb", REVERB_LEVEL, REVERB_POSITION, &values_0_to_99},
+};
+
+static EffectSettings gnx3k_reverb_settings[] = {
+ {"Predelay", REVERB_PREDELAY, REVERB_POSITION, &values_0_to_15},
+ {"Decay", REVERB_DECAY, REVERB_POSITION, &values_0_to_99},
+ {"Damping", REVERB_DAMPING, REVERB_POSITION, &values_0_to_99},
+ {"Balance", REVERB_BALANCE, REVERB_POSITION, &values_balance},
+ {"Level", REVERB_LEVEL, REVERB_POSITION, &values_0_to_99},
+};
+
+static EffectSettings reverb_lex_settings[] = {
+ {"Predelay", REVERB_PREDELAY, REVERB_POSITION, &values_0_to_15},
+ {"Decay", REVERB_DECAY, REVERB_POSITION, &values_0_to_99},
+ {"Liveliness", REVERB_LIVELINESS, REVERB_POSITION, &values_0_to_99},
+ {"Level", REVERB_LEVEL, REVERB_POSITION, &values_0_to_99},
+};
+
+static EffectGroup gnx3k_wah_group[] = {
+ {GNX3K_WAH_TYPE_CRY, "Cry", gnx3k_wah_settings, G_N_ELEMENTS(gnx3k_wah_settings)},
+ {GNX3K_WAH_TYPE_BOUTIQUE, "Boutique", gnx3k_wah_settings, G_N_ELEMENTS(gnx3k_wah_settings)},
+ {GNX3K_WAH_TYPE_FULLRANGE, "Full-Range", gnx3k_wah_settings, G_N_ELEMENTS(gnx3k_wah_settings)},
+};
+
+static EffectGroup wah_group[] = {
+ {WAH_TYPE_CRY, "Cry wah", wah_settings, G_N_ELEMENTS(wah_settings)},
+ {WAH_TYPE_FULLRANGE, "Fullrange wah", wah_settings, G_N_ELEMENTS(wah_settings)},
+ {WAH_TYPE_CLYDE, "Clyde wah", wah_settings, G_N_ELEMENTS(wah_settings)},
+};
+
+static EffectGroup gnx3k_whammy_group[] = {
+ {GNX3K_WHAM_TYPE_WHAMMY, "Whammy", gnx3k_whammy_settings, G_N_ELEMENTS(gnx3k_whammy_settings)},
+ {GNX3K_WHAM_TYPE_IPS, "IPS", gnx3k_ips_settings, G_N_ELEMENTS(gnx3k_ips_settings)},
+ {GNX3K_WHAM_TYPE_DETUNE, "Detune", gnx3k_detune_settings, G_N_ELEMENTS(gnx3k_detune_settings)},
+ {GNX3K_WHAM_TYPE_PITCH, "Pitch Shift", gnx3k_pitch_settings, G_N_ELEMENTS(gnx3k_pitch_settings)},
+ {GNX3K_WHAM_TYPE_TALK1, "Talker 1", gnx3k_talk_settings, G_N_ELEMENTS(gnx3k_talk_settings)},
+ {GNX3K_WHAM_TYPE_TALK2, "Talker 2", gnx3k_talk_settings, G_N_ELEMENTS(gnx3k_talk_settings)},
+ {GNX3K_WHAM_TYPE_TALK3, "Talker 3", gnx3k_talk_settings, G_N_ELEMENTS(gnx3k_talk_settings)},
+ {GNX3K_WHAM_TYPE_TALK4, "Talker 4", gnx3k_talk_settings, G_N_ELEMENTS(gnx3k_talk_settings)},
+ {GNX3K_WHAM_TYPE_TALK5, "Talker 5", gnx3k_talk_settings, G_N_ELEMENTS(gnx3k_talk_settings)},
+};
+
+static EffectGroup gnx3k_amp_channel_group[] = {
+ {-1, NULL, gnx3k_amp_channel_settings, G_N_ELEMENTS(gnx3k_amp_channel_settings)},
+};
+
+/** \todo it's not part of Preset, but should appear in GUI */
+static EffectGroup usb_group[] = {
+ {-1, NULL, usb_settings, G_N_ELEMENTS(usb_settings)},
+};
+
+static EffectGroup misc_group[] = {
+ {-1, NULL, misc_settings, G_N_ELEMENTS(misc_settings)},
+};
+
+static EffectGroup gnx3k_preset_group[] = {
+ {-1, NULL, gnx3k_preset_settings, G_N_ELEMENTS(gnx3k_preset_settings)},
+};
+
+static EffectGroup gnx_comp_group[] = {
+ {-1, NULL, gnx_comp_settings, G_N_ELEMENTS(gnx_comp_settings)},
+};
+
+static EffectGroup rp250_comp_group[] = {
+ {COMP_TYPE_DIGI, "Digital compressor", comp_digi_settings, G_N_ELEMENTS(comp_digi_settings)},
+ {COMP_TYPE_CS, "CS compressor", comp_cs_settings, G_N_ELEMENTS(comp_cs_settings)},
+};
+
+static EffectGroup rp355_comp_group[] = {
+ {COMP_TYPE_DIGI, "Digital compressor", comp_digi_settings, G_N_ELEMENTS(comp_digi_settings)},
+ {COMP_TYPE_CS, "CS compressor", comp_cs_settings, G_N_ELEMENTS(comp_cs_settings)},
+ {COMP_TYPE_DYNA, "Dyna comp", comp_dyna_settings, G_N_ELEMENTS(comp_dyna_settings)},
+};
+
+static EffectGroup rp500_comp_group[] = {
+ {COMP_TYPE_DIGI, "Digital compressor", comp_digi_settings, G_N_ELEMENTS(comp_digi_settings)},
+ {COMP_TYPE_CS, "CS compressor", comp_cs_settings, G_N_ELEMENTS(comp_cs_settings)},
+ {COMP_TYPE_DYNA, "Dyna comp", comp_dyna_settings, G_N_ELEMENTS(comp_dyna_settings)},
+};
+
+static EffectGroup rp155_dist_group[] = {
+ {DIST_TYPE_SCREAMER, "Screamer", dist_screamer_settings, G_N_ELEMENTS(dist_screamer_settings)},
+ {DIST_TYPE_808, "808", dist_808_settings, G_N_ELEMENTS(dist_808_settings)},
+ {DIST_TYPE_DOD250, "DOD250", dist_dod250_settings, G_N_ELEMENTS(dist_dod250_settings)},
+ {DIST_TYPE_RODENT, "Rodent", dist_rodent_settings, G_N_ELEMENTS(dist_rodent_settings)},
+ {DIST_TYPE_DS, "DS", dist_ds_settings, G_N_ELEMENTS(dist_ds_settings)},
+ {DIST_TYPE_GRUNGE, "Grunge", dist_grunge_settings, G_N_ELEMENTS(dist_grunge_settings)},
+ {DIST_TYPE_ZONE, "Zone", dist_zone_settings, G_N_ELEMENTS(dist_zone_settings)},
+ {DIST_TYPE_GONK, "Gonk", dist_gonk_settings, G_N_ELEMENTS(dist_gonk_settings)},
+ {DIST_TYPE_FUZZY, "Fuzzy", dist_fuzzy_settings, G_N_ELEMENTS(dist_fuzzy_settings)},
+ {DIST_TYPE_MP, "Big MP", dist_mp_settings, G_N_ELEMENTS(dist_mp_settings)},
+};
+
+static EffectGroup rp250_dist_group[] = {
+ {DIST_TYPE_SCREAMER, "Screamer", dist_screamer_settings, G_N_ELEMENTS(dist_screamer_settings)},
+ {DIST_TYPE_808, "808", dist_808_settings, G_N_ELEMENTS(dist_808_settings)},
+ {DIST_TYPE_GUYOD, "GuyOD", dist_guyod_settings, G_N_ELEMENTS(dist_guyod_settings)},
+ {DIST_TYPE_DOD250, "DOD250", dist_dod250_settings, G_N_ELEMENTS(dist_dod250_settings)},
+ {DIST_TYPE_RODENT, "Rodent", dist_rodent_settings, G_N_ELEMENTS(dist_rodent_settings)},
+ {DIST_TYPE_MX, "MX", dist_mx_settings, G_N_ELEMENTS(dist_mx_settings)},
+ {DIST_TYPE_DS, "DS", dist_ds_settings, G_N_ELEMENTS(dist_ds_settings)},
+ {DIST_TYPE_GRUNGE, "Grunge", dist_grunge_settings, G_N_ELEMENTS(dist_grunge_settings)},
+ {DIST_TYPE_ZONE, "Zone", dist_zone_settings, G_N_ELEMENTS(dist_zone_settings)},
+ {DIST_TYPE_DEATH, "Death", dist_death_settings, G_N_ELEMENTS(dist_death_settings)},
+ {DIST_TYPE_GONK, "Gonk", dist_gonk_settings, G_N_ELEMENTS(dist_gonk_settings)},
+ {DIST_TYPE_FUZZY, "Fuzzy", dist_fuzzy_settings, G_N_ELEMENTS(dist_fuzzy_settings)},
+ {DIST_TYPE_MP, "Big MP", dist_mp_settings, G_N_ELEMENTS(dist_mp_settings)},
+};
+
+static EffectGroup rp355_dist_group[] = {
+ {DIST_TYPE_SCREAMER, "Screamer", dist_screamer_settings, G_N_ELEMENTS(dist_screamer_settings)},
+ {DIST_TYPE_808, "808", dist_808_settings, G_N_ELEMENTS(dist_808_settings)},
+ {DIST_TYPE_SPARKDRIVE, "Sparkdrive", dist_sparkdrive_settings, G_N_ELEMENTS(dist_sparkdrive_settings)},
+ {DIST_TYPE_GUYOD, "OD Overdrive", dist_guyod_settings, G_N_ELEMENTS(dist_guyod_settings)},
+ {DIST_TYPE_DOD250, "DOD250", dist_dod250_settings, G_N_ELEMENTS(dist_dod250_settings)},
+ {DIST_TYPE_REDLINE, "Redline", dist_redline_settings, G_N_ELEMENTS(dist_redline_settings)},
+ {DIST_TYPE_RODENT, "Rodent", dist_rodent_settings, G_N_ELEMENTS(dist_rodent_settings)},
+ {DIST_TYPE_MX, "MX", dist_mx_settings, G_N_ELEMENTS(dist_mx_settings)},
+ {DIST_TYPE_DS, "DS", dist_ds_settings, G_N_ELEMENTS(dist_ds_settings)},
+ {DIST_TYPE_GRUNGE, "Grunge", dist_grunge_settings, G_N_ELEMENTS(dist_grunge_settings)},
+ {DIST_TYPE_ZONE, "Zone", dist_zone_settings, G_N_ELEMENTS(dist_zone_settings)},
+ {DIST_TYPE_DEATH, "Death", dist_death_settings, G_N_ELEMENTS(dist_death_settings)},
+ {DIST_TYPE_GONK, "Gonk", dist_gonk_settings, G_N_ELEMENTS(dist_gonk_settings)},
+ {DIST_TYPE_8TAVIA, "8tavia", dist_8tavia_settings, G_N_ELEMENTS(dist_8tavia_settings)},
+ {DIST_TYPE_FUZZLATOR, "Fuzzlator", dist_fuzzlator_settings, G_N_ELEMENTS(dist_fuzzlator_settings)},
+ {DIST_TYPE_CLASSIC_FUZZ, "Classic Fuzz", dist_classic_fuzz_settings, G_N_ELEMENTS(dist_classic_fuzz_settings)},
+ {DIST_TYPE_FUZZY, "Fuzzy", dist_fuzzy_settings, G_N_ELEMENTS(dist_fuzzy_settings)},
+ {DIST_TYPE_MP, "Big MP", dist_mp_settings, G_N_ELEMENTS(dist_mp_settings)},
+};
+
+static EffectGroup rp500_dist_group[] = {
+ {DIST_TYPE_SCREAMER, "Screamer", dist_screamer_settings, G_N_ELEMENTS(dist_screamer_settings)},
+ {DIST_TYPE_808, "808", dist_808_settings, G_N_ELEMENTS(dist_808_settings)},
+ {DIST_TYPE_SPARKDRIVE, "Sparkdrive", dist_sparkdrive_settings, G_N_ELEMENTS(dist_sparkdrive_settings)},
+ {DIST_TYPE_GUYOD, "OD Overdrive", dist_guyod_settings, G_N_ELEMENTS(dist_guyod_settings)},
+ {DIST_TYPE_DOD250, "DOD250", dist_dod250_settings, G_N_ELEMENTS(dist_dod250_settings)},
+ {DIST_TYPE_REDLINE, "Redline", dist_redline_settings, G_N_ELEMENTS(dist_redline_settings)},
+ {DIST_TYPE_RODENT, "Rodent", dist_rodent_settings, G_N_ELEMENTS(dist_rodent_settings)},
+ {DIST_TYPE_MX, "MX", dist_mx_settings, G_N_ELEMENTS(dist_mx_settings)},
+ {DIST_TYPE_DS, "DS", dist_ds_settings, G_N_ELEMENTS(dist_ds_settings)},
+ {DIST_TYPE_GRUNGE, "Grunge", dist_grunge_settings, G_N_ELEMENTS(dist_grunge_settings)},
+ {DIST_TYPE_ZONE, "Zone", dist_zone_settings, G_N_ELEMENTS(dist_zone_settings)},
+ {DIST_TYPE_DEATH, "Death", dist_death_settings, G_N_ELEMENTS(dist_death_settings)},
+ {DIST_TYPE_GONK, "Gonk", dist_gonk_settings, G_N_ELEMENTS(dist_gonk_settings)},
+ {DIST_TYPE_8TAVIA, "8tavia", dist_8tavia_settings, G_N_ELEMENTS(dist_8tavia_settings)},
+ {DIST_TYPE_FUZZLATOR, "Fuzzlator", dist_fuzzlator_settings, G_N_ELEMENTS(dist_fuzzlator_settings)},
+ {DIST_TYPE_CLASSIC_FUZZ, "Classic Fuzz", dist_classic_fuzz_settings, G_N_ELEMENTS(dist_classic_fuzz_settings)},
+ {DIST_TYPE_FUZZY, "Fuzzy", dist_fuzzy_settings, G_N_ELEMENTS(dist_fuzzy_settings)},
+ {DIST_TYPE_MP, "Big MP", dist_mp_settings, G_N_ELEMENTS(dist_mp_settings)},
+};
+
+static EffectGroup rp1000_dist_group[] = {
+ {DIST_TYPE_SCREAMER, "Screamer", dist_screamer_settings, G_N_ELEMENTS(dist_screamer_settings)},
+ {DIST_TYPE_808, "808", dist_808_settings, G_N_ELEMENTS(dist_808_settings)},
+ {DIST_TYPE_TS_MOD, "TS Mod", dist_ts_mod_settings, G_N_ELEMENTS(dist_ts_mod_settings)},
+ {DIST_TYPE_SD_ODRV, "SD Overdrive", dist_sd_odrv_settings, G_N_ELEMENTS(dist_sd_odrv_settings)},
+ {DIST_TYPE_OD_ODRV, "OD Overdrive", dist_od_odrv_settings, G_N_ELEMENTS(dist_od_odrv_settings)},
+ {DIST_TYPE_SPARKDRIVE, "Sparkdrive", dist_sparkdrive_settings, G_N_ELEMENTS(dist_sparkdrive_settings)},
+ {DIST_TYPE_GUYOD, "Guy Overdrive", dist_guyod_settings, G_N_ELEMENTS(dist_guyod_settings)},
+ {DIST_TYPE_DOD250, "DOD250", dist_dod250_settings, G_N_ELEMENTS(dist_dod250_settings)},
+ {DIST_TYPE_REDLINE, "Redline", dist_redline_settings, G_N_ELEMENTS(dist_redline_settings)},
+ {DIST_TYPE_AMPDRIVR, "Amp Driver", dist_ampdrivr_settings, G_N_ELEMENTS(dist_ampdrivr_settings)},
+ {DIST_TYPE_OC_DRIVE, "OC Drive", dist_oc_drive_settings, G_N_ELEMENTS(dist_oc_drive_settings)},
+ {DIST_TYPE_RODENT, "Rodent", dist_rodent_settings, G_N_ELEMENTS(dist_rodent_settings)},
+ {DIST_TYPE_MX, "MX Dist", dist_mx_settings, G_N_ELEMENTS(dist_mx_settings)},
+ {DIST_TYPE_DS, "DS Dist", dist_ds_settings, G_N_ELEMENTS(dist_ds_settings)},
+ {DIST_TYPE_GRUNGE, "Grunge", dist_grunge_settings, G_N_ELEMENTS(dist_grunge_settings)},
+ {DIST_TYPE_ZONE, "Zone", dist_zone_settings, G_N_ELEMENTS(dist_zone_settings)},
+ {DIST_TYPE_DEATH, "Death", dist_death_settings, G_N_ELEMENTS(dist_death_settings)},
+ {DIST_TYPE_GONK, "Gonk", dist_gonk_settings, G_N_ELEMENTS(dist_gonk_settings)},
+ {DIST_TYPE_8TAVIA, "8tavia", dist_8tavia_settings, G_N_ELEMENTS(dist_8tavia_settings)},
+ {DIST_TYPE_FUZZLATOR, "Fuzzlator", dist_fuzzlator_settings, G_N_ELEMENTS(dist_fuzzlator_settings)},
+ {DIST_TYPE_CLASSIC_FUZZ, "Classic Fuzz", dist_classic_fuzz_settings, G_N_ELEMENTS(dist_classic_fuzz_settings)},
+ {DIST_TYPE_FUZZY, "Fuzzy", dist_fuzzy_settings, G_N_ELEMENTS(dist_fuzzy_settings)},
+ {DIST_TYPE_MP, "Big Pi", dist_mp_settings, G_N_ELEMENTS(dist_mp_settings)},
+};
+
+static EffectGroup gnx4_dist_group[] = {
+ {DIST_TYPE_SCREAMER, "Screamer", dist_screamer_settings, G_N_ELEMENTS(dist_screamer_settings)},
+ {DIST_TYPE_RODENT, "Rodent", dist_rodent_settings, G_N_ELEMENTS(dist_rodent_settings)},
+ {DIST_TYPE_DS, "DS Dist", dist_ds_settings, G_N_ELEMENTS(dist_ds_settings)},
+ {DIST_TYPE_DOD250, "DOD250", dist_dod250_settings, G_N_ELEMENTS(dist_dod250_settings)},
+ {DIST_TYPE_MP, "Big MP", dist_mp_settings, G_N_ELEMENTS(dist_mp_settings)},
+ {DIST_TYPE_GUYOD, "Guy OD", dist_guyod_settings, G_N_ELEMENTS(dist_guyod_settings)},
+ {DIST_TYPE_SPARKDRIVE, "Sparkdrive", dist_sparkdrive_settings, G_N_ELEMENTS(dist_sparkdrive_settings)},
+ {DIST_TYPE_GRUNGE, "Grunge", dist_grunge_settings, G_N_ELEMENTS(dist_grunge_settings)},
+ {DIST_TYPE_FUZZY, "Fuzzy", dist_fuzzy_settings, G_N_ELEMENTS(dist_fuzzy_settings)},
+ {DIST_TYPE_ZONE, "Zone", dist_zone_settings, G_N_ELEMENTS(dist_zone_settings)},
+};
+
+static EffectGroup gnx3k_dist_group[] = {
+ {DIST_TYPE_SCREAMER, "Screamer", dist_screamer_settings, G_N_ELEMENTS(dist_screamer_settings)},
+ {DIST_TYPE_RODENT, "Rodent", dist_rodent_settings, G_N_ELEMENTS(dist_rodent_settings)},
+ {DIST_TYPE_DS, "DS", dist_ds_settings, G_N_ELEMENTS(dist_ds_settings)},
+ {DIST_TYPE_DOD250, "DOD250", dist_dod250_settings, G_N_ELEMENTS(dist_dod250_settings)},
+ {DIST_TYPE_MP, "Big MP", dist_mp_settings, G_N_ELEMENTS(dist_mp_settings)},
+ {DIST_TYPE_GUYOD, "Guy OD", dist_guyod_settings, G_N_ELEMENTS(dist_guyod_settings)},
+ {DIST_TYPE_SPARKDRIVE, "Sparkdrive", dist_sparkdrive_settings, G_N_ELEMENTS(dist_sparkdrive_settings)},
+ {DIST_TYPE_GRUNGE, "Grunge", dist_grunge_settings, G_N_ELEMENTS(dist_grunge_settings)},
+ {DIST_TYPE_FUZZY, "Fuzzy", dist_fuzzy_settings, G_N_ELEMENTS(dist_fuzzy_settings)},
+ {DIST_TYPE_ZONE, "Zone", dist_zone_settings, G_N_ELEMENTS(dist_zone_settings)},
+ {DIST_TYPE_8TAVIA, "8tavia", dist_8tavia_settings, G_N_ELEMENTS(dist_8tavia_settings)},
+};
+
+static EffectGroup gnx3k_noisegate_group[] = {
+ {NOISEGATE_GATE, "Silencer", noisegate_silencer_settings, G_N_ELEMENTS(noisegate_silencer_settings)},
+ {NOISEGATE_SWELL, "Pluck", noisegate_pluck_settings, G_N_ELEMENTS(noisegate_pluck_settings)},
+};
+
+static EffectGroup noisegate_group[] = {
+ {NOISEGATE_GATE, "Gate", noisegate_gate_settings, G_N_ELEMENTS(noisegate_gate_settings)},
+ {NOISEGATE_SWELL, "Swell", noisegate_swell_settings, G_N_ELEMENTS(noisegate_swell_settings)},
+};
+
+static EffectGroup gnx4_chorusfx_group[] = {
+ {GNX3K_MOD_TYPE_CHORUS, "Chorus", gnx3k_chorus_settings, G_N_ELEMENTS(gnx3k_chorus_settings)},
+ {GNX3K_MOD_TYPE_FLANGER, "Flanger", gnx3k_flanger_settings, G_N_ELEMENTS(gnx3k_flanger_settings)},
+ {GNX3K_MOD_TYPE_PHASER, "Phaser", gnx3k_phaser_settings, G_N_ELEMENTS(gnx3k_phaser_settings)},
+ {GNX3K_MOD_TYPE_TRIGFLANGER, "Triggered Flanger", gnx3k_trigflanger_settings, G_N_ELEMENTS(gnx3k_trigflanger_settings)},
+ {GNX3K_MOD_TYPE_TRIGPHASER, "Triggered Phaser", gnx3k_trigphaser_settings, G_N_ELEMENTS(gnx3k_trigphaser_settings)},
+ {GNX3K_MOD_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {GNX3K_MOD_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {GNX3K_MOD_TYPE_VIBRATO, "Vibrato", gnx3k_vibrato_settings, G_N_ELEMENTS(gnx3k_vibrato_settings)},
+ {GNX3K_MOD_TYPE_ROTARY, "Rotary", gnx3k_rotary_settings, G_N_ELEMENTS(gnx3k_rotary_settings)},
+ {GNX3K_MOD_TYPE_AUTOYA, "Auto Ya", gnx3k_autoya_settings, G_N_ELEMENTS(gnx3k_autoya_settings)},
+ {GNX3K_MOD_TYPE_YAYA, "Ya Ya", gnx3k_yaya_settings, G_N_ELEMENTS(gnx3k_yaya_settings)},
+ {GNX3K_MOD_TYPE_SYNTHTALK, "Synthtalk", gnx3k_synthtalk_settings, G_N_ELEMENTS(gnx3k_synthtalk_settings)},
+ {GNX3K_MOD_TYPE_ENVELOPE, "Envelope", gnx3k_envelope_settings, G_N_ELEMENTS(gnx3k_envelope_settings)},
+ {GNX3K_MOD_TYPE_DETUNE, "Detune", gnx3k_mod_detune_settings, G_N_ELEMENTS(gnx3k_mod_detune_settings)},
+ {GNX3K_MOD_TYPE_PITCH, "Pitch", gnx3k_mod_pitch_settings, G_N_ELEMENTS(gnx3k_mod_pitch_settings)},
+};
+
+static EffectGroup gnx3k_chorusfx_group[] = {
+ {GNX3K_MOD_TYPE_CHORUS, "Chorus", gnx3k_chorus_settings, G_N_ELEMENTS(gnx3k_chorus_settings)},
+ {GNX3K_MOD_TYPE_FLANGER, "Flanger", gnx3k_flanger_settings, G_N_ELEMENTS(gnx3k_flanger_settings)},
+ {GNX3K_MOD_TYPE_PHASER, "Phaser", gnx3k_phaser_settings, G_N_ELEMENTS(gnx3k_phaser_settings)},
+ {GNX3K_MOD_TYPE_TRIGFLANGER, "Triggered Flanger", gnx3k_trigflanger_settings, G_N_ELEMENTS(gnx3k_trigflanger_settings)},
+ {GNX3K_MOD_TYPE_TRIGPHASER, "Triggered Phaser", gnx3k_trigphaser_settings, G_N_ELEMENTS(gnx3k_trigphaser_settings)},
+ {GNX3K_MOD_TYPE_UNOVIBE, "Unovibe", gnx3k_unovibe_settings, G_N_ELEMENTS(gnx3k_unovibe_settings)},
+ {GNX3K_MOD_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {GNX3K_MOD_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {GNX3K_MOD_TYPE_VIBRATO, "Vibrato", gnx3k_vibrato_settings, G_N_ELEMENTS(gnx3k_vibrato_settings)},
+ {GNX3K_MOD_TYPE_ROTARY, "Rotary", gnx3k_rotary_settings, G_N_ELEMENTS(gnx3k_rotary_settings)},
+ {GNX3K_MOD_TYPE_AUTOYA, "Auto Ya", gnx3k_autoya_settings, G_N_ELEMENTS(gnx3k_autoya_settings)},
+ {GNX3K_MOD_TYPE_YAYA, "Ya Ya", gnx3k_yaya_settings, G_N_ELEMENTS(gnx3k_yaya_settings)},
+ {GNX3K_MOD_TYPE_SYNTHTALK, "Synthtalk", gnx3k_synthtalk_settings, G_N_ELEMENTS(gnx3k_synthtalk_settings)},
+ {GNX3K_MOD_TYPE_ENVELOPE, "Envelope", gnx3k_envelope_settings, G_N_ELEMENTS(gnx3k_envelope_settings)},
+ {GNX3K_MOD_TYPE_DETUNE, "Detune", gnx3k_mod_detune_settings, G_N_ELEMENTS(gnx3k_mod_detune_settings)},
+ {GNX3K_MOD_TYPE_PITCH, "Pitch", gnx3k_mod_pitch_settings, G_N_ELEMENTS(gnx3k_mod_pitch_settings)},
+};
+
+static EffectGroup rp155_chorusfx_group[] = {
+ {CHORUS_TYPE_CE, "CE Chorus", chorusfx_ce_settings, G_N_ELEMENTS(chorusfx_ce_settings)},
+ {CHORUS_TYPE_DUAL, "Dual Chorus", chorusfx_dual_settings, G_N_ELEMENTS(chorusfx_dual_settings)},
+ {CHORUS_TYPE_MULTI, "Multi Chorus", chorusfx_multi_settings, G_N_ELEMENTS(chorusfx_multi_settings)},
+ {CHORUS_TYPE_FLANGER, "Flanger", chorusfx_flanger_settings, G_N_ELEMENTS(chorusfx_flanger_settings)},
+ {CHORUS_TYPE_MXR_FLANGER, "MXR Flanger", chorusfx_mxr_flanger_settings, G_N_ELEMENTS(chorusfx_mxr_flanger_settings)},
+ {CHORUS_TYPE_PHASER, "Phaser", chorusfx_phaser_settings, G_N_ELEMENTS(chorusfx_phaser_settings)},
+ {CHORUS_TYPE_VIBRATO, "Vibrato", chorusfx_vibrato_settings, G_N_ELEMENTS(chorusfx_vibrato_settings)},
+ {CHORUS_TYPE_ROTARY, "Rotary", chorusfx_rotary_settings, G_N_ELEMENTS(chorusfx_rotary_settings)},
+ {CHORUS_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {CHORUS_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {CHORUS_TYPE_ENVELOPE, "Envelope", chorusfx_envelope_settings, G_N_ELEMENTS(chorusfx_envelope_settings)},
+ {CHORUS_TYPE_AUTOYA, "AutoYa", chorusfx_autoya_settings, G_N_ELEMENTS(chorusfx_autoya_settings)},
+ {CHORUS_TYPE_STEP_FILTER, "Step Filter", chorusfx_step_filter_settings, G_N_ELEMENTS(chorusfx_step_filter_settings)},
+ {CHORUS_TYPE_WHAMMY, "Whammy", chorusfx_whammy_settings, G_N_ELEMENTS(chorusfx_whammy_settings)},
+ {CHORUS_TYPE_PITCH_SHIFT, "Pitch Shift", chorusfx_pitch_shift_settings, G_N_ELEMENTS(chorusfx_pitch_shift_settings)},
+ {CHORUS_TYPE_DETUNE, "Detune", chorusfx_detune_settings, G_N_ELEMENTS(chorusfx_detune_settings)},
+ {CHORUS_TYPE_IPS, "Harmony Pitch", chorusfx_ips_settings, G_N_ELEMENTS(chorusfx_ips_settings)},
+};
+
+static EffectGroup rp250_chorusfx_group[] = {
+ {CHORUS_TYPE_CE, "CE Chorus", chorusfx_ce_settings, G_N_ELEMENTS(chorusfx_ce_settings)},
+ {CHORUS_TYPE_DUAL, "Dual Chorus", chorusfx_dual_settings, G_N_ELEMENTS(chorusfx_dual_settings)},
+ {CHORUS_TYPE_MULTI, "Multi Chorus", chorusfx_multi_settings, G_N_ELEMENTS(chorusfx_multi_settings)},
+ {CHORUS_TYPE_FLANGER, "Flanger", chorusfx_flanger_settings, G_N_ELEMENTS(chorusfx_flanger_settings)},
+ {CHORUS_TYPE_MXR_FLANGER, "MXR FLANGER", chorusfx_mxr_flanger_settings, G_N_ELEMENTS(chorusfx_mxr_flanger_settings)},
+ {CHORUS_TYPE_PHASER, "Phaser", chorusfx_phaser_settings, G_N_ELEMENTS(chorusfx_phaser_settings)},
+ {CHORUS_TYPE_VIBRATO, "Vibrato", chorusfx_vibrato_settings, G_N_ELEMENTS(chorusfx_vibrato_settings)},
+ {CHORUS_TYPE_ROTARY, "Rotary", chorusfx_rotary_settings, G_N_ELEMENTS(chorusfx_rotary_settings)},
+ {CHORUS_TYPE_VIBROPAN, "Vibropan", chorusfx_vibropan_settings, G_N_ELEMENTS(chorusfx_vibropan_settings)},
+ {CHORUS_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {CHORUS_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {CHORUS_TYPE_ENVELOPE, "Envelope", chorusfx_envelope_settings, G_N_ELEMENTS(chorusfx_envelope_settings)},
+ {CHORUS_TYPE_AUTOYA, "AutoYa", chorusfx_autoya_settings, G_N_ELEMENTS(chorusfx_autoya_settings)},
+ {CHORUS_TYPE_YAYA, "YaYa", chorusfx_yaya_settings, G_N_ELEMENTS(chorusfx_yaya_settings)},
+ {CHORUS_TYPE_STEP_FILTER, "Step Filter", chorusfx_step_filter_settings, G_N_ELEMENTS(chorusfx_step_filter_settings)},
+ {CHORUS_TYPE_WHAMMY, "Whammy", chorusfx_whammy_settings, G_N_ELEMENTS(chorusfx_whammy_settings)},
+ {CHORUS_TYPE_PITCH_SHIFT, "Pitch Shift", chorusfx_pitch_shift_settings, G_N_ELEMENTS(chorusfx_pitch_shift_settings)},
+ {CHORUS_TYPE_DETUNE, "Detune", chorusfx_detune_settings, G_N_ELEMENTS(chorusfx_detune_settings)},
+ {CHORUS_TYPE_IPS, "IPS", chorusfx_ips_settings, G_N_ELEMENTS(chorusfx_ips_settings)},
+};
+
+/* same as rp250, with IPS renamed to Harmony Pitch */
+static EffectGroup rp255_chorusfx_group[] = {
+ {CHORUS_TYPE_CE, "CE Chorus", chorusfx_ce_settings, G_N_ELEMENTS(chorusfx_ce_settings)},
+ {CHORUS_TYPE_DUAL, "Dual Chorus", chorusfx_dual_settings, G_N_ELEMENTS(chorusfx_dual_settings)},
+ {CHORUS_TYPE_MULTI, "Multi Chorus", chorusfx_multi_settings, G_N_ELEMENTS(chorusfx_multi_settings)},
+ {CHORUS_TYPE_FLANGER, "Flanger", chorusfx_flanger_settings, G_N_ELEMENTS(chorusfx_flanger_settings)},
+ {CHORUS_TYPE_MXR_FLANGER, "MXR FLANGER", chorusfx_mxr_flanger_settings, G_N_ELEMENTS(chorusfx_mxr_flanger_settings)},
+ {CHORUS_TYPE_PHASER, "Phaser", chorusfx_phaser_settings, G_N_ELEMENTS(chorusfx_phaser_settings)},
+ {CHORUS_TYPE_VIBRATO, "Vibrato", chorusfx_vibrato_settings, G_N_ELEMENTS(chorusfx_vibrato_settings)},
+ {CHORUS_TYPE_ROTARY, "Rotary", chorusfx_rotary_settings, G_N_ELEMENTS(chorusfx_rotary_settings)},
+ {CHORUS_TYPE_VIBROPAN, "Vibropan", chorusfx_vibropan_settings, G_N_ELEMENTS(chorusfx_vibropan_settings)},
+ {CHORUS_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {CHORUS_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {CHORUS_TYPE_ENVELOPE, "Envelope", chorusfx_envelope_settings, G_N_ELEMENTS(chorusfx_envelope_settings)},
+ {CHORUS_TYPE_AUTOYA, "AutoYa", chorusfx_autoya_settings, G_N_ELEMENTS(chorusfx_autoya_settings)},
+ {CHORUS_TYPE_YAYA, "YaYa", chorusfx_yaya_settings, G_N_ELEMENTS(chorusfx_yaya_settings)},
+ {CHORUS_TYPE_STEP_FILTER, "Step Filter", chorusfx_step_filter_settings, G_N_ELEMENTS(chorusfx_step_filter_settings)},
+ {CHORUS_TYPE_WHAMMY, "Whammy", chorusfx_whammy_settings, G_N_ELEMENTS(chorusfx_whammy_settings)},
+ {CHORUS_TYPE_PITCH_SHIFT, "Pitch Shift", chorusfx_pitch_shift_settings, G_N_ELEMENTS(chorusfx_pitch_shift_settings)},
+ {CHORUS_TYPE_DETUNE, "Detune", chorusfx_detune_settings, G_N_ELEMENTS(chorusfx_detune_settings)},
+ {CHORUS_TYPE_IPS, "Harmony Pitch", chorusfx_ips_settings, G_N_ELEMENTS(chorusfx_ips_settings)},
+};
+
+static EffectGroup rp355_chorusfx_group[] = {
+ {CHORUS_TYPE_CE, "CE Chorus", chorusfx_ce_settings, G_N_ELEMENTS(chorusfx_ce_settings)},
+ {CHORUS_TYPE_TC, "TC Chorus", chorusfx_tc_settings, G_N_ELEMENTS(chorusfx_tc_settings)},
+ {CHORUS_TYPE_DUAL, "Dual Chorus", chorusfx_dual_settings, G_N_ELEMENTS(chorusfx_dual_settings)},
+ {CHORUS_TYPE_MULTI, "Multi Chorus", chorusfx_multi_settings, G_N_ELEMENTS(chorusfx_multi_settings)},
+ {CHORUS_TYPE_FLANGER, "Flanger", chorusfx_flanger_settings, G_N_ELEMENTS(chorusfx_flanger_settings)},
+ {CHORUS_TYPE_TRIGGERED_FLANGER, "Triggered Flanger", chorusfx_trig_flanger_settings, G_N_ELEMENTS(chorusfx_trig_flanger_settings)},
+ {CHORUS_TYPE_MXR_FLANGER, "MXR FLANGER", chorusfx_mxr_flanger_settings, G_N_ELEMENTS(chorusfx_mxr_flanger_settings)},
+ {CHORUS_TYPE_EH_FLANGER, "EH Flanger", chorusfx_eh_flanger_settings, G_N_ELEMENTS(chorusfx_eh_flanger_settings)},
+ {CHORUS_TYPE_PHASER, "Phaser", chorusfx_phaser_settings, G_N_ELEMENTS(chorusfx_phaser_settings)},
+ {CHORUS_TYPE_TRIGGERED_PHASER, "Triggered Phaser", chorusfx_trig_phaser_settings, G_N_ELEMENTS(chorusfx_trig_phaser_settings)},
+ {CHORUS_TYPE_MX_PHASER, "MX Phaser", chorusfx_mx_phaser_settings, G_N_ELEMENTS(chorusfx_mx_phaser_settings)},
+ {CHORUS_TYPE_EH_PHASER, "EH Phaser", chorusfx_eh_phaser_settings, G_N_ELEMENTS(chorusfx_eh_phaser_settings)},
+ {CHORUS_TYPE_VIBRATO, "Vibrato", chorusfx_vibrato_settings, G_N_ELEMENTS(chorusfx_vibrato_settings)},
+ {CHORUS_TYPE_ROTARY, "Rotary", chorusfx_rotary_settings, G_N_ELEMENTS(chorusfx_rotary_settings)},
+ {CHORUS_TYPE_VIBROPAN, "Vibropan", chorusfx_vibropan_settings, G_N_ELEMENTS(chorusfx_vibropan_settings)},
+ {CHORUS_TYPE_UNOVIBE, "Unovibe", chorusfx_unovibe_settings, G_N_ELEMENTS(chorusfx_unovibe_settings)},
+ {CHORUS_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {CHORUS_TYPE_OPTO_TREMOLO, "Opto Tremolo", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_BIAS_TREMOLO, "Bias Tremolo", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {CHORUS_TYPE_ENVELOPE, "Envelope", chorusfx_envelope_settings, G_N_ELEMENTS(chorusfx_envelope_settings)},
+ {CHORUS_TYPE_FX25, "FX25", chorusfx_fx25_settings, G_N_ELEMENTS(chorusfx_fx25_settings)},
+ {CHORUS_TYPE_AUTOYA, "AutoYa", chorusfx_autoya_settings, G_N_ELEMENTS(chorusfx_autoya_settings)},
+ {CHORUS_TYPE_YAYA, "YaYa", chorusfx_yaya_settings, G_N_ELEMENTS(chorusfx_yaya_settings)},
+ {CHORUS_TYPE_SYNTH_TALK, "Synth Talk", chorusfx_synth_talk_settings, G_N_ELEMENTS(chorusfx_synth_talk_settings)},
+ {CHORUS_TYPE_STEP_FILTER, "Step Filter", chorusfx_step_filter_settings, G_N_ELEMENTS(chorusfx_step_filter_settings)},
+ {CHORUS_TYPE_WHAMMY, "Whammy", chorusfx_whammy_settings, G_N_ELEMENTS(chorusfx_whammy_settings)},
+ {CHORUS_TYPE_PITCH_SHIFT, "Pitch Shift", chorusfx_pitch_shift_settings, G_N_ELEMENTS(chorusfx_pitch_shift_settings)},
+ {CHORUS_TYPE_DETUNE, "Detune", chorusfx_detune_settings, G_N_ELEMENTS(chorusfx_detune_settings)},
+ {CHORUS_TYPE_IPS, "Harmony Pitch", chorusfx_ips_settings, G_N_ELEMENTS(chorusfx_ips_settings)},
+ {CHORUS_TYPE_OCTAVER, "Octaver", chorusfx_octaver_settings, G_N_ELEMENTS(chorusfx_octaver_settings)},
+};
+
+static EffectGroup rp500_chorusfx_group[] = {
+ {CHORUS_TYPE_CE, "CE Chorus", chorusfx_ce_settings, G_N_ELEMENTS(chorusfx_ce_settings)},
+ {CHORUS_TYPE_TC, "TC Chorus", chorusfx_tc_settings, G_N_ELEMENTS(chorusfx_tc_settings)},
+ {CHORUS_TYPE_DUAL, "Dual Chorus", chorusfx_dual_settings, G_N_ELEMENTS(chorusfx_dual_settings)},
+ {CHORUS_TYPE_GLISTEN, "Glisten Chorus", chorusfx_glisten_settings, G_N_ELEMENTS(chorusfx_glisten_settings)},
+ {CHORUS_TYPE_MULTI, "Multi Chorus", chorusfx_multi_settings, G_N_ELEMENTS(chorusfx_multi_settings)},
+ {CHORUS_TYPE_FLANGER, "Flanger", chorusfx_flanger_settings, G_N_ELEMENTS(chorusfx_flanger_settings)},
+ {CHORUS_TYPE_TRIGGERED_FLANGER, "Triggered Flanger", chorusfx_trig_flanger_settings, G_N_ELEMENTS(chorusfx_trig_flanger_settings)},
+ {CHORUS_TYPE_MXR_FLANGER, "MXR FLANGER", chorusfx_mxr_flanger_settings, G_N_ELEMENTS(chorusfx_mxr_flanger_settings)},
+ {CHORUS_TYPE_EH_FLANGER, "EH Flanger", chorusfx_eh_flanger_settings, G_N_ELEMENTS(chorusfx_eh_flanger_settings)},
+ {CHORUS_TYPE_AD_FLANGER, "AD Flanger", chorusfx_ad_flanger_settings, G_N_ELEMENTS(chorusfx_ad_flanger_settings)},
+ {CHORUS_TYPE_PHASER, "Phaser", chorusfx_phaser_settings, G_N_ELEMENTS(chorusfx_phaser_settings)},
+ {CHORUS_TYPE_TRIGGERED_PHASER, "Triggered Phaser", chorusfx_trig_phaser_settings, G_N_ELEMENTS(chorusfx_trig_phaser_settings)},
+ {CHORUS_TYPE_MX_PHASER, "MX Phaser", chorusfx_mx_phaser_settings, G_N_ELEMENTS(chorusfx_mx_phaser_settings)},
+ {CHORUS_TYPE_EH_PHASER, "EH Phaser", chorusfx_eh_phaser_settings, G_N_ELEMENTS(chorusfx_eh_phaser_settings)},
+ {CHORUS_TYPE_VIBRATO, "Vibrato", chorusfx_vibrato_settings, G_N_ELEMENTS(chorusfx_vibrato_settings)},
+ {CHORUS_TYPE_ROTARY, "Rotary", chorusfx_rotary_settings, G_N_ELEMENTS(chorusfx_rotary_settings)},
+ {CHORUS_TYPE_VIBROPAN, "Vibropan", chorusfx_vibropan_settings, G_N_ELEMENTS(chorusfx_vibropan_settings)},
+ {CHORUS_TYPE_UNOVIBE, "Unovibe", chorusfx_unovibe_settings, G_N_ELEMENTS(chorusfx_unovibe_settings)},
+ {CHORUS_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {CHORUS_TYPE_SCATTER_TREM, "ScatterTrem", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_OPTO_TREMOLO, "Opto Tremolo", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_BIAS_TREMOLO, "Bias Tremolo", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {CHORUS_TYPE_ENVELOPE, "Envelope", chorusfx_envelope_settings, G_N_ELEMENTS(chorusfx_envelope_settings)},
+ {CHORUS_TYPE_FX25, "FX25", chorusfx_fx25_settings, G_N_ELEMENTS(chorusfx_fx25_settings)},
+ {CHORUS_TYPE_AUTOYA, "AutoYa", chorusfx_autoya_settings, G_N_ELEMENTS(chorusfx_autoya_settings)},
+ {CHORUS_TYPE_YAYA, "YaYa", chorusfx_yaya_settings, G_N_ELEMENTS(chorusfx_yaya_settings)},
+ {CHORUS_TYPE_SYNTH_TALK, "Synth Talk", chorusfx_synth_talk_settings, G_N_ELEMENTS(chorusfx_synth_talk_settings)},
+ {CHORUS_TYPE_STEP_FILTER, "Step Filter", chorusfx_step_filter_settings, G_N_ELEMENTS(chorusfx_step_filter_settings)},
+ {CHORUS_TYPE_SAMPLE_HOLD, "Sample/Hold", chorusfx_sample_hold_settings, G_N_ELEMENTS(chorusfx_sample_hold_settings)},
+ {CHORUS_TYPE_WHAMMY, "Whammy", chorusfx_whammy_settings, G_N_ELEMENTS(chorusfx_whammy_settings)},
+ {CHORUS_TYPE_PITCH_SHIFT, "Pitch", chorusfx_pitch_shift_settings, G_N_ELEMENTS(chorusfx_pitch_shift_settings)},
+ {CHORUS_TYPE_DETUNE, "Detune", chorusfx_detune_settings, G_N_ELEMENTS(chorusfx_detune_settings)},
+ {CHORUS_TYPE_IPS, "Harmony Pitch", chorusfx_ips_settings, G_N_ELEMENTS(chorusfx_ips_settings)},
+ {CHORUS_TYPE_OCTAVER, "Octaver", chorusfx_octaver_settings, G_N_ELEMENTS(chorusfx_octaver_settings)},
+};
+
+static EffectGroup rp1000_chorusfx_group[] = {
+ {CHORUS_TYPE_CE, "CE Chorus", chorusfx_ce_settings, G_N_ELEMENTS(chorusfx_ce_settings)},
+ {CHORUS_TYPE_TC, "TC Chorus", chorusfx_tc_settings, G_N_ELEMENTS(chorusfx_tc_settings)},
+ {CHORUS_TYPE_DUAL, "Dual Chorus", chorusfx_dual_settings, G_N_ELEMENTS(chorusfx_dual_settings)},
+ {CHORUS_TYPE_GLISTEN, "Glisten Chorus", chorusfx_glisten_settings, G_N_ELEMENTS(chorusfx_glisten_settings)},
+ {CHORUS_TYPE_MULTI, "Multi Chorus", chorusfx_multi_settings, G_N_ELEMENTS(chorusfx_multi_settings)},
+ {CHORUS_TYPE_VOO_DOO, "Analog Chorus", chorusfx_voo_doo_settings, G_N_ELEMENTS(chorusfx_voo_doo_settings)},
+ {CHORUS_TYPE_CLONE, "Small Clone", chorusfx_clone_settings, G_N_ELEMENTS(chorusfx_clone_settings)},
+ {CHORUS_TYPE_FLANGER, "Flanger", chorusfx_flanger_settings, G_N_ELEMENTS(chorusfx_flanger_settings)},
+ {CHORUS_TYPE_TRIGGERED_FLANGER, "Triggered Flanger", chorusfx_trig_flanger_settings, G_N_ELEMENTS(chorusfx_trig_flanger_settings)},
+ {CHORUS_TYPE_FLTFLANGER, "Filter Flanger", chorusfx_fltflanger_settings, G_N_ELEMENTS(chorusfx_fltflanger_settings)},
+ {CHORUS_TYPE_MXR_FLANGER, "MXR FLANGER", chorusfx_mxr_flanger_settings, G_N_ELEMENTS(chorusfx_mxr_flanger_settings)},
+ {CHORUS_TYPE_EH_FLANGER, "EH Flanger", chorusfx_eh_flanger_settings, G_N_ELEMENTS(chorusfx_eh_flanger_settings)},
+ {CHORUS_TYPE_AD_FLANGER, "AD Flanger", chorusfx_ad_flanger_settings, G_N_ELEMENTS(chorusfx_ad_flanger_settings)},
+ {CHORUS_TYPE_PHASER, "Phaser", chorusfx_phaser_settings, G_N_ELEMENTS(chorusfx_phaser_settings)},
+ {CHORUS_TYPE_TRIGGERED_PHASER, "Triggered Phaser", chorusfx_trig_phaser_settings, G_N_ELEMENTS(chorusfx_trig_phaser_settings)},
+ {CHORUS_TYPE_MX_PHASER, "MX Phaser", chorusfx_mx_phaser_settings, G_N_ELEMENTS(chorusfx_mx_phaser_settings)},
+ {CHORUS_TYPE_EH_PHASER, "EH Phaser", chorusfx_eh_phaser_settings, G_N_ELEMENTS(chorusfx_eh_phaser_settings)},
+ {CHORUS_TYPE_VIBRATO, "Vibrato", chorusfx_vibrato_settings, G_N_ELEMENTS(chorusfx_vibrato_settings)},
+ {CHORUS_TYPE_ROTARY, "Rotary", chorusfx_rotary_settings, G_N_ELEMENTS(chorusfx_rotary_settings)},
+ {CHORUS_TYPE_VIBROPAN, "Vibropan", chorusfx_vibropan_settings, G_N_ELEMENTS(chorusfx_vibropan_settings)},
+ {CHORUS_TYPE_UNOVIBE, "Unovibe", chorusfx_unovibe_settings, G_N_ELEMENTS(chorusfx_unovibe_settings)},
+ {CHORUS_TYPE_TREMOLO, "Tremolo", chorusfx_tremolo_settings, G_N_ELEMENTS(chorusfx_tremolo_settings)},
+ {CHORUS_TYPE_SCATTER_TREM, "ScatterTrem", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_OPTO_TREMOLO, "Opto Tremolo", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_BIAS_TREMOLO, "Bias Tremolo", chorusfx_trem_settings, G_N_ELEMENTS(chorusfx_trem_settings)},
+ {CHORUS_TYPE_PANNER, "Panner", chorusfx_panner_settings, G_N_ELEMENTS(chorusfx_panner_settings)},
+ {CHORUS_TYPE_ENVELOPE, "Envelope", chorusfx_envelope_settings, G_N_ELEMENTS(chorusfx_envelope_settings)},
+ {CHORUS_TYPE_FX25, "FX25", chorusfx_fx25_settings, G_N_ELEMENTS(chorusfx_fx25_settings)},
+ {CHORUS_TYPE_AUTOYA, "AutoYa", chorusfx_autoya_settings, G_N_ELEMENTS(chorusfx_autoya_settings)},
+ {CHORUS_TYPE_YAYA, "YaYa", chorusfx_yaya_settings, G_N_ELEMENTS(chorusfx_yaya_settings)},
+ {CHORUS_TYPE_SYNTH_TALK, "Synth Talk", chorusfx_synth_talk_settings, G_N_ELEMENTS(chorusfx_synth_talk_settings)},
+ {CHORUS_TYPE_STEP_FILTER, "Step Filter", chorusfx_step_filter_settings, G_N_ELEMENTS(chorusfx_step_filter_settings)},
+ {CHORUS_TYPE_SAMPLE_HOLD, "Sample/Hold", chorusfx_sample_hold_settings, G_N_ELEMENTS(chorusfx_sample_hold_settings)},
+ {CHORUS_TYPE_WHAMMY, "Whammy", chorusfx_whammy_settings, G_N_ELEMENTS(chorusfx_whammy_settings)},
+ {CHORUS_TYPE_PITCH_SHIFT, "Pitch", chorusfx_pitch_shift_settings, G_N_ELEMENTS(chorusfx_pitch_shift_settings)},
+ {CHORUS_TYPE_DETUNE, "Detune", chorusfx_detune_settings, G_N_ELEMENTS(chorusfx_detune_settings)},
+ {CHORUS_TYPE_IPS, "Harmony Pitch", chorusfx_ips_settings, G_N_ELEMENTS(chorusfx_ips_settings)},
+ {CHORUS_TYPE_OCTAVER, "Octaver", chorusfx_octaver_settings, G_N_ELEMENTS(chorusfx_octaver_settings)},
+};
+
+static EffectGroup gnx3k_delay_group[] = {
+ {DELAY_GNX3K_TYPE_MONO, "Mono", gnx3k_delay_settings, G_N_ELEMENTS(gnx3k_delay_settings)},
+ {DELAY_GNX3K_TYPE_PINGPONG, "Ping-Pong", gnx3k_delay_settings, G_N_ELEMENTS(gnx3k_delay_settings)},
+ {DELAY_GNX3K_TYPE_ANALOG, "Analog", gnx3k_delay_settings, G_N_ELEMENTS(gnx3k_delay_settings)},
+ {DELAY_GNX3K_TYPE_ANAPONG, "Analog-Pong", gnx3k_delay_settings, G_N_ELEMENTS(gnx3k_delay_settings)},
+ {DELAY_GNX3K_TYPE_SPREAD, "Spread", gnx3k_delay_spread_settings, G_N_ELEMENTS(gnx3k_delay_spread_settings)},
+};
+
+static EffectGroup rp250_delay_group[] = {
+ {DELAY_TYPE_ANALOG, "Analog", delay_analog_settings, G_N_ELEMENTS(delay_analog_settings)},
+ {DELAY_TYPE_DIGITAL, "Digital", delay_digital_settings, G_N_ELEMENTS(delay_digital_settings)},
+ {DELAY_TYPE_MODULATED, "Modulated", delay_modulated_settings, G_N_ELEMENTS(delay_modulated_settings)},
+ {DELAY_TYPE_PONG, "Pong", delay_pong_settings, G_N_ELEMENTS(delay_pong_settings)},
+ {DELAY_TYPE_TAPE, "Tape", delay_tape_settings, G_N_ELEMENTS(delay_tape_settings)},
+};
+
+static EffectGroup rp355_delay_group[] = {
+ {DELAY_TYPE_ANALOG, "Analog", delay_analog_settings, G_N_ELEMENTS(delay_analog_settings)},
+ {DELAY_TYPE_DM, "DM Delay", delay_dm_settings, G_N_ELEMENTS(delay_dm_settings)},
+ {DELAY_TYPE_DIGITAL, "Digital", delay_digital_settings, G_N_ELEMENTS(delay_digital_settings)},
+ {DELAY_TYPE_MODULATED, "Modulated", delay_modulated_settings, G_N_ELEMENTS(delay_modulated_settings)},
+ {DELAY_TYPE_PONG, "Pong", delay_pong_settings, G_N_ELEMENTS(delay_pong_settings)},
+ {DELAY_TYPE_TAPE, "Tape", delay_tape_settings, G_N_ELEMENTS(delay_tape_settings)},
+ {DELAY_TYPE_ECHOPLEX, "Echo Plex", delay_echoplex_settings, G_N_ELEMENTS(delay_echoplex_settings)},
+};
+
+static EffectGroup rp500_delay_group[] = {
+ {DELAY_RP500_TYPE_DIGITAL, "Digital", rp500_delay_digital_settings, G_N_ELEMENTS(rp500_delay_digital_settings)},
+ {DELAY_RP500_TYPE_ANALOG, "Analog", rp500_delay_analog_settings, G_N_ELEMENTS(rp500_delay_analog_settings)},
+ {DELAY_RP500_TYPE_DM, "DM Delay", rp500_delay_dm_settings, G_N_ELEMENTS(rp500_delay_dm_settings)},
+ {DELAY_RP500_TYPE_ECHOPLEX, "Echo Plex", rp500_delay_echoplex_settings, G_N_ELEMENTS(rp500_delay_echoplex_settings)},
+ {DELAY_RP500_TYPE_MODULATED, "Modulated", rp500_delay_modulated_settings, G_N_ELEMENTS(rp500_delay_modulated_settings)},
+ {DELAY_RP500_TYPE_PONG, "Pong", rp500_delay_pong_settings, G_N_ELEMENTS(rp500_delay_pong_settings)},
+ {DELAY_RP500_TYPE_REVERSE, "Reverse", rp500_delay_reverse_settings, G_N_ELEMENTS(rp500_delay_reverse_settings)},
+ {DELAY_RP500_TYPE_TAPE, "Tape", rp500_delay_tape_settings, G_N_ELEMENTS(rp500_delay_tape_settings)},
+};
+
+static EffectGroup rp1000_delay_group[] = {
+ {DELAY_RP500_TYPE_DIGITAL, "Digital", rp500_delay_digital_settings, G_N_ELEMENTS(rp500_delay_digital_settings)},
+ {DELAY_RP500_TYPE_ANALOG, "Analog", rp500_delay_analog_settings, G_N_ELEMENTS(rp500_delay_analog_settings)},
+ {DELAY_RP500_TYPE_DM, "DM Delay", rp500_delay_dm_settings, G_N_ELEMENTS(rp500_delay_dm_settings)},
+ {DELAY_RP500_TYPE_ECHOPLEX, "Echo Plex", rp500_delay_echoplex_settings, G_N_ELEMENTS(rp500_delay_echoplex_settings)},
+ {DELAY_RP500_TYPE_MODULATED, "Modulated", rp500_delay_modulated_settings, G_N_ELEMENTS(rp500_delay_modulated_settings)},
+ {DELAY_RP500_TYPE_PONG, "Pong", rp500_delay_pong_settings, G_N_ELEMENTS(rp500_delay_pong_settings)},
+ {DELAY_RP500_TYPE_REVERSE, "Reverse", rp500_delay_reverse_settings, G_N_ELEMENTS(rp500_delay_reverse_settings)},
+ {DELAY_RP500_TYPE_TAPE, "Tape", rp500_delay_tape_settings, G_N_ELEMENTS(rp500_delay_tape_settings)},
+ {DELAY_RP1000_TYPE_LO_FI, "Lo Fidelity", rp1000_delay_lo_fi_settings, G_N_ELEMENTS(rp1000_delay_lo_fi_settings)},
+ {DELAY_RP1000_TYPE_2_TAP, "2-tap", rp1000_delay_2_tap_settings, G_N_ELEMENTS(rp1000_delay_2_tap_settings)},
+};
+
+static EffectGroup gnx3k_reverb_group[] = {
+ {GNX3K_REVERB_TYPE_STUDIO, "Studio", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_ROOM, "Room", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_CLUB, "Club", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_PLATE, "Plate", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_HALL, "Hall", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_AMPHITHEATER, "Amphitheater", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_CHURCH, "Church", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_GARAGE, "Garage", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_ARENA, "Arena", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+ {GNX3K_REVERB_TYPE_SPRING, "Spring", gnx3k_reverb_settings, G_N_ELEMENTS(gnx3k_reverb_settings)},
+};
+
+static EffectGroup reverb_group[] = {
+ {REVERB_TYPE_TWIN, "Twin", reverb_twin_settings, G_N_ELEMENTS(reverb_twin_settings)},
+ {REVERB_TYPE_LEX_AMBIENCE, "Lexicon ambience", reverb_lex_settings, G_N_ELEMENTS(reverb_lex_settings)},
+ {REVERB_TYPE_LEX_STUDIO, "Lexicon studio", reverb_lex_settings, G_N_ELEMENTS(reverb_lex_settings)},
+ {REVERB_TYPE_LEX_ROOM, "Lexicon room", reverb_lex_settings, G_N_ELEMENTS(reverb_lex_settings)},
+ {REVERB_TYPE_LEX_HALL, "Lexicon hall", reverb_lex_settings, G_N_ELEMENTS(reverb_lex_settings)},
+ {REVERB_TYPE_EMT240_PLATE, "EMT240 Plate", reverb_lex_settings, G_N_ELEMENTS(reverb_lex_settings)},
+};
+
+static EffectGroup rp155_amp_group[] = {
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Super Lead Plexi", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_JCM800, "JCM800", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_JCM900, "JCM900", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_AC15, "AC15", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_AC30TB, "AC30TB", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark II", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_SOLO, "Solo", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_METAL, "Metal", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BRIGHT, "Bright", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_CLEAN, "Clean", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_ACOUSTIC, "Acoustic", rp250_amp_settings2, G_N_ELEMENTS(rp250_amp_settings2)},
+ {AMP_TYPE_DIRECT, "Direct", rp250_amp_settings2, G_N_ELEMENTS(rp250_amp_settings2)},
+};
+
+static EffectGroup rp250_amp_group[] = {
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Super Lead Plexi", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_JCM800, "JCM800", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_JCM900, "JCM900", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_AC15, "AC15", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_AC30TB, "AC30TB", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark II", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_SOLO, "Solo", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_METAL, "Metal", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BRIGHT, "Bright", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_CLEAN, "Clean", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_ACOUSTIC, "Acoustic", rp250_amp_settings2, G_N_ELEMENTS(rp250_amp_settings2)},
+ {AMP_TYPE_DIRECT, "Direct", rp250_amp_settings2, G_N_ELEMENTS(rp250_amp_settings2)},
+};
+
+/* same as RP250, with added 45 JTM, JMPPNL and SOLDNO */
+static EffectGroup rp255_amp_group[] = {
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Super Lead Plexi", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_PLEXI_JTM_45, "Plexi JTM-45", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_PLEXI_JUMP_PANEL, "Plexi Jump Panel", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_JCM800, "JCM800", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_JCM900, "JCM900", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_AC15, "AC15", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_AC30TB, "AC30TB", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark II", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_SOLDANO_100, "Soldano 100", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_SOLO, "Solo", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_METAL, "Metal", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_BRIGHT, "Bright", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_CLEAN, "Clean", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", rp250_amp_settings, G_N_ELEMENTS(rp250_amp_settings)},
+ {AMP_TYPE_ACOUSTIC, "Acoustic", rp250_amp_settings2, G_N_ELEMENTS(rp250_amp_settings2)},
+ {AMP_TYPE_DIRECT, "Direct", rp250_amp_settings2, G_N_ELEMENTS(rp250_amp_settings2)},
+};
+
+static EffectGroup rp355_amp_select_group[] = {
+ {AMP_CHANNEL_A, "A", NULL, -1},
+ {AMP_CHANNEL_B, "B", NULL, -1},
+};
+
+static EffectGroup rp355_amp_group_A[] = {
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_PLEXI_JTM_45, "Plexi JTM-45", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Plexi Lead", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_PLEXI_JUMP_PANEL, "Plexi Jump Panel", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_JCM800, "JCM800", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_JCM900, "JCM900", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_AC15, "AC-15", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_AC30TB, "AC-30 TB", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark IIC", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_SOLDANO_100, "Soldano 100", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_SOLO, "Solo", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_METAL, "Metal", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_BRIGHT, "Bright Clean", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_CHUNK, "Chunk", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_CLEAN, "Clean Tube", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_GSP2101_CLEAN_TUBE, "GSP2101 Clean Tube", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_GSP2101_SAT_TUBE, "GSP2101 Sat Tube", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_MONSTER, "Monster", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_TWEEDFACE, "Tweedface", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_BLACKBASS, "Blackbass", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_STONER_ROCK, "Stoner Rock", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_DARK_METAL, "Dark Metal", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_BROWN_SOUND, "Brown Sound", rp355_amp_settings_A, G_N_ELEMENTS(rp355_amp_settings_A)},
+ {AMP_TYPE_ACOUSTIC, "Dread Acoustic", rp355_amp_settings2_A, G_N_ELEMENTS(rp355_amp_settings2_A)},
+ {AMP_TYPE_JUMBO_ACOUSTIC, "Jumbo Acoustic", rp355_amp_settings2_A, G_N_ELEMENTS(rp355_amp_settings2_A)},
+ {AMP_TYPE_DIRECT, "Direct", rp355_amp_settings2_A, G_N_ELEMENTS(rp355_amp_settings2_A)},
+};
+
+static EffectGroup rp355_amp_group_B[] = {
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_PLEXI_JTM_45, "Plexi JTM-45", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Plexi Lead", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_PLEXI_JUMP_PANEL, "Plexi Jump Panel", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_JCM800, "JCM800", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_JCM900, "JCM900", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_AC15, "AC-15", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_AC30TB, "AC-30 TB", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark IIC", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_SOLDANO_100, "Soldano 100", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_SOLO, "Solo", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_METAL, "Metal", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_BRIGHT, "Bright Clean", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_CHUNK, "Chunk", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_CLEAN, "Clean Tube", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_GSP2101_CLEAN_TUBE, "GSP2101 Clean Tube", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_GSP2101_SAT_TUBE, "GSP2101 Sat Tube", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_MONSTER, "Monster", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_TWEEDFACE, "Tweedface", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_BLACKBASS, "Blackbass", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_STONER_ROCK, "Stoner Rock", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_DARK_METAL, "Dark Metal", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_BROWN_SOUND, "Brown Sound", rp355_amp_settings_B, G_N_ELEMENTS(rp355_amp_settings_B)},
+ {AMP_TYPE_ACOUSTIC, "Dread Acoustic", rp355_amp_settings2_B, G_N_ELEMENTS(rp355_amp_settings2_B)},
+ {AMP_TYPE_JUMBO_ACOUSTIC, "Jumbo Acoustic", rp355_amp_settings2_B, G_N_ELEMENTS(rp355_amp_settings2_B)},
+ {AMP_TYPE_DIRECT, "Direct", rp355_amp_settings2_B, G_N_ELEMENTS(rp355_amp_settings2_B)},
+};
+
+static EffectGroup rp500_amp_group[] = {
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BROWN_BASSMAN, "Brown Bassman", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_PLEXI_JTM_45, "Plexi JTM-45", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Plexi Lead", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_PLEXI_JUMP_PANEL, "Plexi Jump Panel", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JCM800, "JCM800", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JCM900, "JCM900", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JCM2000, "JCM2000", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_AC15, "AC-15", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_AC30TB, "AC-30 TB", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark IIC", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BOOGIE_MARK_IV, "Boogie Mark IV", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TRIPLE_RECTIFIER, "Triple Rectifier", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_LEGACY_VL100, "Legacy VL-100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SOLDANO_100, "Soldano 100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SUPERGROUP, "Supergroup", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_GA40, "GA-40", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_OR120, "OR-120", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_PV5150II, "PV 5150II", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_RG100, "RG100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JC120_JAZZ, "JC-120 Jazz", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SOLAR100, "Solar 100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SOLO, "Solo", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_METAL, "Metal", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BRIGHT, "Bright Clean", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_CHUNK, "Chunk", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_CLEAN, "Clean Tube", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLUES, "Blues", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_FUZZ, "Fuzz", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SPANK, "Spank", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_GSP2101_CLEAN_TUBE, "GSP2101 Clean Tube", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_GSP2101_SAT_TUBE, "GSP2101 Sat Tube", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_CRUNCH, "Crunch", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MONSTER, "Monster", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TWEEDFACE, "Tweedface", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLACKBASS, "Blackbass", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_STONER_ROCK, "Stoner Rock", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_DARK_METAL, "Dark Metal", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TRANSISTOR, "Transistor", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BROWN_SOUND, "Brown Sound", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MOSH, "Mosh", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_ACOUSTIC, "Dread Acoustic", rp500_amp_settings2, G_N_ELEMENTS(rp500_amp_settings2)},
+ {AMP_TYPE_JUMBO_ACOUSTIC, "Jumbo Acoustic", rp500_amp_settings2, G_N_ELEMENTS(rp500_amp_settings2)},
+ {AMP_TYPE_DIRECT, "Direct", rp500_amp_settings3, G_N_ELEMENTS(rp500_amp_settings3)},
+};
+
+static EffectGroup rp1000_amp_group[] = {
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BROWN_BASSMAN, "Brown Bassman", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_PLEXI_JTM_45, "Plexi JTM-45", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Plexi Lead", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_PLEXI_JUMP_PANEL, "Plexi Jump Panel", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JCM800, "JCM800", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JCM900, "JCM900", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JCM2000, "JCM2000", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_AC15, "AC-15", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_AC30TB, "AC-30 TB", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark IIC", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BOOGIE_MARK_IV, "Boogie Mark IV", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TRIPLE_RECTIFIER, "Triple Rectifier", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_22_CALIBR, ".22 Caliber", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_LEGACY_VL100, "Legacy VL-100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_CHIEF, "Matchless Chieftan", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SOLDANO_100, "Soldano 100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SUPERGROUP, "Supergroup", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_GA40, "GA-40", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_OR120, "OR-120", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_PV5150II, "PV 5150II", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_RG100, "RG100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_JC120_JAZZ, "JC-120 Jazz", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SOLAR100, "Solar 100", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SOLO, "Solo", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_METAL, "Metal", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BRIGHT, "Bright Clean", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_CHUNK, "Chunk", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_CLEAN, "Clean Tube", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLUES, "Blues", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_FUZZ, "Fuzz", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_SPANK, "Spank", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_GSP2101_CLEAN_TUBE, "GSP2101 Clean Tube", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_GSP2101_SAT_TUBE, "GSP2101 Sat Tube", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_CRUNCH, "Crunch", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MONSTER, "Monster", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TWEEDFACE, "Tweedface", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BLACKBASS, "Blackbass", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_STONER_ROCK, "Stoner Rock", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_DARK_METAL, "Dark Metal", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_TRANSISTOR, "Transistor", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_BROWN_SOUND, "Brown Sound", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_MOSH, "Mosh", rp500_amp_settings, G_N_ELEMENTS(rp500_amp_settings)},
+ {AMP_TYPE_ACOUSTIC, "Dread Acoustic", rp500_amp_settings2, G_N_ELEMENTS(rp500_amp_settings2)},
+ {AMP_TYPE_JUMBO_ACOUSTIC, "Jumbo Acoustic", rp500_amp_settings2, G_N_ELEMENTS(rp500_amp_settings2)},
+ {AMP_TYPE_DIRECT, "Direct", rp500_amp_settings3, G_N_ELEMENTS(rp500_amp_settings3)},
+};
+
+static EffectGroup gnx3k_amp_group[] = {
+ {AMP_TYPE_DIRECT, "Direct", NULL, -1},
+ {AMP_TYPE_TWEED_CHAMP, "Tweed Champ", NULL, -1},
+ {AMP_TYPE_TWEED_DELUXE, "Tweed Deluxe", NULL, -1},
+ {AMP_TYPE_TWEED_BASSMAN, "Tweed Bassman", NULL, -1},
+ {AMP_TYPE_BROWN_BASSMAN, "Brown Bassman", NULL, -1},
+ {AMP_TYPE_BLACKFACE_TWIN, "Blackface Twin", NULL, -1},
+ {AMP_TYPE_BLACKFACE_DELUXE, "Blackface Deluxe", NULL, -1},
+ {AMP_TYPE_PLEXI_JTM_45, "Plexi JTM-45", NULL, -1},
+ {AMP_TYPE_SUPER_LEAD_PLEXI, "Plexi Lead", NULL, -1},
+ {AMP_TYPE_PLEXI_JUMP_PANEL, "Plexi Jump Panel", NULL, -1},
+ {AMP_TYPE_MASTER_VOLUME, "Master Volume", NULL, -1},
+ {AMP_TYPE_JCM800, "JCM800", NULL, -1},
+ {AMP_TYPE_JCM900, "JCM900", NULL, -1},
+ {AMP_TYPE_JCM2000, "JCM2000", NULL, -1},
+ {AMP_TYPE_BOOGIE_MARK_II, "Boogie Mark II", NULL, -1},
+ {AMP_TYPE_DUAL_RECTIFIER, "Dual Rectifier", NULL, -1},
+ {AMP_TYPE_AC15, "AC-15", NULL, -1},
+ {AMP_TYPE_AC30TB, "AC-30 TB", NULL, -1},
+ {AMP_TYPE_HIWATT_100, "Hiwatt 100", NULL, -1},
+ {AMP_TYPE_SOLO, "Solo", NULL, -1},
+ {AMP_TYPE_MATCHLESS_HC30, "Matchless HC30", NULL, -1},
+ {AMP_TYPE_LEGACY_VL100, "Legacy VL-100", NULL, -1},
+ {AMP_TYPE_GSP2101_CLEAN_TUBE, "GSP2101 Clean Tube", NULL, -1},
+ {AMP_TYPE_GSP2101_SAT_TUBE, "GSP2101 Sat Tube", NULL, -1},
+ {AMP_TYPE_SPANK, "Spank", NULL, -1},
+ {AMP_TYPE_METAL, "Metal", NULL, -1},
+ {AMP_TYPE_BRIGHT, "Bright Clean", NULL, -1},
+ {AMP_TYPE_CHUNK, "Chunk", NULL, -1},
+ {AMP_TYPE_CLEAN, "Clean Tube", NULL, -1},
+ {AMP_TYPE_CRUNCH, "Crunch", NULL, -1},
+ {AMP_TYPE_HIGH_GAIN, "High Gain", NULL, -1},
+ {AMP_TYPE_BLUES, "Blues", NULL, -1},
+ {AMP_TYPE_FUZZ, "Fuzz", NULL, -1},
+ {AMP_TYPE_JUMBO_ACOUSTIC, "Jumbo Acoustic", NULL, -1},
+ {AMP_TYPE_ACOUSTIC, "Dread Acoustic", NULL, -1},
+ {AMP_TYPE_SVT_ROCK_BASS, "SVT Rock Bass", NULL, -1},
+ {AMP_TYPE_SVT_CLASSIC_BASS, "SVT Classic Bass", NULL, -1},
+ {AMP_TYPE_PEG_B15_BASS, "Peg B-15 Bass", NULL, -1},
+ {AMP_TYPE_BASIC_BASS , "Basic Bass", NULL, -1},
+ {AMP_TYPE_SHOWMAN_BASS , "Showman Bass", NULL, -1},
+ {AMP_TYPE_ASH_MODERN_BASS , "Ash Modern Bass", NULL, -1},
+ {AMP_TYPE_BRIT_BASS , "Brit Bass", NULL, -1},
+ {AMP_TYPE_SOLAR_BASS , "Solar 200s Bass", NULL, -1},
+ {AMP_TYPE_BOOGIE_BASS , "Boogie Bass", NULL, -1},
+ {AMP_TYPE_HART_BASS , "Hart Bass", NULL, -1},
+};
+
+static EffectGroup rp250_eq_group[] = {
+ {EQ_TYPE_BRIGHT, "Bright", rp250_eq_settings, G_N_ELEMENTS(rp250_eq_settings)},
+ {EQ_TYPE_MIDBOOST, "Mid Boost", rp250_eq_settings, G_N_ELEMENTS(rp250_eq_settings)},
+ {EQ_TYPE_SCOOP, "Scoop", rp250_eq_settings, G_N_ELEMENTS(rp250_eq_settings)},
+ {EQ_TYPE_WARM, "Warm", rp250_eq_settings, G_N_ELEMENTS(rp250_eq_settings)},
+};
+
+static EffectGroup rp355_eq_group_A[] = {
+ {EQ_TYPE_BRIGHT, "Bright", rp355_eq_settings_A, G_N_ELEMENTS(rp355_eq_settings_A)},
+ {EQ_TYPE_MIDBOOST, "Mid Boost", rp355_eq_settings_A, G_N_ELEMENTS(rp355_eq_settings_A)},
+ {EQ_TYPE_SCOOP, "Scoop", rp355_eq_settings_A, G_N_ELEMENTS(rp355_eq_settings_A)},
+ {EQ_TYPE_WARM, "Warm", rp355_eq_settings_A, G_N_ELEMENTS(rp355_eq_settings_A)},
+};
+
+static EffectGroup rp355_eq_group_B[] = {
+ {EQ_TYPE_BRIGHT, "Bright", rp355_eq_settings_B, G_N_ELEMENTS(rp355_eq_settings_B)},
+ {EQ_TYPE_MIDBOOST, "Mid Boost", rp355_eq_settings_B, G_N_ELEMENTS(rp355_eq_settings_B)},
+ {EQ_TYPE_SCOOP, "Scoop", rp355_eq_settings_B, G_N_ELEMENTS(rp355_eq_settings_B)},
+ {EQ_TYPE_WARM, "Warm", rp355_eq_settings_B, G_N_ELEMENTS(rp355_eq_settings_B)},
+};
+
+static EffectGroup rp500_eq_group[] = {
+ {-1, NULL, rp500_eq_settings, G_N_ELEMENTS(rp500_eq_settings)},
+};
+
+static EffectGroup rp155_amp_cab_group[] = {
+ {AMP_CAB_DIRECT, "Direct", NULL, -1},
+ {AMP_CAB_DELUXE, "Deluxe 1x12", NULL, -1},
+ {AMP_CAB_TWIN, "Twin 2x12", NULL, -1},
+ {AMP_CAB_BRITISH2_12, "British 2x12", NULL, -1},
+ {AMP_CAB_BASSMAN, "Bassman 4x10", NULL, -1},
+ {AMP_CAB_BRITISH4_12, "British 4x12", NULL, -1},
+ {AMP_CAB_VINTAGE, "Vintage V30 4x12", NULL, -1},
+ {AMP_CAB_DIGI_SOLO, "DigiTech Solo 4x12", NULL, -1},
+ {AMP_CAB_DIGI_BRIGHT, "DigiTech Bright 2x12", NULL, -1},
+ {AMP_CAB_DIGI_METAL, "DigiTech Metal 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ROCK, "DigiTech Rock 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ALT, "DigiTech Alt 4x12", NULL, -1},
+ {AMP_CAB_DIGI_VNTG, "DigiTech Vntg 4x12", NULL, -1},
+};
+
+static EffectGroup rp250_amp_cab_group[] = {
+ {AMP_CAB_DIRECT, "Direct", NULL, -1},
+ {AMP_CAB_CHAMP, "Champ 1x8", NULL, -1},
+ {AMP_CAB_DELUXE, "Deluxe 1x12", NULL, -1},
+ {AMP_CAB_TWIN, "Twin 2x12", NULL, -1},
+ {AMP_CAB_BRITISH2_12, "British 2x12", NULL, -1},
+ {AMP_CAB_BASSMAN, "Bassman 4x10", NULL, -1},
+ {AMP_CAB_BRITISH4_12, "British 4x12", NULL, -1},
+ {AMP_CAB_BRITISH_GREEN, "British Green 4x12", NULL, -1},
+ {AMP_CAB_VINTAGE, "Vintage V30 4x12", NULL, -1},
+ {AMP_CAB_DIGI_SOLO, "DigiTech Solo 4x12", NULL, -1},
+ {AMP_CAB_DIGI_BRIGHT, "DigiTech Bright 2x12", NULL, -1},
+ {AMP_CAB_DIGI_METAL, "DigiTech Metal 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ROCK, "DigiTech Rock 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ALT, "DigiTech Alt 4x12", NULL, -1},
+ {AMP_CAB_DIGI_VNTG, "DigiTech Vntg 4x12", NULL, -1},
+};
+
+static EffectGroup rp355_amp_cab_group[] = {
+ {AMP_CAB_DIRECT, "Direct", NULL, -1},
+ {AMP_CAB_CHAMP, "Champ 1x8", NULL, -1},
+ {AMP_CAB_DELUXE, "Deluxe 1x12", NULL, -1},
+ {AMP_CAB_DELUXE_REVERB, "Deluxe Reverb 1x12", NULL, -1},
+ {AMP_CAB_BLONDE2_12, "Blonde 2x12", NULL, -1},
+ {AMP_CAB_TWIN, "Twin 2x12", NULL, -1},
+ {AMP_CAB_BRITISH2_12, "British 2x12", NULL, -1},
+ {AMP_CAB_BASSMAN, "Bassman 4x10", NULL, -1},
+ {AMP_CAB_BRITISH4_12, "British 4x12", NULL, -1},
+ {AMP_CAB_BRITISH_GREEN, "British Green 4x12", NULL, -1},
+ {AMP_CAB_FANE4_12, "Fane 4x12", NULL, -1},
+ {AMP_CAB_BOUTIQUE4_12, "Boutique 4x12", NULL, -1},
+ {AMP_CAB_VINTAGE, "Vintage V30 4x12", NULL, -1},
+ {AMP_CAB_DIGI_SOLO, "DigiTech Solo 4x12", NULL, -1},
+ {AMP_CAB_DIGI_BRIGHT, "DigiTech Bright 2x12", NULL, -1},
+ {AMP_CAB_DIGI_METAL, "DigiTech Metal 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ROCK, "DigiTech Rock 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ALT, "DigiTech Alt 4x12", NULL, -1},
+ {AMP_CAB_DIGI_VNTG, "DigiTech Vntg 4x12", NULL, -1},
+};
+
+static EffectGroup rp500_amp_cab_group[] = {
+ {AMP_CAB_DIRECT, "Direct", NULL, -1},
+ {AMP_CAB_CHAMP, "Champ", NULL, -1},
+ {AMP_CAB_DELUXE, "Deluxe", NULL, -1},
+ {AMP_CAB_DELUXE_REVERB, "Deluxe Reverb 1x12", NULL, -1},
+ {AMP_CAB_BRITISH1_12, "British 1x12", NULL, -1},
+ {AMP_CAB_GA1_12, "GA 1x12", NULL, -1},
+ {AMP_CAB_BLONDE2_12, "Blonde 2x12", NULL, -1},
+ {AMP_CAB_TWIN, "Twin 2x12", NULL, -1},
+ {AMP_CAB_BRITISH2_12, "British 2x12", NULL, -1},
+ {AMP_CAB_JAZZ2_12, "Jazz 2x12", NULL, -1},
+ {AMP_CAB_BASSMAN, "Bassman 4x10", NULL, -1},
+ {AMP_CAB_BRITISH4_12, "British 4x12", NULL, -1},
+ {AMP_CAB_BRITISH_GREEN, "Greenback 4x12", NULL, -1},
+ {AMP_CAB_FANE4_12, "Fane 4x12", NULL, -1},
+ {AMP_CAB_BOUTIQUE4_12, "Boutique 4x12", NULL, -1},
+ {AMP_CAB_VINTAGE, "Vintage 4x12", NULL, -1},
+ {AMP_CAB_RECTO4_12, "Recto 4x12", NULL, -1},
+ {AMP_CAB_DIGI_SOLO, "DigiTech Solo 4x12", NULL, -1},
+ {AMP_CAB_DIGI_BRIGHT, "DigiTech Bright 2x12", NULL, -1},
+ {AMP_CAB_DIGI_METAL, "DigiTech Metal 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ROCK, "DigiTech Rock 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ALT, "DigiTech Alt 4x12", NULL, -1},
+ {AMP_CAB_DIGI_VNTG, "DigiTech Vintage 4x12", NULL, -1},
+ {AMP_CAB_DIGI_CHUNK, "DigiTech Chunk 4x12", NULL, -1},
+ {AMP_CAB_DIGI_SPANK2_12, "DigiTech Spank 2x12", NULL, -1},
+ {AMP_CAB_DIGI_SPKR_COMP, "DigiTech Spkr Comp", NULL, -1},
+};
+
+static EffectGroup rp1000_amp_cab_group[] = {
+ {AMP_CAB_DIRECT, "Direct", NULL, -1},
+ {AMP_CAB_CHAMP, "Champ", NULL, -1},
+ {AMP_CAB_DELUXE, "Deluxe", NULL, -1},
+ {AMP_CAB_DELUXE_REVERB, "Deluxe Reverb 1x12", NULL, -1},
+ {AMP_CAB_BRITISH1_12, "British 1x12", NULL, -1},
+ {AMP_CAB_GA1_12, "GA 1x12", NULL, -1},
+ {AMP_CAB_BLONDE2_12, "Blonde 2x12", NULL, -1},
+ {AMP_CAB_TWIN, "Twin 2x12", NULL, -1},
+ {AMP_CAB_BRITISH2_12, "British 2x12", NULL, -1},
+ {AMP_CAB_JAZZ2_12, "Jazz 2x12", NULL, -1},
+ {AMP_CAB_JBL_215, "JBL/Lansing Enclosure", NULL, -1},
+ {AMP_CAB_BASSMAN, "Bassman 4x10", NULL, -1},
+ {AMP_CAB_BRITISH4_12, "British 4x12", NULL, -1},
+ {AMP_CAB_BRITISH_GREEN, "Greenback 4x12", NULL, -1},
+ {AMP_CAB_FANE4_12, "Fane 4x12", NULL, -1},
+ {AMP_CAB_BOUTIQUE4_12, "Boutique 4x12", NULL, -1},
+ {AMP_CAB_VINTAGE, "Vintage 4x12", NULL, -1},
+ {AMP_CAB_RECTO4_12, "Recto 4x12", NULL, -1},
+ {AMP_CAB_DIGI_SOLO, "DigiTech Solo 4x12", NULL, -1},
+ {AMP_CAB_DIGI_BRIGHT, "DigiTech Bright 2x12", NULL, -1},
+ {AMP_CAB_DIGI_METAL, "DigiTech Metal 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ROCK, "DigiTech Rock 4x12", NULL, -1},
+ {AMP_CAB_DIGI_ALT, "DigiTech Alt 4x12", NULL, -1},
+ {AMP_CAB_DIGI_VNTG, "DigiTech Vintage 4x12", NULL, -1},
+ {AMP_CAB_DIGI_CHUNK, "DigiTech Chunk 4x12", NULL, -1},
+ {AMP_CAB_DIGI_SPANK2_12, "DigiTech Spank 2x12", NULL, -1},
+ {AMP_CAB_DIGI_SPKR_COMP, "DigiTech Spkr Comp", NULL, -1},
+};
+
+static EffectGroup gnx3k_amp_cab_group[] = {
+ {GNX_AMP_CAB_DIRECT, "Direct", NULL, -1},
+ {GNX_AMP_CAB_TWEED1_8, "Tweed 1x8", NULL, -1},
+ {GNX_AMP_CAB_TWEED1_12, "Tweed 1x12", NULL, -1},
+ {GNX_AMP_CAB_BLACKFACE1_12, "Blackface 1x12", NULL, -1},
+ {GNX_AMP_CAB_BRITISH1_12, "British 1x12", NULL, -1},
+ {GNX_AMP_CAB_BLACKFACE2_12, "Blackface 2x12", NULL, -1},
+ {GNX_AMP_CAB_BLONDE2_12, "Blonde 2x12", NULL, -1},
+ {GNX_AMP_CAB_BRITISH2_12, "British 2x12", NULL, -1},
+ {GNX_AMP_CAB_TWEED4_10, "Tweed 4x10", NULL, -1},
+ {GNX_AMP_CAB_BRITISH_70_4_12, "British 70 4x12", NULL, -1},
+ {GNX_AMP_CAB_BRITISH_GREEN4_12, "British Green 4x12", NULL, -1},
+ {GNX_AMP_CAB_STRAIGHT_V30_4_12, "Straight V30 4x12", NULL, -1},
+ {GNX_AMP_CAB_SLANT_V30_4_12, "Slant V30 4x12", NULL, -1},
+ {GNX_AMP_CAB_FANE4_12, "Fane 4x12", NULL, -1},
+ {GNX_AMP_CAB_2101_SPKR_COMP, "2101 Spkr Comp", NULL, -1},
+ {GNX_AMP_CAB_DIGI_SPANK, "Digitech Spank 4x12", NULL, -1},
+ {GNX_AMP_CAB_DIGI_SOLO, "Digitech Solo 4x12", NULL, -1},
+ {GNX_AMP_CAB_DIGI_METAL, "Digitech Metal 4x12", NULL, -1},
+ {GNX_AMP_CAB_DIGI_BRIGHT, "Digitech Bright 4x12", NULL, -1},
+ {GNX_AMP_CAB_DIGI_CHUNK, "Digitech Chunk 4x12", NULL, -1},
+ {GNX_AMP_CAB_JUMBO_ACOUSTIC, "Jumbo Acoustic", NULL, -1},
+ {GNX_AMP_CAB_DREAD_ACOUSTIC, "Dread Acoustic", NULL, -1},
+ {GNX_AMP_CAB_HART_BASS1_15, "Hart Bass 1x15", NULL, -1},
+ {GNX_AMP_CAB_BASIC_BASS1_15, "Basic Bass 1x15", NULL, -1},
+ {GNX_AMP_CAB_PORTA_BASS1_15, "Porta Bass 1x15", NULL, -1},
+ {GNX_AMP_CAB_REFLEX1_18, "Reflex 1x18", NULL, -1},
+ {GNX_AMP_CAB_SOLAR_BASS2_15, "Solar Bass 2x15", NULL, -1},
+ {GNX_AMP_CAB_DE_BASS4_10, "DE Bass 4x10", NULL, -1},
+ {GNX_AMP_CAB_ASH_BASS4_10, "Ash Bass 4x10", NULL, -1},
+ {GNX_AMP_CAB_GOLIATH_BASS4_10, "Goliath Bass 4x10", NULL, -1},
+ {GNX_AMP_CAB_HART_BASS4_10, "Hart Bass 4x10", NULL, -1},
+ {GNX_AMP_CAB_SVT_BASS8_10, "SVT Bass 8x10", NULL, -1},
+};
+
+static EffectGroup gnx3k_ch1_cab_tuning_group[] = {
+ {-1, NULL, gnx3k_ch1_cab_tuning_settings, G_N_ELEMENTS(gnx3k_ch1_cab_tuning_settings)},
+};
+
+static EffectGroup gnx3k_ch2_cab_tuning_group[] = {
+ {-1, NULL, gnx3k_ch2_cab_tuning_settings, G_N_ELEMENTS(gnx3k_ch2_cab_tuning_settings)},
+};
+
+static EffectGroup gnx3k_ch1_amp_eq_group[] = {
+ {-1, NULL, gnx3k_ch1_amp_eq_settings, G_N_ELEMENTS(gnx3k_ch1_amp_eq_settings)},
+};
+
+static EffectGroup gnx3k_ch2_amp_eq_group[] = {
+ {-1, NULL, gnx3k_ch2_amp_eq_settings, G_N_ELEMENTS(gnx3k_ch2_amp_eq_settings)},
+};
+
+/* LIBRARY_TONE, LIBRARY_POSITION */
+static EffectGroup tone_lib_group[] = {
+ {TONE_LIB_OVERDRIVE, "Overdrive", NULL, -1},
+ {TONE_LIB_ROCK1, "Rock 1", NULL, -1},
+ {TONE_LIB_ROCK2, "Rock 2", NULL, -1},
+ {TONE_LIB_BLUES1, "Blues 1", NULL, -1},
+ {TONE_LIB_BLUES2, "Blues 2", NULL, -1},
+ {TONE_LIB_METAL1, "Metal 1", NULL, -1},
+ {TONE_LIB_METAL2, "Metal 2", NULL, -1},
+ {TONE_LIB_COUNTRY1, "Country 1", NULL, -1},
+ {TONE_LIB_COUNTRY2, "Country 2", NULL, -1},
+ {TONE_LIB_WARM_DRIVE, "Warm Drive", NULL, -1},
+ {TONE_LIB_CRUNCH, "Crunch", NULL, -1},
+ {TONE_LIB_TEXAS_TONE, "Texas Tone", NULL, -1},
+ {TONE_LIB_ROCKABILLY, "Rockabilly", NULL, -1},
+ {TONE_LIB_SOLO1, "Solo 1", NULL, -1},
+ {TONE_LIB_SOLO2, "Solo 2", NULL, -1},
+ {TONE_LIB_ROCKWAH, "Rock Wah", NULL, -1},
+ {TONE_LIB_CHUNKY, "Chunky", NULL, -1},
+ {TONE_LIB_SMOOTH, "Smooth", NULL, -1},
+ {TONE_LIB_HEAVY, "Heavy", NULL, -1},
+ {TONE_LIB_CLEAN1, "Clean 1", NULL, -1},
+ {TONE_LIB_CLEAN2, "Clean 2", NULL, -1},
+ {TONE_LIB_BRITISH1, "British 1", NULL, -1},
+ {TONE_LIB_BRITISH2, "British 2", NULL, -1},
+ {TONE_LIB_AMERICAN1, "American 1", NULL, -1},
+ {TONE_LIB_AMERICAN2, "American 2", NULL, -1},
+ {TONE_LIB_TUBE_DRIVE, "Tube Drive", NULL, -1},
+ {TONE_LIB_DISTORTION, "Distortion", NULL, -1},
+ {TONE_LIB_SCOOPED, "Scooped", NULL, -1},
+ {TONE_LIB_PUNCHY, "Punchy", NULL, -1},
+ {TONE_LIB_BRIGHT_CLEAN, "Bright Clean", NULL, -1},
+};
+
+/* LIBRARY_EFFECTS, LIBRARY_POSITION */
+static EffectGroup effects_lib_group[] = {
+ {EFFECTS_LIB_CHORUS, "Chorus", NULL, -1},
+ {EFFECTS_LIB_PHASER, "Phaser", NULL, -1},
+ {EFFECTS_LIB_FLANGER, "Flanger", NULL, -1},
+ {EFFECTS_LIB_PITCH, "Pitch", NULL, -1},
+ {EFFECTS_LIB_TREMOLO, "Tremolo", NULL, -1},
+ {EFFECTS_LIB_ROTARY, "Rotary", NULL, -1},
+ {EFFECTS_LIB_ENVELOPE, "Envelope Filter", NULL, -1},
+ {EFFECTS_LIB_DIGITAL, "Digital Delay", NULL, -1},
+ {EFFECTS_LIB_ANALOG, "Analog Delay", NULL, -1},
+ {EFFECTS_LIB_PONG, "Pong Delay", NULL, -1},
+ {EFFECTS_LIB_MOD, "Mod Delay", NULL, -1},
+ {EFFECTS_LIB_TAPE, "Tape Delay", NULL, -1},
+ {EFFECTS_LIB_HALL, "Hall Reverb", NULL, -1},
+ {EFFECTS_LIB_PLATE, "Plate Reverb", NULL, -1},
+ {EFFECTS_LIB_SPRING, "Spring Reverb", NULL, -1},
+ {EFFECTS_LIB_CHORUS_DIGITAL, "Chorus + Digital Delay", NULL, -1},
+ {EFFECTS_LIB_CHORUS_DELAY_REVERB, "Chorus + Delay + Reverb", NULL, -1},
+ {EFFECTS_LIB_FLANGER_ANALOG, "Flanger + Analog Delay", NULL, -1},
+ {EFFECTS_LIB_PHASER_TAPE, "Phaser + Tape Delay", NULL, -1},
+ {EFFECTS_LIB_PHASER_MOD, "Phaser + Mod Delay", NULL, -1},
+ {EFFECTS_LIB_PHASER_ROOM, "Phaser + Room Reverb", NULL, -1},
+ {EFFECTS_LIB_DIGITAL_HALL, "Digital Delay + Hall Reverb", NULL, -1},
+ {EFFECTS_LIB_ANALOG_SPRING, "Analog Delay + Spring Reverb", NULL, -1},
+ {EFFECTS_LIB_CHORUS_HALL, "Chorus + Hall Reverb", NULL, -1},
+ {EFFECTS_LIB_PONG_HALL, "Pong Delay + Hall Reverb", NULL, -1},
+ {EFFECTS_LIB_TAPE_SPRING, "Tape Delay + Spring Reverb", NULL, -1},
+ {EFFECTS_LIB_TREMOLO_TAPE, "Tremolo + Tape Delay", NULL, -1},
+ {EFFECTS_LIB_PITCH_DIGITAL, "Pitch + Digital Delay", NULL, -1},
+ {EFFECTS_LIB_MOD_PLATE, "Mod Delay + Plate Reverb", NULL, -1},
+ {EFFECTS_LIB_ROTARY_TAPE, "Rotary + Tape Delay", NULL, -1},
+};
+
+static EffectGroup pickup_group[] = {
+ {PICKUP_TYPE_HB_SC, "HB>SC", NULL, -1},
+ {PICKUP_TYPE_SC_HB, "SC>HB", NULL, -1},
+};
+
+static EffectGroup pre_post_group[] = {
+ {CHORUSFX_PRE, "PRE AMP", NULL, -1},
+ {CHORUSFX_POST, "POST AMP", NULL, -1},
+};
+
+static EffectGroup delay_mult_group[] = {
+ {DELAY_3_QUARTR, "3 Quarter", NULL, -1},
+ {DELAY_EIGHT, "Eighth", NULL, -1},
+ {DELAY_DOTEIGHT, "Dot Eighth", NULL, -1},
+ {DELAY_QUARTER, "Quarter", NULL, -1},
+ {DELAY_HALF, "Half", NULL, -1},
+};
+
+static Effect gnx3k_wah_effect[] = {
+ {NULL, WAH_ON_OFF, WAH_TYPE, WAH_POSITION, gnx3k_wah_group, G_N_ELEMENTS(gnx3k_wah_group)},
+};
+
+static Effect wah_effect[] = {
+ {NULL, WAH_ON_OFF, WAH_TYPE, WAH_POSITION, wah_group, G_N_ELEMENTS(wah_group)},
+};
+
+static Effect gnx3k_whammy_effect[] = {
+ {NULL, GNX3K_WHAM_ENABLE, GNX3K_WHAM_TYPE, GNX3K_WHAM_POSITION, gnx3k_whammy_group, G_N_ELEMENTS(gnx3k_whammy_group)},
+};
+
+static Effect gnx3k_preset_effect[] = {
+ {NULL, -1, -1, -1, gnx3k_preset_group, G_N_ELEMENTS(gnx3k_preset_group)},
+};
+
+static Effect rp250_comp_effect[] = {
+ {NULL, COMP_ON_OFF, COMP_TYPE, COMP_POSITION, rp250_comp_group, G_N_ELEMENTS(rp250_comp_group)},
+};
+
+static Effect rp355_comp_effect[] = {
+ {NULL, COMP_ON_OFF, COMP_TYPE, COMP_POSITION, rp355_comp_group, G_N_ELEMENTS(rp355_comp_group)},
+};
+
+static Effect gnx_comp_effect[] = {
+ {"Compressor", COMP_ON_OFF, -1, COMP_POSITION, gnx_comp_group, G_N_ELEMENTS(gnx_comp_group)},
+};
+
+static Effect rp500_comp_effect[] = {
+ {NULL, COMP_ON_OFF, COMP_TYPE, COMP_POSITION, rp500_comp_group, G_N_ELEMENTS(rp500_comp_group)},
+};
+
+static Effect rp155_dist_effect[] = {
+ {NULL, DIST_ON_OFF, DIST_TYPE, DIST_POSITION, rp155_dist_group, G_N_ELEMENTS(rp155_dist_group)},
+};
+
+static Effect rp250_dist_effect[] = {
+ {NULL, DIST_ON_OFF, DIST_TYPE, DIST_POSITION, rp250_dist_group, G_N_ELEMENTS(rp250_dist_group)},
+};
+
+static Effect rp355_dist_effect[] = {
+ {NULL, DIST_ON_OFF, DIST_TYPE, DIST_POSITION, rp355_dist_group, G_N_ELEMENTS(rp355_dist_group)},
+};
+
+static Effect rp500_dist_effect[] = {
+ {NULL, DIST_ON_OFF, DIST_TYPE, DIST_POSITION, rp500_dist_group, G_N_ELEMENTS(rp500_dist_group)},
+};
+
+static Effect rp1000_dist_effect[] = {
+ {NULL, DIST_ON_OFF, DIST_TYPE, DIST_POSITION, rp1000_dist_group, G_N_ELEMENTS(rp1000_dist_group)},
+};
+
+static Effect gnx4_dist_effect[] = {
+ {NULL, DIST_ON_OFF, DIST_TYPE, DIST_POSITION, gnx4_dist_group, G_N_ELEMENTS(gnx4_dist_group)},
+};
+
+static Effect gnx3k_dist_effect[] = {
+ {NULL, DIST_ON_OFF, DIST_TYPE, DIST_POSITION, gnx3k_dist_group, G_N_ELEMENTS(gnx3k_dist_group)},
+};
+
+static Effect gnx3k_noisegate_effect[] = {
+ {NULL, NOISEGATE_ON_OFF, NOISEGATE_TYPE, NOISEGATE_POSITION, gnx3k_noisegate_group, G_N_ELEMENTS(gnx3k_noisegate_group)},
+};
+
+static Effect noisegate_effect[] = {
+ {NULL, NOISEGATE_ON_OFF, NOISEGATE_TYPE, NOISEGATE_POSITION, noisegate_group, G_N_ELEMENTS(noisegate_group)},
+};
+
+static Effect gnx4_chorusfx_effect[] = {
+ {NULL, CHORUSFX_ON_OFF, CHORUSFX_TYPE, CHORUSFX_POSITION, gnx4_chorusfx_group, G_N_ELEMENTS(gnx4_chorusfx_group)},
+};
+
+static Effect gnx3k_chorusfx_effect[] = {
+ {NULL, CHORUSFX_ON_OFF, CHORUSFX_TYPE, CHORUSFX_POSITION, gnx3k_chorusfx_group, G_N_ELEMENTS(gnx3k_chorusfx_group)},
+};
+
+static Effect rp155_chorusfx_effect[] = {
+ {NULL, CHORUSFX_ON_OFF, CHORUSFX_TYPE, CHORUSFX_POSITION, rp155_chorusfx_group, G_N_ELEMENTS(rp155_chorusfx_group)},
+};
+
+static Effect rp250_chorusfx_effect[] = {
+ {NULL, CHORUSFX_ON_OFF, CHORUSFX_TYPE, CHORUSFX_POSITION, rp250_chorusfx_group, G_N_ELEMENTS(rp250_chorusfx_group)},
+};
+
+static Effect rp255_chorusfx_effect[] = {
+ {NULL, CHORUSFX_ON_OFF, CHORUSFX_TYPE, CHORUSFX_POSITION, rp255_chorusfx_group, G_N_ELEMENTS(rp255_chorusfx_group)},
+};
+
+static Effect rp355_chorusfx_effect[] = {
+ {"Position",-1, CHORUSFX_PRE_POST,CHORUSFX_POSITION, pre_post_group,G_N_ELEMENTS(pre_post_group)},
+ {NULL, CHORUSFX_ON_OFF,CHORUSFX_TYPE, CHORUSFX_POSITION, rp355_chorusfx_group, G_N_ELEMENTS(rp355_chorusfx_group)},
+};
+
+static Effect rp500_chorusfx_effect[] = {
+ {NULL, CHORUSFX_ON_OFF, CHORUSFX_TYPE, CHORUSFX_POSITION, rp500_chorusfx_group, G_N_ELEMENTS(rp500_chorusfx_group)},
+};
+
+static Effect rp1000_chorusfx_effect[] = {
+ {NULL, CHORUSFX_ON_OFF, CHORUSFX_TYPE, CHORUSFX_POSITION, rp1000_chorusfx_group, G_N_ELEMENTS(rp1000_chorusfx_group)},
+ {"Position",-1, CHORUSFX_PRE_POST,CHORUSFX_POSITION, pre_post_group,G_N_ELEMENTS(pre_post_group)},
+};
+
+static Effect gnx3k_delay_effect[] = {
+ {NULL, DELAY_ON_OFF, DELAY_TYPE, DELAY_POSITION, gnx3k_delay_group, G_N_ELEMENTS(gnx3k_delay_group)},
+};
+
+static Effect rp250_delay_effect[] = {
+ {NULL, DELAY_ON_OFF, DELAY_TYPE, DELAY_POSITION, rp250_delay_group, G_N_ELEMENTS(rp250_delay_group)},
+};
+
+static Effect rp355_delay_effect[] = {
+ {NULL, DELAY_ON_OFF, DELAY_TYPE, DELAY_POSITION, rp355_delay_group, G_N_ELEMENTS(rp355_delay_group)},
+};
+
+static Effect rp500_delay_effect[] = {
+ {NULL, DELAY_ON_OFF, DELAY_TYPE, DELAY_POSITION, rp500_delay_group, G_N_ELEMENTS(rp500_delay_group)},
+};
+
+static Effect rp1000_delay_effect[] = {
+ {NULL, DELAY_ON_OFF, DELAY_TYPE, DELAY_POSITION, rp1000_delay_group, G_N_ELEMENTS(rp1000_delay_group)},
+ {NULL, -1, DELAY_MULTIPLIER, DELAY_POSITION, delay_mult_group, G_N_ELEMENTS(delay_mult_group)},
+};
+
+static Effect gnx3k_reverb_effect[] = {
+ {NULL, REVERB_ON_OFF, REVERB_TYPE, REVERB_POSITION, gnx3k_reverb_group, G_N_ELEMENTS(gnx3k_reverb_group)},
+};
+
+static Effect reverb_effect[] = {
+ {NULL, REVERB_ON_OFF, REVERB_TYPE, REVERB_POSITION, reverb_group, G_N_ELEMENTS(reverb_group)},
+};
+
+static Effect rp155_amp_effect[] = {
+ {NULL, AMP_ON_OFF, AMP_TYPE, AMP_POSITION, rp155_amp_group, G_N_ELEMENTS(rp155_amp_group)},
+ {"Cabinet", -1, AMP_CAB_TYPE, AMP_CAB_POSITION, rp155_amp_cab_group, G_N_ELEMENTS(rp155_amp_cab_group)},
+};
+
+static Effect rp250_amp_effect[] = {
+ {NULL, AMP_ON_OFF, AMP_TYPE, AMP_POSITION, rp250_amp_group, G_N_ELEMENTS(rp250_amp_group)},
+ {"Cabinet", -1, AMP_CAB_TYPE, AMP_CAB_POSITION, rp250_amp_cab_group, G_N_ELEMENTS(rp250_amp_cab_group)},
+};
+
+/* same cabs as rp250, but 3 new amp models */
+static Effect rp255_amp_effect[] = {
+ {NULL, AMP_ON_OFF, AMP_TYPE, AMP_POSITION, rp255_amp_group, G_N_ELEMENTS(rp255_amp_group)},
+ {"Cabinet", -1, AMP_CAB_TYPE, AMP_CAB_POSITION, rp250_amp_cab_group, G_N_ELEMENTS(rp250_amp_cab_group)},
+};
+
+static Effect rp355_select_amp_effect[] = {
+ {"Select Amp", -1, AMP_SELECT, AMP_SELECT_POSITION, rp355_amp_select_group, G_N_ELEMENTS(rp355_amp_select_group)},
+};
+
+static Effect rp355_amp_effect_A[] = {
+ {NULL, AMP_ON_OFF, AMP_TYPE, AMP_POSITION, rp355_amp_group_A, G_N_ELEMENTS(rp355_amp_group_A)},
+ {"Cabinet", -1, AMP_CAB_TYPE, AMP_CAB_POSITION, rp355_amp_cab_group, G_N_ELEMENTS(rp355_amp_cab_group)},
+};
+
+static Effect rp355_amp_effect_B[] = {
+ {NULL, AMP_ON_OFF, AMP_TYPE, CH2_AMP_POSITION, rp355_amp_group_B, G_N_ELEMENTS(rp355_amp_group_B)},
+ {"Cabinet", -1, AMP_CAB_TYPE, CH2_AMP_CAB_POSITION, rp355_amp_cab_group, G_N_ELEMENTS(rp355_amp_cab_group)},
+};
+
+static Effect rp500_amp_effect[] = {
+ {NULL, AMP_ON_OFF, AMP_TYPE, AMP_POSITION, rp500_amp_group, G_N_ELEMENTS(rp500_amp_group)},
+ {"Cabinet", -1, AMP_CAB_TYPE, AMP_CAB_POSITION, rp500_amp_cab_group, G_N_ELEMENTS(rp500_amp_cab_group)},
+};
+
+static Effect rp1000_amp_effect[] = {
+ {"Amp Loop", AMP_LOOP_ON_OFF, -1, AMP_LOOP_POSITION, NULL, -1},
+ {"Amp/Cab Bypass", AMP_BYPASS_ON_OFF, -1, AMP_BYPASS_POSITION, NULL, -1},
+ {NULL, -1, AMP_TYPE, AMP_POSITION, rp1000_amp_group, G_N_ELEMENTS(rp1000_amp_group)},
+ {NULL, -1, AMP_CAB_TYPE, AMP_CAB_POSITION, rp1000_amp_cab_group, G_N_ELEMENTS(rp1000_amp_cab_group)},
+};
+
+static Effect gnx3k_channel_1_effect[] = {
+ {"EQ Enable", AMP_EQ_ON_OFF, AMP_TYPE, AMP_POSITION, gnx3k_amp_group, G_N_ELEMENTS(gnx3k_amp_group)},
+ {NULL, -1, AMP_CAB_TYPE, AMP_CAB_POSITION, gnx3k_amp_cab_group, G_N_ELEMENTS(gnx3k_amp_cab_group)},
+ {NULL, -1, -1, -1, gnx3k_ch1_cab_tuning_group, G_N_ELEMENTS(gnx3k_ch1_cab_tuning_group)},
+ {NULL, -1, -1, -1, gnx3k_ch1_amp_eq_group, G_N_ELEMENTS(gnx3k_ch1_amp_eq_group)},
+};
+
+static Effect gnx3k_channel_2_effect[] = {
+ {"EQ Enable", AMP_EQ_ON_OFF, AMP_TYPE, CH2_AMP_POSITION, gnx3k_amp_group, G_N_ELEMENTS(gnx3k_amp_group)},
+ {NULL, -1, AMP_CAB_TYPE, CH2_AMP_CAB_POSITION, gnx3k_amp_cab_group, G_N_ELEMENTS(gnx3k_amp_cab_group)},
+ {NULL, -1, -1, -1, gnx3k_ch2_cab_tuning_group, G_N_ELEMENTS(gnx3k_ch2_cab_tuning_group)},
+ {NULL, -1, -1, -1, gnx3k_ch2_amp_eq_group, G_N_ELEMENTS(gnx3k_ch2_amp_eq_group)},
+};
+
+static Effect rp250_eq_effect[] = {
+ {NULL, EQ_ON_OFF, EQ_TYPE, EQ_POSITION, rp250_eq_group, G_N_ELEMENTS(rp250_eq_group)},
+};
+
+static Effect rp355_eq_effect_A[] = {
+ {NULL, EQ_ON_OFF, EQ_TYPE, EQ_POSITION, rp355_eq_group_A, G_N_ELEMENTS(rp355_eq_group_A)},
+};
+
+static Effect rp355_eq_effect_B[] = {
+ {NULL, EQ_ON_OFF, EQ_TYPE, EQ_POSITION_B, rp355_eq_group_B, G_N_ELEMENTS(rp355_eq_group_B)},
+};
+
+static Effect rp500_eq_effect[] = {
+ {"Enable Equalizer", EQ_ON_OFF, -1, EQ_POSITION, rp500_eq_group, G_N_ELEMENTS(rp500_eq_group)},
+};
+
+static Effect pickup_misc_effect[] = {
+ {NULL, PICKUP_ON_OFF, PICKUP_TYPE, PICKUP_POSITION, pickup_group, G_N_ELEMENTS(pickup_group)},
+ {NULL, -1, -1, -1, misc_group, G_N_ELEMENTS(misc_group)},
+};
+
+static Effect pickup_effect[] = {
+ {NULL, PICKUP_ON_OFF, PICKUP_TYPE, PICKUP_POSITION, pickup_group, G_N_ELEMENTS(pickup_group)},
+};
+
+static Effect gnx3k_amp_channel_effect[] = {
+ {NULL, -1, -1, -1, gnx3k_amp_channel_group, G_N_ELEMENTS(gnx3k_amp_channel_group)},
+};
+
+/* in signal chain order */
+static EffectList rp155_effects[] = {
+ {"Pickup", pickup_misc_effect, G_N_ELEMENTS(pickup_misc_effect)},
+ {"Wah", wah_effect, G_N_ELEMENTS(wah_effect)},
+ {"Compressor", rp250_comp_effect, G_N_ELEMENTS(rp250_comp_effect)},
+ {"Distortion", rp155_dist_effect, G_N_ELEMENTS(rp155_dist_effect)},
+ {"Amplifier", rp155_amp_effect, G_N_ELEMENTS(rp155_amp_effect)},
+ {"Equalizer", rp250_eq_effect, G_N_ELEMENTS(rp250_eq_effect)},
+ {"Noisegate", noisegate_effect, G_N_ELEMENTS(noisegate_effect)},
+ {"Chorus/FX", rp155_chorusfx_effect, G_N_ELEMENTS(rp155_chorusfx_effect)},
+ {"Delay", rp250_delay_effect, G_N_ELEMENTS(rp250_delay_effect)},
+ {"Reverb", reverb_effect, G_N_ELEMENTS(reverb_effect)},
+};
+
+static EffectList rp250_effects[] = {
+ {"Wah", wah_effect, G_N_ELEMENTS(wah_effect)},
+ {"Amplifier", rp250_amp_effect, G_N_ELEMENTS(rp250_amp_effect)},
+ {"Equalizer", rp250_eq_effect, G_N_ELEMENTS(rp250_eq_effect)},
+ {"Compressor", rp250_comp_effect, G_N_ELEMENTS(rp250_comp_effect)},
+ {"Distortion", rp250_dist_effect, G_N_ELEMENTS(rp250_dist_effect)},
+ {"Noisegate", noisegate_effect, G_N_ELEMENTS(noisegate_effect)},
+ {"Chorus/FX", rp250_chorusfx_effect, G_N_ELEMENTS(rp250_chorusfx_effect)},
+ {"Delay", rp250_delay_effect, G_N_ELEMENTS(rp250_delay_effect)},
+ {"Reverb", reverb_effect, G_N_ELEMENTS(reverb_effect)},
+ {"Pickup/Misc", pickup_misc_effect, G_N_ELEMENTS(pickup_misc_effect)},
+};
+
+/* Almost like rp250, except for Amplifier and Chorus/FX */
+static EffectList rp255_effects[] = {
+ {"Wah", wah_effect, G_N_ELEMENTS(wah_effect)},
+ {"Amplifier", rp255_amp_effect, G_N_ELEMENTS(rp255_amp_effect)},
+ {"Equalizer", rp250_eq_effect, G_N_ELEMENTS(rp250_eq_effect)},
+ {"Compressor", rp250_comp_effect, G_N_ELEMENTS(rp250_comp_effect)},
+ {"Distortion", rp250_dist_effect, G_N_ELEMENTS(rp250_dist_effect)},
+ {"Noisegate", noisegate_effect, G_N_ELEMENTS(noisegate_effect)},
+ {"Chorus/FX", rp255_chorusfx_effect, G_N_ELEMENTS(rp255_chorusfx_effect)},
+ {"Delay", rp250_delay_effect, G_N_ELEMENTS(rp250_delay_effect)},
+ {"Reverb", reverb_effect, G_N_ELEMENTS(reverb_effect)},
+ {"Pickup/Misc", pickup_misc_effect, G_N_ELEMENTS(pickup_misc_effect)},
+};
+
+static EffectList rp355_effects[] = {
+ {"Pickup/Misc", pickup_misc_effect, G_N_ELEMENTS(pickup_misc_effect)},
+ {"Wah", wah_effect, G_N_ELEMENTS(wah_effect)},
+ {"Compressor", rp355_comp_effect, G_N_ELEMENTS(rp355_comp_effect)},
+ {"Distortion", rp355_dist_effect, G_N_ELEMENTS(rp355_dist_effect)},
+ {"Select Amp", rp355_select_amp_effect, G_N_ELEMENTS(rp355_select_amp_effect)},
+ {"Amplifier A", rp355_amp_effect_A, G_N_ELEMENTS(rp355_amp_effect_A)},
+ {"Equalizer A", rp355_eq_effect_A, G_N_ELEMENTS(rp355_eq_effect_A)},
+ {"Amplifier B", rp355_amp_effect_B, G_N_ELEMENTS(rp355_amp_effect_B)},
+ {"Equalizer B", rp355_eq_effect_B, G_N_ELEMENTS(rp355_eq_effect_B)},
+ {"Noisegate", noisegate_effect, G_N_ELEMENTS(noisegate_effect)},
+ {"Chorus/FX", rp355_chorusfx_effect, G_N_ELEMENTS(rp355_chorusfx_effect)},
+ {"Delay", rp355_delay_effect, G_N_ELEMENTS(rp355_delay_effect)},
+ {"Reverb", reverb_effect, G_N_ELEMENTS(reverb_effect)},
+};
+
+static EffectList rp500_effects[] = {
+ {"Wah", wah_effect, G_N_ELEMENTS(wah_effect)},
+ {"Amplifier", rp500_amp_effect, G_N_ELEMENTS(rp500_amp_effect)},
+ {"Equalizer", rp500_eq_effect, G_N_ELEMENTS(rp500_eq_effect)},
+ {"Compressor", rp500_comp_effect, G_N_ELEMENTS(rp500_comp_effect)},
+ {"Distortion", rp500_dist_effect, G_N_ELEMENTS(rp500_dist_effect)},
+ {"Noisegate", noisegate_effect, G_N_ELEMENTS(noisegate_effect)},
+ {"Chorus/FX", rp500_chorusfx_effect, G_N_ELEMENTS(rp500_chorusfx_effect)},
+ {"Delay", rp500_delay_effect, G_N_ELEMENTS(rp500_delay_effect)},
+ {"Reverb", reverb_effect, G_N_ELEMENTS(reverb_effect)},
+};
+
+static EffectList rp1000_effects[] = {
+ {"Wah", wah_effect, G_N_ELEMENTS(wah_effect)},
+ {"Amplifier", rp1000_amp_effect, G_N_ELEMENTS(rp1000_amp_effect)},
+ {"Equalizer", rp500_eq_effect, G_N_ELEMENTS(rp500_eq_effect)},
+ {"Compressor", rp500_comp_effect, G_N_ELEMENTS(rp500_comp_effect)},
+ {"Distortion", rp1000_dist_effect, G_N_ELEMENTS(rp1000_dist_effect)},
+ {"Noisegate", noisegate_effect, G_N_ELEMENTS(noisegate_effect)},
+ {"Chorus/FX", rp1000_chorusfx_effect, G_N_ELEMENTS(rp1000_chorusfx_effect)},
+ {"Delay", rp1000_delay_effect, G_N_ELEMENTS(rp1000_delay_effect)},
+ {"Reverb", reverb_effect, G_N_ELEMENTS(reverb_effect)},
+};
+
+static EffectList gnx4_effects[] = {
+ {"Pickup", pickup_effect, G_N_ELEMENTS(pickup_effect)},
+ {"Wah", gnx3k_wah_effect, G_N_ELEMENTS(gnx3k_wah_effect)},
+ {"Compressor", gnx_comp_effect, G_N_ELEMENTS(gnx_comp_effect)},
+ {"Whammy/IPS", gnx3k_whammy_effect, G_N_ELEMENTS(gnx3k_whammy_effect)},
+ {"Stompbox", gnx4_dist_effect, G_N_ELEMENTS(gnx4_dist_effect)},
+ {"Noisegate", gnx3k_noisegate_effect, G_N_ELEMENTS(gnx3k_noisegate_effect)},
+ {"Chorus/Mod", gnx4_chorusfx_effect, G_N_ELEMENTS(gnx4_chorusfx_effect)},
+ {"Delay", gnx3k_delay_effect, G_N_ELEMENTS(gnx3k_delay_effect)},
+ {"Reverb", gnx3k_reverb_effect, G_N_ELEMENTS(gnx3k_reverb_effect)},
+};
+
+static EffectList gnx3000_effects[] = {
+ {"Pickup", pickup_effect, G_N_ELEMENTS(pickup_effect)},
+ {"Wah", gnx3k_wah_effect, G_N_ELEMENTS(gnx3k_wah_effect)},
+ {"Whammy/IPS", gnx3k_whammy_effect, G_N_ELEMENTS(gnx3k_whammy_effect)},
+ {"Preset Level", gnx3k_preset_effect, G_N_ELEMENTS(gnx3k_preset_effect)},
+ {"Compressor", gnx_comp_effect, G_N_ELEMENTS(gnx_comp_effect)},
+ {"Stompbox", gnx3k_dist_effect, G_N_ELEMENTS(gnx3k_dist_effect)},
+ {"Noisegate", gnx3k_noisegate_effect, G_N_ELEMENTS(gnx3k_noisegate_effect)},
+ {"Chorus/Mod", gnx3k_chorusfx_effect, G_N_ELEMENTS(gnx3k_chorusfx_effect)},
+ {"Delay", gnx3k_delay_effect, G_N_ELEMENTS(gnx3k_delay_effect)},
+ {"Reverb", gnx3k_reverb_effect, G_N_ELEMENTS(gnx3k_reverb_effect)},
+};
+
+static EffectList gnx3000_genetx[] = {
+ {"Channel 1", gnx3k_channel_1_effect, G_N_ELEMENTS(gnx3k_channel_1_effect)},
+ {"Channel 2", gnx3k_channel_2_effect, G_N_ELEMENTS(gnx3k_channel_2_effect)},
+ {"Amp Channel", gnx3k_amp_channel_effect, G_N_ELEMENTS(gnx3k_amp_channel_effect)},
+};
+
+static Banks rp_banks[] = {
+ {"User Presets", PRESETS_USER},
+ {"System Presets", PRESETS_SYSTEM},
+};
+
+static Banks gnx4_banks[] = {
+ {"Factory", PRESETS_SYSTEM},
+ {"User Presets", PRESETS_USER},
+ {"Flash Card", PRESETS_MEDIA_CARD},
+};
+
+static Banks gnx3k_banks[] = {
+ {"User Presets", PRESETS_USER},
+ {"Factory 1", PRESETS_SYSTEM},
+ {"Factory 2", PRESETS_FACTORY2},
+};
+
+static EffectPage rp155_pages[] = {
+ {"Effects", rp155_effects, G_N_ELEMENTS(rp155_effects), 2},
+};
+
+static EffectPage rp250_pages[] = {
+ {"Effects", rp250_effects, G_N_ELEMENTS(rp250_effects), 2},
+};
+
+static EffectPage rp255_pages[] = {
+ {"Effects", rp255_effects, G_N_ELEMENTS(rp255_effects), 2},
+};
+
+static EffectPage rp355_pages[] = {
+ {"Effects", rp355_effects, G_N_ELEMENTS(rp355_effects), 2},
+};
+
+static EffectPage rp500_pages[] = {
+ {"Effects", rp500_effects, G_N_ELEMENTS(rp500_effects), 2},
+};
+
+static EffectPage rp1000_pages[] = {
+ {"Effects", rp1000_effects, G_N_ELEMENTS(rp1000_effects), 2},
+};
+
+static EffectPage gnx4_pages[] = {
+ {"Effects", gnx4_effects, G_N_ELEMENTS(gnx4_effects), 2},
+};
+
+static EffectPage gnx3000_pages[] = {
+ {"Effects", gnx3000_effects, G_N_ELEMENTS(gnx3000_effects), 2},
+ {"Amp/GeNetX", gnx3000_genetx, G_N_ELEMENTS(gnx3000_genetx), 1},
+};
+
+static Device rp155 = {
+ .name = "DigiTech RP155",
+ .family_id = 0x5E,
+ .product_id = 0x07,
+ .pages = rp155_pages,
+ .n_pages = G_N_ELEMENTS(rp155_pages),
+ .banks = rp_banks,
+ .n_banks = G_N_ELEMENTS(rp_banks),
+};
+
+static Device rp250 = {
+ .name = "DigiTech RP250",
+ .family_id = 0x5E,
+ .product_id = 0x02,
+ .pages = rp250_pages,
+ .n_pages = G_N_ELEMENTS(rp250_pages),
+ .banks = rp_banks,
+ .n_banks = G_N_ELEMENTS(rp_banks),
+};
+
+static Device rp255 = {
+ .name = "DigiTech RP255",
+ .family_id = 0x5E,
+ .product_id = 0x08,
+ .pages = rp255_pages,
+ .n_pages = G_N_ELEMENTS(rp255_pages),
+ .banks = rp_banks,
+ .n_banks = G_N_ELEMENTS(rp_banks),
+};
+
+static Device rp355 = {
+ .name = "DigiTech RP355",
+ .family_id = 0x5E,
+ .product_id = 0x09,
+ .pages = rp355_pages,
+ .n_pages = G_N_ELEMENTS(rp355_pages),
+ .banks = rp_banks,
+ .n_banks = G_N_ELEMENTS(rp_banks),
+};
+
+static Device rp500 = {
+ .name = "DigiTech RP500",
+ .family_id = 0x5E,
+ .product_id = 0x05,
+ .pages = rp500_pages,
+ .n_pages = G_N_ELEMENTS(rp500_pages),
+ .banks = rp_banks,
+ .n_banks = G_N_ELEMENTS(rp_banks),
+};
+
+static Device rp1000 = {
+ .name = "DigiTech RP1000",
+ .family_id = 0x05E,
+ .product_id = 0x06,
+ .pages = rp1000_pages,
+ .n_pages = G_N_ELEMENTS(rp1000_pages),
+ .banks = rp_banks,
+ .n_banks = G_N_ELEMENTS(rp_banks),
+};
+
+static Device gnx4 = {
+ .name = "DigiTech GNX4",
+ .family_id = 0x5C,
+ .product_id = 0x03,
+ .pages = gnx4_pages,
+ .n_pages = G_N_ELEMENTS(gnx4_pages),
+ .banks = gnx4_banks,
+ .n_banks = G_N_ELEMENTS(gnx4_banks),
+};
+
+static Device gnx3000 = {
+ .name = "DigiTech GNX3000",
+ .family_id = 0x5C,
+ .product_id = 0x04,
+ .pages = gnx3000_pages,
+ .n_pages = G_N_ELEMENTS(gnx3000_pages),
+ .banks = gnx3k_banks,
+ .n_banks = G_N_ELEMENTS(gnx3k_banks),
+};
+
+Device* supported_devices[] = {
+ &rp155,
+ &rp250,
+ &rp255,
+ &rp355,
+ &rp500,
+ &rp1000,
+ &gnx4,
+ &gnx3000,
+};
+
+int n_supported_devices = G_N_ELEMENTS(supported_devices);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+typedef struct {
+ gchar *label;
+ guint id;
+ guint position;
+ EffectValues *values;
+} Modifier;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+static Modifier modifiers[] = {
+ {"None", 0, 0, NULL},
+ {"Pickup Enable", PICKUP_ON_OFF, PICKUP_POSITION, &values_on_off},
+ {"Pickup Type", PICKUP_TYPE, PICKUP_POSITION, &values_pickup_type},
+ {"Compressor Enable", COMP_ON_OFF, COMP_POSITION, &values_on_off},
+ {"Compressor Sustain", COMP_SUSTAIN, COMP_POSITION, &values_0_to_99},
+ {"Compressor Tone", COMP_TONE, COMP_POSITION, &values_0_to_99},
+ {"Compressor Level", COMP_LEVEL, COMP_POSITION, &values_0_to_99},
+ {"Compressor Attack", COMP_ATTACK, COMP_POSITION, &values_0_to_99},
+ {"Dist Enable", DIST_ON_OFF, DIST_POSITION, &values_on_off},
+ {"Dist Drive", DIST_SCREAMER_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Dist Tone", DIST_SCREAMER_TONE, DIST_POSITION, &values_0_to_99},
+ {"Dist Level", DIST_SCREAMER_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist Overdrive", DIST_808_OVERDRIVE, DIST_POSITION, &values_0_to_99},
+ {"Dist Tone", DIST_808_TONE, DIST_POSITION, &values_0_to_99},
+ {"Dist Level", DIST_808_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist Drive", DIST_GUYOD_DRIVE, DIST_POSITION, &values_0_to_99},
+ {"Dist Level", DIST_GUYOD_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist Gain", DIST_DOD250_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Dist Level", DIST_DOD250_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist Distortion", DIST_RODENT_DIST, DIST_POSITION, &values_0_to_99},
+ {"Dist Filter", DIST_RODENT_FILTER, DIST_POSITION, &values_0_to_99},
+ {"Dist Volume", DIST_RODENT_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist Distortion", DIST_MX_DIST, DIST_POSITION, &values_0_to_99},
+ {"Dist Output", DIST_MX_OUTPUT, DIST_POSITION, &values_0_to_99},
+ {"Dist Distortion", DIST_DS_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Dist Tone", DIST_DS_TONE, DIST_POSITION, &values_0_to_99},
+ {"Dist Level", DIST_DS_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist Gain", DIST_GRUNGE_GRUNGE, DIST_POSITION, &values_0_to_99},
+ {"Dist Face", DIST_GRUNGE_FACE, DIST_POSITION, &values_0_to_99},
+ {"Dist Loud", DIST_GRUNGE_LOUD, DIST_POSITION, &values_0_to_99},
+ {"Dist Butt", DIST_GRUNGE_BUTT, DIST_POSITION, &values_0_to_99},
+ {"Dist Gain", DIST_ZONE_GAIN, DIST_POSITION, &values_0_to_99},
+ {"Dist Mid Level", DIST_ZONE_MID_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist Level", DIST_ZONE_LEVEL, DIST_POSITION, &values_0_to_99},
+ {"Dist Low", DIST_ZONE_LOW, DIST_POSITION, &values_0_to_99},
+ {"Dist Mid Freq", DIST_ZONE_MID_FREQ, DIST_POSITION, &values_0_to_99},
+ {"Dist High", DIST_ZONE_HIGH, DIST_POSITION, &values_0_to_99},
+ {"Dist Low", DIST_DEATH_LOW, DIST_POSITION, &values_0_to_99},
+ {"Dist Mid", DIST_DEATH_MID, DIST_POSITION, &values_0_to_99},
+ {"Dist Level", DIST_DEATH_LVL, DIST_POSITION, &values_0_to_99},
+ {"Dist High", DIST_DEATH_HIGH, DIST_POSITION, &values_0_to_99},
+ {"Dist Gunk", DIST_GONK_GONK, DIST_POSITION, &values_0_to_99},
+ {"Dist Smear", DIST_GONK_SMEAR, DIST_POSITION, &values_0_to_99},
+ {"Dist Suck", DIST_GONK_SUCK, DIST_POSITION, &values_0_to_99},
+ {"Dist Heave", DIST_GONK_HEAVE, DIST_POSITION, &values_0_to_99},
+ {"Dist Fuzz", DIST_FUZZY_FUZZ, DIST_POSITION, &values_0_to_99},
+ {"Dist Volume", DIST_FUZZY_VOLUME, DIST_POSITION, &values_0_to_99},
+ {"Dist Sustain", DIST_MP_SUSTAIN, DIST_POSITION, &values_0_to_99},
+ {"Dist Tone", DIST_MP_TONE, DIST_POSITION, &values_0_to_99},
+ {"Dist Volume", DIST_MP_VOLUME, DIST_POSITION, &values_0_to_99},
+ {"Amp Channel Enable", AMP_ON_OFF, AMP_POSITION, &values_on_off},
+ {"Amp Gain", AMP_GAIN, AMP_POSITION, &values_0_to_99},
+ {"Amp Level", AMP_LEVEL, AMP_POSITION, &values_0_to_99},
+ {"EQ Enable", EQ_ON_OFF, EQ_POSITION, &values_on_off},
+ {"EQ Bass", EQ_BASS, EQ_POSITION, &values_eq_db},
+ {"EQ Mid", EQ_MID, EQ_POSITION, &values_eq_db},
+ {"EQ Treb", EQ_TREBLE, EQ_POSITION, &values_eq_db},
+ {"Gate Enable", NOISEGATE_ON_OFF, NOISEGATE_POSITION, &values_on_off},
+ {"Gate Pluck Sens", NOISEGATE_SWELL_SENS, NOISEGATE_POSITION, &values_0_to_99},
+ {"Gate Threshold", NOISEGATE_GATE_TRESHOLD, NOISEGATE_POSITION, &values_0_to_99},
+ {"Gate Attack", NOISEGATE_ATTACK, NOISEGATE_POSITION, &values_0_to_99},
+ {"Gate Release", NOISEGATE_RELEASE, NOISEGATE_POSITION, &values_0_to_99},
+ {"Gate Attenuation", NOISEGATE_ATTN, NOISEGATE_POSITION, &values_0_to_99},
+ {"Chorus/FX Enable", CHORUSFX_ON_OFF, CHORUSFX_POSITION, &values_on_off},
+ {"Phaser Speed", PHASER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Phaser Depth", PHASER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Phaser Regen", PHASER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Phaser Waveform", PHASER_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Phaser Level", PHASER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Chorus Speed", CHORUS_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Chorus Depth", CHORUS_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Chorus Level", CHORUS_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Chorus Waveform", CHORUS_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Flanger Speed", FLANGER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Flanger Depth", FLANGER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Flanger Regen", FLANGER_REGEN, CHORUSFX_POSITION, &values_0_to_99},
+ {"Flanger Waveform", FLANGER_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Flanger Level", FLANGER_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Flanger Width", MXR_FLANGER_WIDTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Flanger Manual", MXR_FLANGER_MANUAL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Vibrato Speed", VIBRATO_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Vibrato Depth", VIBRATO_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Rotary Speed", ROTARY_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Rotary Intensity", ROTARY_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Rotary Doppler", ROTARY_DOPPLER, CHORUSFX_POSITION, &values_0_to_99},
+ {"Rotary Crossover", ROTARY_CROSSOVER, CHORUSFX_POSITION, &values_0_to_99},
+ {"VibroPan Speed", VIBROPAN_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"VibroPan Depth", VIBROPAN_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"VibroPan VibratoPan", VIBROPAN_VIBRA, CHORUSFX_POSITION, &values_0_to_99},
+ {"VibroPan Waveform", VIBROPAN_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Tremolo Speed", TREMOLO_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Tremolo Depth", TREMOLO_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Tremolo Waveform", TREMOLO_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Panner Speed", PANNER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Panner Depth", PANNER_DEPTH, CHORUSFX_POSITION, &values_0_to_99},
+ {"Panner Waveform", PANNER_WAVE, CHORUSFX_POSITION, &values_waveform},
+ {"Envelope Sens.", ENVELOPE_SENSITIVITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Envelope Range", ENVELOPE_RANGE, CHORUSFX_POSITION, &values_0_to_99},
+ {"AutoYa Speed", AUTOYA_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"AutoYa Intensity", AUTOYA_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"AutoYa Range", AUTOYA_RANGE, CHORUSFX_POSITION, &values_0_to_49},
+ {"YaYa Pedal", YAYA_PEDAL, CHORUSFX_POSITION, &values_0_to_99},
+ {"YaYa Intensity", YAYA_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"YaYa Range", YAYA_RANGE, CHORUSFX_POSITION, &values_0_to_49},
+ {"Step Filter Speed", STEP_FILTER_SPEED, CHORUSFX_POSITION, &values_0_to_99},
+ {"Step Filter Intensity", STEP_FILTER_INTENSITY, CHORUSFX_POSITION, &values_0_to_99},
+ {"Whammy Amount", WHAMMY_AMOUNT, CHORUSFX_POSITION, &values_whammy_amount},
+ {"Whammy Pedal", WHAMMY_PEDAL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Whammy Mix", WHAMMY_MIX, CHORUSFX_POSITION, &values_0_to_99},
+ {"Pitch Shift Amount", PITCH_AMOUNT, CHORUSFX_POSITION, &values_m24_to_24},
+ {"Pitch Shift Mix", PITCH_MIX, CHORUSFX_POSITION, &values_0_to_99},
+ {"Detune Amount", DETUNE_AMOUNT, CHORUSFX_POSITION, &values_m24_to_24},
+ {"Detune Level", DETUNE_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"IPS Amount", IPS_SHIFT_AMOUNT, CHORUSFX_POSITION, &values_ips_shift},
+ {"IPS Key", IPS_KEY, CHORUSFX_POSITION, &values_ips_key},
+ {"IPS Scale", IPS_SCALE, CHORUSFX_POSITION, &values_ips_scale},
+ {"IPS Level", IPS_LEVEL, CHORUSFX_POSITION, &values_0_to_99},
+ {"Delay Enable", DELAY_ON_OFF, DELAY_POSITION, &values_on_off},
+ {"Delay Time", DELAY_TIME, DELAY_POSITION, &values_delay_time},
+ {"Delay Repeats", DELAY_REPEATS, DELAY_POSITION, &values_delay_repeats},
+ {"Delay Level", DELAY_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Delay Duck Thresh", DELAY_DUCK_THRESH, DELAY_POSITION, &values_0_to_99},
+ {"Delay Duck Level", DELAY_DUCK_LEVEL, DELAY_POSITION, &values_0_to_99},
+ {"Delay Mod Depth", DELAY_DEPTH, DELAY_POSITION, &values_0_to_99},
+ {"Delay Tape Wow", DELAY_TAPE_WOW, DELAY_POSITION, &values_0_to_99},
+ {"Delay Tape Flut", DELAY_TAPE_FLUTTER, DELAY_POSITION, &values_0_to_99},
+ {"Reverb Enable", REVERB_ON_OFF, REVERB_POSITION, &values_on_off},
+ {"Reverb Decay", REVERB_DECAY, REVERB_POSITION, &values_0_to_99},
+ {"Reverb Liveliness", REVERB_LIVELINESS, REVERB_POSITION, &values_0_to_99},
+ {"Reverb Level", REVERB_LEVEL, REVERB_POSITION, &values_0_to_99},
+ {"Reverb Predelay", REVERB_PREDELAY, REVERB_POSITION, &values_0_to_15},
+ {"Volume Pre FX", 2626, 13, &values_0_to_99},
+ {"Volume Post FX", 2626, 17, &values_0_to_99},
+};
+
+int n_modifiers = G_N_ELEMENTS(modifiers);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+/**
+ * \param id modifier ID
+ * \param position modifier position
+ *
+ * Gets modifier info.
+ *
+ * \return Modifier which must not be freed, or NULL if no matching Modifier has been found.
+*/
+static Modifier *get_modifier(guint id, guint position)
+{
+ gint x;
+
+ for (x=0; x<n_modifiers; x++)
+ if ((modifiers[x].id == id) && (modifiers[x].position == position))
+ return &(modifiers[x]);
+
+ return NULL;
+}
+
+/**
+ * \param values possible setting values
+ *
+ * Creates EffectSettings containing expression pedal min and max settings.
+ *
+ * \return EffectSettings which must be freed using effect_settings_free.
+ **/
+static EffectSettings *get_modifier_settings(EffectValues *values)
+{
+ if (values == NULL)
+ return NULL;
+
+ /** \todo reuse exsisting settings if values is the same */
+ EffectSettings *settings = g_slice_alloc0(2 * sizeof(EffectSettings));
+ settings[0].id = EXP_MIN;
+ settings[1].id = EXP_MAX;
+
+ settings[0].label = "Min";
+ settings[1].label = "Max";
+
+ settings[0].position = settings[1].position = EXP_POSITION;
+
+ settings[0].values = settings[1].values = values;
+
+ return settings;
+}
+
+/**
+ * \param settings settings to be freed
+ *
+ * Frees all memory used by EffectSettings.
+ **/
+static void effect_settings_free(EffectSettings *settings)
+{
+ g_slice_free1(2 * sizeof(EffectSettings), settings);
+}
+
+/**
+ * Retrieves modifier linkable gruop from device.
+ *
+ * \return ModifierGroup which must be freed using modifier_group_free.
+ **/
+ModifierGroup *modifier_linkable_list()
+{
+ guint group_id;
+ guint count;
+ guint i;
+
+ send_message(REQUEST_MODIFIER_LINKABLE_LIST, "\x00\x01", 2);
+
+ GString *data = get_message_by_id(RECEIVE_MODIFIER_LINKABLE_LIST);
+
+ unsigned char *str = (unsigned char*)data->str;
+
+ group_id = (str[8] << 8) | str[9];
+ count = (str[10] << 8) | str[11];
+
+ ModifierGroup *modifier_group = g_slice_new(ModifierGroup);
+
+ modifier_group->type = EXP_TYPE;
+ modifier_group->position = EXP_POSITION;
+
+ g_message("Group %d count %d", group_id, count);
+ EffectGroup *group = g_slice_alloc(count * sizeof(EffectGroup));
+
+ for (i=0; i<count; i++) {
+ guint id = (str[12 + (i*3)] << 8) | str[13 + (i*3)];
+ guint position = str[14 + (i*3)];
+
+ group[i].type = (position << 16) | id;
+
+ Modifier *modifier = get_modifier(id, position);
+ if (modifier) {
+ group[i].label = modifier->label;
+ group[i].settings = get_modifier_settings(modifier->values);
+ group[i].settings_amt = 2;
+ } else {
+ group[i].label = NULL;
+ group[i].settings = NULL;
+ }
+
+ if (group[i].settings == NULL)
+ group[i].settings_amt = 0;
+
+ g_message("ID: %d Position: %d Label: %s", id, position, modifier ? modifier->label : NULL);
+ }
+
+ modifier_group->group = group;
+ modifier_group->group_amt = count;
+
+ return modifier_group;
+}
+
+/**
+ * \param modifier_group group to be freed
+ *
+ * Frees all memory used by ModifierGroup.
+ **/
+void modifier_group_free(ModifierGroup *modifier_group)
+{
+ g_return_if_fail(modifier_group != NULL);
+
+ int x;
+ for (x=0; x<modifier_group->group_amt; x++) {
+ if (modifier_group->group[x].settings)
+ effect_settings_free(modifier_group->group[x].settings);
+ }
+ g_slice_free1(modifier_group->group_amt * sizeof(EffectGroup),
+ modifier_group->group);
+ g_slice_free(ModifierGroup, modifier_group);
+}
+
+/**
+ * \param values EffectValues to examine
+ * \param min return location for minimum value
+ * \param max return location for maximum value
+ * \param custom return location for custom flag
+ *
+ * Retrieves information about provided EffectValues, custom is set to TRUE if values type isn't VALUE_TYPE_PLAIN.
+ **/
+void get_values_info(EffectValues *values,
+ gdouble *min, gdouble *max, gboolean *custom)
+{
+ g_return_if_fail(values != NULL);
+
+ *min = values->min;
+ *custom = (values->type != VALUE_TYPE_PLAIN);
+
+ while ((values->type & VALUE_TYPE_EXTRA) && (values->extra != NULL))
+ values = values->extra;
+
+ *max = values->max;
+}
+
+/**
+ * \param device_id Device ID
+ * \param family_id Family ID
+ * \param product_id Product ID
+ * \param device Variable to hold device information
+ *
+ * Gets appropiate effect list basing on device, family and product IDs.
+ *
+ * \return TRUE if list and n_list were set, FALSE otherwise.
+ **/
+gboolean get_device_info(unsigned char device_id, unsigned char family_id,
+ unsigned char product_id,
+ Device **device)
+{
+ int x;
+ for (x = 0; x < G_N_ELEMENTS(supported_devices); x++) {
+ if (supported_devices[x]->product_id == product_id && supported_devices[x]->family_id == family_id) {
+ *device = supported_devices[x];
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
diff --git a/effects.h b/effects.h
new file mode 100644
index 0000000..40e95f7
--- /dev/null
+++ b/effects.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef GDIGI_EFFECTS_H
+#define GDIGI_EFFECTS_H
+
+#include <glib.h>
+
+enum {
+ VALUE_TYPE_PLAIN = 0, /**< value displayed directly */
+ VALUE_TYPE_SUFFIX = 1 << 0, /**< use suffix for displaying */
+ VALUE_TYPE_OFFSET = 1 << 1, /**< use value offset */
+ VALUE_TYPE_STEP = 1 << 2, /**< use value step different than 1 */
+ VALUE_TYPE_LABEL = 1 << 3, /**< use value labels (overrides any other option) */
+ VALUE_TYPE_EXTRA = 1 << 4, /**< use extra values */
+ VALUE_TYPE_DECIMAL= 1 << 5, /**< display decimal places */
+} ValueType;
+
+typedef struct _EffectValues {
+ gdouble min; /**< Minumum value */
+ gdouble max; /**< Maximum value */
+ gint type; /**< value type bitmask (ValueType) */
+
+ GStrv labels; /**< value labels */
+ gint offset; /**< value offset */
+ gdouble step; /**< value step */
+ gchar *suffix; /**< value suffix */
+
+ struct _EffectValues *extra;
+ /**< additional value range,
+ use it when there're different range types */
+ gint decimal; /**< amount of decimal places to display */
+} EffectValues;
+
+typedef struct {
+ gchar *label; /**< Parameter name */
+ guint id; /**< ID (to set parameter) */
+ guint position; /**< position */
+ EffectValues *values; /**< valid parameter values */
+} EffectSettings;
+
+typedef struct {
+ guint type; /**< value (type) */
+ gchar *label; /**< Effect name */
+ EffectSettings *settings; /**< possible parameters */
+ gint settings_amt; /**< possible parameters length */
+} EffectGroup;
+
+typedef struct {
+ gchar *label; /**< Group label */
+ guint id; /**< ID to set effect on/off, or if it isn't on/off group then -1 */
+ guint type; /**< ID to set effect type */
+ guint position; /**< position */
+ EffectGroup *group; /**< possible effect types */
+ gint group_amt; /**< possible effect types length */
+} Effect;
+
+typedef struct {
+ gchar *label; /**< base effect name */
+ Effect *effect; /**< list of supported effects */
+ gint amt; /**< list of supported effects length */
+} EffectList;
+
+typedef struct {
+ guint type; /**< ID to set effect type */
+ guint position;
+ EffectGroup *group;
+ gint group_amt;
+} ModifierGroup;
+
+typedef struct {
+ gchar *name;
+ EffectList *effects;
+ gint n_effects;
+ gint n_rows;
+} EffectPage;
+
+typedef struct {
+ gchar *name;
+ PresetBank bank;
+} Banks;
+
+typedef struct {
+ gchar *name;
+ unsigned char family_id;
+ unsigned char product_id;
+ EffectPage *pages;
+ gint n_pages;
+ Banks *banks;
+ gint n_banks;
+} Device;
+
+ModifierGroup *modifier_linkable_list();
+void modifier_group_free(ModifierGroup *modifier_group);
+void get_values_info(EffectValues *values,
+ gdouble *min, gdouble *max, gboolean *custom);
+gboolean get_device_info(unsigned char device_id, unsigned char family_id,
+ unsigned char product_id,
+ Device **device);
+
+#endif /* GDIGI_EFFECTS_H */
diff --git a/gdigi.1 b/gdigi.1
new file mode 100644
index 0000000..49cf5e6
--- /dev/null
+++ b/gdigi.1
@@ -0,0 +1,74 @@
+.\" Hey, EMACS: -*- nroff -*-
+.\" First parameter, NAME, should be all caps
+.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
+.\" other parameters are allowed: see man(7), man(1)
+.TH GDIGI 1 "October 07, 2010"
+.\" Please adjust this date whenever revising the manpage.
+.\"
+.\" Some roff macros, for reference:
+.\" .nh disable hyphenation
+.\" .hy enable hyphenation
+.\" .ad l left justify
+.\" .ad b justify to both left and right margins
+.\" .nf disable filling
+.\" .fi enable filling
+.\" .br insert line break
+.\" .sp <n> insert n+1 empty lines
+.\" for manpage-specific macros, see man(7)
+.SH NAME
+gdigi \- utility to control DigiTech effect pedals
+.SH SYNOPSIS
+.B gdigi
+.RI [OPTION...]
+.SH DESCRIPTION
+gdigi is a tool aimed to provide X-Edit functionality to Linux users
+.PP
+Supported devices:
+.IP \(bu
+RP250
+.IP \(bu
+RP255
+.IP \(bu
+RP355
+.IP \(bu
+RP500
+.IP \(bu
+RP1000
+.IP \(bu
+GNX3000
+.IP \(bu
+GNX4K
+.PP
+.SH OPTIONS
+These programs follow the usual GNU command line syntax, with long
+options starting with two dashes (`\-').
+A summary of options is included below.
+For a complete description, see the Info files.
+.TP
+.B \-?, \-\-help
+Show summary of options.
+.TP
+.B \-\-help\-all
+Show all help options.
+.TP
+.B \-\-help\-gtk
+Show GTK+ options.
+.TP
+.B \-\-display=\fIDISPLAY\fR
+X display to use.
+.TP
+.B \-d, \-\-device
+MIDI device port to use.
+.SH AUTHOR
+gdigi was written by Tomasz Moń <desowin@gmail.com>.
+.PP
+Send comments, bug reports and patches to gdigi
+mailinglist at Google Groups.
+.PP
+This manual page was written by Andrew O. Shadoura <bugzilla@tut.by>,
+for the Debian project (but may be used by others).
+.PP
+Permission is granted to copy, distribute and/or modify this document under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, under version 3 of the License.
+
diff --git a/gdigi.c b/gdigi.c
new file mode 100644
index 0000000..5a46939
--- /dev/null
+++ b/gdigi.c
@@ -0,0 +1,1241 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#include <stdio.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+#include <getopt.h>
+#include <alsa/asoundlib.h>
+#include <alloca.h>
+#include "gdigi.h"
+#include "gui.h"
+
+static unsigned char device_id = 0x7F;
+static unsigned char family_id = 0x7F;
+static unsigned char product_id = 0x7F;
+
+static snd_rawmidi_t *output = NULL;
+static snd_rawmidi_t *input = NULL;
+static char *device_port = NULL;
+
+static GQueue *message_queue = NULL;
+static GMutex *message_queue_mutex = NULL;
+static GCond *message_queue_cond = NULL;
+
+/**
+ * Registers an error quark for gdigi if necessary.
+ *
+ * \return error quark used for gdigi errors
+ **/
+static GQuark gdigi_error_quark()
+{
+ static GQuark quark = 0;
+
+ if (quark == 0) {
+ quark = g_quark_from_static_string("gdigi-error");
+ }
+
+ return quark;
+}
+
+/**
+ * \param array data to calculate checksum
+ * \param length data length
+ *
+ * Calculates message checksum.
+ *
+ * \return calculated checksum.
+ **/
+static char calculate_checksum(gchar *array, gint length)
+{
+ int x;
+ int checksum = 0;
+
+ for (x = 0; x<length; x++) {
+ checksum ^= array[x];
+ }
+
+ return checksum;
+}
+
+/**
+ * Opens MIDI device. This function modifies global input and output variables.
+ *
+ * \return FALSE on success, TRUE on error.
+ **/
+gboolean open_device()
+{
+ int err;
+
+ err = snd_rawmidi_open(&input, &output, device_port, SND_RAWMIDI_SYNC);
+ if (err) {
+ fprintf(stderr, "snd_rawmidi_open %s failed: %d\n", device_port, err);
+ return TRUE;
+ }
+
+ err = snd_rawmidi_nonblock(output, 0);
+ if (err) {
+ fprintf(stderr, "snd_rawmidi_nonblock failed: %d\n", err);
+ return TRUE;
+ }
+
+ snd_rawmidi_read(input, NULL, 0); /* trigger reading */
+
+ return FALSE;
+}
+
+/**
+ * \param data data to be sent
+ * \param length data length
+ *
+ * Sends data to device. This function uses global output variable.
+ **/
+void send_data(char *data, int length)
+{
+ snd_rawmidi_write(output, data, length);
+}
+
+/**
+ * \param data data to be packed
+ * \param len data length
+ *
+ * Packs data using method used on all newer DigiTech products.
+ *
+ * \return GString containing packed data
+ **/
+GString *pack_data(gchar *data, gint len)
+{
+ GString *packed;
+ gint i;
+ gint new_len;
+ unsigned char status;
+ gint offset;
+ gint status_byte;
+
+ new_len = len + (len/7);
+ packed = g_string_sized_new(new_len);
+ status = 0;
+ offset = -1;
+ status_byte = 0;
+
+ for (i=0; i<len; i++) {
+ if ((i % 7) == 0) {
+ packed->str[status_byte] = status;
+ status = 0;
+ status_byte = packed->len;
+ g_string_append_c(packed, '\0');
+ }
+ g_string_append_c(packed, (data[i] & 0x7F));
+ status |= (data[i] & 0x80) >> ((i%7) + 1);
+ }
+ packed->str[status_byte] = status;
+
+ return packed;
+}
+
+static void message_free_func(GString *msg, gpointer user_data)
+{
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param msg message to unpack
+ *
+ * Unpacks message data. This function modifies given GString.
+ **/
+static void unpack_message(GString *msg)
+{
+ int offset;
+ int x;
+ int i;
+ unsigned char status;
+ unsigned char *str;
+ gboolean stop = FALSE;
+
+ g_return_if_fail(msg != NULL);
+ g_return_if_fail(msg->len > 9);
+
+ offset = 1;
+ x = 0;
+ i = 8;
+
+ str = (unsigned char*)msg->str;
+ do {
+ offset += 8;
+ status = str[offset-1];
+ for (x=0; x<7 && !stop; x++) {
+ if (offset+x >= msg->len) {
+ i++;
+ stop = TRUE;
+ break;
+ }
+ if (str[offset+x] == 0xF7) {
+ if (x == 0) {
+ str[i] = status;
+ i++;
+ }
+ str[i] = 0xF7;
+ i++;
+ stop = TRUE;
+ break;
+ }
+
+ str[i] = (((status << (x+1)) & 0x80) | str[x+offset]);
+ i++;
+ }
+ } while (!stop);
+
+ g_string_truncate(msg, i);
+}
+
+/**
+ * \param msg SysEx message
+ *
+ * Checks message ID.
+ *
+ * \return MessageID, or -1 on error.
+ **/
+MessageID get_message_id(GString *msg)
+{
+ /** \todo check if msg is valid SysEx message */
+ g_return_val_if_fail(msg != NULL, -1);
+ g_return_val_if_fail(msg->str != NULL, -1);
+
+ if (msg->len > 7) {
+ return (unsigned char)msg->str[7];
+ }
+ return -1;
+}
+
+void push_message(GString *msg)
+{
+ if (((unsigned char)msg->str[0] == 0xF0) && ((unsigned char)msg->str[msg->len-1] == 0xF7))
+ g_message("Pushing correct message!");
+ else
+ g_warning("Pushing incorrect message!");
+
+ int x;
+ for (x = 0; x<msg->len; x++)
+ printf("%02x ", (unsigned char)msg->str[x]);
+ printf("\n");
+
+ switch (get_message_id(msg)) {
+ case ACK:
+ g_message("Received ACK");
+ g_string_free(msg, TRUE);
+ return;
+
+ case NACK:
+ g_message("Received NACK");
+ g_string_free(msg, TRUE);
+ return;
+
+ case RECEIVE_PARAMETER_VALUE:
+ unpack_message(msg);
+ SettingParam *param = setting_param_new_from_data(&msg->str[8], NULL);
+ g_message("Received parameter change ID: %d Position: %d Value: %d", param->id, param->position, param->value);
+
+ GDK_THREADS_ENTER();
+ apply_setting_param_to_gui(param);
+ GDK_THREADS_LEAVE();
+
+ setting_param_free(param);
+ g_string_free(msg, TRUE);
+ return;
+
+ case RECEIVE_DEVICE_NOTIFICATION:
+ unpack_message(msg);
+ unsigned char *str = (unsigned char*)msg->str;
+ switch (str[8]) {
+ case NOTIFY_PRESET_MOVED:
+ if (str[11] == PRESETS_EDIT_BUFFER && str[12] == 0) {
+ g_message("Loaded preset %d from bank %d", str[10], str[9]);
+
+ GDK_THREADS_ENTER();
+ g_timeout_add(0, apply_current_preset_to_gui, NULL);
+ GDK_THREADS_LEAVE();
+ } else
+ g_message("%d %d moved to %d %d", str[9], str[10], str[11], str[12]);
+ default:
+ g_message("Received unhandled device notification");
+ }
+ g_string_free(msg, TRUE);
+ return;
+ default:
+ g_mutex_lock(message_queue_mutex);
+ g_queue_push_tail(message_queue, msg);
+ g_cond_signal(message_queue_cond);
+ g_mutex_unlock(message_queue_mutex);
+ }
+}
+
+gpointer read_data_thread(gboolean *stop)
+{
+ /* This is mostly taken straight from alsa-utils-1.0.19 amidi/amidi.c
+ by Clemens Ladisch <clemens@ladisch.de> */
+ int err;
+ int npfds;
+ struct pollfd *pfds;
+ GString *string = NULL;
+
+ npfds = snd_rawmidi_poll_descriptors_count(input);
+ pfds = alloca(npfds * sizeof(struct pollfd));
+ snd_rawmidi_poll_descriptors(input, pfds, npfds);
+
+ do {
+ unsigned char buf[256];
+ int i, length;
+ unsigned short revents;
+
+ /* SysEx messages can't contain bytes with 8th bit set.
+ memset our buffer to 0xFF, so if for some reason we'll get out of reply bounds, we'll catch it */
+ memset(buf, sizeof(buf), 0xFF);
+
+ err = poll(pfds, npfds, 200);
+ if (err < 0 && errno == EINTR)
+ break;
+ if (err < 0) {
+ g_error("poll failed: %s", strerror(errno));
+ break;
+ }
+ if ((err = snd_rawmidi_poll_descriptors_revents(input, pfds, npfds, &revents)) < 0) {
+ g_error("cannot get poll events: %s", snd_strerror(errno));
+ break;
+ }
+ if (revents & (POLLERR | POLLHUP))
+ break;
+ if (!(revents & POLLIN))
+ continue;
+
+ err = snd_rawmidi_read(input, buf, sizeof(buf));
+ if (err == -EAGAIN)
+ continue;
+ if (err < 0) {
+ g_error("cannot read: %s", snd_strerror(err));
+ break;
+ }
+
+ length = 0;
+ for (i = 0; i < err; ++i)
+ if ((unsigned char)buf[i] != 0xFE) /* ignore active sensing */
+ buf[length++] = buf[i];
+
+ i = 0;
+
+ while (i < length) {
+ int pos;
+ int bytes;
+
+ if (string == NULL) {
+ while (buf[i] != 0xF0 && i < length)
+ i++;
+ }
+
+ pos = i;
+
+ for (bytes = 0; (bytes<length-i) && (buf[i+bytes] != 0xF7); bytes++);
+
+ if (buf[i+bytes] == 0xF7) bytes++;
+
+ i += bytes;
+
+ if (string == NULL)
+ string = g_string_new_len((gchar*)&buf[pos], bytes);
+ else
+ g_string_append_len(string, (gchar*)&buf[pos], bytes);
+
+ if ((unsigned char)string->str[string->len-1] == 0xF7) {
+ /* push message on stack */
+ push_message(string);
+ string = NULL;
+ }
+ }
+ } while (*stop == FALSE);
+
+ if (string) {
+ g_string_free(string, TRUE);
+ string = NULL;
+ }
+
+ return NULL;
+}
+
+/**
+ * \param procedure procedure ID
+ * \param data unpacked message data
+ * \param len data length
+ *
+ * Creates SysEx message then sends it. This function uses folowing global variables: device_id, family_id and product_id.
+ **/
+void send_message(gint procedure, gchar *data, gint len)
+{
+ GString *msg = g_string_new_len("\xF0" /* SysEx status byte */
+ "\x00\x00\x10", /* Manufacturer ID */
+ 4);
+ g_string_append_printf(msg,
+ "%c%c%c" /* device, family, product ID */
+ "%c", /* procedure */
+ device_id, family_id, product_id,
+ procedure);
+
+ if (len > 0) {
+ GString *tmp = pack_data(data, len);
+ g_string_append_len(msg, tmp->str, tmp->len);
+ g_string_free(tmp, TRUE);
+ }
+
+ g_string_append_printf(msg, "%c\xF7",
+ calculate_checksum(&msg->str[1], msg->len - 1));
+
+ send_data(msg->str, msg->len);
+
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param id MessageID of requested message
+ *
+ * Reads data from message queue until message with matching id is found.
+ *
+ * \return GString containing unpacked message.
+ **/
+GString *get_message_by_id(MessageID id)
+{
+ GString *data = NULL;
+ guint x, len;
+ gboolean found = FALSE;
+
+ g_mutex_lock(message_queue_mutex);
+ do {
+ len = g_queue_get_length(message_queue);
+ for (x = 0; x<len; x++) {
+ data = g_queue_peek_nth(message_queue, x);
+ if (get_message_id(data) == id) {
+ found = TRUE;
+ g_queue_pop_nth(message_queue, x);
+ break;
+ }
+ }
+
+ if (found == FALSE)
+ g_cond_wait(message_queue_cond, message_queue_mutex);
+
+ } while (found == FALSE);
+ g_mutex_unlock(message_queue_mutex);
+
+ unpack_message(data);
+
+ return data;
+}
+
+/**
+ * \param msg message to append value
+ * \param value value to append
+ *
+ * Packs value using scheme used on all newer DigiTech products.
+ **/
+void append_value(GString *msg, guint value)
+{
+ /* check how many bytes long the value is */
+ guint temp = value;
+ gint n = 0;
+ do {
+ n++;
+ temp = temp >> 8;
+ } while (temp);
+
+ if (n == 1) {
+ if (value & 0x80)
+ n = 2;
+ else
+ g_string_append_printf(msg, "%c", value);
+ }
+
+ if (n > 1) {
+ gint x;
+ g_string_append_printf(msg, "%c", (n | 0x80));
+ for (x=0; x<n; x++) {
+ g_string_append_printf(msg, "%c",
+ ((value >> (8*(n-x-1))) & 0xFF));
+ }
+ }
+}
+
+/**
+ * \param str pointer to value to unpack
+ * \param len return location for how many bytes value is encoded on (length is added to current value)
+ *
+ * Unpacks value using scheme used on all newer DigiTech products.
+ *
+ * \return unpacked value
+ **/
+guint unpack_value(gchar *str, int *len)
+{
+ guint value;
+ gint tmp;
+
+ value = (unsigned char)str[0];
+ if (len != NULL)
+ *len += 1;
+
+ if (value > 0x80) {
+ tmp = value & 0x7F;
+ value = 0;
+ gint i;
+ for (i = 0; i<tmp; i++) {
+ value |= ((unsigned char)str[1+i] << (8*(tmp-i-1)));
+ }
+
+ if (len != NULL)
+ *len += tmp;
+ }
+
+ return value;
+}
+
+/**
+ * Allocates memory for SettingParam.
+ *
+ * \return SettingParam which must be freed using setting_param_free.
+ **/
+SettingParam *setting_param_new()
+{
+ SettingParam *param = g_slice_new(SettingParam);
+ param->id = -1;
+ param->position = -1;
+ param->value = -1;
+
+ return param;
+}
+
+/**
+ * \param str pointer to setting param in message
+ * \param len return location for how many bytes value is encoded on (length is added to current value)
+ *
+ * Creates SettingParam basing on data.
+ * This function expects str to point on:
+ * -Parameter ID - 2 bytes
+ * -Parameter position - 1 byte
+ * -Parameter value - var
+ *
+ * \return newly created SettingParam which must be freed using setting_param_free.
+ **/
+SettingParam *setting_param_new_from_data(gchar *str, gint *len)
+{
+ gint id;
+ gint position;
+ guint value;
+
+ id = ((unsigned char)str[0] << 8) | (unsigned char)str[1];
+ position = (unsigned char)str[2];
+ if (len != NULL)
+ *len += 3;
+
+ value = unpack_value(&str[3], len);
+
+ SettingParam *param = g_slice_new(SettingParam);
+ param->id = id;
+ param->position = position;
+ param->value = value;
+
+ return param;
+}
+
+/**
+ * \param param SettingParam to be freed
+ *
+ * Frees all memory used by SettingParam.
+ **/
+void setting_param_free(SettingParam *param)
+{
+ g_slice_free(SettingParam, param);
+}
+
+/**
+ * Allocates memory for SettingGenetx.
+ *
+ * \return SettingGenetx which must be freed using setting_genetx_free.
+ **/
+SettingGenetx *setting_genetx_new()
+{
+ SettingGenetx *genetx = g_slice_new(SettingGenetx);
+ /* Older patches don't specify GeNetX version */
+ genetx->version = GENETX_VERSION_1;
+ genetx->type = GENETX_TYPE_NOT_SET;
+ genetx->channel = -1;
+ genetx->name = NULL;
+ genetx->data = NULL;
+
+ return genetx;
+}
+
+/**
+ * \param genetx SettingGenetx to be freed
+ *
+ * Frees all memory used by SettingGenetx.
+ **/
+void setting_genetx_free(SettingGenetx *genetx)
+{
+ g_free(genetx->name);
+ if (genetx->data != NULL) {
+ g_string_free(genetx->data, TRUE);
+ }
+ g_slice_free(SettingGenetx, genetx);
+}
+
+/**
+ * \param version GeNetX version
+ * \param type GeNetX type
+ *
+ * Retrieves SectionID for specified GeNetX version and type.
+ *
+ * \return SectionID specified by version and type, or -1 on error.
+ **/
+SectionID get_genetx_section_id(gint version, gint type)
+{
+ if (version == GENETX_VERSION_1) {
+ if (type == GENETX_TYPE_AMP) {
+ return SECTION_GENETX_AMP;
+ } else if (type == GENETX_TYPE_CABINET) {
+ return SECTION_GENETX_CABINET;
+ }
+ } else if (version == GENETX_VERSION_2) {
+ if (type == GENETX_TYPE_AMP) {
+ return SECTION_GENETX2_AMP;
+ } else if (type == GENETX_TYPE_CABINET) {
+ return SECTION_GENETX2_CABINET;
+ }
+ }
+
+ g_message("This version of gdigi don't know what to do with this "
+ "GeNetX version (%d) and type (%d)", version, type);
+
+ return -1;
+}
+
+/**
+ * \param id Parameter ID
+ * \param position Parameter position
+ * \param value Parameter value
+ *
+ * Forms SysEx message to set parameter then sends it to device.
+ **/
+void set_option(guint id, guint position, guint value)
+{
+ GString *msg = g_string_sized_new(9);
+ g_string_append_printf(msg, "%c%c%c",
+ ((id & 0xFF00) >> 8), (id & 0xFF),
+ position);
+ append_value(msg, value);
+ send_message(RECEIVE_PARAMETER_VALUE, msg->str, msg->len);
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param section data section ID
+ * \param bank section-specific bank number
+ * \param index index of the desired object within the bank
+ * \param name object name
+ * \param data GString containing object data
+ *
+ * Forms RECEIVE_OBJECT SysEx message then sends it to device.
+ **/
+void send_object(SectionID section, guint bank, guint index,
+ gchar *name, GString *data)
+{
+ GString *msg = g_string_new(NULL);
+
+ gint len = data->len;
+
+ g_string_append_printf(msg,
+ "%c%c%c%c%s%c%c%c",
+ section, bank,
+ ((index & 0xFF00) >> 8), (index & 0xFF),
+ name, 0 /* NULL terminated string */,
+ ((len & 0xFF00) >> 8), (len & 0xFF));
+
+ g_string_append_len(msg, data->str, data->len);
+
+ send_message(RECEIVE_OBJECT, msg->str, msg->len);
+
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param params GList containing SettingParam
+ *
+ * Forms RECEIVE_PRESET_PARAMETERS SysEx message then sends it to device.
+ **/
+void send_preset_parameters(GList *params)
+{
+ GString *msg = g_string_sized_new(500);
+ GList *iter = params;
+ gint len = g_list_length(iter);
+
+ g_string_append_printf(msg, "%c%c",
+ ((len & 0xFF00) >> 8),
+ (len & 0xFF));
+
+ while (iter) {
+ SettingParam *param = (SettingParam *) iter->data;
+ iter = iter->next;
+
+ g_string_append_printf(msg, "%c%c%c",
+ ((param->id & 0xFF00) >> 8),
+ (param->id & 0xFF),
+ param->position);
+
+ append_value(msg, param->value);
+ };
+
+ send_message(RECEIVE_PRESET_PARAMETERS, msg->str, msg->len);
+
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param bank preset bank
+ * \param x preset index
+ *
+ * Switches to selected preset.
+ **/
+void switch_preset(guint bank, guint x)
+{
+ GString *msg = g_string_sized_new(6);
+ g_string_append_printf(msg, "%c%c%c%c%c%c",
+ bank, x, /* source */
+ PRESETS_EDIT_BUFFER, 0, /* destination */
+ 0, /* keep existing name */
+ 1); /* load */
+ send_message(MOVE_PRESET, msg->str, msg->len);
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param x preset index
+ * \param name preset name
+ *
+ * Stores current edit buffer in user presets bank.
+ **/
+void store_preset_name(int x, const gchar *name)
+{
+ GString *msg = g_string_sized_new(6);
+ g_string_append_printf(msg, "%c%c%c%c%s%c%c",
+ PRESETS_EDIT_BUFFER, 0, /* source */
+ PRESETS_USER, x, /* destination */
+ name, 0, /* name */
+ 1); /* load */
+ send_message(MOVE_PRESET, msg->str, msg->len);
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param x preset index
+ * \param name preset name
+ *
+ * Sets preset name.
+ **/
+void set_preset_name(int x, gchar *name)
+{
+ GString *msg = g_string_sized_new(12);
+ g_string_append_printf(msg, "%c%c%s%c",
+ PRESETS_USER, /* preset bank */
+ x, /* preset index */
+ name, 0); /* name */
+ send_message(RECEIVE_PRESET_NAME, msg->str, msg->len);
+ g_string_free(msg, TRUE);
+}
+
+/**
+ * \param bank preset bank
+ *
+ * Queries preset names.
+ *
+ * \return GStrv which must be freed with g_strfreev, or NULL on error.
+ **/
+GStrv query_preset_names(gchar bank)
+{
+ GString *data = NULL;
+ int x; /* used to iterate over whole reply */
+ int n = 0; /* current preset number */
+ int n_total; /* total number of presets */
+ gchar **str_array = NULL;
+
+ /* query user preset names */
+ send_message(REQUEST_PRESET_NAMES, &bank, 1);
+
+ /* read reply */
+ data = get_message_by_id(RECEIVE_PRESET_NAMES);
+
+ if (data != NULL) {
+ if (data->len >= 10) {
+ n_total = data->str[9];
+ str_array = g_new(gchar*, n_total + 1);
+ str_array[n_total] = NULL;
+ }
+
+ for (x=10; ((x<data->len) && (n<n_total)); x++) {
+ if ((unsigned char)data->str[x] == 0xF7) /* every message ends with 0xF7 */
+ break;
+
+ str_array[n] = g_strdup(&data->str[x]);
+ x += strlen(str_array[n]);
+ n++;
+ }
+ g_string_free(data, TRUE);
+ }
+ return str_array;
+}
+
+/**
+ * Reads multiple messages and puts them into GList.
+ *
+ * \param id MessageID starting message sequence
+ *
+ * \return GList with SysEx messages, which must be freed using message_list_free.
+ **/
+GList *get_message_list(MessageID id)
+{
+ GString *data = NULL;
+ GList *list = NULL;
+ guint x, len;
+ gboolean found = FALSE;
+ gboolean done = FALSE;
+
+ g_mutex_lock(message_queue_mutex);
+ do {
+ len = g_queue_get_length(message_queue);
+
+ for (x = 0; x<len && (found == FALSE); x++) {
+ data = g_queue_peek_nth(message_queue, x);
+ if (get_message_id(data) == id) {
+ found = TRUE;
+ g_queue_pop_nth(message_queue, x);
+ unpack_message(data);
+ list = g_list_append(list, data);
+ break;
+ }
+ }
+
+ if (found == TRUE) {
+ int i;
+ int amt;
+
+ switch (id) {
+ case RECEIVE_PRESET_START:
+ for (i = 10; (i < data->len) && data->str[i]; i++);
+ amt = (unsigned char)data->str[i+2];
+ break;
+ case RECEIVE_BULK_DUMP_START:
+ amt = ((unsigned char)data->str[8] << 8) | (unsigned char)data->str[9];
+ break;
+ default:
+ g_error("get_message_list() doesn't support followning id: %d", id);
+ g_string_free(data, TRUE);
+ g_list_free(list);
+ return NULL;
+ }
+
+ while (amt) {
+ g_message("%d messages left", amt);
+ data = g_queue_pop_nth(message_queue, x);
+ if (data == NULL) {
+ g_cond_wait(message_queue_cond, message_queue_mutex);
+ } else {
+ unpack_message(data);
+ list = g_list_append(list, data);
+ amt--;
+ }
+ }
+
+ done = TRUE;
+ } else {
+ /* id not found in message queue */
+ g_cond_wait(message_queue_cond, message_queue_mutex);
+ }
+ } while (done == FALSE);
+ g_mutex_unlock(message_queue_mutex);
+
+ return list;
+}
+
+/**
+ * \param list list to be freed
+ *
+ * Frees all memory used by message list.
+ **/
+void message_list_free(GList *list)
+{
+ g_return_if_fail(list != NULL);
+
+ g_list_foreach(list, (GFunc) message_free_func, NULL);
+ g_list_free(list);
+}
+
+/**
+ * Queries current edit buffer.
+ *
+ * \return GList with preset SysEx messages, which must be freed using message_list_free.
+ **/
+GList *get_current_preset()
+{
+ send_message(REQUEST_PRESET, "\x04\x00", 2);
+ return get_message_list(RECEIVE_PRESET_START);
+}
+
+/**
+ * Creates backup file.
+ *
+ * \param file backup file handle
+ * \param error a GError
+ *
+ * \return FALSE on success, TRUE on error.
+ **/
+static gboolean create_backup_file(GFile *file, GError **error)
+{
+ GFileOutputStream *output = NULL;
+ GList *list = NULL, *iter = NULL;
+ const gchar header[] = {'\x01', '\x00'};
+ gsize written;
+ gboolean val;
+
+ if (error)
+ *error = NULL;
+ output = g_file_create(file, G_FILE_CREATE_NONE, NULL, error);
+ if (output == NULL)
+ return TRUE;
+
+ if (error)
+ *error = NULL;
+ val = g_output_stream_write_all(G_OUTPUT_STREAM(output), header,
+ sizeof(header), &written, NULL, error);
+ if (val == FALSE) {
+ g_object_unref(output);
+ return TRUE;
+ }
+
+ send_message(REQUEST_BULK_DUMP, "\x00", 1);
+ list = get_message_list(RECEIVE_BULK_DUMP_START);
+
+ for (iter = list; iter; iter = g_list_next(iter)) {
+ GString *str;
+ guchar id; /* message id */
+ guint32 len; /* message length */
+
+ str = (GString*) iter->data;
+
+ id = get_message_id(str);
+ if (error)
+ *error = NULL;
+ val = g_output_stream_write_all(G_OUTPUT_STREAM(output), &id,
+ sizeof(id), &written, NULL, error);
+ if (val == FALSE) {
+ message_list_free(list);
+ g_object_unref(output);
+ return TRUE;
+ }
+
+ len = GUINT32_TO_LE(str->len - 10);
+ if (error)
+ *error = NULL;
+ val = g_output_stream_write_all(G_OUTPUT_STREAM(output), &len,
+ sizeof(len), &written, NULL, error);
+ if (val == FALSE) {
+ message_list_free(list);
+ g_object_unref(output);
+ return TRUE;
+ }
+
+ if (error)
+ *error = NULL;
+ val = g_output_stream_write_all(G_OUTPUT_STREAM(output), &str->str[8],
+ str->len - 10, &written, NULL, error);
+ if (val == FALSE) {
+ message_list_free(list);
+ g_object_unref(output);
+ return TRUE;
+ }
+ }
+
+ message_list_free(list);
+
+ if (error)
+ *error = NULL;
+ val = g_output_stream_close(G_OUTPUT_STREAM(output), NULL, error);
+ g_object_unref(output);
+ return !val;
+}
+
+/**
+ * Restores backup file.
+ *
+ * \param filename backup filename
+ * \param error a GError
+ *
+ * \return FALSE on success, TRUE on error.
+ **/
+static gboolean restore_backup_file(const gchar *filename, GError **error)
+{
+ gchar *data;
+ gsize length;
+ gsize x;
+
+ if (g_file_get_contents(filename, &data, &length, error) == FALSE)
+ return TRUE;
+
+ if (error)
+ *error = NULL;
+
+ if (!(data[0] == 0x01 && data[1] == 0x00)) {
+ g_free(data);
+ g_set_error_literal(error, gdigi_error_quark(), 0,
+ "Magic byte doesn't match");
+ return TRUE;
+ }
+
+ x = 0x02;
+ while (x < length) {
+ gchar id;
+ guint32 len;
+
+ id = data[x];
+ x++;
+
+ if (x+4 <= length) {
+ len = GUINT32_FROM_LE(*((guint32*) &data[x]));
+ x += 4;
+ } else {
+ g_free(data);
+ g_set_error_literal(error, gdigi_error_quark(), 0,
+ "Unexpected end of data");
+ return TRUE;
+ }
+
+ if (x+len <= length) {
+ send_message(id, &data[x], len);
+ x += len;
+ } else {
+ g_free(data);
+ g_set_error_literal(error, gdigi_error_quark(), 0,
+ "Unexpected end of data");
+ return TRUE;
+ }
+ }
+
+ g_free(data);
+ return FALSE;
+}
+
+/**
+ * \param device_id Variable to hold device ID
+ * \param family_id Variable to hold family ID
+ * \param product_id Variable to hold product ID
+ *
+ * Requests device information.
+ *
+ * \return TRUE on success, FALSE on error.
+ **/
+static gboolean request_who_am_i(unsigned char *device_id, unsigned char *family_id,
+ unsigned char *product_id)
+{
+ send_message(REQUEST_WHO_AM_I, "\x7F\x7F\x7F", 3);
+
+ GString *data = get_message_by_id(RECEIVE_WHO_AM_I);
+ if ((data != NULL) && (data->len > 11)) {
+ *device_id = data->str[8];
+ *family_id = data->str[9];
+ *product_id = data->str[10];
+ g_string_free(data, TRUE);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void request_device_configuration()
+{
+ gint os_major, os_minor;
+ gint cpu_major, cpu_minor;
+ gint protocol_version;
+ gint current_bank, current_preset;
+ gint media_card;
+
+ send_message(REQUEST_DEVICE_CONFIGURATION, NULL, 0);
+
+ GString *data = get_message_by_id(RECEIVE_DEVICE_CONFIGURATION);
+
+ if (data->len > 14) {
+ os_major = data->str[8];
+ os_minor = (((data->str[9] & 0xF0) >> 4) * 10) |
+ (data->str[9] & 0x0F);
+ g_message("OS version: %d.%d", os_major, os_minor);
+
+ cpu_major = data->str[10];
+ cpu_minor = data->str[11];
+ g_message("CPU version: %d.%d", cpu_major, cpu_minor);
+
+ protocol_version = data->str[12];
+ g_message("Protocol version: %d", protocol_version);
+
+ current_bank = data->str[13];
+ current_preset = data->str[14];
+ g_message("Active bank: %d", current_bank);
+ g_message("Active preset: %d", current_preset);
+
+ if (os_major >= 1) {
+ media_card = data->str[15];
+ g_message("Media card present: %d", media_card);
+ }
+ }
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+static GOptionEntry options[] = {
+ {"device", 'd', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &device_port, "MIDI device port to use", NULL},
+ {NULL}
+};
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+/**
+ * \param[out] devices GList containing numbers (packed into pointers)
+ * of connected DigiTech devices
+ *
+ * Checks available soundcards for DigiTech devices.
+ *
+ * \return the number of connected DigiTech devices.
+ **/
+static gint get_digitech_devices(GList **devices)
+{
+ gint card_num = -1;
+ gint number = 0;
+ snd_card_next(&card_num);
+
+ while (card_num > -1) {
+ char* name;
+ snd_card_get_longname(card_num, &name);
+ gint count = strspn(name,"DigiTech");
+ if (count > 0)
+ {
+ number++;
+ *devices = g_list_append(*devices, GINT_TO_POINTER(card_num));
+ }
+ snd_card_next(&card_num);
+ }
+
+ return number;
+}
+
+int main(int argc, char *argv[]) {
+ GError *error = NULL;
+ GOptionContext *context;
+ static gboolean stop_read_thread = FALSE;
+ GThread *read_thread = NULL;
+
+ g_thread_init(NULL);
+ gdk_threads_init();
+
+ context = g_option_context_new(NULL);
+ g_option_context_add_main_entries(context, options, NULL);
+ g_option_context_add_group(context, gtk_get_option_group(TRUE));
+
+ if (!g_option_context_parse(context, &argc, &argv, &error)) {
+ g_message("option parsing failed: %s\n", error->message);
+ g_error_free(error);
+ g_option_context_free(context);
+ exit(EXIT_FAILURE);
+ }
+
+ if (device_port == NULL) {
+ /* port not given explicitly in commandline - search for devices */
+ GList *devices = NULL;
+ if (get_digitech_devices(&devices) <= 0) {
+ g_message("Couldn't find DigiTech devices!");
+ exit(EXIT_FAILURE);
+ }
+ device_port = g_strdup_printf("hw:%d,0,0",
+ GPOINTER_TO_INT(devices->data));
+ g_list_free(devices);
+ g_message("Found device %s", device_port);
+ } else {
+ g_message("Using device %s", device_port);
+ }
+
+ g_option_context_free(context);
+
+ if (open_device() == TRUE) {
+ show_error_message(NULL, "Failed to open MIDI device");
+ } else {
+ message_queue = g_queue_new();
+ message_queue_mutex = g_mutex_new();
+ message_queue_cond = g_cond_new();
+ read_thread = g_thread_create((GThreadFunc)read_data_thread,
+ &stop_read_thread,
+ TRUE, NULL);
+
+ if (request_who_am_i(&device_id, &family_id, &product_id) == FALSE) {
+ show_error_message(NULL, "No suitable reply from device");
+ } else {
+ Device *device = NULL;
+
+ if (get_device_info(device_id, family_id, product_id, &device) == FALSE) {
+ if (unsupported_device_dialog(&device) == FALSE) {
+ g_message("Shutting down");
+ }
+ }
+
+ if (device != NULL) {
+ /* enable GUI mode */
+ set_option(GUI_MODE_ON_OFF, USB_POSITION, 1);
+
+ gui_create(device);
+ gtk_main();
+ gui_free();
+
+ /* disable GUI mode */
+ set_option(GUI_MODE_ON_OFF, USB_POSITION, 0);
+ }
+ }
+ }
+
+ if (read_thread != NULL) {
+ stop_read_thread = TRUE;
+ g_thread_join(read_thread);
+ }
+
+ if (message_queue_mutex != NULL) {
+ g_mutex_free(message_queue_mutex);
+ }
+
+ if (message_queue != NULL) {
+ g_message("%d unread messages in queue",
+ g_queue_get_length(message_queue));
+ g_queue_foreach(message_queue, (GFunc) message_free_func, NULL);
+ g_queue_free(message_queue);
+ }
+
+ if (output != NULL) {
+ snd_rawmidi_drain(output);
+ snd_rawmidi_close(output);
+ }
+
+ if (input != NULL) {
+ snd_rawmidi_drain(input);
+ snd_rawmidi_close(input);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/gdigi.desktop b/gdigi.desktop
new file mode 100644
index 0000000..804407a
--- /dev/null
+++ b/gdigi.desktop
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Version=1.0
+Type=Application
+Name=gdigi
+Exec=gdigi
+Categories=GNOME;Audio;AudioVideo;
+
diff --git a/gdigi.h b/gdigi.h
new file mode 100644
index 0000000..0fc0ace
--- /dev/null
+++ b/gdigi.h
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef GDIGI_H
+#define GDIGI_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#define GNX_CHANNEL_POSITION 7
+#define GNX_CHANNEL_AMP 260
+#define GNX_WARP 261
+#define GNX_AMP_WARP 262
+#define GNX_CABINET_WARP 263
+#define GNX_CHANNEL_FS_MODE 264
+
+enum {
+ GNX3K_WAH_TYPE_CRY = 129,
+ GNX3K_WAH_TYPE_BOUTIQUE = 130,
+ GNX3K_WAH_TYPE_FULLRANGE = 131,
+
+ WAH_TYPE_CRY = 132,
+ WAH_TYPE_FULLRANGE = 133,
+ WAH_TYPE_CLYDE = 134
+};
+
+#define WAH_POSITION_MIN_MAX 20
+
+#define WAH_MIN 8195
+#define WAH_MAX 8196
+
+#define WAH_TYPE 128
+#define WAH_ON_OFF 129
+#define WAH_POSITION 3
+
+#define WAH_LEVEL 133
+
+enum {
+ COMP_TYPE_DIGI = 195,
+ COMP_TYPE_CS = 196,
+ COMP_TYPE_DYNA = 197
+};
+
+#define GNX3K_WHAM_TYPE 768
+#define GNX3K_WHAM_ENABLE 769
+#define GNX3K_WHAM_POSITION 5
+#define GNX3K_DETUNE_AMOUNT 1670
+#define GNX3K_PITCH_AMOUNT 1732
+#define GNX3K_PITCH_LEVEL 1731
+#define GNX3K_TALK_LEVEL 2818
+
+enum {
+ GNX3K_WHAM_TYPE_WHAMMY = 1344,
+ GNX3K_WHAM_TYPE_IPS = 1345,
+ GNX3K_WHAM_TYPE_DETUNE = 1346,
+ GNX3K_WHAM_TYPE_PITCH = 1347,
+ GNX3K_WHAM_TYPE_TALK1 = 1348,
+ GNX3K_WHAM_TYPE_TALK2 = 1349,
+ GNX3K_WHAM_TYPE_TALK3 = 1350,
+ GNX3K_WHAM_TYPE_TALK4 = 1351,
+ GNX3K_WHAM_TYPE_TALK5 = 1352
+};
+
+#define COMP_TYPE 207
+#define COMP_ON_OFF 193
+#define COMP_POSITION 4
+
+#define GNX3K_COMP_ATTACK 194
+#define GNX3K_COMP_RATIO 195
+#define GNX3K_COMP_THRESHOLD 200
+#define GNX3K_COMP_GAIN 201
+
+#define COMP_SUSTAIN 208
+#define COMP_TONE 209
+#define COMP_ATTACK 211
+#define COMP_LEVEL 210
+#define COMP_SENSITIVITY 213
+#define COMP_OUTPUT 212
+
+enum {
+ PICKUP_TYPE_HB_SC = 66,
+ PICKUP_TYPE_SC_HB = 65
+};
+
+#define PICKUP_TYPE 64
+#define PICKUP_ON_OFF 65
+#define PICKUP_POSITION 2
+
+enum {
+ DIST_TYPE_SCREAMER = 1280,
+ DIST_TYPE_808 = 1292,
+ DIST_TYPE_TS_MOD = 1301,
+ DIST_TYPE_SD_ODRV = 1302,
+ DIST_TYPE_OD_ODRV = 1299,
+ DIST_TYPE_SPARKDRIVE = 1286,
+ DIST_TYPE_GUYOD = 1285,
+ DIST_TYPE_DOD250 = 1283,
+ DIST_TYPE_REDLINE = 1297,
+ DIST_TYPE_AMPDRIVR = 1298,
+ DIST_TYPE_OC_DRIVE = 1300,
+ DIST_TYPE_RODENT = 1281,
+ DIST_TYPE_MX = 1291,
+ DIST_TYPE_DS = 1282,
+ DIST_TYPE_GRUNGE = 1287,
+ DIST_TYPE_ZONE = 1289,
+ DIST_TYPE_DEATH = 1294,
+ DIST_TYPE_GONK = 1293,
+ DIST_TYPE_8TAVIA = 1290,
+ DIST_TYPE_FUZZLATOR = 1295,
+ DIST_TYPE_CLASSIC_FUZZ = 1296,
+ DIST_TYPE_FUZZY = 1288,
+ DIST_TYPE_MP = 1284
+};
+
+#define DIST_TYPE 2432
+#define DIST_ON_OFF 2433
+#define DIST_POSITION 6
+
+#define DIST_SCREAMER_DRIVE 2434
+#define DIST_SCREAMER_TONE 2435
+#define DIST_SCREAMER_LVL 2436
+
+#define DIST_808_OVERDRIVE 2473
+#define DIST_808_TONE 2474
+#define DIST_808_LVL 2475
+
+#define DIST_TS_MOD_DRIVE 2562
+#define DIST_TS_MOD_TONE 2564
+#define DIST_TS_MOD_LVL 2563
+
+#define DIST_SD_ODRV_DRIVE 2565
+#define DIST_SD_ODRV_TONE 2566
+#define DIST_SD_ODRV_LVL 2567
+
+#define DIST_OD_ODRV_OVERDRIVE 2568
+#define DIST_OD_ODRV_LVL 2569
+
+#define DIST_SPARKDRIVE_GAIN 2450
+#define DIST_SPARKDRIVE_TONE 2451
+#define DIST_SPARKDRIVE_CLEAN 2452
+#define DIST_SPARKDRIVE_VOLUME 2453
+
+#define DIST_GUYOD_DRIVE 2448
+#define DIST_GUYOD_LVL 2449
+
+#define DIST_DOD250_GAIN 2443
+#define DIST_DOD250_LVL 2444
+
+#define DIST_REDLINE_GAIN 2488
+#define DIST_REDLINE_LOW 2489
+#define DIST_REDLINE_HIGH 2490
+#define DIST_REDLINE_LEVEL 2491
+
+#define DIST_AMPDRIVR_GAIN 2570
+#define DIST_AMPDRIVR_MIDBOOST 2571
+#define DIST_AMPDRIVR_LVL 2572
+
+#define DIST_OC_DRIVE_DRIVE 2492
+#define DIST_OC_DRIVE_TONE 2494
+#define DIST_OC_DRIVE_HP_LP 2493
+#define DIST_OC_DRIVE_LVL 2495
+
+#define DIST_RODENT_DIST 2437
+#define DIST_RODENT_FILTER 2438
+#define DIST_RODENT_LVL 2439
+
+#define DIST_MX_DIST 2468
+#define DIST_MX_OUTPUT 2469
+
+#define DIST_DS_GAIN 2440
+#define DIST_DS_TONE 2441
+#define DIST_DS_LVL 2442
+
+#define DIST_GRUNGE_GRUNGE 2454
+#define DIST_GRUNGE_FACE 2456
+#define DIST_GRUNGE_LOUD 2457
+#define DIST_GRUNGE_BUTT 2455
+
+#define DIST_ZONE_GAIN 2460
+#define DIST_ZONE_LOW 2463
+#define DIST_ZONE_MID_LVL 2462
+#define DIST_ZONE_MID_FREQ 2461
+#define DIST_ZONE_HIGH 2464
+#define DIST_ZONE_LEVEL 2465
+
+#define DIST_DEATH_LOW 2477
+#define DIST_DEATH_MID 2476
+#define DIST_DEATH_HIGH 2479
+#define DIST_DEATH_LVL 2478
+
+#define DIST_GONK_GONK 2480
+#define DIST_GONK_SMEAR 2471
+#define DIST_GONK_SUCK 2470
+#define DIST_GONK_HEAVE 2472
+
+#define DIST_8TAVIA_DRIVE 2466
+#define DIST_8TAVIA_VOLUME 2467
+
+#define DIST_FUZZLATOR_FUZZ 2481
+#define DIST_FUZZLATOR_TONE 2482
+#define DIST_FUZZLATOR_LOOSETIGHT 2483
+#define DIST_FUZZLATOR_VOLUME 2484
+
+#define DIST_CLASSIC_FUZZ_FUZZ 2485
+#define DIST_CLASSIC_FUZZ_TONE 2486
+#define DIST_CLASSIC_FUZZ_VOLUME 2487
+
+#define DIST_FUZZY_FUZZ 2458
+#define DIST_FUZZY_VOLUME 2459
+
+#define DIST_MP_SUSTAIN 2445
+#define DIST_MP_TONE 2446
+#define DIST_MP_VOLUME 2447
+
+#define PRESET_POSITION 18
+#define PRESET_LEVEL 2626
+
+enum {
+ AMP_TYPE_TWEED_CHAMP = 307,
+ AMP_TYPE_TWEED_DELUXE = 308,
+ AMP_TYPE_TWEED_BASSMAN = 309,
+ AMP_TYPE_BROWN_BASSMAN = 310,
+ AMP_TYPE_BLACKFACE_TWIN = 311,
+ AMP_TYPE_BLACKFACE_DELUXE = 312,
+ AMP_TYPE_PLEXI_JTM_45 = 313,
+ AMP_TYPE_SUPER_LEAD_PLEXI = 314,
+ AMP_TYPE_PLEXI_JUMP_PANEL = 315,
+ AMP_TYPE_MASTER_VOLUME = 316,
+ AMP_TYPE_JCM800 = 317,
+ AMP_TYPE_JCM900 = 318,
+ AMP_TYPE_JCM2000 = 319,
+ AMP_TYPE_AC15 = 322,
+ AMP_TYPE_AC30TB = 323,
+ AMP_TYPE_HIWATT_100 = 324,
+ AMP_TYPE_BOOGIE_MARK_II = 320,
+ AMP_TYPE_BOOGIE_MARK_IV = 371,
+ AMP_TYPE_DUAL_RECTIFIER = 321,
+ AMP_TYPE_TRIPLE_RECTIFIER = 370,
+ AMP_TYPE_22_CALIBR = 386,
+ AMP_TYPE_LEGACY_VL100 = 327,
+ AMP_TYPE_MATCHLESS_HC30 = 326,
+ AMP_TYPE_CHIEF = 385,
+ AMP_TYPE_SOLDANO_100 = 325,
+ AMP_TYPE_SUPERGROUP = 381,
+ AMP_TYPE_GA40 = 380,
+ AMP_TYPE_OR120 = 372,
+ AMP_TYPE_PV5150II = 373,
+ AMP_TYPE_RG100 = 374,
+ AMP_TYPE_JC120_JAZZ = 375,
+ AMP_TYPE_SOLAR100 = 376,
+ AMP_TYPE_SOLO = 331,
+ AMP_TYPE_METAL = 332,
+ AMP_TYPE_BRIGHT = 333,
+ AMP_TYPE_CHUNK = 334,
+ AMP_TYPE_CLEAN = 335,
+ AMP_TYPE_HIGH_GAIN = 337,
+ AMP_TYPE_BLUES = 338,
+ AMP_TYPE_FUZZ = 339,
+ AMP_TYPE_SPANK = 330,
+ AMP_TYPE_GSP2101_CLEAN_TUBE = 328,
+ AMP_TYPE_GSP2101_SAT_TUBE = 329,
+ AMP_TYPE_CRUNCH = 336,
+ AMP_TYPE_MONSTER = 377,
+ AMP_TYPE_TWEEDFACE = 378,
+ AMP_TYPE_BLACKBASS = 379,
+ AMP_TYPE_STONER_ROCK = 368,
+ AMP_TYPE_DARK_METAL = 369,
+ AMP_TYPE_TRANSISTOR = 382,
+ AMP_TYPE_BROWN_SOUND = 383,
+ AMP_TYPE_MOSH = 384,
+ AMP_TYPE_ACOUSTIC = 341,
+ AMP_TYPE_JUMBO_ACOUSTIC = 340,
+ AMP_TYPE_DIRECT = 306,
+ AMP_TYPE_SVT_ROCK_BASS = 342,
+ AMP_TYPE_SVT_CLASSIC_BASS = 343,
+ AMP_TYPE_PEG_B15_BASS = 344,
+ AMP_TYPE_BASIC_BASS = 345,
+ AMP_TYPE_SHOWMAN_BASS = 346,
+ AMP_TYPE_ASH_MODERN_BASS = 347,
+ AMP_TYPE_BRIT_BASS = 348,
+ AMP_TYPE_SOLAR_BASS = 349,
+ AMP_TYPE_BOOGIE_BASS = 350,
+ AMP_TYPE_HART_BASS = 351,
+};
+
+enum {
+ EQ_TYPE_BRIGHT = 1474,
+ EQ_TYPE_MIDBOOST = 1472,
+ EQ_TYPE_SCOOP = 1473,
+ EQ_TYPE_WARM = 1475
+};
+
+#define AMP_TYPE 2496
+#define AMP_ON_OFF 265
+#define AMP_POSITION 8
+#define CH2_AMP_POSITION 10
+
+#define AMP_LOOP_ON_OFF 3649
+#define AMP_LOOP_POSITION 33
+
+#define AMP_BYPASS_ON_OFF 12361
+#define AMP_BYPASS_POSITION 0
+
+#define AMP_SELECT 256
+#define AMP_SELECT_POSITION 7
+
+#define AMP_CHANNEL_A 0
+#define AMP_CHANNEL_B 1
+
+#define AMP_GAIN 2497
+#define AMP_LEVEL 2498
+#define AMP_BASS_FREQ 2499
+#define AMP_BASS_LEVEL 2500
+#define AMP_MID_FREQ 2501
+#define AMP_MID_LEVEL 2502
+#define AMP_TREBLE_FREQ 2503
+#define AMP_TREBLE_LEVEL 2504
+#define AMP_EQ_ON_OFF 2505
+#define AMP_PRESENCE 2506
+#define AMP_BASS 2507
+#define AMP_MID 2508
+#define AMP_TREBLE 2509
+
+#define AMP_CAB_TYPE 2560
+#define AMP_CAB_TUNING 2561
+#define AMP_CAB_POSITION 9
+#define CH2_AMP_CAB_POSITION 11
+
+enum {
+ AMP_CAB_DIRECT = 570,
+ AMP_CAB_CHAMP = 571,
+ AMP_CAB_DELUXE = 572,
+ AMP_CAB_DELUXE_REVERB = 573,
+ AMP_CAB_BRITISH1_12 = 623,
+ AMP_CAB_GA1_12 = 624,
+ AMP_CAB_BLONDE2_12 = 577,
+ AMP_CAB_TWIN = 576,
+ AMP_CAB_BRITISH2_12 = 613,
+ AMP_CAB_JAZZ2_12 = 626,
+ AMP_CAB_JBL_215 = 627,
+ AMP_CAB_BASSMAN = 579,
+ AMP_CAB_BRITISH4_12 = 614,
+ AMP_CAB_BRITISH_GREEN = 616,
+ AMP_CAB_FANE4_12 = 584,
+ AMP_CAB_BOUTIQUE4_12 = 583,
+ AMP_CAB_VINTAGE = 622,
+ AMP_CAB_RECTO4_12 = 625,
+ AMP_CAB_DIGI_SOLO = 609,
+ AMP_CAB_DIGI_BRIGHT = 611,
+ AMP_CAB_DIGI_METAL = 618,
+ AMP_CAB_DIGI_ROCK = 619,
+ AMP_CAB_DIGI_ALT = 620,
+ AMP_CAB_DIGI_VNTG = 621,
+ AMP_CAB_DIGI_CHUNK = 612,
+ AMP_CAB_DIGI_SPANK2_12 = 608,
+ AMP_CAB_DIGI_SPKR_COMP = 585
+};
+
+enum {
+ GNX_AMP_CAB_DIRECT = 570,
+ GNX_AMP_CAB_TWEED1_8 = 571,
+ GNX_AMP_CAB_TWEED1_12 = 572,
+ GNX_AMP_CAB_BLACKFACE1_12 = 573,
+ GNX_AMP_CAB_BRITISH1_12 = 574,
+ GNX_AMP_CAB_BLACKFACE2_12 = 576,
+ GNX_AMP_CAB_BLONDE2_12 = 577,
+ GNX_AMP_CAB_BRITISH2_12 = 578,
+ GNX_AMP_CAB_TWEED4_10 = 579,
+ GNX_AMP_CAB_BRITISH_70_4_12 = 580,
+ GNX_AMP_CAB_BRITISH_GREEN4_12 = 581,
+ GNX_AMP_CAB_STRAIGHT_V30_4_12 = 582,
+ GNX_AMP_CAB_SLANT_V30_4_12 = 583,
+ GNX_AMP_CAB_FANE4_12 = 584,
+ GNX_AMP_CAB_2101_SPKR_COMP = 585,
+ GNX_AMP_CAB_JUMBO_ACOUSTIC = 606,
+ GNX_AMP_CAB_DREAD_ACOUSTIC = 607,
+ GNX_AMP_CAB_DIGI_SPANK = 608,
+ GNX_AMP_CAB_DIGI_SOLO = 609,
+ GNX_AMP_CAB_DIGI_METAL = 610,
+ GNX_AMP_CAB_DIGI_BRIGHT = 611,
+ GNX_AMP_CAB_DIGI_CHUNK = 612,
+ GNX_AMP_CAB_HART_BASS1_15 = 586,
+ GNX_AMP_CAB_BASIC_BASS1_15 = 587,
+ GNX_AMP_CAB_PORTA_BASS1_15 = 588,
+ GNX_AMP_CAB_REFLEX1_18 = 589,
+ GNX_AMP_CAB_SOLAR_BASS2_15 = 590,
+ GNX_AMP_CAB_DE_BASS4_10 = 591,
+ GNX_AMP_CAB_ASH_BASS4_10 = 592,
+ GNX_AMP_CAB_GOLIATH_BASS4_10 = 593,
+ GNX_AMP_CAB_HART_BASS4_10 = 594,
+ GNX_AMP_CAB_SVT_BASS8_10 = 595,
+};
+
+#define EQ_TYPE 3202
+#define EQ_ON_OFF 3212
+#define EQ_POSITION 24
+#define EQ_POSITION_B 25
+
+#define EQ_BASS 3203
+#define EQ_MID 3204
+#define EQ_MID_HZ 3206
+#define EQ_TREBLE 3205
+#define EQ_PRESENCE 3207
+#define EQ_TREBLE_HZ 3211
+#define EQ_LOW_LEVEL 3203
+#define EQ_MID_LEVEL 3204
+#define EQ_HIGH_LEVEL 3205
+#define EQ_LOW_FREQ 3213
+#define EQ_MID_FREQ 3214
+#define EQ_HIGH_FREQ 3215
+#define EQ_LOW_BANDWIDTH 3216
+#define EQ_MID_BANDWIDTH 3217
+#define EQ_HIGH_BANDWIDTH 3218
+
+enum {
+ NOISEGATE_GATE = 768,
+ NOISEGATE_SWELL = 769
+};
+
+#define NOISEGATE_TYPE 704
+#define NOISEGATE_ON_OFF 705
+#define NOISEGATE_POSITION 12
+
+#define GNX3K_GATE_ATTACK 706
+
+/* available only in Gate mode */
+#define NOISEGATE_GATE_TRESHOLD 710
+/* available only in Swell mode */
+#define NOISEGATE_SWELL_SENS 711
+/* available in both Gate and Swell modes */
+#define NOISEGATE_ATTACK 712
+#define NOISEGATE_RELEASE 713
+#define NOISEGATE_ATTN 714
+
+enum {
+ GNX3K_MOD_TYPE_CHORUS = 857,
+ GNX3K_MOD_TYPE_FLANGER = 858,
+ GNX3K_MOD_TYPE_TRIGFLANGER = 859,
+ GNX3K_MOD_TYPE_PHASER = 860,
+ GNX3K_MOD_TYPE_TRIGPHASER = 861,
+ GNX3K_MOD_TYPE_TREMOLO = 862,
+ GNX3K_MOD_TYPE_PANNER = 863,
+ GNX3K_MOD_TYPE_VIBRATO = 864,
+ GNX3K_MOD_TYPE_ROTARY = 865,
+ GNX3K_MOD_TYPE_AUTOYA = 866,
+ GNX3K_MOD_TYPE_YAYA = 867,
+ GNX3K_MOD_TYPE_SYNTHTALK = 868,
+ GNX3K_MOD_TYPE_ENVELOPE = 869,
+ GNX3K_MOD_TYPE_DETUNE = 870,
+ GNX3K_MOD_TYPE_PITCH = 871,
+ GNX3K_MOD_TYPE_UNOVIBE = 880,
+};
+
+enum {
+ CHORUS_TYPE_CE = 0x37B,
+ CHORUS_TYPE_TC = 0x37C,
+ CHORUS_TYPE_DUAL = 0x379,
+ CHORUS_TYPE_GLISTEN = 0x392,
+ CHORUS_TYPE_MULTI = 0x37a,
+ CHORUS_TYPE_VOO_DOO = 0x396,
+ CHORUS_TYPE_CLONE = 0x397,
+ CHORUS_TYPE_FLANGER = 0x37d,
+ CHORUS_TYPE_TRIGGERED_FLANGER = 0x37e,
+ CHORUS_TYPE_FLTFLANGER = 0x398,
+ CHORUS_TYPE_MXR_FLANGER = 0x37f,
+ CHORUS_TYPE_EH_FLANGER = 0x380,
+ CHORUS_TYPE_AD_FLANGER = 0x393,
+ CHORUS_TYPE_PHASER = 0x381,
+ CHORUS_TYPE_TRIGGERED_PHASER = 0x382,
+ CHORUS_TYPE_MX_PHASER = 0x383,
+ CHORUS_TYPE_EH_PHASER = 0x384,
+ CHORUS_TYPE_VIBRATO = 0x360,
+ CHORUS_TYPE_ROTARY = 0x361,
+ CHORUS_TYPE_VIBROPAN = 0x38f,
+ CHORUS_TYPE_UNOVIBE = 0x390,
+ CHORUS_TYPE_TREMOLO = 0x35e,
+ CHORUS_TYPE_SCATTER_TREM = 0x394,
+ CHORUS_TYPE_OPTO_TREMOLO = 0x388,
+ CHORUS_TYPE_BIAS_TREMOLO = 0x389,
+ CHORUS_TYPE_PANNER = 0x35f,
+ CHORUS_TYPE_ENVELOPE = 0x38a,
+ CHORUS_TYPE_FX25 = 0x38e,
+ CHORUS_TYPE_AUTOYA = 0x38b,
+ CHORUS_TYPE_YAYA = 0x38c,
+ CHORUS_TYPE_SYNTH_TALK = 0x391,
+ CHORUS_TYPE_STEP_FILTER = 0x38d,
+ CHORUS_TYPE_SAMPLE_HOLD = 0x395,
+ CHORUS_TYPE_WHAMMY = 0x540,
+ CHORUS_TYPE_PITCH_SHIFT = 0x543,
+ CHORUS_TYPE_DETUNE = 0x542,
+ CHORUS_TYPE_IPS = 0x541,
+ CHORUS_TYPE_OCTAVER = 0x385,
+};
+
+#define CHORUSFX_TYPE 768
+#define CHORUSFX_ON_OFF 769
+#define CHORUSFX_PRE_POST 770
+#define CHORUSFX_POSITION 14
+#define CHORUSFX_PRE 1543
+#define CHORUSFX_POST 1544
+
+#define CHORUS_SPEED 837
+#define CHORUS_DEPTH 838
+#define CHORUS_PREDELAY 839
+
+#define CHORUS_WIDTH 848
+#define CHORUS_INTENSITY 849
+
+#define CHORUS_LEVEL 836
+#define CHORUS_WAVE 840
+#define CHORUS_BALANCE 841
+
+#define CHORUS_RATE 850
+
+#define FLANGER_SPEED 902
+#define FLANGER_DEPTH 903
+#define FLANGER_REGEN 904
+#define FLANGER_LEVEL 901
+#define FLANGER_WAVE 905
+#define FLANGER_BALANCE 906
+
+#define TRIG_FLANGER_SPEED 1030
+#define TRIG_FLANGER_SENS 1031
+#define TRIG_FLANGER_LFO_START 1028
+#define TRIG_FLANGER_MIX 1029
+#define TRIG_FLANGER_LEVEL 1032
+
+#define FLTFLANGER_FREQ 922
+
+#define MXR_FLANGER_WIDTH 914
+#define MXR_FLANGER_MANUAL 917
+
+#define EH_FLANGER_RATE 918
+#define EH_FLANGER_RANGE 919
+#define EH_FLANGER_COLOR 916
+
+#define AD_FLANGER_ENHANCE 920
+#define AD_FLANGER_HARMONICS 921
+
+#define PHASER_SPEED 962
+#define PHASER_DEPTH 963
+#define PHASER_REGEN 966
+#define PHASER_LEVEL 965
+#define PHASER_WAVE 967
+#define PHASER_BALANCE 968
+
+#define TRIG_PHASER_SPEED 1094
+#define TRIG_PHASER_SENS 1095
+#define TRIG_PHASER_LFO_START 1092
+#define TRIG_PHASER_MIX 1093
+#define TRIG_PHASER_LEVEL 1096
+
+#define MX_PHASER_INTENSITY 976
+
+#define EH_PHASER_RATE 979
+#define EH_PHASER_COLOR 977
+
+#define VIBRATO_SPEED 1284
+#define VIBRATO_DEPTH 1285
+#define VIBRATO_WAVEFORM 1286
+
+#define ROTARY_SPEED 1346
+#define ROTARY_INTENSITY 1348
+#define ROTARY_MIX 1349
+#define ROTARY_DOPPLER 1350
+#define ROTARY_CROSSOVER 1351
+#define ROTARY_BALANCE 1352
+
+#define VIBROPAN_SPEED 1314
+#define VIBROPAN_DEPTH 1315
+#define VIBROPAN_VIBRA 1316
+#define VIBROPAN_WAVE 1317
+
+#define UNOVIBE_PEDAL_SPEED 2884
+#define UNOVIBE_INTENSITY 2883
+#define UNOVIBE_CHORUS_VIBRATO 2882
+#define UNOVIBE_VOLUME 2885
+
+#define TREMOLO_SPEED 1156
+#define TREMOLO_DEPTH 1155
+#define TREMOLO_WAVE 1157
+
+#define PANNER_SPEED 1220
+#define PANNER_DEPTH 1219
+#define PANNER_WAVE 1221
+
+#define ENVELOPE_MIX 1604
+#define ENVELOPE_SENSITIVITY 1606
+#define ENVELOPE_RANGE 1605
+#define ENVELOPE_BALANCE 1607
+#define ENVELOPE_BLEND 1608
+
+#define GNX3K_AUTOYA_RANGE 1476
+#define AUTOYA_MIX 1477
+#define AUTOYA_SPEED 1478
+#define AUTOYA_DEPTH 1479
+#define AUTOYA_BALANCE 1481
+#define AUTOYA_INTENSITY 1482
+#define AUTOYA_RANGE 1483
+
+#define YAYA_PEDAL 1410
+#define GNX3K_YAYA_RANGE 1412
+#define YAYA_MIX 1413
+#define YAYA_DEPTH 1414
+#define YAYA_BALANCE 1416
+#define YAYA_INTENSITY 1417
+#define YAYA_RANGE 1418
+
+#define SYNTH_TALK_ATTACK 1542
+#define GNX3K_SYNTH_TALK_RELEASE 1543
+#define SYNTH_TALK_RELEASE 1547
+#define SYNTH_TALK_SENS 1544
+#define SYNTH_TALK_VOX 1540
+#define SYNTH_TALK_BALANCE 1545
+
+#define STEP_FILTER_SPEED 3010
+#define STEP_FILTER_INTENSITY 3011
+
+#define SAMPLE_HOLD_SPEED 3012
+#define SAMPLE_HOLD_INTENSITY 3013
+
+#define WHAMMY_AMOUNT 1797
+#define WHAMMY_PEDAL 1795
+#define WHAMMY_MIX 1796
+
+#define PITCH_AMOUNT 1730
+#define PITCH_BALANCE 1733
+#define PITCH_MIX 1745
+
+#define DETUNE_LEVEL 1667
+#define DETUNE_AMOUNT 1668
+#define DETUNE_BALANCE 1669
+
+#define IPS_SHIFT_AMOUNT 2754
+#define IPS_KEY 2756
+#define IPS_SCALE 2755
+#define IPS_LEVEL 2757
+
+#define OCTAVER_OCTAVE1 1746
+#define OCTAVER_OCTAVE2 1747
+#define OCTAVER_DRY_LEVEL 1748
+
+enum {
+ DELAY_TYPE_ANALOG = 1046,
+ DELAY_TYPE_DIGITAL = 1045,
+ DELAY_TYPE_MODULATED = 1047,
+ DELAY_TYPE_PONG = 1048,
+ DELAY_TYPE_TAPE = 1049,
+ DELAY_TYPE_ECHOPLEX = 1050,
+ DELAY_TYPE_DM = 1051,
+
+ DELAY_RP500_TYPE_DIGITAL = 1052,
+ DELAY_RP500_TYPE_ANALOG = 1053,
+ DELAY_RP500_TYPE_DM = 1058,
+ DELAY_RP500_TYPE_ECHOPLEX = 1057,
+ DELAY_RP500_TYPE_MODULATED = 1054,
+ DELAY_RP500_TYPE_PONG = 1055,
+ DELAY_RP500_TYPE_REVERSE = 1064,
+ DELAY_RP500_TYPE_TAPE = 1056,
+
+ DELAY_RP1000_TYPE_LO_FI = 1065,
+ DELAY_RP1000_TYPE_2_TAP = 1066,
+
+ DELAY_GNX3K_TYPE_MONO = 1027,
+ DELAY_GNX3K_TYPE_PINGPONG = 1028,
+ DELAY_GNX3K_TYPE_ANALOG = 1029,
+ DELAY_GNX3K_TYPE_ANAPONG = 1030,
+ DELAY_GNX3K_TYPE_SPREAD = 1031,
+};
+
+#define DELAY_TYPE 1856
+#define DELAY_ON_OFF 1857
+#define DELAY_POSITION 15
+
+#define DELAY_TIME 1888
+
+#define DELAY_MULTIPLIER 1904
+#define DELAY_3_QUARTR 2180
+#define DELAY_EIGHT 2179
+#define DELAY_DOTEIGHT 2178
+#define DELAY_QUARTER 2177
+#define DELAY_HALF 2176
+
+#define DELAY_TAPE_WOW 1891
+#define DELAY_TAPE_FLUTTER 1892
+
+#define DELAY_LEVEL 1860
+#define DELAY_REPEATS 1863
+#define DELAY_TAP_TIME 1868
+#define DELAY_DUCK_THRESH 1889
+#define DELAY_DUCK_LEVEL 1890
+#define DELAY_REPEAT_RATE 1898
+#define DELAY_REPEAT_RATE_DM 1894
+#define DELAY_ECHO 1895
+#define DELAY_INTENSITY 1896
+#define DELAY_ECHOPLEX_TIME 1897
+#define DELAY_TIME_0_760 1899
+#define DELAY_VOLUME 1893
+#define DELAY_REPEATS_0_99 1874
+#define DELAY_DEPTH 1873
+#define DELAY_TAP_TIME_0_4990 1900
+#define DELAY_MIX 1902
+#define DELAY_TIME_0_4650 1901
+#define DELAY_TAP_RATIO 1905
+
+#define GNX3K_DELAY_TIME 1862
+#define GNX3K_DELAY_FEEDBACK 1863
+#define GNX3K_DELAY_DUCK_THRESH 1864
+#define GNX3K_DELAY_DUCK_ATTEN 1865
+#define GNX3K_DELAY_BALANCE 1866
+#define GNX3K_DELAY_SPREAD 1867
+
+enum {
+ GNX3K_REVERB_TYPE_STUDIO = 1107,
+ GNX3K_REVERB_TYPE_ROOM = 1108,
+ GNX3K_REVERB_TYPE_CLUB = 1109,
+ GNX3K_REVERB_TYPE_PLATE = 1110,
+ GNX3K_REVERB_TYPE_HALL = 1111,
+ GNX3K_REVERB_TYPE_AMPHITHEATER = 1112,
+ GNX3K_REVERB_TYPE_CHURCH = 1113,
+ GNX3K_REVERB_TYPE_GARAGE = 1114,
+ GNX3K_REVERB_TYPE_ARENA = 1115,
+ GNX3K_REVERB_TYPE_SPRING = 1116,
+
+ REVERB_TYPE_TWIN = 1146,
+ REVERB_TYPE_LEX_AMBIENCE = 1150,
+ REVERB_TYPE_LEX_STUDIO = 1149,
+ REVERB_TYPE_LEX_ROOM = 1148,
+ REVERB_TYPE_LEX_HALL = 1147,
+ REVERB_TYPE_EMT240_PLATE = 1151
+};
+
+#define REVERB_TYPE 1920
+#define REVERB_ON_OFF 1921
+#define REVERB_POSITION 16
+
+#define REVERB_PREDELAY 1922
+#define REVERB_DAMPING 1924
+#define REVERB_DECAY 1927
+#define REVERB_BALANCE 1928
+#define REVERB_LIVELINESS 1933
+#define REVERB_LEVEL 1925
+
+#define EXP_TYPE 8194
+#define EXP_POSITION 19
+
+#define EXP_MIN 8195
+#define EXP_MAX 8196
+#define LFO_TYPE 8258
+#define LFO1_POSITION 22
+#define LFO2_POSITION 23
+
+#define LIBRARY_TONE 8704
+#define LIBRARY_EFFECTS 8705
+#define EFFECTS_LEVEL 8706
+
+#define LIBRARY_POSITION 25
+
+enum {
+ TONE_LIB_OVERDRIVE = 1793,
+ TONE_LIB_ROCK1 = 1794,
+ TONE_LIB_ROCK2 = 1795,
+ TONE_LIB_BLUES1 = 1796,
+ TONE_LIB_BLUES2 = 1797,
+ TONE_LIB_METAL1 = 1798,
+ TONE_LIB_METAL2 = 1799,
+ TONE_LIB_COUNTRY1 = 1800,
+ TONE_LIB_COUNTRY2 = 1801,
+ TONE_LIB_WARM_DRIVE = 1802,
+ TONE_LIB_CRUNCH = 1803,
+ TONE_LIB_TEXAS_TONE = 1804,
+ TONE_LIB_ROCKABILLY = 1805,
+ TONE_LIB_SOLO1 = 1806,
+ TONE_LIB_SOLO2 = 1807,
+ TONE_LIB_ROCKWAH = 1808,
+ TONE_LIB_CHUNKY = 1809,
+ TONE_LIB_SMOOTH = 1810,
+ TONE_LIB_HEAVY = 1811,
+ TONE_LIB_CLEAN1 = 1812,
+ TONE_LIB_CLEAN2 = 1813,
+ TONE_LIB_BRITISH1 = 1814,
+ TONE_LIB_BRITISH2 = 1815,
+ TONE_LIB_AMERICAN1 = 1816,
+ TONE_LIB_AMERICAN2 = 1817,
+ TONE_LIB_TUBE_DRIVE = 1818,
+ TONE_LIB_DISTORTION = 1819,
+ TONE_LIB_SCOOPED = 1820,
+ TONE_LIB_PUNCHY = 1821,
+ TONE_LIB_BRIGHT_CLEAN = 1822,
+
+ /* setting LIBRARY_TONE to this option seems to crash device */
+ TONE_LIB_CUSTOM = 1792
+};
+
+enum {
+ EFFECTS_LIB_CHORUS = 1857,
+ EFFECTS_LIB_PHASER = 1858,
+ EFFECTS_LIB_FLANGER = 1859,
+ EFFECTS_LIB_PITCH = 1860,
+ EFFECTS_LIB_TREMOLO = 1861,
+ EFFECTS_LIB_ROTARY = 1862,
+ EFFECTS_LIB_ENVELOPE = 1863,
+ EFFECTS_LIB_DIGITAL = 1864,
+ EFFECTS_LIB_ANALOG = 1865,
+ EFFECTS_LIB_PONG = 1866,
+ EFFECTS_LIB_MOD = 1867,
+ EFFECTS_LIB_TAPE = 1868,
+ EFFECTS_LIB_HALL = 1869,
+ EFFECTS_LIB_PLATE = 1870,
+ EFFECTS_LIB_SPRING = 1871,
+ EFFECTS_LIB_CHORUS_DIGITAL = 1872,
+ EFFECTS_LIB_CHORUS_DELAY_REVERB = 1873,
+ EFFECTS_LIB_FLANGER_ANALOG = 1874,
+ EFFECTS_LIB_PHASER_TAPE = 1875,
+ EFFECTS_LIB_PHASER_MOD = 1876,
+ EFFECTS_LIB_PHASER_ROOM = 1877,
+ EFFECTS_LIB_DIGITAL_HALL = 1878,
+ EFFECTS_LIB_ANALOG_SPRING = 1879,
+ EFFECTS_LIB_CHORUS_HALL = 1880,
+ EFFECTS_LIB_PONG_HALL = 1881,
+ EFFECTS_LIB_TAPE_SPRING = 1882,
+ EFFECTS_LIB_TREMOLO_TAPE = 1883,
+ EFFECTS_LIB_PITCH_DIGITAL = 1884,
+ EFFECTS_LIB_MOD_PLATE = 1885,
+ EFFECTS_LIB_ROTARY_TAPE = 1886,
+
+ /* setting EFFECTS_LIBRARY to this option seems to crash device */
+ EFFECTS_LIB_CUSTOM = 1856
+};
+
+#define USB_POSITION 0
+#define USB_AUDIO_PLAYBACK_MIX 12297
+#define USB_AUDIO_LEVEL 12307
+
+#define GUI_MODE_ON_OFF 12298
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+typedef enum {
+ PRESETS_SYSTEM = 0,
+ PRESETS_USER = 1,
+ PRESETS_ARTIST = 2,
+
+ /* Version 1 and later */
+ PRESETS_MEDIA_CARD = 3,
+ PRESETS_EDIT_BUFFER = 4, /* Current preset edit buffer, index must be 0 */
+ PRESETS_FACTORY2 = 5,
+
+ /* Version 2 and later */
+ PRESETS_EXTERNAL = 6
+} PresetBank;
+
+typedef enum {
+ /* Version 0 only */
+ NOTIFY_PRESET_LOADED = 0,
+ NOTIFY_PRESET_STORED = 1,
+
+ NOTIFY_MODIFIER_GROUP_CHANGED = 2,
+
+ /* Version 1 */
+ NOTIFY_PRESET_MOVED = 3,
+ NOTIFY_OBJECT_MOVED = 4,
+ NOTIFY_OBJECT_RENAMED = 5,
+ NOTIFY_MEDIA_CARD_PRESENT_CHANGED = 6,
+ NOTIFY_ALL_GLOBALS_CHANGED = 7,
+ NOTIFY_PRESET_INDEX_TABLE_CHANGED = 8,
+ NOTIFY_PRESET_RENAMED = 9
+} NotifyCode;
+
+typedef enum {
+ REQUEST_WHO_AM_I = 0x01,
+ RECEIVE_WHO_AM_I = 0x02,
+
+ REQUEST_DEVICE_CONFIGURATION = 0x08,
+ RECEIVE_DEVICE_CONFIGURATION = 0x09,
+
+ REQUEST_GLOBAL_PARAMETERS = 0x10,
+ RECEIVE_GLOBAL_PARAMETERS = 0x11,
+
+ REQUEST_BULK_DUMP = 0x18,
+ RECEIVE_BULK_DUMP_START = 0x19,
+ RECEIVE_BULK_DUMP_END = 0x1B,
+
+ REQUEST_PRESET_NAMES = 0x21,
+ RECEIVE_PRESET_NAMES = 0x22,
+
+ REQUEST_PRESET_NAME = 0x28,
+ RECEIVE_PRESET_NAME = 0x29,
+
+ REQUEST_PRESET = 0x2A,
+ RECEIVE_PRESET_START = 0x2B,
+ RECEIVE_PRESET_END = 0x2C,
+ RECEIVE_PRESET_PARAMETERS = 0x2D,
+
+ LOAD_EDIT_BUFFER_PRESET = 0x38, /* version 0 only
+ use move preset in later versions */
+
+ MOVE_PRESET = 0x39,
+
+ REQUEST_MODIFIER_LINKABLE_LIST = 0x3A,
+ RECEIVE_MODIFIER_LINKABLE_LIST = 0x3B,
+
+ REQUEST_PARAMETER_VALUE = 0x40,
+ RECEIVE_PARAMETER_VALUE = 0x41,
+
+ /* version 1 and later */
+ REQUEST_OBJECT_NAMES = 0x50,
+ RECEIVE_OBJECT_NAMES = 0x51,
+ REQUEST_OBJECT_NAME = 0x52,
+ RECEIVE_OBJECT_NAME = 0x53,
+ REQUEST_OBJECT = 0x54,
+ RECEIVE_OBJECT = 0x55,
+ MOVE_OBJECT = 0x56,
+ DELETE_OBJECT = 0x57,
+ REQUEST_TABLE = 0x5A,
+ RECEIVE_TABLE = 0x5B,
+
+ RECEIVE_DEVICE_NOTIFICATION = 0x70,
+
+ ACK = 0x7E,
+ NACK = 0x7F
+} MessageID;
+
+typedef enum {
+ SECTION_GENETX_AMP = 0,
+ SECTION_GENETX_CABINET = 1,
+ SECTION_DRUM_PATTERN = 2,
+ SECTION_DRUM_KIT = 3,
+ SECTION_DRUM_SAMPLES = 4,
+ SECTION_SONG = 5,
+ SECTION_FOOTSWITCH = 6,
+ SECTION_GENETX2_AMP = 7,
+ SECTION_GENETX2_CABINET = 8,
+ SECTION_DEVICE_GUID = 9,
+ SECTION_DEVICE_NAME = 10,
+} SectionID;
+
+typedef struct {
+ int id;
+ int position;
+ int value;
+} SettingParam;
+
+enum {
+ GENETX_VERSION_1,
+ GENETX_VERSION_2
+};
+
+enum {
+ GENETX_TYPE_NOT_SET = -1,
+ GENETX_TYPE_AMP,
+ GENETX_TYPE_CABINET
+};
+
+enum {
+ GENETX_CHANNEL1 = 0,
+ GENETX_CHANNEL2 = 1,
+ GENETX_CHANNEL1_CUSTOM = 2,
+ GENETX_CHANNEL2_CUSTOM = 3,
+ GENETX_CHANNEL_CURRENT = 4
+} ChannelBankIndex;
+
+typedef struct {
+ int version;
+ int type;
+ int channel;
+ gchar *name;
+ GString *data;
+} SettingGenetx;
+
+void send_message(gint procedure, gchar *data, gint len);
+MessageID get_message_id(GString *msg);
+void append_value(GString *msg, guint value);
+GString *get_message_by_id(MessageID id);
+SettingParam *setting_param_new();
+SettingParam *setting_param_new_from_data(gchar *str, gint *len);
+SettingGenetx *setting_genetx_new();
+void setting_genetx_free(SettingGenetx *genetx);
+void setting_param_free(SettingParam *param);
+SectionID get_genetx_section_id(gint version, gint type);
+void set_option(guint id, guint position, guint value);
+void send_object(SectionID section, guint bank, guint index,
+ gchar *name, GString *data);
+void send_preset_parameters(GList *params);
+void switch_preset(guint bank, guint x);
+void store_preset_name(int x, const gchar *name);
+void set_preset_level(int level);
+GStrv query_preset_names(gchar bank);
+void message_list_free(GList *list);
+GList *get_current_preset();
+
+#endif /* GDIGI_H */
diff --git a/gtkknob.c b/gtkknob.c
new file mode 100644
index 0000000..d64a467
--- /dev/null
+++ b/gtkknob.c
@@ -0,0 +1,919 @@
+/*****************************************************************************
+ *
+ * Most of this code comes from gAlan 0.2.0, copyright (C) 1999
+ * Tony Garnock-Jones, with modifications from Sean Bolton,
+ * copyright (C) 2004, William Weston copyright (C) 2007,
+ * Pete Shorthose copyright (C) 2007, and Tomasz Moń,
+ * copyright (C) 2009
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+
+#include <math.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+#include "gtkknob.h"
+
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846 /* pi */
+#endif
+#ifndef M_1_PI
+# define M_1_PI 0.31830988618379067154 /* 1/pi */
+#endif
+
+
+#define SCROLL_DELAY_LENGTH 250
+#define KNOB_SIZE 32 /* this should really be read from the knob image */
+
+#define STATE_IDLE 0
+#define STATE_PRESSED 1
+#define STATE_DRAGGING 2
+
+static void gtk_knob_class_init(GtkKnobClass *klass);
+static void gtk_knob_init(GtkKnob *knob);
+static void gtk_knob_destroy(GtkObject *object);
+static void gtk_knob_realize(GtkWidget *widget);
+static void gtk_knob_size_request(GtkWidget *widget, GtkRequisition *requisition);
+static void gtk_knob_size_allocate(GtkWidget *widget, GtkAllocation *allocation);
+static gint gtk_knob_expose(GtkWidget *widget, GdkEventExpose *event);
+static gint gtk_knob_scroll(GtkWidget *widget, GdkEventScroll *event);
+static gint gtk_knob_button_press(GtkWidget *widget, GdkEventButton *event);
+static gint gtk_knob_button_release(GtkWidget *widget, GdkEventButton *event);
+static gint gtk_knob_key_press(GtkWidget *widget, GdkEventKey *event);
+static gint gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event);
+static gint gtk_knob_timer(GtkKnob *knob);
+
+static void gtk_knob_update_mouse_update(GtkKnob *knob);
+static void gtk_knob_update_mouse(GtkKnob *knob, gint x, gint y, gboolean step);
+static void gtk_knob_update(GtkKnob *knob);
+static void gtk_knob_adjustment_changed(GtkAdjustment *adjustment, gpointer data);
+static void gtk_knob_adjustment_value_changed(GtkAdjustment *adjustment, gpointer data);
+
+/* Local data */
+
+static GtkWidgetClass *parent_class = NULL;
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_get_type()
+ *
+ *****************************************************************************/
+GType
+gtk_knob_get_type(void) {
+ static GType knob_type = 0;
+
+ if (!knob_type) {
+ static const GTypeInfo knob_info = {
+ sizeof (GtkKnobClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) gtk_knob_class_init,
+ NULL,
+ NULL,
+ sizeof (GtkKnob),
+ 0,
+ (GInstanceInitFunc) gtk_knob_init,
+ };
+ knob_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkKnob", &knob_info, 0);
+ }
+
+ return knob_type;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_class_init()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_class_init (GtkKnobClass *klass) {
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) klass;
+ widget_class = (GtkWidgetClass*) klass;
+
+ parent_class = g_type_class_peek_parent(klass);
+
+ object_class->destroy = gtk_knob_destroy;
+
+ widget_class->realize = gtk_knob_realize;
+ widget_class->expose_event = gtk_knob_expose;
+ widget_class->size_request = gtk_knob_size_request;
+ widget_class->size_allocate = gtk_knob_size_allocate;
+ widget_class->scroll_event = gtk_knob_scroll;
+ widget_class->button_press_event = gtk_knob_button_press;
+ widget_class->button_release_event = gtk_knob_button_release;
+ widget_class->key_press_event = gtk_knob_key_press;
+ widget_class->motion_notify_event = gtk_knob_motion_notify;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_init()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_init (GtkKnob *knob) {
+ knob->policy = GTK_UPDATE_CONTINUOUS;
+ knob->state = STATE_IDLE;
+ knob->saved_x = 0;
+ knob->saved_y = 0;
+ knob->timer = 0;
+ knob->anim = NULL;
+ knob->mask = NULL;
+ knob->mask_gc = NULL;
+ knob->red_gc = NULL;
+ knob->old_value = 0.0;
+ knob->old_lower = 0.0;
+ knob->old_upper = 0.0;
+ knob->adjustment = NULL;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_new()
+ *
+ *****************************************************************************/
+GtkWidget *
+gtk_knob_new(GtkAdjustment *adjustment, GtkKnobAnim *anim) {
+ GtkKnob *knob;
+
+ g_return_val_if_fail (anim != NULL, NULL);
+ g_return_val_if_fail (GDK_IS_PIXBUF (anim->pixbuf), NULL);
+
+ knob = g_object_new (gtk_knob_get_type (), NULL);
+
+ gtk_knob_set_animation (knob, anim);
+
+ if (!adjustment) {
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0);
+ }
+
+ gtk_knob_set_adjustment (knob, adjustment);
+
+ return GTK_WIDGET (knob);
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_destroy()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_destroy(GtkObject *object) {
+ GtkKnob *knob;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_KNOB (object));
+
+ knob = GTK_KNOB (object);
+
+ gtk_knob_set_adjustment (knob, NULL);
+ /* FIXME: needs ref counting for automatic GtkKnobAnim cleanup
+ if (knob->anim) {
+ gtk_knob_anim_unref (knob->anim);
+ knob->anim = NULL;
+ }
+ */
+
+ if (knob->mask) {
+ g_object_unref (knob->mask);
+ knob->mask = NULL;
+ }
+
+ if (knob->mask_gc) {
+ g_object_unref (knob->mask_gc);
+ knob->mask_gc = NULL;
+ }
+ if (knob->red_gc) {
+ g_object_unref (knob->red_gc);
+ knob->red_gc = NULL;
+ }
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy) {
+ (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_get_adjustment()
+ *
+ *****************************************************************************/
+GtkAdjustment*
+gtk_knob_get_adjustment(GtkKnob *knob) {
+
+ g_return_val_if_fail (knob != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_KNOB (knob), NULL);
+
+ return knob->adjustment;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_set_update_policy()
+ *
+ *****************************************************************************/
+void
+gtk_knob_set_update_policy(GtkKnob *knob, GtkUpdateType policy) {
+
+ g_return_if_fail (knob != NULL);
+ g_return_if_fail (GTK_IS_KNOB (knob));
+
+ knob->policy = policy;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_set_adjustment()
+ *
+ *****************************************************************************/
+void
+gtk_knob_set_adjustment(GtkKnob *knob, GtkAdjustment *adjustment) {
+
+ g_return_if_fail (knob != NULL);
+ g_return_if_fail (GTK_IS_KNOB (knob));
+
+ if (knob->adjustment) {
+ g_signal_handlers_disconnect_matched(knob->adjustment,
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL,
+ knob);
+ g_object_unref (knob->adjustment);
+ }
+
+ knob->adjustment = adjustment;
+ if (adjustment) {
+ g_object_ref_sink (adjustment);
+
+ g_signal_connect (adjustment, "changed",
+ G_CALLBACK(gtk_knob_adjustment_changed),
+ knob);
+ g_signal_connect (adjustment, "value_changed",
+ G_CALLBACK(gtk_knob_adjustment_value_changed),
+ knob);
+
+ knob->old_value = adjustment->value;
+ knob->old_lower = adjustment->lower;
+ knob->old_upper = adjustment->upper;
+
+ gtk_knob_update (knob);
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_realize()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_realize(GtkWidget *widget) {
+ GtkKnob *knob;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ GdkColor color = { 0, 0xffff, 0, 0 };
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_KNOB (widget));
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+ knob = GTK_KNOB (widget);
+
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask =
+ gtk_widget_get_events (widget) |
+ GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (widget->parent->window,
+ &attributes, attributes_mask);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+
+ gdk_window_set_user_data (widget->window, widget);
+
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+ knob->mask_gc = gdk_gc_new (widget->window);
+ gdk_gc_copy (knob->mask_gc, widget->style->bg_gc[GTK_STATE_NORMAL]);
+ gdk_gc_set_clip_mask (knob->mask_gc, knob->mask);
+
+ knob->red_gc = gdk_gc_new (widget->window);
+ gdk_gc_copy (knob->red_gc, widget->style->bg_gc[GTK_STATE_NORMAL]);
+ gdk_colormap_alloc_color (attributes.colormap, &color, FALSE, TRUE);
+ gdk_gc_set_foreground (knob->red_gc, &color);
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_size_request()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_size_request (GtkWidget *widget, GtkRequisition *requisition) {
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_KNOB (widget));
+
+ requisition->width = GTK_KNOB (widget)->width;
+ requisition->height = GTK_KNOB (widget)->height;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_size_allocate()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_size_allocate (GtkWidget *widget, GtkAllocation *allocation) {
+ GtkKnob *knob;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_KNOB (widget));
+ g_return_if_fail (allocation != NULL);
+
+ widget->allocation = *allocation;
+ knob = GTK_KNOB (widget);
+
+ if (GTK_WIDGET_REALIZED (widget)) {
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_expose()
+ *
+ *****************************************************************************/
+static gint
+gtk_knob_expose(GtkWidget *widget, GdkEventExpose *event) {
+ GtkKnob *knob;
+ gfloat dx, dy;
+ gint frames;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
+
+ if (event->count > 0)
+ return FALSE;
+
+ knob = GTK_KNOB (widget);
+
+ frames = ((knob->anim->width / knob->anim->frame_width) - 1);
+ dx = knob->adjustment->value - knob->adjustment->lower; /* value, from 0 */
+ dy = knob->adjustment->upper - knob->adjustment->lower; /* range */
+
+ dx = (int)(frames * dx / dy) * knob->width; /* check this for height != width */
+
+ gdk_draw_pixbuf (widget->window, knob->mask_gc, knob->anim->pixbuf,
+ dx, 0, 0, 0, knob->width, knob->height,
+ GDK_RGB_DITHER_NONE, 0, 0);
+
+ if (GTK_WIDGET_HAS_FOCUS(widget)) {
+ gtk_paint_focus (widget->style, widget->window, widget->state,
+ NULL, widget, NULL, 0, 0,
+ widget->allocation.width, widget->allocation.height);
+ }
+
+ return FALSE;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_scroll()
+ *
+ *****************************************************************************/
+static gint
+gtk_knob_scroll(GtkWidget *widget, GdkEventScroll *event) {
+ GtkKnob *knob;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
+
+ knob = GTK_KNOB (widget);
+
+ switch (event->direction) {
+ case GDK_SCROLL_UP:
+ knob->adjustment->value += knob->adjustment->step_increment;
+ g_signal_emit_by_name (knob->adjustment, "value_changed");
+ break;
+ case GDK_SCROLL_DOWN:
+ knob->adjustment->value -= knob->adjustment->step_increment;
+ g_signal_emit_by_name (knob->adjustment, "value_changed");
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_button_press()
+ *
+ *****************************************************************************/
+static gint
+gtk_knob_button_press(GtkWidget *widget, GdkEventButton *event) {
+ GtkKnob *knob;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
+
+ knob = GTK_KNOB (widget);
+
+ switch (knob->state) {
+ case STATE_IDLE:
+ switch (event->button) {
+ case 1:
+ case 3:
+ if (!GTK_WIDGET_HAS_FOCUS(widget))
+ gtk_widget_grab_focus(widget);
+ knob->state = STATE_PRESSED;
+ knob->saved_x = event->x;
+ knob->saved_y = event->y;
+ break;
+ case 2:
+ knob->adjustment->value = floor ((knob->adjustment->lower +
+ knob->adjustment->upper + 1.0)
+ * 0.5);
+ g_signal_emit_by_name (knob->adjustment, "value_changed");
+ break;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_button_release()
+ *
+ *****************************************************************************/
+static gint
+gtk_knob_button_release(GtkWidget *widget, GdkEventButton *event) {
+ GtkKnob *knob;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
+
+ knob = GTK_KNOB (widget);
+
+ switch (knob->state) {
+
+ case STATE_PRESSED:
+ knob->state = STATE_IDLE;
+ break;
+
+ case STATE_DRAGGING:
+ knob->state = STATE_IDLE;
+
+ switch (event->button) {
+ case 1:
+ case 3:
+ if (knob->policy != GTK_UPDATE_CONTINUOUS
+ && knob->old_value != knob->adjustment->value)
+ {
+ g_signal_emit_by_name (knob->adjustment, "value_changed");
+ }
+ break;
+ }
+
+ break;
+ }
+
+ return FALSE;
+}
+
+static gint gtk_knob_key_press(GtkWidget *widget, GdkEventKey *event)
+{
+ GtkKnob *knob;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (GTK_KNOB (widget)->adjustment), FALSE);
+
+ knob = GTK_KNOB (widget);
+
+ switch (event->keyval) {
+
+ case GDK_Up:
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ gtk_adjustment_set_value (knob->adjustment,
+ knob->old_value + knob->adjustment->step_increment);
+ return TRUE;
+ }
+ return FALSE;
+
+ case GDK_Down:
+ if (GTK_WIDGET_HAS_FOCUS (widget))
+ {
+ gtk_adjustment_set_value (knob->adjustment,
+ knob->old_value - knob->adjustment->step_increment);
+ return TRUE;
+ }
+ return FALSE;
+ default:
+ break;
+ }
+
+ return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
+}
+
+/*****************************************************************************
+ *
+ * gtk_knob_motion_notify()
+ *
+ *****************************************************************************/
+static gint
+gtk_knob_motion_notify(GtkWidget *widget, GdkEventMotion *event) {
+ GtkKnob *knob;
+ GdkModifierType mods;
+ gint x, y;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_KNOB (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ knob = GTK_KNOB (widget);
+
+ x = event->x;
+ y = event->y;
+
+ if (event->is_hint || (event->window != widget->window)) {
+ gdk_window_get_pointer (widget->window, &x, &y, &mods);
+ }
+
+ switch (knob->state) {
+
+ case STATE_PRESSED:
+ knob->state = STATE_DRAGGING;
+ /* fall through */
+
+ case STATE_DRAGGING:
+ if (mods & GDK_BUTTON1_MASK) {
+ gtk_knob_update_mouse (knob, x, y, TRUE);
+ return TRUE;
+ }
+ else if (mods & GDK_BUTTON3_MASK) {
+ gtk_knob_update_mouse (knob, x, y, FALSE);
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_timer()
+ *
+ *****************************************************************************/
+static gint
+gtk_knob_timer(GtkKnob *knob) {
+
+ g_return_val_if_fail (knob != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_KNOB (knob), FALSE);
+ g_return_val_if_fail (GTK_IS_ADJUSTMENT (knob->adjustment), FALSE);
+
+ if (knob->policy == GTK_UPDATE_DELAYED) {
+ g_signal_emit_by_name (knob->adjustment, "value_changed");
+ }
+
+ /* don't keep running this timer */
+ return FALSE;
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_update_mouse_update()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_update_mouse_update(GtkKnob *knob) {
+ g_return_if_fail(GTK_IS_ADJUSTMENT (knob->adjustment));
+
+ if (knob->policy == GTK_UPDATE_CONTINUOUS) {
+ g_signal_emit_by_name (knob->adjustment, "value_changed");
+ }
+ else {
+ gtk_widget_queue_draw (GTK_WIDGET (knob));
+
+ if (knob->policy == GTK_UPDATE_DELAYED) {
+ if (knob->timer) {
+ g_source_remove (knob->timer);
+ }
+ knob->timer = g_timeout_add (SCROLL_DELAY_LENGTH,
+ (GSourceFunc) gtk_knob_timer,
+ (gpointer) knob);
+ }
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_update_mouse()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_update_mouse(GtkKnob *knob, gint x, gint y, gboolean step) {
+ gfloat old_value, new_value, dv, dh;
+ gfloat angle;
+
+ g_return_if_fail (knob != NULL);
+ g_return_if_fail (GTK_IS_KNOB (knob));
+ g_return_if_fail (GTK_IS_ADJUSTMENT (knob->adjustment));
+
+ old_value = knob->adjustment->value;
+
+ angle = atan2f (-y + (knob->height >> 1), x - (knob->width >> 1));
+
+ /* inverted cartesian graphics coordinate system */
+ dv = knob->saved_y - y;
+ dh = x - knob->saved_x;
+ knob->saved_x = x;
+ knob->saved_y = y;
+
+ if ((x >= 0) && (x <= knob->width)) {
+ dh = 0; /* dead zone */
+ } else {
+ angle = cosf (angle);
+ dh *= angle * angle;
+ }
+
+ new_value = knob->adjustment->value +
+ dv * (step ? knob->adjustment->step_increment : knob->adjustment->page_increment) +
+ dh * (knob->adjustment->upper -
+ knob->adjustment->lower) * 0.005; /* 0.005 == (1 / 200) */
+
+ new_value = MAX (MIN (new_value, knob->adjustment->upper),
+ knob->adjustment->lower);
+
+ knob->adjustment->value = new_value;
+
+ if (knob->adjustment->value != old_value) {
+ gtk_knob_update_mouse_update (knob);
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_update()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_update(GtkKnob *knob) {
+ gfloat new_value;
+
+ g_return_if_fail (knob != NULL);
+ g_return_if_fail (GTK_IS_KNOB (knob));
+ g_return_if_fail (GTK_IS_ADJUSTMENT (knob->adjustment));
+
+ if (knob->adjustment->step_increment == 1) {
+ new_value = floor (knob->adjustment->value + 0.5);
+ }
+ else {
+ new_value = knob->adjustment->value;
+ }
+
+ if (new_value < knob->adjustment->lower) {
+ new_value = knob->adjustment->lower;
+ }
+
+ if (new_value > knob->adjustment->upper) {
+ new_value = knob->adjustment->upper;
+ }
+
+ if (new_value != knob->adjustment->value) {
+ knob->adjustment->value = new_value;
+ g_signal_emit_by_name (knob->adjustment, "value_changed");
+ }
+
+ gtk_widget_queue_draw (GTK_WIDGET (knob));
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_adjustment_changed()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_adjustment_changed(GtkAdjustment *adjustment, gpointer data) {
+ GtkKnob *knob;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ knob = GTK_KNOB (data);
+
+ if ((knob->old_value != adjustment->value) ||
+ (knob->old_lower != adjustment->lower) ||
+ (knob->old_upper != adjustment->upper))
+ {
+ gtk_knob_update (knob);
+
+ knob->old_value = adjustment->value;
+ knob->old_lower = adjustment->lower;
+ knob->old_upper = adjustment->upper;
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_adjustment_value_changed()
+ *
+ *****************************************************************************/
+static void
+gtk_knob_adjustment_value_changed (GtkAdjustment *adjustment, gpointer data) {
+ GtkKnob *knob;
+
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
+
+ knob = GTK_KNOB (data);
+
+ if (knob->old_value != adjustment->value) {
+ gtk_knob_update (knob);
+ knob->old_value = adjustment->value;
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_set_animation()
+ *
+ *****************************************************************************/
+void
+gtk_knob_set_animation (GtkKnob *knob, GtkKnobAnim *anim) {
+ g_return_if_fail (knob != NULL);
+ g_return_if_fail (anim != NULL);
+ g_return_if_fail (GTK_IS_KNOB (knob));
+ g_return_if_fail (GDK_IS_PIXBUF (anim->pixbuf));
+
+ knob->anim = (GtkKnobAnim *)anim;
+ knob->width = anim->frame_width;
+ knob->height = anim->height;
+
+ if (GTK_WIDGET_REALIZED (knob)) {
+ gtk_widget_queue_resize (GTK_WIDGET (knob));
+ }
+}
+
+
+/*****************************************************************************
+ *
+ * gtk_knob_animation_new_from_file()
+ *
+ *****************************************************************************/
+GtkKnobAnim *
+gtk_knob_animation_new_from_file(gchar *filename) {
+ GtkKnobAnim *anim;
+
+ anim = gtk_knob_animation_new_from_file_full (filename, -1, -1, KNOB_SIZE);
+ return anim;
+}
+
+/*****************************************************************************
+ *
+ * gtk_knob_animation_new_from_inline()
+ *
+ *****************************************************************************/
+GtkKnobAnim *
+gtk_knob_animation_new_from_inline(const guint8 *pixbuf) {
+ GtkKnobAnim *anim = g_new0 (GtkKnobAnim, 1);
+
+ g_return_val_if_fail((pixbuf != NULL), NULL);
+
+ anim->pixbuf = gdk_pixbuf_new_from_inline(-1, pixbuf, FALSE, NULL);
+ if (anim->pixbuf == NULL) {
+ g_free(anim);
+ return NULL;
+ }
+
+ anim->height = gdk_pixbuf_get_height (anim->pixbuf);
+ anim->width = gdk_pixbuf_get_width (anim->pixbuf);
+ anim->frame_width = anim->height;
+
+ return anim;
+}
+
+/*****************************************************************************
+ *
+ * gtk_knob_new_from_file_full()
+ *
+ * frame_width: overrides the frame width (to make rectangular frames)
+ * but doesn't affect the image size width and height cause optional
+ * scaling if not set to -1 when they are derived from the native
+ * image size.
+ *
+ * FIXME: account for any problems where (width % frame_width != 0)
+ *
+ *****************************************************************************/
+GtkKnobAnim *
+gtk_knob_animation_new_from_file_full(gchar *filename, gint frame_width,
+ gint width, gint height) {
+ GtkKnobAnim *anim = g_new0 (GtkKnobAnim, 1);
+
+ g_return_val_if_fail ((filename != NULL), NULL);
+
+ GError *gerror = NULL;
+
+#if GTK_MINOR_VERSION < 10
+ if (!(anim->pixbuf = gdk_pixbuf_new_from_file (filename, &gerror))) {
+ g_error_free(gerror);
+ gerror = NULL;
+ return NULL;
+ }
+#else /* GTK_MINOR_VERSION >= 10 */
+ if (!(anim->pixbuf = gdk_pixbuf_new_from_file_at_size (filename, width,
+ height, &gerror))) {
+ g_error_free(gerror);
+ gerror = NULL;
+ return NULL;
+ }
+#endif /* GTK_MINOR_VERSION < 10 */
+ else {
+ anim->height = gdk_pixbuf_get_height (anim->pixbuf);
+ anim->width = gdk_pixbuf_get_width (anim->pixbuf);
+ anim->frame_width = (frame_width != -1) ? frame_width : anim->height;
+ }
+
+ return anim;
+}
+
+/*****************************************************************************
+ *
+ * gtk_knob_animation_free()
+ *
+ *****************************************************************************/
+void
+gtk_knob_animation_free(GtkKnobAnim *anim) {
+ g_return_if_fail (anim != NULL);
+
+ if (anim->pixbuf)
+ g_object_unref (anim->pixbuf);
+
+ g_free (anim);
+}
diff --git a/gtkknob.h b/gtkknob.h
new file mode 100644
index 0000000..46643b8
--- /dev/null
+++ b/gtkknob.h
@@ -0,0 +1,102 @@
+/*****************************************************************************
+ *
+ * Most of this code comes from gAlan 0.2.0, copyright (C) 1999
+ * Tony Garnock-Jones, with modifications by Sean Bolton,
+ * copyright (C) 2004, and minor modifications by William Weston,
+ * copyright (C) 2007, Tomasz Moń, copyright (C) 2009
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *****************************************************************************/
+#ifndef __GTK_KNOB_H__
+#define __GTK_KNOB_H__
+
+#include <gtk/gtk.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GTK_KNOB(obj) G_TYPE_CHECK_INSTANCE_CAST(obj, gtk_knob_get_type(), GtkKnob)
+#define GTK_KNOB_CLASS(klass) G_TYPE_CHECK_CLASS_CAST(klass, gtk_knob_get_type(), GtkKnobClass)
+#define GTK_IS_KNOB(obj) G_TYPE_CHECK_INSTANCE_TYPE(obj, gtk_knob_get_type())
+
+typedef struct _GtkKnob GtkKnob;
+typedef struct _GtkKnobClass GtkKnobClass;
+typedef struct _GtkKnobAnim GtkKnobAnim;
+
+ /* better to make this an object and let widgets ref/deref it perhaps */
+ struct _GtkKnobAnim {
+ GdkPixbuf *pixbuf;
+ gint width; /* derived from image width */
+ gint height; /* derived from image height. */
+ gint frame_width; /* derived from pixbuf (width / height) or provided override for rectangular frames */
+ };
+
+ struct _GtkKnob {
+ GtkWidget widget;
+
+ /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
+ guint policy : 2;
+
+ /* State of widget (to do with user interaction) */
+ guint8 state;
+ gint saved_x, saved_y;
+
+ /* ID of update timer, or 0 if none */
+ guint32 timer;
+
+ /* knob animation */
+ GtkKnobAnim *anim;
+ gint width, height;
+
+ GdkBitmap *mask;
+ GdkGC *mask_gc;
+ GdkGC *red_gc;
+
+ /* Old values from adjustment stored so we know when something changes */
+ gfloat old_value;
+ gfloat old_lower;
+ gfloat old_upper;
+
+ /* The adjustment object that stores the data for this knob */
+ GtkAdjustment *adjustment;
+ };
+
+ struct _GtkKnobClass {
+ GtkWidgetClass parent_class;
+ };
+
+
+ extern GtkWidget *gtk_knob_new(GtkAdjustment *adjustment, GtkKnobAnim *anim);
+ extern GType gtk_knob_get_type(void);
+ extern GtkAdjustment *gtk_knob_get_adjustment(GtkKnob *knob);
+ extern void gtk_knob_set_update_policy(GtkKnob *knob, GtkUpdateType policy);
+ extern void gtk_knob_set_adjustment(GtkKnob *knob, GtkAdjustment *adjustment);
+
+ GtkKnobAnim *gtk_knob_animation_new_from_inline(const guint8 *pixbuf);
+ GtkKnobAnim *gtk_knob_animation_new_from_file_full(gchar *filename,
+ gint frame_width,
+ gint width,
+ gint height);
+
+ GtkKnobAnim *gtk_knob_animation_new_from_file(gchar *filename);
+ void gtk_knob_set_animation (GtkKnob *knob, GtkKnobAnim *anim);
+ void gtk_knob_animation_free(GtkKnobAnim *anim);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gui.c b/gui.c
new file mode 100644
index 0000000..d96b479
--- /dev/null
+++ b/gui.c
@@ -0,0 +1,1265 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include "gdigi.h"
+#include "gui.h"
+#include "effects.h"
+#include "preset.h"
+#include "gtkknob.h"
+#include "knob.h"
+
+typedef struct {
+ GtkObject *widget;
+
+ /* used for combo boxes, if widget isn't combo box, then both value and x are -1 */
+ gint value; /**< effect type value */
+ gint x; /**< combo box item number */
+} WidgetTreeElem;
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+static GtkKnobAnim *knob_anim = NULL; /* animation used by knobs */
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+static GTree *widget_tree = NULL; /**< this tree contains lists containing WidgetTreeElem data elements */
+static gboolean allow_send = FALSE; /**< if FALSE GUI parameter changes won't be sent to device */
+
+/**
+ * \param parent transient parent, or NULL for none
+ * \param message error description
+ *
+ * Shows error message dialog.
+ **/
+void show_error_message(GtkWidget *parent, gchar *message)
+{
+ g_return_if_fail(message != NULL);
+
+ GtkWidget *msg = gtk_message_dialog_new(GTK_WINDOW(parent),
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ message);
+
+ gtk_dialog_run(GTK_DIALOG(msg));
+ gtk_widget_destroy(msg);
+}
+
+/**
+ * \param value value to examine
+ * \param values EffectValues to check value against
+ *
+ * Examines whether value fits inside values range for given EffectValues.
+ *
+ * \return TRUE is value fits inside range, otherwise FALSE.
+ **/
+static gboolean check_value_range(gint value, EffectValues *values)
+{
+ if (((gint) values->min <= value) && (value <= (gint) values->max))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/**
+ * \param spin a GtkSpinButton
+ * \param new_val return value for valid input
+ * \param values signal user data, EffectValues for this parameter
+ *
+ * Custom GtkSpinButton "input" handler for EffectValues with non plain type.
+ *
+ * \return TRUE if new_val was set, otherwise FALSE.
+ **/
+static gboolean custom_value_input_cb(GtkSpinButton *spin, gdouble *new_val, EffectValues *values)
+{
+ gchar *text = g_strdup(gtk_entry_get_text(GTK_ENTRY(spin)));
+ gchar *err = NULL;
+ gdouble value;
+
+ for (;;) {
+ if (values->type & VALUE_TYPE_LABEL) {
+ /** search labels for value */
+ gint n;
+ for (n = 0; values->labels[n] != NULL; n++) {
+ if (g_strcmp0(values->labels[n], text) == 0) {
+ /* Value found */
+ *new_val = values->min + (gdouble)n;
+ g_free(text);
+ return TRUE;
+ }
+ }
+
+ /* Value not found */
+ if (values->type & VALUE_TYPE_EXTRA) {
+ values = values->extra;
+ continue;
+ } else {
+ g_free(text);
+ return FALSE;
+ }
+ }
+
+ if (values->type & VALUE_TYPE_SUFFIX) {
+ /* remove suffix from entry text */
+ gchar *tmp;
+
+ tmp = strstr(text, values->suffix);
+ if (tmp != NULL) {
+ gchar *temp = g_strndup(text, tmp - text);
+ g_free(text);
+ text = temp;
+ }
+ }
+
+ g_strstrip(text);
+
+ value = g_strtod(text, &err);
+ if (*err) {
+ if (values->type & VALUE_TYPE_EXTRA) {
+ values = values->extra;
+ continue;
+ } else {
+ g_free(text);
+ return FALSE;
+ }
+ }
+
+ if (values->type & VALUE_TYPE_STEP) {
+ value /= values->step;
+ }
+
+ if (values->type & VALUE_TYPE_OFFSET) {
+ value -= values->offset;
+ }
+
+ if (check_value_range((gint) value, values) == FALSE) {
+ if (values->type & VALUE_TYPE_EXTRA) {
+ values = values->extra;
+ continue;
+ } else {
+ g_free(text);
+ return FALSE;
+ }
+ }
+
+ *new_val = value;
+
+ g_free(text);
+
+ return TRUE;
+ }
+}
+
+/**
+ * \param spin a GtkSpinButton
+ * \param values signal user data, EffectValues for this parameter
+ *
+ * Custom GtkSpinButton "output" handler for EffectValues with non plain type.
+ *
+ * \return TRUE if text was set, otherwise FALSE.
+ **/
+static gboolean custom_value_output_cb(GtkSpinButton *spin, EffectValues *values)
+{
+ GtkAdjustment *adj;
+ gchar *text;
+ gdouble value;
+
+ adj = gtk_spin_button_get_adjustment(spin);
+ value = gtk_adjustment_get_value(adj);
+
+ while (check_value_range(value, values) == FALSE) {
+ if (values->type & VALUE_TYPE_EXTRA) {
+ values = values->extra;
+ } else {
+ g_message("custom_value_output_cb called with out of bounds value");
+ return FALSE;
+ }
+ }
+
+ if (values->type & VALUE_TYPE_LABEL) {
+ gtk_entry_set_text(GTK_ENTRY(spin), values->labels[(gint) value - (gint) values->min]);
+ return TRUE;
+ }
+
+ if (values->type & VALUE_TYPE_OFFSET) {
+ value += (gdouble) values->offset;
+ }
+
+ if (values->type & VALUE_TYPE_STEP) {
+ value *= values->step;
+ }
+
+ if (values->type & VALUE_TYPE_DECIMAL) {
+ text = g_strdup_printf("%.*f", values->decimal, value);
+ } else {
+ text = g_strdup_printf("%d", (gint) value);
+ }
+
+ if (values->type & VALUE_TYPE_SUFFIX) {
+ gchar *tmp;
+ tmp = g_strdup_printf("%s %s", text, values->suffix);
+ g_free(text);
+ text = tmp;
+ }
+
+ gtk_entry_set_text(GTK_ENTRY(spin), text);
+ g_free(text);
+
+ return TRUE;
+}
+
+/**
+ * \param adj the object which emitted the signal
+ * \param setting setting controlled by adj
+ *
+ * Sets effect value.
+ **/
+void value_changed_option_cb(GtkAdjustment *adj, EffectSettings *setting)
+{
+ g_return_if_fail(setting != NULL);
+
+ if (allow_send) {
+ gdouble val;
+ g_object_get(G_OBJECT(adj), "value", &val, NULL);
+ set_option(setting->id, setting->position, (gint)val);
+ }
+}
+
+/**
+ * \param button the object which emitted the signal
+ * \param effect effect controlled by button
+ *
+ * Turns effect on/off basing on state of button.
+ **/
+void toggled_cb(GtkToggleButton *button, Effect *effect)
+{
+ g_return_if_fail(effect != NULL);
+
+ if (allow_send) {
+ guint val = gtk_toggle_button_get_active(button);
+ set_option(effect->id, effect->position, val);
+ }
+}
+
+/**
+ * \param widget GtkObject to add to widget tree
+ * \param id object controlled ID
+ * \param position object controlled position
+ * \param value effect value type (if widget is GtkComboBox, otherwise -1)
+ * \param x combo box item number (if widget is GtkComboBox, otherwise -1)
+ *
+ * Adds widget to widget tree.
+ **/
+static WidgetTreeElem *widget_tree_add(GtkObject *widget, gint id, gint position, gint value, gint x)
+{
+ GList *list;
+ WidgetTreeElem *el;
+ gpointer key;
+
+ el = g_slice_new(WidgetTreeElem);
+ el->widget = widget;
+ el->value = value;
+ el->x = x;
+
+ key = GINT_TO_POINTER((position << 16) | id);
+
+ list = g_tree_lookup(widget_tree, key);
+
+ if (list == NULL) {
+ list = g_list_append(list, el);
+ g_tree_insert(widget_tree, key, list);
+ } else {
+ list = g_list_append(list, el);
+
+ /* replace the list pointer */
+ g_tree_steal(widget_tree, key);
+ g_tree_insert(widget_tree, key, list);
+ }
+
+ return el;
+}
+
+/**
+ * \param el widget tree element
+ * \param param parameter to set
+ *
+ * Sets widget tree element value to param value.
+ **/
+static void apply_widget_setting(WidgetTreeElem *el, SettingParam *param)
+{
+ if (el->value == -1) {
+ if (GTK_IS_TOGGLE_BUTTON(el->widget))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(el->widget), (param->value == 0) ? FALSE : TRUE);
+ else if (GTK_IS_ADJUSTMENT(el->widget))
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(el->widget), (gdouble)param->value);
+ } else { /* combo box */
+ if (el->value == param->value)
+ gtk_combo_box_set_active(GTK_COMBO_BOX(el->widget), el->x);
+ }
+}
+
+/**
+ * \param param SettingParam to apply to GUI
+ *
+ * Applies SettingParam to GUI
+ **/
+void apply_setting_param_to_gui(SettingParam *param)
+{
+ gpointer key;
+ g_return_if_fail(param != NULL);
+
+ allow_send = FALSE;
+ key = GINT_TO_POINTER((param->position << 16) | param->id);
+ GList *list = g_tree_lookup(widget_tree, key);
+ g_list_foreach(list, (GFunc)apply_widget_setting, param);
+ allow_send = TRUE;
+}
+
+/**
+ * \param preset preset to sync
+ *
+ * Synces GUI with preset.
+ **/
+static void apply_preset_to_gui(Preset *preset)
+{
+ g_return_if_fail(preset != NULL);
+ g_return_if_fail(widget_tree != NULL);
+
+ allow_send = FALSE;
+
+ GList *iter = preset->params;
+ while (iter) {
+ gpointer key;
+
+ SettingParam *param = iter->data;
+ iter = iter->next;
+
+ if (param != NULL) {
+ key = GINT_TO_POINTER((param->position << 16) | param->id);
+ GList *list = g_tree_lookup(widget_tree, key);
+ g_list_foreach(list, (GFunc)apply_widget_setting, param);
+ }
+ }
+
+ allow_send = TRUE;
+}
+
+/**
+ * Synces GUI with device current edit buffer.
+ **/
+static void apply_current_preset()
+{
+ GList *list = get_current_preset();
+ Preset *preset = create_preset_from_data(list);
+ message_list_free(list);
+ apply_preset_to_gui(preset);
+ preset_free(preset);
+}
+
+gboolean apply_current_preset_to_gui(gpointer data)
+{
+ apply_current_preset();
+ return FALSE;
+}
+
+/**
+ * \param settings effect parameters
+ * \param amt amount of effect parameters
+ * \param widget_table hash table matching settings pointer with created table (may be NULL)
+ *
+ * Creates knobs that allow user to set effect parameters.
+ *
+ * \return GtkTable containing necessary widgets to set effect parameters.
+ **/
+GtkWidget *create_table(EffectSettings *settings, gint amt, GHashTable *widget_table)
+{
+ GtkWidget *table, *label, *widget, *knob;
+ GtkObject *adj;
+ int x;
+
+ if (widget_table != NULL) {
+ table = g_hash_table_lookup(widget_table, settings);
+ if (table != NULL)
+ return table;
+ }
+
+ table = gtk_table_new(3, amt, FALSE);
+
+ for (x = 0; x<amt; x++) {
+ gdouble min, max;
+ gboolean custom;
+
+ get_values_info(settings[x].values, &min, &max, &custom);
+
+ label = gtk_label_new(settings[x].label);
+ adj = gtk_adjustment_new(0.0, min, max,
+ 1.0, /* step increment */
+ MAX((max / 100), 5.0), /* page increment */
+ 0.0);
+ knob = gtk_knob_new(GTK_ADJUSTMENT(adj), knob_anim);
+
+ widget = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
+ gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(widget), FALSE);
+ gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(widget), GTK_UPDATE_IF_VALID);
+ if (custom == TRUE) {
+ g_signal_connect(G_OBJECT(widget), "input", G_CALLBACK(custom_value_input_cb), settings[x].values);
+ g_signal_connect(G_OBJECT(widget), "output", G_CALLBACK(custom_value_output_cb), settings[x].values);
+ }
+
+ widget_tree_add(adj, settings[x].id, settings[x].position, -1, -1);
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, x, x+1, GTK_SHRINK, GTK_SHRINK, 2, 2);
+ gtk_table_attach(GTK_TABLE(table), knob, 1, 2, x, x+1, GTK_SHRINK, GTK_SHRINK, 2, 2);
+ gtk_table_attach(GTK_TABLE(table), widget, 2, 3, x, x+1, GTK_SHRINK, GTK_SHRINK, 2, 2);
+
+ g_signal_connect(G_OBJECT(adj), "value-changed", G_CALLBACK(value_changed_option_cb), &settings[x]);
+
+ if (widget_table != NULL) {
+ g_hash_table_insert(widget_table, settings, table);
+ }
+ }
+
+ return table;
+}
+
+/**
+ * \param effect Effect that can be turned on/off
+ *
+ * Creates toggle button that allow user to turn effect on/off.
+ *
+ * \return GtkToggleButton
+ **/
+GtkWidget *create_on_off_button(Effect *effect)
+{
+ GtkWidget *button;
+ if (effect->label == NULL)
+ button = gtk_check_button_new();
+ else
+ button = gtk_check_button_new_with_label(effect->label);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
+ g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(toggled_cb), effect);
+ widget_tree_add(GTK_OBJECT(button), effect->id, effect->position, -1, -1);
+ return button;
+}
+
+typedef struct {
+ gint type; /**< effect group type (value) */
+ gint id; /**< option ID */
+ gint position; /**< position */
+ GtkWidget *child; /**< child widget */
+} EffectSettingsGroup;
+
+/**
+ * \param group group to be freed
+ *
+ * Frees all memory used by group
+ **/
+void effect_settings_group_free(EffectSettingsGroup *group)
+{
+ if (group->child != NULL) {
+ /* destroy widget without parent */
+ if (gtk_widget_get_parent(group->child) == NULL)
+ gtk_widget_destroy(group->child);
+
+ g_object_unref(group->child);
+ }
+
+ g_slice_free(EffectSettingsGroup, group);
+}
+
+/**
+ * \param widget the object which emitted the signal
+ * \param data user data (unused, can be anything)
+ *
+ * Switches effect type and shows widgets allowing to set selected effect type parameters.
+ **/
+void combo_box_changed_cb(GtkComboBox *widget, gpointer data)
+{
+ GtkWidget *child;
+ GtkWidget *vbox;
+ EffectSettingsGroup *settings = NULL;
+ gchar *name = NULL;
+ gint x;
+ g_object_get(G_OBJECT(widget), "active", &x, NULL);
+
+ vbox = g_object_get_data(G_OBJECT(widget), "vbox");
+
+ if (x != -1) {
+ name = g_strdup_printf("SettingsGroup%d", x);
+ settings = g_object_get_data(G_OBJECT(widget), name);
+ g_free(name);
+
+ if (settings != NULL && allow_send)
+ set_option(settings->id, settings->position, settings->type);
+
+ child = g_object_get_data(G_OBJECT(widget), "active_child");
+ if (child == settings->child) {
+ return;
+ }
+
+ if (child != NULL) {
+ gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(gtk_widget_get_parent(vbox))), child);
+ }
+
+ if (settings->child != NULL) {
+ gtk_container_add(GTK_CONTAINER(gtk_widget_get_parent(gtk_widget_get_parent(vbox))), settings->child);
+ gtk_widget_show_all(gtk_widget_get_parent(gtk_widget_get_parent(vbox)));
+ }
+ g_object_set_data(G_OBJECT(widget), "active_child", settings->child);
+ }
+}
+
+/**
+ * \param group Effect type groups
+ * \param amt amount of effect groups
+ * \param id ID to set effect type
+ * \param position position
+ *
+ * Creates widget allowing user to choose effect type.
+ *
+ * \return widget that allow user to set effect type.
+ **/
+GtkWidget *create_widget_container(EffectGroup *group, gint amt, gint id, gint position)
+{
+ GtkWidget *vbox;
+ GtkWidget *widget;
+ GtkWidget *combo_box = NULL;
+ GHashTable *widget_table;
+ EffectSettingsGroup *settings = NULL;
+ gchar *name = NULL;
+ gint x;
+ gint cmbox_no = -1;
+
+ vbox = gtk_vbox_new(FALSE, 0);
+
+ widget_table = g_hash_table_new(g_direct_hash, g_direct_equal);
+
+ for (x = 0; x<amt; x++) {
+ if (group[x].label) {
+ if (combo_box == NULL) {
+ combo_box = gtk_combo_box_new_text();
+ gtk_container_add(GTK_CONTAINER(vbox), combo_box);
+ g_signal_connect(G_OBJECT(combo_box), "changed", G_CALLBACK(combo_box_changed_cb), group);
+ g_object_set_data(G_OBJECT(combo_box), "vbox", vbox);
+ }
+ gtk_combo_box_append_text(GTK_COMBO_BOX(combo_box), group[x].label);
+ cmbox_no++;
+
+ if ((group[x].settings != NULL) && (group[x].settings_amt > 0)) {
+ widget = create_table(group[x].settings, group[x].settings_amt, widget_table);
+ g_object_ref_sink(widget);
+ } else
+ widget = NULL;
+
+ settings = g_slice_new(EffectSettingsGroup);
+ settings->id = id;
+ settings->type = group[x].type;
+ settings->position = position;
+ settings->child = widget;
+
+ widget_tree_add(GTK_OBJECT(combo_box), id, position, group[x].type, x);
+
+ name = g_strdup_printf("SettingsGroup%d", cmbox_no);
+ g_object_set_data_full(G_OBJECT(combo_box), name, settings, ((GDestroyNotify)effect_settings_group_free));
+ g_free(name);
+ } else {
+ if ((group[x].settings != NULL) && (group[x].settings_amt > 0)) {
+ widget = create_table(group[x].settings, group[x].settings_amt, widget_table);
+ gtk_container_add(GTK_CONTAINER(vbox), widget);
+ }
+ }
+ }
+
+ g_hash_table_destroy(widget_table);
+
+ return vbox;
+}
+
+/**
+ * \param widgets Effect descriptions
+ * \param amt amount of effect descriptions
+ * \param label frame label (can be NULL)
+ *
+ * Creates frame (with optional label) containing widgets allowing user to set effect options.
+ *
+ * \return widget that allow user to set effect options.
+ **/
+GtkWidget *create_vbox(Effect *widgets, gint amt, gchar *label)
+{
+ GtkWidget *vbox;
+ GtkWidget *widget;
+ GtkWidget *table;
+ GtkWidget *container;
+ GtkWidget *frame;
+ int x;
+ int y;
+
+ frame = gtk_frame_new(label);
+
+ vbox = gtk_vbox_new(FALSE, 0);
+
+ table = gtk_table_new(2, amt, FALSE);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 2);
+
+ for (x = 0; x<amt; x++) {
+ if ((widgets[x].id != -1) && (widgets[x].position != -1)) {
+ widget = create_on_off_button(&widgets[x]);
+ gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, x, x+1);
+
+ if (widgets[x].label)
+ y = 1;
+ else
+ y = 0;
+
+ } else if (widgets[x].label) {
+ widget = gtk_label_new(widgets[x].label);
+ gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, x, x+1);
+ y = 0;
+ } else {
+ /* Default to 1 */
+ if (x == 0)
+ y = 1;
+ }
+
+ container = create_widget_container(widgets[x].group, widgets[x].group_amt, widgets[x].type, widgets[x].position);
+ gtk_table_attach_defaults(GTK_TABLE(table), container, 1-y, 2-y, x+y, x+y+1);
+ }
+ gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 2);
+
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ return frame;
+}
+
+enum {
+ PRESET_NAME_COLUMN = 0,
+ PRESET_NUMBER_COLUMN,
+ PRESET_BANK_COLUMN,
+ NUM_COLUMNS
+};
+
+/**
+ * \param treeview the object which emitted the signal
+ * \param path the GtkTreePath for the activated row
+ * \param column the GtkTreeViewColumn in which the activation occurred
+ * \param model model holding preset names
+ *
+ * Sets active device preset to preset selected by user.
+ **/
+void row_activate_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, GtkTreeModel *model) {
+ GtkTreeIter iter;
+ gint id;
+ gint bank;
+
+ gtk_tree_model_get_iter(model, &iter, path);
+ gtk_tree_model_get(model, &iter, PRESET_NUMBER_COLUMN, &id, PRESET_BANK_COLUMN, &bank, -1);
+
+ if ((bank != -1) && (id != -1)) {
+ switch_preset(bank, id);
+ apply_current_preset();
+ }
+}
+
+/**
+ * \param model model to fill
+ * \param bank preset bank
+ * \param name preset bank description visible to user
+ *
+ * Appends to model preset names found in device preset bank.
+ **/
+static void fill_store_with_presets(GtkTreeStore *model, guint bank, gchar *name)
+{
+ GtkTreeIter iter;
+ GtkTreeIter child_iter;
+ int x;
+
+ GStrv presets = query_preset_names(bank);
+ g_return_if_fail(presets != NULL);
+
+ gtk_tree_store_append(model, &iter, NULL);
+ gtk_tree_store_set(model, &iter,
+ PRESET_NAME_COLUMN, name,
+ PRESET_NUMBER_COLUMN, -1,
+ PRESET_BANK_COLUMN, -1,
+ -1);
+
+ for (x=0; x<g_strv_length(presets); x++) {
+ gchar *tmp = g_strdup_printf("%d - %s", x+1, presets[x]);
+
+ gtk_tree_store_append(model, &child_iter, &iter);
+ gtk_tree_store_set(model, &child_iter,
+ PRESET_NAME_COLUMN, tmp,
+ PRESET_NUMBER_COLUMN, x,
+ PRESET_BANK_COLUMN, bank,
+ -1);
+
+ g_free(tmp);
+ }
+ g_strfreev(presets);
+}
+
+/**
+ * \param model model to fill
+ *
+ * Fills model with preset names found on device.
+ **/
+static void fill_store(GtkTreeStore *model)
+{
+ Device *device = g_object_get_data(G_OBJECT(model), "device");
+
+ g_return_if_fail(device != NULL);
+
+ gint i;
+ for (i=0; i<device->n_banks; i++)
+ fill_store_with_presets(model,
+ device->banks[i].bank,
+ device->banks[i].name);
+}
+
+/**
+ * \param device device information
+ *
+ * Creates treeview showing list of presets available on device.
+ *
+ * \return treeview containing all preset names found on device.
+ **/
+GtkWidget *create_preset_tree(Device *device)
+{
+ GtkWidget *treeview;
+ GtkTreeStore *store;
+ GtkCellRenderer *renderer;
+
+ store = gtk_tree_store_new(NUM_COLUMNS, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT);
+ g_object_set_data(G_OBJECT(store), "device", device);
+ fill_store(store);
+
+ treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ g_object_unref(store);
+
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview),
+ -1, "Preset name",
+ renderer, "text",
+ PRESET_NAME_COLUMN, NULL);
+
+ g_object_set(G_OBJECT(treeview), "headers-visible", FALSE, NULL);
+ g_signal_connect(G_OBJECT(treeview), "realize", G_CALLBACK(gtk_tree_view_expand_all), NULL);
+ g_signal_connect(G_OBJECT(treeview), "row-activated", G_CALLBACK(row_activate_cb), GTK_TREE_MODEL(store));
+
+ return treeview;
+}
+
+/**
+ * \param window application toplevel window
+ * \param default_name default preset name
+ *
+ * Shows window allowing user to store current edit buffer.
+ **/
+static void show_store_preset_window(GtkWidget *window, gchar *default_name)
+{
+ GtkWidget *dialog, *cmbox, *entry, *table, *label, *vbox;
+ GStrv names;
+ int x;
+
+ dialog = gtk_dialog_new_with_buttons("Store preset",
+ GTK_WINDOW(window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+ table = gtk_table_new(2, 2, FALSE);
+ gtk_container_add(GTK_CONTAINER(vbox), table);
+
+ cmbox = gtk_combo_box_new_text();
+ names = query_preset_names(PRESETS_USER);
+ for (x=0; x<g_strv_length(names); x++) {
+ gchar *title = g_strdup_printf("%d - %s", x+1, names[x]);
+ gtk_combo_box_append_text(GTK_COMBO_BOX(cmbox), title);
+ g_free(title);
+ }
+ g_strfreev(names);
+ gtk_table_attach_defaults(GTK_TABLE(table), cmbox, 1, 2, 0, 1);
+
+ entry = gtk_entry_new();
+ if (default_name != NULL)
+ gtk_entry_set_text(GTK_ENTRY(entry), default_name);
+ gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 2, 1, 2);
+
+ label = gtk_label_new("Preset slot:");
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
+
+ label = gtk_label_new("Preset name:");
+ gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 1, 2);
+
+ gtk_widget_show_all(vbox);
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+ gint number = gtk_combo_box_get_active(GTK_COMBO_BOX(cmbox));
+ if (number != -1) {
+ store_preset_name(number, gtk_entry_get_text(GTK_ENTRY(entry)));
+ }
+ }
+
+ gtk_widget_destroy(dialog);
+}
+
+/**
+ * \param action the object which emitted the signal
+ *
+ * Shows store preset window.
+ **/
+static void action_store_cb(GtkAction *action)
+{
+ GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
+ show_store_preset_window(window, NULL);
+}
+
+/**
+ * \param action the object which emitted the signal
+ *
+ * Shows about dialog.
+ **/
+static void action_show_about_dialog_cb(GtkAction *action)
+{
+ static const gchar * const authors[] = {
+ "Tomasz Moń <desowin@gmail.com>",
+ NULL
+ };
+ static const gchar copyright[] = "Copyright \xc2\xa9 2009 Tomasz Moń";
+ static const gchar website[] = "http://desowin.org/gdigi/";
+
+ GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
+
+ gtk_show_about_dialog(GTK_WINDOW(window),
+ "authors", authors,
+ "copyright", copyright,
+ "website", website,
+ NULL);
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+typedef struct {
+ gchar *name;
+ gchar *suffix;
+} SupportedFileTypes;
+
+static SupportedFileTypes file_types[] = {
+ {"RP155Preset", "*.rp155p"},
+ {"RP250Preset", "*.rp250p"},
+ {"RP255Preset", "*.rp255p"},
+ {"RP355Preset", "*.rp355p"},
+ {"RP500Preset", "*.rp500p"},
+ {"RP1000Preset", "*.rp1000p"},
+ {"GNX4 Preset", "*.g4p"},
+ {"GNX3kPreset", "*.g3kp"},
+};
+
+static guint n_file_types = G_N_ELEMENTS(file_types);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+/**
+ * \param action the object which emitted the signal
+ *
+ * Shows file chooser dialog.
+ * If user opens valid preset file, the preset gets applied to edit buffer and store preset window is shown.
+ **/
+static void action_open_preset_cb(GtkAction *action)
+{
+ static GtkWidget *dialog = NULL;
+
+ if (dialog != NULL)
+ return;
+
+ GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
+
+ dialog = gtk_file_chooser_dialog_new("Open Preset", GTK_WINDOW(window),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ GtkFileFilter *filter;
+ filter = gtk_file_filter_new();
+ gtk_file_filter_set_name(filter, "All Supported Types");
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
+
+ int x;
+ for (x=0; x<n_file_types; x++) {
+ GtkFileFilter *current_filter = gtk_file_filter_new();
+
+ gtk_file_filter_set_name(current_filter, file_types[x].name);
+ gtk_file_filter_add_pattern(current_filter, file_types[x].suffix);
+ gtk_file_filter_add_pattern(filter, file_types[x].suffix);
+
+ gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), current_filter);
+ }
+
+ gboolean loaded = FALSE;
+ while (!loaded && gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+ GError *error = NULL;
+ gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+ Preset *preset = create_preset_from_xml_file(filename, &error);
+ if (error) {
+ show_error_message(window, error->message);
+ g_error_free(error);
+ error = NULL;
+ } else if (preset != NULL) {
+ apply_preset_to_gui(preset);
+
+ gtk_widget_hide(dialog);
+
+ GString *start = g_string_new(NULL);
+ g_string_append_printf(start,
+ "%c%c%s%c%c%c",
+ PRESETS_EDIT_BUFFER, 0,
+ preset->name, 0 /* NULL terminated string */,
+ 0 /* modified */,
+ /* messages to follow */
+ preset->genetxs ? 10 : 2);
+
+ send_message(RECEIVE_PRESET_START, start->str, start->len);
+ send_preset_parameters(preset->params);
+ if (preset->genetxs != NULL) {
+ gint i;
+
+ /* GNX4 sends messages in following order:
+ * Section Bank Index
+ * 0x00 0x04 0x0000
+ * 0x00 0x04 0x0001
+ * 0x01 0x04 0x0000
+ * 0x01 0x04 0x0001
+ * 0x00 0x04 0x0002
+ * 0x00 0x04 0x0003
+ * 0x01 0x04 0x0002
+ * 0x01 0x04 0x0003
+ */
+
+ /* GNX3000 sends messages in following order:
+ * Section Bank Index
+ * 0x07 0x04 0x0000
+ * 0x07 0x04 0x0001
+ * 0x08 0x04 0x0000
+ * 0x08 0x04 0x0001
+ * 0x07 0x04 0x0002
+ * 0x07 0x04 0x0003
+ * 0x08 0x04 0x0002
+ * 0x08 0x04 0x0003
+ */
+ for (i = 0; i < 2; i++) {
+ GList *iter = preset->genetxs;
+
+ while (iter) {
+ SectionID section;
+ guint bank, index;
+
+ SettingGenetx *genetx = (SettingGenetx *) iter->data;
+ iter = iter->next;
+
+ section = get_genetx_section_id(genetx->version,
+ genetx->type);
+ bank = 0x04;
+
+ if (i == 0) {
+ index = genetx->channel;
+ } else {
+ if (genetx->channel == GENETX_CHANNEL1) {
+ index = GENETX_CHANNEL1_CUSTOM;
+ } else if (genetx->channel == GENETX_CHANNEL2) {
+ index = GENETX_CHANNEL2_CUSTOM;
+ }
+ }
+
+ send_object(section, bank, index,
+ genetx->name, genetx->data);
+ }
+ }
+ }
+ send_message(RECEIVE_PRESET_END, NULL, 0);
+
+ show_store_preset_window(window, preset->name);
+
+ g_string_free(start, TRUE);
+ preset_free(preset);
+ loaded = TRUE;
+ }
+ g_free(filename);
+ }
+
+ gtk_widget_destroy(dialog);
+ dialog = NULL;
+}
+
+/**
+ * \param list widget tree list to be freed
+ *
+ * Frees all memory used by widget tree list.
+ */
+static void widget_tree_elem_free(GList *list)
+{
+ GList *iter;
+ for (iter = list; iter; iter = iter->next) {
+ g_slice_free(WidgetTreeElem, iter->data);
+ }
+ g_list_free(list);
+}
+
+/**
+ * \param action the object which emitted the signal
+ *
+ * Destroys action object "window" data, then stops gtk main loop.
+ **/
+static void action_quit_cb(GtkAction *action)
+{
+ GtkWidget *window = g_object_get_data(G_OBJECT(action), "window");
+
+ gtk_widget_destroy(window);
+ gtk_main_quit();
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+static GtkActionEntry entries[] = {
+ {"File", NULL, "_File"},
+ {"Preset", NULL, "_Preset"},
+ {"Help", NULL, "_Help"},
+ {"Open", GTK_STOCK_OPEN, "_Open", "<control>O", "Open preset file", G_CALLBACK(action_open_preset_cb)},
+ {"Quit", GTK_STOCK_QUIT, "_Quit", "<control>Q", "Quit", G_CALLBACK(action_quit_cb)},
+ {"Store", NULL, "_Store", "<control>S", "Store", G_CALLBACK(action_store_cb)},
+ {"About", GTK_STOCK_ABOUT, "_About", "<control>A", "About", G_CALLBACK(action_show_about_dialog_cb)},
+};
+static guint n_entries = G_N_ELEMENTS(entries);
+
+static const gchar *menu_info =
+"<ui>"
+" <menubar name='MenuBar'>"
+" <menu action='File'>"
+" <menuitem action='Open'/>"
+" <separator/>"
+" <menuitem action='Quit'/>"
+" </menu>"
+" <menu action='Preset'>"
+" <menuitem action='Store'/>"
+" </menu>"
+" <menu action='Help'>"
+" <menuitem action='About'/>"
+" </menu>"
+" </menubar>"
+"</ui>";
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+/**
+ * \param ui GtkUIManager to lookup actions
+ * \param path path to action
+ * \param window toplevel window
+ *
+ * Sets action object "window" data to toplevel window.
+ **/
+static void add_action_data(GtkUIManager *ui, const gchar *path, GtkWidget *window)
+{
+ GtkAction *action;
+
+ action = gtk_ui_manager_get_action(ui, path);
+ g_return_if_fail(action != NULL);
+
+ g_object_set_data(G_OBJECT(action), "window", window);
+}
+
+/**
+ * \param window toplevel window
+ * \param vbox vbox to hold menubar
+ *
+ * Creates menubar (adds accel group to toplevel window as well) and packs it into vbox.
+ **/
+static void add_menubar(GtkWidget *window, GtkWidget *vbox)
+{
+ GtkUIManager *ui;
+ GtkActionGroup *actions;
+ GError *error = NULL;
+
+ actions = gtk_action_group_new("Actions");
+ gtk_action_group_add_actions(actions, entries, n_entries, NULL);
+
+ ui = gtk_ui_manager_new();
+ gtk_ui_manager_insert_action_group(ui, actions, 0);
+ g_object_unref(actions);
+ gtk_window_add_accel_group(GTK_WINDOW(window), gtk_ui_manager_get_accel_group(ui));
+
+ if (!gtk_ui_manager_add_ui_from_string(ui, menu_info, -1, &error)) {
+ g_message("building menus failed: %s", error->message);
+ g_error_free(error);
+ error = NULL;
+ }
+ gtk_box_pack_start(GTK_BOX(vbox),
+ gtk_ui_manager_get_widget(ui, "/MenuBar"),
+ FALSE, FALSE, 0);
+
+ add_action_data(ui, "/MenuBar/File/Quit", window);
+ add_action_data(ui, "/MenuBar/File/Open", window);
+ add_action_data(ui, "/MenuBar/Preset/Store", window);
+ add_action_data(ui, "/MenuBar/Help/About", window);
+
+ g_object_unref(ui);
+}
+
+static gint widget_tree_key_compare_func(gconstpointer a, gconstpointer b, gpointer data)
+{
+ gint position_a = GPOINTER_TO_INT(a) & 0xFF0000;
+ gint position_b = GPOINTER_TO_INT(b) & 0xFF0000;
+
+ if (position_a > position_b) {
+ return 1;
+ } else if (position_a == position_b) {
+ gint val_a = GPOINTER_TO_INT(a) & 0xFFFF;
+ gint val_b = GPOINTER_TO_INT(b) & 0xFFFF;
+ return val_a - val_b;
+ } else
+ return -1;
+}
+
+/**
+ * Creates main window.
+ **/
+void gui_create(Device *device)
+{
+ GtkWidget *window;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *widget;
+ GtkWidget *notebook;
+ GtkWidget *sw; /* scrolled window to carry preset treeview */
+ gint x;
+ gint i;
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "gdigi");
+
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+
+ add_menubar(window, vbox);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(vbox), hbox);
+
+ sw = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(hbox), sw, FALSE, FALSE, 0);
+
+ widget = create_preset_tree(device);
+ gtk_container_add(GTK_CONTAINER(sw), widget);
+
+ notebook = gtk_notebook_new();
+ gtk_box_pack_start(GTK_BOX(hbox), notebook, TRUE, TRUE, 2);
+
+ knob_anim = gtk_knob_animation_new_from_inline(knob_pixbuf);
+
+ widget_tree = g_tree_new_full(widget_tree_key_compare_func,
+ NULL, /* key compare data */
+ NULL, /* key destroy func */
+ (GDestroyNotify) widget_tree_elem_free);
+
+ gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), device->n_pages > 1 ? TRUE : FALSE);
+
+ for (i = 0; i<device->n_pages; i++) {
+ GtkWidget *label = NULL;
+ vbox = gtk_vbox_new(FALSE, 0);
+ label = gtk_label_new(device->pages[i].name);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
+
+ for (x = 0; x<device->pages[i].n_effects; x++) {
+ if ((x % ((device->pages[i].n_effects+1)/device->pages[i].n_rows)) == 0) {
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
+ }
+ widget = create_vbox(device->pages[i].effects[x].effect, device->pages[i].effects[x].amt, device->pages[i].effects[x].label);
+ gtk_box_pack_start(GTK_BOX(hbox), widget, TRUE, TRUE, 2);
+ }
+ }
+
+ apply_current_preset();
+ gtk_widget_show_all(window);
+
+ g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
+}
+
+/**
+ * Frees memory allocated by gui_create which is not explicitly freed when main window is destroyed.
+ **/
+void gui_free()
+{
+ g_tree_destroy(widget_tree);
+ widget_tree = NULL;
+
+ gtk_knob_animation_free(knob_anim);
+ knob_anim = NULL;
+}
+
+/**
+ * \param device Variable to hold device information
+ *
+ * Displays dialogbox stating that device is unsupported.
+ *
+ * \return TRUE if user selects "compability mode", otherwise FALSE.
+ **/
+gboolean unsupported_device_dialog(Device **device)
+{
+ extern Device* supported_devices[];
+ extern int n_supported_devices;
+
+ GtkWidget *dialog;
+ GtkWidget *label;
+ GtkWidget *combo_box;
+ GtkWidget *vbox;
+ int x;
+
+ dialog = gtk_dialog_new_with_buttons("Unsupported device",
+ NULL, GTK_DIALOG_MODAL,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+
+ label = gtk_label_new("Your device appears to be unsupported by gdigi.\n"
+ "As some of the settings may be common between different devices,\n"
+ "you can now select compability mode with one of the supported devices.\n"
+ "Please take a look at gdigi's HACKING file.");
+ gtk_container_add(GTK_CONTAINER(vbox), label);
+
+ combo_box = gtk_combo_box_new_text();
+ for (x=0; x<n_supported_devices; x++) {
+ gtk_combo_box_append_text(GTK_COMBO_BOX(combo_box), supported_devices[x]->name);
+ }
+
+ gtk_container_add(GTK_CONTAINER(vbox), combo_box);
+
+ gtk_widget_show_all(vbox);
+ if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+ gint number = gtk_combo_box_get_active(GTK_COMBO_BOX(combo_box));
+ if (number != -1 && number <n_supported_devices) {
+ g_message("Starting %s compability mode", supported_devices[number]->name);
+ *device = supported_devices[number];
+ gtk_widget_destroy(dialog);
+ return TRUE;
+ }
+ }
+
+ gtk_widget_destroy(dialog);
+ return FALSE;
+}
diff --git a/gui.h b/gui.h
new file mode 100644
index 0000000..42538fb
--- /dev/null
+++ b/gui.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef GDIGI_GUI_H
+#define GDIGI_GUI_H
+
+#include <glib.h>
+#include "effects.h"
+
+void show_error_message(GtkWidget *parent, gchar *message);
+void apply_setting_param_to_gui(SettingParam *param);
+gboolean apply_current_preset_to_gui(gpointer data);
+void gui_create(Device *device);
+void gui_free();
+gboolean unsupported_device_dialog(Device **device);
+
+#endif /* GDIGI_GUI_H */
diff --git a/knob.png b/knob.png
new file mode 100644
index 0000000..3290361
--- /dev/null
+++ b/knob.png
Binary files differ
diff --git a/preset.c b/preset.c
new file mode 100644
index 0000000..839f635
--- /dev/null
+++ b/preset.c
@@ -0,0 +1,357 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#include <gio/gio.h>
+#include <expat.h>
+#include <string.h>
+#include "preset.h"
+#include "gdigi.h"
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+enum {
+ PARSER_TYPE_NOT_SET = -1,
+ PARSER_TYPE_PRESET_NAME = 0,
+ PARSER_TYPE_PARAM_ID,
+ PARSER_TYPE_PARAM_POSITION,
+ PARSER_TYPE_PARAM_VALUE,
+ PARSER_TYPE_PARAM_NAME,
+ PARSER_TYPE_PARAM_TEXT,
+ PARSER_TYPE_GENETX_VERSION,
+ PARSER_TYPE_GENETX_TYPE,
+ PARSER_TYPE_GENETX_CHANNEL,
+ PARSER_TYPE_GENETX_NAME,
+ PARSER_TYPE_GENETX_DATA
+};
+
+enum {
+ SECTION_NOT_SET = -1,
+ SECTION_PARAMS,
+ SECTION_GENETX
+};
+
+typedef struct {
+ int depth;
+ int id;
+ int section;
+ Preset *preset;
+} AppData;
+
+static void XMLCALL start(void *data, const char *el, const char **attr) {
+ AppData *ad = (AppData *) data;
+
+ ad->id = PARSER_TYPE_NOT_SET;
+ if (g_strcmp0(el, "Name") == 0) {
+ if (ad->depth == 1) {
+ ad->id = PARSER_TYPE_PRESET_NAME;
+ } else if (ad->depth == 3) {
+ if (ad->section == SECTION_PARAMS) {
+ ad->id = PARSER_TYPE_PARAM_NAME;
+ } else if (ad->section == SECTION_GENETX) {
+ ad->id = PARSER_TYPE_GENETX_NAME;
+ }
+ }
+ }
+
+ if (g_strcmp0(el, "Params") == 0) {
+ ad->section = SECTION_PARAMS;
+ if (ad->preset->params != NULL)
+ g_message("Params aleady exists!");
+ } else if (g_strcmp0(el, "Param") == 0) {
+ SettingParam *param = setting_param_new();
+ ad->preset->params = g_list_prepend(ad->preset->params, param);
+ } else if (g_strcmp0(el, "ID") == 0) {
+ ad->id = PARSER_TYPE_PARAM_ID;
+ } else if (g_strcmp0(el, "Position") == 0) {
+ ad->id = PARSER_TYPE_PARAM_POSITION;
+ } else if (g_strcmp0(el, "Value") == 0) {
+ ad->id = PARSER_TYPE_PARAM_VALUE;
+ } else if (g_strcmp0(el, "Text") == 0) {
+ ad->id = PARSER_TYPE_PARAM_TEXT;
+ } else if (g_strcmp0(el, "Genetx") == 0) {
+ ad->section = SECTION_GENETX;
+ if (ad->preset->genetxs != NULL)
+ g_message("Genetx already exists!");
+ } else if (g_strcmp0(el, "GenetxModel") == 0) {
+ SettingGenetx *genetx = setting_genetx_new();
+ ad->preset->genetxs = g_list_prepend(ad->preset->genetxs, genetx);
+ } else if (g_strcmp0(el, "Version") == 0) {
+ ad->id = PARSER_TYPE_GENETX_VERSION;
+ } else if (g_strcmp0(el, "Type") == 0) {
+ ad->id = PARSER_TYPE_GENETX_TYPE;
+ } else if (g_strcmp0(el, "Channel") == 0) {
+ ad->id = PARSER_TYPE_GENETX_CHANNEL;
+ } else if (g_strcmp0(el, "Data") == 0) {
+ ad->id = PARSER_TYPE_GENETX_DATA;
+ }
+
+ ad->depth++;
+}
+
+static void XMLCALL end(void *data, const char *el) {
+ AppData *ad = (AppData *) data;
+ ad->depth--;
+ ad->id = PARSER_TYPE_NOT_SET;
+}
+
+static void XMLCALL text_cb(void *data, const char* text, int len)
+{
+ AppData *ad = (AppData *) data;
+
+ if ((ad == NULL) || (ad->preset == NULL))
+ return;
+
+ if (ad->id == PARSER_TYPE_PRESET_NAME) {
+ if (ad->preset->name != NULL)
+ g_free(ad->preset->name);
+ ad->preset->name = g_strndup(text, len);
+ }
+
+ if (ad->section == SECTION_PARAMS) {
+ if (ad->preset->params == NULL)
+ return;
+
+ SettingParam *param = (SettingParam *) ad->preset->params->data;
+ if (param == NULL)
+ return;
+
+ gchar *value = g_strndup(text, len);
+
+ switch (ad->id) {
+ case PARSER_TYPE_PARAM_ID:
+ param->id = atoi(value);
+ break;
+ case PARSER_TYPE_PARAM_POSITION:
+ param->position = atoi(value);
+ break;
+ case PARSER_TYPE_PARAM_VALUE:
+ param->value = atoi(value);
+ break;
+ }
+
+ g_free(value);
+ } else if (ad->section == SECTION_GENETX) {
+ if (ad->preset->genetxs == NULL)
+ return;
+
+ SettingGenetx *genetx = (SettingGenetx *) ad->preset->genetxs->data;
+ if (genetx == NULL)
+ return;
+
+ gchar *value = g_strndup(text, len);
+
+ switch (ad->id) {
+ case PARSER_TYPE_GENETX_VERSION:
+ if (g_strcmp0(value, "Version1") == 0) {
+ genetx->version = GENETX_VERSION_1;
+ } else if (g_strcmp0(value, "Version2") == 0) {
+ genetx->version = GENETX_VERSION_2;
+ } else {
+ g_message("Unknown GeNetX version: %s", value);
+ }
+ break;
+ case PARSER_TYPE_GENETX_TYPE:
+ if (g_strcmp0(value, "Amp") == 0) {
+ genetx->type = GENETX_TYPE_AMP;
+ } else if (g_strcmp0(value, "Cabinet") == 0) {
+ genetx->type = GENETX_TYPE_CABINET;
+ } else {
+ g_message("Unknown GeNetX type: %s", value);
+ }
+ break;
+ case PARSER_TYPE_GENETX_CHANNEL:
+ if (g_strcmp0(value, "Channel1") == 0) {
+ genetx->channel = GENETX_CHANNEL1;
+ } else if (g_strcmp0(value, "Channel2") == 0) {
+ genetx->channel = GENETX_CHANNEL2;
+ } else {
+ g_message("Unknown GeNetX channel: %s", value);
+ }
+ break;
+ case PARSER_TYPE_GENETX_NAME:
+ /* reassign pointer */
+ genetx->name = value;
+ value = NULL;
+ break;
+ case PARSER_TYPE_GENETX_DATA:
+ {
+ guchar *data = NULL;
+ gsize length = 0;
+
+ data = g_base64_decode(value, &length);
+ genetx->data = g_string_new_len((gchar *) data, length);
+
+ g_free(data);
+ break;
+ }
+ }
+
+ g_free(value);
+ }
+}
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+/**
+ * \param filename valid path to file
+ * \param error return location for an error
+ *
+ * Tries to open file pointed by path, then parses it.
+ *
+ * \return Preset which must be freed using preset_free, or NULL on error.
+ **/
+Preset *create_preset_from_xml_file(gchar *filename, GError **error)
+{
+ GError *err = NULL;
+ gchar *contents;
+
+ if (g_file_get_contents(filename, &contents, NULL, &err) == FALSE) {
+ g_message("Failed to get %s contents: %s", filename, err->message);
+ *error = g_error_copy(err);
+ g_error_free(err);
+ return NULL;
+ }
+
+ AppData *ad = g_slice_new(AppData);
+ ad->depth = 0;
+ ad->preset = g_slice_new(Preset);
+ ad->preset->name = NULL;
+ ad->preset->params = NULL;
+ ad->preset->genetxs = NULL;
+ ad->id = PARSER_TYPE_NOT_SET;
+
+ XML_Parser p;
+ p = XML_ParserCreate(NULL);
+ XML_SetUserData(p, (void *) ad);
+ XML_SetElementHandler(p, start, end);
+ XML_SetCharacterDataHandler(p, text_cb);
+
+ if (XML_Parse(p, contents, strlen(contents), XML_TRUE) != XML_STATUS_OK) {
+ g_set_error(error, 0, 0, "Parse error at line %d:\n%s",
+ (int)XML_GetCurrentLineNumber(p),
+ XML_ErrorString(XML_GetErrorCode(p)));
+ preset_free(ad->preset);
+ g_slice_free(AppData, ad);
+ g_free(contents);
+ return NULL;
+ }
+
+ Preset *preset = ad->preset;
+ preset->params = g_list_reverse(preset->params);
+ preset->genetxs = g_list_reverse(preset->genetxs);
+
+ XML_ParserFree(p);
+ g_slice_free(AppData, ad);
+
+ g_free(contents);
+ return preset;
+}
+
+/**
+ * \param list list containing unpacked preset SysEx messages.
+ *
+ * Parses message
+ *
+ * \return Preset which must be freed using preset_free, or NULL on error.
+ **/
+Preset *create_preset_from_data(GList *list)
+{
+ GString *data;
+ GList *iter;
+ gint total, n, x;
+ gint bank, number, modified;
+ gchar *name;
+
+ g_return_val_if_fail(list != NULL, NULL);
+
+ Preset *preset = g_slice_new(Preset);
+ preset->name = NULL;
+ preset->params = NULL;
+ preset->genetxs = NULL;
+
+ iter = list;
+ for (iter = list; iter; iter = g_list_next(iter)) {
+ data = (GString*) iter->data;
+ switch (get_message_id(data)) {
+ case RECEIVE_PRESET_START:
+ bank = (unsigned char)data->str[8];
+ number = (unsigned char)data->str[9];
+ name = g_strdup(&data->str[10]);
+ modified = (unsigned char)data->str[11+strlen(name)];
+
+ if ((bank == PRESETS_EDIT_BUFFER) && (number == 0)) {
+ g_message("Received current edit buffer");
+ } else {
+ g_message("Received preset %d from bank %d", number, bank);
+ }
+
+ g_message("Modified flag: %d Name: %s", modified, name);
+ preset->name = name;
+ break;
+ case RECEIVE_PRESET_PARAMETERS:
+ x = 0x09;
+ n = 0;
+ total = (unsigned char)data->str[x];
+ x++;
+
+ do {
+ SettingParam *param = setting_param_new_from_data(&data->str[x], &x);
+ n++;
+ preset->params = g_list_prepend(preset->params, param);
+ g_message("%d ID %d Position %d Value %d", n, param->id, param->position, param->value);
+ } while ((x < data->len) && n<total);
+ g_message("TOTAL %d", total);
+ preset->params = g_list_reverse(preset->params);
+ break;
+ case RECEIVE_PRESET_END:
+ break;
+ default:
+ g_message("Unhandled message in preset messages list");
+ }
+ }
+
+ return preset;
+}
+
+/**
+ * \param preset preset to be freed
+ *
+ * Frees all memory used by preset.
+ **/
+void preset_free(Preset *preset)
+{
+ g_return_if_fail(preset != NULL);
+
+ if (preset->params != NULL) {
+ GList *iter;
+ for (iter = preset->params; iter; iter = iter->next) {
+ setting_param_free((SettingParam*)iter->data);
+ }
+ g_list_free(preset->params);
+ }
+
+ if (preset->genetxs != NULL) {
+ GList *iter;
+ for (iter = preset->genetxs; iter; iter = iter->next) {
+ setting_genetx_free((SettingGenetx*)iter->data);
+ }
+ g_list_free(preset->genetxs);
+ }
+
+ g_free(preset->name);
+
+ g_slice_free(Preset, preset);
+}
diff --git a/preset.h b/preset.h
new file mode 100644
index 0000000..95d92d7
--- /dev/null
+++ b/preset.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Tomasz Moń <desowin@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef GDIGI_PRESET_H
+#define GDIGI_PRESET_H
+
+#include <glib.h>
+
+typedef struct {
+ gchar *name;
+ GList *params;
+ GList *genetxs;
+} Preset;
+
+Preset *create_preset_from_xml_file(gchar *filename, GError **error);
+Preset *create_preset_from_data(GList *list);
+void preset_free(Preset *preset);
+
+#endif /* GDIGI_PRESET_H */