NO-OP; whitespace
[ardour.git] / libs / ardour / audio_diskstream.cc
index d75dfea90f5acb6cbd2199b622ce8480336c9b1e..9dde2226518ceca6ae8de9cf82ea659a5b5426b4 100644 (file)
@@ -16,7 +16,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <fstream>
 #include <cstdio>
 #include <unistd.h>
 #include <cmath>
@@ -28,6 +27,7 @@
 #include <cstdlib>
 #include <ctime>
 
+#include "pbd/gstdio_compat.h"
 #include "pbd/error.h"
 #include "pbd/xml++.h"
 #include "pbd/memento_command.h"
@@ -56,7 +56,7 @@
 #include "ardour/types.h"
 #include "ardour/utils.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 #include <locale.h>
 
 using namespace std;
@@ -168,7 +168,7 @@ AudioDiskstream::non_realtime_input_change ()
                        need_write_sources = true;
                }
 
-               if (input_change_pending.type == IOChange::ConfigurationChanged) {
+               if (input_change_pending.type & IOChange::ConfigurationChanged) {
                        RCUWriter<ChannelList> writer (channels);
                        boost::shared_ptr<ChannelList> c = writer.get_copy();
 
@@ -316,6 +316,7 @@ AudioDiskstream::use_copy_playlist ()
        newname = Playlist::bump_name (_playlist->name(), _session);
 
        if ((playlist = boost::dynamic_pointer_cast<AudioPlaylist>(PlaylistFactory::create (audio_playlist(), newname))) != 0) {
+               playlist->reset_shares();
                return use_playlist (playlist);
        } else {
                return -1;
@@ -359,8 +360,9 @@ AudioDiskstream::use_destructive_playlist ()
 
        boost::shared_ptr<Region> rp;
        {
-               const RegionList& rl (_playlist->region_list().rlist());
+               const RegionList& rl (_playlist->region_list_property().rlist());
                if (rl.size() > 0) {
+                       /* this can happen when dragging a region onto a tape track */
                        assert((rl.size() == 1));
                        rp = rl.front();
                }
@@ -377,9 +379,9 @@ AudioDiskstream::use_destructive_playlist ()
                throw failed_constructor();
        }
 
-       /* be sure to stretch the region out to the maximum length */
+       /* be sure to stretch the region out to the maximum length (non-musical)*/
 
-       region->set_length (max_framepos - region->position());
+       region->set_length (max_framepos - region->position(), 0);
 
        uint32_t n;
        ChannelList::iterator chan;
@@ -392,7 +394,12 @@ AudioDiskstream::use_destructive_playlist ()
 
                /* this might be false if we switched modes, so force it */
 
+#ifdef XXX_OLD_DESTRUCTIVE_API_XXX
                (*chan)->write_source->set_destructive (true);
+#else
+               // should be set when creating the source or loading the state
+               assert ((*chan)->write_source->destructive());
+#endif
        }
 
        /* the source list will never be reset for a destructive track */
@@ -523,7 +530,7 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
 
                                Sample *buf = bufs.get_audio (n).data(rec_offset);
                                memcpy (chaninfo->current_capture_buffer, buf, sizeof (Sample) * rec_nframes);
-                               
+
                        } else {
 
                                framecnt_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1];
@@ -599,7 +606,7 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
        }
 
        if ((_track->monitoring_state () & MonitoringDisk) || collect_playback) {
-               
+
                /* we're doing playback */
 
                framecnt_t necessary_samples;
@@ -655,7 +662,7 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
                                        memcpy ((char *) chaninfo->playback_wrap_buffer,
                                                        chaninfo->playback_vector.buf[0],
                                                        chaninfo->playback_vector.len[0] * sizeof (Sample));
-                                       
+
                                        /* Copy buf[1] from playback_buf */
                                        memcpy (chaninfo->playback_wrap_buffer + chaninfo->playback_vector.len[0],
                                                        chaninfo->playback_vector.buf[1],
@@ -674,13 +681,13 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
                        int channel = 0;
                        for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++channel) {
                                ChannelInfo* chaninfo (*chan);
-                               
+
                                playback_distance = interpolation.interpolate (
                                        channel, nframes, chaninfo->current_playback_buffer, chaninfo->speed_buffer);
-                               
+
                                chaninfo->current_playback_buffer = chaninfo->speed_buffer;
                        }
-                       
+
                } else {
                        playback_distance = nframes;
                }
