#include <glibmm/thread.h>
#include <glibmm/miscutils.h>
+#include <glibmm/fileutils.h>
#include <pbd/error.h>
#include <glibmm/thread.h>
#include <ardour/audioengine.h>
#include <ardour/configuration.h>
#include <ardour/session.h>
+#include <ardour/analyser.h>
#include <ardour/audio_diskstream.h>
#include <ardour/utils.h>
#include <ardour/audioplaylist.h>
const char* Session::interchange_dir_name = X_("interchange");
const char* Session::export_dir_name = X_("export");
+bool Session::_disable_all_loaded_plugins = false;
+
Session::compute_peak_t Session::compute_peak = 0;
Session::find_peaks_t Session::find_peaks = 0;
Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0;
Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
+sigc::signal<void,std::string> Session::Dialog;
sigc::signal<int> Session::AskAboutPendingState;
+sigc::signal<int,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch;
sigc::signal<void> Session::SendFeedback;
sigc::signal<void> Session::SMPTEOffsetChanged;
sigc::signal<void> Session::StartTimeChanged;
sigc::signal<void> Session::EndTimeChanged;
+sigc::signal<void> Session::AutoBindingOn;
+sigc::signal<void> Session::AutoBindingOff;
+
+
+sigc::signal<void, std::string, std::string> Session::Exported;
+
int
Session::find_session (string str, string& path, string& snapshot, bool& isnew)
{
first_stage_init (fullpath, snapshot_name);
- new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+ new_session = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+
if (new_session) {
if (create (new_session, mix_template, compute_initial_length())) {
- cerr << "create failed\n";
destroy ();
throw failed_constructor ();
}
}
if (!rl.empty()) {
- add_routes (rl);
+ add_routes (rl, false);
}
}
throw failed_constructor ();
}
- store_recent_sessions(_name, _path);
+ store_recent_sessions (_name, _path);
- bool was_dirty = dirty ();
-
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
- Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
- if (was_dirty) {
- DirtyChanged (); /* EMIT SIGNAL */
- }
+ Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
}
Session::~Session ()
remove_pending_capture_state ();
_state_of_the_state = StateOfTheState (CannotSave|Deletion);
+
_engine.remove_session ();
GoingAway (); /* EMIT SIGNAL */
tmp = i;
++tmp;
-
+
i->second->drop_references ();
-
+
i = tmp;
}
-
audio_sources.clear ();
-
+
#ifdef TRACK_DESTRUCTION
cerr << "delete mix groups\n";
#endif /* TRACK_DESTRUCTION */
/* we don't want to run execute this again */
+ BootMessage (_("Set block size and sample rate"));
+
set_block_size (_engine.frames_per_cycle());
set_frame_rate (_engine.frame_rate());
+ BootMessage (_("Using configuration"));
+
Config->map_parameters (mem_fun (*this, &Session::config_changed));
/* every time we reconnect, recompute worst case output latencies */
error << _("cannot setup Click I/O") << endmsg;
}
+ BootMessage (_("Compute I/O Latencies"));
+
set_worst_io_latencies ();
if (_clicking) {
to the physical outputs currently available
*/
+ BootMessage (_("Set up standard connections"));
+
/* ONE: MONO */
for (uint32_t np = 0; np < n_physical_audio_outputs; ++np) {
}
add_connection (c);
}
+
+ BootMessage (_("Setup signal flow and plugins"));
hookup_io ();
/* catch up on send+insert cnts */
+ BootMessage (_("Catch up with send/insert state"));
+
insert_cnt = 0;
for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
/* hook us up to the engine */
+ BootMessage (_("Connect to engine"));
+
_engine.set_session (this);
#ifdef HAVE_LIBLO
/* and to OSC */
+ BootMessage (_("OSC startup"));
+
osc->set_session (*this);
#endif
- _state_of_the_state = Clean;
-
- DirtyChanged (); /* EMIT SIGNAL */
}
void
_state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
+
if (auditioner == 0) {
/* we delay creating the auditioner till now because
_state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
+
/* now handle the whole enchilada as if it was one
graph reorder event.
*/
}
last_loopend = location->end();
-
}
void
auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed));
location->set_auto_punch (true, this);
+
+
+ auto_punch_changed (location);
+
auto_punch_location_changed (location);
}
auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed));
location->set_auto_loop (true, this);
+
+ /* take care of our stuff first */
+
+ auto_loop_changed (location);
+
+ /* now tell everyone else */
+
auto_loop_location_changed (location);
}
if (g_atomic_int_get (&_record_status) == Recording) {
g_atomic_int_set (&_record_status, Enabled);
- if (Config->get_monitoring_model() == HardwareMonitoring) {
+ if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
- if (Config->get_auto_input() && (*i)->record_enabled ()) {
+ if ((*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
}
failed:
if (!new_routes.empty()) {
- add_routes (new_routes, false);
- save_state (_current_snapshot_name);
+ add_routes (new_routes, true);
}
return ret;
failure:
if (!ret.empty()) {
- add_routes (ret, false);
- save_state (_current_snapshot_name);
+ add_routes (ret, true);
}
return ret;
void
Session::add_region (boost::shared_ptr<Region> region)
+{
+ vector<boost::shared_ptr<Region> > v;
+ v.push_back (region);
+ add_regions (v);
+}
+
+void
+Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions)
{
boost::shared_ptr<AudioRegion> ar;
boost::shared_ptr<AudioRegion> oar;
{
Glib::Mutex::Lock lm (region_lock);
- if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
-
- AudioRegionList::iterator x;
-
- for (x = audio_regions.begin(); x != audio_regions.end(); ++x) {
-
- oar = boost::dynamic_pointer_cast<AudioRegion> (x->second);
-
- if (ar->region_list_equivalent (oar)) {
- break;
- }
- }
-
- if (x == audio_regions.end()) {
-
- pair<AudioRegionList::key_type,AudioRegionList::mapped_type> entry;
-
- entry.first = region->id();
- entry.second = ar;
+ for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
+
+ boost::shared_ptr<Region> region = *ii;
+
+ if (region == 0) {
- pair<AudioRegionList::iterator,bool> x = audio_regions.insert (entry);
+ error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
+ } else if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
- if (!x.second) {
- return;
+ AudioRegionList::iterator x;
+
+ for (x = audio_regions.begin(); x != audio_regions.end(); ++x) {
+
+ oar = boost::dynamic_pointer_cast<AudioRegion> (x->second);
+
+ if (ar->region_list_equivalent (oar)) {
+ break;
+ }
}
+
+ if (x == audio_regions.end()) {
+
+ pair<AudioRegionList::key_type,AudioRegionList::mapped_type> entry;
+
+ entry.first = region->id();
+ entry.second = ar;
+
+ pair<AudioRegionList::iterator,bool> x = audio_regions.insert (entry);
+
+
+ if (!x.second) {
+ return;
+ }
+
+ added = true;
+ }
- added = true;
- }
-
- } else {
-
- fatal << _("programming error: ")
- << X_("unknown region type passed to Session::add_region()")
- << endmsg;
- /*NOTREACHED*/
-
+ } else {
+
+ fatal << _("programming error: ")
+ << X_("unknown region type passed to Session::add_region()")
+ << endmsg;
+ /*NOTREACHED*/
+
+ }
}
}
set_dirty();
if (added) {
- region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
- region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
- AudioRegionAdded (ar); /* EMIT SIGNAL */
+
+ vector<boost::weak_ptr<AudioRegion> > v;
+ boost::shared_ptr<AudioRegion> first_ar;
+
+ for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
+
+ boost::shared_ptr<Region> region = *ii;
+ boost::shared_ptr<AudioRegion> ar;
+
+ if (region == 0) {
+
+ error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
+
+ } else if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
+ v.push_back (ar);
+
+ if (!first_ar) {
+ first_ar = ar;
+ }
+ }
+
+ region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
+ region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
+ }
+
+ if (!v.empty()) {
+ AudioRegionsAdded (v); /* EMIT SIGNAL */
+ }
}
}
set_dirty();
}
+ if (Config->get_auto_analyse_audio()) {
+ Analyser::queue_source_for_analysis (source, false);
+ }
}
}
Session::tempo_map_changed (Change ignored)
{
clear_clicks ();
+
+ for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+ (*i)->update_after_tempo_map_change ();
+ }
+
+ for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
+ (*i)->update_after_tempo_map_change ();
+ }
+
set_dirty ();
}
void
Session::ensure_passthru_buffers (uint32_t howmany)
{
+ if (current_block_size == 0) {
+ return;
+ }
+
while (howmany > _passthru_buffers.size()) {
Sample *p;
#ifdef NO_POSIX_MEMALIGN
p = (Sample *) malloc(current_block_size * sizeof(Sample));
#else
- posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample));
+ if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample)) != 0) {
+ fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
+ current_block_size, sizeof (Sample), strerror (errno))
+ << endmsg;
+ /*NOTREACHED*/
+ }
#endif
_passthru_buffers.push_back (p);
#ifdef NO_POSIX_MEMALIGN
p = (Sample *) malloc(current_block_size * sizeof(Sample));
#else
- posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * 4);
+ if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * 4) != 0) {
+ fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
+ current_block_size, sizeof (Sample), strerror (errno))
+ << endmsg;
+ /*NOTREACHED*/
+ }
#endif
memset (p, 0, sizeof (Sample) * current_block_size);
_silent_buffers.push_back (p);
vector<Sample*>&
Session::get_silent_buffers (uint32_t howmany)
{
+ if (howmany > _silent_buffers.size()) {
+
+ error << string_compose (_("Programming error: get_silent_buffers() called for %1 buffers but only %2 exist"),
+ howmany, _silent_buffers.size()) << endmsg;
+
+ if (howmany > 1000) {
+ cerr << "ABSURD: more than 1000 silent buffers requested!\n";
+ abort ();
+ }
+
+ while (howmany > _silent_buffers.size()) {
+ Sample *p = 0;
+
+#ifdef NO_POSIX_MEMALIGN
+ p = (Sample *) malloc(current_block_size * sizeof(Sample));
+#else
+ if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * 4) != 0) {
+ fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
+ current_block_size, sizeof (Sample), strerror (errno))
+ << endmsg;
+ /*NOTREACHED*/
+ }
+#endif
+ _silent_buffers.push_back (p);
+ }
+ }
+
for (uint32_t i = 0; i < howmany; ++i) {
memset (_silent_buffers[i], 0, sizeof (Sample) * current_block_size);
}
+
return _silent_buffers;
}