From 989830fb7e4545e25dbd85536d2b0cb0539e86a6 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 7 Sep 2012 18:05:53 +0000 Subject: [PATCH] get initialization, skeletonmixer-style connections working, add incomplete fader control git-svn-id: svn://localhost/ardour2/branches/3.0-SG@13170 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour_ui.cc | 12 ++++ gtk2_ardour/engine_dialog.cc | 14 ++-- gtk2_ardour/soundgrid.mm | 4 +- libs/ardour/amp.cc | 38 ++++++++++- libs/ardour/ardour/amp.h | 21 +++++- libs/ardour/ardour/sg_rack.h | 17 ++--- libs/ardour/route.cc | 2 +- libs/ardour/sg_rack.cc | 94 ++++++++++++++++++--------- libs/ardour/soundgrid.mm | 121 ++++++++++++++++++++++------------- 9 files changed, 226 insertions(+), 97 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 3164467a83..e93071034e 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -73,6 +73,7 @@ #include "ardour/session_route.h" #include "ardour/session_state_utils.h" #include "ardour/session_utils.h" +#include "ardour/soundgrid.h" typedef uint64_t microseconds_t; @@ -644,6 +645,9 @@ ARDOUR_UI::startup () app->ready (); if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) { + if (Profile->get_soundgrid()) { + SoundGrid::instance().teardown(); + } exit (1); } @@ -807,6 +811,11 @@ If you still wish to quit, please use the\n\n\ ArdourDialog::close_all_dialogs (); engine->stop (true); + + if (Profile->get_soundgrid()) { + SoundGrid::instance().teardown (); + } + quit (); } @@ -2439,6 +2448,9 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri if (!apply) { if (quit_on_cancel) { + if (Profile->get_soundgrid()) { + SoundGrid::instance().teardown(); + } exit (1); } else { return ret; diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index 206053c10a..d0df37dc97 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -46,6 +46,7 @@ #endif #include "ardour/soundgrid.h" +#include "ardour/debug.h" #include @@ -711,7 +712,7 @@ EngineControl::enumerate_devices (const string& driver) */ soundgrid_init (16, 16, inputs_adjustment.get_value(), outputs_adjustment.get_value()); - devices[driver] = vector(); + devices[driver] = SoundGrid::lan_port_names(); #else @@ -1617,13 +1618,16 @@ EngineControl::refill_soundgrid_inventory () void EngineControl::set_soundgrid_parameters () { +#if 0 string lan_port = interface_combo.get_active_text (); int sr = atoi (sample_rate_combo.get_active_text()); int bufsize = atoi (period_size_combo.get_active_text()); - - cerr << "Calling soundgrid::set_parmeter...\n"; - int ret = SoundGrid::set_parameters (lan_port, sr, bufsize); - cerr << "\treturned " << ret << endl; + + DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("setting parameters to lanport:%1 sr:%2 bufsize:3\n", + lan_port, sr, bufsize)); + + SoundGrid::set_parameters (lan_port, sr, bufsize); +#endif } void diff --git a/gtk2_ardour/soundgrid.mm b/gtk2_ardour/soundgrid.mm index dba50c7f14..03f2490b07 100644 --- a/gtk2_ardour/soundgrid.mm +++ b/gtk2_ardour/soundgrid.mm @@ -116,11 +116,11 @@ soundgrid_init (uint32_t max_track_inputs, uint32_t max_track_outputs, return -1; } - /* as of early August 2012, we need to wait 2 seconds before configuring the CoreAudio driver */ + /* as of early August 2012, we need to wait 5 seconds before configuring the CoreAudio driver */ Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (soundgrid_driver_init), max_track_inputs, max_track_outputs, - max_phys_inputs, max_phys_outputs), 2000); + max_phys_inputs, max_phys_outputs), 5000); /* tell everyone/everything that we're using soundgrid */ diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc index d68f73ef3e..3bfd8f2a4e 100644 --- a/libs/ardour/amp.cc +++ b/libs/ardour/amp.cc @@ -16,6 +16,8 @@ 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "libardour-config.h" + #include #include #include @@ -28,18 +30,28 @@ #include "ardour/buffer_set.h" #include "ardour/midi_buffer.h" #include "ardour/session.h" +#if HAVE_SOUNDGRID +#include "ardour/sg_rack.h" +#endif #include "i18n.h" using namespace ARDOUR; using namespace PBD; -Amp::Amp (Session& s) +Amp::Amp (Session& s +#if HAVE_SOUNDGRID + , SoundGridRack* sr +#endif + ) : Processor(s, "Amp") , _apply_gain(true) , _apply_gain_automation(false) , _current_gain(1.0) , _gain_automation_buffer(0) +#if HAVE_SOUNDGRID + , _rack (sr) +#endif { Evoral::Parameter p (GainAutomation); /* gain range of -inf to +6dB, default 0dB */ @@ -77,6 +89,11 @@ Amp::configure_io (ChanCount in, ChanCount out) void Amp::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_frame*/, pframes_t nframes, bool) { +#if HAVE_SOUNDGRID + _active = _pending_active; + return; +#endif + if (!_active && !_pending_active) { return; } @@ -385,6 +402,8 @@ Amp::set_gain (gain_t val, void *src) _gain_control->set_double (val); _session.set_dirty(); + + } XMLNode& @@ -419,11 +438,28 @@ Amp::GainControl::set_value (double val) val = 1.99526231; } +#if HAVE_SOUNDGRID + if (_amp->soundgrid_rack()) { + return _amp->soundgrid_rack()->set_fader (val); + } +#endif + _amp->set_gain (val, this); AutomationControl::set_value(val); } +double +Amp::GainControl::get_value () const +{ +#if HAVE_SOUNDGRID + if (_amp->soundgrid_rack()) { + return _amp->soundgrid_rack()->get_fader(); + } +#endif + return AutomationControl::get_value(); +} + double Amp::GainControl::internal_to_interface (double v) const { diff --git a/libs/ardour/ardour/amp.h b/libs/ardour/ardour/amp.h index 46dbdba227..56b6580777 100644 --- a/libs/ardour/ardour/amp.h +++ b/libs/ardour/ardour/amp.h @@ -19,6 +19,8 @@ #ifndef __ardour_amp_h__ #define __ardour_amp_h__ +#include "libardour-config.h" + #include "ardour/types.h" #include "ardour/chan_count.h" #include "ardour/processor.h" @@ -29,12 +31,20 @@ namespace ARDOUR { class BufferSet; class IO; +#if HAVE_SOUNDGRID +class SoundGridRack; +#endif + /** Applies a declick operation to all audio inputs, passing the same number of * audio outputs, and passing through any other types unchanged. */ class Amp : public Processor { public: - Amp(Session& s); + Amp(Session& s +#if HAVE_SOUNDGRID + , SoundGridRack* sr = 0 +#endif + ); std::string display_name() const; @@ -85,6 +95,7 @@ public: } void set_value (double val); + double get_value() const; double internal_to_interface (double) const; double interface_to_internal (double) const; @@ -102,6 +113,10 @@ public: } std::string value_as_string (boost::shared_ptr) const; + +#if HAVE_SOUNDGRID + SoundGridRack* soundgrid_rack() const { return _rack; } +#endif private: bool _denormal_protection; @@ -113,6 +128,10 @@ private: /** Buffer that we should use for gain automation */ gain_t* _gain_automation_buffer; + +#if HAVE_SOUNDGRID + SoundGridRack* _rack; +#endif }; diff --git a/libs/ardour/ardour/sg_rack.h b/libs/ardour/ardour/sg_rack.h index 1c655c5a98..35469e4f66 100644 --- a/libs/ardour/ardour/sg_rack.h +++ b/libs/ardour/ardour/sg_rack.h @@ -44,26 +44,23 @@ class SoundGridRack : public SessionObject { void add_plugin (boost::shared_ptr); void remove_plugin (boost::shared_ptr); - void set_gain (gain_t); void set_input_gain (gain_t); + + void set_fader (gain_t); + double get_fader() const; XMLNode& get_state() { return *(new XMLNode ("SGRack")); } int set_state (const XMLNode&, int /* version*/) { return 0; } - int32_t jack_port_as_input (const std::string& port_name); - std::string input_as_jack_port (uint32_t chn); - int make_connections (); + + uint32_t id() const { return _rack_id; } + uint32_t type() const { return _cluster_type; } private: - typedef std::map ChannelJackMap; - ChannelJackMap channel_jack_map; - typedef std::map JackChannelMap; - JackChannelMap jack_channel_map; - Glib::Threads::Mutex map_lock; - Route& _route; uint32_t _rack_id; + uint32_t _cluster_type; typedef std::list > PluginList; PluginList _plugins; diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index c47af51332..23cf33cf8e 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -139,7 +139,7 @@ Route::init () /* add amp processor */ - _amp.reset (new Amp (_session)); + _amp.reset (new Amp (_session, _sg_rack)); add_processor (_amp, PostFader); /* create standard processors: meter, main outs, monitor out; diff --git a/libs/ardour/sg_rack.cc b/libs/ardour/sg_rack.cc index 0faef9aee9..f528a4bf73 100644 --- a/libs/ardour/sg_rack.cc +++ b/libs/ardour/sg_rack.cc @@ -23,6 +23,7 @@ #include "ardour/ardour.h" #include "ardour/debug.h" #include "ardour/route.h" +#include "ardour/track.h" #include "ardour/session.h" #include "ardour/sg_rack.h" #include "ardour/soundgrid.h" @@ -37,7 +38,24 @@ SoundGridRack::SoundGridRack (Session& s, Route& r, const std::string& name) { DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Creating SG Chainer for %1\n", r.name())); - if (SoundGrid::instance().add_rack_synchronous (eClusterType_Input, _rack_id)) { + if (r.is_hidden()) { + return; + } + + if (dynamic_cast (&r) != 0) { + _cluster_type = eClusterType_Input; + } else { + /* bus */ + if (r.is_master()) { + _cluster_type = eClusterType_Input; + } else if (r.is_monitor()) { + _cluster_type = eClusterType_Input; + } else { + _cluster_type = eClusterType_Input; + } + } + + if (SoundGrid::instance().add_rack_synchronous (_cluster_type, _rack_id)) { throw failed_constructor(); } @@ -51,7 +69,7 @@ SoundGridRack::SoundGridRack (Session& s, Route& r, const std::string& name) SoundGridRack::~SoundGridRack () { DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Destroying SG Chainer for %1\n", _route.name())); - (void) SoundGrid::instance().remove_rack_synchronous (eClusterType_Input, _rack_id); + (void) SoundGrid::instance().remove_rack_synchronous (_cluster_type, _rack_id); } int @@ -59,23 +77,37 @@ SoundGridRack::make_connections () { DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Mapping input for %1\n", _route.name())); - /* input */ + /* we need to deliver out output (essentially at the fader) to the SG server, which will + happen via the native OS audio driver (and thus via JACK). the output needs to get to + our chainer, so we map its input(s) to one or more unused JACK ports. we then connect + our output JACK ports to these JACK ports, thus establishing signal flow into the chainer. + */ +#if 0 string portname; - - portname = SoundGrid::instance().sg_port_as_jack_port (SoundGrid::TrackInputPort (_rack_id, 0, eMixMatrixSub_Input)); + + portname = SoundGrid::instance().sg_port_as_jack_port (SoundGrid::TrackInputPort (_rack_id, eChainerSub_NoSub, (uint32_t) -1)); if (portname.empty()) { return -1; } +#endif - /* output */ + _route.input()->disconnect (this); + _route.output()->disconnect (this); - portname = SoundGrid::instance().sg_port_as_jack_port (SoundGrid::TrackOutputPort (_rack_id, 0, eMixMatrixSub_PostPan)); + /* wire up the driver input to the chainer input, thus allowing us to pick up data from the native OS driver + (where JACK will deliver it) + */ - if (portname.empty()) { - return -1; - } + SoundGrid::instance().connect (SoundGrid::PhysicalInputPort (0), + SoundGrid::DriverOutputPort (0)); + + SoundGrid::instance().connect (SoundGrid::DriverInputPort (0), + SoundGrid::TrackInputPort (_rack_id, eChainerSub_NoSub, (uint32_t) -1)); + + SoundGrid::instance().connect (SoundGrid::TrackOutputPort (_rack_id, eChainerSub_Left, eMixMatrixSub_PostFader), + SoundGrid::PhysicalOutputPort (0)); return 0; } @@ -91,8 +123,18 @@ SoundGridRack::remove_plugin (boost::shared_ptr) } void -SoundGridRack::set_gain (gain_t) +SoundGridRack::set_fader (gain_t v) { + /* convert to SoundGrid value range */ + + v *= 1000.0; + + if (SoundGrid::instance().set_gain (_cluster_type, _rack_id, v) != 0) { + return; + } + + DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("fader level for %1:%2 set to %3\n", + _cluster_type, _rack_id, v)); } void @@ -100,28 +142,18 @@ SoundGridRack::set_input_gain (gain_t) { } -int32_t -SoundGridRack::jack_port_as_input (const std::string& port_name) +double +SoundGridRack::get_fader() const { - JackChannelMap::iterator x; - Glib::Threads::Mutex::Lock lm (map_lock); - - if ((x = jack_channel_map.find (port_name)) != jack_channel_map.end()) { - return x->second; + double v; + + if (!SoundGrid::instance().get_gain (_cluster_type, _rack_id, v)) { + /* failure, return 0dB gain coefficient */ + return 1.0; } - return -1; -} + /* convert soundgrid value to our range (0..2.0) + */ -string -SoundGridRack::input_as_jack_port (uint32_t channel) -{ - ChannelJackMap::iterator x; - Glib::Threads::Mutex::Lock lm (map_lock); - - if ((x = channel_jack_map.find (channel)) != channel_jack_map.end()) { - return x->second; - } - - return string (); + return v / 1000.0; } diff --git a/libs/ardour/soundgrid.mm b/libs/ardour/soundgrid.mm index 1073ca413b..6ab8100a39 100644 --- a/libs/ardour/soundgrid.mm +++ b/libs/ardour/soundgrid.mm @@ -109,6 +109,9 @@ SoundGrid::configure_driver (uint32_t inputs, uint32_t outputs) Init_WSConfigSGDriverCommand (&myCommand, inputs, outputs, (WSDControllerHandle)this, 0); + inputs = 32; + outputs = 32; + DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Initializing SG driver to use %1 inputs + %2 outputs\n", inputs, outputs)); @@ -138,24 +141,28 @@ SoundGrid::initialize (void* window_handle, uint32_t max_track_inputs, uint32_t mixer_limits.m_clusterConfigs[eClusterType_Inputs].m_uiIndexNum = 2; // 1 for Ardour stuff, 1 for the coreaudio driver/JACK mixer_limits.m_clusterConfigs[eClusterType_Outputs].m_uiIndexNum = 2; // 1 for Ardour stuff, 1 for the coreaudio driver/JACK + max_track_inputs = 64; + //the following is for the tracks that this app will create. //This will probably be changed to eClusterType_Group in future. mixer_limits.m_clusterConfigs[eClusterType_Input].m_uiIndexNum = max_track_inputs; + DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Initializing SG Core with %1 tracks\n", max_track_inputs)); + + // XXX use portable, installable technique for this + char b[PATH_MAX+1]; getcwd (b, PATH_MAX); string driver_path = b; driver_path += "/../build/libs/soundgrid/SurfaceDriver_App.bundle"; - cerr << "Starting soundgrid with " << driver_path << endl; - if ((ret = InitializeMixerCoreDLL (&mixer_limits, driver_path.c_str(), window_handle, _sg_callback, this, &_sg)) != eNoErr) { DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Initialized SG core, ret = %1 core handle %2\n", ret, _sg)); return -1; } - DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Initialized SG core, core handle %2\n", _sg)); + DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("Initialized SG core, core handle %1\n", _sg)); } else { DEBUG_TRACE (DEBUG::SoundGrid, "SG core already initialized...\n"); } @@ -169,6 +176,7 @@ SoundGrid::teardown () WTErr retval = eNoErr; if (_sg) { + DEBUG_TRACE (DEBUG::SoundGrid, "shutting down SG core ...\n"); retval = UnInitializeMixerCoreDLL (_sg); _sg = 0; } @@ -211,7 +219,6 @@ SoundGrid::get (WSControlID* id, WSControlInfo* info) void SoundGrid::event_completed (int) { - cerr << "CURRENT LAN PORT: " << current_lan_port_name() << endl; } void @@ -498,8 +505,17 @@ SoundGrid::driver_register (const WSDCoreHandle ch, const WSCoreCallbackTable* c { if (_instance) { _instance->_host_handle = ch; - _instance->_callback_table = *ct; - _instance->_mixer_config = *mc; + + if (ct) { + _instance->_callback_table = *ct; + } else { + memset (&_instance->_callback_table, 0, sizeof (_instance->_callback_table)); + } + if (mc) { + _instance->_mixer_config = *mc; + } else { + memset (&_instance->_mixer_config, 0, sizeof (_instance->_mixer_config)); + } } } @@ -778,6 +794,11 @@ SoundGrid::disconnect (const Port& src, const Port& dst) int SoundGrid::map_io_as_jack_ports (uint32_t ninputs, uint32_t noutputs) { + return 0; + + ninputs = 0; + noutputs = 1; + /* the JACK ports for the native OS audio driver already exist, because JACK will have created them based on the native driver will have told JACK how many there are. @@ -789,52 +810,60 @@ SoundGrid::map_io_as_jack_ports (uint32_t ninputs, uint32_t noutputs) this is a special case that benefits from not calling connect() many times. */ - WSAssignmentsCommand inputsCommand; - Init_WSAddAssignmentsCommand(&inputsCommand, ninputs, (WSDControllerHandle)this, 0); + DEBUG_TRACE (DEBUG::SoundGrid, string_compose ("setting up wiring for %1 inputs and %2 outputs\n", ninputs, noutputs)); - for (uint32_t n = 0; n < ninputs; ++n) { + if (ninputs) { - WSAudioAssignment &assignment (inputsCommand.in_Assignments.m_aAssignments[n]); - ARDOUR::SoundGrid::DriverOutputPort dst (n); // readable driver/JACK port - ARDOUR::SoundGrid::PhysicalInputPort src (n); // where the signal should come from - - assignment.m_asgnSrc.m_chainerID.clusterType = src.type; - assignment.m_asgnSrc.m_chainerID.clusterHandle = src.id; - assignment.m_asgnSrc.m_eChainerSubIndex = (WEChainerSub) src.channel; - assignment.m_asgnSrc.m_uiMixMtxSubIndex = src.matrix_sub; + WSAssignmentsCommand inputsCommand; + Init_WSAddAssignmentsCommand(&inputsCommand, ninputs, (WSDControllerHandle)this, 0); - assignment.m_asgnDest.m_chainerID.clusterType = dst.type; - assignment.m_asgnDest.m_chainerID.clusterHandle = dst.id; - assignment.m_asgnDest.m_eChainerSubIndex = (WEChainerSub) dst.channel; - assignment.m_asgnDest.m_uiMixMtxSubIndex = dst.matrix_sub; - } - - if (command (&inputsCommand.m_command) != 0) { - return -1; - } - - WSAssignmentsCommand outputsCommand; - Init_WSAddAssignmentsCommand(&outputsCommand, noutputs, (WSDControllerHandle)this, 0); - - for (uint32_t n = 0; n < noutputs; ++n) { - - WSAudioAssignment &assignment (outputsCommand.in_Assignments.m_aAssignments[n]); - ARDOUR::SoundGrid::DriverInputPort src (n); // writable driver/JACK port - ARDOUR::SoundGrid::PhysicalOutputPort dst (n); // physical channel where the signal should go - - assignment.m_asgnSrc.m_chainerID.clusterType = src.type; - assignment.m_asgnSrc.m_chainerID.clusterHandle = src.id; - assignment.m_asgnSrc.m_eChainerSubIndex = (WEChainerSub) src.channel; - assignment.m_asgnSrc.m_uiMixMtxSubIndex = src.matrix_sub; + for (uint32_t n = 0; n < ninputs; ++n) { + + WSAudioAssignment &assignment (inputsCommand.in_Assignments.m_aAssignments[n]); + ARDOUR::SoundGrid::DriverOutputPort dst (n); // readable driver/JACK port + ARDOUR::SoundGrid::PhysicalInputPort src (n); // where the signal should come from + + assignment.m_asgnSrc.m_chainerID.clusterType = src.type; + assignment.m_asgnSrc.m_chainerID.clusterHandle = src.id; + assignment.m_asgnSrc.m_eChainerSubIndex = (WEChainerSub) src.channel; + assignment.m_asgnSrc.m_uiMixMtxSubIndex = src.matrix_sub; + + assignment.m_asgnDest.m_chainerID.clusterType = dst.type; + assignment.m_asgnDest.m_chainerID.clusterHandle = dst.id; + assignment.m_asgnDest.m_eChainerSubIndex = (WEChainerSub) dst.channel; + assignment.m_asgnDest.m_uiMixMtxSubIndex = dst.matrix_sub; + } - assignment.m_asgnDest.m_chainerID.clusterType = dst.type; - assignment.m_asgnDest.m_chainerID.clusterHandle = dst.id; - assignment.m_asgnDest.m_eChainerSubIndex = (WEChainerSub) dst.channel; - assignment.m_asgnDest.m_uiMixMtxSubIndex = dst.matrix_sub; + if (command (&inputsCommand.m_command) != 0) { + return -1; + } } - if (command (&outputsCommand.m_command) != 0) { - return -1; + if (noutputs) { + + WSAssignmentsCommand outputsCommand; + Init_WSAddAssignmentsCommand(&outputsCommand, noutputs, (WSDControllerHandle)this, 0); + + for (uint32_t n = 0; n < noutputs; ++n) { + + WSAudioAssignment &assignment (outputsCommand.in_Assignments.m_aAssignments[n]); + ARDOUR::SoundGrid::DriverInputPort src (n); // writable driver/JACK port + ARDOUR::SoundGrid::PhysicalOutputPort dst (n); // physical channel where the signal should go + + assignment.m_asgnSrc.m_chainerID.clusterType = src.type; + assignment.m_asgnSrc.m_chainerID.clusterHandle = src.id; + assignment.m_asgnSrc.m_eChainerSubIndex = (WEChainerSub) src.channel; + assignment.m_asgnSrc.m_uiMixMtxSubIndex = src.matrix_sub; + + assignment.m_asgnDest.m_chainerID.clusterType = dst.type; + assignment.m_asgnDest.m_chainerID.clusterHandle = dst.id; + assignment.m_asgnDest.m_eChainerSubIndex = (WEChainerSub) dst.channel; + assignment.m_asgnDest.m_uiMixMtxSubIndex = dst.matrix_sub; + } + + if (command (&outputsCommand.m_command) != 0) { + return -1; + } } return 0;