Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env tclsh
- # execute in wish from path \
- #exec wish "$0" ${1+"$@"}
- # ======================== LINVST BLASTER =========================
- # ==================== LINVST DLL BATCH LINKER ====================
- # by a linvst user
- #
- # READ THIS INTRODUCTION BEFORE ATTEMPTING TO USE IT
- #
- # IF YOU DON'T RUN LINUX, THIS IS NONE OF YOUR BUSINESS
- #
- # ==================== HOW TO USE IT ===============================
- # This is a Tcl script. You must have Tcl 8.4.6 or later to use it.
- # Older versions of Tcl may work, but I am not sure they will.
- #
- # First, 'cd' to the directory that contains the DLL files of the
- # Windows plugins and run the command. All the *.dll files in the
- # working directory will be found and linked RECURSIVELY. Yes,
- # recursively, so make sure you're happy with the directory location
- # and structure before you run this script.
- #
- # Example:
- # $ cd /some/directory/with/a/truckload/of/plugins
- # $ linvstblast
- #
- # Tip: some file managers such as pcmanfm or spacefm let you press F4
- # to launch a terminal session in whatever directory it is displaying,
- # so you don't even have to 'cd' manually.
- #
- # After you run the command, a temporary file may be opened in a text
- # editor. I use Vim, but it is easy to edit the USER OPTIONS section
- # of this script and change it to another editor of your preference.
- # That will be your chance to edit the list of plugins that will be
- # linked to linvst. You can change that list or not. Your call.
- #
- # Unlike airwave (another Windows plugin DLL bridge for Linux), linvst
- # doesn't let you link to the plugins with some kind of alias or
- # alternative name. The name of the bridge .so file must be EXACTLY the
- # same as the name of the original .dll file. If you really must change
- # names, you will have to rename the .dll files first. Up to you. Most
- # plugins will work fine after being renamed. It's possible that one
- # or another will refuse to work, but that should be extremely rare.
- # Renaming is an awful lot of work though, hardly worth the trouble.
- #
- # Anyway,
- #
- # Your first providence before using this script is making sure you
- # have a copy of the linvst.so file stored in a predictable path. For
- # the sake of instruction, this documentation assumes you keep that
- # file as /usr/local/bin/linvst.so
- # Then you navigate to a target directory that contains many Windows
- # plugin .dll files and run the script.
- # linvstblast (this script) will then recursively traverse that target
- # directory and find all .dll files in it. Note that not all .dll files
- # are plugins, and the script will handle that problem to some extent.
- # More on that later.
- # For every .dll file that is found, the script will copy your linvst.so
- # file from /usr/local/bin/ over to the same directory as the .dll file
- # and rename that brand new copy of the linvst.so file so that it has
- # the exact same name as the .dll file except the extension will be .so
- # rather than .dll. That is just how linvst works.
- #
- # POSSIBLE CONFLICTS
- # When copying the linvst.so file over to each directory where a .dll
- # file is found, linvstblast performs two checks:
- #
- # 1) There is a USER OPTIONS section in the beginning of this script,
- # right after these instructions. You are the one supposed to maintain
- # it. Yes, you. Don't look around, I am talking to you. That section
- # contains a blacklist. It is a list of .dll files that might exist
- # inside any given directory inside the target directory and are
- # required by their parent plugins, but are not plugins themselves
- # therefore they must never be linked to linvst in any way.
- # Those little buggers are easy to spot once you try to add them to a
- # DAW thinking that you're adding plugins and they fail, and their names
- # also should give them away if you know anything about software.
- # It's too bad neither clue can be identified automatically by this
- # script. They're unpredictable. So our only recourse is to maintain a
- # blacklist. Once you find one of those pesky .dll files, add it to
- # the blacklist HERE, IN THIS SCRIPT, in the USER OPTIONS section of
- # this script so you never have to worry about that particular file
- # again, even if the same target directory is selected over and over
- # (because you have added new directories and plugins to it).
- # When copying the linvst.so file over to each directory where a .dll
- # file is found, linvstblast checks if the .dll file is included in the
- # blacklist, in which case the .dll file is excluded from the entire
- # operation.
- # Note: the blacklist check procedure is case insensitive, and the .dll
- # extensions are optional. You can write the extensions, but they are
- # always assumed anyway.
- #
- # 2) If linvstblast finds that a PLUGIN-NAME.so file already exists
- # whose name matches that of PLUGIN-NAME.dll, linvstblast checks
- # whether PLUGIN-NAME.so is a copy of the /usr/local/bin/linvst.so file.
- # If it is indeed a copy, then that plugin is already taken care of and
- # will be ignored. Such occurrence is never mentioned in any reports
- # or requests for confirmation. That would be very annoying.
- # If PLUGIN-NAME.so is not a copy of the /usr/local/bin/linvst.so file,
- # that occurrence will be added to a conflict report presented to you
- # before the end of the procedure and you will be offered the chance to
- # decide what to do about it.
- # The report will tell you exactly what to do. Just follow the
- # instructions on it, and everything will be fine.
- # The only caveat is that I only test these things on Vim. If you use
- # another text editor and it fails, you might want to try to inform me
- # of the problem. Who knows, I might even fix it. Or not.
- # Or you can just stick to Vim and stay out of trouble. It's what
- # grownups do.
- # If you use pico, Ok, I'll be merciful to you.
- # If you use emacs, bleh, you can fix the situation on your own. You
- # brought this fate upon yourself.
- #
- # OUTCOME
- # After running this highfallutin script, open your DAW and have it
- # refresh the list of plugins -- assuming it's already configured to
- # find plugins in the same target directory that you selected in the
- # beginning of the procedure. That's it. The DAW will detect the new
- # plugins in that directory and add them to its internal catalogue.
- #
- # OTHER FEATURES
- # This script can operate in three modes: normal, express and remove.
- # Modes are triggered by the presence or absence of arguments.
- # If neither the "express" or "remove" argument is used, "normal" mode
- # is assumed automatically. Only one mode can be used at a time.
- # If you try to use more than one argument, the script aborts all
- # operation and outputs a warning.
- #
- # NORMAL MODE
- # Already described in the previous sections of this documentation.
- #
- # EXPRESS MODE
- # In express mode, the script skips the confirmation stage entirely.
- # You will never be given the chance to edit anything in a text
- # editor. Items that match your blacklist and potential conflicts will
- # be properly skipped, and you will be given a brief report on standard
- # output.
- #
- # How to use:
- # $ cd /some/directory/with/a/truckload/of/plugins
- # $ linvstblast express
- #
- # REMOVE MODE
- # The remove mode will remove all copies of the linvst.so file in the
- # working directory, recursively. Don't worry, you will be presented
- # with a list in your file editor that you can edit before the
- # procedure is run, so you can be sure that you're only removing the
- # ones you want. There is no express mode for this operation.
- # Also note that .so files are only removed if they are an exact copy
- # of your matrix linvst.so file, so if you have any old copies of
- # linvst.so lingering around, they will be preserved and will probably
- # be detected as potential conflicts in subsequent runs.
- #
- # How to use:
- # $ cd /some/directory/with/a/truckload/of/plugins
- # $ linvstblast remove
- #
- # This script is placed in the public domain.
- # No guarantees are included whatsoever. If it blows up in your face,
- # eats your files or teaches profanity to your parrot, no one will be
- # responsible.
- # If you find a bug in my precious script, fix it for your own good.
- # That's open source for ya! Har. If you don't find any bugs, rejoice.
- # Ignorance is bliss.
- #
- # ==================================================================
- # USER OPTIONS SECTION. YOU MUST CHECK AND POSSIBLY EDIT THESE.
- # This is the location of the linvst.so file that will be copied to all
- # the directories where a plugin DLL is found. Make sure it is correct.
- set _linvst "/usr/local/bin/linvst.so"
- # Specify the full path of the editor you want to use. I've only tested
- # it with vim. Other editors may fail. Sorry!
- set _editor "/usr/bin/vim"
- # Sometimes a plugin's directory contains other DLL files that are not
- # plugins and should be ignored, but this script is not smart enough
- # to figure them out on its own. You may add such undesirable DLL files
- # to this list, so they will always be ignored.
- # NOTE: this check is case insensitive and the '.dll' extension part is
- # optional. If '.dll' is omitted, it's still assumed, though.
- set _blackList {
- d2d1.dll
- msvcr120.dll
- msvcr140
- msvcp120
- msvcp140.dll
- }
- # ==================================================================
- # END OF THE USER OPTIONS SECTION.
- # ==================================================================
- # ==================================================================
- # SCRIPT BEGINS HERE. DON'T CHANGE ANYTHING BELOW THIS POINT
- # UNLESS YOU KNOW WHAT YOU'RE DOING.
- # ==================================================================
- # ==================================================================
- # CHECKS AND PREPARATIONS
- # ==================================================================
- if {$argc > 1} {
- puts "ERROR! Only one argument, please."
- puts ""
- exit
- }
- # --------------------------------
- if {$argc == 1} {
- if {[lindex $argv 0] == "remove"} {
- set _mode "remove"
- } elseif {[lindex $argv 0] == "express"} {
- set _mode "express"
- } {
- puts "ERROR! Incorrect argument \"[lindex $argv 0]\""
- puts ""
- exit
- }
- } else {set _mode "normal"}
- # --------------------------------
- if {![file isfile $_linvst]} {
- puts "ERROR! Choice of linvst.so does not exist."
- puts "Please fix first line in the USER OPTIONS section of the script."
- puts ""
- exit
- }
- # --------------------------------
- set _found_dlls_tmpfile [file normalize "/tmp/found_dlls.txt"]
- file delete $_found_dlls_tmpfile
- # --------------------------------
- set ::hashMethod tcllib
- foreach i {sha512sum sha384sum sha256sum sha224sum sha1sum md5sum} {
- if {[catch {set ::hashMethod [exec which $i]} _catchError]} {
- continue
- } else {break}
- }
- if {$::hashMethod == "tcllib"} {
- if {[catch {package require sha256} _catchError]} {
- puts "ERROR! Impossible to proceed. Please install at least one of these packages: "
- puts "sha512sum, sha384sum, sha256sum, sha224sum, sha1sum, md5sum, or tcllib."
- puts "Note: tcllib is considerably slower than all the others."
- puts ""
- exit
- }
- }
- proc p.compare {arg1 arg2} {
- if {$::hashMethod == "tcllib"} {
- package require sha256
- set arg1 [::sha2::sha256 -hex -file $arg1]
- set arg2 [::sha2::sha256 -hex -file $arg2]
- if {$arg1 == $arg2} {return 1} else {return 0}
- } else {
- set arg1 [lindex [exec $::hashMethod $arg1] 0]
- set arg2 [lindex [exec $::hashMethod $arg2] 0]
- if {$arg1 == $arg2} {return 1} else {return 0}
- }
- }
- # ==================================================================
- # END OF CHECKS AND PREPARATIONS
- # ==================================================================
- # ==================================================================
- # REMOVE MODE
- # ==================================================================
- if {$_mode == "remove"} {
- set _found_sos [exec find [pwd] -iname "*.so"]
- if {[llength $_found_sos] == 0} {
- puts "-> Done! No .so files found whatsoever."
- puts "Are you sure you're running this in the right directory?"
- puts ""
- exit
- }
- foreach i [split $_found_sos "\n"] {
- if {[p.compare "$i" "$_linvst"] == 1} {lappend _found_sos_confirmed $i}
- }
- if {![info exists _found_sos_confirmed]} {
- puts "-> Done! Some .so files were found, but none of them is a copy of "
- puts "$_linvst, so nothing has been done this time. Here they are:"
- foreach i [split $_found_sos "\n"] {puts $i}
- puts ""
- exit
- }
- set _fp [open $_found_dlls_tmpfile w]
- puts $_fp "# All these .so files are confirmed to be copies of $_linvst "
- puts $_fp "# and will be removed. If you don't want any of them to be removed, delete "
- puts $_fp "# its corresponding line in this document before saving and closing the document."
- puts $_fp "# You can obviously delete all lines then save and close, which has the same effect "
- puts $_fp "# as cancelling the whole operation altogether."
- puts $_fp ""
- foreach i [split $_found_sos "\n"] {
- if {[p.compare $i $_linvst]} {
- puts $_fp $i
- }
- }
- close $_fp
- eval "exec $::_editor $::_found_dlls_tmpfile <@stdin >@stdout"
- set _count 0
- set _fp [open $_found_dlls_tmpfile r]
- while {-1 != [gets $_fp _line]} {
- if {[file isfile $_line]} {
- file delete $_line
- incr _count
- }
- }
- close $_fp
- puts "-> Done! $_count files removed."
- exit
- }
- # ==================================================================
- # END OF REMOVE MODE
- # ==================================================================
- # ==================================================================
- # NORMAL AND EXPRESS MODE
- # ==================================================================
- set _found_dlls [exec find [pwd] -iname "*.dll"]
- foreach i $_blackList {
- lappend _blackList_cleaned [file rootname $i]
- }
- foreach i [split $_found_dlls "\n"] {
- if {[lsearch -nocase $_blackList_cleaned [file rootname [file tail $i]]] >= 0} {
- lappend _blacklisted $i
- continue
- }
- set _dir [file dirname $i]
- if {[file isfile $_dir/[file rootname [file tail $i]].so]} {
- if {![p.compare $_dir/[file rootname [file tail $i]].so $_linvst]} {
- lappend _conflicts $i
- }
- continue
- }
- lappend _dll_final_list $i
- }
- if {![info exists _blacklisted] && ![info exists _conflicts] && ![info exists _dll_final_list]} {
- puts ""
- puts "No .dll files without a proper .so counterpart found."
- puts "No conflicts or blacklist matches either."
- puts "Nothing to do now. Maybe next time."
- puts ""
- exit
- }
- set _fp [open $_found_dlls_tmpfile w]
- puts $_fp "# Once you save and close this document, the operation will be executed "
- puts $_fp "# automatically."
- puts $_fp "# If you want to cancel/abort the entire operation, just delete all lines "
- puts $_fp "# in this document, save and close."
- puts $_fp ""
- if {[info exists _blacklisted]} {
- puts $_fp "# Here is the list of files that will NOT be linked to linvst "
- puts $_fp "# because they match at least one of the items in your blacklist: "
- puts $_fp ""
- foreach i $_blacklisted {puts $_fp "#$i"}
- puts $_fp ""
- puts $_fp "# If you think that any of the files above has been blacklisted in error "
- puts $_fp "# and should be linked to linvst, just delete the # symbol at the beginning of its line "
- puts $_fp "# before you save the document and close the text editor."
- puts $_fp ""
- puts $_fp "# --------------------------------"
- puts $_fp ""
- }
- if {[info exists _conflicts]} {
- puts $_fp "# This is the list of '.dll' files that already have their own '.so' counterpart, "
- puts $_fp "# but the .so file is not a copy of your linvst file. If you think they should be overwritten "
- puts $_fp "# with your linvst.so file, just remove the # symbol at the beginning of their respective lines. "
- puts $_fp "# BE CAREFUL with that decision. You may overwrite a file that is provided by the plugin "
- puts $_fp "# vendor/developer and is required for proper operation of the plugin."
- puts $_fp ""
- foreach i $_conflicts {puts $_fp "#$i"}
- puts $_fp ""
- puts $_fp "# --------------------------------"
- }
- if {[info exists _dll_final_list]} {
- puts $_fp "# This is the list of files that WILL be linked to linvst."
- puts $_fp "# After inspecting the list, save the document and close the text editor."
- puts $_fp "# If you want to exclude any of the files below, delete it from the list here "
- puts $_fp "# before saving the document and closing the text editor."
- puts $_fp "# If you don't want to have to exclude it manually again in the future, "
- puts $_fp "# add it to the blacklist in the USER OPTIONS section of the script."
- puts $_fp ""
- foreach i $_dll_final_list {puts $_fp "$i"}
- }
- close $_fp
- if {$_mode != "express"} {eval "exec $::_editor $::_found_dlls_tmpfile <@stdin >@stdout"}
- set _count 0
- set _fp [open $_found_dlls_tmpfile r]
- while {-1 != [gets $_fp _line]} {
- if {[regexp "^\s*#" $_line]} {continue}
- if {[file isfile $_line]} {
- file copy -force $_linvst [file dirname $_line]/[file rootname [file tail $_line]].so
- incr _count
- }
- if {[info exists _blacklisted]} {
- set _lsearch [lsearch -nocase $_blacklisted $_line]
- if {$_lsearch >= 0} {
- lappend _overridden $_line
- set _blacklisted [lreplace $_blacklisted $_lsearch $_lsearch]
- }
- if {[llength $_blacklisted] == 0} {unset _blacklisted}
- }
- if {[info exists _conflicts]} {
- set _lsearch [lsearch -nocase $_conflicts $_line]
- if {$_lsearch >= 0} {
- lappend _overridden $_line
- set _conflicts [lreplace $_conflicts $_lsearch $_lsearch]
- }
- if {[llength $_conflicts] == 0} {unset _conflicts}
- }
- }
- close $_fp
- # ==================================================================
- # FINAL OUTPUT
- # ==================================================================
- puts ""
- if {[info exists _dll_final_list]} {
- puts "-> Done. $_count new .dll to .so copies were performed."
- }
- if {[info exists _blacklisted]} {
- puts "-> Excluded by blacklisting:"
- foreach i $_blacklisted {puts $i}
- }
- if {[info exists _overridden]} {
- puts "-> These files were blacklisted, but were copied because you chose to override the blacklist:"
- foreach i $_overridden {puts $i}
- }
- if {[info exists _conflicts]} {
- puts "-> Excluded due to name conflicts:"
- foreach i $_conflicts {puts $i}
- }
- puts ""
- exit
Add Comment
Please, Sign In to add comment