@@ -691,20 +698,20 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
        if (need_disk_signal) {
 
                /* copy data over to buffer set */
-               
+
                size_t n_buffers = bufs.count().n_audio();
                size_t n_chans = c->size();
                gain_t scaling = 1.0f;
-               
+
                if (n_chans > n_buffers) {
                        scaling = ((float) n_buffers)/n_chans;
                }
 
                for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
-                       
+
                        AudioBuffer& buf (bufs.get_audio (n%n_buffers));
                        ChannelInfo* chaninfo (*chan);
-                       
+
                        if (n < n_chans) {
                                if (scaling != 1.0f) {
                                        buf.read_from_with_gain (chaninfo->current_playback_buffer, nframes, scaling);
@@ -724,7 +731,7 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
                ChanCount cnt (DataType::AUDIO, n_chans);
                cnt.set (DataType::MIDI, bufs.count().n_midi());
                bufs.set_count (cnt);
-       
+
                /* extra buffers will already be silent, so leave them alone */
        }
 
@@ -787,6 +794,7 @@ AudioDiskstream::commit (framecnt_t playback_distance)
 
        if (adjust_capture_position != 0) {
                capture_captured += adjust_capture_position;
+               DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 now captured %2 (by %3)\n", name(), capture_captured, adjust_capture_position));
                adjust_capture_position = 0;
        }
 
@@ -962,7 +970,7 @@ AudioDiskstream::internal_playback_seek (framecnt_t distance)
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        for (chan = c->begin(); chan != c->end(); ++chan) {
-               (*chan)->playback_buf->increment_read_ptr (llabs(distance));
+               (*chan)->playback_buf->increment_read_ptr (::llabs(distance));
        }
 
        if (first_recordable_frame < max_framepos) {
@@ -1122,11 +1130,11 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn
        /* do not read from disk while session is marked as Loading, to avoid
           useless redundant I/O.
        */
-       
+
        if (_session.state_of_the_state() & Session::Loading) {
                return 0;
        }
-       
+
        if (c->empty()) {
                return 0;
        }
@@ -1261,14 +1269,14 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn
        /* now back to samples */
 
        framecnt_t samples_to_read = byte_size_for_read / (bits_per_sample / 8);
-       
+
        //cerr << name() << " will read " << byte_size_for_read << " out of total bytes " << total_bytes << " in buffer of "
        // << c->front()->playback_buf->bufsize() * bits_per_sample / 8 << " bps = " << bits_per_sample << endl;
        // cerr << name () << " read samples = " << samples_to_read << " out of total space " << total_space << " in buffer of " << c->front()->playback_buf->bufsize() << " samples\n";
 
        // uint64_t before = g_get_monotonic_time ();
        // uint64_t elapsed;
-       
+
        for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) {
 
                ChannelInfo* chan (*i);
@@ -1350,14 +1358,14 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, framecn
 
        // elapsed = g_get_monotonic_time () - before;
        // cerr << "\tbandwidth = " << (byte_size_for_read / 1048576.0) / (elapsed/1000000.0) << "MB/sec\n";
-               
+
        file_frame = file_frame_tmp;
        assert (file_frame >= 0);
 
        ret = ((total_space - samples_to_read) > disk_read_chunk_frames);
-       
+
        c->front()->playback_buf->get_write_vector (&vector);
-       
+
   out:
        return ret;
 }
@@ -1468,7 +1476,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush)
                        error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg;
                        return -1;
                }
-                
+
                (*chan)->capture_buf->increment_read_ptr (to_write);
                (*chan)->curr_capture_cnt += to_write;
 
@@ -1579,6 +1587,8 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
                        if (Config->get_auto_analyse_audio()) {
                                Analyser::queue_source_for_analysis (s, true);
                        }
+
+                       DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("newly captured source %1 length %2\n", s->path(), s->length (0)));
                }
        }
 
@@ -1626,19 +1636,20 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
                }
 
                _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end());
-               
+
                _playlist->clear_changes ();
                _playlist->set_capture_insertion_in_progress (true);
                _playlist->freeze ();
 
