From 149af1941d60351a79695f47fdd30d2631d4c8a7 Mon Sep 17 00:00:00 2001 From: RobU Date: Wed, 10 May 2017 07:22:36 +0100 Subject: [PATCH 01/27] reapack indexing --- index.xml | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 index.xml diff --git a/index.xml b/index.xml new file mode 100644 index 0000000..30aca5b --- /dev/null +++ b/index.xml @@ -0,0 +1,71 @@ + + + + + + + Forum Thread + https://www.paypal.me/RobUrquhart + + + + https://github.com/RobU23/ReaScripts/raw/b425115e55ea654c8916ef6c3a3ee71b359a87d0/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/b425115e55ea654c8916ef6c3a3ee71b359a87d0/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/b425115e55ea654c8916ef6c3a3ee71b359a87d0/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + https://github.com/RobU23/ReaScripts/raw/b425115e55ea654c8916ef6c3a3ee71b359a87d0/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + + https://github.com/RobU23/ReaScripts/raw/2116b22f05844ed25267fb03e6190063c1480afe/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/2116b22f05844ed25267fb03e6190063c1480afe/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/2116b22f05844ed25267fb03e6190063c1480afe/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + https://github.com/RobU23/ReaScripts/raw/2116b22f05844ed25267fb03e6190063c1480afe/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + + From bdb6bafffec96a855de0d63b54a5fb72cc273ff8 Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 13 May 2017 18:17:57 +0100 Subject: [PATCH 02/27] index: 1 modified package, 1 new version --- index.xml | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/index.xml b/index.xml index 30aca5b..e9d17cf 100644 --- a/index.xml +++ b/index.xml @@ -1,5 +1,5 @@ - + @@ -66,6 +66,30 @@ added right-click reset for sliders (right-click the textbox)]]> https://github.com/RobU23/ReaScripts/raw/2116b22f05844ed25267fb03e6190063c1480afe/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua https://github.com/RobU23/ReaScripts/raw/2116b22f05844ed25267fb03e6190063c1480afe/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + https://github.com/RobU23/ReaScripts/raw/af80cdadc76b1dbe4fcfc4cc3f946f4b9df5dd36/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/af80cdadc76b1dbe4fcfc4cc3f946f4b9df5dd36/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/af80cdadc76b1dbe4fcfc4cc3f946f4b9df5dd36/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + https://github.com/RobU23/ReaScripts/raw/af80cdadc76b1dbe4fcfc4cc3f946f4b9df5dd36/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + From 347b968423f8128bff2cce22e9f4ce4abc9587c4 Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 13 May 2017 18:34:47 +0100 Subject: [PATCH 03/27] Update README.md --- MIDI Editor/MIDI Ex Machina/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MIDI Editor/MIDI Ex Machina/README.md b/MIDI Editor/MIDI Ex Machina/README.md index c88bd95..7eef7c4 100644 --- a/MIDI Editor/MIDI Ex Machina/README.md +++ b/MIDI Editor/MIDI Ex Machina/README.md @@ -12,6 +12,7 @@ Features * Note length probability sliders * Accent level and probability sliders * Legato probability slider + * Shift notes left or right by grid size * Options toggle (seq, acc, leg, rnd, etc..) * Euclidean sequencer * Pulse, steps, and rotation euclidean sliders From d511a4d55555fa8071014613aa1812563bb45a23 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 18 Mar 2018 13:20:09 +0000 Subject: [PATCH 04/27] Create LICENSE --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. From f1253dd4c7fcf947070db945ee9c9941c8d80c56 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 18 Mar 2018 13:20:09 +0000 Subject: [PATCH 05/27] Create LICENSE --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. From 70d59fc252bc336730149d0220a11331a57d9088 Mon Sep 17 00:00:00 2001 From: robu Date: Sun, 10 Feb 2019 14:55:01 +0000 Subject: [PATCH 06/27] Revert "Create LICENSE" This reverts commit f1253dd4c7fcf947070db945ee9c9941c8d80c56. --- LICENSE | 674 -------------------------------------------------------- 1 file changed, 674 deletions(-) delete mode 100644 LICENSE diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 94a9ed0..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - 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. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 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 . - -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: - - Copyright (C) - 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 -. - - 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 -. From aa8326c54fffd870a218f0fffd47a8f7b4314c4c Mon Sep 17 00:00:00 2001 From: robu Date: Sun, 10 Feb 2019 14:55:12 +0000 Subject: [PATCH 07/27] Revert "Revert "Create LICENSE"" This reverts commit 70d59fc252bc336730149d0220a11331a57d9088. --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. From 198aa4189ea337679a0e970c7fd72509fca39b50 Mon Sep 17 00:00:00 2001 From: robu Date: Sun, 10 Feb 2019 16:57:20 +0000 Subject: [PATCH 08/27] Minor scale tweaks --- MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 8f5d424..470415f 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -131,9 +131,9 @@ m.notes = {'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B', 'C'} m.scales = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, name = "Chromatic"}, {0, 2, 4, 5, 7, 9, 11, 12, name = "Ionian / Major"}, - {0, 2, 3, 5, 6, 9, 10, 12, name = "Dorian"}, + {0, 2, 3, 5, 7, 9, 10, 12, name = "Dorian"}, {0, 1, 3, 5, 7, 8, 10, 12, name = "Phrygian"}, - {0, 2, 4, 6, 7, 9, 11, 12, name = "Lyndian"}, + {0, 2, 4, 6, 7, 9, 11, 12, name = "Lydian"}, {0, 2, 4, 5, 7, 9, 10, 12, name = "Mixolydian"}, {0, 2, 3, 5, 7, 8, 10, 12, name = "Aeolian / Minor"}, {0, 1, 3, 5, 6, 8, 10, 12, name = "Locrian"}, From 2ac1c28669a5dc429a83b3c0e84e6230e8d14ce3 Mon Sep 17 00:00:00 2001 From: robu Date: Sun, 10 Feb 2019 18:20:43 +0000 Subject: [PATCH 09/27] Fixed looped items (thanks Thrash) Fixed scale issues (thanks Mike) Added some scales Added OSX font size kludge --- .../RobU - MIDI Ex Machina.lua | 155 ++++++++++-------- 1 file changed, 89 insertions(+), 66 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 470415f..4fbbae4 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -28,9 +28,13 @@ @donation https://www.paypal.me/RobUrquhart @link Reaper http://reaper.fm @link Forum Thread http://reaper.fm -@version 1.3.2 +@version 1.3.3 @author RobU @changelog + v1.3.3 + fixed looped item bug (thanks Thrash!) + fixed scales (dorian), added some new, minor tweaks (thanks Mike!) + added dirty OSX font cludge, might work, might not... v1.3.2 fixed bug all note sliders at zero causes crash added sequencer note shifter (left / right by grid size) @@ -56,7 +60,7 @@ [nomain] persistence.lua Reaper 5.x -Extensions: None +Extensions: SWS Licenced under the GPL v3 --]] -------------------------------------------------------------------------------- @@ -74,14 +78,24 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, m = {} -- all ex machina data -- user changeable defaults are marked with "(option)" m.debug = false +m.OS = reaper.GetOS() -- window -m.win_title = "RobU : MIDI Ex Machina - v1.3.2"; m.win_dockstate = 0 +m.win_title = "RobU : MIDI Ex Machina - v1.3.3"; m.win_dockstate = 0 m.win_x = 10; m.win_y = 10; m.win_w = 900; m.win_h = 280 -- window dimensions m.win_bg = {0, 0, 0} -- background colour m.def_zoom = 4 -- 100% (option) +m.font_sz = 16 -- zoom values are 1=70, 2=80, 3=90, 4=100, 5=110%, 6=120, 7=140, 8=160, 9=180, 10=200 m.zoomF = false +if string.match(m.OS, "Win") then + -- nada +elseif string.match(m.OS, "OSX") then + m.font_sz = m.font_sz - 2 +else + -- nada +end + -- default octave & key -- due to some quirk, oct 4 is really oct 3... m.oct = 4; m.key = 1; m.root = 0 -- (options, except m.root) @@ -130,16 +144,23 @@ m.euclid = {} -- for pattern generation m.notes = {'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B', 'C'} m.scales = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, name = "Chromatic"}, - {0, 2, 4, 5, 7, 9, 11, 12, name = "Ionian / Major"}, - {0, 2, 3, 5, 7, 9, 10, 12, name = "Dorian"}, - {0, 1, 3, 5, 7, 8, 10, 12, name = "Phrygian"}, - {0, 2, 4, 6, 7, 9, 11, 12, name = "Lydian"}, - {0, 2, 4, 5, 7, 9, 10, 12, name = "Mixolydian"}, {0, 2, 3, 5, 7, 8, 10, 12, name = "Aeolian / Minor"}, + {0, 2, 3, 5, 7, 9, 10, 12, name = "Dorian"}, + {0, 2, 4, 5, 7, 9, 11, 12, name = "Ionian / Major"}, {0, 1, 3, 5, 6, 8, 10, 12, name = "Locrian"}, - {0, 3, 5, 6, 7, 10, 12,name = "Blues"}, - {0, 2, 4, 7, 9, 12,name = "Pentatonic Major"}, - {0, 3, 5, 7, 10, 12,name = "Pentatonic Minor"}, + {0, 2, 4, 6, 7, 9, 11, 12, name = "Lydian"}, + {0, 2, 4, 5, 7, 9, 10, 12, name = "Mixolydian"}, + {0, 1, 3, 5, 7, 8, 10, 12, name = "Phrygian"}, + {0, 3, 5, 6, 7, 10, 12, name = "Blues"}, + {0, 1, 4, 5, 7, 8, 11, 12, name = "Dbl. Harmonic"}, + {0, 1, 3, 6, 8, 10, 11, 12, name = "Enigmatic"}, + {0, 1, 4, 5, 7, 8, 11, 12, name = "Flamenco"}, + {0, 2, 4, 5, 7, 8, 11, 12, name = "Harmonic Maj"}, + {0, 2, 3, 5, 7, 8, 11, 12, name = "Harmonic min"}, + {0, 2, 3, 5, 7, 9, 11, 12, name = "Melodic min"}, + {0, 2, 4, 7, 9, 12, name = "Pentatonic Maj"}, + {0, 3, 5, 7, 10, 12, name = "Pentatonic min"}, + {0, 1, 4, 5, 6, 8, 11, 12, name = "Persian"}, {name = "Permute"} } -- a list of scales available to the note randomiser, more can be added manually if required @@ -428,6 +449,8 @@ function GetItemLength() ConMsg("Num of Bar = " .. numBarsPerItem) ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") end + mItemTake = reaper.GetTake(mItem, 0) -- should fix looped items + ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! return ItemPPQN end -------------------------------------------------------------------------------- @@ -1025,14 +1048,14 @@ end -------------------------------------------------------------------------------- -- Persistent window elements local winFrame = e.Frame:new({0}, 5, 5, m.win_w - 10, m.win_h - 10, e.col_grey4) -local zoomDrop = e.Droplist:new({0}, 5, 5, 40, 22, e.col_green, "", e.Arial, 16, e.col_grey8, 4, {"70%", "80%", "90%", "100%", "110%", "120%", "140%", "160%", "180%", "200%"}) -local winText = e.Textbox:new({0}, 45, 5, m.win_w - 50, 22, e.col_green, "MIDI Ex Machina ", e.Arial, 16, e.col_grey8) -local layerBtn01 = e.Button:new({0}, 5, m.win_h - 25, 100, 20, e.col_green, "Randomiser", e.Arial, 16, e.col_grey8) -local layerBtn02 = e.Button:new({0}, 105, m.win_h - 25, 100, 20, e.col_grey5, "Sequencer", e.Arial, 16, e.col_grey7) -local layerBtn03 = e.Button:new({0}, 205, m.win_h - 25, 100, 20, e.col_grey5, "Euclidiser", e.Arial, 16, e.col_grey7) -local layerBtn04 = e.Button:new({0}, 305, m.win_h - 25, 100, 20, e.col_grey5, "Options", e.Arial, 16, e.col_grey7) -local undoBtn = e.Button:new({0}, m.win_w-85, m.win_h -25, 40, 20, e.col_grey5, "Undo", e.Arial, 16, e.col_grey7) -local redoBtn = e.Button:new({0}, m.win_w-45, m.win_h -25, 40, 20, e.col_grey5, "Redo", e.Arial, 16, e.col_grey7) +local zoomDrop = e.Droplist:new({0}, 5, 5, 40, 22, e.col_green, "", e.Arial, m.font_sz, e.col_grey8, 4, {"70%", "80%", "90%", "100%", "110%", "120%", "140%", "160%", "180%", "200%"}) +local winText = e.Textbox:new({0}, 45, 5, m.win_w - 50, 22, e.col_green, "MIDI Ex Machina ", e.Arial, m.font_sz, e.col_grey8) +local layerBtn01 = e.Button:new({0}, 5, m.win_h - 25, 100, 20, e.col_green, "Randomiser", e.Arial, m.font_sz, e.col_grey8) +local layerBtn02 = e.Button:new({0}, 105, m.win_h - 25, 100, 20, e.col_grey5, "Sequencer", e.Arial, m.font_sz, e.col_grey7) +local layerBtn03 = e.Button:new({0}, 205, m.win_h - 25, 100, 20, e.col_grey5, "Euclidiser", e.Arial, m.font_sz, e.col_grey7) +local layerBtn04 = e.Button:new({0}, 305, m.win_h - 25, 100, 20, e.col_grey5, "Options", e.Arial, m.font_sz, e.col_grey7) +local undoBtn = e.Button:new({0}, m.win_w-85, m.win_h -25, 40, 20, e.col_grey5, "Undo", e.Arial, m.font_sz, e.col_grey7) +local redoBtn = e.Button:new({0}, m.win_w-45, m.win_h -25, 40, 20, e.col_grey5, "Redo", e.Arial, m.font_sz, e.col_grey7) -- Persistent window element table t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03, layerBtn04, undoBtn, redoBtn} @@ -1041,100 +1064,100 @@ t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03 -------------------------------------------------------------------------------- -- key, octave, & scale droplists dx, dy, dw, dh = 25, 70, 110, 20 -local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", e.Arial, 16, e.col_grey8, m.key, m.notes) -local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", e.Arial, 16, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) -local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", e.Arial, 16, e.col_grey8, 1, m.scalelist) +local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", e.Arial, m.font_sz, e.col_grey8, m.key, m.notes) +local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", e.Arial, m.font_sz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) +local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", e.Arial, m.font_sz, e.col_grey8, 1, m.scalelist) local t_Droplists = {keyDrop, octDrop, scaleDrop} -------------------------------------------------------------------------------- -- Randomiser Layer -------------------------------------------------------------------------------- -- note randomise button -local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Generate", e.Arial, 16, e.col_grey8) +local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Generate", e.Arial, m.font_sz, e.col_grey8) -- note weight sliders local nx, ny, nw, nh, np = 160, 50, 30, 150, 40 -local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr02 = e.Vert_Slider:new({1}, nx+(np*1), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr03 = e.Vert_Slider:new({1}, nx+(np*2), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr04 = e.Vert_Slider:new({1}, nx+(np*3), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr05 = e.Vert_Slider:new({1}, nx+(np*4), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr06 = e.Vert_Slider:new({1}, nx+(np*5), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr07 = e.Vert_Slider:new({1}, nx+(np*6), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr08 = e.Vert_Slider:new({1}, nx+(np*7), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr09 = e.Vert_Slider:new({1}, nx+(np*8), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr10 = e.Vert_Slider:new({1}, nx+(np*9), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr11 = e.Vert_Slider:new({1}, nx+(np*10), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr12 = e.Vert_Slider:new({1}, nx+(np*11), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) -local noteSldr13 = e.Vert_Slider:new({1}, nx+(np*12), ny, nw, nh, e.col_blue, "", e.Arial, 16, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr02 = e.Vert_Slider:new({1}, nx+(np*1), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr03 = e.Vert_Slider:new({1}, nx+(np*2), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr04 = e.Vert_Slider:new({1}, nx+(np*3), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr05 = e.Vert_Slider:new({1}, nx+(np*4), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr06 = e.Vert_Slider:new({1}, nx+(np*5), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr07 = e.Vert_Slider:new({1}, nx+(np*6), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr08 = e.Vert_Slider:new({1}, nx+(np*7), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr09 = e.Vert_Slider:new({1}, nx+(np*8), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr10 = e.Vert_Slider:new({1}, nx+(np*9), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr11 = e.Vert_Slider:new({1}, nx+(np*10), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr12 = e.Vert_Slider:new({1}, nx+(np*11), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) +local noteSldr13 = e.Vert_Slider:new({1}, nx+(np*12), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) -- Note probability slider table local t_noteSliders = {noteSldr01, noteSldr02, noteSldr03, noteSldr04, noteSldr05, noteSldr06, noteSldr07, noteSldr08, noteSldr09, noteSldr10, noteSldr11, noteSldr12, noteSldr13} -- Note probability slider label (Textbox) - right-click to reset all -local probSldrText = e.Textbox:new({1}, nx, 210, 510, 20, e.col_grey5, "Note Weight Sliders", e.Arial, 16, e.col_grey7) +local probSldrText = e.Textbox:new({1}, nx, 210, 510, 20, e.col_grey5, "Note Weight Sliders", e.Arial, m.font_sz, e.col_grey7) -- Note octave doubler probability slider -local octProbSldr = e.Vert_Slider:new({1}, nx+(np*13) + 10, ny, nw, nh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.rndOctProb, 0, 0, 10, 1) -local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", e.Arial, 16, e.col_grey7) +local octProbSldr = e.Vert_Slider:new({1}, nx+(np*13) + 10, ny, nw, nh, e.col_blue, "%", e.Arial, m.font_sz, e.col_grey8, m.rndOctProb, 0, 0, 10, 1) +local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", e.Arial, m.font_sz, e.col_grey7) -- Note randomiser options -local noteOptionsCb = e.Checkbox:new({1}, nx+(np*14)+10, ny+30, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) -local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_grey5, "Options", e.Arial, 16, e.col_grey7) +local noteOptionsCb = e.Checkbox:new({1}, nx+(np*14)+10, ny+30, 30, 30, e.col_orange, "", e.Arial, m.font_sz, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) +local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_grey5, "Options", e.Arial, m.font_sz, e.col_grey7) -------------------------------------------------------------------------------- -- Sequencer Layer -------------------------------------------------------------------------------- -- sequence generate button -local sequenceBtn = e.Button:new({2}, 25, 205, 110, 25, e.col_yellow, "Generate", e.Arial, 16, e.col_grey8) +local sequenceBtn = e.Button:new({2}, 25, 205, 110, 25, e.col_yellow, "Generate", e.Arial, m.font_sz, e.col_grey8) local sx, sy, sw, sh, sp = 160, 50, 30, 150, 40 -- sequencer grid size radio selector -local seqGridRad = e.Rad_Button:new({2,3}, sx, sy + 40, 30, 30, e.col_yellow, "", e.Arial, 16, e.col_grey8, 1, {"1/16", "1/8", "1/4"}) -local seqGridText = e.Textbox:new({2,3}, sx, 210, (sw*2)+20, 20, e.col_grey5, "Grid Size", e.Arial, 16, e.col_grey7) +local seqGridRad = e.Rad_Button:new({2,3}, sx, sy + 40, 30, 30, e.col_yellow, "", e.Arial, m.font_sz, e.col_grey8, 1, {"1/16", "1/8", "1/4"}) +local seqGridText = e.Textbox:new({2,3}, sx, 210, (sw*2)+20, 20, e.col_grey5, "Grid Size", e.Arial, m.font_sz, e.col_grey7) -- sequence grid probability sliders -local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*3), sy, sw, sh, e.col_blue, "1/16", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*4), sy, sw, sh, e.col_blue, "1/8", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*5), sy, sw, sh, e.col_blue, "1/4", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) -local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*6), sy, sw, sh, e.col_blue, "Rest", e.Arial, 16, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*3), sy, sw, sh, e.col_blue, "1/16", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*4), sy, sw, sh, e.col_blue, "1/8", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*5), sy, sw, sh, e.col_blue, "1/4", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) +local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*6), sy, sw, sh, e.col_blue, "Rest", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) -- sequence grid probability slider table local t_seqSliders = {seqSldr16, seqSldr8, seqSldr4, seqSldrRest} -- sequence grid probability sliders label - right click to reset all (per grid size selection) -local seqSldrText = e.Textbox:new({2}, sx + (sp * 3), 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", e.Arial, 16, e.col_grey7) +local seqSldrText = e.Textbox:new({2}, sx + (sp * 3), 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", e.Arial, m.font_sz, e.col_grey7) -- velocity accent slider (shared with Euclid layer) -local seqAccRSldr = e.V_Rng_Slider:new({2,3}, sx + (sp * 8) - (sw / 2), sy, sw, sh, e.col_blue, "", e.Arial, 16, e.col_grey8, m.accentLow, m.accentHigh, 0, 127, 1) -local seqAccProbSldr = e.Vert_Slider:new({2,3}, sx + (sp * 9) - (sw / 2), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.accentProb, 0, 0, 10, 1) -local seqAccSldrText = e.Textbox:new({2,3}, sx + (sp * 8) - (sw / 2), 210, (sw * 2) + 10, 20, e.col_grey5, "Vel | Acc", e.Arial, 16, e.col_grey7) +local seqAccRSldr = e.V_Rng_Slider:new({2,3}, sx + (sp * 8) - (sw / 2), sy, sw, sh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, m.accentLow, m.accentHigh, 0, 127, 1) +local seqAccProbSldr = e.Vert_Slider:new({2,3}, sx + (sp * 9) - (sw / 2), sy, sw, sh, e.col_blue, "%", e.Arial, m.font_sz, e.col_grey8, m.accentProb, 0, 0, 10, 1) +local seqAccSldrText = e.Textbox:new({2,3}, sx + (sp * 8) - (sw / 2), 210, (sw * 2) + 10, 20, e.col_grey5, "Vel | Acc", e.Arial, m.font_sz, e.col_grey7) -- legato slider -local seqLegProbSldr = e.Vert_Slider:new({2}, sx + (sp * 10) - (sw / 2), sy, sw, sh, e.col_blue, "%", e.Arial, 16, e.col_grey8, m.legatoProb, 0, 0, 10, 1) -local seqLegSldrText = e.Textbox:new({2}, sx + (sp * 10) - (sw / 2), 210, sw, 20, e.col_grey5, "Leg", e.Arial, 16, e.col_grey7) +local seqLegProbSldr = e.Vert_Slider:new({2}, sx + (sp * 10) - (sw / 2), sy, sw, sh, e.col_blue, "%", e.Arial, m.font_sz, e.col_grey8, m.legatoProb, 0, 0, 10, 1) +local seqLegSldrText = e.Textbox:new({2}, sx + (sp * 10) - (sw / 2), 210, sw, 20, e.col_grey5, "Leg", e.Arial, m.font_sz, e.col_grey7) -- sequence shift buttons -local seqShiftLBtn = e.Button:new({2}, sx + (sp * 11) + 10, sy + sh - 25, sw, 25, e.col_blue, "<<", e.Arial, 16, e.col_grey8) -local seqShiftRBtn = e.Button:new({2}, sx + (sp * 13) - 10, sy + sh - 25, sw, 25, e.col_blue, ">>", e.Arial, 16, e.col_grey8) -local seqShiftVal = e.Textbox:new({2}, sx + (sp * 12), sy + sh - 25, sw, 25, e.col_grey5, tostring(m.seqShift), e.Arial, 16, e.col_grey7) -local seqShiftText = e.Textbox:new({2}, sx + (sp * 11) + 10, 210, sw * 3, 20, e.col_grey5, "Shift Notes", e.Arial, 16, e.col_grey7) +local seqShiftLBtn = e.Button:new({2}, sx + (sp * 11) + 10, sy + sh - 25, sw, 25, e.col_blue, "<<", e.Arial, m.font_sz, e.col_grey8) +local seqShiftRBtn = e.Button:new({2}, sx + (sp * 13) - 10, sy + sh - 25, sw, 25, e.col_blue, ">>", e.Arial, m.font_sz, e.col_grey8) +local seqShiftVal = e.Textbox:new({2}, sx + (sp * 12), sy + sh - 25, sw, 25, e.col_grey5, tostring(m.seqShift), e.Arial, m.font_sz, e.col_grey7) +local seqShiftText = e.Textbox:new({2}, sx + (sp * 11) + 10, 210, sw * 3, 20, e.col_grey5, "Shift Notes", e.Arial, m.font_sz, e.col_grey7) -- Sequencer options -local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 14) + 10, sy + 5, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0,0,0}, {"Generate", "1st Note Always", "Accent", "Legato", "Rnd Notes"}) +local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 14) + 10, sy + 5, 30, 30, e.col_orange, "", e.Arial, m.font_sz, e.col_grey8, {0,0,0,0,0}, {"Generate", "1st Note Always", "Accent", "Legato", "Rnd Notes"}) -------------------------------------------------------------------------------- -- Euclid Layer -------------------------------------------------------------------------------- -- euclid generate button -local euclidBtn = e.Button:new({3}, 25, 205, 110, 25, e.col_orange, "Generate", Arial, 16, e.col_grey8) +local euclidBtn = e.Button:new({3}, 25, 205, 110, 25, e.col_orange, "Generate", Arial, m.font_sz, e.col_grey8) -- euclidean sliders local ex, ey, ew, eh, ep = 160, 50, 30, 150, 40 -local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Puls", Arial, 16, e.col_grey8, m.eucPulses, 0, 1, 24, 1) -local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Step", Arial, 16, e.col_grey8, m.eucSteps, 0, 1, 24, 1) -local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*5), ey, ew, eh, e.col_blue, "Rot", Arial, 16, e.col_grey8, m.eucRot, 0, 0, 24, 1) +local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Puls", Arial, m.font_sz, e.col_grey8, m.eucPulses, 0, 1, 24, 1) +local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Step", Arial, m.font_sz, e.col_grey8, m.eucSteps, 0, 1, 24, 1) +local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*5), ey, ew, eh, e.col_blue, "Rot", Arial, m.font_sz, e.col_grey8, m.eucRot, 0, 0, 24, 1) local t_euclidSliders = {euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr} -- euclid slider label - right click to reset all -local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 3), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", Arial, 16, e.col_grey7) +local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 3), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", Arial, m.font_sz, e.col_grey7) -- Sequencer options -local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 14) + 10, ey + 40, 30, 30, e.col_orange, "", e.Arial, 16, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) +local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 14) + 10, ey + 40, 30, 30, e.col_orange, "", e.Arial, m.font_sz, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) -------------------------------------------------------------------------------- -- Options Layer -------------------------------------------------------------------------------- -local optText = e.Textbox:new({4}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_grey5, "Nothing to see here, yet...", e.Arial, 16, e.col_grey8) +local optText = e.Textbox:new({4}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_grey5, "Nothing to see here, yet...", e.Arial, m.font_sz, e.col_grey8) -------------------------------------------------------------------------------- -- Messages Layer From 3ebe536510ca77adeef647dd7e552aa956f9cb03 Mon Sep 17 00:00:00 2001 From: RobU Date: Sun, 10 Feb 2019 18:32:32 +0000 Subject: [PATCH 10/27] index: 1 modified package, 1 new version --- index.xml | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/index.xml b/index.xml index e9d17cf..32a97be 100644 --- a/index.xml +++ b/index.xml @@ -1,5 +1,5 @@ - + @@ -90,6 +90,34 @@ added right-click reset for sliders (right-click the textbox)]]> https://github.com/RobU23/ReaScripts/raw/af80cdadc76b1dbe4fcfc4cc3f946f4b9df5dd36/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua https://github.com/RobU23/ReaScripts/raw/af80cdadc76b1dbe4fcfc4cc3f946f4b9df5dd36/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + https://github.com/RobU23/ReaScripts/raw/2ac1c28669a5dc429a83b3c0e84e6230e8d14ce3/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/2ac1c28669a5dc429a83b3c0e84e6230e8d14ce3/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/2ac1c28669a5dc429a83b3c0e84e6230e8d14ce3/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + https://github.com/RobU23/ReaScripts/raw/2ac1c28669a5dc429a83b3c0e84e6230e8d14ce3/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + From 6fc14048fee05b74b2888e5a5a69061eabe3630f Mon Sep 17 00:00:00 2001 From: robu Date: Tue, 12 Feb 2019 22:15:57 +0000 Subject: [PATCH 11/27] bug fix - shifting notes in looped items --- .../RobU - MIDI Ex Machina.lua | 172 +++++++----------- 1 file changed, 67 insertions(+), 105 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 4fbbae4..1e38c54 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -28,31 +28,11 @@ @donation https://www.paypal.me/RobUrquhart @link Reaper http://reaper.fm @link Forum Thread http://reaper.fm -@version 1.3.3 +@version 1.3.4 @author RobU @changelog - v1.3.3 - fixed looped item bug (thanks Thrash!) - fixed scales (dorian), added some new, minor tweaks (thanks Mike!) - added dirty OSX font cludge, might work, might not... - v1.3.2 - fixed bug all note sliders at zero causes crash - added sequencer note shifter (left / right by grid size) - v1.3 - added monophonic sequence generator - added euclidean sequence generator (bjorklund algorithm) - added all/selected notes option - added force first note to root option - added randomise octave option - added permute scale in note randomiser - added force first note in sequence generator - added velocity/accent randomisation to sequence/euclidean generators - added legato randomisation to sequence generator - added rotation slider to euclidean generator - added active-take detection - added undo/redo - added script state save/restore to Reaper project file - added right-click reset for sliders (right-click the textbox) + v1.3.4 + fixed looped item note shifting bug @provides [main=midi_editor] . [nomain] eGUI.lua @@ -80,7 +60,7 @@ m = {} -- all ex machina data m.debug = false m.OS = reaper.GetOS() -- window -m.win_title = "RobU : MIDI Ex Machina - v1.3.3"; m.win_dockstate = 0 +m.win_title = "RobU : MIDI Ex Machina - v1.3.4"; m.win_dockstate = 0 m.win_x = 10; m.win_y = 10; m.win_w = 900; m.win_h = 280 -- window dimensions m.win_bg = {0, 0, 0} -- background colour m.def_zoom = 4 -- 100% (option) @@ -123,7 +103,7 @@ m.legato = -10 -- default legatolessness value m.accentLow = 100; m.accentHigh = 127; m.accentProb = 3 -- default values (options) -- accentLow/High - min 0, max 127; accentProb - min 0, max 10 m.legatoProb = 3 -- default value (option - min 0, max 10) -m.seqGrid16 = {8, 8, 0, 4} -- sane default sequencer note length slider values +m.seqGrid16 = {8, 4, 0, 2} -- sane default sequencer note length slider values m.seqGrid8 = {0, 8, 2, 2} -- sane default sequencer note length slider values m.seqGrid4 = {0, 2, 8, 1} -- sane default sequencer note length slider values m.seqShift = 0; m.seqShiftMin = -16; m.seqShiftMax = 16 -- shift notes left-right from sequencer @@ -188,59 +168,32 @@ pExtStateStr = "" -- pickled string. a nom a nom a nom... -- Utility Functions Start -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --- Bitfields - set, clear, flip, or check bits - returns a bitfield, or bool (check) --------------------------------------------------------------------------------- -local function BitSet(bitField, bitIdx) - return bitField | (1 << bitIdx) -end --------------------------------------------------------------------------------- -local function BitClear(bitField, bitIdx) - return bitField & ~(1 << bitIdx) -end --------------------------------------------------------------------------------- -local function BitFlip(bitField, bitIdx) - return bitField ~ (1 << bitIdx) -end --------------------------------------------------------------------------------- -local function BitCheck(bitField, bitIdx) - return (bitField & (1 << bitIdx) ~= 0) and true or false -end --------------------------------------------------------------------------------- --- GetSign(n) -return -1 or 1 --------------------------------------------------------------------------------- -function GetSign(n) - return n > 0 and 1 or n < 0 and -1 or 1 -end --------------------------------------------------------------------------------- --- Wrap(n, max) -return n wrapped between 'n' and 'max' --------------------------------------------------------------------------------- + local function Wrap (n, max) +-- Wrap(n, max) -return n wrapped between 'n' and 'max' n = n % max if (n < 1) then n = n + max end return n end --------------------------------------------------------------------------------- --- RGB2Dec(r, g, b) - takes 8 bit r, g, b values, returns decimal (0 to 1) --------------------------------------------------------------------------------- + local function RGB2Dec(r, g, b) +-- RGB2Dec(r, g, b) - takes 8 bit r, g, b values, returns decimal (0 to 1) if r < 0 or r > 255 then r = wrap(r, 255) end if g < 0 or g > 255 then g = wrap(g, 255) end if b < 0 or b > 255 then b = wrap(b, 255) end return r/255, g/255, b/255 end --------------------------------------------------------------------------------- --- RGB2Packed(r, g, b) - returns a packed rgb value --------------------------------------------------------------------------------- + local function RGB2Packed(r, g, b) +-- RGB2Packed(r, g, b) - returns a packed rgb value local floor = math.floor g = (g << 8) b = (b << 16) return floor(r + g + b) end --------------------------------------------------------------------------------- --- ConMsg(str) - outputs 'str' to the Reaper console --------------------------------------------------------------------------------- + local function ConMsg(str) +-- ConMsg(str) - outputs 'str' to the Reaper console reaper.ShowConsoleMsg(str .."\n") end @@ -331,20 +284,17 @@ end -------------------------------------------------------------------------------- -- Ex Machina Functions Start -------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- ClearTable(t) - set all items in 2D table 't' to nil --------------------------------------------------------------------------------- function ClearTable(t) +-- ClearTable(t) - set all items in 2D table 't' to nil local debug = false if debug or m.debug then ConMsg("ClearTable()") end for k, v in pairs(t) do t[k] = nil end end --------------------------------------------------------------------------------- --- CopyTable(t1, t2) - copies note data from t1 to t2 --------------------------------------------------------------------------------- + function CopyTable(t1, t2) +-- CopyTable(t1, t2) - copies note data from t1 to t2 ClearTable(t2) local i = 1 while t1[i] do @@ -358,9 +308,10 @@ function CopyTable(t1, t2) end -- while t1[i] end -------------------------------------------------------------------------------- --- NewNoteBuf() - add a new note buffer to the table, returns handle +-- Note Buffers -------------------------------------------------------------------------------- local function NewNoteBuf() +-- NewNoteBuf() - add a new note buffer to the table, returns handle local debug = false if debug or m.debug then ConMsg("NewNoteBuf()") end m.notebuf.i = m.notebuf.i + 1 @@ -373,10 +324,9 @@ local function NewNoteBuf() end return m.notebuf[m.notebuf.i] end --------------------------------------------------------------------------------- --- GetNoteBuf() - returns handle to the current note buffer --------------------------------------------------------------------------------- + local function GetNoteBuf() +-- GetNoteBuf() - returns handle to the current note buffer local debug = false if debug or m.debug then ConMsg("GetNoteBuf()") end if m.notebuf.i >= 1 then @@ -388,10 +338,9 @@ local function GetNoteBuf() return m.notebuf[m.notebuf.i] end end --------------------------------------------------------------------------------- --- UndoNoteBuf() - points to previous note buffer --------------------------------------------------------------------------------- + local function UndoNoteBuf() +-- UndoNoteBuf() - points to previous note buffer local debug = false if debug or m.debug then ConMsg("UndoNoteBuf()") end if m.notebuf.i > 1 then @@ -409,10 +358,9 @@ local function UndoNoteBuf() end end end --------------------------------------------------------------------------------- --- PurgeNoteBuf() - purge all note buffers from current+1 to end --------------------------------------------------------------------------------- + local function PurgeNoteBuf() +-- PurgeNoteBuf() - purge all note buffers from current+1 to end local debug = false if debug or m.debug then ConMsg("PurgeNoteBuf()") @@ -426,6 +374,7 @@ local function PurgeNoteBuf() m.notebuf.max = m.notebuf.max - 1 end end + -------------------------------------------------------------------------------- -- GetItemLength(t) - get length of take 't', set various global vars -- currently it only returns the item length (used in Sequencer and Euclid) @@ -433,30 +382,30 @@ end function GetItemLength() local debug = false if debug or m.debug then ConMsg("GetItemLength()") end - mItem = reaper.GetSelectedMediaItem(0, 0) - mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") - mBPM, mBPI = reaper.GetProjectTimeSignature2(0) - msPerMin = 60000 - msPerQN = msPerMin / mBPM - numQNPerItem = (mItemLen * 1000) / msPerQN - numBarsPerItem = numQNPerItem / 4 - ItemPPQN = numQNPerItem * m.ppqn - if debug or m.debug then - ConMsg("ItemLen (ms) = " .. mItemLen) - ConMsg("mBPM = " .. mBPM) - ConMsg("MS Per QN = " .. msPerQN) - ConMsg("Num of QN = " .. numQNPerItem) - ConMsg("Num of Bar = " .. numBarsPerItem) - ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") - end - mItemTake = reaper.GetTake(mItem, 0) -- should fix looped items - ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! - return ItemPPQN + + mItem = reaper.GetSelectedMediaItem(0, 0) + mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") + mBPM, mBPI = reaper.GetProjectTimeSignature2(0) + msPerMin = 60000 + msPerQN = msPerMin / mBPM + numQNPerItem = (mItemLen * 1000) / msPerQN + numBarsPerItem = numQNPerItem / 4 + ItemPPQN = numQNPerItem * m.ppqn + if debug or m.debug then + ConMsg("ItemLen (ms) = " .. mItemLen) + ConMsg("mBPM = " .. mBPM) + ConMsg("MS Per QN = " .. msPerQN) + ConMsg("Num of QN = " .. numQNPerItem) + ConMsg("Num of Bar = " .. numBarsPerItem) + ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") + end + mItemTake = reaper.GetTake(mItem, 0) -- should fix looped items + ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! + return ItemPPQN end --------------------------------------------------------------------------------- --- GetReaperGrid() - get the current grid size, set global var m.reaGrid --------------------------------------------------------------------------------- + function GetReaperGrid(gridRad) +-- GetReaperGrid() - get the current grid size, set global var m.reaGrid local debug = false if debug or m.debug then ConMsg("GetReaperGrid()") end if m.activeTake then @@ -935,24 +884,37 @@ function InsertNotes() DeleteNotes() local i = 1 if m.activeTake then + local noteLength = 0 local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() local noteShift = m.seqShift * gridSize local t1 = GetNoteBuf() local t2 = {} -- for note shifting CopyTable(t1, t2) + if debug then ConMsg("itemPPQN = "..itemLength) end + if debug then ConMsg("noteshift = "..noteShift) end + for k, v in pairs(t2) do -- do note shifting + noteLength = v[4] - v[3] v[3] = v[3] + noteShift - v[4] = v[4] + noteShift - if v[3] < 0 then - v[3] = itemLength + v[3] - v[4] = itemLength + v[4] - if v[4] > itemLength then v[4] = itemLength + m.legato end - elseif v[3] >= itemLength then + v[4] = v[4] + noteShift + + if v[3] >= itemLength then -- positive shift v[3] = v[3] - itemLength - v[4] = v[4] - itemLength + v[4] = v[4] - itemLength + + elseif v[3] < 0 then -- negative shift + v[3] = v[3] + itemLength + v[4] = v[4] + itemLength + end + + if v[4] > itemLength then v[4] = itemLength - 1 end + + if debug then ConMsg("v3 = "..v[3].." ".."v4 = "..v[4].." ".."notelen = "..noteLength) end end + + while t2[i] do reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) From 2d38191a0d753d26d1096c6758366cdb735dc19e Mon Sep 17 00:00:00 2001 From: RobU Date: Tue, 12 Feb 2019 22:23:55 +0000 Subject: [PATCH 12/27] index: 1 modified package, 1 new version --- index.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/index.xml b/index.xml index 32a97be..f4f3840 100644 --- a/index.xml +++ b/index.xml @@ -1,5 +1,5 @@ - + @@ -118,6 +118,14 @@ added right-click reset for sliders (right-click the textbox)]]> https://github.com/RobU23/ReaScripts/raw/2ac1c28669a5dc429a83b3c0e84e6230e8d14ce3/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua https://github.com/RobU23/ReaScripts/raw/2ac1c28669a5dc429a83b3c0e84e6230e8d14ce3/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + From 0798593912ccd7c03c5dfa8cfbcdcc4dfc855519 Mon Sep 17 00:00:00 2001 From: robu Date: Tue, 3 Dec 2019 22:49:02 +0000 Subject: [PATCH 13/27] Fix for error when no item selected in arrange. Found switch item bug - work in progress --- .../RobU - MIDI Ex Machina.lua | 194 +++++------ Stop_no_item_error_patch.diff | 317 ++++++++++++++++++ 2 files changed, 407 insertions(+), 104 deletions(-) create mode 100644 Stop_no_item_error_patch.diff diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 1e38c54..da244f3 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -57,7 +57,7 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, -------------------------------------------------------------------------------- m = {} -- all ex machina data -- user changeable defaults are marked with "(option)" -m.debug = false +m.debug = true m.OS = reaper.GetOS() -- window m.win_title = "RobU : MIDI Ex Machina - v1.3.4"; m.win_dockstate = 0 @@ -359,7 +359,7 @@ local function UndoNoteBuf() end end -local function PurgeNoteBuf() +local function PurgeNoteBuf(idx) -- PurgeNoteBuf() - purge all note buffers from current+1 to end local debug = false if debug or m.debug then @@ -383,25 +383,26 @@ function GetItemLength() local debug = false if debug or m.debug then ConMsg("GetItemLength()") end - mItem = reaper.GetSelectedMediaItem(0, 0) - mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") - mBPM, mBPI = reaper.GetProjectTimeSignature2(0) - msPerMin = 60000 - msPerQN = msPerMin / mBPM - numQNPerItem = (mItemLen * 1000) / msPerQN - numBarsPerItem = numQNPerItem / 4 - ItemPPQN = numQNPerItem * m.ppqn - if debug or m.debug then - ConMsg("ItemLen (ms) = " .. mItemLen) - ConMsg("mBPM = " .. mBPM) - ConMsg("MS Per QN = " .. msPerQN) - ConMsg("Num of QN = " .. numQNPerItem) - ConMsg("Num of Bar = " .. numBarsPerItem) - ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") - end - mItemTake = reaper.GetTake(mItem, 0) -- should fix looped items - ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! - return ItemPPQN + --mItem = reaper.GetSelectedMediaItem(0, 0) + mItemLen = reaper.GetMediaItemInfo_Value(m.mItem, "D_LENGTH") + mBPM, mBPI = reaper.GetProjectTimeSignature2(0) + msPerMin = 60000 + msPerQN = msPerMin / mBPM + numQNPerItem = (mItemLen * 1000) / msPerQN + numBarsPerItem = numQNPerItem / 4 + ItemPPQN = numQNPerItem * m.ppqn + if debug or m.debug then + ConMsg("ItemLen (ms) = " .. mItemLen) + ConMsg("mBPM = " .. mBPM) + ConMsg("MS Per QN = " .. msPerQN) + ConMsg("Num of QN = " .. numQNPerItem) + ConMsg("Num of Bar = " .. numBarsPerItem) + ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") + end + mItemTake = reaper.GetTake(m.mItem, 0) -- should fix looped items + ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! + return ItemPPQN + end function GetReaperGrid(gridRad) @@ -447,7 +448,7 @@ end -- GetNotesFromTake() - fill a note buffer from the active take -------------------------------------------------------------------------------- function GetNotesFromTake() - local debug = false + local debug = true if debug or m.debug then ConMsg("GetNotesFromTake()") end local i, t if m.activeTake then @@ -468,6 +469,7 @@ function GetNotesFromTake() t[i][8] = velocity end -- for i end -- num_notes + PrintNotes(GetNoteBuf()) else -- no active take if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake @@ -855,26 +857,7 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) PurgeNoteBuf() InsertNotes() end --------------------------------------------------------------------------------- --- SetNotes - arg notebuf t1; set notes in the active take --------------------------------------------------------------------------------- -function SetNotes() - local debug = false - if debug or m.debug then ConMsg("SetNotes()") end - local i = 1 - if m.activeTake then - local t1 = GetNoteBuf() - while t1[i] do - reaper.MIDI_SetNote(m.activeTake, i-1, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], __) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - i = i + 1 - end -- while t1[i] - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake -end + -------------------------------------------------------------------------------- -- InsertNotes(note_buffer) - insert notes in the active take -------------------------------------------------------------------------------- @@ -883,7 +866,7 @@ function InsertNotes() if debug or m.debug then ConMsg("\nInsertNotes()") end DeleteNotes() local i = 1 - if m.activeTake then + if m.activeTake and m.mItem then local noteLength = 0 local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() @@ -926,33 +909,14 @@ function InsertNotes() if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake end --------------------------------------------------------------------------------- --- InsertNotes(note_buffer) - insert notes in the active take --------------------------------------------------------------------------------- -function InsertNotesOld() - local debug = false - if debug or m.debug then ConMsg("InsertNotes()") end - DeleteNotes() - local i = 1 - if m.activeTake then - local t1 = GetNoteBuf() - while t1[i] do - reaper.MIDI_InsertNote(m.activeTake, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], false) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - i = i + 1 - end -- while t1[i] - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake -end + -------------------------------------------------------------------------------- -- PrintNotes - arg note_buffer t; print note_buffer to reaper console -------------------------------------------------------------------------------- function PrintNotes(t) -- debug code local debug = false if debug or m.debug then ConMsg("PrintNotes()") end + if not t then return end local i = 1 local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" while t[i] do @@ -991,7 +955,10 @@ function ShowMessage(tb, msgNum) tb.label = "" elseif msgNum == 1 then tb.tab = 0 - tb.label = "No Active Take" + tb.label = "MIDI Editor Closed" + elseif msgNum == 2 then + tb.tab = 0 + tb.label = "Please select a MIDI Item in the Arrange Window" end e.gScaleState = true end @@ -1300,7 +1267,7 @@ end randomBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end - if m.activeTake then + if m.activeTake and m.mItem then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift seqShiftVal.label = tostring(m.seqShift) GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) @@ -1470,7 +1437,7 @@ end sequenceBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end - if m.activeTake then + if m.activeTake and m.mItem then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence seqShiftVal.label = tostring(m.seqShift) if m.seqF then @@ -1589,6 +1556,7 @@ seqGridRad.onLClick = function() -- change grid size end -- Sequencer shift left seqShiftLBtn.onLClick = function() + if not m.mItem then return end local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMin = -(math.floor(itemLength / gridSize)-1) @@ -1602,6 +1570,7 @@ seqShiftLBtn.onLClick = function() end -- Sequencer shift right seqShiftRBtn.onLClick = function() + if not m.mItem then return end local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMax = math.floor(itemLength / gridSize) - 1 @@ -1800,7 +1769,7 @@ end euclidBtn.onLClick = function() local debug = false if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end - if m.activeTake then + if m.activeTake and m.mItem then if m.eucF then if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) @@ -1981,8 +1950,8 @@ function InitMidiExMachina() SetDefaultSeqOptions(); SetDefaultSeqShift() SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() SetDefaultEucOptions(); SetDefaultEucSliders() - - GetItemLength() + m.mItem = reaper.GetSelectedMediaItem(0, 0) + --GetItemLength() GetNotesFromTake() -- grab the original note data (if any...) if debug or m.debug then ConMsg("End InitMidiExMachina()\n") end end @@ -2053,41 +2022,58 @@ function MainLoop() -- Update Reaper GFX gfx.update() - -- check for midi editor and take - m.activeEditor = reaper.MIDIEditor_GetActive() - if m.activeEditor then - m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) - if m.activeTake then - ShowMessage(msgText, 0) -- clear old messages - -- check for changes in the active take if the "Permute" scale is selected - if scaleDrop.val2[scaleDrop.val1] == "Permute" then - __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) - if m.pHash ~= pHash then - SetScale("Permute", m.scales, m.preNoteProbTable) - UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) - m.pHash = pHash - end -- m.pHash - -- don't allow any note options that might upset permute... - noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false - noteOptionsCb.val1[3] = 0; m.rndOctX2F = false - end -- scaleDrop - -- check for grid changes - local grid = m.reaGrid - m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) - if grid ~= m.reaGrid then - GetReaperGrid(seqGridRad) - seqGridRad.onLClick() -- update the sequence grid sizes - end -- grid - else -- handle m.activeTake error - ShowMessage(msgText, 1) + -- check for selected item, midi editor and take + m.lmItem = m.mItem + m.mItem = reaper.GetSelectedMediaItem(0, 0) + if m.mItem then + if m.mItem ~= m.lmItem then + m.mItemNew = true + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) + m.notebuf.i = 0 -- brutal hack + PurgeNoteBuf(); NewNoteBuf() + else + m.mItemNew = false + end + + m.activeEditor = reaper.MIDIEditor_GetActive() + if m.activeEditor then + m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) + if m.activeTake then + ShowMessage(msgText, 0) -- clear old messages + -- check for changes in the active take if the "Permute" scale is selected + if scaleDrop.val2[scaleDrop.val1] == "Permute" then + __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) + if m.pHash ~= pHash then + SetScale("Permute", m.scales, m.preNoteProbTable) + UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) + m.pHash = pHash + end -- m.pHash + -- don't allow any note options that might upset permute... + noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false + noteOptionsCb.val1[3] = 0; m.rndOctX2F = false + end -- scaleDrop + -- check for grid changes + local grid = m.reaGrid + m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) + if grid ~= m.reaGrid then + GetReaperGrid(seqGridRad) + seqGridRad.onLClick() -- update the sequence grid sizes + end -- grid + else -- handle m.activeTake error + ShowMessage(msgText, 1) + m.activeTake = nil + end -- m.activeTake + else -- handle m.activeEditor error + -- pop up error message - switch layer on textbox element + ShowMessage(msgText, 1) + m.activeEditor = nil m.activeTake = nil - end -- m.activeTake - else -- handle m.activeEditor error - -- pop up error message - switch layer on textbox element - ShowMessage(msgText, 1) - m.activeEditor = nil - m.activeTake = nil - end -- m.activeEditor + end -- m.activeEditor + else + ShowMessage(msgText, 2) + m.mItem = nil + end end -------------------------------------------------------------------------------- diff --git a/Stop_no_item_error_patch.diff b/Stop_no_item_error_patch.diff new file mode 100644 index 0000000..b89299c --- /dev/null +++ b/Stop_no_item_error_patch.diff @@ -0,0 +1,317 @@ +diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +index 1e38c54..da244f3 100644 +--- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua ++++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +@@ -57,7 +57,7 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, + -------------------------------------------------------------------------------- + m = {} -- all ex machina data + -- user changeable defaults are marked with "(option)" +-m.debug = false ++m.debug = true + m.OS = reaper.GetOS() + -- window + m.win_title = "RobU : MIDI Ex Machina - v1.3.4"; m.win_dockstate = 0 +@@ -359,7 +359,7 @@ local function UndoNoteBuf() + end + end + +-local function PurgeNoteBuf() ++local function PurgeNoteBuf(idx) + -- PurgeNoteBuf() - purge all note buffers from current+1 to end + local debug = false + if debug or m.debug then +@@ -383,25 +383,26 @@ function GetItemLength() + local debug = false + if debug or m.debug then ConMsg("GetItemLength()") end + +- mItem = reaper.GetSelectedMediaItem(0, 0) +- mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") +- mBPM, mBPI = reaper.GetProjectTimeSignature2(0) +- msPerMin = 60000 +- msPerQN = msPerMin / mBPM +- numQNPerItem = (mItemLen * 1000) / msPerQN +- numBarsPerItem = numQNPerItem / 4 +- ItemPPQN = numQNPerItem * m.ppqn +- if debug or m.debug then +- ConMsg("ItemLen (ms) = " .. mItemLen) +- ConMsg("mBPM = " .. mBPM) +- ConMsg("MS Per QN = " .. msPerQN) +- ConMsg("Num of QN = " .. numQNPerItem) +- ConMsg("Num of Bar = " .. numBarsPerItem) +- ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") +- end +- mItemTake = reaper.GetTake(mItem, 0) -- should fix looped items +- ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! +- return ItemPPQN ++ --mItem = reaper.GetSelectedMediaItem(0, 0) ++ mItemLen = reaper.GetMediaItemInfo_Value(m.mItem, "D_LENGTH") ++ mBPM, mBPI = reaper.GetProjectTimeSignature2(0) ++ msPerMin = 60000 ++ msPerQN = msPerMin / mBPM ++ numQNPerItem = (mItemLen * 1000) / msPerQN ++ numBarsPerItem = numQNPerItem / 4 ++ ItemPPQN = numQNPerItem * m.ppqn ++ if debug or m.debug then ++ ConMsg("ItemLen (ms) = " .. mItemLen) ++ ConMsg("mBPM = " .. mBPM) ++ ConMsg("MS Per QN = " .. msPerQN) ++ ConMsg("Num of QN = " .. numQNPerItem) ++ ConMsg("Num of Bar = " .. numBarsPerItem) ++ ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") ++ end ++ mItemTake = reaper.GetTake(m.mItem, 0) -- should fix looped items ++ ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! ++ return ItemPPQN ++ + end + + function GetReaperGrid(gridRad) +@@ -447,7 +448,7 @@ end + -- GetNotesFromTake() - fill a note buffer from the active take + -------------------------------------------------------------------------------- + function GetNotesFromTake() +- local debug = false ++ local debug = true + if debug or m.debug then ConMsg("GetNotesFromTake()") end + local i, t + if m.activeTake then +@@ -468,6 +469,7 @@ function GetNotesFromTake() + t[i][8] = velocity + end -- for i + end -- num_notes ++ PrintNotes(GetNoteBuf()) + else -- no active take + if debug or m.debug then ConMsg("No Active Take") end + end -- m.activeTake +@@ -855,26 +857,7 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) + PurgeNoteBuf() + InsertNotes() + end +--------------------------------------------------------------------------------- +--- SetNotes - arg notebuf t1; set notes in the active take +--------------------------------------------------------------------------------- +-function SetNotes() +- local debug = false +- if debug or m.debug then ConMsg("SetNotes()") end +- local i = 1 +- if m.activeTake then +- local t1 = GetNoteBuf() +- while t1[i] do +- reaper.MIDI_SetNote(m.activeTake, i-1, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], __) +- --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) +- i = i + 1 +- end -- while t1[i] +- reaper.MIDI_Sort(m.activeTake) +- reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off +- else +- if debug or m.debug then ConMsg("No Active Take") end +- end -- m.activeTake +-end ++ + -------------------------------------------------------------------------------- + -- InsertNotes(note_buffer) - insert notes in the active take + -------------------------------------------------------------------------------- +@@ -883,7 +866,7 @@ function InsertNotes() + if debug or m.debug then ConMsg("\nInsertNotes()") end + DeleteNotes() + local i = 1 +- if m.activeTake then ++ if m.activeTake and m.mItem then + local noteLength = 0 + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() +@@ -926,33 +909,14 @@ function InsertNotes() + if debug or m.debug then ConMsg("No Active Take") end + end -- m.activeTake + end +--------------------------------------------------------------------------------- +--- InsertNotes(note_buffer) - insert notes in the active take +--------------------------------------------------------------------------------- +-function InsertNotesOld() +- local debug = false +- if debug or m.debug then ConMsg("InsertNotes()") end +- DeleteNotes() +- local i = 1 +- if m.activeTake then +- local t1 = GetNoteBuf() +- while t1[i] do +- reaper.MIDI_InsertNote(m.activeTake, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], false) +- --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) +- i = i + 1 +- end -- while t1[i] +- reaper.MIDI_Sort(m.activeTake) +- reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off +- else +- if debug or m.debug then ConMsg("No Active Take") end +- end -- m.activeTake +-end ++ + -------------------------------------------------------------------------------- + -- PrintNotes - arg note_buffer t; print note_buffer to reaper console + -------------------------------------------------------------------------------- + function PrintNotes(t) -- debug code + local debug = false + if debug or m.debug then ConMsg("PrintNotes()") end ++ if not t then return end + local i = 1 + local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" + while t[i] do +@@ -991,7 +955,10 @@ function ShowMessage(tb, msgNum) + tb.label = "" + elseif msgNum == 1 then + tb.tab = 0 +- tb.label = "No Active Take" ++ tb.label = "MIDI Editor Closed" ++ elseif msgNum == 2 then ++ tb.tab = 0 ++ tb.label = "Please select a MIDI Item in the Arrange Window" + end + e.gScaleState = true + end +@@ -1300,7 +1267,7 @@ end + randomBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end +- if m.activeTake then ++ if m.activeTake and m.mItem then + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift + seqShiftVal.label = tostring(m.seqShift) + GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) +@@ -1470,7 +1437,7 @@ end + sequenceBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end +- if m.activeTake then ++ if m.activeTake and m.mItem then + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence + seqShiftVal.label = tostring(m.seqShift) + if m.seqF then +@@ -1589,6 +1556,7 @@ seqGridRad.onLClick = function() -- change grid size + end + -- Sequencer shift left + seqShiftLBtn.onLClick = function() ++ if not m.mItem then return end + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() + m.seqShiftMin = -(math.floor(itemLength / gridSize)-1) +@@ -1602,6 +1570,7 @@ seqShiftLBtn.onLClick = function() + end + -- Sequencer shift right + seqShiftRBtn.onLClick = function() ++ if not m.mItem then return end + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() + m.seqShiftMax = math.floor(itemLength / gridSize) - 1 +@@ -1800,7 +1769,7 @@ end + euclidBtn.onLClick = function() + local debug = false + if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end +- if m.activeTake then ++ if m.activeTake and m.mItem then + if m.eucF then + if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end + GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) +@@ -1981,8 +1950,8 @@ function InitMidiExMachina() + SetDefaultSeqOptions(); SetDefaultSeqShift() + SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() + SetDefaultEucOptions(); SetDefaultEucSliders() +- +- GetItemLength() ++ m.mItem = reaper.GetSelectedMediaItem(0, 0) ++ --GetItemLength() + GetNotesFromTake() -- grab the original note data (if any...) + if debug or m.debug then ConMsg("End InitMidiExMachina()\n") end + end +@@ -2053,41 +2022,58 @@ function MainLoop() + -- Update Reaper GFX + gfx.update() + +- -- check for midi editor and take +- m.activeEditor = reaper.MIDIEditor_GetActive() +- if m.activeEditor then +- m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) +- if m.activeTake then +- ShowMessage(msgText, 0) -- clear old messages +- -- check for changes in the active take if the "Permute" scale is selected +- if scaleDrop.val2[scaleDrop.val1] == "Permute" then +- __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) +- if m.pHash ~= pHash then +- SetScale("Permute", m.scales, m.preNoteProbTable) +- UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) +- m.pHash = pHash +- end -- m.pHash +- -- don't allow any note options that might upset permute... +- noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false +- noteOptionsCb.val1[3] = 0; m.rndOctX2F = false +- end -- scaleDrop +- -- check for grid changes +- local grid = m.reaGrid +- m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) +- if grid ~= m.reaGrid then +- GetReaperGrid(seqGridRad) +- seqGridRad.onLClick() -- update the sequence grid sizes +- end -- grid +- else -- handle m.activeTake error +- ShowMessage(msgText, 1) ++ -- check for selected item, midi editor and take ++ m.lmItem = m.mItem ++ m.mItem = reaper.GetSelectedMediaItem(0, 0) ++ if m.mItem then ++ if m.mItem ~= m.lmItem then ++ m.mItemNew = true ++ m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 ++ seqShiftVal.label = tostring(m.seqShift) ++ m.notebuf.i = 0 -- brutal hack ++ PurgeNoteBuf(); NewNoteBuf() ++ else ++ m.mItemNew = false ++ end ++ ++ m.activeEditor = reaper.MIDIEditor_GetActive() ++ if m.activeEditor then ++ m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) ++ if m.activeTake then ++ ShowMessage(msgText, 0) -- clear old messages ++ -- check for changes in the active take if the "Permute" scale is selected ++ if scaleDrop.val2[scaleDrop.val1] == "Permute" then ++ __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) ++ if m.pHash ~= pHash then ++ SetScale("Permute", m.scales, m.preNoteProbTable) ++ UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) ++ m.pHash = pHash ++ end -- m.pHash ++ -- don't allow any note options that might upset permute... ++ noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false ++ noteOptionsCb.val1[3] = 0; m.rndOctX2F = false ++ end -- scaleDrop ++ -- check for grid changes ++ local grid = m.reaGrid ++ m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) ++ if grid ~= m.reaGrid then ++ GetReaperGrid(seqGridRad) ++ seqGridRad.onLClick() -- update the sequence grid sizes ++ end -- grid ++ else -- handle m.activeTake error ++ ShowMessage(msgText, 1) ++ m.activeTake = nil ++ end -- m.activeTake ++ else -- handle m.activeEditor error ++ -- pop up error message - switch layer on textbox element ++ ShowMessage(msgText, 1) ++ m.activeEditor = nil + m.activeTake = nil +- end -- m.activeTake +- else -- handle m.activeEditor error +- -- pop up error message - switch layer on textbox element +- ShowMessage(msgText, 1) +- m.activeEditor = nil +- m.activeTake = nil +- end -- m.activeEditor ++ end -- m.activeEditor ++ else ++ ShowMessage(msgText, 2) ++ m.mItem = nil ++ end + end + + -------------------------------------------------------------------------------- From 7140700ac6142828ee8836f633d4e84d1e95ec74 Mon Sep 17 00:00:00 2001 From: robu Date: Thu, 5 Dec 2019 21:47:04 +0000 Subject: [PATCH 14/27] Fix for no item selected in arrange --- .../MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index da244f3..65d11f2 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -57,7 +57,7 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, -------------------------------------------------------------------------------- m = {} -- all ex machina data -- user changeable defaults are marked with "(option)" -m.debug = true +m.debug = false m.OS = reaper.GetOS() -- window m.win_title = "RobU : MIDI Ex Machina - v1.3.4"; m.win_dockstate = 0 @@ -448,7 +448,7 @@ end -- GetNotesFromTake() - fill a note buffer from the active take -------------------------------------------------------------------------------- function GetNotesFromTake() - local debug = true + local debug = false if debug or m.debug then ConMsg("GetNotesFromTake()") end local i, t if m.activeTake then @@ -2024,21 +2024,23 @@ function MainLoop() -- check for selected item, midi editor and take m.lmItem = m.mItem + m.lactiveTake = m.activeTake m.mItem = reaper.GetSelectedMediaItem(0, 0) if m.mItem then if m.mItem ~= m.lmItem then - m.mItemNew = true m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) m.notebuf.i = 0 -- brutal hack PurgeNoteBuf(); NewNoteBuf() - else - m.mItemNew = false - end - + m.activeEditor, m.activeTake = nil, nil + end + m.activeEditor = reaper.MIDIEditor_GetActive() if m.activeEditor then m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) + + if m.activeTake ~= m.lactiveTake then GetNotesFromTake() end + if m.lmItem == nil and m.mItem then GetNotesFromTake() end if m.activeTake then ShowMessage(msgText, 0) -- clear old messages -- check for changes in the active take if the "Permute" scale is selected From 21c8bf0cf3199e7551f78dcecfda2cf213d009b3 Mon Sep 17 00:00:00 2001 From: RobU Date: Fri, 6 Dec 2019 07:30:42 +0000 Subject: [PATCH 15/27] version point update and changelog --- MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 65d11f2..134e953 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -31,8 +31,9 @@ @version 1.3.4 @author RobU @changelog - v1.3.4 - fixed looped item note shifting bug + v1.3.5 + Fixed crash when item not selected in arrange view + Provided more meaningful warning messages (for not item, or no midi editor) @provides [main=midi_editor] . [nomain] eGUI.lua @@ -60,7 +61,7 @@ m = {} -- all ex machina data m.debug = false m.OS = reaper.GetOS() -- window -m.win_title = "RobU : MIDI Ex Machina - v1.3.4"; m.win_dockstate = 0 +m.win_title = "RobU : MIDI Ex Machina - v1.3.5"; m.win_dockstate = 0 m.win_x = 10; m.win_y = 10; m.win_w = 900; m.win_h = 280 -- window dimensions m.win_bg = {0, 0, 0} -- background colour m.def_zoom = 4 -- 100% (option) From e697cda55c3306c429bcc1c40d89736ab537f20d Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 7 Dec 2019 19:15:03 +0000 Subject: [PATCH 16/27] reapack index update --- MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 134e953..0450fdd 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -28,7 +28,7 @@ @donation https://www.paypal.me/RobUrquhart @link Reaper http://reaper.fm @link Forum Thread http://reaper.fm -@version 1.3.4 +@version 1.3.5 @author RobU @changelog v1.3.5 From 553fcb4b2260bdbcb9c79e2e4125bf724972a1e2 Mon Sep 17 00:00:00 2001 From: RobU Date: Sat, 7 Dec 2019 19:15:19 +0000 Subject: [PATCH 17/27] index: 1 modified package, 1 new version --- index.xml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/index.xml b/index.xml index f4f3840..16425ee 100644 --- a/index.xml +++ b/index.xml @@ -1,5 +1,5 @@ - + @@ -126,6 +126,15 @@ fixed looped item note shifting bug]]> https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + From 153e3a2bdb62a07e8e7a8549d4134458ff37ebc2 Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Tue, 7 Dec 2021 22:06:19 +0000 Subject: [PATCH 18/27] Added Fisher-Yates shuffle to Randomiser tab - MIDI Ex Machina.lua --- .../RobU - MIDI Ex Machina.lua | 86 +++++++++++++++++-- 1 file changed, 81 insertions(+), 5 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 0450fdd..2810501 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -706,6 +706,64 @@ function RandomiseNotesPoly(noteProbTable) m.pHash = pHash end end + +-------------------------------------------------------------------------------- +-- ShuffleNotes() +-------------------------------------------------------------------------------- +function ShuffleNotes() + local debug = false + if debug or m.debug then ConMsg("ShuffleNotes()") end + + local fy = {ind={}, pos={}, num={}} + local t1, t2 = GetNoteBuf(), NewNoteBuf() + CopyTable(t1, t2) + + + local i, j = 1, 1 + + -- grab all the selected notes + while t2[i] do + + if t2[i][1] == true or m.rndAllNotesF then + table.insert(fy.ind, i) + table.insert(fy.pos, t2[i][3]) + table.insert(fy.num, t2[i][7]) + end + + i = i + 1 + end + + -- fisher-yates + for i = #fy.ind, 2, -1 do + local j = math.random(i) + fy.num[i], fy.num[j] = fy.num[j], fy.num[i] + end + + if #fy.ind > 1 then -- check for note munching + + for i = 1, #fy.ind - 1 do + + if fy.pos[i] == fy.pos[i + 1] then -- same note position + + while fy.num[i] == fy.num[i + 1] do --same note number + j = math.random(#fy.ind) + fy.num[i], fy.num[j] = fy.num[j], fy.num[i] + end + + end + end + end + + -- write back to the note buffer + for k, v in ipairs(fy.ind) do + t2[v][7] = fy.num[k] + end + + PurgeNoteBuf() + InsertNotes() + +end + -------------------------------------------------------------------------------- -- GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) -------------------------------------------------------------------------------- @@ -994,16 +1052,20 @@ t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03 -------------------------------------------------------------------------------- -- key, octave, & scale droplists dx, dy, dw, dh = 25, 70, 110, 20 -local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", e.Arial, m.font_sz, e.col_grey8, m.key, m.notes) -local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", e.Arial, m.font_sz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) -local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", e.Arial, m.font_sz, e.col_grey8, 1, m.scalelist) +local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, (dw*0.5)-5, dh, e.col_blue, "Key", e.Arial, m.font_sz, e.col_grey8, m.key, m.notes) +local octDrop = e.Droplist:new({1, 2, 3}, dx+(dw*0.5)+5, dy, (dw*0.5)-5, dh, e.col_blue, "Oct ", e.Arial, m.font_sz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) +local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 50, dw, dh, e.col_blue, "Scale", e.Arial, m.font_sz, e.col_grey8, 1, m.scalelist) local t_Droplists = {keyDrop, octDrop, scaleDrop} -------------------------------------------------------------------------------- -- Randomiser Layer -------------------------------------------------------------------------------- +-- note shuffle button +local shuffleBtn = e.Button:new({1}, 25, 165, 110, 25, e.col_green, "Shuffle", e.Arial, m.font_sz, e.col_grey8) -- note randomise button -local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Generate", e.Arial, m.font_sz, e.col_grey8) +local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Randomise", e.Arial, m.font_sz, e.col_grey8) + + -- note weight sliders local nx, ny, nw, nh, np = 160, 50, 30, 150, 40 local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) @@ -1097,7 +1159,7 @@ local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.w -------------------------------------------------------------------------------- -- Shared Element Tables -------------------------------------------------------------------------------- -local t_Buttons = {randomBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} +local t_Buttons = {randomBtn, shuffleBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} local t_Checkboxes = {noteOptionsCb, seqOptionsCb, eucOptionsCb} local t_RadButtons = {seqGridRad} local t_RSliders = {octProbSldr, seqAccRSldr, seqAccProbSldr, seqLegProbSldr} @@ -1285,6 +1347,20 @@ randomBtn.onLClick = function() pExtSaveStateF = true end --m.activeTake end +shuffleBtn.onLClick = function() + local debug = false + + if debug or m.debug then ConMsg("\nshuffleBtn.onLClick()") end + if m.activeTake and m.mItem then + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift + seqShiftVal.label = tostring(m.seqShift) + + GetNotesFromTake() + ShuffleNotes() + end + +end + -- Randomiser options toggle logic noteOptionsCb.onLClick = function() local debug = false From ffe6eed4068163f75880e954276d8576cab06f0b Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Wed, 8 Dec 2021 08:31:36 +0000 Subject: [PATCH 19/27] Revert "index: 1 modified package, 1 new version" This reverts commit 553fcb4b2260bdbcb9c79e2e4125bf724972a1e2. --- index.xml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/index.xml b/index.xml index 16425ee..f4f3840 100644 --- a/index.xml +++ b/index.xml @@ -1,5 +1,5 @@ - + @@ -126,15 +126,6 @@ fixed looped item note shifting bug]]> https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua - - - https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua - https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua - https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua - https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua - From d51b691e630ed4362e5f5b90c649df8df31a355a Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Wed, 8 Dec 2021 08:31:52 +0000 Subject: [PATCH 20/27] Update RobU - MIDI Ex Machina.lua --- .../RobU - MIDI Ex Machina.lua | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 2810501..25b60db 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -647,37 +647,46 @@ function GetUniqueNote(tNotes, noteIdx, noteProbTable, octProbTable) if m.rndOctX2F and not m.rndPermuteF then newNote = newNote + octProbTable[math.random(1, #octProbTable)] end + if #m.dupes == 0 then -- dupe table is empty m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- add note to the dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] m.dupes[m.dupes.i].midi = newNote return newNote + elseif tNotes[noteIdx][3] >= m.dupes[m.dupes.i].srtpos and tNotes[noteIdx][3] < m.dupes[m.dupes.i].endpos then -- note overlaps with previous note m.dupes.i = m.dupes.i + 1; m.dupes[m.dupes.i] = {} -- add note to dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] unique = false + while not unique do newNote = m.root + noteProbTable[math.random(1,#noteProbTable)] + if m.rndOctX2F and not m.rndPermuteF then newNote = newNote + octProbTable[math.random(1, #octProbTable)] end unique = true + for i = 1, m.dupes.i - 1 do -- check all previous overlapping notes if m.dupes[i].midi == newNote then unique = false end -- clash, try again end -- m.dupes.i + end -- not unique m.dupes[m.dupes.i].midi = newNote -- update dupe table return newNote + else -- note does not overlap with previous note m.dupes = {}; m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- reset dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] m.dupes[m.dupes.i].midi = newNote - return newNote + return newNote + end -- if #m.dupes + end -------------------------------------------------------------------------------- -- RandomiseNotesPoly(noteProbTable) @@ -718,7 +727,6 @@ function ShuffleNotes() local t1, t2 = GetNoteBuf(), NewNoteBuf() CopyTable(t1, t2) - local i, j = 1, 1 -- grab all the selected notes @@ -732,7 +740,7 @@ function ShuffleNotes() i = i + 1 end - + ConMsg("Number of notes: " .. i) -- fisher-yates for i = #fy.ind, 2, -1 do local j = math.random(i) @@ -744,10 +752,17 @@ function ShuffleNotes() for i = 1, #fy.ind - 1 do if fy.pos[i] == fy.pos[i + 1] then -- same note position + + ConMsg("POS :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) while fy.num[i] == fy.num[i + 1] do --same note number + + ConMsg("PRE :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) + j = math.random(#fy.ind) - fy.num[i], fy.num[j] = fy.num[j], fy.num[i] + fy.num[i + 1], fy.num[j] = fy.num[j], fy.num[i + 1] + + ConMsg("POST :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) end end @@ -764,6 +779,10 @@ function ShuffleNotes() end +function shuffleDeMunch() + +end + -------------------------------------------------------------------------------- -- GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) -------------------------------------------------------------------------------- From 181862e95fd04311211e5c289780bcc73afaf876 Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Wed, 8 Dec 2021 08:32:44 +0000 Subject: [PATCH 21/27] Revert "index: 1 modified package, 1 new version" This reverts commit 553fcb4b2260bdbcb9c79e2e4125bf724972a1e2. From b5104b45631c48dcedc2da180138dd0c408a2705 Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Wed, 8 Dec 2021 08:42:28 +0000 Subject: [PATCH 22/27] Update RobU - MIDI Ex Machina.lua --- MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 25b60db..7c0c597 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -740,7 +740,7 @@ function ShuffleNotes() i = i + 1 end - ConMsg("Number of notes: " .. i) + --ConMsg("Number of notes: " .. i) -- fisher-yates for i = #fy.ind, 2, -1 do local j = math.random(i) @@ -753,16 +753,16 @@ function ShuffleNotes() if fy.pos[i] == fy.pos[i + 1] then -- same note position - ConMsg("POS :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) + --ConMsg("POS :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) while fy.num[i] == fy.num[i + 1] do --same note number - ConMsg("PRE :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) + --ConMsg("PRE :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) j = math.random(#fy.ind) fy.num[i + 1], fy.num[j] = fy.num[j], fy.num[i + 1] - ConMsg("POST :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) + --ConMsg("POST :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) end end From a1de462a1721f1c4c90d8b051930a760dc2d14e6 Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Wed, 8 Dec 2021 21:26:36 +0000 Subject: [PATCH 23/27] Fix accidental merge [sigh] - MIDI Ex Machina.lua --- .../RobU - MIDI Ex Machina.lua | 107 +----------------- 1 file changed, 6 insertions(+), 101 deletions(-) diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 7c0c597..0450fdd 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -647,46 +647,37 @@ function GetUniqueNote(tNotes, noteIdx, noteProbTable, octProbTable) if m.rndOctX2F and not m.rndPermuteF then newNote = newNote + octProbTable[math.random(1, #octProbTable)] end - if #m.dupes == 0 then -- dupe table is empty m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- add note to the dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] m.dupes[m.dupes.i].midi = newNote return newNote - elseif tNotes[noteIdx][3] >= m.dupes[m.dupes.i].srtpos and tNotes[noteIdx][3] < m.dupes[m.dupes.i].endpos then -- note overlaps with previous note m.dupes.i = m.dupes.i + 1; m.dupes[m.dupes.i] = {} -- add note to dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] unique = false - while not unique do newNote = m.root + noteProbTable[math.random(1,#noteProbTable)] - if m.rndOctX2F and not m.rndPermuteF then newNote = newNote + octProbTable[math.random(1, #octProbTable)] end unique = true - for i = 1, m.dupes.i - 1 do -- check all previous overlapping notes if m.dupes[i].midi == newNote then unique = false end -- clash, try again end -- m.dupes.i - end -- not unique m.dupes[m.dupes.i].midi = newNote -- update dupe table return newNote - else -- note does not overlap with previous note m.dupes = {}; m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- reset dupe table m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] m.dupes[m.dupes.i].midi = newNote - return newNote - + return newNote end -- if #m.dupes - end -------------------------------------------------------------------------------- -- RandomiseNotesPoly(noteProbTable) @@ -715,74 +706,6 @@ function RandomiseNotesPoly(noteProbTable) m.pHash = pHash end end - --------------------------------------------------------------------------------- --- ShuffleNotes() --------------------------------------------------------------------------------- -function ShuffleNotes() - local debug = false - if debug or m.debug then ConMsg("ShuffleNotes()") end - - local fy = {ind={}, pos={}, num={}} - local t1, t2 = GetNoteBuf(), NewNoteBuf() - CopyTable(t1, t2) - - local i, j = 1, 1 - - -- grab all the selected notes - while t2[i] do - - if t2[i][1] == true or m.rndAllNotesF then - table.insert(fy.ind, i) - table.insert(fy.pos, t2[i][3]) - table.insert(fy.num, t2[i][7]) - end - - i = i + 1 - end - --ConMsg("Number of notes: " .. i) - -- fisher-yates - for i = #fy.ind, 2, -1 do - local j = math.random(i) - fy.num[i], fy.num[j] = fy.num[j], fy.num[i] - end - - if #fy.ind > 1 then -- check for note munching - - for i = 1, #fy.ind - 1 do - - if fy.pos[i] == fy.pos[i + 1] then -- same note position - - --ConMsg("POS :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) - - while fy.num[i] == fy.num[i + 1] do --same note number - - --ConMsg("PRE :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) - - j = math.random(#fy.ind) - fy.num[i + 1], fy.num[j] = fy.num[j], fy.num[i + 1] - - --ConMsg("POST :: pos = " .. fy.pos[i] .. "fy.num[i] = " .. fy.num[i] .. ", fy.num[i + 1] = " .. fy.num[i + 1]) - end - - end - end - end - - -- write back to the note buffer - for k, v in ipairs(fy.ind) do - t2[v][7] = fy.num[k] - end - - PurgeNoteBuf() - InsertNotes() - -end - -function shuffleDeMunch() - -end - -------------------------------------------------------------------------------- -- GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) -------------------------------------------------------------------------------- @@ -1071,20 +994,16 @@ t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03 -------------------------------------------------------------------------------- -- key, octave, & scale droplists dx, dy, dw, dh = 25, 70, 110, 20 -local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, (dw*0.5)-5, dh, e.col_blue, "Key", e.Arial, m.font_sz, e.col_grey8, m.key, m.notes) -local octDrop = e.Droplist:new({1, 2, 3}, dx+(dw*0.5)+5, dy, (dw*0.5)-5, dh, e.col_blue, "Oct ", e.Arial, m.font_sz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) -local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 50, dw, dh, e.col_blue, "Scale", e.Arial, m.font_sz, e.col_grey8, 1, m.scalelist) +local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", e.Arial, m.font_sz, e.col_grey8, m.key, m.notes) +local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", e.Arial, m.font_sz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) +local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", e.Arial, m.font_sz, e.col_grey8, 1, m.scalelist) local t_Droplists = {keyDrop, octDrop, scaleDrop} -------------------------------------------------------------------------------- -- Randomiser Layer -------------------------------------------------------------------------------- --- note shuffle button -local shuffleBtn = e.Button:new({1}, 25, 165, 110, 25, e.col_green, "Shuffle", e.Arial, m.font_sz, e.col_grey8) -- note randomise button -local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Randomise", e.Arial, m.font_sz, e.col_grey8) - - +local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Generate", e.Arial, m.font_sz, e.col_grey8) -- note weight sliders local nx, ny, nw, nh, np = 160, 50, 30, 150, 40 local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) @@ -1178,7 +1097,7 @@ local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.w -------------------------------------------------------------------------------- -- Shared Element Tables -------------------------------------------------------------------------------- -local t_Buttons = {randomBtn, shuffleBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} +local t_Buttons = {randomBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} local t_Checkboxes = {noteOptionsCb, seqOptionsCb, eucOptionsCb} local t_RadButtons = {seqGridRad} local t_RSliders = {octProbSldr, seqAccRSldr, seqAccProbSldr, seqLegProbSldr} @@ -1366,20 +1285,6 @@ randomBtn.onLClick = function() pExtSaveStateF = true end --m.activeTake end -shuffleBtn.onLClick = function() - local debug = false - - if debug or m.debug then ConMsg("\nshuffleBtn.onLClick()") end - if m.activeTake and m.mItem then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift - seqShiftVal.label = tostring(m.seqShift) - - GetNotesFromTake() - ShuffleNotes() - end - -end - -- Randomiser options toggle logic noteOptionsCb.onLClick = function() local debug = false From 0692c3bb7ceaa9490f27172749f0a5af51c992bc Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Thu, 3 Mar 2022 19:34:43 +0000 Subject: [PATCH 24/27] Shuffle and clean up --- .../RobU - MIDI Ex Machina.lua | 2041 +++++++++-------- MIDI Editor/MIDI Ex Machina/persistence.lua | 228 -- Stop_no_item_error_patch.diff | 317 --- 3 files changed, 1083 insertions(+), 1503 deletions(-) delete mode 100644 MIDI Editor/MIDI Ex Machina/persistence.lua delete mode 100644 Stop_no_item_error_patch.diff diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua index 0450fdd..efe6188 100644 --- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua +++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua @@ -7,17 +7,17 @@ #### Features note randomiser - selectable root note, octave, scale - - note probability sliders + - note probability per scale note - randomise all or selected notes - - octave doubler, with probability slider - - force first note to root note option - - permute selected notes + - octave doubler, with probability + - force first note to root of the scale option + - shuffle notes (fisher-yates) monophonic random sequence generator - - note length probability sliders + - note length probability - grid size control - - velocity accent level, and probabilty slider - - legato probability slider + - velocity accent level, and probabilty + - legato probability - various generation options euclidean sequence generator @@ -28,40 +28,44 @@ @donation https://www.paypal.me/RobUrquhart @link Reaper http://reaper.fm @link Forum Thread http://reaper.fm -@version 1.3.5 +@version 1.3.6 @author RobU @changelog - v1.3.5 - Fixed crash when item not selected in arrange view - Provided more meaningful warning messages (for not item, or no midi editor) + v1.3.6 + Added proper note shuffling using Fisher-Yates algorithm (polyphonic) + Removed the shitty 'Permute' scale hack :) + Fixed several corner-cases where notes might get eaten by the randomiser + Code clean-up in preparation for GUI update @provides [main=midi_editor] . [nomain] eGUI.lua [nomain] euclid.lua - [nomain] persistence.lua Reaper 5.x Extensions: SWS Licenced under the GPL v3 --]] + + + +-- requires ------------------------------------------------------------------ -------------------------------------------------------------------------------- --- REQUIRES --------------------------------------------------------------------------------- + package.path = debug.getinfo(1,"S").source:match[[^@?(.*[\/])[^\/]-$]] .."?.lua;".. package.path local e = require 'eGUI' local b = require 'euclid' -local p = require 'persistence' -- currently unused, i.e. no preset save, load, nada... --- ToDo preset save, load, etc... + + +-- globals ------------------------------------------------------------------- -------------------------------------------------------------------------------- --- GLOBAL VARIABLES START --------------------------------------------------------------------------------- + m = {} -- all ex machina data + -- user changeable defaults are marked with "(option)" -m.debug = false m.OS = reaper.GetOS() -- window -m.win_title = "RobU : MIDI Ex Machina - v1.3.5"; m.win_dockstate = 0 +m.win_title = "RobU : MIDI Ex Machina - v1.3.6"; m.win_dockstate = 0 m.win_x = 10; m.win_y = 10; m.win_w = 900; m.win_h = 280 -- window dimensions m.win_bg = {0, 0, 0} -- background colour m.def_zoom = 4 -- 100% (option) @@ -78,7 +82,7 @@ else end -- default octave & key --- due to some quirk, oct 4 is really oct 3... +-- due to reaper.ini offset value, oct 4 might be oct 3... (fixed in next build) m.oct = 4; m.key = 1; m.root = 0 -- (options, except m.root) -- midi editor, take, grid @@ -90,7 +94,8 @@ m.reaGrid = 0 m.rndAllNotesF = false -- all notes or only selected notes (option) m.rndOctX2F = false -- enable double scale randomisation (option) m.rndFirstNoteF = true; -- first note is always root (option) -m.rndPermuteF = false; m.pHash = 0 -- midi item state changes +--m.rndPermuteF = false; +m.pHash = 0 -- midi item state changes m.rndOctProb = 1 -- (option - min 0, max 10) -- sequence generator @@ -142,7 +147,6 @@ m.scales = { {0, 2, 4, 7, 9, 12, name = "Pentatonic Maj"}, {0, 3, 5, 7, 10, 12, name = "Pentatonic min"}, {0, 1, 4, 5, 6, 8, 11, 12, name = "Persian"}, - {name = "Permute"} } -- a list of scales available to the note randomiser, more can be added manually if required -- each value is the interval step from the root note of the scale (0) including the octave (12) @@ -161,305 +165,88 @@ pExtSaveStateF = false -- when true, update the pExtState for saving pExtLoadStateF = true -- when true, load the pExtState pExtState = {} -- Reaper project ext state table pExtStateStr = "" -- pickled string. a nom a nom a nom... --------------------------------------------------------------------------------- --- GLOBAL VARIABLES END --------------------------------------------------------------------------------- - --------------------------------------------------------------------------------- --- Utility Functions Start --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- -local function Wrap (n, max) --- Wrap(n, max) -return n wrapped between 'n' and 'max' - n = n % max - if (n < 1) then n = n + max end - return n -end - -local function RGB2Dec(r, g, b) --- RGB2Dec(r, g, b) - takes 8 bit r, g, b values, returns decimal (0 to 1) - if r < 0 or r > 255 then r = wrap(r, 255) end - if g < 0 or g > 255 then g = wrap(g, 255) end - if b < 0 or b > 255 then b = wrap(b, 255) end - return r/255, g/255, b/255 -end -local function RGB2Packed(r, g, b) --- RGB2Packed(r, g, b) - returns a packed rgb value - local floor = math.floor - g = (g << 8) - b = (b << 16) - return floor(r + g + b) -end -local function ConMsg(str) --- ConMsg(str) - outputs 'str' to the Reaper console - reaper.ShowConsoleMsg(str .."\n") -end --------------------------------------------------------------------------------- --- Pickle table serialization - Steve Dekorte, http://www.dekorte.com, Apr 2000 --------------------------------------------------------------------------------- -function pickle(t) - return Pickle:clone():pickle_(t) -end --------------------------------------------------------------------------------- -Pickle = { - clone = function (t) local nt = {} - for i, v in pairs(t) do - nt[i] = v - end - return nt -end -} --------------------------------------------------------------------------------- -function Pickle:pickle_(root) - if type(root) ~= "table" then - error("can only pickle tables, not " .. type(root) .. "s") - end - self._tableToRef = {} - self._refToTable = {} - local savecount = 0 - self:ref_(root) - local s = "" - while #self._refToTable > savecount do - savecount = savecount + 1 - local t = self._refToTable[savecount] - s = s .. "{\n" - for i, v in pairs(t) do - s = string.format("%s[%s]=%s,\n", s, self:value_(i), self:value_(v)) - end - s = s .. "},\n" - end - return string.format("{%s}", s) -end --------------------------------------------------------------------------------- -function Pickle:value_(v) - local vtype = type(v) - if vtype == "string" then return string.format("%q", v) - elseif vtype == "number" then return v - elseif vtype == "boolean" then return tostring(v) - elseif vtype == "table" then return "{"..self:ref_(v).."}" - else error("pickle a " .. type(v) .. " is not supported") - end -end --------------------------------------------------------------------------------- -function Pickle:ref_(t) - local ref = self._tableToRef[t] - if not ref then - if t == self then error("can't pickle the pickle class") end - table.insert(self._refToTable, t) - ref = #self._refToTable - self._tableToRef[t] = ref - end - return ref -end --------------------------------------------------------------------------------- --- unpickle --------------------------------------------------------------------------------- -function unpickle(s) - if type(s) ~= "string" then - error("can't unpickle a " .. type(s) .. ", only strings") - end - local gentables = load("return " .. s) - local tables = gentables() - for tnum = 1, #tables do - local t = tables[tnum] - local tcopy = {} - for i, v in pairs(t) do tcopy[i] = v end - for i, v in pairs(tcopy) do - local ni, nv - if type(i) == "table" then ni = tables[i[1]] else ni = i end - if type(v) == "table" then nv = tables[v[1]] else nv = v end - t[i] = nil - t[ni] = nv - end - end - return tables[1] -end --------------------------------------------------------------------------------- --- Utility Functions End +-- midi ex machina functions ------------------------------------------------- -------------------------------------------------------------------------------- +-- note buffers -------------------------------------------------------------- -------------------------------------------------------------------------------- --- Ex Machina Functions Start --------------------------------------------------------------------------------- -function ClearTable(t) --- ClearTable(t) - set all items in 2D table 't' to nil - local debug = false - if debug or m.debug then ConMsg("ClearTable()") end - for k, v in pairs(t) do - t[k] = nil - end -end -function CopyTable(t1, t2) --- CopyTable(t1, t2) - copies note data from t1 to t2 - ClearTable(t2) - local i = 1 - while t1[i] do - local j = 1 - t2[i] = {} - while (t1[i][j] ~= nil) do - t2[i][j] = t1[i][j] - j = j + 1 - end --while (t1[i][j] - i = i + 1 - end -- while t1[i] -end --------------------------------------------------------------------------------- --- Note Buffers --------------------------------------------------------------------------------- local function NewNoteBuf() -- NewNoteBuf() - add a new note buffer to the table, returns handle - local debug = false - if debug or m.debug then ConMsg("NewNoteBuf()") end + m.notebuf.i = m.notebuf.i + 1 m.notebuf.max = m.notebuf.max + 1 m.notebuf[m.notebuf.i] = {} - if debug or m.debug then - str = "created buffer\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" - ConMsg(str) - end + return m.notebuf[m.notebuf.i] end local function GetNoteBuf() -- GetNoteBuf() - returns handle to the current note buffer - local debug = false - if debug or m.debug then ConMsg("GetNoteBuf()") end + if m.notebuf.i >= 1 then - if debug or m.debug then - str = "retrieved buffer\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" - ConMsg(str) - end + return m.notebuf[m.notebuf.i] end end local function UndoNoteBuf() -- UndoNoteBuf() - points to previous note buffer - local debug = false - if debug or m.debug then ConMsg("UndoNoteBuf()") end + if m.notebuf.i > 1 then m.notebuf.i = m.notebuf.i -1 - if debug or m.debug then - str = "removed buffer " .. tostring(m.notebuf.i + 1) .. "\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" - ConMsg(str) - end - else - if debug or m.debug then - str = "nothing to undo...\n" - str = str .. "buffer index = " .. tostring(m.notebuf.i) .. "\n" - ConMsg(str) - end end end local function PurgeNoteBuf(idx) -- PurgeNoteBuf() - purge all note buffers from current+1 to end - local debug = false - if debug or m.debug then - ConMsg("PurgeNoteBuf()") - ConMsg("current idx = " .. tostring(m.notebuf.i)) - ConMsg("max idx = " .. tostring(m.notebuf.max)) - end + while m.notebuf.max > m.notebuf.i do m.notebuf[m.notebuf.max] = nil - if debug or m.debug then ConMsg("purging buffer " .. tostring(m.notebuf.max)) - end m.notebuf.max = m.notebuf.max - 1 end end --------------------------------------------------------------------------------- --- GetItemLength(t) - get length of take 't', set various global vars --- currently it only returns the item length (used in Sequencer and Euclid) --------------------------------------------------------------------------------- -function GetItemLength() - local debug = false - if debug or m.debug then ConMsg("GetItemLength()") end - - --mItem = reaper.GetSelectedMediaItem(0, 0) - mItemLen = reaper.GetMediaItemInfo_Value(m.mItem, "D_LENGTH") - mBPM, mBPI = reaper.GetProjectTimeSignature2(0) - msPerMin = 60000 - msPerQN = msPerMin / mBPM - numQNPerItem = (mItemLen * 1000) / msPerQN - numBarsPerItem = numQNPerItem / 4 - ItemPPQN = numQNPerItem * m.ppqn - if debug or m.debug then - ConMsg("ItemLen (ms) = " .. mItemLen) - ConMsg("mBPM = " .. mBPM) - ConMsg("MS Per QN = " .. msPerQN) - ConMsg("Num of QN = " .. numQNPerItem) - ConMsg("Num of Bar = " .. numBarsPerItem) - ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") - end - mItemTake = reaper.GetTake(m.mItem, 0) -- should fix looped items - ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! - return ItemPPQN -end -function GetReaperGrid(gridRad) --- GetReaperGrid() - get the current grid size, set global var m.reaGrid - local debug = false - if debug or m.debug then ConMsg("GetReaperGrid()") end - if m.activeTake then - m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) -- returns quarter notes - if gridRad then -- if a grid object was passed, update it - if m.reaGrid == 0.25 then gridRad.val1 = 1 -- 1/16 - elseif m.reaGrid == 0.5 then gridRad.val1 = 2 -- 1/8 - elseif m.reaGrid == 1 then gridRad.val1 = 3 -- 1/4 - end -- m.reaGrid - end - else - if debug or m.debug then ConMsg("No Active Take\n") end - end -- m.activeTake -end +-- delete, get, insert ------------------------------------------------------- -------------------------------------------------------------------------------- --- GetPermuteScaleFromTake(t) - fill a scale buffer 't' from the active take --------------------------------------------------------------------------------- -function GetPermuteScaleFromTake(t) - local debug = false - if debug or m.debug then ConMsg("GetPermuteScaleFromTake()") end - local i, j = 1, 0 + +function DeleteNotes() +-- DeleteNotes() - delete all notes from the active take + + local i, num_notes = 0, 0 + if m.activeTake then - local __, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) - if num_notes > 0 then - ClearTable(t) - for i = 1, num_notes do - __, selected, __, __, __, __, pitch, __ = reaper.MIDI_GetNote(m.activeTake, i-1) - if selected == true then - j = j + 1 - t[j] = pitch - m.root - end - end -- for i - end --if num_notes - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake + __, num_notes, __, __ = reaper.MIDI_CountEvts(m.activeTake) + + for i = 0, num_notes do + reaper.MIDI_DeleteNote(m.activeTake, 0) + end --for + end --m.activeTake end --------------------------------------------------------------------------------- --- GetNotesFromTake() - fill a note buffer from the active take --------------------------------------------------------------------------------- + function GetNotesFromTake() - local debug = false - if debug or m.debug then ConMsg("GetNotesFromTake()") end +-- GetNotesFromTake() - fill a note buffer from the active take + local i, t + if m.activeTake then + reaper.MIDI_Sort(m.activeTake) local _retval, num_notes, num_cc, num_sysex = reaper.MIDI_CountEvts(m.activeTake) + if num_notes > 0 then t = GetNoteBuf(); if t == nil then t = NewNoteBuf() end ClearTable(t) + for i = 1, num_notes do _retval, selected, muted, startppq, endppq, channel, pitch, velocity = reaper.MIDI_GetNote(m.activeTake, i-1) t[i] = {} + t[i][0] = i t[i][1] = selected t[i][2] = muted t[i][3] = startppq @@ -470,162 +257,252 @@ function GetNotesFromTake() t[i][8] = velocity end -- for i end -- num_notes - PrintNotes(GetNoteBuf()) - else -- no active take - if debug or m.debug then ConMsg("No Active Take") end end -- m.activeTake end --------------------------------------------------------------------------------- --- DeleteNotes() - delete all notes from the active take --------------------------------------------------------------------------------- -function DeleteNotes() - local debug = false - if debug or m.debug then ConMsg("DeleteNotes()") end - local i, num_notes = 0, 0 - if m.activeTake then - __, num_notes, __, __ = reaper.MIDI_CountEvts(m.activeTake) - for i = 0, num_notes do - reaper.MIDI_DeleteNote(m.activeTake, 0) - end --for - else - if debug or m.debug then ConMsg("No Active Take") end - end --m.activeTake -end --------------------------------------------------------------------------------- --- SetRootNote(octave, key) - returns new root midi note --------------------------------------------------------------------------------- -function SetRootNote(octave, key) - local debug = false - local o = octave * 12 - local k = key - 1 - if debug or m.debug then ConMsg("SetRootNote() - Note = " .. tostring(o + k)) end - return o + k -end --------------------------------------------------------------------------------- --- GenProbTable(preProbTable, slidersTable, probTable) --- creates an event probability table using values from sliders --------------------------------------------------------------------------------- -function GenProbTable(preProbTable, sliderTable, probTable) - local debug = false - if debug or m.debug then ConMsg("GenProbTable()") end - local i, j, k, l = 1, 1, 1, 1 - local floor = math.floor - ClearTable(probTable) - for i, v in ipairs(preProbTable) do - if sliderTable[j].val1 > 0 then - for l = 1, (sliderTable[j].val1) do - probTable[k] = preProbTable[i] - k = k + 1 - end -- for l - end -- if sliderTable[j] - j = j + 1 - end -end --------------------------------------------------------------------------------- --- GenAccentTable(probTable, velSlider, probSlider) --- creates an event probability table using values from sliders --------------------------------------------------------------------------------- -function GenAccentTable(probTable, velSlider, probSlider) - local debug = false - if debug or m.debug then ConMsg("GenAccentTable()") end - local i, j = 1, 1 - ClearTable(probTable) - -- insert normal velocity - for i = 1, (probSlider.max - probSlider.val1) do - probTable[j] = math.floor(velSlider.val1) - j = j + 1 - end - -- insert the accented velocity - for i = 1, (probSlider.val1) do - probTable[j] = math.floor(velSlider.val2) - j = j + 1 - end -end --------------------------------------------------------------------------------- --- GenLegatoTable(probTable, velSlider, probSlider) --- creates an event probability table using values from sliders --------------------------------------------------------------------------------- -function GenLegatoTable(probTable, probSlider) - local debug = false - if debug or m.debug then ConMsg("GenLegatoTable()") end - local i, j = 1, 1 - ClearTable(probTable) - -- no legato - for i = 1, (probSlider.max - probSlider.val1) do - probTable[j] = m.legato - j = j + 1 - end - -- legato - for i = 1, (probSlider.val1) do - probTable[j] = 0 - j = j + 1 - end + +function InsertNotes() +-- InsertNotes(note_buffer) - insert notes in the active take + + DeleteNotes() + local i = 1 + + if m.activeTake and m.mItem then + local noteLength = 0 + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() + local noteShift = m.seqShift * gridSize + local t1 = GetNoteBuf() + local t2 = {} -- for note shifting + CopyTable(t1, t2) + + for k, v in pairs(t2) do -- do note shifting + noteLength = v[4] - v[3] + v[3] = v[3] + noteShift + v[4] = v[4] + noteShift + + if v[3] >= itemLength then -- positive shift + v[3] = v[3] - itemLength + v[4] = v[4] - itemLength + + elseif v[3] < 0 then -- negative shift + v[3] = v[3] + itemLength + v[4] = v[4] + itemLength + + end + + if v[4] > itemLength then v[4] = itemLength - 1 end + + end + + + while t2[i] do + reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) + --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) + i = i + 1 + end -- while t2[i] + + reaper.MIDI_Sort(m.activeTake) + reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off + + end -- m.activeTake end + + + +-- randomiser ---------------------------------------------------------------- -------------------------------------------------------------------------------- + +function GenOctaveTable(probTable, probSlider) -- GenOctaveTable(probTable, velSlider, probSlider) -- creates an event probability table using values from sliders --------------------------------------------------------------------------------- -function GenOctaveTable(probTable, probSlider) - local debug = false - if debug or m.debug then ConMsg("GenOctaveTable()") end + local i, j = 1, 1 ClearTable(probTable) + -- single octave for i = 1, (probSlider.max - probSlider.val1) do probTable[j] = 0 j = j + 1 end + -- double octave for i = 1, (probSlider.val1) do probTable[j] = 12 j = j + 1 end end --------------------------------------------------------------------------------- + +function GetUniqueNote(note_in) +-- GetUniqueNote - returns a random note number based on selected scale, and various flags + local rand_note + + rand_note = (note_in[0]==1 and m.rndFirstNoteF) and -- select on note pos 1 && first note is root flag + m.root or m.root + m.noteProbTable[math.random(1, #m.noteProbTable)] -- get appropriate note (fixed/random) + + if m.rndOctX2F then rand_note = rand_note + m.octProbTable[math.random(1, #m.octProbTable)] end -- get octave + + return rand_note + + --old code for posterity :P + --t_sel[s][7] = (t_sel[s][0]==1 and m.rndFirstNoteF) and -- select on note pos 1 && first note is root flag + -- m.root or m.root + m.noteProbTable[math.random(1, #m.noteProbTable)] -- get appropriate note (fixed/random) + --if m.rndOctX2F then t_sel[s][7] = t_sel[s][7] + m.octProbTable[math.random(1, #m.octProbTable)] end -- get octave +end + +function RandomiseNotes() +-- RandomiseNotes - randomise all/selected notes + + local t1, t_all, t_sel = GetNoteBuf(), NewNoteBuf(), {} + local a, s, t_all_len, t_sel_len = 0, 0, 0, 0 + local unique, retry = true, 0 + local overs = {} + + CopyNoteTable(t1, t_all) + CopyNoteTable(t_all, t_sel, true) + + if #t_sel < 1 then return else t_sel_len = #t_sel end + + for s = 1, t_sel_len do -- for each note in t_sel + unique = true -- assume unique + + t_sel[s][7] = GetUniqueNote(t_sel[s]) + + for a = 1, #t_all do -- for all notes, find the overlaps between the selected notes and or notes + + if t_sel[s][0] ~= t_all[a][0] then -- exclude the same note ID + + if (t_sel[s][3] >= t_all[a][3] and t_sel[s][3] < t_all[a][4]) or -- sel start pos overlap with all? + (t_all[a][3] >= t_sel[s][3] and t_all[a][3] < t_sel[s][4]) then -- all start pos overlap with sel? + table.insert(overs, t_all[a]) -- update pos overlaps + + if t_sel[s][7] == t_all[a][7] then -- note overlap + unique = false -- note is not unique + end + end + end + end -- for a = 1, #t_all do + + while not unique do + unique = true -- assume the next random note will be unique + t_sel[s][7] = GetUniqueNote(t_sel[s]) + + for _, over in ipairs(overs) do -- check all overlapping notes for duplicates + if t_sel[s][7] == over[7] then unique = false end -- not unique + end + + retry = retry + 1; if retry > 10 then break end -- break loop if we can't find a solution + end -- while not unique + + if retry > 11 then return 1 else retry = 1 end -- return if we can't find a solution + + overs={} + end -- for s = 1, t_sel_len + + -- write back to the note buffer + for s = 1, #t_sel do + t_all[t_sel[s][0]][7] = t_sel[s][7] + end + + PurgeNoteBuf() + InsertNotes() + if m.activeTake then + __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) + m.pHash = pHash + end +end + +function SetRootNote(octave, key) +-- SetRootNote(octave, key) - returns new root midi note + + local o = octave * 12 + local k = key - 1 + + return o + k +end + +function SetScale(scaleName, allScales, scale) -- SetScale() -- copies a scale from allScales to scale, key = scaleName --------------------------------------------------------------------------------- -function SetScale(scaleName, allScales, scale) - local debug = false - if debug or m.debug then ConMsg("SetScale()") end + ClearTable(scale) + for i = 1, #allScales, 1 do if scaleName == allScales[i].name then - if scaleName == "Permute" then - m.rndPermuteF = true - GetPermuteScaleFromTake(scale) - else - m.rndPermuteF = false - end for k, v in pairs(allScales[i]) do scale[k] = v end break end end - if debug or m.debug then ConMsg("scaleName = " .. tostring(scaleName)) end + end --------------------------------------------------------------------------------- --- SetSeqGridSizes() --------------------------------------------------------------------------------- -function SetSeqGridSizes(sliderTable) - local debug = false - if debug or m.debug then ConMsg("SetSeqGridSizes()") end - for k, v in pairs(sliderTable) do - if sliderTable[k].label == "1/16" then m.preSeqProbTable[k] = 0.25 - elseif sliderTable[k].label == "1/8" then m.preSeqProbTable[k] = 0.5 - elseif sliderTable[k].label == "1/4" then m.preSeqProbTable[k] = 1.0 - elseif sliderTable[k].label == "Rest" then m.preSeqProbTable[k] = -1.0 - end + +function ShuffleNotes() +-- ShuffleNotes - shuffle all/selected notes using Fisher-Yates algo + + local t1, t_all, t_sel = GetNoteBuf(), NewNoteBuf(), {} + local a, s, t, t_all_len, t_sel_len = 0, 0, 0, 0, 0 + local unique, retry = true, 0 + local overs = {} + + CopyNoteTable(t1, t_all) -- copy the note buffer to an empty stack note buffer + CopyNoteTable(t_all, t_sel, true) -- copy selected notes only to a temp empty table + + if #t_sel < 2 then return else t_sel_len = #t_sel end + + for s = 1, t_sel_len do -- for each note in t_sel + unique = true -- assume unique + + t = math.random(s, t_sel_len) + t_sel[s][7], t_sel[t][7] = t_sel[t][7], t_sel[s][7] -- shuffle one note + + for a = 1, #t_all do -- for all notes, find the overlaps between the selected notes and or notes + + if t_sel[s][0] ~= t_all[a][0] then -- exclude the same note ID + + if (t_sel[s][3] >= t_all[a][3] and t_sel[s][3] < t_all[a][4]) or -- sel start pos overlap with all? + (t_all[a][3] >= t_sel[s][3] and t_all[a][3] < t_sel[s][4]) then -- all start pos overlap with sel? + table.insert(overs, t_all[a]) -- update pos overlaps + + if t_sel[s][7] == t_all[a][7] then -- note overlap + unique = false -- note is not unique + end + end + end + end -- for a = 1, #t_all do + + while not unique do + unique = true -- assume the next shuffled note will be unique + t = math.random(s, t_sel_len) + t_sel[s][7], t_sel[t][7] = t_sel[t][7], t_sel[s][7] -- shuffle one note + + for _, over in ipairs(overs) do -- check all overlapping notes for duplicates + if t_sel[s][7] == over[7] then unique = false end -- not unique + end + + retry = retry + 1; if retry > 10 then break end -- break loop if we can't find a solution + end -- while not unique + + if retry > 11 then return 1 else retry = 1 end -- return if we can't find a solution + + overs={} + + end -- for i = 1, t_sel_len do + + -- write back to the note buffer + for i = 1, #t_sel do + t_all[t_sel[i][0]][7] = t_sel[i][7] end + + PurgeNoteBuf() + InsertNotes() + end --------------------------------------------------------------------------------- + +function UpdateSliderLabels(sliderTable, preProbTable) -- UpdateSliderLabels() args t_noteSliders, m.preNoteProbTable -- sets the sliders to the appropriate scale notes, including blanks --------------------------------------------------------------------------------- -function UpdateSliderLabels(sliderTable, preProbTable) - local debug = false - if debug or m.debug then ConMsg("UpdateSliderLabels()") end + for k, v in pairs(sliderTable) do if preProbTable[k] then -- if there's a Scale note -- set the slider to the note name @@ -637,91 +514,27 @@ function UpdateSliderLabels(sliderTable, preProbTable) end end end + + + +-- sequencer ----------------------------------------------------------------- -------------------------------------------------------------------------------- --- GetUniqueNote() --------------------------------------------------------------------------------- -function GetUniqueNote(tNotes, noteIdx, noteProbTable, octProbTable) - local debug = false - if debug and m.debug then ConMsg("GetUniqueNote()") end - newNote = m.root + noteProbTable[math.random(1, #noteProbTable)] - if m.rndOctX2F and not m.rndPermuteF then - newNote = newNote + octProbTable[math.random(1, #octProbTable)] - end - if #m.dupes == 0 then -- dupe table is empty - m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- add note to the dupe table - m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] - m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] - m.dupes[m.dupes.i].midi = newNote - return newNote - elseif tNotes[noteIdx][3] >= m.dupes[m.dupes.i].srtpos - and tNotes[noteIdx][3] < m.dupes[m.dupes.i].endpos then -- note overlaps with previous note - m.dupes.i = m.dupes.i + 1; m.dupes[m.dupes.i] = {} -- add note to dupe table - m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] - m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] - unique = false - while not unique do - newNote = m.root + noteProbTable[math.random(1,#noteProbTable)] - if m.rndOctX2F and not m.rndPermuteF then - newNote = newNote + octProbTable[math.random(1, #octProbTable)] - end - unique = true - for i = 1, m.dupes.i - 1 do -- check all previous overlapping notes - if m.dupes[i].midi == newNote then unique = false end -- clash, try again - end -- m.dupes.i - end -- not unique - m.dupes[m.dupes.i].midi = newNote -- update dupe table - return newNote - else -- note does not overlap with previous note - m.dupes = {}; m.dupes.i = 1; m.dupes[m.dupes.i] = {} -- reset dupe table - m.dupes[m.dupes.i].srtpos = tNotes[noteIdx][3] - m.dupes[m.dupes.i].endpos = tNotes[noteIdx][4] - m.dupes[m.dupes.i].midi = newNote - return newNote - end -- if #m.dupes -end --------------------------------------------------------------------------------- --- RandomiseNotesPoly(noteProbTable) --------------------------------------------------------------------------------- -function RandomiseNotesPoly(noteProbTable) - local debug = false - if debug or m.debug then ConMsg("RandomiseNotesPoly()") end - m.dupes.i = 1 - local i = 1 - local t1, t2 = GetNoteBuf(), NewNoteBuf() - CopyTable(t1, t2) - while t2[i] do - if t2[i][1] == true or m.rndAllNotesF then -- if selected, or all notes flag is true - if i == 1 and m.rndFirstNoteF then -- if selected, the first not is always root of scale - t2[i][7] = m.root - else - t2[i][7] = GetUniqueNote(t1, i, noteProbTable, m.octProbTable) - end - end - i = i + 1 - end -- while t1[i] - PurgeNoteBuf() - InsertNotes() - if m.rndPermuteF and m.activeTake then - __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) - m.pHash = pHash - end -end --------------------------------------------------------------------------------- --- GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) --------------------------------------------------------------------------------- + function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) - local debug = false - if debug or m.debug then ConMsg("GenSequence()") end +-- GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) + local t, t2 = NewNoteBuf(), GetNoteBuf() CopyTable(t2, t) GetReaperGrid() -- populates m.reaGrid ClearTable(t) + local itemPos = 0 local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() local noteStart, noteEnd, noteLen, noteVel = 0, 0, 0, 0 local newNote = 0 local noteCount = 0; restCount = 0 + while itemPos < itemLength do if m.seqFirstNoteF and noteCount == 0 then -- handle first note flag @@ -736,6 +549,7 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) if newNote == -1 then itemPos = itemPos + gridSize restCount = restCount + 1 + else noteStart = itemPos noteLen = newNote * m.ppqn @@ -765,83 +579,70 @@ function GenSequence(seqProbTable, accProbTable, accSlider, legProbTable) t[noteCount][8] = noteVel -- velocity end -- newNote end -- itemPos < itemLength - if debug and m.debug then PrintNotes(t) end + PurgeNoteBuf() InsertNotes() end --------------------------------------------------------------------------------- --- GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) --------------------------------------------------------------------------------- -function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) - local debug = false - if debug or m.debug then ConMsg("GenBjorklund()") end - local floor = math.floor - local t, t2 = NewNoteBuf(), GetNoteBuf() - CopyTable(t2, t) - GetReaperGrid() -- populates m.reaGrid - --t = GetNoteBuf(); if t == nil then t = NewNoteBuf() end -- pre-undo - ClearTable(t) - local itemPos = 0 - local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() - local noteStart, noteEnd, noteLen, noteVel = 0, 0, 0, 0 - local newNote = 0 - local noteCount = 0; restCount = 0 - local pulse = floor(pulses.val1 + 0.5) - local step = floor(steps.val1 + 0.5) - local pattern = b.generate(pulse, step) - local rot = floor(rotation.val1 + 0.5) - local idx = (-rot) + 1; idx = Wrap(idx, step) - while itemPos < itemLength do - if pattern[idx] then - noteStart = itemPos - noteLen = gridSize - noteEnd = noteStart + noteLen - itemPos = itemPos + noteLen - if m.eucAccentF then -- handle accent flag - noteVel = accProbTable[math.random(1, #accProbTable)] - else - noteVel = floor(accSlider.val1) - end -- m.seqAccentF - --noteVel = accProbTable[math.random(1, #accProbTable)] - noteCount = noteCount + 1 - t[noteCount] = {} - t[noteCount][1] = true -- selected - t[noteCount][2] = false -- muted - t[noteCount][3] = noteStart -- startppqn - t[noteCount][4] = noteEnd + m.legato -- endppqn - t[noteCount][5] = noteLen -- note length - t[noteCount][6] = 0 -- channel - t[noteCount][7] = m.root -- note number - t[noteCount][8] = noteVel -- velocity - else - itemPos = itemPos + gridSize - restCount = restCount + 1 - end - idx = idx + 1 - idx = Wrap(idx, step) - end - PurgeNoteBuf() - InsertNotes() -end --------------------------------------------------------------------------------- --- GenNoteAttributes(accF, accProb, accVal, legF, legVal) -- accent, legato only --------------------------------------------------------------------------------- + +function GenAccentTable(probTable, velSlider, probSlider) +-- GenAccentTable(probTable, velSlider, probSlider) +-- creates an event probability table using values from sliders + + local i, j = 1, 1 + ClearTable(probTable) + + -- insert normal velocity + for i = 1, (probSlider.max - probSlider.val1) do + probTable[j] = math.floor(velSlider.val1) + j = j + 1 + end + + -- insert the accented velocity + for i = 1, (probSlider.val1) do + probTable[j] = math.floor(velSlider.val2) + j = j + 1 + end +end + +function GenLegatoTable(probTable, probSlider) +-- GenLegatoTable(probTable, velSlider, probSlider) +-- creates an event probability table using values from sliders + + local i, j = 1, 1 + ClearTable(probTable) + + -- no legato + for i = 1, (probSlider.max - probSlider.val1) do + probTable[j] = m.legato + j = j + 1 + end + + -- legato + for i = 1, (probSlider.val1) do + probTable[j] = 0 + j = j + 1 + end +end + function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) - local debug = false - if debug or m.debug then ConMsg("GenNoteAttributes()") end +-- GenNoteAttributes(accF, accProb, accVal, legF, legVal) -- accent, legato only + if not accF and not legF then return end local t1, t2 = GetNoteBuf(), NewNoteBuf() local i = 1 local noteStart, noteEnd, noteLen = 0, 0, 0 CopyTable(t1, t2) - if debug and m.debug then PrintNotes(t2) end + while t2[i] do + if t2[i][1] then + if accF then -- handle accent flag (8 = velocity) t2[i][8] = accProbTable[math.random(1, #accProbTable)] end -- end accent + if legF ~= 1 then -- no legato when called by euclid + if legF then -- handle legato flag (3 = noteStart, 4 = noteEnd, 5 = noteLen) noteLen = t2[i][5] if noteLen >= 960 + m.legato and noteLen <= 960 - m.legato then noteLen = 960 -- 1/4 @@ -854,128 +655,403 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) end --selected i = i + 1 end -- while t1[i] - if debug and m.debug then PrintNotes(t2) end + PurgeNoteBuf() InsertNotes() end --------------------------------------------------------------------------------- --- InsertNotes(note_buffer) - insert notes in the active take --------------------------------------------------------------------------------- -function InsertNotes() - local debug = false - if debug or m.debug then ConMsg("\nInsertNotes()") end - DeleteNotes() - local i = 1 - if m.activeTake and m.mItem then - local noteLength = 0 - local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() - local noteShift = m.seqShift * gridSize - local t1 = GetNoteBuf() - local t2 = {} -- for note shifting - CopyTable(t1, t2) - if debug then ConMsg("itemPPQN = "..itemLength) end - if debug then ConMsg("noteshift = "..noteShift) end +function GetItemLength() +-- GetItemLength(t) - get length of take 't', set various global vars +-- currently it only returns the item length (used in Sequencer and Euclid) + + --mItem = reaper.GetSelectedMediaItem(0, 0) + mItemLen = reaper.GetMediaItemInfo_Value(m.mItem, "D_LENGTH") + mBPM, mBPI = reaper.GetProjectTimeSignature2(0) + msPerMin = 60000 + msPerQN = msPerMin / mBPM + numQNPerItem = (mItemLen * 1000) / msPerQN + numBarsPerItem = numQNPerItem / 4 + ItemPPQN = numQNPerItem * m.ppqn + mItemTake = reaper.GetTake(m.mItem, 0) -- should fix looped items + ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! + return ItemPPQN + +end + +function GetReaperGrid(gridRad) +-- GetReaperGrid() - get the current grid size, set global var m.reaGrid + + if m.activeTake then + m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) -- returns quarter notes - for k, v in pairs(t2) do -- do note shifting - noteLength = v[4] - v[3] - v[3] = v[3] + noteShift - v[4] = v[4] + noteShift - - if v[3] >= itemLength then -- positive shift - v[3] = v[3] - itemLength - v[4] = v[4] - itemLength - - elseif v[3] < 0 then -- negative shift - v[3] = v[3] + itemLength - v[4] = v[4] + itemLength + if gridRad then -- if a grid object was passed, update it + if m.reaGrid == 0.25 then gridRad.val1 = 1 -- 1/16 + elseif m.reaGrid == 0.5 then gridRad.val1 = 2 -- 1/8 + elseif m.reaGrid == 1 then gridRad.val1 = 3 -- 1/4 + end -- m.reaGrid + end + end -- m.activeTake +end - end +function GenProbTable(preProbTable, sliderTable, probTable) +-- GenProbTable(preProbTable, slidersTable, probTable) +-- creates an event probability table using values from sliders + + local i, j, k, l = 1, 1, 1, 1 + local floor = math.floor + ClearTable(probTable) + + for i, v in ipairs(preProbTable) do + if sliderTable[j].val1 > 0 then + for l = 1, (sliderTable[j].val1) do + probTable[k] = preProbTable[i] + k = k + 1 + end -- for l + end -- if sliderTable[j] + j = j + 1 + end +end + +function SetSeqGridSizes(sliderTable) +-- SetSeqGridSizes() + for k, v in pairs(sliderTable) do + if sliderTable[k].label == "1/16" then m.preSeqProbTable[k] = 0.25 + elseif sliderTable[k].label == "1/8" then m.preSeqProbTable[k] = 0.5 + elseif sliderTable[k].label == "1/4" then m.preSeqProbTable[k] = 1.0 + elseif sliderTable[k].label == "Rest" then m.preSeqProbTable[k] = -1.0 + end + end +end + + + +-- euclidiser ---------------------------------------------------------------- +-------------------------------------------------------------------------------- +function GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) +-- GenBjorklund(pulses, steps, rotation, accProbTable, accSlider) + + local floor = math.floor + local t, t2 = NewNoteBuf(), GetNoteBuf() + CopyTable(t2, t) + GetReaperGrid() -- populates m.reaGrid + ClearTable(t) + + local itemPos = 0 + local gridSize = m.reaGrid * m.ppqn + local itemLength = GetItemLength() + local noteStart, noteEnd, noteLen, noteVel = 0, 0, 0, 0 + local newNote = 0 + local noteCount = 0; restCount = 0 + local pulse = floor(pulses.val1 + 0.5) + local step = floor(steps.val1 + 0.5) + local pattern = b.generate(pulse, step) + local rot = floor(rotation.val1 + 0.5) + local idx = (-rot) + 1; idx = Wrap(idx, step) + + while itemPos < itemLength do + + if pattern[idx] then + noteStart = itemPos + noteLen = gridSize + noteEnd = noteStart + noteLen + itemPos = itemPos + noteLen - if v[4] > itemLength then v[4] = itemLength - 1 end + if m.eucAccentF then -- handle accent flag + noteVel = accProbTable[math.random(1, #accProbTable)] + else + noteVel = floor(accSlider.val1) + end -- m.seqAccentF - if debug then ConMsg("v3 = "..v[3].." ".."v4 = "..v[4].." ".."notelen = "..noteLength) end + --noteVel = accProbTable[math.random(1, #accProbTable)] + noteCount = noteCount + 1 + t[noteCount] = {} + t[noteCount][1] = true -- selected + t[noteCount][2] = false -- muted + t[noteCount][3] = noteStart -- startppqn + t[noteCount][4] = noteEnd + m.legato -- endppqn + t[noteCount][5] = noteLen -- note length + t[noteCount][6] = 0 -- channel + t[noteCount][7] = m.root -- note number + t[noteCount][8] = noteVel -- velocity + + else + itemPos = itemPos + gridSize + restCount = restCount + 1 end + idx = idx + 1 + idx = Wrap(idx, step) + end + + PurgeNoteBuf() + InsertNotes() +end + + +-- utility functions ---------------------------------------------------------- +-------------------------------------------------------------------------------- + +function ClearTable(t) +-- ClearTable(t) - set all items in 2D table 't' to nil + + for k, v in pairs(t) do + t[k] = nil + end +end + +function CopyTable(t1, t2) -- deprecated +-- CopyTable(t1, t2) - copies note data from t1 to t2 + ClearTable(t2) -- safety, not needed if new table supplied + + local i, j = 1, 1 + + while t1[i] do + j = 1 + t2[i] = {} - while t2[i] do - reaper.MIDI_InsertNote(m.activeTake, t2[i][1], t2[i][2], t2[i][3], t2[i][4], t2[i][6], t2[i][7], t2[i][8], false) - --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) - i = i + 1 - end -- while t2[i] - reaper.MIDI_Sort(m.activeTake) - reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off - else - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake + while (t1[i][j] ~= nil) do + t2[i][j] = t1[i][j] + j = j + 1 + end --while (t1[i][j] + + i = i + 1 + end -- while t1[i] end --------------------------------------------------------------------------------- --- PrintNotes - arg note_buffer t; print note_buffer to reaper console --------------------------------------------------------------------------------- +function CopyNoteTable(t1, t2, selected) +-- Copies notes from table1 to table2, optionally filtered on selected notes + + ClearTable(t2) + + local i, j = 1, 1 + + if not selected then-- copy all + while t1[i] do + table.insert(t2, t1[i]) + t2[i].idx = i + i = i + 1 + end + + else -- copy selected + while t1[i] do + if t1[i][1] or m.rndAllNotesF then + table.insert(t2, t1[i]) + t2[#t2].idx = i + end + i = i + 1 + end + end + +end + +function PrintNote(t) -- debug code +-- PrintNote - arg note t; print a single note to reaper console + + if not t then return end + + local j = 0 + local str = "id \t sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" + + while t[j] ~= nil do + str = str .. tostring(t[j]) .. "\t" + j = j + 1 + end + + ConMsg(str) +end + function PrintNotes(t) -- debug code - local debug = false - if debug or m.debug then ConMsg("PrintNotes()") end - if not t then return end - local i = 1 - local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" +-- PrintNotes - arg note_buffer t; print note_buffer to reaper console + + if not t then return end + + local i, j = 1, 0 + local str = "id \t sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" + while t[i] do - j = 1 + j = 0 + while (t[i][j] ~= nil) do str = str .. tostring(t[i][j]) .. "\t" j = j + 1 end + str = str .. "\n" i = i + 1 end -- while t[i] + str = str .. "\n" - if debug or m.debug then ConMsg(str) end + ConMsg(str) end --------------------------------------------------------------------------------- + +function PrintTable(t) -- debug code (deprecate?) -- PrintTable - print table to reaper console --------------------------------------------------------------------------------- -function PrintTable(t) -- debug code - local debug = false - if debug or m.debug then ConMsg("PrintTable()") end + local str = "" for k, v in pairs(t) do str = str .. tostring(v) .. "\t" end str = str .. "\n" - if debug or m.debug then ConMsg(str) end + end --------------------------------------------------------------------------------- --- ShowMessage(textbox, message number) - display or hide a message for user --------------------------------------------------------------------------------- + + +function Wrap (n, max) +-- Wrap(n, max) -return n wrapped between 'n' and 'max' + + n = n % max + if (n < 1) then n = n + max end + + return n +end + +function RGB2Dec(r, g, b) +-- RGB2Dec(r, g, b) - takes 8 bit r, g, b values, returns decimal (0 to 1) + + if r < 0 or r > 255 then r = wrap(r, 255) end + if g < 0 or g > 255 then g = wrap(g, 255) end + if b < 0 or b > 255 then b = wrap(b, 255) end + + return r/255, g/255, b/255 +end + +function RGB2Packed(r, g, b) +-- RGB2Packed(r, g, b) - returns a packed rgb value + + local floor = math.floor + g = (g << 8) + b = (b << 16) + + return floor(r + g + b) +end + +function ConMsg(str) +-- ConMsg(str) - outputs 'str' to the Reaper console + reaper.ShowConsoleMsg(str .."\n") +end + function ShowMessage(tb, msgNum) - local debug = false - if debug and m.debug then ConMsg("ShowMessage() ") end +-- ShowMessage(textbox, message number) - display or hide a message for user + if msgNum == 0 then tb.tab = (1 << 9) tb.label = "" + elseif msgNum == 1 then tb.tab = 0 tb.label = "MIDI Editor Closed" + elseif msgNum == 2 then tb.tab = 0 tb.label = "Please select a MIDI Item in the Arrange Window" end - e.gScaleState = true + + e.gScaleState = true +end + + +-- table serialization - steve dekorte ---------------------------------------- +-------------------------------------------------------------------------------- +function pickle(t) + return Pickle:clone():pickle_(t) +end + +Pickle = { + clone = function (t) local nt = {} + for i, v in pairs(t) do + nt[i] = v + end + return nt +end +} + +function Pickle:pickle_(root) + + if type(root) ~= "table" then + error("can only pickle tables, not " .. type(root) .. "s") + end + + self._tableToRef = {} + self._refToTable = {} + local savecount = 0 + self:ref_(root) + local s = "" + + while #self._refToTable > savecount do + savecount = savecount + 1 + local t = self._refToTable[savecount] + s = s .. "{\n" + + for i, v in pairs(t) do + s = string.format("%s[%s]=%s,\n", s, self:value_(i), self:value_(v)) + end + + s = s .. "},\n" + end + + return string.format("{%s}", s) +end + +function Pickle:value_(v) + local vtype = type(v) + + if vtype == "string" then return string.format("%q", v) + elseif vtype == "number" then return v + elseif vtype == "boolean" then return tostring(v) + elseif vtype == "table" then return "{"..self:ref_(v).."}" + else error("pickle a " .. type(v) .. " is not supported") + end +end + +function Pickle:ref_(t) + + local ref = self._tableToRef[t] + + if not ref then + if t == self then error("can't pickle the pickle class") end + table.insert(self._refToTable, t) + ref = #self._refToTable + self._tableToRef[t] = ref + end + + return ref end --------------------------------------------------------------------------------- --- FUNCTIONS END --------------------------------------------------------------------------------- +function unpickle(s) + + if type(s) ~= "string" then + error("can't unpickle a " .. type(s) .. ", only strings") + end + + local gentables = load("return " .. s) + local tables = gentables() + + for tnum = 1, #tables do + local t = tables[tnum] + local tcopy = {} + for i, v in pairs(t) do tcopy[i] = v end + + for i, v in pairs(tcopy) do + local ni, nv + if type(i) == "table" then ni = tables[i[1]] else ni = i end + if type(v) == "table" then nv = tables[v[1]] else nv = v end + t[i] = nil + t[ni] = nv + end + end + + return tables[1] +end + + + + +-- GUI Elements -------------------------------------------------------------- -------------------------------------------------------------------------------- --- GUI START --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- GUI Elements --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- Main Window + +-- Main Window --------------------------------------------------------------- -------------------------------------------------------------------------------- + -- Persistent window elements local winFrame = e.Frame:new({0}, 5, 5, m.win_w - 10, m.win_h - 10, e.col_grey4) local zoomDrop = e.Droplist:new({0}, 5, 5, 40, 22, e.col_green, "", e.Arial, m.font_sz, e.col_grey8, 4, {"70%", "80%", "90%", "100%", "110%", "120%", "140%", "160%", "180%", "200%"}) @@ -986,24 +1062,35 @@ local layerBtn03 = e.Button:new({0}, 205, m.win_h - 25, 100, 20, e.col_grey5, "E local layerBtn04 = e.Button:new({0}, 305, m.win_h - 25, 100, 20, e.col_grey5, "Options", e.Arial, m.font_sz, e.col_grey7) local undoBtn = e.Button:new({0}, m.win_w-85, m.win_h -25, 40, 20, e.col_grey5, "Undo", e.Arial, m.font_sz, e.col_grey7) local redoBtn = e.Button:new({0}, m.win_w-45, m.win_h -25, 40, 20, e.col_grey5, "Redo", e.Arial, m.font_sz, e.col_grey7) + -- Persistent window element table t_winElements = {winFrame, zoomDrop, winText, layerBtn01, layerBtn02, layerBtn03, layerBtn04, undoBtn, redoBtn} + + +-- Common Elements ----------------------------------------------------------- -------------------------------------------------------------------------------- --- Common Elements --------------------------------------------------------------------------------- + -- key, octave, & scale droplists dx, dy, dw, dh = 25, 70, 110, 20 -local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, dw, dh, e.col_blue, "Root Note", e.Arial, m.font_sz, e.col_grey8, m.key, m.notes) -local octDrop = e.Droplist:new({1, 2, 3}, dx, dy + 45, dw, dh, e.col_blue, "Octave ", e.Arial, m.font_sz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) -local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 90, dw, dh, e.col_blue, "Scale", e.Arial, m.font_sz, e.col_grey8, 1, m.scalelist) +local keyDrop = e.Droplist:new({1, 2, 3}, dx, dy, (dw*0.5)-5, dh, e.col_blue, "Key", e.Arial, m.font_sz, e.col_grey8, m.key, m.notes) +local octDrop = e.Droplist:new({1, 2, 3}, dx+(dw*0.5)+5, dy, (dw*0.5)-5, dh, e.col_blue, "Oct ", e.Arial, m.font_sz, e.col_grey8, m.oct,{0, 1, 2, 3, 4, 5, 6, 7}) +local scaleDrop = e.Droplist:new({1, 2, 3}, dx, dy + 50, dw, dh, e.col_blue, "Scale", e.Arial, m.font_sz, e.col_grey8, 1, m.scalelist) local t_Droplists = {keyDrop, octDrop, scaleDrop} + + + +-- Randomiser Layer ---------------------------------------------------------- -------------------------------------------------------------------------------- --- Randomiser Layer --------------------------------------------------------------------------------- + +-- note shuffle button +local shuffleBtn = e.Button:new({1}, 25, 165, 110, 25, e.col_green, "Shuffle", e.Arial, m.font_sz, e.col_grey8) + -- note randomise button -local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Generate", e.Arial, m.font_sz, e.col_grey8) +local randomBtn = e.Button:new({1}, 25, 205, 110, 25, e.col_green, "Randomise", e.Arial, m.font_sz, e.col_grey8) + + -- note weight sliders local nx, ny, nw, nh, np = 160, 50, 30, 150, 40 local noteSldr01 = e.Vert_Slider:new({1}, nx, ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) @@ -1019,34 +1106,45 @@ local noteSldr10 = e.Vert_Slider:new({1}, nx+(np*9), ny, nw, nh, e.col_blue, "", local noteSldr11 = e.Vert_Slider:new({1}, nx+(np*10), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) local noteSldr12 = e.Vert_Slider:new({1}, nx+(np*11), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) local noteSldr13 = e.Vert_Slider:new({1}, nx+(np*12), ny, nw, nh, e.col_blue, "", e.Arial, m.font_sz, e.col_grey8, 1, 0, 0, 12, 1) + -- Note probability slider table local t_noteSliders = {noteSldr01, noteSldr02, noteSldr03, noteSldr04, noteSldr05, noteSldr06, noteSldr07, noteSldr08, noteSldr09, noteSldr10, noteSldr11, noteSldr12, noteSldr13} + -- Note probability slider label (Textbox) - right-click to reset all local probSldrText = e.Textbox:new({1}, nx, 210, 510, 20, e.col_grey5, "Note Weight Sliders", e.Arial, m.font_sz, e.col_grey7) + -- Note octave doubler probability slider local octProbSldr = e.Vert_Slider:new({1}, nx+(np*13) + 10, ny, nw, nh, e.col_blue, "%", e.Arial, m.font_sz, e.col_grey8, m.rndOctProb, 0, 0, 10, 1) local octProbText = e.Textbox:new({1}, nx+(np*13) + 10, 210, (nw), 20, e.col_grey5, "Oct", e.Arial, m.font_sz, e.col_grey7) + -- Note randomiser options local noteOptionsCb = e.Checkbox:new({1}, nx+(np*14)+10, ny+30, 30, 30, e.col_orange, "", e.Arial, m.font_sz, e.col_grey8, {0,0,0}, {"All / Sel Notes", "1st Note = Root", "Octave X2"}) local noteOptionText = e.Textbox:new({1}, nx+(np*14)+20, 210, (nw*4), 20, e.col_grey5, "Options", e.Arial, m.font_sz, e.col_grey7) + + + +-- Sequencer Layer ----------------------------------------------------------- -------------------------------------------------------------------------------- --- Sequencer Layer --------------------------------------------------------------------------------- + -- sequence generate button local sequenceBtn = e.Button:new({2}, 25, 205, 110, 25, e.col_yellow, "Generate", e.Arial, m.font_sz, e.col_grey8) local sx, sy, sw, sh, sp = 160, 50, 30, 150, 40 + -- sequencer grid size radio selector local seqGridRad = e.Rad_Button:new({2,3}, sx, sy + 40, 30, 30, e.col_yellow, "", e.Arial, m.font_sz, e.col_grey8, 1, {"1/16", "1/8", "1/4"}) local seqGridText = e.Textbox:new({2,3}, sx, 210, (sw*2)+20, 20, e.col_grey5, "Grid Size", e.Arial, m.font_sz, e.col_grey7) + -- sequence grid probability sliders local seqSldr16 = e.Vert_Slider:new({2}, sx+(sp*3), sy, sw, sh, e.col_blue, "1/16", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) local seqSldr8 = e.Vert_Slider:new({2}, sx+(sp*4), sy, sw, sh, e.col_blue, "1/8", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) local seqSldr4 = e.Vert_Slider:new({2}, sx+(sp*5), sy, sw, sh, e.col_blue, "1/4", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) local seqSldrRest = e.Vert_Slider:new({2}, sx+(sp*6), sy, sw, sh, e.col_blue, "Rest", e.Arial, m.font_sz, e.col_grey8, 0, 0, 0, 16, 1) + -- sequence grid probability slider table local t_seqSliders = {seqSldr16, seqSldr8, seqSldr4, seqSldrRest} + -- sequence grid probability sliders label - right click to reset all (per grid size selection) local seqSldrText = e.Textbox:new({2}, sx + (sp * 3), 210, (sw * 5), 20, e.col_grey5, "Size Weight Sliders", e.Arial, m.font_sz, e.col_grey7) @@ -1068,52 +1166,58 @@ local seqShiftText = e.Textbox:new({2}, sx + (sp * 11) + 10, 210, sw * 3, 20, e. -- Sequencer options local seqOptionsCb = e.Checkbox:new({2}, sx+(np * 14) + 10, sy + 5, 30, 30, e.col_orange, "", e.Arial, m.font_sz, e.col_grey8, {0,0,0,0,0}, {"Generate", "1st Note Always", "Accent", "Legato", "Rnd Notes"}) + + + +-- Euclidean Layer ----------------------------------------------------------- -------------------------------------------------------------------------------- --- Euclid Layer --------------------------------------------------------------------------------- --- euclid generate button + +-- euclidean generate button local euclidBtn = e.Button:new({3}, 25, 205, 110, 25, e.col_orange, "Generate", Arial, m.font_sz, e.col_grey8) + -- euclidean sliders local ex, ey, ew, eh, ep = 160, 50, 30, 150, 40 local euclidPulsesSldr = e.Vert_Slider:new({3}, ex+(ep*3), ey, ew, eh, e.col_blue, "Puls", Arial, m.font_sz, e.col_grey8, m.eucPulses, 0, 1, 24, 1) local euclidStepsSldr = e.Vert_Slider:new({3}, ex+(ep*4), ey, ew, eh, e.col_blue, "Step", Arial, m.font_sz, e.col_grey8, m.eucSteps, 0, 1, 24, 1) local euclidRotationSldr = e.Vert_Slider:new({3}, ex+(ep*5), ey, ew, eh, e.col_blue, "Rot", Arial, m.font_sz, e.col_grey8, m.eucRot, 0, 0, 24, 1) local t_euclidSliders = {euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr} --- euclid slider label - right click to reset all + +-- euclidean slider label - right click to reset all local txtEuclidLabel = e.Textbox:new({3}, ex + (ep * 3), 210, (ew * 3) + 20, 20, e.col_grey5, "Euclid Sliders", Arial, m.font_sz, e.col_grey7) --- Sequencer options + +-- euclidean options local eucOptionsCb = e.Checkbox:new({3}, ex + (ep * 14) + 10, ey + 40, 30, 30, e.col_orange, "", e.Arial, m.font_sz, e.col_grey8, {0,0,0}, {"Generate", "Accent", "Rnd Notes"}) --------------------------------------------------------------------------------- --- Options Layer + + +-- Options Layer ------------------------------------------------------------- -------------------------------------------------------------------------------- local optText = e.Textbox:new({4}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_grey5, "Nothing to see here, yet...", e.Arial, m.font_sz, e.col_grey8) --------------------------------------------------------------------------------- --- Messages Layer + + +-- Messages Layer ------------------------------------------------------------ -------------------------------------------------------------------------------- local msgText = e.Textbox:new({9}, m.win_x + 10, m.win_y + 30, m.win_w - 40, m.win_h - 80, e.col_greym, "", e.Arial, 22, e.col_grey9) + + +-- Shared Element Tables ----------------------------------------------------- -------------------------------------------------------------------------------- --- Shared Element Tables --------------------------------------------------------------------------------- -local t_Buttons = {randomBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} +local t_Buttons = {randomBtn, shuffleBtn, sequenceBtn, seqShiftLBtn, seqShiftRBtn, euclidBtn} local t_Checkboxes = {noteOptionsCb, seqOptionsCb, eucOptionsCb} local t_RadButtons = {seqGridRad} local t_RSliders = {octProbSldr, seqAccRSldr, seqAccProbSldr, seqLegProbSldr} local t_Textboxes = {probSldrText, octProbText, seqGridText, seqSldrText, seqShiftVal, seqShiftText, seqAccSldrText, seqLegSldrText, txtEuclidLabel, optText, msgText} --------------------------------------------------------------------------------- + + + +-- main window gui functions ------------------------------------------------- -------------------------------------------------------------------------------- --- GUI Functions START --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- Main window --------------------------------------------------------------------------------- --- Window zoom droplist -zoomDrop.onLClick = function() -- window scaling - local debug = false - if debug or m.debug then ConMsg("\nzoomDrop.onLClick()") end + +zoomDrop.onLClick = function() -- Window zoom droplist - window scaling + if zoomDrop.val1 == 1 then e.gScale = 0.7 elseif zoomDrop.val1 == 2 then e.gScale = 0.8 elseif zoomDrop.val1 == 3 then e.gScale = 0.9 @@ -1125,7 +1229,7 @@ zoomDrop.onLClick = function() -- window scaling elseif zoomDrop.val1 == 9 then e.gScale = 1.8 elseif zoomDrop.val1 == 10 then e.gScale = 2.0 end - if debug or m.debug then ConMsg("zoom = " .. tostring(e.gScale)) end + -- Save state, close and reopen GFX window if not pExtState.win_x then __, m.win_x, m.win_y, __, __ = gfx.dock(-1,0,0,0,0) @@ -1134,124 +1238,139 @@ zoomDrop.onLClick = function() -- window scaling pExtState.zoomDrop = zoomDrop.val1 pExtSaveStateF = true end + m.zoomF = true end --- Layer 1 button -layerBtn01.onLClick = function() -- randomiser - local debug = false - if debug or m.debug then ConMsg("\nlayerBtn01.onLClick() (note randomiser)") end + +layerBtn01.onLClick = function() -- Layer 1 button - randomiser + e.gActiveLayer = 1 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_green) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_green) + layerBtn01.font_rgba = e.col_grey8 -- highlight layer 1 layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_green) + layerBtn02.font_rgba = e.col_grey7 layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_grey5) + layerBtn03.font_rgba = e.col_grey7 layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_grey5) + layerBtn04.font_rgba = e.col_grey7 layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey5) + e.gScaleState = true + -- set project ext state pExtState.activeLayer = e.gActiveLayer pExtSaveStateF = true end --- Layer 2 button -layerBtn02.onLClick = function() -- sequencer - local debug = false - if debug or m.debug then ConMsg("\nlayerBtn02.onLClick() (sequencer)") end + +layerBtn02.onLClick = function() -- Layer 2 button - sequencer + e.gActiveLayer = 2 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_yellow) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_yellow) + layerBtn01.font_rgba = e.col_grey7 layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_grey5) + layerBtn02.font_rgba = e.col_grey8 -- highlight layer 2 layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_yellow) + layerBtn03.font_rgba = e.col_grey7 layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_grey5) + layerBtn04.font_rgba = e.col_grey7 layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey5) + e.gScaleState = true - -- set project ext state + + -- set project ext state pExtState.activeLayer = e.gActiveLayer pExtSaveStateF = true end --- Layer 3 button -layerBtn03.onLClick = function() -- euclidean - local debug = false - if debug or m.debug then ConMsg("\nlayerBtn03.onLClick() (euclid)") end + +layerBtn03.onLClick = function() -- Layer 3 button - euclidean + e.gActiveLayer = 3 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_orange) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_orange) + layerBtn01.font_rgba = e.col_grey7 layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_grey5) + layerBtn02.font_rgba = e.col_grey7 layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_grey5) + layerBtn03.font_rgba = e.col_grey8 -- highlight layer 3 layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_orange) + layerBtn04.font_rgba = e.col_grey7 layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey5) + e.gScaleState = true - -- set project ext state + + -- set project ext state pExtState.activeLayer = e.gActiveLayer pExtSaveStateF = true end --- Layer 4 button -layerBtn04.onLClick = function() -- options - local debug = false - if debug or m.debug then ConMsg("\nlayerBtn04.onLClick() (options)") end + +layerBtn04.onLClick = function() -- Layer 4 button - options + e.gActiveLayer = 4 zoomDrop.r, zoomDrop.g, zoomDrop.b, zoomDrop.a = table.unpack(e.col_grey5) winText.r, winText.g, winText.b, winText.a = table.unpack(e.col_grey5) + layerBtn01.font_rgba = e.col_grey7 layerBtn01.r, layerBtn01.g, layerBtn01.b, layerBtn01.a = table.unpack(e.col_grey5) + layerBtn02.font_rgba = e.col_grey7 layerBtn02.r, layerBtn02.g, layerBtn02.b, layerBtn02.a = table.unpack(e.col_grey5) + layerBtn03.font_rgba = e.col_grey7 layerBtn03.r, layerBtn03.g, layerBtn03.b, layerBtn03.a = table.unpack(e.col_grey5) + layerBtn04.font_rgba = e.col_grey8 -- highlight layer 4 layerBtn04.r, layerBtn04.g, layerBtn04.b, layerBtn04.a = table.unpack(e.col_grey6) + e.gScaleState = true - -- set project ext state + + -- set project ext state pExtState.activeLayer = e.gActiveLayer pExtSaveStateF = true end --- Undo button -undoBtn.onLClick = function() -- undo - local debug = false - if debug or m.debug then ConMsg("\nundoBtn.onLClick()") end + +undoBtn.onLClick = function() -- Undo button UndoNoteBuf() InsertNotes() - PrintNotes(m.notebuf[m.notebuf.i]) end --- Redo button -redoBtn.onLClick = function() -- redo - local debug = false - if debug or m.debug then ConMsg("\nredoBtn.onLClick()") end + +redoBtn.onLClick = function() -- Redo button + if m.notebuf[m.notebuf.i + 1] ~= nil then - --PrintNotes(m.notebuf[m.notebuf.i + 1]) m.notebuf.i = m.notebuf.i + 1 InsertNotes() - --PrintNotes(m.notebuf[m.notebuf.i]) - else - if debug or m.debug then ConMsg("\nnothing to redo...") end end end --- Set default window options -function SetDefaultWindowOpts() - local debug = false - if debug or m.debug then ConMsg("SetDefaultWinOpts()") end + +-- defaults +function SetDefaultWindowOpts() -- Set default window options + if pExtState.zoomDrop then zoomDrop.val1 = pExtState.zoomDrop end + if pExtState.win_x or pExtState.win_y then m.win_x = pExtState.win_x m.win_y = pExtState.win_y end zoomDrop.onLClick() end --- Set default layer -function SetDefaultLayer() + +function SetDefaultLayer() -- Set default layer + if pExtState.activeLayer then if pExtState.activeLayer == 1 then layerBtn01.onLClick() elseif pExtState.activeLayer == 2 then layerBtn02.onLClick() @@ -1261,13 +1380,13 @@ function SetDefaultLayer() end end + + +-- randomiser gui functions -------------------------------------------------- -------------------------------------------------------------------------------- --- Note Randomiser --------------------------------------------------------------------------------- --- Randomiser button -randomBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end + +randomBtn.onLClick = function() -- Random button action + if m.activeTake and m.mItem then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift seqShiftVal.label = tostring(m.seqShift) @@ -1275,89 +1394,140 @@ randomBtn.onLClick = function() if #m.noteProbTable == 0 then return end GenOctaveTable(m.octProbTable, octProbSldr) GetNotesFromTake() - RandomiseNotesPoly(m.noteProbTable) + RandomiseNotes() + -- set project ext state pExtState.noteSliders = {} + for k, v in pairs(t_noteSliders) do pExtState.noteSliders[k] = v.val1 end + pExtState.rndOctProb = octProbSldr.val1 pExtSaveStateF = true end --m.activeTake end --- Randomiser options toggle logic -noteOptionsCb.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nnoteOptionsCb.onLClick()") end + +shuffleBtn.onLClick = function() -- Shuffle button action + + if m.activeTake and m.mItem then + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift + seqShiftVal.label = tostring(m.seqShift) + GetNotesFromTake() + ShuffleNotes() + end + +end + +noteOptionsCb.onLClick = function() -- Randomiser options toggle logic + m.rndAllNotesF = noteOptionsCb.val1[1] == 1 and true or false -- All / Sel Notes m.rndFirstNoteF = noteOptionsCb.val1[2] == 1 and true or false -- 1st Note Root m.rndOctX2F = noteOptionsCb.val1[3] == 1 and true or false -- Octave X2 + pExtState.noteOptionsCb = {m.rndAllNotesF, m.rndFirstNoteF, m.rndOctX2F} pExtSaveStateF = true - if debug or m.debug then PrintTable(noteOptionsCb.val1) end + end --- Root Key droplist -keyDrop.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nkeyDrop.onLClick()") end + +keyDrop.onLClick = function() -- Root Key droplist + m.key = keyDrop.val1 m.root = SetRootNote(m.oct, m.key) UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) + -- set project ext state pExtState.key = m.key pExtState.root = m.root pExtSaveStateF = true end --- Octave droplist -octDrop.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\noctDrop.onLClick()") end + +octDrop.onLClick = function() -- Octave droplist + m.oct = octDrop.val1 m.root = SetRootNote(m.oct, m.key) + -- set project ext state pExtState.oct = m.oct pExtState.root = m.root pExtSaveStateF = true end --- Scale droplist -scaleDrop.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nscaleDrop.onLClick()") end + +scaleDrop.onLClick = function() -- Scale droplist + SetScale(scaleDrop.val2[scaleDrop.val1], m.scales, m.preNoteProbTable) - if m.rndPermuteF then - noteOptionsCb.val1[1] = 0 - m.rndAllNotesF = false - end UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) + -- set project ext state pExtState.curScaleName = scaleDrop.val2[scaleDrop.val1] pExtSaveStateF = true end --- Set default scale options -function SetDefaultScaleOpts() - local debug = false - if debug or m.debug then ConMsg("SetDefaultScaleOpts()") end +probSldrText.onRClick = function() -- Reset note probability sliders + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Note Sliders") + + if result == 1 then + + for k, v in pairs(t_noteSliders) do -- reset the sliders + if v.label ~= "" then v.val1 = 1 end + end -- in pairs(t_noteSliders) + + if pExtState.noteSliders then -- write the new proj ext state + for k, v in pairs(t_noteSliders) do + if v.label ~= "" then pExtState.noteSliders[k] = v.val1 end + end -- in pairs(t_noteSliders) + end -- pExtState.noteSliders + + pExtSaveStateF = true -- set the ext state save flag + end -- result +end + +octProbText.onRClick = function() -- Reset octave probability slider + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Octave Slider") + + if result == 1 then + octProbSldr.val1 = m.rndOctProb + + if pExtState.rndOctProb then -- write the new proj ext state + pExtState.rndOctProb = nil + end -- pExtState.noteSliders + + pExtSaveStateF = true -- set the ext state save flag + end -- result +end + +-- defaults +function SetDefaultScaleOpts() -- Set default scale options + -- if key saved in project state, load it if pExtState.key then m.key = math.floor(tonumber(pExtState.key)) keyDrop.val1 = m.key end + -- if octave saved in project state, load it if pExtState.oct then m.oct = math.floor(tonumber(pExtState.oct)) octDrop.val1 = m.oct end + -- set the midi note number for scale root m.root = SetRootNote(m.oct, m.key) + -- create a scale name lookup table for the gui (scaleDrop) for k, v in pairs(m.scales) do m.scalelist[k] = m.scales[k]["name"] end + -- if scale name saved in project state, load it if pExtState.curScaleName then m.curScaleName = pExtState.curScaleName end + -- update the scale dropbox val1 to match the scale table index for k, v in pairs(m.scales) do if v.name == m.curScaleName then scaleDrop.val1 = k end @@ -1366,81 +1536,53 @@ function SetDefaultScaleOpts() SetScale(m.curScaleName, m.scales, m.preNoteProbTable) --set chosen scale UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) -- set sliders labels to current scale notes end --- Set default randomiser options -function SetDefaultRndOptions() - local debug = false - if debug or m.debug then ConMsg("SetDefaultRndOptions()") end + +function SetDefaultRndOptions() -- Set default randomiser options + -- if randomiser options were saved to project state, load them if pExtState.noteOptionsCb then m.rndAllNotesF = pExtState.noteOptionsCb[1] == true and true or false m.rndFirstNoteF = pExtState.noteOptionsCb[2] == true and true or false m.rndOctX2F = pExtState.noteOptionsCb[3] == true and true or false - end + end + -- set randomiser options using defaults, or loaded project state noteOptionsCb.val1[1] = (true and m.rndAllNotesF) and 1 or 0 -- all notes noteOptionsCb.val1[2] = (true and m.rndFirstNoteF) and 1 or 0 -- first note root noteOptionsCb.val1[3] = (true and m.rndOctX2F) and 1 or 0 -- octave doubler end --- Set default randomiser sliders -function SetDefaultRndSliders() - local debug = false - if debug or m.debug then ConMsg("SetDefaultRndSliders()") end - -- if randomiser sliders were saved to project state, load them - if pExtState.noteSliders then - for k, v in pairs(t_noteSliders) do - v.val1 = pExtState.noteSliders[k] - end - else - for k, v in pairs(t_noteSliders) do - v.val1 = 1 - end - end -- load note sliders pExtState - if pExtState.rndOctProb then -- octave probability slider - octProbSldr.val1 = pExtState.rndOctProb - else - octProbSldr.val1 = m.rndOctProb - end -end - --- Reset note probability sliders -probSldrText.onRClick = function() - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Note Sliders") - if result == 1 then - for k, v in pairs(t_noteSliders) do -- reset the sliders - if v.label ~= "" then v.val1 = 1 end - end -- in pairs(t_noteSliders) - if pExtState.noteSliders then -- write the new proj ext state - for k, v in pairs(t_noteSliders) do - if v.label ~= "" then pExtState.noteSliders[k] = v.val1 end - end -- in pairs(t_noteSliders) - end -- pExtState.noteSliders - pExtSaveStateF = true -- set the ext state save flag - end -- result -end --- Reset octave probability slider -octProbText.onRClick = function() - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Octave Slider") - if result == 1 then + +function SetDefaultRndSliders() -- Set default randomiser sliders + + -- if randomiser sliders were saved to project state, load them + if pExtState.noteSliders then + for k, v in pairs(t_noteSliders) do + v.val1 = pExtState.noteSliders[k] + end + else + for k, v in pairs(t_noteSliders) do + v.val1 = 1 + end + end -- load note sliders pExtState + + if pExtState.rndOctProb then -- octave probability slider + octProbSldr.val1 = pExtState.rndOctProb + else octProbSldr.val1 = m.rndOctProb - if pExtState.rndOctProb then -- write the new proj ext state - pExtState.rndOctProb = nil - end -- pExtState.noteSliders - pExtSaveStateF = true -- set the ext state save flag - end -- result + end end + + +-- sequencer gui functions --------------------------------------------------- -------------------------------------------------------------------------------- --- Sequencer --------------------------------------------------------------------------------- --- Sequencer button -sequenceBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end + +sequenceBtn.onLClick = function() -- Sequencer button + if m.activeTake and m.mItem then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence seqShiftVal.label = tostring(m.seqShift) + if m.seqF then SetSeqGridSizes(t_seqSliders) GenProbTable(m.preSeqProbTable, t_seqSliders, m.seqProbTable) @@ -1451,6 +1593,7 @@ sequenceBtn.onLClick = function() if m.seqRndNotesF then randomBtn.onLClick() -- call RandomiseNotes end + else -- not m.seqF GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GenLegatoTable(m.legProbTable, seqLegProbSldr) @@ -1460,6 +1603,7 @@ sequenceBtn.onLClick = function() randomBtn.onLClick() -- call RandomiseNotes end end -- m.seqF + -- set project ext state if seqGridRad.val1 == 1 then -- 1/16 grid pExtState.seqGrid16 = {} @@ -1467,12 +1611,14 @@ sequenceBtn.onLClick = function() pExtState.seqGrid16[k] = v.val1 end end + if seqGridRad.val1 == 2 then -- 1/8 grid pExtState.seqGrid8 = {} for k, v in pairs (t_seqSliders) do pExtState.seqGrid8[k] = v.val1 end end + if seqGridRad.val1 == 3 then -- 1/4 grid pExtState.seqGrid4 = {} for k, v in pairs (t_seqSliders) do @@ -1484,28 +1630,26 @@ sequenceBtn.onLClick = function() pExtState.seqAccRSldrHi = seqAccRSldr.val2 pExtState.seqAccProb = seqAccProbSldr.val1 pExtState.seqLegProb = seqLegProbSldr.val1 - pExtSaveStateF = true end --m.activeTake end --- Sequencer options toggle logic -seqOptionsCb.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nseqOptionsCb.onLClick()") end + +seqOptionsCb.onLClick = function() -- Sequencer options toggle logic + m.seqF = seqOptionsCb.val1[1] == 1 and true or false -- Generate m.seqFirstNoteF = seqOptionsCb.val1[2] == 1 and true or false -- 1st Note Always m.seqAccentF = seqOptionsCb.val1[3] == 1 and true or false -- Accent m.seqLegatoF = seqOptionsCb.val1[4] == 1 and true or false -- Legato m.seqRndNotesF = seqOptionsCb.val1[5] == 1 and true or false -- Randomise Notes m.seqRepeatF = seqOptionsCb.val1[6] == 1 and true or false -- Repeat + pExtState.seqOptionsCb = {m.seqF, m.seqFirstNoteF, m.seqAccentF, m.seqLegatoF, m.seqRndNotesF, m.seqRepeatF} pExtSaveStateF = true - if debug or m.debug then PrintTable(seqOptionsCb.val1) end + end --- Sequencer grid radio button -seqGridRad.onLClick = function() -- change grid size - local debug = false - if debug or m.debug then ConMsg("\nseqGridRad.onLClick()") end + +seqGridRad.onLClick = function() -- Sequencer grid radio button + if m.activeTake then if seqGridRad.val1 == 1 then -- 1/16 grid @@ -1555,39 +1699,114 @@ seqGridRad.onLClick = function() -- change grid size end -- m.activeTake end --- Sequencer shift left -seqShiftLBtn.onLClick = function() + +seqShiftLBtn.onLClick = function() -- Sequencer shift left + if not m.mItem then return end local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMin = -(math.floor(itemLength / gridSize)-1) + if m.seqShift <= m.seqShiftMin then m.seqShift = 0 else m.seqShift = m.seqShift - 1 end + seqShiftVal.label = tostring(m.seqShift) InsertNotes() end --- Sequencer shift right -seqShiftRBtn.onLClick = function() + +seqShiftRBtn.onLClick = function() -- Sequencer shift right + if not m.mItem then return end + local gridSize = m.reaGrid * m.ppqn local itemLength = GetItemLength() m.seqShiftMax = math.floor(itemLength / gridSize) - 1 + if m.seqShift >= m.seqShiftMax then m.seqShift = 0 else m.seqShift = m.seqShift + 1 end + seqShiftVal.label = tostring(m.seqShift) InsertNotes() end --- Set sequencer default options -function SetDefaultSeqOptions() - local debug = false - if debug or m.debug then ConMsg("SetDefaultSeqOptions()") end +seqSldrText.onRClick = function() -- Reset sequencer grid sliders + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Sequence Sliders") + + if result == 1 then + if seqGridRad.val1 == 1 then -- 1/16ths + for k, v in pairs(t_seqSliders) do -- reset the sliders + v.val1 = m.seqGrid16[k] + end -- in pairs(t_seqSliders) + pExtState.seqGrid16 = nil + + elseif seqGridRad.val1 == 2 then -- 1/8ths + for k, v in pairs(t_seqSliders) do -- reset the sliders + v.val1 = m.seqGrid8[k] + end -- in pairs(t_seqSliders) + pExtState.seqGrid8 = nil + + elseif seqGridRad.val1 == 3 then -- 1/4ths + for k, v in pairs(t_seqSliders) do -- reset the sliders + v.val1 = m.seqGrid4[k] + end -- in pairs(t_seqSliders) + pExtState.seqGrid4 = nil + + end -- seqGridRad + pExtSaveStateF = true -- set the ext state save flag + end -- result +end + +seqAccSldrText.onRClick = function() -- Reset sequencer velocity slider + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Accent Sliders") + + if result == 1 then + seqAccRSldr.val1 = m.accentLow + if pExtState.seqAccRSldrLo then pExtState.seqAccRSldrLo = nil end + seqAccRSldr.val2 = m.accentHigh + if pExtState.seqAccRSldrHi then pExtState.seqAccRSldrHi = nil end + seqAccProbSldr.val1 = m.accentProb + if pExtState.seqAccProb then pExtState.seqAccProb = nil end + + pExtSaveStateF = true -- set the ext state save flag + end -- result +end + +seqLegSldrText.onRClick = function() -- Reset sequencer legato slider + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Legato Slider") + + if result == 1 then + seqLegProbSldr.val1 = m.legatoProb + if pExtState.seqLegProb then pExtState.seqLegProb = nil end + pExtSaveStateF = true + end -- result +end + +seqShiftText.onRClick = function() -- Reset sequencer shift + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Note Shift") + + if result == 1 then + m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 + seqShiftVal.label = tostring(m.seqShift) + InsertNotes() + end -- result +end + +-- defaults +function SetDefaultSeqOptions() -- Set sequencer default options -- if sequencer options were saved to project state, load them if pExtState.seqOptionsCb then @@ -1607,36 +1826,36 @@ function SetDefaultSeqOptions() seqOptionsCb.val1[5] = (true and m.seqRndNotesF) and 1 or 0 -- random notes seqOptionsCb.val1[6] = (true and m.seqRepeatF) and 1 or 0 -- repeat end --- Set default accent & legato sliders -function SetDefaultAccLegSliders() - local debug = false - if debug or m.debug then ConMsg("SetDefaultAccLegSliders()") end + +function SetDefaultAccLegSliders() -- Set default accent & legato sliders + -- if seq accent & legato sliders were saved to project state, load them if pExtState.seqAccRSldrLo then seqAccRSldr.val1 = pExtState.seqAccRSldrLo else seqAccRSldr.val1 = m.accentLow end + if pExtState.seqAccRSldrHi then seqAccRSldr.val2 = pExtState.seqAccRSldrHi else seqAccRSldr.val2 = m.accentHigh end + if pExtState.seqAccProb then seqAccProbSldr.val1 = pExtState.seqAccProb else seqAccProbSldr.val1 = m.accentProb end + if pExtState.seqLegProb then seqLegProbSldr.val1 = pExtState.seqLegProb else seqLegProbSldr.val1 = m.legatoProb end end --- Set default grid sliders -function SetDefaultSeqGridSliders() - local debug = false - if debug or m.debug then ConMsg("\nSetDefaultSeqGridSliders()") end + +function SetDefaultSeqGridSliders() -- Set default grid sliders GetReaperGrid(seqGridRad) SetSeqGridSizes(t_seqSliders) @@ -1674,121 +1893,43 @@ function SetDefaultSeqGridSliders() end end end -- pExtState.seqGrid4 - - if debug or m.debug then - for k, v in pairs(t_seqSliders) do - ConMsg("t_seqSliders.val1 (4) = " .. tostring(v.val1)) - end - end end --- Set default sequencer shift state -function SetDefaultSeqShift() - local debug = false - if debug or m.debug then ConMsg("SetDefaultSeqShift()") end + +function SetDefaultSeqShift() -- Set default sequencer shift state + m.seqShift = 0 m.seqShiftMin = 0 m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) end --- Reset sequencer grid sliders -seqSldrText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("\nseqSldrText.onLClick()") end - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Sequence Sliders") - if result == 1 then - if seqGridRad.val1 == 1 then -- 1/16ths - for k, v in pairs(t_seqSliders) do -- reset the sliders - v.val1 = m.seqGrid16[k] - end -- in pairs(t_seqSliders) - pExtState.seqGrid16 = nil - - elseif seqGridRad.val1 == 2 then -- 1/8ths - for k, v in pairs(t_seqSliders) do -- reset the sliders - v.val1 = m.seqGrid8[k] - end -- in pairs(t_seqSliders) - pExtState.seqGrid8 = nil - - elseif seqGridRad.val1 == 3 then -- 1/4ths - for k, v in pairs(t_seqSliders) do -- reset the sliders - v.val1 = m.seqGrid4[k] - end -- in pairs(t_seqSliders) - pExtState.seqGrid4 = nil - - end -- seqGridRad - pExtSaveStateF = true -- set the ext state save flag - end -- result -end --- Reset sequencer velocity slider -seqAccSldrText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("\nseqAccSldrText.onLClick()") end - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Accent Sliders") - if result == 1 then - seqAccRSldr.val1 = m.accentLow - if pExtState.seqAccRSldrLo then pExtState.seqAccRSldrLo = nil end - seqAccRSldr.val2 = m.accentHigh - if pExtState.seqAccRSldrHi then pExtState.seqAccRSldrHi = nil end - seqAccProbSldr.val1 = m.accentProb - if pExtState.seqAccProb then pExtState.seqAccProb = nil end - pExtSaveStateF = true -- set the ext state save flag - end -- result -end --- Reset sequencer legato slider -seqLegSldrText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("\nseqLegSldrText.onLClick()") end - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Legato Slider") - if result == 1 then - seqLegProbSldr.val1 = m.legatoProb - if pExtState.seqLegProb then pExtState.seqLegProb = nil end - pExtSaveStateF = true - end -- result -end --- Reset sequencer shift -seqShiftText.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("\nseqShiftText.onRClick") end - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Note Shift") - if result == 1 then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 - seqShiftVal.label = tostring(m.seqShift) - InsertNotes() - end -- result -end +-- euclidiser gui functions -------------------------------------------------- -------------------------------------------------------------------------------- --- Euclidiser --------------------------------------------------------------------------------- --- Euclidiser button -euclidBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end + +euclidBtn.onLClick = function() -- Euclidiser button + if m.activeTake and m.mItem then if m.eucF then - if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GetNotesFromTake() GenBjorklund(euclidPulsesSldr, euclidStepsSldr, euclidRotationSldr, m.accProbTable, seqAccRSldr) if m.eucRndNotesF then randomBtn.onLClick() -- call RandomiseNotes end + else -- not m.eucF - if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) GetNotesFromTake() GenNoteAttributes(m.eucAccentF, m.accProbTable, seqAccRSldr, false, m.legProbTable) + if m.eucRndNotesF then - if debug or m.debug then ConMsg("m.eucRndNotesF = " .. tostring(m.eucRndNotesF)) end randomBtn.onLClick() -- call RandomiseNotes end end -- m.eucF + -- set project ext state pExtState.eucSliders = {} for k, v in pairs(t_euclidSliders) do @@ -1797,30 +1938,27 @@ euclidBtn.onLClick = function() pExtSaveStateF = true end -- m.activeTake end --- Euclidiser options -eucOptionsCb.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\neucOptionsCb.onLClick()") end + +eucOptionsCb.onLClick = function() -- Euclidiser options + m.eucF = eucOptionsCb.val1[1] == 1 and true or false -- Generate m.eucAccentF = eucOptionsCb.val1[2] == 1 and true or false -- Accent m.eucRndNotesF = eucOptionsCb.val1[3] == 1 and true or false -- Randomise notes pExtState.eucOptionsCb = {m.eucF, m.eucAccentF, m.eucRndNotesF} pExtSaveStateF = true - if debug or m.debug then PrintTable(eucOptionsCb.val1) end + end --- Euclid pulses slider -euclidPulsesSldr.onMove = function() - local debug = false - if debug or m.debug then ConMsg("euclidPlusesSldr.onMove()") end + +euclidPulsesSldr.onMove = function() -- Euclid pulses slider + if euclidPulsesSldr.val1 > euclidStepsSldr.val1 then -- pulses > steps euclidStepsSldr.val1 = euclidPulsesSldr.val1 euclidRotationSldr.max = euclidStepsSldr.val1 end end --- Euclid steps slider -euclidStepsSldr.onMove = function() - local debug = false - if debug or m.debug then ConMsg("euclidStepsSldr.onMove()") end + +euclidStepsSldr.onMove = function() -- Euclid steps slider + if euclidStepsSldr.val1 < euclidPulsesSldr.val1 then -- steps < pulses euclidPulsesSldr.val1 = euclidStepsSldr.val1 end @@ -1832,10 +1970,9 @@ euclidStepsSldr.onMove = function() euclidRotationSldr.max = euclidStepsSldr.val1 end end --- Euclid rotation slider -euclidRotationSldr.onMove = function() - local debug = false - if debug or m.debug then ConMsg("euclidRotationSldr.onMove()") end + +euclidRotationSldr.onMove = function() -- Euclid rotation slider + euclidRotationSldr.max = euclidStepsSldr.val1 if euclidRotationSldr.val1 > euclidStepsSldr.val1 then euclidRotationSldr.val1 = euclidStepsSldr.val1 @@ -1843,10 +1980,22 @@ euclidRotationSldr.onMove = function() end end --- Set default euclid options -function SetDefaultEucOptions() - local debug = false - if debug or m.debug then ConMsg("SetDefaultEucOptions()") end +txtEuclidLabel.onRClick = function() -- Reset euclidean sliders + + gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y + local result = gfx.showmenu("Reset Euclid Sliders") + + if result == 1 then + euclidPulsesSldr.val1 = m.eucPulses + euclidStepsSldr.val1 = m.eucSteps + euclidRotationSldr.val1 = m.eucRot + pExtSaveStateF = true + pExtState.eucSliders = nil + end -- result +end + +function SetDefaultEucOptions() -- Set default euclid options + -- if euclidean options were saved to project state, load them if pExtState.eucOptionsCb then m.eucF = pExtState.eucOptionsCb[1] == true and true or false @@ -1858,10 +2007,9 @@ function SetDefaultEucOptions() eucOptionsCb.val1[2] = (true and m.eucAccentF) and 1 or 0 -- accents eucOptionsCb.val1[3] = (true and m.eucRndNotesF) and 1 or 0 -- randomise notes end --- Set default euclid sliders -function SetDefaultEucSliders() - local debug = false - if debug or m.debug then ConMsg("SetDefaultEucSliders()") end + +function SetDefaultEucSliders() -- Set default euclid sliders + -- if euclidean sliders were saved to project state, load them if pExtState.eucSliders then for k, v in pairs(t_euclidSliders) do @@ -1874,25 +2022,13 @@ function SetDefaultEucSliders() end -- load pExtState end --- Reset euclidean sliders -txtEuclidLabel.onRClick = function() - local debug = false - if debug or m.debug then ConMsg("\ntxtEuclidLabel.onLClick()") end - gfx.x = gfx.mouse_x; gfx.y = gfx.mouse_y - local result = gfx.showmenu("Reset Euclid Sliders") - if result == 1 then - euclidPulsesSldr.val1 = m.eucPulses - euclidStepsSldr.val1 = m.eucSteps - euclidRotationSldr.val1 = m.eucRot - pExtSaveStateF = true - pExtState.eucSliders = nil - end -- result -end + +-- draw GUI ------------------------------------------------------------------ -------------------------------------------------------------------------------- --- Draw GUI --------------------------------------------------------------------------------- + function DrawGUI() + for key, winElms in pairs(t_winElements) do winElms:draw() end --for key, frame in pairs(t_Frames) do frame:draw() end for key, check in pairs(t_Checkboxes) do check:draw() end @@ -1905,35 +2041,28 @@ function DrawGUI() for key, ssldrs in pairs(t_seqSliders) do ssldrs:draw() end for key, esldrs in pairs(t_euclidSliders) do esldrs:draw() end for key, textb in pairs(t_Textboxes) do textb:draw() end + end --------------------------------------------------------------------------------- --- GUI Functions END --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- GUI END --------------------------------------------------------------------------------- + + +-- init ---------------------------------------------------------------------- -------------------------------------------------------------------------------- --- INIT --------------------------------------------------------------------------------- --------------------------------------------------------------------------------- --- InitMidiExMachina --------------------------------------------------------------------------------- -function InitMidiExMachina() + +function Init() + math.randomseed(os.time()) for i = 1, 15 do math.random() end -- lua quirk, first random call always returns the same value... reaper.ClearConsole() - local debug = false - if debug or m.debug then ConMsg("InitMidiExMachina()") end -- grab the midi editor, and active take m.activeEditor = reaper.MIDIEditor_GetActive() if m.activeEditor then m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) __ = NewNoteBuf() - if not m.activeTake then ConMsg("InitMidiExMachina() - No Active Take") end + if not m.activeTake then ConMsg("Init() - No Active Take") end else - ConMsg("InitMidiMachina() - No Active MIDI Editor") + ConMsg("Init() - No Active MIDI Editor") end -- m.activeEditor -- Load ProjectExtState @@ -1952,33 +2081,34 @@ function InitMidiExMachina() SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() SetDefaultEucOptions(); SetDefaultEucSliders() m.mItem = reaper.GetSelectedMediaItem(0, 0) - --GetItemLength() + GetNotesFromTake() -- grab the original note data (if any...) - if debug or m.debug then ConMsg("End InitMidiExMachina()\n") end end --------------------------------------------------------------------------------- --- InitGFX --------------------------------------------------------------------------------- + function InitGFX() - local debug = false - if debug or m.debug then ConMsg("InitGFX()") end -- Init window ------ gfx.clear = RGB2Packed(table.unpack(m.win_bg)) gfx.init(m.win_title, m.win_w * e.gScale, m.win_h * e.gScale, m.win_dockstate, m.win_x, m.win_y) + -- Last mouse position and state gLastMouseCap, gLastMouseX, gLastMouseY = 0, 0, 0 gMouseOX, gMouseOY = -1, -1 end + + + +-- main ---------------------------------------------------------------------- -------------------------------------------------------------------------------- --- Mainloop --------------------------------------------------------------------------------- + function MainLoop() + -- Update mouse state and position if gfx.mouse_cap & 1 == 1 and gLastMouseCap & 1 == 0 or -- L mouse gfx.mouse_cap & 2 == 2 and gLastMouseCap & 2 == 0 or -- R mouse gfx.mouse_cap & 64 == 64 and gLastMouseCap & 64 == 0 then -- M mouse gMouseOX, gMouseOY = gfx.mouse_x, gfx.mouse_y end + -- Set modifier keys Ctrl = gfx.mouse_cap & 4 == 4 Shift = gfx.mouse_cap & 8 == 8 @@ -1991,6 +2121,7 @@ function MainLoop() m.win_y = pExtState.win_y pExtSaveStateF = true end + -- if resized, set scale flag and reset gfx if m.zoomF == true then e.gScaleState = true @@ -2027,7 +2158,9 @@ function MainLoop() m.lmItem = m.mItem m.lactiveTake = m.activeTake m.mItem = reaper.GetSelectedMediaItem(0, 0) + if m.mItem then + if m.mItem ~= m.lmItem then m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 seqShiftVal.label = tostring(m.seqShift) @@ -2037,25 +2170,16 @@ function MainLoop() end m.activeEditor = reaper.MIDIEditor_GetActive() + if m.activeEditor then + m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) if m.activeTake ~= m.lactiveTake then GetNotesFromTake() end if m.lmItem == nil and m.mItem then GetNotesFromTake() end + if m.activeTake then ShowMessage(msgText, 0) -- clear old messages - -- check for changes in the active take if the "Permute" scale is selected - if scaleDrop.val2[scaleDrop.val1] == "Permute" then - __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) - if m.pHash ~= pHash then - SetScale("Permute", m.scales, m.preNoteProbTable) - UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) - m.pHash = pHash - end -- m.pHash - -- don't allow any note options that might upset permute... - noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false - noteOptionsCb.val1[3] = 0; m.rndOctX2F = false - end -- scaleDrop -- check for grid changes local grid = m.reaGrid m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) @@ -2067,6 +2191,7 @@ function MainLoop() ShowMessage(msgText, 1) m.activeTake = nil end -- m.activeTake + else -- handle m.activeEditor error -- pop up error message - switch layer on textbox element ShowMessage(msgText, 1) @@ -2079,10 +2204,10 @@ function MainLoop() end end + +-- run ----------------------------------------------------------------------- -------------------------------------------------------------------------------- --- RUN --------------------------------------------------------------------------------- -InitMidiExMachina() + +Init() InitGFX() MainLoop() --------------------------------------------------------------------------------- \ No newline at end of file diff --git a/MIDI Editor/MIDI Ex Machina/persistence.lua b/MIDI Editor/MIDI Ex Machina/persistence.lua deleted file mode 100644 index 2625520..0000000 --- a/MIDI Editor/MIDI Ex Machina/persistence.lua +++ /dev/null @@ -1,228 +0,0 @@ ---[[ -@description Persistence Library -@about - #### Table Serialization Library by Gerhard Roethlin - Provides - - persistence.store(path, ...): store arbitrary items to the file - - persistence.load(path): load files that were previously stored - - Limitations - - Does not support userdata, threads, or most function values - - Function export is not portable -@noindex -@version 1.0 -@author Gerhard Roethlin - -MIT License (see bottom of file) ---]] - ---[[ Provides ]] --- persistence.store(path, ...): Stores arbitrary items to the file at the given path --- persistence.load(path): Loads files that were previously stored with store and returns them - ---[[ Limitations ]] --- Does not export userdata, threads or most function values --- Function export is not portable - ---[[ License: MIT (see bottom) ]] - --------------------------------------------------------------------------------- --- Private methods -local write, writeIndent, writers, refCount; --------------------------------------------------------------------------------- - -persistence = -{ - store = function (path, ...) - local file, e - if type(path) == "string" then - -- Path, open a file - file, e = io.open(path, "w") - if not file then - return error(e) - end - else - -- Just treat it as file - file = path - end - - local n = select("#", ...) - -- Count references - local objRefCount = {} -- Stores reference that will be exported - for i = 1, n do - refCount(objRefCount, (select(i,...))) - end - -- Export Objects with more than one ref and assign name - -- First, create empty tables for each - local objRefNames = {} - local objRefIdx = 0 - file:write("-- Persistent Data\n") - file:write("local multiRefObjects = {\n") - for obj, count in pairs(objRefCount) do - if count > 1 then - objRefIdx = objRefIdx + 1 - objRefNames[obj] = objRefIdx - file:write("{};") -- table objRefIdx - end - end - file:write("\n} -- multiRefObjects\n") - -- Then fill them (this requires all empty multiRefObjects to exist) - for obj, idx in pairs(objRefNames) do - for k, v in pairs(obj) do - file:write("multiRefObjects["..idx.."][") - write(file, k, 0, objRefNames) - file:write("] = ") - write(file, v, 0, objRefNames) - file:write(";\n") - end - end - -- Create the remaining objects - for i = 1, n do - file:write("local ".."obj"..i.." = ") - write(file, (select(i,...)), 0, objRefNames) - file:write("\n") - end - -- Return them - if n > 0 then - file:write("return obj1") - for i = 2, n do - file:write(" ,obj"..i) - end - file:write("\n") - else - file:write("return\n") - end - file:close() - end; - - load = function (path) - local f, e = loadfile(path); - if f then - return f() - else - return nil, e - end - end -} - --- Private methods --------------------------------------------------------------------------------- --- write thing (dispatcher) -write = function (file, item, level, objRefNames) - writers[type(item)](file, item, level, objRefNames) -end --------------------------------------------------------------------------------- --- write indent -writeIndent = function (file, level) - for i = 1, level do - file:write("\t") - end -end --------------------------------------------------------------------------------- --- recursively count references -refCount = function (objRefCount, item) - -- only count reference types (tables) - if type(item) == "table" then - -- Increase ref count - if objRefCount[item] then - objRefCount[item] = objRefCount[item] + 1 - else - objRefCount[item] = 1 - -- If first encounter, traverse - for k, v in pairs(item) do - refCount(objRefCount, k) - refCount(objRefCount, v) - end - end - end -end --------------------------------------------------------------------------------- --- Format items for the purpose of restoring -writers = { - ["nil"] = function (file, item) - file:write("nil") - end; - ["number"] = function (file, item) - file:write(tostring(item)) - end; - ["string"] = function (file, item) - file:write(string.format("%q", item)); - end; - ["boolean"] = function (file, item) - if item then - file:write("true") - else - file:write("false") - end - end; - ["table"] = function (file, item, level, objRefNames) - local refIdx = objRefNames[item] - if refIdx then - -- Table with multiple references - file:write("multiRefObjects["..refIdx.."]") - else - -- Single use table - file:write("{\n") - for k, v in pairs(item) do - writeIndent(file, level+1) - file:write("[") - write(file, k, level+1, objRefNames) - file:write("] = ") - write(file, v, level+1, objRefNames) - file:write(";\n") - end - writeIndent(file, level) - file:write("}") - end - end; - ["function"] = function (file, item) - -- Does only work for "normal" functions, not those - -- with upvalues or c functions - local dInfo = debug.getinfo(item, "uS") - if dInfo.nups > 0 then - file:write("nil --[[functions with upvalue not supported]]") - elseif dInfo.what ~= "Lua" then - file:write("nil --[[non-lua function not supported]]") - else - local r, s = pcall(string.dump,item) - if r then - file:write(string.format("loadstring(%q)", s)) - else - file:write("nil --[[function could not be dumped]]") - end - end - end; - ["thread"] = function (file, item) - file:write("nil --[[thread]]\n") - end; - ["userdata"] = function (file, item) - file:write("nil --[[userdata]]\n") - end; -} --------------------------------------------------------------------------------- -return persistence --------------------------------------------------------------------------------- ---[[ - Copyright (c) 2010 Gerhard Roethlin - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. -]] \ No newline at end of file diff --git a/Stop_no_item_error_patch.diff b/Stop_no_item_error_patch.diff deleted file mode 100644 index b89299c..0000000 --- a/Stop_no_item_error_patch.diff +++ /dev/null @@ -1,317 +0,0 @@ -diff --git a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua -index 1e38c54..da244f3 100644 ---- a/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua -+++ b/MIDI Editor/MIDI Ex Machina/RobU - MIDI Ex Machina.lua -@@ -57,7 +57,7 @@ local p = require 'persistence' -- currently unused, i.e. no preset save, load, - -------------------------------------------------------------------------------- - m = {} -- all ex machina data - -- user changeable defaults are marked with "(option)" --m.debug = false -+m.debug = true - m.OS = reaper.GetOS() - -- window - m.win_title = "RobU : MIDI Ex Machina - v1.3.4"; m.win_dockstate = 0 -@@ -359,7 +359,7 @@ local function UndoNoteBuf() - end - end - --local function PurgeNoteBuf() -+local function PurgeNoteBuf(idx) - -- PurgeNoteBuf() - purge all note buffers from current+1 to end - local debug = false - if debug or m.debug then -@@ -383,25 +383,26 @@ function GetItemLength() - local debug = false - if debug or m.debug then ConMsg("GetItemLength()") end - -- mItem = reaper.GetSelectedMediaItem(0, 0) -- mItemLen = reaper.GetMediaItemInfo_Value(mItem, "D_LENGTH") -- mBPM, mBPI = reaper.GetProjectTimeSignature2(0) -- msPerMin = 60000 -- msPerQN = msPerMin / mBPM -- numQNPerItem = (mItemLen * 1000) / msPerQN -- numBarsPerItem = numQNPerItem / 4 -- ItemPPQN = numQNPerItem * m.ppqn -- if debug or m.debug then -- ConMsg("ItemLen (ms) = " .. mItemLen) -- ConMsg("mBPM = " .. mBPM) -- ConMsg("MS Per QN = " .. msPerQN) -- ConMsg("Num of QN = " .. numQNPerItem) -- ConMsg("Num of Bar = " .. numBarsPerItem) -- ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") -- end -- mItemTake = reaper.GetTake(mItem, 0) -- should fix looped items -- ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! -- return ItemPPQN -+ --mItem = reaper.GetSelectedMediaItem(0, 0) -+ mItemLen = reaper.GetMediaItemInfo_Value(m.mItem, "D_LENGTH") -+ mBPM, mBPI = reaper.GetProjectTimeSignature2(0) -+ msPerMin = 60000 -+ msPerQN = msPerMin / mBPM -+ numQNPerItem = (mItemLen * 1000) / msPerQN -+ numBarsPerItem = numQNPerItem / 4 -+ ItemPPQN = numQNPerItem * m.ppqn -+ if debug or m.debug then -+ ConMsg("ItemLen (ms) = " .. mItemLen) -+ ConMsg("mBPM = " .. mBPM) -+ ConMsg("MS Per QN = " .. msPerQN) -+ ConMsg("Num of QN = " .. numQNPerItem) -+ ConMsg("Num of Bar = " .. numBarsPerItem) -+ ConMsg("Item size ppqn = " .. ItemPPQN .. "\n") -+ end -+ mItemTake = reaper.GetTake(m.mItem, 0) -- should fix looped items -+ ItemPPQN = reaper.BR_GetMidiSourceLenPPQ(mItemTake) -- thanks Thrash! -+ return ItemPPQN -+ - end - - function GetReaperGrid(gridRad) -@@ -447,7 +448,7 @@ end - -- GetNotesFromTake() - fill a note buffer from the active take - -------------------------------------------------------------------------------- - function GetNotesFromTake() -- local debug = false -+ local debug = true - if debug or m.debug then ConMsg("GetNotesFromTake()") end - local i, t - if m.activeTake then -@@ -468,6 +469,7 @@ function GetNotesFromTake() - t[i][8] = velocity - end -- for i - end -- num_notes -+ PrintNotes(GetNoteBuf()) - else -- no active take - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake -@@ -855,26 +857,7 @@ function GenNoteAttributes(accF, accProbTable, accSlider, legF, legProbTable) - PurgeNoteBuf() - InsertNotes() - end ---------------------------------------------------------------------------------- ---- SetNotes - arg notebuf t1; set notes in the active take ---------------------------------------------------------------------------------- --function SetNotes() -- local debug = false -- if debug or m.debug then ConMsg("SetNotes()") end -- local i = 1 -- if m.activeTake then -- local t1 = GetNoteBuf() -- while t1[i] do -- reaper.MIDI_SetNote(m.activeTake, i-1, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], __) -- --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) -- i = i + 1 -- end -- while t1[i] -- reaper.MIDI_Sort(m.activeTake) -- reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off -- else -- if debug or m.debug then ConMsg("No Active Take") end -- end -- m.activeTake --end -+ - -------------------------------------------------------------------------------- - -- InsertNotes(note_buffer) - insert notes in the active take - -------------------------------------------------------------------------------- -@@ -883,7 +866,7 @@ function InsertNotes() - if debug or m.debug then ConMsg("\nInsertNotes()") end - DeleteNotes() - local i = 1 -- if m.activeTake then -+ if m.activeTake and m.mItem then - local noteLength = 0 - local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() -@@ -926,33 +909,14 @@ function InsertNotes() - if debug or m.debug then ConMsg("No Active Take") end - end -- m.activeTake - end ---------------------------------------------------------------------------------- ---- InsertNotes(note_buffer) - insert notes in the active take ---------------------------------------------------------------------------------- --function InsertNotesOld() -- local debug = false -- if debug or m.debug then ConMsg("InsertNotes()") end -- DeleteNotes() -- local i = 1 -- if m.activeTake then -- local t1 = GetNoteBuf() -- while t1[i] do -- reaper.MIDI_InsertNote(m.activeTake, t1[i][1], t1[i][2], t1[i][3], t1[i][4], t1[i][6], t1[i][7], t1[i][8], false) -- --1=selected, 2=muted, 3=startppq, 4=endppq, 5=len, 6=chan, 7=pitch, 8=vel, noSort) -- i = i + 1 -- end -- while t1[i] -- reaper.MIDI_Sort(m.activeTake) -- reaper.MIDIEditor_OnCommand(m.activeEditor, 40435) -- all notes off -- else -- if debug or m.debug then ConMsg("No Active Take") end -- end -- m.activeTake --end -+ - -------------------------------------------------------------------------------- - -- PrintNotes - arg note_buffer t; print note_buffer to reaper console - -------------------------------------------------------------------------------- - function PrintNotes(t) -- debug code - local debug = false - if debug or m.debug then ConMsg("PrintNotes()") end -+ if not t then return end - local i = 1 - local str = "sel \t mut \t s_ppq \t e_ppq \t leng \t chan \t pitch \t vel \n" - while t[i] do -@@ -991,7 +955,10 @@ function ShowMessage(tb, msgNum) - tb.label = "" - elseif msgNum == 1 then - tb.tab = 0 -- tb.label = "No Active Take" -+ tb.label = "MIDI Editor Closed" -+ elseif msgNum == 2 then -+ tb.tab = 0 -+ tb.label = "Please select a MIDI Item in the Arrange Window" - end - e.gScaleState = true - end -@@ -1300,7 +1267,7 @@ end - randomBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nrandomBtn.onLClick()") end -- if m.activeTake then -+ if m.activeTake and m.mItem then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift - seqShiftVal.label = tostring(m.seqShift) - GenProbTable(m.preNoteProbTable, t_noteSliders, m.noteProbTable) -@@ -1470,7 +1437,7 @@ end - sequenceBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\nsequenceBtn.onLClick()") end -- if m.activeTake then -+ if m.activeTake and m.mItem then - m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -- reset shift on new sequence - seqShiftVal.label = tostring(m.seqShift) - if m.seqF then -@@ -1589,6 +1556,7 @@ seqGridRad.onLClick = function() -- change grid size - end - -- Sequencer shift left - seqShiftLBtn.onLClick = function() -+ if not m.mItem then return end - local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() - m.seqShiftMin = -(math.floor(itemLength / gridSize)-1) -@@ -1602,6 +1570,7 @@ seqShiftLBtn.onLClick = function() - end - -- Sequencer shift right - seqShiftRBtn.onLClick = function() -+ if not m.mItem then return end - local gridSize = m.reaGrid * m.ppqn - local itemLength = GetItemLength() - m.seqShiftMax = math.floor(itemLength / gridSize) - 1 -@@ -1800,7 +1769,7 @@ end - euclidBtn.onLClick = function() - local debug = false - if debug or m.debug then ConMsg("\neuclidBtn.onLClick()") end -- if m.activeTake then -+ if m.activeTake and m.mItem then - if m.eucF then - if debug or m.debug then ConMsg("m.eucF = " .. tostring(m.eucF)) end - GenAccentTable(m.accProbTable, seqAccRSldr, seqAccProbSldr) -@@ -1981,8 +1950,8 @@ function InitMidiExMachina() - SetDefaultSeqOptions(); SetDefaultSeqShift() - SetDefaultSeqGridSliders(); SetDefaultAccLegSliders() - SetDefaultEucOptions(); SetDefaultEucSliders() -- -- GetItemLength() -+ m.mItem = reaper.GetSelectedMediaItem(0, 0) -+ --GetItemLength() - GetNotesFromTake() -- grab the original note data (if any...) - if debug or m.debug then ConMsg("End InitMidiExMachina()\n") end - end -@@ -2053,41 +2022,58 @@ function MainLoop() - -- Update Reaper GFX - gfx.update() - -- -- check for midi editor and take -- m.activeEditor = reaper.MIDIEditor_GetActive() -- if m.activeEditor then -- m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) -- if m.activeTake then -- ShowMessage(msgText, 0) -- clear old messages -- -- check for changes in the active take if the "Permute" scale is selected -- if scaleDrop.val2[scaleDrop.val1] == "Permute" then -- __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) -- if m.pHash ~= pHash then -- SetScale("Permute", m.scales, m.preNoteProbTable) -- UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) -- m.pHash = pHash -- end -- m.pHash -- -- don't allow any note options that might upset permute... -- noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false -- noteOptionsCb.val1[3] = 0; m.rndOctX2F = false -- end -- scaleDrop -- -- check for grid changes -- local grid = m.reaGrid -- m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) -- if grid ~= m.reaGrid then -- GetReaperGrid(seqGridRad) -- seqGridRad.onLClick() -- update the sequence grid sizes -- end -- grid -- else -- handle m.activeTake error -- ShowMessage(msgText, 1) -+ -- check for selected item, midi editor and take -+ m.lmItem = m.mItem -+ m.mItem = reaper.GetSelectedMediaItem(0, 0) -+ if m.mItem then -+ if m.mItem ~= m.lmItem then -+ m.mItemNew = true -+ m.seqShift = 0; m.seqShiftMin = 0; m.seqShiftMax = 0 -+ seqShiftVal.label = tostring(m.seqShift) -+ m.notebuf.i = 0 -- brutal hack -+ PurgeNoteBuf(); NewNoteBuf() -+ else -+ m.mItemNew = false -+ end -+ -+ m.activeEditor = reaper.MIDIEditor_GetActive() -+ if m.activeEditor then -+ m.activeTake = reaper.MIDIEditor_GetTake(m.activeEditor) -+ if m.activeTake then -+ ShowMessage(msgText, 0) -- clear old messages -+ -- check for changes in the active take if the "Permute" scale is selected -+ if scaleDrop.val2[scaleDrop.val1] == "Permute" then -+ __, pHash = reaper.MIDI_GetHash(m.activeTake, false, 0) -+ if m.pHash ~= pHash then -+ SetScale("Permute", m.scales, m.preNoteProbTable) -+ UpdateSliderLabels(t_noteSliders, m.preNoteProbTable) -+ m.pHash = pHash -+ end -- m.pHash -+ -- don't allow any note options that might upset permute... -+ noteOptionsCb.val1[2] = 0; m.rndFirstNoteF = false -+ noteOptionsCb.val1[3] = 0; m.rndOctX2F = false -+ end -- scaleDrop -+ -- check for grid changes -+ local grid = m.reaGrid -+ m.reaGrid, __, __ = reaper.MIDI_GetGrid(m.activeTake) -+ if grid ~= m.reaGrid then -+ GetReaperGrid(seqGridRad) -+ seqGridRad.onLClick() -- update the sequence grid sizes -+ end -- grid -+ else -- handle m.activeTake error -+ ShowMessage(msgText, 1) -+ m.activeTake = nil -+ end -- m.activeTake -+ else -- handle m.activeEditor error -+ -- pop up error message - switch layer on textbox element -+ ShowMessage(msgText, 1) -+ m.activeEditor = nil - m.activeTake = nil -- end -- m.activeTake -- else -- handle m.activeEditor error -- -- pop up error message - switch layer on textbox element -- ShowMessage(msgText, 1) -- m.activeEditor = nil -- m.activeTake = nil -- end -- m.activeEditor -+ end -- m.activeEditor -+ else -+ ShowMessage(msgText, 2) -+ m.mItem = nil -+ end - end - - -------------------------------------------------------------------------------- From dbc9ecd13022be4ddf6caa62de8c5ca849303b12 Mon Sep 17 00:00:00 2001 From: RobU23 <24913764+RobU23@users.noreply.github.com> Date: Thu, 3 Mar 2022 19:36:11 +0000 Subject: [PATCH 25/27] index: 1 modified package, 2 new versions --- index.xml | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/index.xml b/index.xml index f4f3840..a68035d 100644 --- a/index.xml +++ b/index.xml @@ -1,27 +1,27 @@ - + - https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua https://github.com/RobU23/ReaScripts/raw/6fc14048fee05b74b2888e5a5a69061eabe3630f/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + https://github.com/RobU23/ReaScripts/raw/e697cda55c3306c429bcc1c40d89736ab537f20d/MIDI%20Editor/MIDI%20Ex%20Machina/persistence.lua + + + + https://github.com/RobU23/ReaScripts/raw/0692c3bb7ceaa9490f27172749f0a5af51c992bc/MIDI%20Editor/MIDI%20Ex%20Machina/RobU%20-%20MIDI%20Ex%20Machina.lua + https://github.com/RobU23/ReaScripts/raw/0692c3bb7ceaa9490f27172749f0a5af51c992bc/MIDI%20Editor/MIDI%20Ex%20Machina/eGUI.lua + https://github.com/RobU23/ReaScripts/raw/0692c3bb7ceaa9490f27172749f0a5af51c992bc/MIDI%20Editor/MIDI%20Ex%20Machina/euclid.lua + From 68417b3af68046bb823906bdf72b96341b5c89df Mon Sep 17 00:00:00 2001 From: RobU <24913764+RobU23@users.noreply.github.com> Date: Sun, 13 Jul 2025 06:46:10 +0100 Subject: [PATCH 26/27] Update README.md script status/future note added --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 11a41fa..d9be562 100644 --- a/README.md +++ b/README.md @@ -7,5 +7,5 @@ See the [Wiki](https://github.com/RobU23/ReaScripts/wiki) for details This repository is [ReaPack](https://reapack.com/) compatible - The import URL is `https://github.com/RobU23/ReaScripts/raw/master/index.xml` --- -*If you find any of this stuff useful, and would like to buy me a beer, the internets has the answer...* -[Beer Donation](https://www.paypal.me/RobUrquhart) +*Please not that this script is not actively maintained. Bad bugs may get fixed from time to time, but there will be no further development of this version* +*A more modular, more maintainable rewrite is in progress, but... don't hold your breath :)* From e392816da519bc1f9b0e8909704a74ce05b1688a Mon Sep 17 00:00:00 2001 From: RobU <24913764+RobU23@users.noreply.github.com> Date: Sun, 13 Jul 2025 06:46:32 +0100 Subject: [PATCH 27/27] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d9be562..864525c 100644 --- a/README.md +++ b/README.md @@ -7,5 +7,6 @@ See the [Wiki](https://github.com/RobU23/ReaScripts/wiki) for details This repository is [ReaPack](https://reapack.com/) compatible - The import URL is `https://github.com/RobU23/ReaScripts/raw/master/index.xml` --- -*Please not that this script is not actively maintained. Bad bugs may get fixed from time to time, but there will be no further development of this version* +*Please not that this script is not actively maintained. Bad bugs may get fixed from time to time, but there will be no further development of this version.* + *A more modular, more maintainable rewrite is in progress, but... don't hold your breath :)*