new headless (GUI-free) version of ardour. run waf, cd headless and run ./hardev DIR SNAPSHOT_NAME. not bug free yet (startup race condition)

This commit is contained in:
Paul Davis 2014-02-24 13:49:58 -05:00
parent e58b337c84
commit 90d0d4d878
7 changed files with 402 additions and 0 deletions

5
headless/hardbg Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
. `dirname "$0"`/../build/headless/hardev_common_waf.sh
LD_LIBRARY_PATH=$LD_LIBRARY_PATH
export ARDOUR_INSIDE_GDB=1
exec gdb --args $TOP/$EXECUTABLE $@

4
headless/hardev Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
. `dirname "$0"`/../build/headless/hardev_common_waf.sh
export UBUNTU_MENUPROXY=""
exec $TOP/$EXECUTABLE "$@"

View File

@ -0,0 +1,39 @@
TOP=`dirname "$0"`/..
#export G_DEBUG=fatal_criticals
libs=$TOP/@LIBS@
#
# when running ardev, the various parts of Ardour have not been consolidated into the locations that they
# would normally end up after an install. We therefore need to set up environment variables so that we
# can find all the components.
#
export ARDOUR_PATH=$TOP/gtk2_ardour/icons:$TOP/gtk2_ardour/pixmaps:$TOP/build/gtk2_ardour:$TOP/gtk2_ardour:.
export ARDOUR_SURFACES_PATH=$libs/surfaces/osc:$libs/surfaces/generic_midi:$libs/surfaces/tranzport:$libs/surfaces/powermate:$libs/surfaces/mackie:$libs/surfaces/wiimote
export ARDOUR_PANNER_PATH=$libs/panners
export ARDOUR_DATA_PATH=$TOP:$TOP/build:$TOP/gtk2_ardour:$TOP/build/gtk2_ardour:.
export ARDOUR_MIDIMAPS_PATH=$TOP/midi_maps:.
export ARDOUR_MCP_PATH=$TOP/mcp:.
export ARDOUR_EXPORT_FORMATS_PATH=$TOP/export:.
export ARDOUR_BACKEND_PATH=$libs/backends/jack
#
# even though we set the above variables, ardour requires that these
# two also be set. the above settings will override them.
#
export ARDOUR_CONFIG_PATH=$TOP:$TOP/gtk2_ardour:$TOP/build:$TOP/build/gtk2_ardour
export ARDOUR_DLL_PATH=$libs
export GTK_PATH=~/.ardour3:$libs/clearlooks-newer
export VAMP_PATH=$libs/vamp-plugins${VAMP_PATH:+:$VAMP_PATH}
export LD_LIBRARY_PATH=$libs/qm-dsp:$libs/vamp-sdk:$libs/surfaces:$libs/surfaces/control_protocol:$libs/ardour:$libs/midi++2:$libs/pbd:$libs/rubberband:$libs/soundtouch:$libs/gtkmm2ext:$libs/gnomecanvas:$libs/libsndfile:$libs/appleutility:$libs/taglib:$libs/evoral:$libs/evoral/src/libsmf:$libs/audiographer:$libs/timecode:$libs/libltc:$libs/canvas${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
# DYLD_LIBRARY_PATH is for darwin.
export DYLD_FALLBACK_LIBRARY_PATH=$LD_LIBRARY_PATH
ARDOURVERSION=@VERSION@
EXECUTABLE=@EXECUTABLE@

199
headless/load_session.cc Normal file
View File

@ -0,0 +1,199 @@
#include <iostream>
#include <cstdlib>
#include <getopt.h>
#include "pbd/failed_constructor.h"
#include "pbd/error.h"
#include "pbd/debug.h"
#include "ardour/ardour.h"
#include "ardour/audioengine.h"
#include "ardour/session.h"
#include "misc.h"
using namespace std;
using namespace ARDOUR;
using namespace PBD;
static const char* localedir = LOCALEDIR;
TestReceiver test_receiver;
/** @param dir Session directory.
* @param state Session state file, without .ardour suffix.
*/
Session *
load_session (string dir, string state)
{
SessionEvent::create_per_thread_pool ("test", 512);
test_receiver.listen_to (error);
test_receiver.listen_to (info);
test_receiver.listen_to (fatal);
test_receiver.listen_to (warning);
AudioEngine* engine = AudioEngine::create ();
if (!engine->set_default_backend ()) {
std::cerr << "Cannot create Audio/MIDI engine\n";
::exit (1);
}
init_post_engine ();
if (engine->start () != 0) {
std::cerr << "Cannot start Audio/MIDI engine\n";
::exit (1);
}
Session* session = new Session (*engine, dir, state);
engine->set_session (session);
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;
void
print_help ()
{
cout << "Usage: hardour [OPTIONS]... DIR SNAPSHOT_NAME\n\n"
<< " DIR Directory/Folder to load session from\n"
<< " SNAPSHOT_NAME Name of session/snapshot to load (without .ardour at end\n"
<< " -v, --version Show version information\n"
<< " -h, --help Print this message\n"
<< " -c, --name <name> Use a specific backend client name, default is ardour\n"
<< " -d, --disable-plugins Disable all plugins in an existing session\n"
<< " -D, --debug <options> Set debug flags. Use \"-D list\" to see available options\n"
<< " -O, --no-hw-optimizations Disable h/w specific optimizations\n"
<< " -P, --no-connect-ports Do not connect any ports at startup\n"
#ifdef WINDOWS_VST_SUPPORT
<< " -V, --novst Do not use VST support\n"
#endif
;
}
int main (int argc, char* argv[])
{
const char *optstring = "vhdD:c:VOU:P";
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' },
{ 0, 0, 0, 0 }
};
int option_index = 0;
int c = 0;
while (1) {
c = getopt_long (argc, argv, optstring, longopts, &option_index);
if (c == -1) {
break;
}
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':
#ifdef WINDOWS_VST_SUPPORT
use_vst = false;
#endif /* WINDOWS_VST_SUPPORT */
break;
case 'U':
backend_session_uuid = optarg;
break;
default:
print_help ();
::exit (1);
}
}
if (argc < 3) {
print_help ();
::exit (1);
}
if (!ARDOUR::init (false, true, localedir)) {
cerr << "Ardour failed to initialize\n" << endl;
::exit (1);
}
Session* s = 0;
try {
s = load_session (argv[optind], argv[optind+1]);
} catch (failed_constructor& e) {
cerr << "failed_constructor: " << e.what() << "\n";
exit (EXIT_FAILURE);
} catch (AudioEngine::PortRegistrationFailure& e) {
cerr << "PortRegistrationFailure: " << e.what() << "\n";
exit (EXIT_FAILURE);
} catch (exception& e) {
cerr << "exception: " << e.what() << "\n";
exit (EXIT_FAILURE);
} catch (...) {
cerr << "unknown exception.\n";
exit (EXIT_FAILURE);
}
s->request_transport_speed (1.0);
sleep (-1);
AudioEngine::instance()->remove_session ();
delete s;
AudioEngine::instance()->stop ();
AudioEngine::destroy ();
return 0;
}

