*/
+#include "pbd/debug.h"
#include "pbd/error.h"
#include "pbd/i18n.h"
#include "ardour/audioplaylist.h"
#include "ardour/butler.h"
+#include "ardour/debug.h"
#include "ardour/disk_io.h"
#include "ardour/disk_reader.h"
#include "ardour/disk_writer.h"
: Processor (s, str)
, _flags (f)
, i_am_the_modifier (false)
- , _visible_speed (0.0)
- , _actual_speed (0.0)
- , _speed (0.0)
- , _target_speed (0.0)
, _buffer_reallocation_required (false)
, _seek_required (false)
, _slaved (false)
, loop_location (0)
, in_set_state (false)
+ , file_frame (0)
+ , playback_sample (0)
, wrap_buffer_size (0)
, speed_buffer_size (0)
, _need_butler (false)
, channels (new ChannelList)
- , _midi_buf (0)
+ , _midi_buf (new MidiRingBuffer<framepos_t> (s.butler()->midi_diskstream_buffer_size()))
, _frames_written_to_ringbuffer (0)
, _frames_read_from_ringbuffer (0)
{
+ midi_interpolation.add_channel_to (0,0);
}
void
return false;
}
- if (in != out) {
- /* currently no way to deliver different channels that we receive */
- return false;
- }
+ /* currently no way to deliver different channels that we receive */
+ out = in;
return true;
}
bool
DiskIOProcessor::configure_io (ChanCount in, ChanCount out)
{
- Glib::Threads::Mutex::Lock lm (state_lock);
+ DEBUG_TRACE (DEBUG::DiskIO, string_compose ("Configuring %1 for in:%2 out:%3\n", name(), in, out));
RCUWriter<ChannelList> writer (channels);
boost::shared_ptr<ChannelList> c = writer.get_copy();
uint32_t n_audio = in.n_audio();
+ bool changed = false;
if (n_audio > c->size()) {
add_channel_to (c, n_audio - c->size());
+ changed = true;
} else if (n_audio < c->size()) {
remove_channel_from (c, c->size() - n_audio);
+ changed = true;
}
if (in.n_midi() > 0 && !_midi_buf) {
const size_t size = _session.butler()->midi_diskstream_buffer_size();
_midi_buf = new MidiRingBuffer<framepos_t>(size);
midi_interpolation.add_channel_to (0,0);
+ changed = true;
}
- if (speed() != 1.0f || speed() != -1.0f) {
- seek ((framepos_t) (_session.transport_frame() * (double) speed()));
- } else {
+ if (changed) {
seek (_session.transport_frame());
}
{
/* now refill channel buffers */
- if (speed() != 1.0f || speed() != -1.0f) {
- seek ((framepos_t) (location * (double) speed()), true);
- } else {
- seek (location, true);
- }
+ seek (location, true);
}
void
-DiskIOProcessor::non_realtime_set_speed ()
+DiskIOProcessor::non_realtime_speed_change ()
{
- if (_buffer_reallocation_required)
- {
- Glib::Threads::Mutex::Lock lm (state_lock);
+ if (_buffer_reallocation_required) {
_buffer_reallocation_required = false;
}
if (_seek_required) {
- if (speed() != 1.0f || speed() != -1.0f) {
- seek ((framepos_t) (_session.transport_frame() * (double) speed()), true);
- }
- else {
- seek (_session.transport_frame(), true);
- }
-
+ seek (_session.transport_frame(), true);
_seek_required = false;
}
}
bool
-DiskIOProcessor::realtime_set_speed (double sp, bool global)
+DiskIOProcessor::realtime_speed_change ()
{
- bool changed = false;
- double new_speed = sp * _session.transport_speed();
-
- if (_visible_speed != sp) {
- _visible_speed = sp;
- changed = true;
- }
-
- if (new_speed != _actual_speed) {
-
- framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() *
- fabs (new_speed)) + 2;
-
- if (required_wrap_size > wrap_buffer_size) {
- _buffer_reallocation_required = true;
- }
-
- _actual_speed = new_speed;
- _target_speed = fabs(_actual_speed);
- }
+ const framecnt_t required_wrap_size = (framecnt_t) ceil (_session.get_block_size() * fabs (_session.transport_speed())) + 2;
+ bool _buffer_reallocation_required;
- if (changed) {
- if (!global) {
- _seek_required = true;
- }
- SpeedChanged (); /* EMIT SIGNAL */
+ if (required_wrap_size > wrap_buffer_size) {
+ _buffer_reallocation_required = true;
+ } else {
+ _buffer_reallocation_required = false;
}
- return _buffer_reallocation_required || _seek_required;
+ return _buffer_reallocation_required;
}
int
_flags = Flag (string_2_enum (prop->value(), _flags));
}
- if ((prop = node.property ("speed")) != 0) {
- double sp = atof (prop->value().c_str());
-
- if (realtime_set_speed (sp, false)) {
- non_realtime_set_speed ();
- }
- }
return 0;
}
while (how_many--) {
c->push_back (new ChannelInfo (_session.butler()->audio_diskstream_playback_buffer_size()));
interpolation.add_channel_to (_session.butler()->audio_diskstream_playback_buffer_size(), speed_buffer_size);
+ DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new channel, write space = %2 read = %3\n",
+ name(),
+ c->back()->buf->write_space(),
+ c->back()->buf->read_space()));
}
return 0;
return 0;
}
- {
- Glib::Threads::Mutex::Lock lm (state_lock);
+ DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: set to use playlist %2 (%3)\n", name(), playlist->name(), dt.to_string()));
- if (playlist == _playlists[dt]) {
- return 0;
- }
+ if (playlist == _playlists[dt]) {
+ DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: already using that playlist\n", name()));
+ return 0;
+ }
- playlist_connections.drop_connections ();
+ playlist_connections.drop_connections ();
- if (_playlists[dt]) {
- _playlists[dt]->release();
- }
+ if (_playlists[dt]) {
+ _playlists[dt]->release();
+ }
- _playlists[dt] = playlist;
- playlist->use();
+ _playlists[dt] = playlist;
+ playlist->use();
- playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
- playlist->LayeringChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
- playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_deleted, this, boost::weak_ptr<Playlist>(playlist)));
- playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_ranges_moved, this, _1, _2));
- }
+ playlist->ContentsChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
+ playlist->LayeringChanged.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_modified, this));
+ playlist->DropReferences.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_deleted, this, boost::weak_ptr<Playlist>(playlist)));
+ playlist->RangesMoved.connect_same_thread (playlist_connections, boost::bind (&DiskIOProcessor::playlist_ranges_moved, this, _1, _2));
+
+ DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1 now using playlist %1 (%2)\n", name(), playlist->name(), playlist->id()));
PlaylistChanged (dt); /* EMIT SIGNAL */
_session.set_dirty ();
return 0;
}
-int
-DiskIOProcessor::find_and_use_playlist (DataType dt, const string& name)
-{
- boost::shared_ptr<Playlist> playlist;
-
- if ((playlist = _session.playlists->by_name (name)) == 0) {
- playlist = PlaylistFactory::create (dt, _session, name);
- }
-
- if (!playlist) {
- error << string_compose(_("DiskIOProcessor: \"%1\" isn't an playlist"), name) << endmsg;
- return -1;
- }
-
- return use_playlist (dt, playlist);
-}
-
-int
-DiskIOProcessor::use_new_playlist (DataType dt)
-{
- string newname;
- boost::shared_ptr<Playlist> playlist = _playlists[dt];
-
- if (playlist) {
- newname = Playlist::bump_name (playlist->name(), _session);
- } else {
- newname = Playlist::bump_name (_name, _session);
- }
-
- playlist = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (dt, _session, newname, hidden()));
-
- if (!playlist) {
- return -1;
- }
-
- return use_playlist (dt, playlist);
-}
-
-int
-DiskIOProcessor::use_copy_playlist (DataType dt)
-{
- assert (_playlists[dt]);
-
- if (_playlists[dt] == 0) {
- error << string_compose(_("DiskIOProcessor %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
- return -1;
- }
-
- string newname;
- boost::shared_ptr<Playlist> playlist;
-
- newname = Playlist::bump_name (_playlists[dt]->name(), _session);
-
- if ((playlist = PlaylistFactory::create (_playlists[dt], newname)) == 0) {
- return -1;
- }
-
- playlist->reset_shares();
-
- return use_playlist (dt, playlist);
-}
-
DiskIOProcessor::ChannelInfo::ChannelInfo (framecnt_t bufsize)
{
buf = new RingBufferNPT<Sample> (bufsize);
capture_transition_buf = 0;
}
+void
+DiskIOProcessor::drop_route ()
+{
+ _route.reset ();
+}
+
void
DiskIOProcessor::set_route (boost::shared_ptr<Route> r)
{
_route = r;
+
+ if (_route) {
+ _route->DropReferences.connect_same_thread (*this, boost::bind (&DiskIOProcessor::drop_route, this));
+ }
+}
+
+/** Get the start, end, and length of a location "atomically".
+ *
+ * Note: Locations don't get deleted, so all we care about when I say "atomic"
+ * is that we are always pointing to the same one and using start/length values
+ * obtained just once. Use this function to achieve this since location being
+ * a parameter achieves this.
+ */
+void
+DiskIOProcessor::get_location_times(const Location* location,
+ framepos_t* start,
+ framepos_t* end,
+ framepos_t* length)
+{
+ if (location) {
+ *start = location->start();
+ *end = location->end();
+ *length = *end - *start;
+ }
}