Remove unnecessary 0 checks before delete; see http://www.parashift.com/c++-faq-lite...
[ardour.git] / libs / ardour / session.cc
index ed5aea1c376dd8f52a2d322a23c3fa76197515cd..8efef136d1e1abf1802f7bcc70a646aa0c80179a 100644 (file)
@@ -123,23 +123,31 @@ Session::Session (AudioEngine &eng,
          _scratch_buffers(new BufferSet()),
          _silent_buffers(new BufferSet()),
          _mix_buffers(new BufferSet()),
+         mmc (0),
          _mmc_port (default_mmc_port),
          _mtc_port (default_mtc_port),
          _midi_port (default_midi_port),
          _midi_clock_port (default_midi_clock_port),
          _session_dir (new SessionDirectory(fullpath)),
          pending_events (2048),
+         state_tree (0),
+         butler_mixdown_buffer (0),
+         butler_gain_buffer (0),
          post_transport_work((PostTransportWork)0),
          _send_smpte_update (false),
-         midi_requests (128),
+         midi_thread (pthread_t (0)),
+         midi_requests (128), // the size of this should match the midi request pool size
          diskstreams (new DiskstreamList),
          routes (new RouteList),
          auditioner ((Auditioner*) 0),
          _total_free_4k_blocks (0),
          _bundle_xml_node (0),
          _click_io ((IO*) 0),
+         click_data (0),
+         click_emphasis_data (0),
          main_outs (0),
          _metadata (new SessionMetadata())
+
 {
        bool new_session;
 
@@ -196,21 +204,30 @@ Session::Session (AudioEngine &eng,
          _scratch_buffers(new BufferSet()),
          _silent_buffers(new BufferSet()),
          _mix_buffers(new BufferSet()),
+         mmc (0),
          _mmc_port (default_mmc_port),
          _mtc_port (default_mtc_port),
          _midi_port (default_midi_port),
          _midi_clock_port (default_midi_clock_port),
          _session_dir ( new SessionDirectory(fullpath)),
          pending_events (2048),
+         state_tree (0),
+         butler_mixdown_buffer (0),
+         butler_gain_buffer (0),
          post_transport_work((PostTransportWork)0),
          _send_smpte_update (false),
+         midi_thread (pthread_t (0)),
          midi_requests (16),
          diskstreams (new DiskstreamList),
          routes (new RouteList),
+         auditioner ((Auditioner *) 0),
          _total_free_4k_blocks (0),
          _bundle_xml_node (0),
-         main_outs (0)
-
+         _click_io ((IO *) 0),
+         click_data (0),
+         click_emphasis_data (0),
+         main_outs (0),
+         _metadata (new SessionMetadata())
 {
        bool new_session;
 
@@ -316,18 +333,16 @@ Session::destroy ()
 
        /* clear state tree so that no references to objects are held any more */
 
-       if (state_tree) {
-               delete state_tree;
-       }
+       delete state_tree;
 
        terminate_butler_thread ();
        //terminate_midi_thread ();
 
-       if (click_data && click_data != default_click) {
+       if (click_data != default_click) {
                delete [] click_data;
        }
 
-       if (click_emphasis_data && click_emphasis_data != default_click_emphasis) {
+       if (click_emphasis_data != default_click_emphasis) {
                delete [] click_emphasis_data;
        }
 
@@ -471,19 +486,12 @@ Session::destroy ()
                i = tmp;
        }
 
-       if (butler_mixdown_buffer) {
-               delete [] butler_mixdown_buffer;
-       }
-
-       if (butler_gain_buffer) {
-               delete [] butler_gain_buffer;
-       }
+       delete [] butler_mixdown_buffer;
+       delete [] butler_gain_buffer;
 
        Crossfade::set_buffer_size (0);
 
-       if (mmc) {
-               delete mmc;
-       }
+       delete mmc;
 }
 
 void
@@ -1213,6 +1221,10 @@ Session::audible_frame () const
        nframes_t offset;
        nframes_t tf;
 
+       if (_transport_speed == 0.0f && non_realtime_work_pending()) {
+               return last_stop_frame;
+       }
+
        /* the first of these two possible settings for "offset"
           mean that the audible frame is stationary until
           audio emerges from the latency compensation
@@ -1241,24 +1253,43 @@ Session::audible_frame () const
        } else {
                tf = _transport_frame;
        }
-
-       if (_transport_speed == 0) {
-               return tf;
-       }
-
-       if (tf < offset) {
-               return 0;
-       }
-
+       
        ret = tf;
 
        if (!non_realtime_work_pending()) {
 
                /* MOVING */
 
-               /* take latency into account */
+               /* check to see if we have passed the first guaranteed
+                  audible frame past our last stopping position. if not,
+                  the return that last stopping point because in terms
+                  of audible frames, we have not moved yet.
+               */
+
+               if (_transport_speed > 0.0f) {
+
+                       if (!play_loop || !have_looped) {
+                               if (tf < last_stop_frame + offset) {
+                                       return last_stop_frame;
+                                       
+                               }
+                       } 
+                       
 
-               ret -= offset;
+                       /* forwards */
+                       ret -= offset;
+
+               } else if (_transport_speed < 0.0f) {
+
+                       /* XXX wot? no backward looping? */
+
+                       if (tf > last_stop_frame - offset) {
+                               return last_stop_frame;
+                       } else {
+                               /* backwards */
+                               ret += offset;
+                       }
+               }
        }
 
        return ret;
@@ -1305,9 +1336,7 @@ Session::set_block_size (nframes_t nframes)
 
                ensure_buffers(_scratch_buffers->available());
 
-               if (_gain_automation_buffer) {
-                       delete [] _gain_automation_buffer;
-               }
+               delete [] _gain_automation_buffer;
                _gain_automation_buffer = new gain_t[nframes];
 
                allocate_pan_automation_buffers (nframes, _npan_buffers, true);
@@ -1875,6 +1904,10 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
 
        _engine.get_physical_outputs (DataType::AUDIO, physoutputs);
        _engine.get_physical_inputs (DataType::AUDIO, physinputs);
+
+       n_physical_audio_outputs = physoutputs.size();
+       n_physical_audio_inputs = physinputs.size();
+
        control_id = ntracks() + nbusses() + 1;
 
        while (how_many) {
@@ -1900,21 +1933,24 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
                                goto failure;
                        }
 
-                       for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs().n_audio(); ++x) {
 
-                               port = "";
 
+                       /*
+                       for (uint32_t x = 0; n_physical_audio_inputs && x < bus->n_inputs(); ++x) {
+                                       
+                               port = "";
+                               
                                if (Config->get_input_auto_connect() & AutoConnectPhysical) {
-                                               port = physinputs[((n+x)%n_physical_inputs)];
-                               }
-
+                                       port = physinputs[((n+x)%n_physical_audio_inputs)];
+                               } 
+                               
                                if (port.length() && bus->connect_input (bus->input (x), port, this)) {
                                        break;
                                }
                        }
+                       */
 
-                       for (uint32_t x = 0; x < bus->n_outputs().n_audio(); ++x) {
-
+                       for (uint32_t x = 0; n_physical_audio_outputs && x < bus->n_outputs().n_audio(); ++x) {
                                port = "";
 
                                if (Config->get_output_auto_connect() & AutoConnectPhysical) {
@@ -1989,8 +2025,12 @@ Session::add_routes (RouteList& new_routes, bool save)
                        _control_out = (*x);
                }
 
-               add_bundle ((*x)->bundle_for_inputs());
-               add_bundle ((*x)->bundle_for_outputs());
+               /* only busses get automatic bundles formed */
+
+               if (!boost::dynamic_pointer_cast<Track> (*x)) {
+                       add_bundle ((*x)->bundle_for_inputs());
+                       add_bundle ((*x)->bundle_for_outputs());
+               }
        }
 
        if (_control_out && IO::connecting_legal) {
@@ -2110,6 +2150,8 @@ Session::remove_route (shared_ptr<Route> route)
 
        route->drop_references ();
 
+       sync_order_keys (N_("session"));
+
        /* save the new state of the world */
 
        if (save_state (_current_snapshot_name)) {
@@ -2234,8 +2276,6 @@ Session::update_route_solo_state ()
        bool is_track = false;
        bool signal = false;
 
-       /* caller must hold RouteLock */
-
        /* this is where we actually implement solo by changing
           the solo mute setting of each track.
        */
@@ -2335,7 +2375,24 @@ Session::catch_up_on_solo ()
           has.
        */
        update_route_solo_state();
-}
+}      
+
+void
+Session::catch_up_on_solo_mute_override ()
+{
+       if (Config->get_solo_model() != InverseMute) {
+               return;
+       }
+
+       /* this is called whenever the param solo-mute-override is
+          changed.
+       */
+       shared_ptr<RouteList> r = routes.reader ();
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               (*i)->catch_up_on_solo_mute_override ();
+       }
+}      
 
 shared_ptr<Route>
 Session::route_by_name (string name)
@@ -4214,8 +4271,13 @@ Session::get_silent_buffers (ChanCount count)
 BufferSet&
 Session::get_scratch_buffers (ChanCount count)
 {
-       assert(_scratch_buffers->available() >= count);
-       _scratch_buffers->set_count(count);
+       if (count != ChanCount::ZERO) {
+               assert(_scratch_buffers->available() >= count);
+               _scratch_buffers->set_count(count);
+       } else {
+               _scratch_buffers->set_count (_scratch_buffers->available());
+       }
+
        return *_scratch_buffers;
 }
 
@@ -4270,7 +4332,7 @@ Session::compute_initial_length ()
 }
 
 void
-Session::sync_order_keys ()
+Session::sync_order_keys (const char* base)
 {
        if (!Config->get_sync_all_route_ordering()) {
                /* leave order keys as they are */
@@ -4280,10 +4342,10 @@ Session::sync_order_keys ()
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               (*i)->sync_order_keys ();
+               (*i)->sync_order_keys (base);
        }
 
-       Route::SyncOrderKeys (); // EMIT SIGNAL
+       Route::SyncOrderKeys (base); // EMIT SIGNAL
 }
 
 void