├── .gitignore ├── LICENSE ├── README.md ├── build └── create_package.sh ├── changelog ├── linreaper.glade ├── main.py └── scripts ├── .conf.glade ├── .conftool.sh ├── .js.svg ├── .vst.svg ├── .vst_installer.sh ├── REAPER.ini.sh ├── _functions.sh ├── conf.glade ├── conftool.sh ├── export_wine_environment.sh ├── get_reaper.sh ├── gnome ├── 128x128 │ └── apps │ │ └── reaper.png ├── 16x16 │ ├── apps │ │ └── reaper.png │ └── reaper.svg ├── 24x24 │ ├── apps │ │ └── linreapervsttool.png │ └── linreapervsttool.svg ├── 256x256 │ └── apps │ │ └── reaper.png ├── 32x32 │ └── apps │ │ └── reaper.png ├── 48x48 │ └── apps │ │ ├── linreapervsttool.png │ │ └── reaper.png ├── 96x96 │ └── apps │ │ └── reaper.png └── scalable │ ├── apps │ └── linreapervsttool.svg │ └── mimetypes │ ├── application-x-reaper-peakfile.svg │ ├── application-x-reaper-project-backup.svg │ └── application-x-reaper-project.svg ├── js.svg ├── linreapercfg.py ├── mimetype.xml ├── reaper_updater.py ├── run_install.sh ├── run_notepad.sh ├── run_reaper.sh ├── setup_config.sh ├── setup_shortcuts.sh ├── setup_wineasio.sh ├── update_checker.py ├── update_config.sh ├── vst.svg ├── vst_installer.sh ├── wineasio-0.7.4.dll.so ├── wineasio-0.8.0.dll.so └── winepath.sh /.gitignore: -------------------------------------------------------------------------------- 1 | build/LinReaper* 2 | build/distrib 3 | build/makeself* 4 | *.sublime* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LinReaper 2 | ========= 3 | 4 | Reaper installer for Linux 5 | 6 | LinReaper will do the following for you: 7 | 8 | * Automatically downloads and installs the newest Reaper version available from the website, or installs from a previously downloaded Reaper installation exe. 9 | * Installs Reaper in a bottled Wine directory (does not mess with the rest of your system) 10 | * Sets up a local installation of WineAsio (again does not mess with the rest of your system) 11 | * Registers file types of .rpp, rpp.bak and .reapeak files (with custom icons), so you can simply double click Reaper files 12 | * Sets up a wrapper script around Reaper enabling it to accept normal UNIX command-line options and paths 13 | * Sets up a wrapper script around Reaper to transform Reaper's configuration files to follow Unix/Freedesktop guidelines and allow automatic multi-user configurations 14 | * Minimally configures the Reaper preferences for better Linux operation 15 | * Optionally creates menu shortcuts 16 | * Includes a tool (LinReaper Options) for installing and managing your Windows VSTs, JS effects, using Reapers more esoteric options and for advanced configuration of Wine 17 | * Intelligently links the Wine folders "Desktop", "My Documents", "My Music", "My Pictures" and "My Videos" to their Linux counterparts 18 | 19 | In many regards, LinReaper is similar to Google's Picassa Linux port. 20 | 21 | Requirements 22 | ============ 23 | 24 | LinReaper requires Wine, Python, PyGTK (most distributions have these) and likes to also have the full 7Zip (p7zip-full in Ubuntu/Kubuntu/Xubuntu/Mint) 25 | 26 | Use 27 | === 28 | 29 | To use, double click the downloaded file and select "Run" if asked - you might also need to make the file executable by right clicking it and selecting Properties then the Permissions tab and checking "Allow executing file as a program". 30 | 31 | Installation Overview 32 | ===================== 33 | 34 | LinReaper installs the following in the selected install directory: 35 | 36 | Custom files and folders: 37 | 38 | Path | Description 39 | ----------------------|------------ 40 | .wine/ | standard wine configuration folder, same as would normally appear in $HOME/.wine 41 | .winelib/ | added wine dlls, currently only wineasio.dll.so lives here 42 | $HOME/.config/reaper | a symbolic link to C:\Windows\Profiles\$USER\Application Data\REAPER (or C:\Users\$USER\Application Data\REAPER depending on the version of Wine) 43 | icon.png | the Reaper icon 44 | reaper.sh | the Reaper launch script 45 | 46 | Files and folders added by Wine on install 47 | 48 | Path | Description 49 | ---------------|------------ 50 | .config | directory added by Wine on initial install to sandbox it from $HOME 51 | .local | directory added by Wine on initial install to sandbox it from $HOME 52 | REAPER.desktop | added by Wine on initial install to sandbox it from $HOME -------------------------------------------------------------------------------- /build/create_package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" 3 | PROJECT_DIRNAME="$(basename "$(dirname "$(dirname "$(readlink -f "$0")")")")" 4 | 5 | cd "$SCRIPT_DIR/../../" 6 | 7 | test -x "$(which makeself)" && MAKESELF="$(which makeself)" 8 | test -x "$(which makeself.sh)" && MAKESELF="$(which makeself.sh)" 9 | test -x "makeself-2"*"/makeself.sh" && MAKESELF="makeself-2"*"/makeself.sh" 10 | test -x "makeself.sh" && MAKESELF="./makeself.sh" 11 | test -x "$SCRIPT_DIR/makeself-2"*"/makeself.sh" && MAKESELF="$SCRIPT_DIR/makeself-2"*"/makeself.sh" 12 | 13 | if [ -z "$MAKESELF" ]; then 14 | echo "Makeself not found; downloading new copy..." 15 | cd "$SCRIPT_DIR" 16 | wget -c "http://megastep.org/makeself/makeself.run" 17 | chmod +x ./makeself.run 18 | ./makeself.run 19 | MAKESELF="$SCRIPT_DIR/makeself-2*/makeself.sh" 20 | cd ../.. 21 | fi 22 | 23 | if [ -z "$1" ]; then 24 | echo "No version given." 25 | echo "USAGE: $0 VERSION" 26 | exit 1 27 | fi 28 | 29 | shopt -s extglob 30 | if [ -d "./$PROJECT_DIRNAME/build/distrib" ]; then 31 | rm -Rf "./$PROJECT_DIRNAME/build/distrib" 32 | fi 33 | mkdir -p "./$PROJECT_DIRNAME/build/distrib" 34 | echo "Copying distribution files to build/distrib..." 35 | cp -a "./$PROJECT_DIRNAME/"!(build) "./$PROJECT_DIRNAME/build/distrib/" 36 | $MAKESELF "./$PROJECT_DIRNAME/build/distrib" "$SCRIPT_DIR/LinReaper$1.run" "LinReaper Reaper Installer For Linux" ./main.py 37 | -------------------------------------------------------------------------------- /changelog: -------------------------------------------------------------------------------- 1 | 0.84 2 | ---- 3 | * Fixed: LinReaper can once again download the latest version of Reaper 4 | and works with the newer versions of Wine lacking wineprefixcreate. 5 | * Updated: wineasio updated to version 0.8.0. 6 | 7 | 0.83 8 | ---- 9 | * Fixed: LinReaper now works even if there are no versions of Reaper 10 | available for download. 11 | 12 | 0.82 13 | ---- 14 | * New: The LinReaper VSTTool has been replaced by a new multi-tool. 15 | The new tool is available from the menu as 16 | "LinReaper Options". 17 | From there you can manage both your VST and JS effects, 18 | run Reaper with the options normally installed as extra 19 | menu shortcuts on Windows and configure and manage LinReapers 20 | Wine installation. 21 | * Fixed: Running Reaper from commandline with filenames containing 22 | spaces now works. 23 | 24 | 0.81 25 | ---- 26 | * New: If DLL registration of WineAsio fails locally, LinReaper will 27 | give the option to install WineAsio to /usr/lib/wine instead. 28 | 29 | 0.80 30 | ---- 31 | * Changed: Cleaned up the config dir and Wine setup handling a lot. 32 | * New: LinReaper will now link the Wine dirs Desktop, My Documents 33 | My Pictures and My Videos to either similar named dirs in 34 | the users home dir, the XDG USER DIR settings or simply 35 | to the users home dir if none of the above exists. 36 | * New: The config dir is now named the same as the installation 37 | directory. This means that you can install several versions 38 | of Reaper, each with their own config, as long as you name 39 | the install dirs differently. 40 | * New: You can now give a reaper install exe as an argument to 41 | LinReaper. 42 | 43 | 0.72 44 | ---- 45 | * New: A new tool called LinReaper VST Tool is now included! 46 | Its function is to aid in installing and maintaining Windows 47 | VSTs in your Reaper installation. 48 | * Changed: Reaper is now configured to use $HOME/.config/reaper/vst and 49 | /usr/lib/vstwin32 as the default paths for Windows VSTs. 50 | $HOME/.vst still works, but really should be used for native 51 | Linux VSTs. 52 | 53 | 0.70 54 | ---- 55 | * New: LinReaper now has much better error handling. 56 | * Fixed: If extraction from exe fails, LinReaper now runs the installer. 57 | 58 | 0.69 59 | ---- 60 | * Fixed: The launcher scripts now actually launches Reaper. My terrible 61 | blunder was once again caught by Rick Stone. 62 | 63 | 0.68 64 | ---- 65 | * Fixed: Not all installations have a $HOME/.local/share - LinReaper will 66 | now create it if missing. Once again, thanks to Rick Stone. 67 | 68 | 0.67 69 | ---- 70 | * Fixed: The installer now again actually works on other systems than 71 | my own, thanks to Rick Stone on the Reaper forum. 72 | 73 | 0.66 74 | ---- 75 | * New: LinReaper now uses the Wine registry to locate Windows paths. 76 | This ensures that LinReaper will work on different locales. 77 | * Fixed: The latest version of Reaper was no longer selected in the list. 78 | 79 | 0.652 80 | ----- 81 | * Fixed: LinReaper now correcly lets one install from local install when no 82 | internet connection is found 83 | 84 | 0.65 85 | ---- 86 | * New: Unbuffered display update is now in the default REAPER.ini 87 | configuration (meaning faster graphics) 88 | * New: Link Windows Desktop in Reaper to Linux Desktop 89 | * New: Added option to install from a local Reaper install exe, instead of 90 | download 91 | 92 | 0,64 93 | ---- 94 | * Fixed: 7Zip detection no longer fails 95 | -------------------------------------------------------------------------------- /linreaper.glade: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | True 8 | 6 9 | LinReaper: Reaper installation for Linux 10 | center 11 | 12 | 13 | 14 | 15 | True 16 | 6 17 | 18 | 19 | True 20 | False 21 | False 22 | 23 | 24 | True 25 | 6 26 | 27 | 28 | True 29 | 0 30 | 6 31 | gtk-info 32 | 6 33 | 34 | 35 | False 36 | False 37 | 0 38 | 39 | 40 | 41 | 42 | True 43 | 44 | 45 | True 46 | 0 47 | 6 48 | 6 49 | <big><big>Welcome to the Reaper installation program for Linux.</big></big> 50 | True 51 | 52 | 53 | False 54 | 0 55 | 56 | 57 | 58 | 59 | True 60 | 0 61 | 6 62 | 6 63 | Please remember that this is an unofficial product, and Cockos 64 | should not be bothered with issues regarding this use of this program. 65 | 66 | Cheers, 67 | <i>Christian Dannie Storgaard (Cybolic)</i> 68 | True 69 | 70 | 71 | False 72 | 1 73 | 74 | 75 | 76 | 77 | 1 78 | 79 | 80 | 81 | 82 | 83 | 84 | True 85 | Intro 86 | 87 | 88 | False 89 | tab 90 | 91 | 92 | 93 | 94 | True 95 | 6 96 | 12 97 | 98 | 99 | True 100 | 0 101 | none 102 | 103 | 104 | True 105 | 3 106 | 18 107 | 108 | 109 | True 110 | 2 111 | 2 112 | 113 | 114 | The latest from Reaper's website (requires an internet connection) 115 | True 116 | True 117 | False 118 | True 119 | True 120 | 121 | 122 | 2 123 | GTK_FILL 124 | 125 | 126 | 127 | 128 | True 129 | False 130 | Select A Reaper Install Exe 131 | 132 | 133 | 134 | 1 135 | 2 136 | 1 137 | 2 138 | 139 | 140 | 141 | 142 | The one contained in this installer: 143 | True 144 | True 145 | False 146 | True 147 | True 148 | radiobutton-installer-website 149 | 150 | 151 | 152 | 1 153 | 2 154 | GTK_FILL 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | True 164 | <b>Which version would you like to install?</b> 165 | True 166 | 167 | 168 | label_item 169 | 170 | 171 | 172 | 173 | False 174 | 0 175 | 176 | 177 | 178 | 179 | True 180 | 0 181 | none 182 | 183 | 184 | True 185 | 3 186 | 18 187 | 188 | 189 | True 190 | 191 | 192 | True 193 | 194 | 195 | True 196 | select-folder 197 | Select where the "reaper" directory should be created 198 | 199 | 200 | 201 | 202 | False 203 | 0 204 | 205 | 206 | 207 | 208 | 0 209 | 210 | 211 | 212 | 213 | True 214 | <span size="large">/</span> 215 | True 216 | 217 | 218 | False 219 | 1 220 | 221 | 222 | 223 | 224 | True 225 | True 226 | 227 | reaper 228 | 229 | 230 | 231 | 2 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | True 241 | <b>Where would you like it installed?</b> 242 | True 243 | 244 | 245 | label_item 246 | 247 | 248 | 249 | 250 | False 251 | 1 252 | 253 | 254 | 255 | 256 | True 257 | 0 258 | none 259 | 260 | 261 | True 262 | 3 263 | 18 264 | 265 | 266 | True 267 | 268 | 269 | Create menu shortcuts 270 | True 271 | True 272 | False 273 | True 274 | True 275 | True 276 | 277 | 278 | 279 | False 280 | False 281 | 0 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | True 291 | <b>Install options</b> 292 | True 293 | 294 | 295 | label_item 296 | 297 | 298 | 299 | 300 | False 301 | 2 302 | 303 | 304 | 305 | 306 | 1 307 | 308 | 309 | 310 | 311 | True 312 | Options 313 | 314 | 315 | 1 316 | False 317 | tab 318 | 319 | 320 | 321 | 322 | True 323 | 6 324 | 325 | 326 | True 327 | 328 | 329 | True 330 | 0.10000000149 331 | 332 | 333 | False 334 | False 335 | 0 336 | 337 | 338 | 339 | 340 | True 341 | Working... 342 | 343 | 344 | False 345 | False 346 | 1 347 | 348 | 349 | 350 | 351 | False 352 | 0 353 | 354 | 355 | 356 | 357 | 2 358 | 359 | 360 | 361 | 362 | True 363 | Install 364 | 365 | 366 | 2 367 | False 368 | tab 369 | 370 | 371 | 372 | 373 | True 374 | 375 | 376 | True 377 | 0 378 | 12 379 | 6 380 | <big><big>Congratulations, you have now installed Reaper on Linux!</big></big> 381 | True 382 | 383 | 384 | False 385 | 0 386 | 387 | 388 | 389 | 390 | True 391 | 0 392 | 12 393 | 6 394 | If you selected to install menu shortcuts, you will find Reaper in the Sound and Video category. 395 | 396 | If you selected not to install menu shortcuts, you can launch Reaper from the installation directory using "reaper.sh". 397 | True 398 | True 399 | 60 400 | 401 | 402 | False 403 | 1 404 | 405 | 406 | 407 | 408 | True 409 | 0 410 | 12 411 | 6 412 | <i>Thank you for using this installer, please report any issues you might have encountered either on the Reaper forums or directly to &lt;cybolic@gmail.com&gt;.</i> 413 | 414 | Also, if you haven't already, please review Reaper's license located in it's installation folder. 415 | True 416 | True 417 | True 418 | 60 419 | 420 | 421 | False 422 | 2 423 | 424 | 425 | 426 | 427 | 3 428 | 429 | 430 | 431 | 432 | True 433 | Done 434 | 435 | 436 | 3 437 | False 438 | tab 439 | 440 | 441 | 442 | 443 | False 444 | False 445 | 0 446 | 447 | 448 | 449 | 450 | True 451 | 452 | 453 | False 454 | end 455 | 2 456 | 457 | 458 | 459 | 460 | True 461 | 462 | 463 | gtk-cancel 464 | True 465 | True 466 | True 467 | False 468 | True 469 | 470 | 471 | 472 | False 473 | False 474 | 0 475 | 476 | 477 | 478 | 479 | gtk-go-forward 480 | True 481 | True 482 | True 483 | True 484 | True 485 | False 486 | True 487 | 488 | 489 | 490 | False 491 | False 492 | 1 493 | 494 | 495 | 496 | 497 | False 498 | False 499 | end 500 | 1 501 | 502 | 503 | 504 | 505 | 506 | 507 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | # -*- coding: utf-8 -*- 3 | 4 | import os, gtk, gobject, gtk.glade, subprocess, sys, threading, urllib, time, locale, re 5 | 6 | class Main: 7 | def _exit(self, *args): 8 | gtk.main_quit() 9 | exit() 10 | 11 | def __init__(self): 12 | self.default_installpath_global = "/usr/local/reaper" 13 | self.default_installpath_local = os.environ['HOME'] + "/.local" 14 | self.installpath_dir = self.default_installpath_local 15 | 16 | self.reaperfilelocal = None 17 | self.option_install_local = True 18 | 19 | self.option_shortcuts = True 20 | self.option_wineasio = True 21 | 22 | self.errorlog = "" 23 | 24 | self.widgets = CreateWidgets(self) 25 | icons = map(lambda i: gtk.gdk.pixbuf_new_from_file("./scripts/gnome/"+str(i)+"x"+str(i)+"/apps/reaper.png"), [16,32,48,96,128,256]) 26 | self.widgets['window'].set_icon_list(*icons) 27 | self.widgets['image-icon'].set_from_pixbuf(icons[1]) 28 | 29 | # Select the home folder as the base for choosing the Reaper installer 30 | self.widgets['filechooserbutton-installer'].set_current_folder(os.environ['HOME']) 31 | # Select the option to install locally 32 | self.widgets['filechooserbutton-path'].set_current_folder(self.default_installpath_local) 33 | 34 | if len(sys.argv) > 1: 35 | self.reaperfilelocal = os.path.abspath(sys.argv[1]) 36 | self.widgets['filechooserbutton-installer'].set_filename(self.reaperfilelocal) 37 | self.widgets['radiobutton-installer-file'].set_active(True) 38 | self.select_local_installer(True) 39 | 40 | # Set the default install options 41 | self.widgets['checkbutton_shortcuts'].set_active(self.option_shortcuts) 42 | ### Deprecated ### 43 | #self.widgets['checkbutton_wineasio'].set_active(self.option_wineasio) 44 | 45 | self.widgets['progressbar_install'].set_pulse_step(0.01) 46 | 47 | def select_version(self, treeview): 48 | # If we were called from inside the program, assume that the first row was selected 49 | if treeview.get_selection().get_selected()[1] == None: 50 | self.selected_version = self.versions[0] 51 | else: 52 | selected = treeview.get_model().get_path(treeview.get_selection().get_selected()[1])[0] 53 | self.selected_version = self.versions[selected] 54 | 55 | def select_local_installer(self, button): 56 | if type(button) == type(True): 57 | self.local_installer = button 58 | else: 59 | self.local_installer = button.get_active() 60 | 61 | if self.local_installer: 62 | self.widgets['filechooserbutton-installer'].set_sensitive(True) 63 | self.widgets['button_next'].set_sensitive(False) 64 | if self.reaperfilelocal != None: 65 | self.widgets['button_next'].set_sensitive(True) 66 | else: 67 | self.widgets['button_next'].set_sensitive(False) 68 | else: 69 | self.widgets['filechooserbutton-installer'].set_sensitive(False) 70 | self.widgets['button_next'].set_sensitive(True) 71 | 72 | def set_local_installer(self, filechooser): 73 | filenames = filechooser.get_filenames() 74 | if len(filenames): 75 | self.reaperfilelocal = filenames[0] 76 | self.widgets['button_next'].set_sensitive(True) 77 | else: 78 | self.widgets['button_next'].set_sensitive(False) 79 | 80 | def select_installation_path(self, button): 81 | # If globally 82 | if button.get_active(): 83 | self.installpath = self.default_installpath_global 84 | self.widgets['filechooserbutton-installer'].set_sensitive(False) 85 | else: 86 | self.widgets['filechooserbutton-installer'].set_sensitive(True) 87 | self.update_installpath() 88 | 89 | def select_local_path(self, filechooser): 90 | filenames = filechooser.get_filenames() 91 | if len(filenames): 92 | self.installpath_dir = filenames[0] 93 | self.update_installpath() 94 | 95 | def update_installpath(self): 96 | self.installpath = self.installpath_dir + '/' + ( self.widgets['entry_install_local'].get_text() or "reaper") 97 | 98 | def change_installation_path(self, entry): 99 | self.update_installpath() 100 | 101 | def select_shortcuts(self, button): 102 | self.option_shortcuts = button.get_active() 103 | 104 | def select_wineasio(self, button): 105 | self.option_wineasio = button.get_active() 106 | 107 | 108 | def next(self, button): 109 | self.widgets['notebook'].next_page() 110 | if self.widgets['notebook'].get_current_page() == 1: 111 | if self.reaperfilelocal == None: 112 | self.select_local_installer(False) 113 | else: 114 | self.selected_version = "local" 115 | self.select_local_installer(True) 116 | self.widgets['check_local_installer'].set_active(True) 117 | elif self.widgets['notebook'].get_current_page() == 2: 118 | do_install() 119 | 120 | def do_install(): 121 | main.rundir = os.path.dirname(os.path.abspath(sys.argv[0])) 122 | 123 | main.widgets['button_next'].set_sensitive(False) 124 | 125 | # If set to use local installer 126 | #if main.widgets['check_local_installer'].get_active() is True: 127 | if main.local_installer is True: 128 | print "Using local Reaper installer" 129 | main.reaperfile = main.reaperfilelocal 130 | do_install_run() 131 | else: 132 | print "Downloading Reaper" 133 | main.widgets['label_install'].set_text("Downloading Reaper...") 134 | #main.reaperfile = "/tmp/"+os.path.basename(main.selected_version['url']) 135 | #main.reaperurl = get_version_url() 136 | #main.reaperfile = "/tmp/"+os.path.basename(main.reaperurl) 137 | run(main.rundir+"/scripts/get_reaper.sh", [], do_install_run, do_error) 138 | 139 | def do_install_run(): 140 | #print "Create Wine setup and run the installer" 141 | main.widgets['label_install'].set_text("Creating Wine setup and running the installer\n(just accept the defaults and don't run Reaper if asked)...") 142 | if hasattr(main, 'reaperfile') and len(main.reaperfile): 143 | run(main.rundir+"/scripts/run_install.sh", [main.installpath, main.reaperfile], do_install_setup_config, do_error) 144 | else: 145 | run(main.rundir+"/scripts/run_install.sh", [main.installpath], do_install_setup_config, do_error) 146 | 147 | def do_install_setup_config(): 148 | #print "Setup installation" 149 | main.widgets['label_install'].set_text("Setting up installation...") 150 | run(main.rundir+"/scripts/setup_config.sh", [main.installpath], do_install_setup_shortcuts, do_error) 151 | 152 | def do_install_setup_shortcuts(): 153 | #print "Add options" 154 | if main.option_shortcuts == True: 155 | main.widgets['label_install'].set_text("Creating shortcuts...") 156 | run(main.rundir+"/scripts/setup_shortcuts.sh", [main.installpath], do_install_setup_wineasio, do_error) 157 | else: 158 | do_install_setup_wineasio() 159 | 160 | def do_install_setup_wineasio(): 161 | if main.option_wineasio == True: 162 | main.widgets['label_install'].set_text("Setting up WineAsio...") 163 | run(main.rundir+"/scripts/setup_wineasio.sh", [main.installpath], do_install_finish, do_error) 164 | else: 165 | do_install_finish() 166 | 167 | def do_install_finish(): 168 | main.widgets['notebook'].next_page() 169 | main.widgets['button_next'].set_sensitive(True) 170 | main.widgets['button_next'].set_label("Done") 171 | main.widgets['button_next'].connect("clicked", main._exit) 172 | 173 | def do_error(): 174 | main.widgets['label_install'].set_text("An error has occured.\nPlease check the console output for more info.") 175 | main.widgets['progressbar_install'].hide() 176 | main.widgets['button_cancel'].set_sensitive(False) 177 | main.widgets['button_next'].set_sensitive(True) 178 | main.widgets['button_next'].set_label("Quit") 179 | main.widgets['button_next'].connect("clicked", main._exit) 180 | 181 | def run(command, arguments, finished_function, error_function): 182 | #print command, arguments, finished_function, error_function 183 | #return 184 | thread = threading.Thread(target=run_process, args=[command, arguments, finished_function, error_function]) 185 | thread.start() 186 | 187 | def run_process(command, arguments, finished_function, error_function): 188 | #print "Running command:",command 189 | p = subprocess.Popen(command + ' ' + ' '.join(arguments), shell=True, 190 | stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) 191 | 192 | output = "" 193 | while p.poll() == None: 194 | line = os.read(p.stdout.fileno(), 32) 195 | percent = None 196 | if line: 197 | output += line 198 | lastline = output.split("\n")[-1].strip() 199 | if lastline and '%' in lastline: 200 | 201 | if len(lastline.split('%')) > 2: 202 | percent = lastline.split('%')[-2].split()[-1] 203 | else: 204 | percent = lastline.split('%')[0].split()[0] 205 | 206 | try: 207 | percent = float(percent) / 100 208 | except: 209 | percent = None 210 | 211 | if percent: 212 | gtk.gdk.threads_enter() 213 | main.widgets['progressbar_install'].set_fraction(percent) 214 | gtk.gdk.threads_leave() 215 | else: 216 | gtk.gdk.threads_enter() 217 | main.widgets['progressbar_install'].pulse() 218 | gtk.gdk.threads_leave() 219 | sys.stdout.write(line) 220 | 221 | main.errorlog += output 222 | 223 | if p.returncode != 0: 224 | error_function() 225 | else: 226 | finished_function() 227 | 228 | 229 | def get_version_url(): 230 | baseurl = 'http://reaper.fm/download.php' 231 | url = urllib.urlopen(baseurl) 232 | url = url.read() 233 | url = re.search('Windows \(', url).groups()[0] 234 | if url: 235 | if '://' not in url[:8]: 236 | url = 'http://reaper.fm/'+url 237 | return url 238 | else: 239 | return None 240 | 241 | def get_version_urls(): 242 | baseurl = 'http://reaper.fm/files/2.x/' 243 | # Get the HTML listing of the available Reaper versions 244 | reaperlisting = urllib.urlopen(baseurl) 245 | reaperlisting = "\n".join( reaperlisting.readlines() ) 246 | 247 | # Split the HTML so it only contains the table rows with the files 248 | try: 249 | reaperlisting = filter(len, reaperlisting.split('
')[1].split("\n")[:-2]) 250 | 251 | # Filter through the table rows, extracting the data we need 252 | versions = {} 253 | for row in reaperlisting[1:]: 254 | url = baseurl + row.split('
')[0].lower() 255 | # Skip if this version is for x64, as Wine can't handle it yet - also discard zip, dll and dmg files 256 | if 'x64' in url or url.endswith('.zip') or url.endswith('.dll') or url.endswith('.dmg'): 257 | continue 258 | date = row.split('')[1].split('')[0].strip() 259 | dateint = int( ''.join(map(lambda i: "%02d" % i, time.strptime(date, "%d-%b-%Y %H:%M")[:3])) ) 260 | try: 261 | name = "Version 2." + url.split('/')[-1].split('reaper2')[1].split('-install')[0] 262 | if '_' in name: 263 | name = name.split('_')[0]+" ("+name.split('_')[1]+")" 264 | except: 265 | print "Error, couldn't parse "+url 266 | versions[dateint] = {'url':url, 'date':date, 'name':name} 267 | # Get the dates of the versions and sort them 268 | dates = versions.keys() 269 | dates.sort() 270 | # Return the versions as a sorted list 271 | versions = [ versions[i] for i in dates ] 272 | versions.reverse() 273 | except IndexError: 274 | versions = [] 275 | return versions 276 | 277 | 278 | class CreateWidgets: 279 | def __init__(self, handlerclass, file="linreaper.glade", name="linreaper"): 280 | self.widgets = gtk.glade.XML(file, None, name) 281 | self.widgets.signal_autoconnect(handlerclass) 282 | self.ownwidgets = {} 283 | def __getitem__(self, key): 284 | if key not in self.ownwidgets: 285 | return self.widgets.get_widget(key) 286 | else: 287 | return self.ownwidgets[key] 288 | def __setitem__(self, key, value): 289 | self.ownwidgets[key] = value 290 | 291 | if __name__ == "__main__": 292 | locale.setlocale(locale.LC_ALL, "C") 293 | try: 294 | gobject.threads_init() 295 | gtk.gdk.threads_init() 296 | global main 297 | gtk.gdk.threads_enter() 298 | main = Main() 299 | gtk.main() 300 | gtk.gdk.threads_leave() 301 | finally: 302 | pass 303 | -------------------------------------------------------------------------------- /scripts/.conf.glade: -------------------------------------------------------------------------------- 1 | conf.glade -------------------------------------------------------------------------------- /scripts/.conftool.sh: -------------------------------------------------------------------------------- 1 | conftool.sh -------------------------------------------------------------------------------- /scripts/.js.svg: -------------------------------------------------------------------------------- 1 | js.svg -------------------------------------------------------------------------------- /scripts/.vst.svg: -------------------------------------------------------------------------------- 1 | vst.svg -------------------------------------------------------------------------------- /scripts/.vst_installer.sh: -------------------------------------------------------------------------------- 1 | vst_installer.sh -------------------------------------------------------------------------------- /scripts/REAPER.ini.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | contents=' 4 | 5 | [REAPER] 6 | audioasync=3 7 | trackupdmode=2 8 | vstpath=Z:\\usr\\lib\\vstwin32;C:\\windows\\profiles\\'$USER'\\My Documents\\.vst;C:\\windows\\profiles\\'$USER'\\My Documents\\.config\\reaper\\vst' 9 | 10 | echo "$contents" 11 | -------------------------------------------------------------------------------- /scripts/_functions.sh: -------------------------------------------------------------------------------- 1 | # Function to get a value from the system registry and convert it to a UNIX path 2 | pathfromreg() { 3 | # Grep for value key, pick first or last one and strip the key part of the line 4 | if [ -z "$2" ]; then 5 | WinPath="$(grep "\"$1\"=" "$appdir/.wine/system.reg" | tail -n1 | cut -d= -f2-)" 6 | else 7 | WinPath="$(grep "\"$1\"=" "$appdir/.wine/system.reg" | head -n1 | cut -d= -f2-)" 8 | fi 9 | # Remove quotes, if any 10 | test "${WinPath:0:1}" = '"' && WinPath="$(echo ${WinPath:1:${#WinPath}-2})" 11 | 12 | # Check for likely variable reference, look for first occurance instead if so 13 | if test "${WinPath:0:3}" = 'str'; then 14 | echo "$(pathfromreg "$1" first)" 15 | else 16 | # Convert to UNIX path 17 | # echo "$WinPath" 18 | winepath -u "$WinPath" 19 | fi 20 | } 21 | 22 | 23 | getProgramFiles() { 24 | ProgramFiles="$(pathfromreg "ProgramFiles")" 25 | # If ProgramFiles isn't set, try ProgramFilesDir 26 | test -z "$ProgramFiles" && ProgramFiles="$(pathfromreg "ProgramFilesDir")" 27 | echo $ProgramFiles 28 | } 29 | getWinSysDir() { 30 | winsysdir="$(pathfromreg "winsysdir")" 31 | echo $winsysdir 32 | } 33 | getAppData() { 34 | APPDATA="$(pathfromreg "APPDATA")" 35 | test -z "$APPDATA" && APPDATA="$(pathfromreg 'Common AppData')" 36 | echo $APPDATA 37 | } 38 | getProfilesDir() { 39 | test -z "$APPDATA" && APPDATA="$(getAppData)" 40 | PROFILESDIR="$(dirname "`dirname "$APPDATA"`")" 41 | echo $PROFILESDIR 42 | } 43 | getUserProfile() { 44 | test -z "$PROFILESDIR" && PROFILESDIR="$(getProfilesDir)" 45 | USERPROFILE="$PROFILESDIR/$USER" 46 | echo $USERPROFILE 47 | } -------------------------------------------------------------------------------- /scripts/conftool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert relative to absolute path 4 | appdir="$(cd "`dirname "$0"`"; pwd)" 5 | 6 | if [ ! -e "$HOME/.config/reaper/vst" ]; then 7 | mkdir "$HOME/.config/reaper/vst" 8 | fi 9 | 10 | if [ -z "$1" ]; then 11 | exit 12 | elif [ "$1" == "__RENDER__" ]; then 13 | exec "$appdir/reaper.sh" --renderproject "$2" 14 | elif [ "$1" == "__AUDIOCONF__" ]; then 15 | exec "$appdir/reaper.sh" --audiocfg 16 | elif [ "$1" == "__CONF__" ]; then 17 | exec "$appdir/reaper.sh" --cfgfile "$2" 18 | elif [ "$1" == "__VSTFOLDER__" ]; then 19 | exec xdg-open "$HOME/.config/reaper/vst/" 20 | elif [ "$1" == "__JSFOLDER__" ]; then 21 | exec xdg-open "$appdir/Effects/" 22 | elif [ "$1" == "__WINECFG__" ]; then 23 | exec env HOME="$appdir" winecfg 24 | elif [ "$1" == "__REGEDIT__" ]; then 25 | exec env HOME="$appdir" regedit 26 | else 27 | exec "$appdir/.vst_installer.sh" "$1" 28 | fi 29 | -------------------------------------------------------------------------------- /scripts/export_wine_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | appdir="$1" 4 | 5 | convert_path_to_unix() { 6 | path="$1" 7 | echo "$(winepath -u "$path")" 8 | # There's nothing wrong with the following code, except that it doesn't take into account 9 | # Wine drives other than C: and winepath does - this code, however, does not fail on a missing directory 10 | # which might or might not be a good thing 11 | #c="$(basename "$WineC")" 12 | #echo "$appdir/.wine/dosdevices/$(echo "$path" | tr '\\' '\/' | sed "s/C:/$c/i" | tr -s '/')" 13 | } 14 | 15 | get_path_from_registry() { 16 | path="$1" 17 | path="$(cat "$appdir/.wine/system.reg" | grep "\"$path\"=" | cut -d= -f2-)" 18 | echo "${path:1:`expr length "$path" - 2`}" 19 | } 20 | get_path_from_user_registry() { 21 | path="$1" 22 | path="$(cat "$appdir/.wine/user.reg" | sed -n '/\\Shell Folders/,/\[/p' | grep "\"$path\"=" | cut -d= -f2-)" 23 | echo "${path:1:`expr length "$path" - 2`}" 24 | } 25 | 26 | if [ -n "$LD_LIBRARY_PATH" ]; then 27 | LD_LIBRARY_PATH="$appdir/.winelib:$LD_LIBRARY_PATH" 28 | else 29 | LD_LIBRARY_PATH="$appdir/.winelib" 30 | fi 31 | export LD_LIBRARY_PATH 32 | 33 | if [ -n "$WINEDLLPATH" ]; then 34 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib:$WINEDLLPATH" 35 | else 36 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib" 37 | fi 38 | export WINEDLLPATH 39 | 40 | WINEPREFIX="$appdir/.wine" 41 | export WINEPREFIX 42 | 43 | WINEDEBUG="fixme-all" 44 | export WINEDEBUG 45 | 46 | # Get the Windows paths from registry since they are different according to locale 47 | WineC="$(winepath -u 'C:\')" 48 | ProgramFiles="$(get_path_from_registry "ProgramFiles")" 49 | ProgramFilesUnix="$(convert_path_to_unix "$ProgramFiles")" 50 | SysDir="$(get_path_from_registry "winsysdir")" 51 | SysDirUnix="$(convert_path_to_unix "$SysDir")" 52 | AppData="$(get_path_from_registry "APPDATA")" 53 | AppDataUnix="$(convert_path_to_unix "$AppData")" 54 | WinDesktop="$(get_path_from_user_registry "Desktop")" 55 | WinDesktopUnix="$(convert_path_to_unix "$WinDesktop")" 56 | WinMyDocuments="$(get_path_from_user_registry "Personal")" 57 | WinMyDocumentsUnix="$(convert_path_to_unix "$WinMyDocuments")" 58 | WinMyMusic="$(get_path_from_user_registry "My Music")" 59 | WinMyMusicUnix="$(convert_path_to_unix "$WinMyMusic")" 60 | WinMyPictures="$(get_path_from_user_registry "My Pictures")" 61 | WinMyPicturesUnix="$(convert_path_to_unix "$WinMyPictures")" 62 | WinMyVideos="$(get_path_from_user_registry "My Videos")" 63 | WinMyVideosUnix="$(convert_path_to_unix "$WinMyVideos")" 64 | 65 | ProfilesDirUnix="$(dirname "`dirname "$AppDataUnix"`")" 66 | AppDataBase="$(basename "$AppDataUnix")" 67 | 68 | UserProfileUnix="$ProfilesDirUnix/$USER" 69 | AppDataUnix="$UserProfileUnix/$AppDataBase" 70 | 71 | export ProgramFiles ProgramFilesUnix 72 | export SysDir SysDirUnix 73 | export ProfilesDirUnix 74 | export AppDataBase 75 | export AppData AppDataUnix 76 | export UserProfileUnix 77 | export WinDesktop WinDesktopUnix 78 | export WinMyDocuments WinMyDocumentsUnix 79 | export WinMyMusic WinMyMusicUnix 80 | export WinMyPictures WinMyPicturesUnix 81 | export WinMyVideos WinMyVideosUnix 82 | -------------------------------------------------------------------------------- /scripts/get_reaper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # If we were not given a URL, find it ourselves 4 | if [ -z "$1" ]; then 5 | url="$(wget -qO - 'http://reaper.fm/download.php' | grep -ie '-install.exe">' | grep -iEoe '".*.exe"' | grep -v 'x64')" 6 | url="${url:1:$(expr ${#url}-2)}" 7 | # If http:// (or ftp:// or similar) is missing from url, add it 8 | if [ -z $(expr "$url" : '.*\(://\)') ]; then 9 | url="http://reaper.fm/$url" 10 | fi 11 | else 12 | url="$1" 13 | fi 14 | 15 | if [ -z "$2" ]; then 16 | output="/tmp/linreaper-reaper-install.exe" 17 | else 18 | output="$2" 19 | fi 20 | 21 | 22 | if [ ! -f "$2" ]; then 23 | wget --progress=bar:force "$url" -O "$output" 24 | fi 25 | -------------------------------------------------------------------------------- /scripts/gnome/128x128/apps/reaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/128x128/apps/reaper.png -------------------------------------------------------------------------------- /scripts/gnome/16x16/apps/reaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/16x16/apps/reaper.png -------------------------------------------------------------------------------- /scripts/gnome/16x16/reaper.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 25 | 28 | 32 | 36 | 37 | 40 | 44 | 48 | 49 | 52 | 56 | 60 | 61 | 68 | 75 | 84 | 93 | 104 | 105 | 126 | 134 | 135 | 137 | 138 | 140 | image/svg+xml 141 | 143 | 144 | 145 | 146 | 150 | 155 | 160 | 165 | 173 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /scripts/gnome/24x24/apps/linreapervsttool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/24x24/apps/linreapervsttool.png -------------------------------------------------------------------------------- /scripts/gnome/24x24/linreapervsttool.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 25 | 27 | 31 | 35 | 39 | 40 | 43 | 47 | 51 | 52 | 55 | 59 | 63 | 64 | 67 | 71 | 75 | 76 | 78 | 82 | 86 | 87 | 94 | 105 | 115 | 125 | 136 | 146 | 147 | 168 | 176 | 177 | 179 | 180 | 182 | image/svg+xml 183 | 185 | 186 | 187 | 188 | 192 | 197 | 202 | 207 | 214 | VST 225 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /scripts/gnome/256x256/apps/reaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/256x256/apps/reaper.png -------------------------------------------------------------------------------- /scripts/gnome/32x32/apps/reaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/32x32/apps/reaper.png -------------------------------------------------------------------------------- /scripts/gnome/48x48/apps/linreapervsttool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/48x48/apps/linreapervsttool.png -------------------------------------------------------------------------------- /scripts/gnome/48x48/apps/reaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/48x48/apps/reaper.png -------------------------------------------------------------------------------- /scripts/gnome/96x96/apps/reaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/gnome/96x96/apps/reaper.png -------------------------------------------------------------------------------- /scripts/gnome/scalable/apps/linreapervsttool.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | 22 | 24 | 28 | 32 | 36 | 37 | 40 | 44 | 48 | 49 | 52 | 56 | 60 | 61 | 64 | 68 | 72 | 73 | 75 | 79 | 83 | 84 | 91 | 102 | 112 | 121 | 131 | 140 | 141 | 162 | 170 | 171 | 173 | 174 | 176 | image/svg+xml 177 | 179 | 180 | 181 | 182 | 186 | 191 | 196 | 201 | 208 | VST 218 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /scripts/js.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 26 | 29 | 33 | 37 | 38 | 41 | 45 | 49 | 50 | 53 | 57 | 61 | 62 | 65 | 69 | 73 | 74 | 77 | 81 | 85 | 86 | 89 | 93 | 97 | 98 | 101 | 105 | 109 | 110 | 117 | 124 | 131 | 141 | 151 | 161 | 164 | 169 | 170 | 180 | 189 | 198 | 207 | 216 | 223 | 227 | 228 | 237 | 246 | 255 | 256 | 279 | 287 | 288 | 290 | 291 | 293 | image/svg+xml 294 | 296 | 297 | 298 | 299 | 304 | 314 | 315 | 320 | 325 | 330 | 331 | 336 | 343 | 347 | 348 | 353 | 363 | 373 | 374 | 379 | 384 | 385 | 386 | -------------------------------------------------------------------------------- /scripts/linreapercfg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import pygtk 5 | pygtk.require('2.0') 6 | import gtk, gobject, gtk.glade, os, sys, subprocess 7 | import locale, gettext 8 | 9 | class Main: 10 | def _exit(self, *args): 11 | gtk.main_quit() 12 | exit() 13 | 14 | def __init__(self): 15 | self.filename = None 16 | self.path = os.path.abspath(os.path.dirname(sys.argv[0])) 17 | 18 | self.widgets = CreateWidgets(self) 19 | 20 | self.widgets['vbox_win_install'].drag_dest_set(gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, [ ( "text/plain", 0, 80 ), ( "text/uri-list", 0, 80 ) ], gtk.gdk.ACTION_COPY) 21 | 22 | filter = gtk.FileFilter() 23 | filter.set_name("Windows executables") 24 | #filter.add_mime_type("application/x-executable") 25 | filter.add_pattern("*.[eE][xX][eE]") 26 | filter.add_pattern("*.[mM][sS][iI]") 27 | self.widgets['filechooserbutton_win_install'].add_filter(filter) 28 | 29 | filter = gtk.FileFilter() 30 | filter.set_name("All files") 31 | filter.add_pattern("*") 32 | self.widgets['filechooserbutton_win_install'].add_filter(filter) 33 | 34 | 35 | filter = gtk.FileFilter() 36 | filter.set_name("Reaper Projects") 37 | #filter.add_mime_type("application/x-executable") 38 | filter.add_pattern("*.[rR][pP][pP]") 39 | filter.add_pattern("*.[rR][pP][pP]-[bB][aA][kK]") 40 | self.widgets['filechooserbutton_render'].add_filter(filter) 41 | 42 | filter = gtk.FileFilter() 43 | filter.set_name("All files") 44 | filter.add_pattern("*") 45 | self.widgets['filechooserbutton_render'].add_filter(filter) 46 | 47 | 48 | filter = gtk.FileFilter() 49 | filter.set_name("Reaper Configuration Files") 50 | #filter.add_mime_type("application/x-executable") 51 | filter.add_pattern("*.[iI][nN][iI]") 52 | filter.add_pattern("*.[tT][xX][tT]") 53 | self.widgets['filechooserbutton_conf'].add_filter(filter) 54 | 55 | filter = gtk.FileFilter() 56 | filter.set_name("All files") 57 | filter.add_pattern("*") 58 | self.widgets['filechooserbutton_conf'].add_filter(filter) 59 | 60 | def motion_cb(self, wid, context, x, y, time): 61 | context.drag_status(gtk.gdk.ACTION_COPY, time) 62 | return True 63 | 64 | def drop_cb(self, wid, context, x, y, time): 65 | #l.set_text('\n'.join([str(t) for t in context.targets])) 66 | context.finish(True, False, time) 67 | return True 68 | 69 | 70 | def data_received(self, wid, context, x, y, selection, targettype, time): 71 | if targettype == 80: 72 | text = selection.data 73 | if text.startswith('file://'): text = text.split('file://')[1][:-2] 74 | self.filename = text.replace('%20', ' ') 75 | self.widgets['filechooserbutton_win_install'].set_filename(self.filename) 76 | self.widgets['button_run'].set_sensitive(True) 77 | 78 | 79 | def filechooser_selected(self, filechooser): 80 | filenames = filechooser.get_filenames() 81 | if len(filenames): 82 | self.filename = filenames[0] 83 | self.widgets['button_run'].set_sensitive(True) 84 | else: 85 | self.widgets['button_run'].set_sensitive(False) 86 | 87 | def render_selection_changed(self, filechooser): 88 | filenames = filechooser.get_filenames() 89 | if len(filenames): 90 | self.filename_render = filenames[0] 91 | self.widgets['button_reaper_render'].set_sensitive(True) 92 | else: 93 | self.widgets['button_reaper_render'].set_sensitive(False) 94 | 95 | def conf_selection_changed(self, filechooser): 96 | filenames = filechooser.get_filenames() 97 | if len(filenames): 98 | self.filename_conf = filenames[0] 99 | self.widgets['button_reaper_conf'].set_sensitive(True) 100 | else: 101 | self.widgets['button_reaper_conf'].set_sensitive(False) 102 | 103 | 104 | def open_reaper_render(self, *args): 105 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, "__RENDER__", self.filename_render]).pid 106 | 107 | def open_reaper_audio(self, *args): 108 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, "__AUDIOCONF__"]).pid 109 | 110 | def open_reaper_conf(self, *args): 111 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, "__CONF__", self.filename_conf]).pid 112 | 113 | def open_vst(self, *args): 114 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, "__VSTFOLDER__"]).pid 115 | 116 | def open_js(self, *args): 117 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, "__JSFOLDER__"]).pid 118 | 119 | def open_winecfg(self, *args): 120 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, "__WINECFG__"]).pid 121 | 122 | def open_regedit(self, *args): 123 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, "__REGEDIT__"]).pid 124 | 125 | def run_installer(self, *args): 126 | self.pid = subprocess.Popen(["%s/.conftool.sh" % self.path, self.filename]).pid 127 | 128 | 129 | 130 | class CreateWidgets: 131 | def __init__(self, handlerclass, file=".conf.glade", name="linreaper"): 132 | self.widgets = gtk.glade.XML("%s/%s" % (handlerclass.path, file), None, name) 133 | self.widgets.signal_autoconnect(handlerclass) 134 | self.ownwidgets = {} 135 | def __getitem__(self, key): 136 | if key not in self.ownwidgets: 137 | return self.widgets.get_widget(key) 138 | else: 139 | return self.ownwidgets[key] 140 | def __setitem__(self, key, value): 141 | self.ownwidgets[key] = value 142 | 143 | if __name__ == "__main__": 144 | locale.setlocale(locale.LC_ALL, "C") 145 | try: 146 | gobject.threads_init() 147 | gtk.gdk.threads_init() 148 | global main 149 | gtk.gdk.threads_enter() 150 | main = Main() 151 | gtk.main() 152 | gtk.gdk.threads_leave() 153 | finally: 154 | pass 155 | -------------------------------------------------------------------------------- /scripts/mimetype.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Reaper project 5 | 6 | 7 | 8 | 9 | 10 | 11 | Reaper project backup 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Reaper peak file 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /scripts/reaper_updater.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os, gtk, gobject, gtk.glade, subprocess, sys, threading, urllib, time, locale, re 5 | 6 | 7 | if __name__ == "__main__": 8 | locale.setlocale(locale.LC_ALL, "C") 9 | try: 10 | gobject.threads_init() 11 | gtk.gdk.threads_init() 12 | global main 13 | gtk.gdk.threads_enter() 14 | main = Main() 15 | gtk.main() 16 | gtk.gdk.threads_leave() 17 | finally: 18 | pass 19 | -------------------------------------------------------------------------------- /scripts/run_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "$(dirname "$(readlink -f "$0")")"/_functions.sh 4 | 5 | # Convert relative to absolute paths 6 | tempdir="$(cd "$(dirname "$0")"; pwd)" 7 | if [ -z "$2" ]; then 8 | installexe="/tmp/linreaper-reaper-install.exe" 9 | else 10 | installexe="$2" 11 | fi 12 | 13 | if [ ! -d "$1" ]; then 14 | echo -n "Creating directory $1" 15 | 16 | mkdir "$1" 17 | echo "." 18 | else 19 | echo "Install directory \"$1\" already exists." 20 | fi 21 | appdir="$(cd "$1"; pwd)" 22 | 23 | 24 | if [ ! -d "$appdir/.winelib" ]; then mkdir "$appdir/.winelib"; fi 25 | if [ ! -d "$appdir/.wine" ]; then mkdir "$appdir/.wine"; fi 26 | 27 | if [ -n "$LD_LIBRARY_PATH" ]; then 28 | LD_LIBRARY_PATH="$appdir/.winelib:$LD_LIBRARY_PATH" 29 | else 30 | LD_LIBRARY_PATH="$appdir/.winelib" 31 | fi 32 | export LD_LIBRARY_PATH 33 | 34 | if [ -n "$WINEDLLPATH" ]; then 35 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib:$WINEDLLPATH" 36 | else 37 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib" 38 | fi 39 | export WINEDLLPATH 40 | 41 | WINEPREFIX="$appdir/.wine" 42 | export WINEPREFIX 43 | 44 | if [ ! -d "$WINEPREFIX" ]; then 45 | echo "Creating Wine directory" 46 | else 47 | echo "Updating Wine directory" 48 | fi 49 | env HOME="$appdir" regedit /E /tmp/.linreaper_prefix_created 'HKEY_CURRENT_USER\Software\Wine' &> /tmp/.linreaper_wine_output 50 | 51 | if [ ! -d "$WINEPREFIX" ]; then 52 | echo -n "Waiting for registry files to be created..." 53 | else 54 | echo -n "Waiting for registry files to be updated..." 55 | fi 56 | while [ ! -f "$appdir/.wine/system.reg" ]; do 57 | sleep 0 58 | done 59 | echo " Done." 60 | 61 | 62 | ProgramFiles="$(getProgramFiles)" 63 | winsysdir="$(getWinSysDir)" 64 | APPDATA="$(getAppData)" 65 | PROFILESDIR="$(getProfilesDir)" 66 | USERPROFILE="$(getUserProfile)" 67 | 68 | # Debug stuff 69 | # echo "ProgramFiles: '$ProgramFiles'" 70 | # echo "winsysdir: '$winsysdir'" 71 | # echo "APPDATA: '$APPDATA'" 72 | # echo "PROFILESDIR: '$PROFILESDIR'" 73 | # echo "USERPROFILE: '$USERPROFILE'" 74 | # exit 0 75 | 76 | runinstall=1 77 | # If 7zip is installed, bypass the installer and install Reaper ourselves 78 | if 7za --help &> /dev/null ; then 79 | echo "7zip installed, bypassing installer" 80 | echo "Installing Reaper into it" 81 | # Debug stuff 82 | #echo "7z x -y -o"$ProgramFiles/REAPER" "$installexe"" 83 | #exit 84 | 7z x -y -o"$ProgramFiles/REAPER" "$installexe" 85 | if [ "$?" != 0 ]; then 86 | echo "Extracting from exe failed, running installer instead" 87 | else 88 | runinstall=0 89 | mv "$ProgramFiles/REAPER/\$SYSDIR"/* "$winsysdir"/ 90 | rmdir "$ProgramFiles/REAPER/\$SYSDIR" 91 | chmod +x "$ProgramFiles/REAPER"/*.exe 92 | fi 93 | fi 94 | 95 | if [ $runinstall == 1 ]; then 96 | echo "Running the installer" 97 | env HOME="$appdir" wine "$installexe" 98 | if [ "$?" != 0 ]; then 99 | echo "Running the installer failed. Cancelling install." 100 | exit 1 101 | fi 102 | fi 103 | 104 | 105 | if [ -d "$appdir/.wine" ]; then 106 | # Copy LinReaper tools to the install dir 107 | cp "$tempdir/run_reaper.sh" "$appdir/reaper.sh" 108 | chmod +x "$appdir/reaper.sh" 109 | cp "$tempdir/REAPER.ini.sh" "$appdir/.REAPER.ini.default.sh" 110 | 111 | cp "$tempdir/winepath.sh" "$appdir/.winepath.sh" 112 | cp "$tempdir/conftool.sh" "$appdir/.conftool.sh" 113 | cp "$tempdir/vst_installer.sh" "$appdir/.vst_installer.sh" 114 | cp "$tempdir/conf.glade" "$appdir/.conf.glade" 115 | cp "$tempdir/vst.svg" "$appdir/.vst.svg" 116 | cp "$tempdir/js.svg" "$appdir/.js.svg" 117 | cp "$tempdir/linreapercfg.py" "$appdir/linreapercfg.py" 118 | chmod +x "$appdir/.conftool.sh" "$appdir/.vst_installer.sh" "$appdir/linreapercfg.py" 119 | 120 | cp "$tempdir/export_wine_environment.sh" "$appdir/.export_wine_environment.sh" 121 | cp "$tempdir/update_config.sh" "$appdir/.update_config.sh" 122 | 123 | # Setup the Reaper installation for the current user 124 | # to save time on the first run (only if this is first time install) 125 | if [ -d "$tempdir/gnome" ]; then 126 | "$appdir/.update_config.sh" 127 | 128 | # Setup shortcuts and icons 129 | cp -R "$tempdir/gnome" "$HOME/.icons/" 130 | if [ ! -d "$HOME/.local/share/mime/packages" ]; then 131 | mkdir -p "$HOME/.local/share/mime/packages" 132 | fi 133 | if [ ! -d "$HOME/.local/share/applications" ]; then 134 | mkdir -p "$HOME/.local/share/applications" 135 | fi 136 | cp "$tempdir/mimetype.xml" "$HOME/.local/share/mime/packages/reaper.xml" 137 | update-mime-database "$HOME/.local/share/mime" 138 | #update-desktop-database "$HOME/.local/share" # This loops over Wine's Z: link and gets sad :( 139 | update-desktop-database "$HOME/.local/share/applications" 140 | # Make C:\Windows\Profiles read/writable for everyone, so all users can save their settings. 141 | # Remember that the Profiles dir will not contain important directories, only symlinks to 142 | # users ~/.config/reaper dirs, so security should be fine. 143 | chmod a+rw "$PROFILESDIR" 144 | fi 145 | else 146 | echo "ERROR: It seems Wine didn't get run. Are you sure you have Wine installed?" 147 | exit 1 148 | fi 149 | 150 | -------------------------------------------------------------------------------- /scripts/run_notepad.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert relative to absolute path 4 | appdir="$(cd "`dirname "$0"`"; pwd)" 5 | 6 | if [ -n "$LD_LIBRARY_PATH" ]; then 7 | LD_LIBRARY_PATH="$appdir/.winelib:$LD_LIBRARY_PATH" 8 | else 9 | LD_LIBRARY_PATH="$appdir/.winelib" 10 | fi 11 | export LD_LIBRARY_PATH 12 | 13 | if [ -n "$WINEDLLPATH" ]; then 14 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib:$WINEDLLPATH" 15 | else 16 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib" 17 | fi 18 | export WINEDLLPATH 19 | 20 | WINEPREFIX="$appdir/.wine" 21 | export WINEPREFIX 22 | 23 | WINEDEBUG="fixme-all" 24 | export WINEDEBUG 25 | 26 | convert_path_to_unix() { 27 | filename="$1" 28 | if [ "${filename:1:2}" != ':\' ]; then 29 | echo -n "$filename" 30 | else 31 | echo -n "$(winepath -u "$filename")" 32 | fi 33 | } 34 | 35 | #args="'`convert_path_to_unix "$1"`' " 36 | 37 | #eval "wine '$ProgramFiles\REAPER\Reaper.exe' $args" 38 | xdg-open "$(convert_path_to_unix "$1")" 39 | exit 40 | 41 | # If Reaper doesn't have a configuration for this user, create a directory 42 | # in $HOME/.config containing a base Linux configuration and link Reaper to it 43 | if [ ! -e "$APPDATA/REAPER" ]; then 44 | if [ ! -e "$HOME/.config/reaper" ]; then 45 | if [ ! -e "$HOME/.config" ]; then mkdir "$HOME/.config"; fi 46 | mkdir "$HOME/.config/reaper" 47 | "$appdir"/.REAPER.ini.default.sh > "$HOME/.config/reaper/REAPER.ini" 48 | fi 49 | ln -s "$HOME/.config/reaper" "$APPDATA/REAPER" 50 | # Link Windows profile dirs to $HOME 51 | for dir in "My Documents" "My Music" "My Pictures" "My Videos"; do 52 | rm "$WINEPREFIX/drive_c/windows/profiles/$USER/$dir" 53 | ln -s "$HOME" "$USERPROFILE/$dir" 54 | done 55 | # Link Windows Desktop to $HOME/Desktop 56 | rm "$USERPROFILE/Desktop" 57 | ln -s "$HOME/Desktop" "$USERPROFILE/Desktop" 58 | 59 | if [ $# -eq 0 ]; then args="'$ProgramFiles\REAPER\BradSucks_MakingMeNervous\BradSucks_MakingMeNervous.RPP'"; fi 60 | fi 61 | 62 | while [ $# -gt 0 ]; do 63 | case "$1" in 64 | -h|--help|-help) 65 | echo "Usage: `basename "$0"` [OPTION...] [FILE.rpp | FILE.wav]" 66 | echo -e "\nOptions:" 67 | echo -e " -a, --audiocfg \t\t\t\tShow the audio configuration settings" 68 | echo -e " -c, --cfgfile FILE \t\t\t\tLoad the specified config file" 69 | echo -e " -n, --new \t\t\t\t\tOpen a new project, use FILE if specified" 70 | echo -e " -r, --renderproject FILE \t\t\tRender the specified project" 71 | echo -e " -t, --template FILE [-s, -saveas FILE]\tOpen a new project, using FILE as template" 72 | echo -e " \t\t\t\t\t\t- optionally saving the new project as FILE" 73 | exit 0 74 | ;; 75 | -a|--audiocfg) 76 | args+="-audiocfg " 77 | ;; 78 | -c|--cfgfile) 79 | filename="$2" 80 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 81 | filename="`convert_path_to_win "$filename"`" 82 | args+="-cfgfile $filename " 83 | shift 84 | shift 85 | else 86 | echo "Usage: `basename "$0"` --cfgfile FILE" 87 | exit 88 | fi 89 | ;; 90 | -n|--new) 91 | args+="-new " 92 | filename="$2" 93 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 94 | args+="`convert_path_to_win "$2"`" 95 | shift 96 | shift 97 | fi 98 | ;; 99 | -r|--renderproject) 100 | filename="$2" 101 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 102 | filename="`convert_path_to_win "$2"`" 103 | args+="-renderproject $filename " 104 | shift 105 | shift 106 | else 107 | echo "Usage: `basename "$0"` --renderproject FILE" 108 | exit 109 | fi 110 | ;; 111 | -t|--template) 112 | filename="$2" 113 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 114 | filename="`convert_path_to_win "$2"`" 115 | args+="-renderproject $filename " 116 | shift 117 | shift 118 | if [ "$1" = "-s" -o "$1" = "--saveas" ]; then 119 | filename="$2" 120 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 121 | filename="`convert_path_to_win "$2"`" 122 | args+="-saveas $filename " 123 | shift 124 | shift 125 | else 126 | echo "Usage: `basename "$0"` --template FILE --saveas FILE" 127 | exit 128 | fi 129 | fi 130 | else 131 | echo "Usage: `basename "$0"` --renderproject FILE" 132 | exit 133 | fi 134 | ;; 135 | -s|--saveas) 136 | echo "Usage: `basename "$0"` --template FILE --saveas FILE" 137 | exit 138 | ;; 139 | *) 140 | args+="'`convert_path_to_win "$1"`' " 141 | ;; 142 | esac 143 | shift # Check next set of parameters. 144 | done 145 | 146 | # Remove trailing space 147 | #args="${args:0:`expr length "$args" - 1`}" 148 | 149 | eval "wine '$ProgramFiles\REAPER\Reaper.exe' $args" 150 | -------------------------------------------------------------------------------- /scripts/run_reaper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert relative to absolute path 4 | appdir="$(cd "`dirname "$0"`"; pwd)" 5 | 6 | print_help() { 7 | echo "Usage: `basename "$0"` [OPTION...] [FILE.rpp | FILE.wav]" 8 | echo -e "\nOptions:" 9 | echo -e " -v, --version \t\t\t\tPrint the installed version number" 10 | echo -e " -a, --audiocfg \t\t\t\tShow the audio configuration settings" 11 | echo -e " -c, --cfgfile FILE \t\t\t\tLoad the specified config file" 12 | echo -e " -n, --new \t\t\t\t\tOpen a new project, use FILE if specified" 13 | echo -e " -r, --renderproject FILE \t\t\tRender the specified project" 14 | echo -e " -t, --template FILE [-s, -saveas FILE]\tOpen a new project, using FILE as template" 15 | echo -e " \t\t\t\t\t\t- optionally saving the new project as FILE" 16 | exit 0 17 | } 18 | 19 | SELFTEST=0 20 | case "$1" in 21 | -h|--help|-help) 22 | print_help 23 | ;; 24 | -s|--selftest|-selftest) 25 | SELFTEST=1 26 | ;; 27 | esac 28 | 29 | if [ -n "$LD_LIBRARY_PATH" ]; then 30 | LD_LIBRARY_PATH="$appdir/.winelib:$LD_LIBRARY_PATH" 31 | else 32 | LD_LIBRARY_PATH="$appdir/.winelib" 33 | fi 34 | export LD_LIBRARY_PATH 35 | 36 | if [ -n "$WINEDLLPATH" ]; then 37 | WINEDLLPATH="$appdir/.winelib:$WINEDLLPATH" 38 | else 39 | WINEDLLPATH="$appdir/.winelib" 40 | fi 41 | export WINEDLLPATH 42 | 43 | WINEPREFIX="$appdir/.wine" 44 | export WINEPREFIX 45 | 46 | WINEDEBUG="fixme-all" 47 | export WINEDEBUG 48 | 49 | # 50 | # Underscore prefixed variables are only used in this block to determine the non-underscored ones 51 | # 52 | 53 | ProgramFiles='C:\\Program Files' 54 | _PROGRAMFILES="$WINEPREFIX/drive_c/Program Files" 55 | _winsysdir="$WINEPREFIX/drive_c/windows/profiles/$USERNAME/Application Data" 56 | _PROFILESDIR="$WINEPREFIX/drive_c/windows/profiles" 57 | _APPDATA="$WINEPREFIX/drive_c/windows/profiles/$USERNAME/Application Data" 58 | 59 | if [ -d "$_PROGRAMFILES" ] || \ 60 | [ -d "$_winsysdir" ] || \ 61 | [ -d "$_PROFILESDIR" ] || \ 62 | [ -d "$_APPDATA" ]; then 63 | APPDATA=$_APPDATA 64 | else 65 | # Get the Windows paths from registry since they are different according to locale 66 | ProgramFiles="$(grep '"ProgramFiles"=' "$appdir/.wine/system.reg" | cut -d\" -f4- | cut -d\" -f1)" 67 | if [[ -z $(echo $ProgramFiles) ]]; then 68 | ProgramFiles="$(grep '"ProgramFilesDir"=' "$appdir/.wine/system.reg" | cut -d\" -f4- | cut -d\" -f1)" 69 | if [[ -z $(echo $ProgramFiles) ]]; then 70 | ProgramFiles='C:\Program Files' 71 | echo "WARNING: The system registry didn't contain the path to ProgramFiles, defaulting to \""$ProgramFiles'".' 72 | fi 73 | fi 74 | _winsysdir="$(grep '"winsysdir"=' "$appdir/.wine/system.reg" | cut -d\" -f4- | cut -d\" -f1)" 75 | _winsysdir="$("$appdir"/.winepath.sh -u "$_winsysdir")" 76 | _APPDATA="$(grep '"APPDATA"=' "$appdir/.wine/system.reg" | cut -d\" -f4- | cut -d\" -f1)" 77 | _LOCALAPPDATA="$(grep '"LOCALAPPDATA"=' "$appdir/.wine/system.reg" | cut -d\" -f4- | cut -d\" -f1)" 78 | _APPDATA="$(winepath -u "$_APPDATA")" 79 | _LOCALAPPDATA="$(winepath -u "$_LOCALAPPDATA")" 80 | _winsysdir="$("$appdir"/.winepath.sh -u "$_APPDATA")" 81 | 82 | _PROFILESDIR="$(dirname "`dirname "$APPDATA"`")" 83 | if [[ "$_PROFILESDIR" == "." ]]; then 84 | _PROFILESDIR="$(dirname "$(dirname "`dirname "$_LOCALAPPDATA"`")")" 85 | fi 86 | _APPDATANAME="$(basename "$_APPDATA")" 87 | 88 | _USERPROFILE="$PROFILESDIR/$USER" 89 | APPDATA="$_USERPROFILE/$_APPDATANAME" 90 | fi 91 | 92 | if [[ $SELFTEST == 1 ]]; then 93 | echo "ProgramFiles: "$ProgramFiles 94 | echo "winsysdir: "$_winsysdir 95 | echo "PROFILESDIR: "$_PROFILESDIR 96 | echo "APPDATA: "$APPDATA 97 | exit 98 | fi 99 | args="$@" 100 | 101 | convert_path_to_win() { 102 | filename="$1" 103 | if [ "${filename:1:2}" = ':\' ]; then 104 | echo -n "$filename" 105 | else 106 | echo -n "$(winepath -w "$filename")" 107 | fi 108 | } 109 | 110 | print_version() { 111 | cat "$(winepath -u "$ProgramFiles"'\\REAPER')/whatsnew.txt" | cut -s -d\ -f1 | head -n1 | cut -dv -f2- 112 | } 113 | 114 | print_latest_changelog() { 115 | wget -qO - 'http://reaper.fm/whatsnew.txt' 116 | } 117 | 118 | print_latest_version() { 119 | print_latest_changelog | cut -s -d\ -f1 | head -n1 | cut -dv -f2- 120 | } 121 | 122 | check_for_new_version() { 123 | check=true 124 | # If there's a config file 125 | if [ -e "$APPDATA/REAPER/REAPER.ini" ]; then 126 | echo "Config exists" 127 | # and it has the option for checking for new version 128 | setting="$(cat "$APPDATA/REAPER/REAPER.ini" | grep -oE '^verchk=([01])' | cut -d= -f2)" 129 | # and that options says "don't check", then don't 130 | test "x$setting" = "x0" && check=false 131 | fi 132 | 133 | if $check; then 134 | if [[ "$(print_latest_version)" > "$(print_version)" ]]; then 135 | echo "Update!" 136 | fi 137 | fi 138 | } 139 | 140 | args="" 141 | 142 | # If Reaper hasn't been set-up, do it 143 | if [ ! -e "$HOME/.config/$(cat "$appdir/.configuration_dir")" ]; then 144 | if [ ! -e "$APPDATA/REAPER/REAPER.ini" ]; then 145 | "$appdir/.update_config.sh" 146 | 147 | test $# -eq 0 && args="'$ProgramFiles\\REAPER\\BradSucks_MakingMeNervous\\BradSucks_MakingMeNervous.RPP'" 148 | fi 149 | fi 150 | 151 | 152 | while [ $# -gt 0 ]; do 153 | case "$1" in 154 | -h|--help|-help) 155 | print_help 156 | ;; 157 | -v|--version) 158 | print_version 159 | exit 0 160 | ;; 161 | -l|--latest-version) 162 | print_latest_version 163 | exit 0 164 | ;; 165 | --check-version) 166 | check_for_new_version 167 | exit 0 168 | ;; 169 | -a|--audiocfg) 170 | args+="-audiocfg " 171 | ;; 172 | -c|--cfgfile) 173 | filename="$2" 174 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 175 | filename="`convert_path_to_win "$filename"`" 176 | args+="-cfgfile $filename " 177 | shift 178 | shift 179 | else 180 | echo "Usage: `basename "$0"` --cfgfile FILE" 181 | exit 182 | fi 183 | ;; 184 | -n|--new) 185 | args+="-new " 186 | filename="$2" 187 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 188 | args+="'`convert_path_to_win "$2"`'" 189 | shift 190 | shift 191 | fi 192 | ;; 193 | -r|--renderproject) 194 | filename="$2" 195 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 196 | filename="`convert_path_to_win "$2"`" 197 | args+="-renderproject '$filename' " 198 | shift 199 | shift 200 | else 201 | echo "Usage: `basename "$0"` --renderproject FILE" 202 | exit 203 | fi 204 | ;; 205 | -t|--template) 206 | filename="$2" 207 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 208 | filename="`convert_path_to_win "$2"`" 209 | args+="-renderproject '$filename' " 210 | shift 211 | shift 212 | if [ "$1" = "-s" -o "$1" = "--saveas" ]; then 213 | filename="$2" 214 | if [ -n "$filename" -a "${filename:0:1}" != "-" ]; then 215 | filename="`convert_path_to_win "$2"`" 216 | args+="-saveas '$filename' " 217 | shift 218 | shift 219 | else 220 | echo "Usage: `basename "$0"` --template FILE --saveas FILE" 221 | exit 222 | fi 223 | fi 224 | else 225 | echo "Usage: `basename "$0"` --renderproject FILE" 226 | exit 227 | fi 228 | ;; 229 | -s|--saveas) 230 | echo "Usage: `basename "$0"` --template FILE --saveas FILE" 231 | exit 232 | ;; 233 | *) 234 | args+="'`convert_path_to_win "$1"`' " 235 | ;; 236 | esac 237 | shift # Check next set of parameters. 238 | done 239 | 240 | # Remove trailing space 241 | #args="${args:0:`expr length "$args" - 1`}" 242 | 243 | #if [ $("$appdir/.update_checker.py"; echo $?) == 255 ]; then 244 | 245 | eval "wine '$ProgramFiles\REAPER\Reaper.exe' $args" 246 | 247 | -------------------------------------------------------------------------------- /scripts/setup_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source "$(dirname "$(readlink -f "$0")")"/_functions.sh 4 | 5 | # Convert relative to absolute paths 6 | appdir="$(cd "$1"; pwd)" 7 | 8 | WINEPREFIX="$appdir/.wine" 9 | export WINEPREFIX 10 | 11 | # Get the Windows paths from registry since they are different according to locale 12 | ProgramFiles="$(getProgramFiles)" 13 | APPDATA="$(getAppData)" 14 | 15 | if [ -d "$appdir/.wine" ]; then 16 | 17 | configpath="$APPDATA/REAPER" 18 | programpath="$ProgramFiles/REAPER" 19 | 20 | echo "Setting up Reaper installation directory." 21 | # if $appdir/reaper doesn't exist 22 | if [ ! -e "$appdir/reaper" ]; then 23 | # Link C:\Program Files\REAPER to $appdir/reaper 24 | ln -s "$programpath" "$appdir/reaper" 25 | fi 26 | for dir in "ColorThemes" "Data" "Effects" "KeyMaps" "Plugins"; do 27 | # if $appdir/$dir doesn't exist 28 | if [ ! -e "$appdir/$dir" ]; then 29 | # Link $appdir/reaper/$dir to $appdir/$dir 30 | ln -s "$appdir/reaper/$dir" "$appdir/$dir" 31 | fi 32 | done 33 | else 34 | echo "ERROR: Installation is borked: No .wine directory." 35 | exit 1 36 | fi 37 | -------------------------------------------------------------------------------- /scripts/setup_shortcuts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert relative to absolute path 4 | appdir="$(cd "$1"; pwd)" 5 | 6 | if [ ! -d "$appdir/.wine" ]; then 7 | echo "ERROR: Reaper doesn't seem to be properly installed." 8 | exit 1 9 | fi 10 | 11 | reaperdesktopfile="[Desktop Entry] 12 | Categories=AudioVideo 13 | Encoding=UTF-8 14 | Name=Reaper 15 | GenericName=Digital Audio Workstation 16 | Comment=Audio production without limits 17 | Type=Application 18 | Terminal=False 19 | Exec=$appdir/reaper.sh 20 | Icon=reaper 21 | MimeType=application/x-reaper-project;application/x-reaper-project-backup;application/x-reaper-peakfile;" 22 | 23 | vsttooldesktopfile="[Desktop Entry] 24 | Categories=AudioVideo 25 | Encoding=UTF-8 26 | Name=LinReaper Options 27 | Comment=Manage your LinReaper Reaper installation 28 | Type=Application 29 | Terminal=False 30 | Exec=$appdir/linreapercfg.py 31 | Icon=reaper" 32 | 33 | 34 | echo "Installing menu shortcuts and file associations." 35 | 36 | if [ ! -e "$HOME/.local/share/applications" ]; then 37 | mkdir -p "$HOME/.local/share/applications"; 38 | fi 39 | echo "$reaperdesktopfile" > "$HOME/.local/share/applications/Reaper.desktop" 40 | echo "$vsttooldesktopfile" > "$HOME/.local/share/applications/LinReaperCfg.desktop" 41 | 42 | if [ -e "$HOME/.local/share/applications/VSTTool.desktop" ]; then 43 | rm "$HOME/.local/share/applications/VSTTool.desktop" 44 | fi 45 | 46 | update-desktop-database "$HOME/.local/share/applications" 47 | # Update OpenBox menu as well, if running 48 | if [ ! -z "$(ps -A | grep openbox)" ]; then 49 | openbox --reconfigure & 50 | fi 51 | -------------------------------------------------------------------------------- /scripts/setup_wineasio.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert relative to absolute path 4 | tempdir="$(cd "`dirname "$0"`"; pwd)" 5 | appdir="$(cd "$1"; pwd)" 6 | 7 | if [ -n "$LD_LIBRARY_PATH" ]; then 8 | LD_LIBRARY_PATH="$appdir/.winelib:$LD_LIBRARY_PATH" 9 | else 10 | LD_LIBRARY_PATH="$appdir/.winelib" 11 | fi 12 | export LD_LIBRARY_PATH 13 | 14 | if [ -n "$WINEDLLPATH" ]; then 15 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib:$WINEDLLPATH" 16 | else 17 | WINEDLLPATH="$appdir/.winelib:$appdir/.winelib" 18 | fi 19 | export WINEDLLPATH 20 | 21 | if [ -d "$appdir" ]; then 22 | if [ -d "$appdir/.winelib" ]; then 23 | echo "Installing WineAsio to the Reaper installation dir." 24 | 25 | cp "$tempdir/wineasio-0.8.0.dll.so" "$appdir/.winelib/wineasio.dll.so" 26 | 27 | env HOME="$appdir" regsvr32 "$appdir/.winelib/wineasio.dll.so" 28 | # If it failed, ask permission to install WineAsio to /usr/lib/wine 29 | if [ $? != 0 ]; then 30 | echo -n "Asking permission to install WineAsio system-wide instead" 31 | if which zenity &> /dev/null; then 32 | echo "." 33 | if zenity --question --text="WineAsio failed to install to the local Reaper installation.\nWould you like to install WineAsio version 0.7.4 to /usr/lib/wine instead?\n\nNote that this will require your administrator password." --ok-label="Ok, install system wide" --cancel-label="No thanks"; then 34 | gksu --description "LinReaper WineAsio installation" cp "$tempdir/wineasio-0.7.4.dll.so" "/usr/lib/wine/wineasio.dll.so" 35 | regsvr32 wineasio.dll 36 | fi 37 | else 38 | echo -e "... failed.\nZenity isn't installed, can't ask.\n\nIf you want to install WineAsio system-wide, run the following commands from a terminal:\n\tsudo cp \"$appdir/.winelib/wineasio.dll.so\" /usr/lib/wine/\n\tregsvr32 wineasio.dll" 39 | fi 40 | fi 41 | fi 42 | else 43 | echo "ERROR: The install directory is missing, can't continue." 44 | exit 1 45 | fi 46 | -------------------------------------------------------------------------------- /scripts/update_checker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2007-2011 Christian Dannie Storgaard 5 | # 6 | # AUTHOR: 7 | # Christian Dannie Storgaard 8 | # 9 | 10 | from __future__ import print_function 11 | 12 | import gtk, pango, gobject 13 | import os, sys, subprocess, threading, time 14 | import urllib2 15 | 16 | 17 | def widget_get_char_width(widget): 18 | pango_context = widget.get_pango_context() 19 | return int(pango.PIXELS( 20 | pango_context.get_metrics( 21 | pango_context.get_font_description() 22 | ).get_approximate_char_width())) 23 | 24 | def widget_get_char_height(widget): 25 | """ 26 | Return maximum height in pixels of a single character. 27 | We create a Pango Layout, put in a line of lowercase+uppercase letters 28 | and read the height of the line.""" 29 | pango_layout = pango.Layout(widget.get_pango_context()) 30 | pango_layout.set_text(sys.modules['string'].ascii_letters) 31 | extents = pango_layout.get_line(0).get_pixel_extents() 32 | return int(extents[0][3] - extents[0][1]) 33 | 34 | class Dialog(gtk.Dialog): 35 | def __init__(self): 36 | 37 | gtk.Dialog.__init__(self, 38 | title = "Checking if there's a new version of Reaper available...", 39 | ) 40 | 41 | self.scrolledwindow = gtk.ScrolledWindow() 42 | self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) 43 | self.scrolledwindow.set_size_request( 44 | widget_get_char_width(self.scrolledwindow)*120, 45 | widget_get_char_height(self.scrolledwindow)*10 46 | ) 47 | 48 | self.textview = gtk.TextView() 49 | self.textview.get_buffer().set_text("Checking...") 50 | fontdescr = pango.FontDescription('monospace 8') 51 | self.textview.modify_font(fontdescr) 52 | self.textview.set_cursor_visible(False) 53 | self.scrolledwindow.add(self.textview) 54 | 55 | self.vbox.pack_start(self.scrolledwindow) 56 | 57 | self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) 58 | 59 | self.set_default_response(gtk.RESPONSE_CANCEL) 60 | 61 | self.button_cancel = self.action_area.get_children()[0] 62 | self.button_cancel.connect('clicked', self.__cancel_clicked) 63 | 64 | self.show_all() 65 | 66 | self.errorlog = "" 67 | self.return_code = 0 68 | self.changelog = None 69 | self.thread = start_thread(self.get_changelog, self.show_changes) 70 | 71 | 72 | def __cancel_clicked(self, button): 73 | try: 74 | gtk.main_quit() 75 | self.destroy() 76 | except: 77 | pass 78 | exit(self.return_code) 79 | 80 | def get_changelog(self): 81 | self.current_version = get_current_version() 82 | #self.changelog = 'v4.30 - ' # for testing 83 | self.changelog = get_changelog() 84 | print(self.changelog) 85 | 86 | def show_changes(self): 87 | self.new_version = float(self.changelog.split(' ')[0][1:]) 88 | if float(self.current_version) < self.new_version: 89 | self.button_cancel.set_label('gtk-cancel') 90 | self.button_cancel.set_use_stock(True) 91 | self.button_cancel.set_label("Ignore") 92 | self.set_title("There's a new version of Reaper available") 93 | self.add_button("Go to download page", gtk.RESPONSE_OK) 94 | self.add_button("Update", gtk.RESPONSE_YES) 95 | self.button_update = self.action_area.get_children()[0] 96 | self.button_web = self.action_area.get_children()[1] 97 | gtk.settings_get_default().set_property('gtk-alternative-button-order', True) 98 | self.set_alternative_button_order([ 99 | gtk.RESPONSE_OK, gtk.RESPONSE_YES, gtk.RESPONSE_CANCEL 100 | ]) 101 | self.scrolledwindow.set_size_request( 102 | widget_get_char_width(self.scrolledwindow)*120, 103 | widget_get_char_height(self.scrolledwindow)*min(len(self.changelog.split('\n')), 10) 104 | ) 105 | self.textview.get_buffer().set_text(self.changelog) 106 | 107 | self.button_update.connect('clicked', self.update_clicked) 108 | self.button_web.connect('clicked', self.web_clicked) 109 | else: 110 | self.destroy() 111 | exit(0) 112 | 113 | 114 | def web_clicked(self, button): 115 | # Go to download page 116 | subprocess.Popen( 117 | 'xdg-open http://reaper.fm/download.php', shell = True 118 | ) 119 | self.destroy() 120 | exit(0) 121 | 122 | def update_clicked(self, button): 123 | self.button_cancel.set_sensitive(False) 124 | self.label = gtk.Label("Downloading Reaper {0}".format(self.new_version)) 125 | self.label.set_alignment(0.0, 0.5) 126 | self.progressbar = gtk.ProgressBar() 127 | self.progressbar.set_pulse_step(0.01) 128 | self.vbox.pack_start(self.label) 129 | self.vbox.pack_start(self.progressbar) 130 | self.show_all() 131 | run( 132 | #get_install_dir()+"/scripts/get_reaper.sh", 133 | "echo 'Hello'", 134 | [], 135 | self.do_install_run, 136 | self.do_error, 137 | self.progressbar 138 | ) 139 | 140 | def do_install_run(self): 141 | self.label.set_text("Installing Reaper {0}".format(self.new_version)) 142 | run( 143 | get_install_dir()+"/scripts/run_install.sh", 144 | [get_install_dir()], 145 | self.do_install_finish, 146 | self.do_error, 147 | self.progressbar 148 | ) 149 | 150 | def do_install_finish(self): 151 | self.label.set_text("Reaper updated succesfully to version {0}".format(self.new_version)) 152 | self.progressbar.set_fraction(1.0) 153 | self.button_cancel.set_sensitive(True) 154 | self.button_cancel.set_label('gtk-ok') 155 | self.button_cancel.set_use_stock(True) 156 | self.button_cancel.set_label("Run Reaper") 157 | self.return_code = -1 158 | 159 | def do_error(self): 160 | main.widgets['label_install'].set_text("An error has occured.\nReaper wasn't updated.") 161 | self.button_cancel.set_sensitive(True) 162 | self.button_cancel.set_label('gtk-ok') 163 | self.button_cancel.set_use_stock(True) 164 | self.button_cancel.set_label("Run old Reaper") 165 | self.progressbar.hide() 166 | 167 | 168 | 169 | 170 | 171 | def run(command, arguments, finished_function, error_function, progressbar=None): 172 | thread = threading.Thread(target=run_process, args=[command, arguments, finished_function, error_function, progressbar]) 173 | thread.daemon = True 174 | thread.start() 175 | 176 | def run_process(command, arguments, finished_function, error_function, progressbar=None): 177 | #print "Running command:",command 178 | p = subprocess.Popen(command + ' ' + ' '.join(arguments), shell=True, 179 | stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) 180 | 181 | output = "" 182 | while p.poll() == None: 183 | line = os.read(p.stdout.fileno(), 32) 184 | procent = None 185 | if line: 186 | output += line 187 | lastline = output.split("\n")[-1].strip() 188 | if lastline and '%' in lastline: 189 | if len(lastline.split('%')) > 2: 190 | procent = lastline.split('%')[-2].split()[-1] 191 | else: 192 | procent = lastline.split('%')[0].split()[0] 193 | if progressbar is not None: 194 | if procent: 195 | gtk.gdk.threads_enter() 196 | progressbar.set_fraction( float(procent) / 100 ) 197 | gtk.gdk.threads_leave() 198 | else: 199 | gtk.gdk.threads_enter() 200 | progressbar.pulse() 201 | gtk.gdk.threads_leave() 202 | sys.stdout.write(line) 203 | 204 | main.errorlog += output 205 | 206 | if p.returncode != 0: 207 | error_function() 208 | else: 209 | finished_function() 210 | 211 | 212 | def start_thread(function, finished_function): 213 | thread = threading.Thread(target=function) 214 | thread.daemon = True 215 | thread.start() 216 | while thread.isAlive(): 217 | while gtk.events_pending(): 218 | gtk.main_iteration() 219 | time.sleep(0.1) 220 | finished_function() 221 | 222 | 223 | def get_internet_available(): 224 | if len(subprocess.Popen( 225 | 'which ip', shell = True, stdout=subprocess.PIPE 226 | ).communicate()[0].strip()): 227 | # Try testing for IPv4 with the ip command first 228 | if len(subprocess.Popen( 229 | 'ip -4 route', shell = True, stdout=subprocess.PIPE 230 | ).communicate()[0]): 231 | return True 232 | return False 233 | 234 | 235 | def get_install_dir(): 236 | path = os.path.dirname(sys.argv[0]) 237 | if not os.path.exists(os.path.join(path, '.wine')): 238 | path = os.path.expanduser('~/.local/reaper') 239 | return path 240 | 241 | 242 | def get_wine_env(key): 243 | value = subprocess.Popen( 244 | 'grep \'"{key}"=\' {path}/.wine/system.reg'.format( 245 | key = key, 246 | path = get_install_dir() 247 | ), shell = True, stdout=subprocess.PIPE 248 | ).communicate() 249 | value = value[0].strip().split('="')[1][0:-1] 250 | return value 251 | 252 | 253 | def get_filename(path, filename): 254 | """Get the filename of a basename regardless of case. 255 | Returns "path/filename" if none was found.""" 256 | try: 257 | matches = [ 258 | name for name 259 | in os.listdir(path) 260 | if name.lower() == filename.lower() 261 | ] 262 | if len(matches): 263 | return os.path.join(path, matches[0]) 264 | else: 265 | return os.path.join(path, filename) 266 | except OSError: 267 | return os.path.join(path, filename) 268 | 269 | 270 | def get_reaper_dir(): 271 | if 'ProgramFilesUnix' in os.environ: 272 | path_program_files = os.environ['ProgramFilesUnix'] 273 | else: 274 | path_program_files = get_wine_env('ProgramFiles') 275 | path_program_files = path_program_files.split('C:\\\\')[1] 276 | 277 | return get_filename( 278 | os.path.join(get_install_dir(), '.wine', 'drive_c', path_program_files), 279 | 'REAPER' 280 | ) 281 | 282 | 283 | def get_online_check_setting(): 284 | if 'APPDATA' in os.environ: 285 | path_settings = os.environ['APPDATA'] 286 | else: 287 | path_settings = get_wine_env('APPDATA') 288 | path_settings = path_settings.split('C:\\\\')[1].replace('\\', '/') 289 | 290 | filename = get_filename( 291 | os.path.join(get_install_dir(), '.wine', 'drive_c', path_settings), 292 | 'REAPER' 293 | ) 294 | filename = get_filename(filename, 'REAPER.ini') 295 | 296 | with open(filename, 'r') as _file: 297 | setting = [ 298 | line for line 299 | in _file 300 | if line.startswith('verchk=') 301 | ] 302 | if len(setting) and setting[0].strip().split('=')[1] == '1': 303 | return True 304 | else: 305 | return False 306 | 307 | 308 | def get_current_version(): 309 | with open(os.path.join(get_reaper_dir(), 'whatsnew.txt'), 'r') as _file: 310 | version_current = _file.read().split(' ')[0][1:] 311 | return version_current 312 | 313 | 314 | def get_changelog(): 315 | try: 316 | _file = urllib2.urlopen('http://reaper.fm/whatsnew.txt') 317 | changelog = [] 318 | for line in _file: 319 | if len(line.strip()): 320 | changelog.append(line) 321 | else: 322 | break 323 | return ''.join(changelog) 324 | except: 325 | return 'v0.0 - Error' 326 | 327 | 328 | if __name__ == "__main__": 329 | try: 330 | if get_online_check_setting() and get_internet_available(): 331 | gobject.threads_init() 332 | gtk.gdk.threads_init() 333 | gtk.gdk.threads_enter() 334 | main = Dialog() 335 | gtk.main() 336 | gtk.gdk.threads_leave() 337 | exit(main.return_code) 338 | finally: 339 | pass 340 | 341 | -------------------------------------------------------------------------------- /scripts/update_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert relative to absolute path 4 | appdir="$(cd "`dirname "$0"`"; pwd -P)" 5 | 6 | source "$appdir/.export_wine_environment.sh" "$appdir" 7 | 8 | 9 | # Name of the dir in $HOME/.config/ 10 | # Defaults to the basename of the installation dir (usually "reaper") 11 | if [ -z "$configname" ]; then configname="$(basename $appdir)"; else configname="$1"; fi 12 | 13 | 14 | check_home_config() { 15 | # If $HOME/.config/$configname does not exist, create it 16 | if [ ! -e "$HOME/.config/$configname" ]; then 17 | mkdir -p "$HOME/.config/$configname" 18 | 19 | # Create the default configuration file for Reaper in it 20 | "$appdir"/.REAPER.ini.default.sh > "$HOME/.config/$configname/REAPER.ini" 21 | 22 | # Create the default vst directory 23 | mkdir -p "$HOME/.config/$configname/vst" 24 | 25 | ln -sf "$HOME/.config/reaper" "$APPDATA/REAPER" 26 | fi 27 | } 28 | 29 | link_winedirs_to_user() { 30 | # Link Windows profile dirs to $HOME 31 | for x in "DESKTOP-$WinDesktopUnix" "DOCUMENTS-$WinMyDocumentsUnix" "MUSIC-$WinMyMusicUnix" "PICTURES-$WinMyPicturesUnix" "VIDEOS-$WinMyVideosUnix"; do 32 | dir="$(echo "$x" | cut -d- -f2-)" 33 | name="$(echo "$x" | cut -d- -f1)" 34 | # Get the matching XDG DIR for this dir 35 | xdgdir="$(cat ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs | grep -i $name | cut -d= -f2-)" 36 | # Remove the quotes around it 37 | xdgdir="$(echo ${xdgdir:1:`expr length "$xdgdir" - 2`})" 38 | # Remove any trailing / 39 | xdgdir="${xdgdir/%\/}" 40 | name="$(basename "$dir")" 41 | # If fx. $HOME/My Documents exists, link to that 42 | if [ -e "$HOME/$name" ]; then 43 | lindir="$HOME/$name" 44 | # If instead fx. $HOME/Documents exists, link to that 45 | elif [ -e "$HOME/$(echo "$name" | cut -d\ -f2-)" ]; then 46 | lindir="$HOME/$(echo "$name" | cut -d\ -f2-)" 47 | # Else, link to XDG_DOCUMENTS_DIR (or similar XDG dir) or $HOME 48 | else 49 | if [ -z "$xdgdir" ]; then lindir=$HOME; else lindir="$(eval echo $xdgdir)"; fi 50 | fi 51 | echo "Linking \"$(basename "$dir")\" to \"$lindir\"." 52 | ln -sf "$lindir" "$dir" 53 | 54 | xdgdir="" 55 | done 56 | } 57 | 58 | check_home_config 59 | 60 | link_winedirs_to_user 61 | 62 | echo "$configname" > "$appdir/.configuration_dir" 63 | -------------------------------------------------------------------------------- /scripts/vst.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | 26 | 29 | 33 | 37 | 38 | 41 | 45 | 49 | 50 | 53 | 57 | 61 | 62 | 65 | 69 | 73 | 74 | 77 | 81 | 85 | 86 | 89 | 93 | 97 | 98 | 101 | 105 | 109 | 110 | 113 | 117 | 121 | 122 | 125 | 129 | 133 | 134 | 137 | 141 | 145 | 146 | 149 | 153 | 157 | 158 | 165 | 172 | 179 | 189 | 199 | 209 | 219 | 222 | 227 | 228 | 238 | 247 | 256 | 265 | 274 | 283 | 290 | 294 | 295 | 304 | 313 | 322 | 332 | 342 | 352 | 362 | 372 | 382 | 383 | 406 | 414 | 415 | 417 | 418 | 420 | image/svg+xml 421 | 423 | 424 | 425 | 426 | 431 | 441 | 442 | 447 | 452 | 457 | 458 | 463 | 468 | 473 | 478 | 483 | 484 | 489 | 499 | 509 | 510 | 515 | 520 | 528 | 529 | 530 | -------------------------------------------------------------------------------- /scripts/vst_installer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Convert relative to absolute path 4 | appdir="$(cd "`dirname "$0"`"; pwd)" 5 | 6 | WINEPREFIX="$appdir/.wine" 7 | export WINEPREFIX 8 | 9 | WINEDEBUG="fixme-all" 10 | export WINEDEBUG 11 | 12 | ###################################################################### 13 | ### Make sure that the VST installer gets the right VST directory ### 14 | 15 | # Get the Windows paths from registry since they are different according to locale 16 | eval ProgramFiles="$(less "$appdir/.wine/system.reg" | grep '"ProgramFiles"=' | cut -d= -f2-)" 17 | UnixProgramFiles="$(winepath -u "$ProgramFiles")" 18 | 19 | UnixVSTPath="$(cd "$appdir/.wine/drive_c/windows/profiles/$USER/My Documents/.config/reaper/vst/"; pwd -P)" 20 | 21 | # Create registry keys for the correct VST install path 22 | registryfile="$(tempfile -s .reg)" 23 | 24 | echo "Windows Registry Editor Version 5.00 25 | 26 | [HKEY_CURRENT_USER\\Software\\VST] 27 | \"VSTPluginsPath\"=\"C:\\\\windows\\\\profiles\\\\$USER\\\\My Documents\\\\.config\\\\reaper\\\\vst\" 28 | [HKEY_LOCAL_MACHINE\\Software\\VST] 29 | \"VSTPluginsPath\"=\"C:\\\\windows\\\\profiles\\\\$USER\\\\My Documents\\\\.config\\\\reaper\\\\vst\"" > "$registryfile" 30 | 31 | 32 | regedit "$registryfile" 33 | VST_PATH="C:\\windows\\profiles\\$USER\\My Documents\\.config\\reaper\\vst" 34 | export VST_PATH 35 | 36 | # Make Shell Pattern Matching case-insensitive, so we are sure to find the Steinberg path 37 | shopt -s nocaseglob 38 | # If there is no Steinberg VST path, then we link to LinReapers 39 | # The "[s]" causes bash to use Pattern Matching, and so, be case-insensitive. 40 | if [ ! -e "$UnixProgramFiles/Steinberg/VstPlugin"[s] ]; then 41 | if [ ! -e "$UnixProgramFiles/Steinber"[g] ]; then 42 | mkdir -p "$UnixProgramFiles/Steinberg" 43 | fi 44 | ln -s "$UnixVSTPath" "$UnixProgramFiles/Steinberg/VstPlugins" 45 | fi 46 | 47 | ### Made sure that the VST installer gets the right VST directory ### 48 | ###################################################################### 49 | 50 | 51 | # Run the VST installer 52 | if [ "$(echo ${1/*./} | tr [:upper:] [:lower:])" == "msi" ]; then 53 | wine start /Unix "$1" 54 | else 55 | wine "$1" 56 | fi 57 | -------------------------------------------------------------------------------- /scripts/wineasio-0.7.4.dll.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/wineasio-0.7.4.dll.so -------------------------------------------------------------------------------- /scripts/wineasio-0.8.0.dll.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cybolic/LinReaper/696e3c623288da655e70d472e30b189a7ac8f3a9/scripts/wineasio-0.8.0.dll.so -------------------------------------------------------------------------------- /scripts/winepath.sh: -------------------------------------------------------------------------------- 1 | #!/bin/dash 2 | # 3 | # POSIX Shell script replacement for winepath 4 | # 5 | # Copyright (c) 2011 Christian Dannie Storgaard 6 | # Released under the GNU Lesser General Public License version 2.1 or later 7 | # 8 | ################################################################################ 9 | # 10 | # Note that this script varies slightly from winepath in that it will not output 11 | # Windows paths containing characters that are illegal on a Windows filesystem. 12 | # Any such character will be replaced by the character tilde (~). 13 | # 14 | # You can also use Windows environment variables in a path as well as wildcards. 15 | # winepath supports neither for some reason. 16 | # E.g. '%ProgramFiles%/foobar~/~.exe' 17 | # 18 | ################################################################################ 19 | # 20 | # Notes about string manipulation to clear things up a bit: 21 | # 22 | # Every character but first: 23 | # ${var#?} 24 | # 25 | # Every character but last: 26 | # ${var%?} 27 | # 28 | # First character (string up until every-character-but-first): 29 | # ${var%"${var#?}"} 30 | # 31 | # Last character (string after every-character-but-last): 32 | # ${var#"${var%?}"} 33 | # 34 | # Replace substring: 35 | # (string up until $search_str + $replacement_str + string after $search_str) 36 | # ${var%%$search_str*}$replacement_str${var#*$search_str} 37 | 38 | 39 | w_get_reg_env() 40 | { 41 | grep -i "\"$1\"=\"" ${WINEPREFIX:-~/.wine}/*.reg | head -n 1 | \ 42 | cut -d\" -f4- | cut -d\" -f1 43 | } 44 | 45 | w_path_wintounix() 46 | { 47 | case "$1" in 48 | *':\'*|*%*) 49 | case "$1" in 50 | *':\'*) 51 | # Get drive letter in lower and upper case 52 | drive="${1%"${1#?}"}" 53 | drive_lower="`echo $drive | tr [:upper:] [:lower:]`" 54 | drive_upper="`echo $drive | tr [:lower:] [:upper:]`" 55 | # Get the real location of the drive 56 | # NOTE: I prefer this output (the actual location), but winepath 57 | # returns just the link location so we do the same 58 | #drive_path="`readlink -mn ${WINEPREFIX:-~/.wine}/dosdevices/[$drive_lower,$drive_upper]:`" 59 | if test -x ${WINEPREFIX:-~/.wine}/dosdevices/$drive_lower: 60 | then 61 | drive_path="${WINEPREFIX:-$HOME/.wine}/dosdevices/$drive_lower:" 62 | elif test -x ${WINEPREFIX:-~/.wine}/dosdevices/$drive_upper: 63 | then 64 | drive_path="${WINEPREFIX:-$HOME/.wine}/dosdevices/$drive_upper:" 65 | # If the drive isn't linked properly, return the same as winepath 66 | else 67 | echo "" 68 | return 0 69 | fi 70 | ;; 71 | *) 72 | drive_path="" 73 | esac 74 | # Replace backslashes with slashes, and remove duplicates 75 | path="`echo "$1" | sed -re 's,\\\+,/,g'`" 76 | # Get the rest of the path, without the drive 77 | path="`echo $path | sed -re 's,[a-zA-Z]:/+,,g'`" 78 | # Check if there are any {} characters, since that means a reg variable 79 | if test "`echo $path | tr -d '[%]'`" != "$path" 80 | then 81 | reg_key="`echo "$path" | grep -o '%.*%' | cut -d% -f2- | cut -d% -f1`" 82 | reg_value="`w_get_reg_env "$reg_key"`" 83 | reg_value="`w_path_wintounix "$reg_value"`" 84 | # Replace key name with converted value 85 | path="${path%%\%$reg_key*}$reg_value${path#*$reg_key\%}" 86 | fi 87 | # If a simple translation on \ to / will locate the location, return that 88 | if test -x "$drive_path/$path" 89 | then 90 | echo "$drive_path/$path" 91 | else 92 | # Didn't work, we'll have to look for the location 93 | dir_so_far="$drive_path" 94 | IFS="/" 95 | for dir_part in $path 96 | do 97 | test -z "$dir_part" && continue # skip empty parts 98 | found=false 99 | if test -x "$dir_so_far/$dir_part" 100 | then 101 | dir_so_far="$dir_so_far/$dir_part" 102 | found=true 103 | else 104 | match_start=false 105 | match_end=false 106 | # There's a wildcard at the end, use wildcard matching 107 | if test ${dir_part#"${dir_part%?}"} = '~' 108 | then 109 | search_part=${dir_part%%\~} 110 | match_start=true 111 | # There's a wildcard at the start, use wildcard matching 112 | elif test ${dir_part%"${dir_part#?}"} = '~' 113 | then 114 | search_part=${dir_part#*\~} 115 | match_end=true 116 | fi 117 | 118 | # Go through the directory looking for matches 119 | for dir_name in "$dir_so_far"/* "$dir_so_far"/.* 120 | do 121 | dir_name="`basename "$dir_name"`" 122 | # Match filename by its start 123 | if $match_start 124 | then 125 | if printf '%s\n' "$dir_name" | grep -qi "^$search_part" 126 | then 127 | # Use it 128 | dir_so_far="$dir_so_far/$dir_name" 129 | found=true 130 | break 131 | fi 132 | # Match filename by its ending 133 | elif $match_end 134 | then 135 | if printf '%s\n' "$dir_name" | grep -qi "$search_part$" 136 | then 137 | # Use it 138 | dir_so_far="$dir_so_far/$dir_name" 139 | found=true 140 | break 141 | fi 142 | # Match full filename 143 | else 144 | # If this dirname matches either exactly 145 | # or case insensitively 146 | if test \ 147 | "$dir_part" = "$dir_name" -o \ 148 | "`echo "$dir_part" | tr [:upper:] [:lower:]`" = \ 149 | "`echo "$dir_name" | tr [:upper:] [:lower:]`" 150 | then 151 | # Use it 152 | dir_so_far="$dir_so_far/$dir_name" 153 | found=true 154 | break 155 | fi 156 | fi 157 | done 158 | fi 159 | if ! $found 160 | then 161 | # This part wasn't found, return a simple conversion 162 | dir_so_far="$drive_path/$path" 163 | break 164 | fi 165 | done 166 | # Remove double slashes (can happen if the drive maps to /) 167 | printf '%s\n' "`echo "$dir_so_far" | sed -re 's,[/]+,/,g'`" 168 | fi 169 | ;; 170 | *) printf '%s/dosdevices/z:%s\n' "${WINEPREFIX:-$HOME/.wine}" "$1" ;; 171 | esac 172 | } 173 | 174 | w_path_unixtowin() 175 | { 176 | # Go through the mappings for the drives 177 | use_drive='' 178 | for drive_link in ${WINEPREFIX:-$HOME/.wine}/dosdevices/*: 179 | do 180 | case $drive_link in 181 | *::) continue ;; 182 | esac 183 | 184 | drive_in_case=${drive_link#*"dosdevices/"} 185 | drive_in_case=${drive_in_case%":"} 186 | drive="`echo $drive_in_case | tr [:upper:] [:lower:]`" 187 | mapping="`readlink -mn "$drive_link"`" 188 | # Check if the mapping uses the same format as the path 189 | same_mapping=false 190 | case "$mapping" in 191 | */drive_*) 192 | case "$1" in 193 | */.wine/drive_*) 194 | # Both drives are using the same format, we're good 195 | same_mapping=true 196 | ;; 197 | esac 198 | ;; 199 | esac 200 | if ! $same_mapping 201 | then 202 | prefix=${mapping%%"/drive_"*} 203 | new_mapping="$prefix/dosdevices/$drive:" 204 | if test -x $new_mapping 205 | then 206 | mapping=$new_mapping 207 | fi 208 | fi 209 | # If path starts with mapping, use this drive 210 | if test "$1" != "${1%%$mapping*}" 211 | then 212 | use_drive="`echo "$drive" | tr [:lower:] [:upper:]`" 213 | break 214 | fi 215 | done 216 | if test "$use_drive"x != ""x 217 | then 218 | # Strip mapping from beginning of path 219 | path=${1#*$mapping} 220 | else 221 | # Give a simple conversion of the path using Z as root 222 | use_drive="Z" 223 | case "$1" in 224 | /*) 225 | path="${1#?}" ;; 226 | *) 227 | dir_name="`dirname "$1"`" 228 | path="`cd "$dir_name"; pwd`/$1" 229 | path="${path#?}" 230 | ;; 231 | esac 232 | fi 233 | # Replace backslashes with tildes 234 | path="`echo "$path" | sed -re 's,\\\,~,g'`" 235 | # Replace illegal characters with a tilde 236 | path=`echo $path | sed -re 's,[<>:\"|?*],~,g'` 237 | # Convert separators to Windows separators 238 | path="`echo "$path" | sed -re 's,/+,\\\,g'`" 239 | printf '%s:\\%s\n' "$use_drive" "$path" 240 | } 241 | 242 | 243 | w_pathconv() 244 | { 245 | case "$1" in 246 | -u) w_path_wintounix "$2" ;; 247 | -w) w_path_unixtowin "$2" ;; 248 | esac 249 | } 250 | 251 | 252 | w_pathconv "$@" 253 | 254 | --------------------------------------------------------------------------------