Remove beat entry from meter dialog (beats are not allowed in API), clean up some...
[ardour.git] / libs / ardour / session.cc
index ad629f5d6e53213dd092571e03f289e779a22601..a992e89458550e3f6d78e77373e0aad7a41b37c8 100644 (file)
@@ -46,6 +46,7 @@
 #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>
@@ -105,6 +106,7 @@ 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<int> Session::AskAboutPendingState;
+sigc::signal<int,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch;
 sigc::signal<void> Session::SendFeedback;
 
 sigc::signal<void> Session::SMPTEOffsetChanged;
@@ -665,9 +667,13 @@ Session::when_engine_running ()
 
        /* 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 */
@@ -723,6 +729,8 @@ Session::when_engine_running ()
                error << _("cannot setup Click I/O") << endmsg;
        }
 
+       BootMessage (_("Compute I/O Latencies"));
+
        set_worst_io_latencies ();
 
        if (_clicking) {
@@ -733,6 +741,8 @@ Session::when_engine_running ()
           to the physical outputs currently available
        */
 
+       BootMessage (_("Set up standard connections"));
+
        /* ONE: MONO */
 
        for (uint32_t np = 0; np < n_physical_audio_outputs; ++np) {
@@ -837,11 +847,15 @@ Session::when_engine_running ()
                }
                add_connection (c);
        } 
+       
+       BootMessage (_("Connect ports"));
 
        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) {
@@ -869,14 +883,17 @@ Session::when_engine_running ()
        
        _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
 
-
        /* 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
     
@@ -1294,11 +1311,11 @@ Session::step_back_from_record ()
        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);   
                                }
@@ -2565,6 +2582,14 @@ Session::region_name (string& result, string base, bool newlevel) const
 
 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;
@@ -2573,45 +2598,52 @@ Session::add_region (boost::shared_ptr<Region> region)
        { 
                Glib::Mutex::Lock lm (region_lock);
 
-               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) {
-
-                       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*/
+                               
+                       }
                }
        }
 
@@ -2622,9 +2654,34 @@ Session::add_region (boost::shared_ptr<Region> region)
        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 */
+               }
        }
 }
 
@@ -2819,6 +2876,9 @@ Session::add_source (boost::shared_ptr<Source> source)
                        set_dirty();
                }
 
+               if (Config->get_auto_analyse_audio()) {
+                       Analyser::queue_source_for_analysis (source, false);
+               }
        } 
 }
 
@@ -3606,18 +3666,36 @@ void
 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);
 
@@ -3626,7 +3704,12 @@ Session::ensure_passthru_buffers (uint32_t howmany)
 #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);