+               const framepos_t preroll_off = _session.preroll_record_trim_len ();
                for (buffer_position = c->front()->write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
 
                        string region_name;
 
                        RegionFactory::region_name (region_name, whole_file_region_name, false);
 
-                       DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 capture start @ %2 length %3 add new region %4\n",
-                                                                             _name, (*ci)->start, (*ci)->frames, region_name));
+                       DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 capture bufpos %5 start @ %2 length %3 add new region %4\n",
+                                                                             _name, (*ci)->start, (*ci)->frames, region_name, buffer_position));
 
                        try {
 
@@ -1650,6 +1661,9 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
 
                                boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
                                region = boost::dynamic_pointer_cast<AudioRegion> (rx);
+                               if (preroll_off > 0) {
+                                       region->trim_front (buffer_position + preroll_off);
+                               }
                        }
 
                        catch (failed_constructor& err) {
@@ -1659,7 +1673,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
 
                        i_am_the_modifier++;
 
-                       _playlist->add_region (region, (*ci)->start, 1, non_layered());
+                       _playlist->add_region (region, (*ci)->start + preroll_off, 1, non_layered());
                        _playlist->set_layer (region, DBL_MAX);
                        i_am_the_modifier--;
 
@@ -1693,18 +1707,6 @@ AudioDiskstream::transport_looped (framepos_t transport_frame)
                // all we need to do is finish this capture, with modified capture length
                boost::shared_ptr<ChannelList> c = channels.reader();
 
-               // adjust the capture length knowing that the data will be recorded to disk
-               // only necessary after the first loop where we're recording
-               if (capture_info.size() == 0) {
-                       capture_captured += _capture_offset;
-
-                       if (_alignment_style == ExistingMaterial) {
-                               capture_captured += _session.worst_output_latency();
-                       } else {
-                               capture_captured += _roll_delay;
-                       }
-               }
-
                finish_capture (c);
 
                // the next region will start recording via the normal mechanism
@@ -1782,7 +1784,7 @@ AudioDiskstream::finish_capture (boost::shared_ptr<ChannelList> c)
        */
 
        DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("Finish capture, add new CI, %1 + %2\n", ci->start, ci->frames));
-       
+
        capture_info.push_back (ci);
        capture_captured = 0;
 
@@ -1824,25 +1826,25 @@ AudioDiskstream::set_record_safe (bool yn)
        if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) {
                return;
        }
-       
-       /* can't rec-safe in destructive mode if transport is before start ???? 
+
+       /* can't rec-safe in destructive mode if transport is before start ????
         REQUIRES REVIEW */
-       
+
        if (destructive() && yn && _session.transport_frame() < _session.current_start_frame()) {
                return;
        }
-       
+
        /* yes, i know that this not proof against race conditions, but its
         good enough. i think.
         */
-       
+
        if (record_safe () != yn) {
                if (yn) {
                        engage_record_safe ();
                } else {
                        disengage_record_safe ();
                }
-           
+
                RecordSafeChanged (); /* EMIT SIGNAL */
        }
 }
@@ -1904,7 +1906,7 @@ AudioDiskstream::get_state ()
 {
        XMLNode& node (Diskstream::get_state());
        char buf[64] = "";
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
 
        boost::shared_ptr<ChannelList> c = channels.reader();
        snprintf (buf, sizeof(buf), "%u", (unsigned int) c->size());
@@ -1925,7 +1927,9 @@ AudioDiskstream::get_state ()
 
                Location* pi;
 
-               if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
+               if (_session.preroll_record_punch_enabled ()) {
+                       snprintf (buf, sizeof (buf), "%" PRId64, _session.preroll_record_punch_pos ());
+               } else if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
                        snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
                } else {
                        snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
@@ -1941,12 +1945,12 @@ AudioDiskstream::get_state ()
 int
 AudioDiskstream::set_state (const XMLNode& node, int version)
 {
-       const XMLProperty* prop;
+       XMLProperty const * prop;
        XMLNodeList nlist = node.children();
        XMLNodeIterator niter;
        uint32_t nchans = 1;
        XMLNode* capture_pending_node = 0;
-       LocaleGuard lg (X_("C"));
+       LocaleGuard lg;
 
        /* prevent write sources from being created */
 
@@ -2183,6 +2187,22 @@ AudioDiskstream::set_align_style_from_io ()
                }
        }
 
