various fixes to named selection mgmt and display, plus fixes for xfade mgmt and...
[ardour.git] / libs / ardour / audio_track.cc
index 98a2262f8683e6498ca5781ecb99ecc6d2643a4c..e7b1368fa4a40e704c8e312fa84c3a10956e8f13 100644 (file)
 
     $Id$
 */
-#include <pbd/error.h>
+
 #include <sigc++/retype.h>
 #include <sigc++/retype_return.h>
 #include <sigc++/bind.h>
 
+#include <pbd/error.h>
+#include <pbd/enumwriter.h>
+
 #include <ardour/audio_track.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/session.h>
 #include <ardour/redirect.h>
 #include <ardour/audioregion.h>
 #include <ardour/audiosource.h>
+#include <ardour/region_factory.h>
 #include <ardour/route_group_specialized.h>
 #include <ardour/insert.h>
 #include <ardour/audioplaylist.h>
+#include <ardour/playlist_factory.h>
 #include <ardour/panner.h>
 #include <ardour/utils.h>
 
@@ -64,13 +69,44 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
 AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
        : Track (sess, node)
 {
-       set_state (node);
+       _set_state (node, false);
 }
 
 AudioTrack::~AudioTrack ()
 {
 }
 
+int
+AudioTrack::set_mode (TrackMode m)
+{
+       if (m != _mode) {
+
+               if (_diskstream->set_destructive (m == Destructive)) {
+                       return -1;
+               }
+
+               _mode = m;
+               
+               TrackModeChanged (); /* EMIT SIGNAL */
+       }
+
+       return 0;
+}
+
+bool
+AudioTrack::can_use_mode (TrackMode m, bool& bounce_required)
+{
+       switch (m) {
+       case Normal:
+               bounce_required = false;
+               return true;
+               
+       case Destructive:
+       default:
+               return _diskstream->can_become_destructive (bounce_required);
+       }
+}
+
 int
 AudioTrack::deprecated_use_diskstream_connections ()
 {
@@ -186,23 +222,24 @@ AudioTrack::audio_diskstream() const
 
 int
 AudioTrack::set_state (const XMLNode& node)
+{
+       return _set_state (node, true);
+}
+
+int
+AudioTrack::_set_state (const XMLNode& node, bool call_base)
 {
        const XMLProperty *prop;
        XMLNodeConstIterator iter;
 
-       if (Route::set_state (node)) {
-               return -1;
+       if (call_base) {
+               if (Route::_set_state (node, call_base)) {
+                       return -1;
+               }
        }
 
        if ((prop = node.property (X_("mode"))) != 0) {
-               if (prop->value() == X_("normal")) {
-                       _mode = Normal;
-               } else if (prop->value() == X_("destructive")) {
-                       _mode = Destructive;
-               } else {
-                       warning << string_compose ("unknown audio track mode \"%1\" seen and ignored", prop->value()) << endmsg;
-                       _mode = Normal;
-               }
+               _mode = TrackMode (string_2_enum (prop->value(), _mode));
        } else {
                _mode = Normal;
        }
@@ -245,6 +282,10 @@ AudioTrack::set_state (const XMLNode& node)
                                sscanf (prop->value().c_str(), "%d", &x);
                                set_remote_control_id (x);
                        }
+
+               } else if (child->name() == X_("recenable")) {
+                       _rec_enable_control.set_state (*child);
+                       _session.add_controllable (&_rec_enable_control);
                }
        }
 
@@ -267,12 +308,11 @@ AudioTrack::state(bool full_state)
 
                freeze_node = new XMLNode (X_("freeze-info"));
                freeze_node->add_property ("playlist", _freeze_record.playlist->name());
-               snprintf (buf, sizeof (buf), "%d", (int) _freeze_record.state);
-               freeze_node->add_property ("state", buf);
+               freeze_node->add_property ("state", enum_2_string (_freeze_record.state));
 
                for (vector<FreezeRecordInsertInfo*>::iterator i = _freeze_record.insert_info.begin(); i != _freeze_record.insert_info.end(); ++i) {
                        inode = new XMLNode (X_("insert"));
-                       (*i)->id.print (buf);
+                       (*i)->id.print (buf, sizeof (buf));
                        inode->add_property (X_("id"), buf);
                        inode->add_child_copy ((*i)->state);
                
@@ -285,15 +325,8 @@ AudioTrack::state(bool full_state)
        /* Alignment: act as a proxy for the diskstream */
        
        XMLNode* align_node = new XMLNode (X_("alignment"));
-       switch (_diskstream->alignment_style()) {
-       case ExistingMaterial:
-               snprintf (buf, sizeof (buf), X_("existing"));
-               break;
-       case CaptureTime:
-               snprintf (buf, sizeof (buf), X_("capture"));
-               break;
-       }
-       align_node->add_property (X_("style"), buf);
+       AlignStyle as = _diskstream->alignment_style ();
+       align_node->add_property (X_("style"), enum_2_string (as));
        root.add_child_nocopy (*align_node);
 
        XMLNode* remote_control_node = new XMLNode (X_("remote_control"));
@@ -301,14 +334,7 @@ AudioTrack::state(bool full_state)
        remote_control_node->add_property (X_("id"), buf);
        root.add_child_nocopy (*remote_control_node);
 
-       switch (_mode) {
-       case Normal:
-               root.add_property (X_("mode"), X_("normal"));
-               break;
-       case Destructive:
-               root.add_property (X_("mode"), X_("destructive"));
-               break;
-       }
+       root.add_property (X_("mode"), enum_2_string (_mode));
 
        /* we don't return diskstream state because we don't
           own the diskstream exclusively. control of the diskstream
@@ -316,9 +342,11 @@ AudioTrack::state(bool full_state)
           diskstream.
        */
 
-       _diskstream->id().print (buf);
+       _diskstream->id().print (buf, sizeof (buf));
        root.add_property ("diskstream-id", buf);
 
+       root.add_child_nocopy (_rec_enable_control.get_state());
+
        return root;
 }
 
