diff --git a/SConstruct b/SConstruct index fcc5382e92..85d8b56224 100644 --- a/SConstruct +++ b/SConstruct @@ -457,6 +457,16 @@ libraries['flac'] = conf.Finish () # or if that fails... #libraries['flac'] = LibraryInfo (LIBS='FLAC') +# boost (we don't link against boost, just use some header files) + +libraries['boost'] = LibraryInfo () +conf = Configure (libraries['boost']) +if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == 0: + print "Boost header files do not appear to be installed." + sys.exit (1) + +libraries['boost'] = conf.Finish () + # # Check for liblo diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index bca27c7231..345f715d39 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -874,9 +874,10 @@ ARDOUR_UI::session_add_midi_track () } void -ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode) +ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many) { - boost::shared_ptr route; + boost::shared_ptr route; + vector > routes; if (session == 0) { warning << _("You cannot add a track without a session already loaded.") << endmsg; @@ -885,9 +886,16 @@ ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t o try { if (disk) { - if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) { - error << _("could not create new audio track") << endmsg; + routes = session->new_audio_track (input_channels, output_channels, mode, how_many); + + if (routes.size() != how_many) { + if (how_many == 1) { + error << _("could not create a new audio track") << endmsg; + } else { + error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg; + } } + } else { if ((route = session->new_audio_route (input_channels, output_channels)) == 0) { error << _("could not create new audio bus") << endmsg; @@ -2075,10 +2083,10 @@ ARDOUR_UI::add_route () /* XXX do something with name template */ - while (count) { - if (track) { - session_add_audio_track (input_chan, output_chan, add_route_dialog->mode()); - } else { + if (track) { + session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count); + } else { + while (count) { session_add_audio_bus (input_chan, output_chan); } --count; diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index c8d0d70a7d..ebb5c76838 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -189,12 +189,12 @@ class ARDOUR_UI : public Gtkmm2ext::UI void add_route (); - void session_add_audio_track (int input_channels, int32_t output_channels, ARDOUR::TrackMode mode) { - session_add_audio_route (true, input_channels, output_channels, mode); + void session_add_audio_track (int input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many) { + session_add_audio_route (true, input_channels, output_channels, mode, how_many); } void session_add_audio_bus (int input_channels, int32_t output_channels) { - session_add_audio_route (false, input_channels, output_channels, ARDOUR::Normal); + session_add_audio_route (false, input_channels, output_channels, ARDOUR::Normal, 1); } void session_add_midi_track (); @@ -532,7 +532,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI void save_template (); - void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode); + void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many); void set_transport_sensitivity (bool); diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc index 238f81dd4f..3d8e99ad6e 100644 --- a/gtk2_ardour/ardour_ui_ed.cc +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -194,7 +194,7 @@ ARDOUR_UI::install_actions () ActionManager::register_action (common_actions, X_("About"), _("About"), mem_fun(*this, &ARDOUR_UI::show_splash)); act = ActionManager::register_toggle_action (common_actions, X_("ToggleColorManager"), _("Colors"), mem_fun(*this, &ARDOUR_UI::toggle_color_manager)); - act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal)); + act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal, 1)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (common_actions, X_("AddAudioBus"), _("Add Audio Bus"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_bus), 1, 1)); ActionManager::session_sensitive_actions.push_back (act); diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc index b6fdefa4d3..4128348e3a 100644 --- a/gtk2_ardour/editor_audio_import.cc +++ b/gtk2_ardour/editor_audio_import.cc @@ -332,17 +332,21 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32 case ImportAsTrack: { - boost::shared_ptr at (session->new_audio_track (in_chans, out_chans, Normal)); - copy = new AudioRegion (region); - at->diskstream()->playlist()->add_region (*copy, pos); + vector > at (session->new_audio_track (in_chans, out_chans, Normal, 1)); + if (!at.empty()) { + copy = new AudioRegion (region); + at.front()->diskstream()->playlist()->add_region (*copy, pos); + } break; } case ImportAsTapeTrack: { - boost::shared_ptr at (session->new_audio_track (in_chans, out_chans, Destructive)); - copy = new AudioRegion (region); - at->diskstream()->playlist()->add_region (*copy, pos); + vector > at (session->new_audio_track (in_chans, out_chans, Destructive)); + if (!at.empty()) { + copy = new AudioRegion (region); + at.front()->diskstream()->playlist()->add_region (*copy, pos); + } break; } } diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 00a0ce6b19..d13e917ff0 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -121,6 +121,9 @@ class AudioEngine : public sigc::trackable uint32_t n_physical_outputs () const; uint32_t n_physical_inputs () const; + void get_physical_outputs (std::vector&); + void get_physical_inputs (std::vector&); + std::string get_nth_physical_output (uint32_t n) { return get_nth_physical (n, JackPortIsInput); } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 3763ebe91e..757d13f79b 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -536,7 +536,7 @@ class Session : public sigc::trackable, public Stateful /* fundamental operations. duh. */ - boost::shared_ptr new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal); + std::vector > new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal, uint32_t how_many = 1); boost::shared_ptr new_audio_route (int input_channels, int output_channels); void remove_route (boost::shared_ptr); @@ -1517,7 +1517,7 @@ class Session : public sigc::trackable, public Stateful SerializedRCUManager routes; - void add_route (boost::shared_ptr); + void add_route (boost::shared_ptr, bool save = true); uint32_t destructive_index; int load_routes (const XMLNode&); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 4a4659d1df..5f86f21762 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -742,6 +742,52 @@ AudioEngine::n_physical_inputs () const return i; } +void +AudioEngine::get_physical_inputs (vector& ins) +{ + const char ** ports; + uint32_t i = 0; + + if (!_jack) { + return; + } + + if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) { + return; + } + + if (ports) { + for (i = 0; ports[i]; ++i) { + ins.push_back (ports[i]); + } + cerr << "got " << ins.size() << " physical ins\n"; + free (ports); + } +} + +void +AudioEngine::get_physical_outputs (vector& outs) +{ + const char ** ports; + uint32_t i = 0; + + if (!_jack) { + return; + } + + if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) { + return; + } + + if (ports) { + for (i = 0; ports[i]; ++i) { + outs.push_back (ports[i]); + } + cerr << "got " << outs.size() << " physical outs\n"; + free (ports); + } +} + string AudioEngine::get_nth_physical (uint32_t n, int flag) { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 02c62eefa1..107fae2585 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -111,8 +111,6 @@ Route::init () Route::~Route () { - cerr << "deleting route " << _name << endl; - clear_redirects (this); if (_control_outs) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 378d4763bc..dfa7468725 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -450,9 +450,7 @@ Session::~Session () RouteList::iterator tmp; tmp = i; ++tmp; - cerr << "BEFORE: use count on route " << (*i)->name() << " = " << (*i).use_count() << endl; (*i)->drop_references (); - cerr << "AFTER: use count on route " << (*i)->name() << " = " << (*i).use_count() << endl; i = tmp; } r->clear (); @@ -1671,15 +1669,15 @@ Session::resort_routes_using (shared_ptr r) } -shared_ptr -Session::new_audio_track (int input_channels, int output_channels, TrackMode mode) +vector > +Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, uint32_t how_many) { char track_name[32]; + uint32_t track_id = 0; uint32_t n = 0; uint32_t channels_used = 0; string port; - uint32_t nphysical_in; - uint32_t nphysical_out; + vector > ret; /* count existing audio tracks */ @@ -1696,97 +1694,125 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod } } - /* check for duplicate route names, since we might have pre-existing - routes with this name (e.g. create Audio1, Audio2, delete Audio1, - save, close,restart,add new route - first named route is now - Audio2) - */ + vector physinputs; + vector physoutputs; + uint32_t nphysical_in; + uint32_t nphysical_out; - do { - snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, n+1); - if (route_by_name (track_name) == 0) { - break; + _engine.get_physical_outputs (physoutputs); + _engine.get_physical_inputs (physinputs); + + while (how_many) { + + /* check for duplicate route names, since we might have pre-existing + routes with this name (e.g. create Audio1, Audio2, delete Audio1, + save, close,restart,add new route - first named route is now + Audio2) + */ + + + do { + ++track_id; + + snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, track_id); + + if (route_by_name (track_name) == 0) { + break; + } + + } while (track_id < (UINT_MAX-1)); + + if (input_auto_connect & AutoConnectPhysical) { + nphysical_in = min (n_physical_inputs, physinputs.size()); + } else { + nphysical_in = 0; } - n++; - - } while (n < (UINT_MAX-1)); - - if (input_auto_connect & AutoConnectPhysical) { - nphysical_in = n_physical_inputs; - } else { - nphysical_in = 0; - } - - if (output_auto_connect & AutoConnectPhysical) { - nphysical_out = n_physical_outputs; - } else { - nphysical_out = 0; - } - - try { - shared_ptr track (new AudioTrack (*this, track_name, Route::Flag (0), mode)); - - if (track->ensure_io (input_channels, output_channels, false, this)) { - error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"), - input_channels, output_channels) - << endmsg; + + if (output_auto_connect & AutoConnectPhysical) { + nphysical_out = min (n_physical_outputs, physinputs.size()); + } else { + nphysical_out = 0; } - - if (nphysical_in) { - for (uint32_t x = 0; x < track->n_inputs() && x < nphysical_in; ++x) { + + try { + shared_ptr track (new AudioTrack (*this, track_name, Route::Flag (0), mode)); + + if (track->ensure_io (input_channels, output_channels, false, this)) { + error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"), + input_channels, output_channels) + << endmsg; + } + + if (nphysical_in) { + for (uint32_t x = 0; x < track->n_inputs() && x < nphysical_in; ++x) { + + port = ""; + + if (input_auto_connect & AutoConnectPhysical) { + port = physinputs[(channels_used+x)%nphysical_in]; + } + + if (port.length() && track->connect_input (track->input (x), port, this)) { + break; + } + } + } + + for (uint32_t x = 0; x < track->n_outputs(); ++x) { port = ""; - if (input_auto_connect & AutoConnectPhysical) { - port = _engine.get_nth_physical_input ((channels_used+x)%nphysical_in); - } + if (nphysical_out && (output_auto_connect & AutoConnectPhysical)) { + port = physoutputs[(channels_used+x)%nphysical_out]; + } else if (output_auto_connect & AutoConnectMaster) { + if (_master_out) { + port = _master_out->input (x%_master_out->n_inputs())->name(); + } + } - if (port.length() && track->connect_input (track->input (x), port, this)) { + if (port.length() && track->connect_output (track->output (x), port, this)) { break; } } + + channels_used += track->n_inputs (); + + if (_control_out) { + vector cports; + uint32_t ni = _control_out->n_inputs(); + + for (n = 0; n < ni; ++n) { + cports.push_back (_control_out->input(n)->name()); + } + + track->set_control_outs (cports); + } + + track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes)); + track->set_remote_control_id (ntracks()); + + ret.push_back (track); + } + + catch (failed_constructor &err) { + error << _("Session: could not create new audio track.") << endmsg; + // XXX should we delete the tracks already created? + ret.clear (); + return ret; } - for (uint32_t x = 0; x < track->n_outputs(); ++x) { - - port = ""; - - if (nphysical_out && (output_auto_connect & AutoConnectPhysical)) { - port = _engine.get_nth_physical_output ((channels_used+x)%nphysical_out); - } else if (output_auto_connect & AutoConnectMaster) { - if (_master_out) { - port = _master_out->input (x%_master_out->n_inputs())->name(); - } - } - - if (port.length() && track->connect_output (track->output (x), port, this)) { - break; - } - } - - if (_control_out) { - vector cports; - uint32_t ni = _control_out->n_inputs(); - - for (n = 0; n < ni; ++n) { - cports.push_back (_control_out->input(n)->name()); - } - - track->set_control_outs (cports); - } - - track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes)); - - add_route (track); - - track->set_remote_control_id (ntracks()); - return track; + --how_many; } - catch (failed_constructor &err) { - error << _("Session: could not create new audio track.") << endmsg; - return shared_ptr ((AudioTrack*) 0); + if (!ret.empty()) { + for (vector >::iterator x = ret.begin(); x != ret.end(); ++x) { + add_route ((*x), false); + } + + save_state (_current_snapshot_name); } + + return ret; } shared_ptr @@ -1879,7 +1905,7 @@ Session::new_audio_route (int input_channels, int output_channels) } void -Session::add_route (boost::shared_ptr route) +Session::add_route (boost::shared_ptr route, bool save) { { RCUWriter writer (routes); @@ -1902,7 +1928,10 @@ Session::add_route (boost::shared_ptr route) } set_dirty(); - save_state (_current_snapshot_name); + + if (save) { + save_state (_current_snapshot_name); + } RouteAdded (route); /* EMIT SIGNAL */ } @@ -1926,9 +1955,6 @@ Session::add_diskstream (boost::shared_ptr dstream) diskstream_playlist_changed (dstream); dstream->prepare (); - - set_dirty(); - save_state (_current_snapshot_name); } void