From 15e564c54afca2d4f27ae38a40f8baccbb39b5e0 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 10 Sep 2020 14:43:05 +0200 Subject: [PATCH] VST3: scanner application --- gtk2_ardour/arvst3 | 49 +++++++++ libs/fst/vst3-scanner.cc | 209 +++++++++++++++++++++++++++++++++++++++ libs/fst/wscript | 31 +++++- 3 files changed, 285 insertions(+), 4 deletions(-) create mode 100755 gtk2_ardour/arvst3 create mode 100644 libs/fst/vst3-scanner.cc diff --git a/gtk2_ardour/arvst3 b/gtk2_ardour/arvst3 new file mode 100755 index 0000000000..fdb153fd01 --- /dev/null +++ b/gtk2_ardour/arvst3 @@ -0,0 +1,49 @@ +#!/bin/sh +TOP=`dirname "$0"`/.. +. $TOP/build/gtk2_ardour/ardev_common_waf.sh +export UBUNTU_MENUPROXY="" + +if [ $# -gt 0 ] ; then + case $1 in + -g|--gdb) DBG=gdb; shift ;; + esac + case $1 in + --valgrind) DBG=valgrind; shift ;; + esac + case $1 in + --callgrind) DBG=callgrind; shift ;; + esac +fi + +if test -z "$DBG"; then + exec $TOP/build/libs/fst/ardour-vst3-scanner "$@" +fi + +if test "$DBG" = "valgrind"; then + export ARDOUR_RUNNING_UNDER_VALGRIND=TRUE + exec valgrind \ + --error-limit=no --num-callers=50 \ + --tool=memcheck \ + --track-origins=yes \ + --leak-check=full --show-leak-kinds=all \ + --suppressions=${TOP}/tools/valgrind.supp \ + $TOP/build/libs/fst/ardour-vst3-scanner "$@" +fi + +if test "$DBG" = "callgrind"; then + exec valgrind \ + --error-limit=no --num-callers=50 \ + --tool=callgrind \ + --separate-callers=3 \ + --separate-threads=yes \ + --collect-systime=yes \ + --collect-jumps=yes \ + $TOP/build/libs/fst/ardour-vst3-scanner "$@" +fi + +if test -n "`which gdb`"; then + exec gdb --args $TOP/build/libs/fst/ardour-vst3-scanner "$@" +fi +if test -n "`which lldb`"; then + exec lldb -- $TOP/build/libs/fst/ardour-vst3-scanner "$@" +fi diff --git a/libs/fst/vst3-scanner.cc b/libs/fst/vst3-scanner.cc new file mode 100644 index 0000000000..aaa129f721 --- /dev/null +++ b/libs/fst/vst3-scanner.cc @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2020 Robin Gareus + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include + +#ifdef COMPILER_MSVC +#include +#else +#include +#endif + +#include "pbd/error.h" +#include "pbd/transmitter.h" +#include "pbd/receiver.h" +#include "pbd/pbd.h" +#include "pbd/xml++.h" + +#ifdef __MINGW64__ +#define NO_OLDNAMES // no backwards compat _pid_t, conflict with w64 pthread/sched +#endif + +#include "../ardour/filesystem_paths.cc" +#include "../ardour/vst3_scan.cc" +#include "../ardour/vst3_host.cc" +#include "../ardour/vst3_module.cc" + +using namespace PBD; + +class LogReceiver : public Receiver +{ +protected: + void receive (Transmitter::Channel chn, const char * str) { + const char *prefix = ""; + switch (chn) { + case Transmitter::Error: + prefix = "[ERROR]: "; + break; + case Transmitter::Info: + prefix = "[Info]: "; + break; + case Transmitter::Warning: + prefix = "[WARNING]: "; + break; + case Transmitter::Fatal: + prefix = "[FATAL]: "; + break; + case Transmitter::Throw: + abort (); + } + + std::cout << prefix << str << std::endl; + + if (chn == Transmitter::Fatal) { + ::exit (EXIT_FAILURE); + } + } +}; + +LogReceiver log_receiver; + +static void vst3_plugin (string const& module_path, VST3Info const& i) +{ + info << "Found Plugin: " << i.name << endmsg; +} + +static bool +scan_vst3 (std::string const& bundle_path, bool force) +{ + info << "Scanning: " << bundle_path << endmsg; + string module_path = module_path_vst3 (bundle_path); + if (module_path.empty ()) { + return false; + } + + if (!vst3_valid_cache_file (module_path, true).empty()) { + if (!force) { + info << "Skipping scan." << endmsg; + return true; + } + } + + if (vst3_scan_and_cache (module_path, bundle_path, sigc::ptr_fun (&vst3_plugin))) { + info << string_compose (_("Saved VST3 plugin cache to %1"), vst3_cache_file (module_path)) << endmsg; + } + + return true; +} + +static void +usage () +{ + // help2man compatible format (standard GNU help-text) + printf ("ardour-vst3-scanner - load and index VST3 plugins.\n\n"); + printf ("Usage: ardour-vst3-scanner [ OPTIONS ] []*\n\n"); + printf ("Options:\n\ + -f, --force Force update ot cache file\n\ + -h, --help Display this help and exit\n\ + -q, --quiet Hide usual output, only print errors\n\ + -V, --version Print version information and exit\n\ +\n"); + + printf ("\n\ +This tool ...\n\ +\n"); + + printf ("Report bugs to \n" + "Website: \n"); + ::exit (EXIT_SUCCESS); +} + +int +main (int argc, char **argv) +{ + bool print_log = true; + bool stop_on_error = false; + bool force = false; + + const char* optstring = "fhqV"; + + /* clang-format off */ + const struct option longopts[] = { + { "force", no_argument, 0, 'f' }, + { "help", no_argument, 0, 'h' }, + { "quiet", no_argument, 0, 'q' }, + { "version", no_argument, 0, 'V' }, + }; + /* clang-format on */ + + int c = 0; + while (EOF != (c = getopt_long (argc, argv, optstring, longopts, (int*)0))) { + switch (c) { + case 'V': + printf ("ardour-vst3-scanner version %s\n\n", VERSIONSTRING); + printf ("Copyright (C) GPL 2020 Robin Gareus \n"); + exit (EXIT_SUCCESS); + break; + + case 'f': + force = true; + break; + + case 'h': + usage (); + break; + + case 'q': + print_log = false; + break; + + default: + std::cerr << "Error: unrecognized option. See --help for usage information.\n"; + ::exit (EXIT_FAILURE); + break; + } + } + + if (optind >= argc) { + std::cerr << "Error: Missing parameter. See --help for usage information.\n"; + ::exit (EXIT_FAILURE); + } + + + PBD::init(); + + if (print_log) { + log_receiver.listen_to (error); + log_receiver.listen_to (info); + log_receiver.listen_to (fatal); + log_receiver.listen_to (warning); + } + + bool err = false; + + while (optind < argc) { + if (!scan_vst3 (argv[optind++], force)) { + err = true; + } + if (stop_on_error) { + break; + } + } + + PBD::cleanup(); + + if (err) { + return EXIT_FAILURE; + } else { + return EXIT_SUCCESS; + } +} diff --git a/libs/fst/wscript b/libs/fst/wscript index 7242024b2e..c7226c33f5 100644 --- a/libs/fst/wscript +++ b/libs/fst/wscript @@ -13,10 +13,6 @@ from waflib.Task import Task top = '.' out = 'build' -scanner_app_src = [ - 'scanner.cc', - ] - # needed for code used from libardour I18N_PACKAGE = 'ardour' @@ -42,6 +38,33 @@ def set_winegcc(self): def build(bld): VERSION = "%s.%s" % (bld.env['MAJOR'], bld.env['MINOR']) + + if bld.is_defined('VST3_SUPPORT'): + obj = bld (features = 'cxx c cxxprogram') + obj.source = 'vst3-scanner.cc' + obj.target = 'ardour-vst3-scanner' + obj.includes = [ '../pbd/', '../ardour/', '../vst3/', '..' ] + obj.defines = [ + '_POSIX_SOURCE', + 'VERSIONSTRING="' + str(bld.env['VERSION']) + '"', + 'PACKAGE="' + I18N_PACKAGE + str(bld.env['MAJOR']) + '"', + 'LIBARDOUR="' + bld.env['lwrcase_dirname'] + '"', + 'LOCALEDIR="' + os.path.join(os.path.normpath(bld.env['DATADIR']), 'locale') + '"', + ] + obj.use = [ 'libpbd' ] + + if bld.env['build_target'] == 'mingw': + obj.uselib = ['GIOMM', 'DL', 'GDI32', 'XML'] + obj.linkflags = ['-mwindows'] + else: + obj.uselib = ['GIOMM', 'DL', 'OSX', 'XML'] + + if re.search ("bsd", sys.platform) != None: + obj.defines.append('_POSIX_C_SOURCE=200809') + obj.defines.append('_XOPEN_SOURCE=700') + obj.install_path = os.path.join(bld.env['LIBDIR']) + + if not (bld.is_defined('WINDOWS_VST_SUPPORT') or bld.is_defined('LXVST_SUPPORT') or bld.is_defined ('MACVST_SUPPORT')): return