@@ -349,18 +377,18 @@ AudioTrack::set_state_part_two ()
                _freeze_record.insert_info.clear ();
                
                if ((prop = fnode->property (X_("playlist"))) != 0) {
-                       Playlist* pl = _session.playlist_by_name (prop->value());
+                       boost::shared_ptr<Playlist> pl = _session.playlist_by_name (prop->value());
                        if (pl) {
-                               _freeze_record.playlist = dynamic_cast<AudioPlaylist*> (pl);
+                               _freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
                        } else {
-                               _freeze_record.playlist = 0;
+                               _freeze_record.playlist.reset ();
                                _freeze_record.state = NoFreeze;
                        return;
                        }
                }
                
                if ((prop = fnode->property (X_("state"))) != 0) {
-                       _freeze_record.state = (FreezeState) atoi (prop->value().c_str());
+                       _freeze_record.state = FreezeState (string_2_enum (prop->value(), _freeze_record.state));
                }
                
                XMLNodeConstIterator citer;
@@ -387,11 +415,21 @@ AudioTrack::set_state_part_two ()
        if ((fnode = find_named_node (*pending_state, X_("alignment"))) != 0) {
 
                if ((prop = fnode->property (X_("style"))) != 0) {
-                       if (prop->value() == "existing") {
-                               _diskstream->set_persistent_align_style (ExistingMaterial);
-                       } else if (prop->value() == "capture") {
-                               _diskstream->set_persistent_align_style (CaptureTime);
+
+                       /* fix for older sessions from before EnumWriter */
+
+                       string pstr;
+
+                       if (prop->value() == "capture") {
+                               pstr = "CaptureTime";
+                       } else if (prop->value() == "existing") {
+                               pstr = "ExistingMaterial";
+                       } else {
+                               pstr = prop->value();
                        }
+
+                       AlignStyle as = AlignStyle (string_2_enum (pstr, as));
+                       _diskstream->set_persistent_align_style (as);
                }
        }
        return;
@@ -404,14 +442,14 @@ AudioTrack::n_process_buffers ()
 }
 
 void
-AudioTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
+AudioTrack::passthru_silence (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset, int declick, bool meter)
 {
        uint32_t nbufs = n_process_buffers ();
        process_output_buffers (_session.get_silent_buffers (nbufs), nbufs, start_frame, end_frame, nframes, offset, true, declick, meter);
 }
 
 int 
-AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, 
+AudioTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, 
                     bool session_state_changing, bool can_record, bool rec_monitors_input)
 {
        if (n_outputs() == 0) {
@@ -443,15 +481,15 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
                send_silence = true;
        } else {
 
-               if (_session.get_auto_input()) {
-                       if (Config->get_use_sw_monitoring()) {
+               if (Config->get_auto_input()) {
+                       if (Config->get_monitoring_model() == SoftwareMonitoring) {
                                send_silence = false;
                        } else {
                                send_silence = true;
                        }
                } else {
                        if (_diskstream->record_enabled()) {
-                               if (Config->get_use_sw_monitoring()) {
+                               if (Config->get_monitoring_model() == SoftwareMonitoring) {
                                        send_silence = false;
                                } else {
                                        send_silence = true;
@@ -491,13 +529,13 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
 }
 
 int
-AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick,
+AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
                  bool can_record, bool rec_monitors_input)
 {
        int dret;
        Sample* b;
        Sample* tmpb;
-       jack_nframes_t transport_frame;
+       nframes_t transport_frame;
        boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
        
        {
@@ -508,6 +546,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
                        automation_snapshot (start_frame);
                }
        }
+
        
        if (n_outputs() == 0 && _redirects.empty()) {
                return 0;
@@ -544,7 +583,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
                just_meter_input (start_frame, end_frame, nframes, offset);
        }
 
-       if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
+       if (diskstream->record_enabled() && !can_record && !Config->get_auto_input()) {
 
                /* not actually recording, but we want to hear the input material anyway,
                   at least potentially (depending on monitoring options)
@@ -592,7 +631,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
                        }
                }
 
-               process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
+               process_output_buffers (bufs, limit, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
                
        } else {
                /* problem with the diskstream; just be quiet for a bit */
@@ -603,7 +642,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
 }
 
 int
-AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, 
+AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, 
                         bool can_record, bool rec_monitors_input)
 {
        if (n_outputs() == 0 && _redirects.empty()) {
@@ -624,7 +663,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
 }
 
 int
-AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes_t start, jack_nframes_t nframes)
+AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, nframes_t start, nframes_t nframes)
 {
        gain_t  gain_automation[nframes];
        gain_t  gain_buffer[nframes];
@@ -638,8 +677,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
        
        Glib::RWLock::ReaderLock rlock (redirect_lock);
 
-       // FIXME
-       AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream->playlist());
+       boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist());
        assert(apl);
 
        if (apl->read (buffers[0], mix_buffer, gain_buffer, start, nframes) != nframes) {
@@ -689,7 +727,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
 
                for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
                        Sample *b = *bi;
-                       for (jack_nframes_t n = 0; n < nframes; ++n) {
+                       for (nframes_t n = 0; n < nframes; ++n) {
                                b[n] *= gain_automation[n];
                        }
                }
@@ -698,7 +736,7 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
 
                for (bi = buffers.begin(); bi != buffers.end(); ++bi) {
                        Sample *b = *bi;
-                       for (jack_nframes_t n = 0; n < nframes; ++n) {
+                       for (nframes_t n = 0; n < nframes; ++n) {
                                b[n] *= this_gain;
                        }
                }
@@ -727,30 +765,29 @@ AudioTrack::export_stuff (vector<Sample*>& buffers, uint32_t nbufs, jack_nframes
 void
 AudioTrack::bounce (InterThreadInfo& itt)
 {
-       vector<AudioSource*> srcs;
+       vector<boost::shared_ptr<AudioSource> > srcs;
        _session.write_one_audio_track (*this, 0, _session.current_end_frame(), false, srcs, itt);
 }
 
 
 void
-AudioTrack::bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo& itt)
+AudioTrack::bounce_range (nframes_t start, nframes_t end, InterThreadInfo& itt)
 {
-       vector<AudioSource*> srcs;
+       vector<boost::shared_ptr<AudioSource> > srcs;
        _session.write_one_audio_track (*this, start, end, false, srcs, itt);
 }
 
 void
 AudioTrack::freeze (InterThreadInfo& itt)
 {
-       vector<AudioSource*> srcs;
+       vector<boost::shared_ptr<AudioSource> > srcs;
        string new_playlist_name;
-       Playlist* new_playlist;
+       boost::shared_ptr<Playlist> new_playlist;
        string dir;
-       AudioRegion* region;
        string region_name;
        boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
        
-       if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream->playlist())) == 0) {
+       if ((_freeze_record.playlist = boost::dynamic_pointer_cast<AudioPlaylist>(diskstream->playlist())) == 0) {
                return;
        }
 
@@ -778,7 +815,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
                return;
        }
 
-       if (_session.write_one_audio_track (*this, 0, _session.current_end_frame(), true, srcs, itt)) {
+       if (_session.write_one_audio_track (*this, _session.current_start_frame(), _session.current_end_frame(), true, srcs, itt)) {
                return;
        }
 
@@ -797,8 +834,7 @@ AudioTrack::freeze (InterThreadInfo& itt)
                                FreezeRecordInsertInfo* frii  = new FreezeRecordInsertInfo ((*r)->get_state(), insert);
                                
                                frii->id = insert->id();
-                               frii->memento = (*r)->get_memento();
-                               
+
                                _freeze_record.insert_info.push_back (frii);
                                
                                /* now deactivate the insert */
@@ -808,22 +844,22 @@ AudioTrack::freeze (InterThreadInfo& itt)
                }
        }
 
-       new_playlist = new AudioPlaylist (_session, new_playlist_name, false);
+       new_playlist = PlaylistFactory::create (_session, new_playlist_name, false);
        region_name = new_playlist_name;
 
        /* create a new region from all filesources, keep it private */
 
-       region = new AudioRegion (srcs, 0, srcs[0]->length(), 
-                                 region_name, 0, 
-                                 (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
-                                 false);
+       boost::shared_ptr<Region> region (RegionFactory::create (srcs, 0, srcs[0]->length(), 
+                                                                region_name, 0, 
+                                                                (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
+                                                                false));
 
        new_playlist->set_orig_diskstream_id (diskstream->id());
-       new_playlist->add_region (*region, 0);
+       new_playlist->add_region (region, _session.current_start_frame());
        new_playlist->set_frozen (true);
        region->set_locked (true);
 
-       diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
+       diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
        diskstream->set_record_enabled (false);
 
        _freeze_record.state = Frozen;
@@ -855,7 +891,7 @@ AudioTrack::unfreeze ()
                        }
                }
                
-               _freeze_record.playlist = 0;
+               _freeze_record.playlist.reset ();
        }
 
        _freeze_record.state = UnFrozen;