+#ifdef MIXBUS
+       // compensate for latency when bouncing from master or mixbus.
+       // we need to use "ExistingMaterial" to pick up the master bus' latency
+       // see also Route::direct_feeds_according_to_reality
+       IOVector ios;
+       ios.push_back (_io);
+       if (_session.master_out() && ios.fed_by (_session.master_out()->output())) {
+               have_physical = true;
+       }
+       for (uint32_t n = 0; n < NUM_MIXBUSES && !have_physical; ++n) {
+               if (_session.get_mixbus (n) && ios.fed_by (_session.get_mixbus(n)->output())) {
+                       have_physical = true;
+               }
+       }
+#endif
+
        if (have_physical) {
                set_align_style (ExistingMaterial);
        } else {
@@ -2246,11 +2266,11 @@ AudioDiskstream::playback_buffer_load () const
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        if (c->empty ()) {
-               return 0;
+               return 1.0;
        }
 
        return (float) ((double) c->front()->playback_buf->read_space()/
-                       (double) c->front()->playback_buf->bufsize());
+                          (double) c->front()->playback_buf->bufsize());
 }
 
 float
@@ -2259,7 +2279,7 @@ AudioDiskstream::capture_buffer_load () const
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        if (c->empty ()) {
-               return 0;
+               return 1.0;
        }
 
        return (float) ((double) c->front()->capture_buf->write_space()/
@@ -2269,7 +2289,7 @@ AudioDiskstream::capture_buffer_load () const
 int
 AudioDiskstream::use_pending_capture_data (XMLNode& node)
 {
-       const XMLProperty* prop;
+       XMLProperty const * prop;
        XMLNodeList nlist = node.children();
        XMLNodeIterator niter;
        boost::shared_ptr<AudioFileSource> fs;
@@ -2293,8 +2313,8 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
                        }
 
                        // This protects sessions from errant CapturingSources in stored sessions
-                       struct stat sbuf;
-                       if (stat (prop->value().c_str(), &sbuf)) {
+                       GStatBuf sbuf;
+                       if (g_stat (prop->value().c_str(), &sbuf)) {
                                continue;
                        }
 
@@ -2342,11 +2362,11 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
 
                boost::shared_ptr<AudioRegion> wf_region;
                boost::shared_ptr<AudioRegion> region;
-               
+
                /* First create the whole file region */
 
                PropertyList plist;
-               
+
                plist.add (Properties::start, 0);
                plist.add (Properties::length, first_fs->length (first_fs->timeline_position()));
                plist.add (Properties::name, region_name_from_path (first_fs->name(), true));
@@ -2361,7 +2381,7 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
                 * the playlist */
 
                region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
-               
+
                _playlist->add_region (region, position);
        }
 
@@ -2377,6 +2397,7 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
        return 0;
 }
 
+#ifdef XXX_OLD_DESTRUCTIVE_API_XXX
 int
 AudioDiskstream::set_non_layered (bool yn)
 {
@@ -2422,7 +2443,7 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const
        if (Profile->get_trx()) {
                return false;
        }
-       
+
        if (!_playlist) {
                requires_bounce = false;
                return false;
@@ -2444,7 +2465,7 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const
 
        boost::shared_ptr<Region> first;
        {
-               const RegionList& rl (_playlist->region_list().rlist());
+               const RegionList& rl (_playlist->region_list_property().rlist());
                assert((rl.size() == 1));
                first = rl.front();
 
@@ -2490,6 +2511,7 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const
        requires_bounce = false;
        return true;
 }
+#endif
 
 void
 AudioDiskstream::adjust_playback_buffering ()
@@ -2583,7 +2605,7 @@ AudioDiskstream::ChannelInfo::~ChannelInfo ()
                           continue to exist. If we do not do this, then the
                           Session retains a reference to it, it is not
                           deleted, and later attempts to create a new source
-                          file will use wierd naming because it already 
+                          file will use wierd naming because it already
                           exists.
 
                           XXX longer term TO-DO: do not add to session source