46
headless/misc.cc Normal file
View File

@ -0,0 +1,46 @@
#include <iostream>
#include <cstdlib>
#include "misc.h"
void
TestReceiver::receive (Transmitter::Channel chn, const char * str)
{
const char *prefix = "";
switch (chn) {
case Transmitter::Error:
prefix = ": [ERROR]: ";
break;
case Transmitter::Info:
/* ignore */
return;
case Transmitter::Warning:
prefix = ": [WARNING]: ";
break;
case Transmitter::Fatal:
prefix = ": [FATAL]: ";
break;
case Transmitter::Throw:
/* this isn't supposed to happen */
abort ();
}
/* note: iostreams are already thread-safe: no external
lock required.
*/
std::cout << prefix << str << std::endl;
if (chn == Transmitter::Fatal) {
::exit (9);
}
}
/* temporarily required due to some code design confusion (Feb 2014) */
#include "ardour/vst_types.h"
int vstfx_init (void*) { return 0; }
void vstfx_exit () {}
void vstfx_destroy_editor (VSTState*) {}

13
headless/misc.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef __hardour_misc_h__
#define __hardour_misc_h__
#include "pbd/transmitter.h"
#include "pbd/receiver.h"
class TestReceiver : public Receiver
{
protected:
void receive (Transmitter::Channel chn, const char * str);
};
#endif /* __hardour_misc_h__ */

