X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudio_diskstream.cc;h=7a30e191d58641f78b4af4d05d6bacf28d51551f;hb=c4e31356170835bf3c4231b906db128187f471d8;hp=c7853a87859490e95fff81872c35764a52fb6267;hpb=0013feddbf260f0b57ee74786c316739806ea47a;p=ardour.git diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index c7853a8785..7a30e191d5 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -46,6 +46,7 @@ #include "ardour/debug.h" #include "ardour/io.h" #include "ardour/playlist_factory.h" +#include "ardour/profile.h" #include "ardour/region_factory.h" #include "ardour/session.h" #include "ardour/session_playlists.h" @@ -74,6 +75,10 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream: in_set_state = true; use_new_playlist (); in_set_state = false; + + if (flag & Destructive) { + use_destructive_playlist (); + } } AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) @@ -128,9 +133,7 @@ AudioDiskstream::~AudioDiskstream () void AudioDiskstream::allocate_working_buffers() { - assert(disk_io_frames() > 0); - - _working_buffers_size = disk_io_frames(); + _working_buffers_size = max (disk_write_chunk_frames, disk_read_chunk_frames); _mixdown_buffer = new Sample[_working_buffers_size]; _gain_buffer = new gain_t[_working_buffers_size]; } @@ -148,6 +151,8 @@ AudioDiskstream::free_working_buffers() void AudioDiskstream::non_realtime_input_change () { + bool need_write_sources = false; + { Glib::Threads::Mutex::Lock lm (state_lock); @@ -155,6 +160,11 @@ AudioDiskstream::non_realtime_input_change () return; } + boost::shared_ptr cr = channels.reader(); + if (!cr->empty() && !cr->front()->write_source) { + need_write_sources = true; + } + if (input_change_pending.type == IOChange::ConfigurationChanged) { RCUWriter writer (channels); boost::shared_ptr c = writer.get_copy(); @@ -166,6 +176,8 @@ AudioDiskstream::non_realtime_input_change () } else if (_io->n_ports().n_audio() < _n_channels.n_audio()) { remove_channel_from (c, _n_channels.n_audio() - _io->n_ports().n_audio()); } + + need_write_sources = true; } if (input_change_pending.type & IOChange::ConnectionsChanged) { @@ -179,9 +191,9 @@ AudioDiskstream::non_realtime_input_change () /* implicit unlock */ } - /* reset capture files */ - - reset_write_sources (false); + if (need_write_sources) { + reset_write_sources (false); + } /* now refill channel buffers */ @@ -218,7 +230,7 @@ AudioDiskstream::get_input_sources () connections.clear (); - if (_io->nth (n)->get_connections (connections) == 0) { + if ((_io->nth (n).get()) && (_io->nth (n)->get_connections (connections) == 0)) { if (!(*chan)->source.name.empty()) { // _source->disable_metering (); } @@ -324,10 +336,13 @@ AudioDiskstream::setup_destructive_playlist () PropertyList plist; plist.add (Properties::name, _name.val()); plist.add (Properties::start, 0); - plist.add (Properties::length, max_framepos - (max_framepos - srcs.front()->natural_position())); + plist.add (Properties::length, max_framepos - srcs.front()->natural_position()); boost::shared_ptr region (RegionFactory::create (srcs, plist)); _playlist->add_region (region, srcs.front()->natural_position()); + + /* apply region properties and update write sources */ + use_destructive_playlist(); } void @@ -339,7 +354,14 @@ AudioDiskstream::use_destructive_playlist () with the (presumed single, full-extent) region. */ - boost::shared_ptr rp = _playlist->find_next_region (_session.current_start_frame(), Start, 1); + boost::shared_ptr rp; + { + const RegionList& rl (_playlist->region_list().rlist()); + if (rl.size() > 0) { + assert((rl.size() == 1)); + rp = rl.front(); + } + } if (!rp) { reset_write_sources (false, true); @@ -451,8 +473,12 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t if (record_enabled()) { Evoral::OverlapType ot = Evoral::coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes); + // XXX should this be transport_frame + nframes - 1 ? coverage() expects its parameter ranges to include their end points + // XXX also, first_recordable_frame & last_recordable_frame may both be == max_framepos: coverage() will return OverlapNone in that case. Is thak OK? calculate_record_range (ot, transport_frame, nframes, rec_nframes, rec_offset); + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: this time record %2 of %3 frames, offset %4\n", _name, rec_nframes, nframes, rec_offset)); + if (rec_nframes && !was_recording) { capture_captured = 0; was_recording = true; @@ -500,6 +526,8 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t framecnt_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1]; if (rec_nframes > total) { + DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 overrun in %2, rec_nframes = %3 total space = %4\n", + DEBUG_THREAD_SELF, name(), rec_nframes, total)); DiskOverrun (); return -1; } @@ -606,6 +634,8 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t if (necessary_samples > total) { cerr << _name << " Need " << necessary_samples << " total = " << total << endl; cerr << "underrun for " << _name << endl; + DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 underrun in %2, rec_nframes = %3 total space = %4\n", + DEBUG_THREAD_SELF, name(), rec_nframes, total)); DiskUnderrun (); return -1; @@ -769,10 +799,10 @@ AudioDiskstream::commit (framecnt_t playback_distance) } } else { if (_io && _io->active()) { - need_butler = ((framecnt_t) c->front()->playback_buf->write_space() >= disk_io_chunk_frames) - || ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames); + need_butler = ((framecnt_t) c->front()->playback_buf->write_space() >= disk_read_chunk_frames) + || ((framecnt_t) c->front()->capture_buf->read_space() >= disk_write_chunk_frames); } else { - need_butler = ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames); + need_butler = ((framecnt_t) c->front()->capture_buf->read_space() >= disk_write_chunk_frames); } } @@ -923,7 +953,7 @@ AudioDiskstream::internal_playback_seek (framecnt_t distance) boost::shared_ptr c = channels.reader(); for (chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->playback_buf->increment_read_ptr (std::llabs(distance)); + (*chan)->playback_buf->increment_read_ptr (llabs(distance)); } if (first_recordable_frame < max_framepos) { @@ -980,6 +1010,7 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, if (loc && start >= loop_end) { start = loop_start + ((start - loop_start) % loop_length); } + } if (reversed) { @@ -1039,8 +1070,8 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, int AudioDiskstream::do_refill_with_alloc () { - Sample* mix_buf = new Sample[disk_io_chunk_frames]; - float* gain_buf = new float[disk_io_chunk_frames]; + Sample* mix_buf = new Sample[disk_read_chunk_frames]; + float* gain_buf = new float[disk_read_chunk_frames]; int ret = _do_refill(mix_buf, gain_buf); @@ -1091,22 +1122,22 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) for us to be called again, ASAP. */ - if (total_space >= (_slaved ? 3 : 2) * disk_io_chunk_frames) { + if (total_space >= (_slaved ? 3 : 2) * disk_read_chunk_frames) { ret = 1; } /* if we're running close to normal speed and there isn't enough - space to do disk_io_chunk_frames of I/O, then don't bother. + space to do disk_read_chunk_frames of I/O, then don't bother. at higher speeds, just do it because the sync between butler and audio thread may not be good enough. - Note: it is a design assumption that disk_io_chunk_frames is smaller + Note: it is a design assumption that disk_read_chunk_frames is smaller than the playback buffer size, so this check should never trip when the playback buffer is empty. */ - if ((total_space < disk_io_chunk_frames) && fabs (_actual_speed) < 2.0f) { + if ((total_space < disk_read_chunk_frames) && fabs (_actual_speed) < 2.0f) { return 0; } @@ -1119,9 +1150,9 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) return 0; } - /* never do more than disk_io_chunk_frames worth of disk input per call (limit doesn't apply for memset) */ + /* never do more than disk_read_chunk_frames worth of disk input per call (limit doesn't apply for memset) */ - total_space = min (disk_io_chunk_frames, total_space); + total_space = min (disk_read_chunk_frames, total_space); if (reversed) { @@ -1198,14 +1229,14 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) chan->playback_buf->get_write_vector (&vector); - if ((framecnt_t) vector.len[0] > disk_io_chunk_frames) { + if ((framecnt_t) vector.len[0] > disk_read_chunk_frames) { /* we're not going to fill the first chunk, so certainly do not bother with the other part. it won't be connected with the part we do fill, as in: .... => writable space ++++ => readable space - ^^^^ => 1 x disk_io_chunk_frames that would be filled + ^^^^ => 1 x disk_read_chunk_frames that would be filled |......|+++++++++++++|...............................| buf1 buf0 @@ -1230,7 +1261,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) len2 = vector.len[1]; to_read = min (ts, len1); - to_read = min (to_read, disk_io_chunk_frames); + to_read = min (to_read, disk_read_chunk_frames); assert (to_read >= 0); @@ -1249,7 +1280,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) if (to_read) { - /* we read all of vector.len[0], but it wasn't an entire disk_io_chunk_frames of data, + /* we read all of vector.len[0], but it wasn't an entire disk_read_chunk_frames of data, so read some or all of vector.len[1] as well. */ @@ -1277,12 +1308,12 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) /** Flush pending data to disk. * - * Important note: this function will write *AT MOST* disk_io_chunk_frames + * Important note: this function will write *AT MOST* disk_write_chunk_frames * of data to disk. it will never write more than that. If it writes that * much and there is more than that waiting to be written, it will return 1, * otherwise 0 on success or -1 on failure. * - * If there is less than disk_io_chunk_frames to be written, no data will be + * If there is less than disk_write_chunk_frames to be written, no data will be * written at all unless @a force_flush is true. */ int @@ -1306,7 +1337,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) total = vector.len[0] + vector.len[1]; - if (total == 0 || (total < disk_io_chunk_frames && !force_flush && was_recording)) { + if (total == 0 || (total < disk_write_chunk_frames && !force_flush && was_recording)) { goto out; } @@ -1321,11 +1352,11 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) let the caller know too. */ - if (total >= 2 * disk_io_chunk_frames || ((force_flush || !was_recording) && total > disk_io_chunk_frames)) { + if (total >= 2 * disk_write_chunk_frames || ((force_flush || !was_recording) && total > disk_write_chunk_frames)) { ret = 1; } - to_write = min (disk_io_chunk_frames, (framecnt_t) vector.len[0]); + to_write = min (disk_write_chunk_frames, (framecnt_t) vector.len[0]); // check the transition buffer when recording destructive // important that we get this after the capture buf @@ -1381,18 +1412,20 @@ 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; - if ((to_write == vector.len[0]) && (total > to_write) && (to_write < disk_io_chunk_frames) && !destructive()) { + if ((to_write == vector.len[0]) && (total > to_write) && (to_write < disk_write_chunk_frames) && !destructive()) { /* we wrote all of vector.len[0] but it wasn't an entire - disk_io_chunk_frames of data, so arrange for some part + disk_write_chunk_frames of data, so arrange for some part of vector.len[1] to be flushed to disk as well. */ - to_write = min ((framecnt_t)(disk_io_chunk_frames - to_write), (framecnt_t) vector.len[1]); + to_write = min ((framecnt_t)(disk_write_chunk_frames - to_write), (framecnt_t) vector.len[1]); + + DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 additional write of %2\n", name(), to_write)); if ((*chan)->write_source->write (vector.buf[1], to_write) != to_write) { error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg; @@ -1537,9 +1570,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo } _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end()); - - // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n"; - + _playlist->clear_changes (); _playlist->set_capture_insertion_in_progress (true); _playlist->freeze (); @@ -1694,8 +1725,8 @@ AudioDiskstream::finish_capture (boost::shared_ptr c) accessors, so that invalidation will not occur (both non-realtime). */ - // cerr << "Finish capture, add new CI, " << ci->start << '+' << ci->frames << endl; - + 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; @@ -1706,7 +1737,7 @@ AudioDiskstream::finish_capture (boost::shared_ptr c) void AudioDiskstream::set_record_enabled (bool yn) { - if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) { + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0 || record_safe ()) { return; } @@ -1731,10 +1762,39 @@ AudioDiskstream::set_record_enabled (bool yn) } } +void +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 ???? + 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 */ + } +} + bool AudioDiskstream::prep_record_enable () { - if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) { + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0 || record_safe ()) { // REQUIRES REVIEW "|| record_safe ()" return false; } @@ -1752,15 +1812,17 @@ AudioDiskstream::prep_record_enable () if (Config->get_monitoring_model() == HardwareMonitoring) { for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->source.request_jack_monitors_input (!(_session.config.get_auto_input() && rolling)); + (*chan)->source.request_input_monitoring (!(_session.config.get_auto_input() && rolling)); capturing_sources.push_back ((*chan)->write_source); - (*chan)->write_source->mark_streaming_write_started (); + Source::Lock lock((*chan)->write_source->mutex()); + (*chan)->write_source->mark_streaming_write_started (lock); } } else { for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { capturing_sources.push_back ((*chan)->write_source); - (*chan)->write_source->mark_streaming_write_started (); + Source::Lock lock((*chan)->write_source->mutex()); + (*chan)->write_source->mark_streaming_write_started (lock); } } @@ -1773,7 +1835,7 @@ AudioDiskstream::prep_record_disable () boost::shared_ptr c = channels.reader(); if (Config->get_monitoring_model() == HardwareMonitoring) { for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->source.request_jack_monitors_input (false); + (*chan)->source.request_input_monitoring (false); } } capturing_sources.clear (); @@ -1786,10 +1848,10 @@ AudioDiskstream::get_state () { XMLNode& node (Diskstream::get_state()); char buf[64] = ""; - LocaleGuard lg (X_("POSIX")); + LocaleGuard lg (X_("C")); boost::shared_ptr c = channels.reader(); - snprintf (buf, sizeof(buf), "%zd", c->size()); + snprintf (buf, sizeof(buf), "%u", (unsigned int) c->size()); node.add_property ("channels", buf); if (!capturing_sources.empty() && _session.get_record_enabled()) { @@ -1828,7 +1890,7 @@ AudioDiskstream::set_state (const XMLNode& node, int version) XMLNodeIterator niter; uint32_t nchans = 1; XMLNode* capture_pending_node = 0; - LocaleGuard lg (X_("POSIX")); + LocaleGuard lg (X_("C")); /* prevent write sources from being created */ @@ -1908,7 +1970,7 @@ AudioDiskstream::use_new_write_source (uint32_t n) try { if ((chan->write_source = _session.create_audio_source_for_session ( - n_channels().n_audio(), name(), n, destructive())) == 0) { + n_channels().n_audio(), write_source_name(), n, destructive())) == 0) { throw failed_constructor(); } } @@ -1926,14 +1988,6 @@ AudioDiskstream::use_new_write_source (uint32_t n) return 0; } -list > -AudioDiskstream::steal_write_sources() -{ - /* not possible to steal audio write sources */ - list > ret; - return ret; -} - void AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/) { @@ -1954,7 +2008,8 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/) if ((*chan)->write_source) { if (mark_write_complete) { - (*chan)->write_source->mark_streaming_write_completed (); + Source::Lock lock((*chan)->write_source->mutex()); + (*chan)->write_source->mark_streaming_write_completed (lock); (*chan)->write_source->done_with_peakfile_writes (); } @@ -2039,12 +2094,12 @@ AudioDiskstream::allocate_temporary_buffers () } void -AudioDiskstream::request_jack_monitors_input (bool yn) +AudioDiskstream::request_input_monitoring (bool yn) { boost::shared_ptr c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->source.request_jack_monitors_input (yn); + (*chan)->source.request_input_monitoring (yn); } } @@ -2187,11 +2242,16 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) continue; } + /* XXX as of June 2014, we always record to mono + files. Since this Source is being created as part of + crash recovery, we know that we need the first + channel (the final argument to the SourceFactory + call below). If we ever support non-mono files for + capture, this will need rethinking. + */ + try { - fs = boost::dynamic_pointer_cast ( - SourceFactory::createWritable ( - DataType::AUDIO, _session, - prop->value(), false, _session.frame_rate())); + fs = boost::dynamic_pointer_cast (SourceFactory::createForRecovery (DataType::AUDIO, _session, prop->value(), 0)); } catch (failed_constructor& err) { @@ -2222,21 +2282,31 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) return -1; } - boost::shared_ptr region; - try { - PropertyList plist; + boost::shared_ptr wf_region; + boost::shared_ptr 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)); - region = boost::dynamic_pointer_cast (RegionFactory::create (pending_sources, plist)); + wf_region = boost::dynamic_pointer_cast (RegionFactory::create (pending_sources, plist)); - region->set_automatic (true); - region->set_whole_file (true); - region->special_set_position (0); + wf_region->set_automatic (true); + wf_region->set_whole_file (true); + wf_region->special_set_position (position); + + /* Now create a region that isn't the whole file for adding to + * the playlist */ + + region = boost::dynamic_pointer_cast (RegionFactory::create (pending_sources, plist)); + + _playlist->add_region (region, position); } catch (failed_constructor& err) { @@ -2247,7 +2317,6 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) return -1; } - _playlist->add_region (region, position); return 0; } @@ -2294,11 +2363,22 @@ AudioDiskstream::set_destructive (bool yn) bool AudioDiskstream::can_become_destructive (bool& requires_bounce) const { + if (Profile->get_trx()) { + return false; + } + if (!_playlist) { requires_bounce = false; return false; } + /* if no regions are present: easy */ + + if (_playlist->n_regions() == 0) { + requires_bounce = false; + return true; + } + /* is there only one region ? */ if (_playlist->n_regions() != 1) { @@ -2306,7 +2386,14 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const return false; } - boost::shared_ptr first = _playlist->find_next_region (_session.current_start_frame(), Start, 1); + boost::shared_ptr first; + { + const RegionList& rl (_playlist->region_list().rlist()); + assert((rl.size() == 1)); + first = rl.front(); + + } + if (!first) { requires_bounce = false; return true; @@ -2315,12 +2402,24 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const /* do the source(s) for the region cover the session start position ? */ if (first->position() != _session.current_start_frame()) { + // what is the idea here? why start() ?? if (first->start() > _session.current_start_frame()) { requires_bounce = true; return false; } } + /* currently RouteTimeAxisView::set_track_mode does not + * implement bounce. Existing regions cannot be converted. + * + * so let's make sure this region is already set up + * as tape-track (spanning the complete range) + */ + if (first->length() != max_framepos - first->position()) { + requires_bounce = true; + return false; + } + /* is the source used by only 1 playlist ? */ boost::shared_ptr afirst = boost::dynamic_pointer_cast (first); @@ -2367,13 +2466,13 @@ AudioDiskstream::ChannelSource::is_physical () const } void -AudioDiskstream::ChannelSource::request_jack_monitors_input (bool yn) const +AudioDiskstream::ChannelSource::request_input_monitoring (bool yn) const { if (name.empty()) { return; } - return AudioEngine::instance()->request_jack_monitors_input (name, yn); + return AudioEngine::instance()->request_input_monitoring (name, yn); } AudioDiskstream::ChannelInfo::ChannelInfo (framecnt_t playback_bufsize, framecnt_t capture_bufsize, framecnt_t speed_size, framecnt_t wrap_size) @@ -2420,6 +2519,24 @@ AudioDiskstream::ChannelInfo::resize_capture (framecnt_t capture_bufsize) AudioDiskstream::ChannelInfo::~ChannelInfo () { + if (write_source) { + if (write_source->removable()) { + /* this is a "stub" write source which exists in the + Session source list, but is removable. We must emit + a drop references call because it should not + 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 + exists. + + XXX longer term TO-DO: do not add to session source + list until we write to the source. + */ + write_source->drop_references (); + } + } + write_source.reset (); delete [] speed_buffer; @@ -2445,6 +2562,9 @@ AudioDiskstream::ChannelInfo::~ChannelInfo () bool AudioDiskstream::set_name (string const & name) { + if (_name == name) { + return true; + } Diskstream::set_name (name); /* get a new write source so that its name reflects the new diskstream name */ @@ -2459,3 +2579,24 @@ AudioDiskstream::set_name (string const & name) return true; } + +bool +AudioDiskstream::set_write_source_name (const std::string& str) { + if (_write_source_name == str) { + return true; + } + + Diskstream::set_write_source_name (str); + + if (_write_source_name == name()) { + return true; + } + boost::shared_ptr c = channels.reader(); + ChannelList::iterator i; + int n = 0; + + for (n = 0, i = c->begin(); i != c->end(); ++i, ++n) { + use_new_write_source (n); + } + return true; +}