X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=headless%2Fload_session.cc;h=0c2d01ecdbe8cfb4312b38c57298a4548d999ce9;hb=8deed500a4840b15156be415eadd6d353b254557;hp=a9037214cc33f3fa6874e0c8f7f75ff024cbe7f4;hpb=95ccbc452f513a9d6f70de45bc413067e568364c;p=ardour.git diff --git a/headless/load_session.cc b/headless/load_session.cc index a9037214cc..0c2d01ecdb 100644 --- a/headless/load_session.cc +++ b/headless/load_session.cc @@ -1,34 +1,62 @@ -#include +/* + * Copyright (C) 2014-2019 Paul Davis + * Copyright (C) 2014-2019 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 "pbd/failed_constructor.h" -#include "pbd/error.h" +#ifndef PLATFORM_WINDOWS +#include +#endif + +#include + +#include "pbd/convert.h" +#include "pbd/crossthread.h" #include "pbd/debug.h" +#include "pbd/error.h" +#include "pbd/failed_constructor.h" #include "ardour/ardour.h" #include "ardour/audioengine.h" +#include "ardour/revision.h" #include "ardour/session.h" +#include "control_protocol/control_protocol.h" + #include "misc.h" using namespace std; using namespace ARDOUR; using namespace PBD; -#ifdef PLATFORM_WINDOWS -#include -#define sleep(X) Sleep((X) * 1000) -#endif - static const char* localedir = LOCALEDIR; -TestReceiver test_receiver; +static string backend_client_name; +static string backend_name = "JACK"; +static CrossThreadChannel xthread (true); +static TestReceiver test_receiver; /** @param dir Session directory. * @param state Session state file, without .ardour suffix. */ -Session * +static Session* load_session (string dir, string state) { SessionEvent::create_per_thread_pool ("test", 512); @@ -40,16 +68,14 @@ load_session (string dir, string state) AudioEngine* engine = AudioEngine::create (); - if (!engine->set_default_backend ()) { - std::cerr << "Cannot create Audio/MIDI engine\n"; - ::exit (1); + if (!engine->set_backend (backend_name, backend_client_name, "")) { + std::cerr << "Cannot set Audio/MIDI engine backend\n"; + exit (EXIT_FAILURE); } - init_post_engine (); - if (engine->start () != 0) { std::cerr << "Cannot start Audio/MIDI engine\n"; - ::exit (1); + exit (EXIT_FAILURE); } Session* session = new Session (*engine, dir, state); @@ -57,15 +83,52 @@ load_session (string dir, string state) return session; } -string session_name = ""; -string backend_client_name = "ardour"; -string backend_session_uuid; -bool just_version = false; -bool use_vst = true; -bool try_hw_optimization = true; -bool no_connect_ports = false; +static void +access_action (const std::string& action_group, const std::string& action_item) +{ + if (action_group == "Common" && action_item == "Quit") { + xthread.deliver ('x'); + } +} + +static void +engine_halted (const char* reason) +{ + cerr << "The audio backend has been shutdown"; + if (reason && strlen (reason) > 0) { + cerr << ": " << reason; + } else { + cerr << "."; + } + cerr << endl; + xthread.deliver ('x'); +} + +#ifndef PLATFORM_WINDOWS +static void +wearedone (int) +{ + cerr << "caught signal - terminating." << endl; + xthread.deliver ('x'); +} +#endif -void +static void +print_version () +{ + cout + << PROGRAM_NAME + << VERSIONSTRING + << " (built using " + << ARDOUR::revision +#ifdef __GNUC__ + << " and GCC version " << __VERSION__ +#endif + << ')' + << endl; +} + +static void print_help () { cout << "Usage: hardour [OPTIONS]... DIR SNAPSHOT_NAME\n\n" @@ -81,124 +144,146 @@ print_help () #ifdef WINDOWS_VST_SUPPORT << " -V, --novst Do not use VST support\n" #endif - ; + ; } -int main (int argc, char* argv[]) +int +main (int argc, char* argv[]) { - const char *optstring = "vhdD:c:VOU:P"; + const char* optstring = "vhBdD:c:VOU:P"; + /* clang-format off */ const struct option longopts[] = { - { "version", 0, 0, 'v' }, - { "help", 0, 0, 'h' }, - { "disable-plugins", 1, 0, 'd' }, - { "debug", 1, 0, 'D' }, - { "name", 1, 0, 'c' }, - { "novst", 0, 0, 'V' }, - { "no-hw-optimizations", 0, 0, 'O' }, - { "uuid", 1, 0, 'U' }, - { "no-connect-ports", 0, 0, 'P' }, + { "version", no_argument, 0, 'v' }, + { "help", no_argument, 0, 'h' }, + { "bypass-plugins", no_argument, 0, 'B' }, + { "disable-plugins", no_argument, 0, 'd' }, + { "debug", required_argument, 0, 'D' }, + { "name", required_argument, 0, 'c' }, + { "novst", no_argument, 0, 'V' }, + { "no-hw-optimizations", no_argument, 0, 'O' }, + { "no-connect-ports", no_argument, 0, 'P' }, { 0, 0, 0, 0 } }; + /* clang-format on */ - int option_index = 0; - int c = 0; + bool use_vst = true; + bool try_hw_optimization = true; - while (1) { - c = getopt_long (argc, argv, optstring, longopts, &option_index); - - if (c == -1) { - break; - } + backend_client_name = PBD::downcase (std::string (PROGRAM_NAME)); + int c; + while ((c = getopt_long (argc, argv, optstring, longopts, (int*)0)) != EOF) { switch (c) { - case 0: - break; - - case 'v': - just_version = true; - break; - - case 'h': - print_help (); - exit (0); - break; - - case 'c': - backend_client_name = optarg; - break; - - case 'd': - ARDOUR::Session::set_disable_all_loaded_plugins (true); - break; - - case 'D': - if (PBD::parse_debug_options (optarg)) { - ::exit (1); - } - break; - - case 'O': - try_hw_optimization = false; - break; - - case 'P': - no_connect_ports = true; - break; - - case 'V': + case 0: + break; + + case 'v': + print_version (); + exit (EXIT_SUCCESS); + break; + + case 'h': + print_help (); + exit (EXIT_SUCCESS); + break; + + case 'c': + backend_client_name = optarg; + break; + + case 'B': + ARDOUR::Session::set_bypass_all_loaded_plugins (true); + break; + + case 'd': + ARDOUR::Session::set_disable_all_loaded_plugins (true); + break; + + case 'D': + if (PBD::parse_debug_options (optarg)) { + exit (EXIT_SUCCESS); + } + break; + + case 'O': + try_hw_optimization = false; + break; + + case 'P': + ARDOUR::Port::set_connecting_blocked (true); + break; + + case 'V': #ifdef WINDOWS_VST_SUPPORT - use_vst = false; + use_vst = false; #endif /* WINDOWS_VST_SUPPORT */ - break; + break; - case 'U': - backend_session_uuid = optarg; - break; - - default: - print_help (); - ::exit (1); + default: + print_help (); + exit (EXIT_FAILURE); } } if (argc < 3) { print_help (); - ::exit (1); + exit (EXIT_FAILURE); } - if (!ARDOUR::init (false, true, localedir)) { - cerr << "Ardour failed to initialize\n" << endl; - ::exit (1); + if (!ARDOUR::init (use_vst, try_hw_optimization, localedir)) { + cerr << "Ardour failed to initialize\n" + << endl; + exit (EXIT_FAILURE); } Session* s = 0; - + try { - s = load_session (argv[optind], argv[optind+1]); + s = load_session (argv[optind], argv[optind + 1]); } catch (failed_constructor& e) { - cerr << "failed_constructor: " << e.what() << "\n"; + cerr << "failed_constructor: " << e.what () << "\n"; exit (EXIT_FAILURE); } catch (AudioEngine::PortRegistrationFailure& e) { - cerr << "PortRegistrationFailure: " << e.what() << "\n"; + cerr << "PortRegistrationFailure: " << e.what () << "\n"; exit (EXIT_FAILURE); } catch (exception& e) { - cerr << "exception: " << e.what() << "\n"; + cerr << "exception: " << e.what () << "\n"; exit (EXIT_FAILURE); } catch (...) { cerr << "unknown exception.\n"; exit (EXIT_FAILURE); } + /* allow signal propagation, callback/thread-pool setup, etc + * similar to to GUI "first idle" + */ + Glib::usleep (1000000); // 1 sec + + if (!s) { + cerr << "failed_to load session\n"; + exit (EXIT_FAILURE); + } + + PBD::ScopedConnectionList con; + BasicUI::AccessAction.connect_same_thread (con, boost::bind (&access_action, _1, _2)); + AudioEngine::instance ()->Halted.connect_same_thread (con, boost::bind (&engine_halted, _1)); + +#ifndef PLATFORM_WINDOWS + signal (SIGINT, wearedone); + signal (SIGTERM, wearedone); +#endif + s->request_transport_speed (1.0); - - sleep (-1); - AudioEngine::instance()->remove_session (); + char msg; + do { + } while (0 == xthread.receive (msg, true)); + + AudioEngine::instance ()->remove_session (); delete s; - AudioEngine::instance()->stop (); + AudioEngine::instance ()->stop (); AudioEngine::destroy (); - return 0; }