96
headless/wscript Normal file
View File

@ -0,0 +1,96 @@
#!/usr/bin/env python
from waflib.extras import autowaf as autowaf
from waflib import Options, TaskGen
import waflib.Logs as Logs, waflib.Utils as Utils
import os
import shutil
import sys
import re
import time
from waflib.Task import Task
# Mandatory variables
top = '.'
out = 'build'
hardour_sources = [
'load_session.cc',
'misc.cc',
]
def options(opt):
autowaf.set_options(opt)
def configure(conf):
conf.load('misc')
conf.load('compiler_cxx')
autowaf.configure(conf)
def build(bld):
VERSION = "%s.%s" % (bld.env['MAJOR'], bld.env['MINOR'])
# just the normal executable version of the GTK GUI
obj = bld (features = 'cxx c cxxprogram')
obj.source = hardour_sources
obj.target = 'hardour-' + bld.env['VERSION']
obj.includes = ['.']
# at this point, "obj" refers to either the normal native executable
# OR the shared library built for use with wine on linux.
obj.use = [ 'libpbd',
'libardour',
'libardour_cp',
'libtimecode',
'libmidipp',
]
obj.defines = [
'VERSIONSTRING="' + bld.env['VERSION'] + '"',
'DATA_DIR="' + os.path.normpath(bld.env['DATADIR']) + '"',
'CONFIG_DIR="' + os.path.normpath(bld.env['SYSCONFDIR']) + '"',
'LOCALEDIR="' + os.path.join(os.path.normpath(bld.env['DATADIR']), 'locale') + '"',
'PROGRAM_NAME="' + bld.env['PROGRAM_NAME'] + '"'
]
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')
obj.uselib = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD OGG CURL DL'
obj.uselib += ' FFTW3F'
obj.uselib += ' AUDIOUNITS OSX LO '
obj.uselib += ' TAGLIB '
if sys.platform == 'darwin':
obj.uselib += ' AUDIOUNITS OSX'
obj.use += ' libappleutility'
obj.includes += ['../libs']
if bld.env['build_target'] == 'mingw':
if bld.env['DEBUG'] == False:
obj.linkflags = ['-mwindows']
if bld.is_defined('NEED_INTL'):
obj.linkflags = ' -lintl'
# Wrappers
wrapper_subst_dict = {
'INSTALL_PREFIX' : bld.env['PREFIX'],
'LIBDIR' : os.path.normpath(bld.env['LIBDIR']),
'DATADIR' : os.path.normpath(bld.env['DATADIR']),
'SYSCONFDIR' : os.path.normpath(bld.env['SYSCONFDIR']),
'LIBS' : 'build/libs',
'VERSION' : bld.env['VERSION'],
'EXECUTABLE' : 'build/headless/hardour-' + bld.env['VERSION']
}
def set_subst_dict(obj, dict):
for i in dict:
setattr(obj, i, dict[i])
obj = bld(features = 'subst', rule= 'chmod 0755 ${TGT}')
obj.source = 'hardev_common.sh.in'
obj.target = 'hardev_common_waf.sh'
obj.chmod = Utils.O755
obj.dict = wrapper_subst_dict
set_subst_dict(obj, wrapper_subst_dict)