From 9d5d82b4df5b3510177fd31557ac765f46778fe8 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 30 Jul 2006 03:25:38 +0000 Subject: Abstraction cleanups/polish, towards merging with trunk git-svn-id: svn://localhost/ardour2/branches/midi@720 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/audio_diskstream.h | 93 +++++----------- libs/ardour/ardour/diskstream.h | 62 ++++------- libs/ardour/ardour/midi_diskstream.h | 22 +--- libs/ardour/ardour/playlist.h | 17 ++- libs/ardour/ardour/region.h | 2 + libs/ardour/ardour/session.h | 2 +- libs/ardour/audio_diskstream.cc | 197 ++++++++++------------------------ libs/ardour/diskstream.cc | 112 +++++++++++++++---- libs/ardour/midi_diskstream.cc | 4 +- libs/ardour/session.cc | 4 +- libs/ardour/session_butler.cc | 18 ++-- libs/ardour/session_state.cc | 3 +- 12 files changed, 224 insertions(+), 312 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index c4a942a5d7..ec15cf1caf 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,8 +14,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: diskstream.h 579 2006-06-12 19:56:37Z essej $ */ #ifndef __ardour_audio_diskstream_h__ @@ -62,18 +60,12 @@ class AudioDiskstream : public Diskstream AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable); AudioDiskstream (Session &, const XMLNode&); - void set_io (ARDOUR::IO& io); - + // FIXME AudioDiskstream& ref() { _refcnt++; return *this; } - //void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; } - //uint32_t refcnt() const { return _refcnt; } float playback_buffer_load() const; float capture_buffer_load() const; - //void set_align_style (AlignStyle); - //void set_persistent_align_style (AlignStyle); - string input_source (uint32_t n=0) const { if (n < channels.size()) { return channels[n].source ? channels[n].source->name() : ""; @@ -87,7 +79,6 @@ class AudioDiskstream : public Diskstream } void set_record_enabled (bool yn, void *src); - //void set_speed (double); float peak_power(uint32_t n=0) { float x = channels[n].peak_power; @@ -98,16 +89,13 @@ class AudioDiskstream : public Diskstream return minus_infinity(); } } + + AudioPlaylist* audio_playlist () { return dynamic_cast(_playlist); } int use_playlist (Playlist *); int use_new_playlist (); int use_copy_playlist (); - void start_scrub (jack_nframes_t where) {} // FIXME? - void end_scrub () {} // FIXME? - - Playlist *playlist () { return _playlist; } - Sample *playback_buffer (uint32_t n=0) { if (n < channels.size()) return channels[n].current_playback_buffer; @@ -137,7 +125,6 @@ class AudioDiskstream : public Diskstream void monitor_input (bool); - // FIXME: these don't belong here static void swap_by_ptr (Sample *first, Sample *last) { while (first < last) { Sample tmp = *first; @@ -154,11 +141,6 @@ class AudioDiskstream : public Diskstream } } - //void handle_input_change (IOChange, void *src); - - //static sigc::signal DiskOverrun; - //static sigc::signal DiskUnderrun; - //static sigc::signal AudioDiskstreamCreated; // XXX use a ref with sigc2 static sigc::signal*> DeleteSources; int set_loop (Location *loc); @@ -168,8 +150,6 @@ class AudioDiskstream : public Diskstream return _last_capture_regions; } - void handle_input_change (IOChange, void *src); - const PBD::ID& id() const { return _id; } XMLNode* deprecated_io_node; @@ -184,7 +164,6 @@ class AudioDiskstream : public Diskstream void set_pending_overwrite(bool); int overwrite_existing_buffers (); - void reverse_scrub_buffer (bool to_forward) {} // FIXME? void set_block_size (jack_nframes_t); int internal_playback_seek (jack_nframes_t distance); int can_internal_playback_seek (jack_nframes_t distance); @@ -237,60 +216,30 @@ class AudioDiskstream : public Diskstream jack_nframes_t curr_capture_cnt; }; - typedef vector ChannelList; - - /* the two central butler operations */ - - int do_flush (char * workbuf, bool force = false); - int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf); + /* The two central butler operations */ + int do_flush (Session::RunContext context, bool force = false); + int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer, _conversion_buffer); } - virtual int non_realtime_do_refill() { return do_refill(0, 0, 0); } + int do_refill_with_alloc(); - int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, - ChannelInfo& channel_info, int channel, bool reversed); - - /* XXX fix this redundancy ... */ - - //void playlist_changed (Change); - //void playlist_modified (); - void playlist_deleted (Playlist*); - void session_controls_changed (Session::ControlType) {} // FIXME? + int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, + jack_nframes_t& start, jack_nframes_t cnt, + ChannelInfo& channel_info, int channel, bool reversed); void finish_capture (bool rec_monitors_input); - void clean_up_capture (struct tm&, time_t, bool abort) {} // FIXME? void transport_stopped (struct tm&, time_t, bool abort); - struct CaptureInfo { - uint32_t start; - uint32_t frames; - }; - - vector capture_info; - Glib::Mutex capture_info_lock; - void init (Diskstream::Flag); void init_channel (ChannelInfo &chan); void destroy_channel (ChannelInfo &chan); int use_new_write_source (uint32_t n=0); - int use_new_fade_source (uint32_t n=0) { return 0; } // FIXME? int find_and_use_playlist (const string&); void allocate_temporary_buffers (); - int create_input_port () { return 0; } // FIXME? - int connect_input_port () { return 0; } // FIXME? - int seek_unlocked (jack_nframes_t which_sample) { return 0; } // FIXME? - - int ports_created () { return 0; } // FIXME? - - //bool realtime_set_speed (double, bool global_change); - void non_realtime_set_speed (); - - std::list _last_capture_regions; - std::vector capturing_sources; int use_pending_capture_data (XMLNode& node); void get_input_sources (); @@ -299,10 +248,26 @@ class AudioDiskstream : public Diskstream void setup_destructive_playlist (); void use_destructive_playlist (); - ChannelList channels; - AudioPlaylist* _playlist; void engage_record_enable (void* src); void disengage_record_enable (void* src); + + // Working buffers for do_refill (butler thread) + static void allocate_working_buffers(); + static void free_working_buffers(); + + static size_t _working_buffers_size; + static Sample* _mixdown_buffer; + static gain_t* _gain_buffer; + static char* _conversion_buffer; + + // Uh, /really/ private? (death to friend classes) + int _do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf); + + + std::vector capturing_sources; + + typedef vector ChannelList; + ChannelList channels; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index b595879264..ff25127ec9 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,7 +52,6 @@ class AudioEngine; class Send; class Session; class Playlist; -//class FileSource; class IO; /* FIXME: There are (obviously) far too many virtual functions in this ATM. @@ -71,10 +70,10 @@ class Diskstream : public Stateful, public sigc::trackable virtual int set_name (string str, void* src); ARDOUR::IO* io() const { return _io; } - virtual void set_io (ARDOUR::IO& io) = 0; + void set_io (ARDOUR::IO& io); virtual Diskstream& ref() { _refcnt++; return *this; } - void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; } + void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; } uint32_t refcnt() const { return _refcnt; } virtual float playback_buffer_load() const = 0; @@ -105,17 +104,15 @@ class Diskstream : public Stateful, public sigc::trackable virtual void punch_in() {} virtual void punch_out() {} - virtual void set_speed (double); - virtual void non_realtime_set_speed () = 0; + void set_speed (double); + void non_realtime_set_speed (); - virtual Playlist *playlist () = 0; + Playlist* playlist () { return _playlist; } + + virtual int use_playlist (Playlist *); virtual int use_new_playlist () = 0; - virtual int use_playlist (Playlist *) = 0; virtual int use_copy_playlist () = 0; - virtual void start_scrub (jack_nframes_t where) = 0; - virtual void end_scrub () = 0; - jack_nframes_t current_capture_start() const { return capture_start_frame; } jack_nframes_t current_capture_end() const { return capture_start_frame + capture_captured; } jack_nframes_t get_capture_start_frame (uint32_t n=0); @@ -123,7 +120,7 @@ class Diskstream : public Stateful, public sigc::trackable uint32_t n_channels() { return _n_channels; } - static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; } + static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; } static void set_disk_io_chunk_frames (uint32_t n) { disk_io_chunk_frames = n; } /* Stateful */ @@ -144,7 +141,7 @@ class Diskstream : public Stateful, public sigc::trackable std::list& last_capture_regions () { return _last_capture_regions; } - virtual void handle_input_change (IOChange, void *src); + void handle_input_change (IOChange, void *src); sigc::signal RecordEnableChanged; sigc::signal SpeedChanged; @@ -170,7 +167,6 @@ class Diskstream : public Stateful, public sigc::trackable virtual void set_pending_overwrite (bool) = 0; virtual int overwrite_existing_buffers () = 0; - virtual void reverse_scrub_buffer (bool to_forward) = 0; virtual void set_block_size (jack_nframes_t) = 0; virtual int internal_playback_seek (jack_nframes_t distance) = 0; virtual int can_internal_playback_seek (jack_nframes_t distance) = 0; @@ -209,25 +205,21 @@ class Diskstream : public Stateful, public sigc::trackable jack_nframes_t capture_val; }; - /* the two central butler operations */ - - virtual int do_flush (char * workbuf, bool force = false) = 0; - //int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf); + /* The two central butler operations */ + virtual int do_flush (Session::RunContext context, bool force = false) = 0; + virtual int do_refill () = 0; - virtual int non_realtime_do_refill() = 0; + /** For non-butler contexts (allocates temporary working buffers) */ + virtual int do_refill_with_alloc() = 0; - //int read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, - // ChannelInfo& channel_info, int channel, bool reversed); /* XXX fix this redundancy ... */ virtual void playlist_changed (Change); virtual void playlist_modified (); - virtual void playlist_deleted (Playlist*) = 0; - virtual void session_controls_changed (Session::ControlType) = 0; + virtual void playlist_deleted (Playlist*); virtual void finish_capture (bool rec_monitors_input) = 0; - virtual void clean_up_capture (struct tm&, time_t, bool abort) = 0; virtual void transport_stopped (struct tm&, time_t, bool abort) = 0; struct CaptureInfo { @@ -237,37 +229,23 @@ class Diskstream : public Stateful, public sigc::trackable virtual void init (Flag); - //void init_channel (ChannelInfo &chan); - //void destroy_channel (ChannelInfo &chan); - virtual int use_new_write_source (uint32_t n=0) = 0; - virtual int use_new_fade_source (uint32_t n=0) = 0; virtual int find_and_use_playlist (const string&) = 0; - //void allocate_temporary_buffers (); - - virtual int create_input_port () = 0; - virtual int connect_input_port () = 0; - virtual int seek_unlocked (jack_nframes_t which_sample) = 0; - - virtual int ports_created () = 0; + virtual void allocate_temporary_buffers () = 0; virtual bool realtime_set_speed (double, bool global_change); - //void non_realtime_set_speed (); std::list _last_capture_regions; - //std::vector capturing_sources; virtual int use_pending_capture_data (XMLNode& node) = 0; virtual void get_input_sources () = 0; virtual void check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record) = 0; - //void set_align_style_from_io(); + virtual void set_align_style_from_io() {} virtual void setup_destructive_playlist () = 0; - //void use_destructive_playlist (); + virtual void use_destructive_playlist () = 0; - // Wouldn't hurt for this thing to do on a diet: - static jack_nframes_t disk_io_chunk_frames; vector capture_info; Glib::Mutex capture_info_lock; @@ -279,6 +257,7 @@ class Diskstream : public Stateful, public sigc::trackable ARDOUR::IO* _io; uint32_t _n_channels; PBD::ID _id; + Playlist* _playlist; mutable gint _record_enabled; double _visible_speed; @@ -338,7 +317,6 @@ class Diskstream : public Stateful, public sigc::trackable sigc::connection plgone_connection; unsigned char _flags; - }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index b6121d1176..5998363d69 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -80,9 +80,6 @@ class MidiDiskstream : public Diskstream int use_new_playlist (); int use_copy_playlist (); - void start_scrub (jack_nframes_t where) {} // FIXME? - void end_scrub () {} // FIXME? - Playlist *playlist () { return _playlist; } static sigc::signal*> DeleteSources; @@ -106,7 +103,6 @@ class MidiDiskstream : public Diskstream void set_pending_overwrite(bool); int overwrite_existing_buffers (); - void reverse_scrub_buffer (bool to_forward) {} // FIXME? void set_block_size (jack_nframes_t); int internal_playback_seek (jack_nframes_t distance); int can_internal_playback_seek (jack_nframes_t distance); @@ -134,12 +130,11 @@ class MidiDiskstream : public Diskstream MidiPlaylist* _playlist; - /* the two central butler operations */ - - int do_flush (char * workbuf, bool force = false); - int do_refill (RawMidi *mixdown_buffer, float *gain_buffer, char *workbuf); + /*Tthe two central butler operations */ + int do_flush (Session::RunContext context, bool force = false) { return 0; } + int do_refill () { return 0; } - virtual int non_realtime_do_refill() { return do_refill(0, 0, 0); } + int do_refill_with_alloc() { return 0; } int read (RawMidi* buf, RawMidi* mixdown_buffer, char * workbuf, jack_nframes_t& start, jack_nframes_t cnt, bool reversed); @@ -148,10 +143,8 @@ class MidiDiskstream : public Diskstream //void playlist_changed (Change); //void playlist_modified (); void playlist_deleted (Playlist*); - void session_controls_changed (Session::ControlType) {} // FIXME? void finish_capture (bool rec_monitors_input); - void clean_up_capture (struct tm&, time_t, bool abort) {} // FIXME? void transport_stopped (struct tm&, time_t, bool abort); struct CaptureInfo { @@ -162,18 +155,11 @@ class MidiDiskstream : public Diskstream void init (Diskstream::Flag); int use_new_write_source (uint32_t n=0); - int use_new_fade_source (uint32_t n=0) { return 0; } // FIXME? int find_and_use_playlist (const string&); void allocate_temporary_buffers (); - int create_input_port () { return 0; } // FIXME? - int connect_input_port () { return 0; } // FIXME? - int seek_unlocked (jack_nframes_t which_sample) { return 0; } // FIXME? - - int ports_created () { return 0; } // FIXME? - //bool realtime_set_speed (double, bool global_change); void non_realtime_set_speed (); diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index ca760a5ad5..add253982f 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -110,16 +110,15 @@ class Playlist : public Stateful, public StateManager { int set_state (const XMLNode&); XMLNode& get_template (); - sigc::signal RegionAdded; - sigc::signal RegionRemoved; - + sigc::signal RegionAdded; + sigc::signal RegionRemoved; sigc::signal InUse; - sigc::signal Modified; - sigc::signal NameChanged; - sigc::signal LengthChanged; - sigc::signal LayeringChanged; - sigc::signal GoingAway; - sigc::signal StatePushed; + sigc::signal Modified; + sigc::signal NameChanged; + sigc::signal LengthChanged; + sigc::signal LayeringChanged; + sigc::signal GoingAway; + sigc::signal StatePushed; static sigc::signal PlaylistCreated; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 68ac55df67..a138f66042 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -145,6 +145,8 @@ class Region : public Stateful, public StateManager bool overlap_equivalent (const Region&) const; bool region_list_equivalent (const Region&) const; virtual bool source_equivalent (const Region&) const = 0; + + virtual bool speed_mismatch (float) const = 0; /*virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 7bd24b96cc..dd8ec4806a 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -938,7 +938,7 @@ class Session : public sigc::trackable, public Stateful /* buffers for gain and pan */ gain_t* gain_automation_buffer () const { return _gain_automation_buffer; } - pan_t** pan_automation_buffer() const { return _pan_automation_buffer; } + pan_t** pan_automation_buffer () const { return _pan_automation_buffer; } /* buffers for conversion */ enum RunContext { diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index a3345cf15a..5f6ce05016 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2003 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,8 +14,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: diskstream.cc 567 2006-06-07 14:54:12Z trutkin $ */ #include @@ -23,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -57,10 +56,14 @@ using namespace PBD; sigc::signal*> AudioDiskstream::DeleteSources; +size_t AudioDiskstream::_working_buffers_size = 0; +Sample* AudioDiskstream::_mixdown_buffer = 0; +gain_t* AudioDiskstream::_gain_buffer = 0; +char* AudioDiskstream::_conversion_buffer = 0; + AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag) : Diskstream(sess, name, flag) , deprecated_io_node(NULL) - , _playlist(NULL) { /* prevent any write sources from being created */ @@ -77,7 +80,6 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream: AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) : Diskstream(sess, node) , deprecated_io_node(NULL) - , _playlist(NULL) { in_set_state = true; init (Recordable); @@ -178,25 +180,33 @@ AudioDiskstream::~AudioDiskstream () { Glib::Mutex::Lock lm (state_lock); - if (_playlist) - _playlist->unref (); - - for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { + for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) destroy_channel((*chan)); - } channels.clear(); } void -AudioDiskstream::handle_input_change (IOChange change, void *src) +AudioDiskstream::allocate_working_buffers() { - Glib::Mutex::Lock lm (state_lock); + assert(disk_io_frames() > 0); - if (!(input_change_pending & change)) { - input_change_pending = IOChange (input_change_pending|change); - _session.request_input_change_handling (); - } + _working_buffers_size = disk_io_frames(); + _mixdown_buffer = new Sample[_working_buffers_size]; + _gain_buffer = new gain_t[_working_buffers_size]; + _conversion_buffer = new char[_working_buffers_size * 4]; +} + +void +AudioDiskstream::free_working_buffers() +{ + delete _mixdown_buffer; + delete _gain_buffer; + delete _conversion_buffer; + _working_buffers_size = 0; + _mixdown_buffer = 0; + _gain_buffer = 0; + _conversion_buffer = 0; } void @@ -312,40 +322,7 @@ AudioDiskstream::use_playlist (Playlist* playlist) { assert(dynamic_cast(playlist)); - { - Glib::Mutex::Lock lm (state_lock); - - if (playlist == _playlist) { - return 0; - } - - plstate_connection.disconnect(); - plmod_connection.disconnect (); - plgone_connection.disconnect (); - - if (_playlist) { - _playlist->unref(); - } - - _playlist = dynamic_cast(playlist); - _playlist->ref(); - - if (!in_set_state && recordable()) { - reset_write_sources (false); - } - - plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &AudioDiskstream::playlist_changed)); - plmod_connection = _playlist->Modified.connect (mem_fun (*this, &AudioDiskstream::playlist_modified)); - plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &AudioDiskstream::playlist_deleted)); - } - - if (!overwrite_queued) { - _session.request_overwrite_buffer (this); - overwrite_queued = true; - } - - PlaylistChanged (); /* EMIT SIGNAL */ - _session.set_dirty (); + Diskstream::use_playlist(playlist); return 0; } @@ -377,6 +354,8 @@ AudioDiskstream::use_new_playlist () int AudioDiskstream::use_copy_playlist () { + assert(audio_playlist()); + if (destructive()) { return 0; } @@ -391,7 +370,7 @@ AudioDiskstream::use_copy_playlist () newname = Playlist::bump_name (_playlist->name(), _session); - if ((playlist = new AudioPlaylist (*_playlist, newname)) != 0) { + if ((playlist = new AudioPlaylist (*audio_playlist(), newname)) != 0) { playlist->set_orig_diskstream_id (id()); return use_playlist (playlist); } else { @@ -399,19 +378,6 @@ AudioDiskstream::use_copy_playlist () } } - -void -AudioDiskstream::playlist_deleted (Playlist* pl) -{ - /* this catches an ordering issue with session destruction. playlists - are destroyed before diskstreams. we have to invalidate any handles - we have to the playlist. - */ - - _playlist = 0; -} - - void AudioDiskstream::setup_destructive_playlist () { @@ -460,36 +426,6 @@ AudioDiskstream::use_destructive_playlist () /* the source list will never be reset for a destructive track */ } -void -AudioDiskstream::set_io (IO& io) -{ - _io = &io; - set_align_style_from_io (); -} - -void -AudioDiskstream::non_realtime_set_speed () -{ - if (_buffer_reallocation_required) - { - Glib::Mutex::Lock lm (state_lock); - allocate_temporary_buffers (); - - _buffer_reallocation_required = false; - } - - if (_seek_required) { - if (speed() != 1.0f || speed() != -1.0f) { - seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true); - } - else { - seek (_session.transport_frame(), true); - } - - _seek_required = false; - } -} - void AudioDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record) { @@ -1054,9 +990,9 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill) file_frame = frame; if (complete_refill) { - while ((ret = non_realtime_do_refill ()) > 0); + while ((ret = do_refill_with_alloc ()) > 0) ; } else { - ret = non_realtime_do_refill (); + ret = do_refill_with_alloc (); } return ret; @@ -1148,7 +1084,7 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, this_read = min(cnt,this_read); - if (_playlist->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) { + if (audio_playlist()->read (buf+offset, mixdown_buffer, gain_buffer, workbuf, start, this_read, channel) != this_read) { error << string_compose(_("AudioDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read, start) << endmsg; return -1; @@ -1182,14 +1118,27 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, } int -AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf) +AudioDiskstream::do_refill_with_alloc() +{ + Sample* mix_buf = new Sample[disk_io_chunk_frames]; + float* gain_buf = new float[disk_io_chunk_frames]; + char* work_buf = new char[disk_io_chunk_frames * 4]; + + int ret = _do_refill(mix_buf, gain_buf, work_buf); + + delete [] mix_buf; + delete [] gain_buf; + delete [] work_buf; + + return ret; +} + +int +AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer, char * workbuf) { int32_t ret = 0; jack_nframes_t to_read; RingBufferNPT::rw_vector vector; - bool free_mixdown; - bool free_gain; - bool free_workbuf; bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f; jack_nframes_t total_space; jack_nframes_t zero_fill; @@ -1197,6 +1146,10 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w ChannelList::iterator i; jack_nframes_t ts; + assert(mixdown_buffer); + assert(gain_buffer); + assert(workbuf); + channels.front().playback_buf->get_write_vector (&vector); if ((total_space = vector.len[0] + vector.len[1]) == 0) { @@ -1303,33 +1256,6 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w zero_fill = 0; } } - - /* Please note: the code to allocate buffers isn't run - during normal butler thread operation. Its there - for other times when we need to call do_refill() - from somewhere other than the butler thread. - */ - - if (mixdown_buffer == 0) { - mixdown_buffer = new Sample[disk_io_chunk_frames]; - free_mixdown = true; - } else { - free_mixdown = false; - } - - if (gain_buffer == 0) { - gain_buffer = new float[disk_io_chunk_frames]; - free_gain = true; - } else { - free_gain = false; - } - - if (workbuf == 0) { - workbuf = new char[disk_io_chunk_frames * 4]; - free_workbuf = true; - } else { - free_workbuf = false; - } jack_nframes_t file_frame_tmp = 0; @@ -1398,22 +1324,15 @@ AudioDiskstream::do_refill (Sample* mixdown_buffer, float* gain_buffer, char * w file_frame = file_frame_tmp; out: - if (free_mixdown) { - delete [] mixdown_buffer; - } - if (free_gain) { - delete [] gain_buffer; - } - if (free_workbuf) { - delete [] workbuf; - } return ret; } int -AudioDiskstream::do_flush (char * workbuf, bool force_flush) +AudioDiskstream::do_flush (Session::RunContext context, bool force_flush) { + char* workbuf = _session.conversion_buffer(context); + uint32_t to_write; int32_t ret = 0; RingBufferNPT::rw_vector vector; @@ -1570,7 +1489,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca */ while (more_work && !err) { - switch (do_flush ( _session.conversion_buffer(Session::TransportContext), true)) { + switch (do_flush (Session::TransportContext, true)) { case 0: more_work = false; break; diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 4e2bec9850..9fc2ded0ce 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000-2003 Paul Davis + Copyright (C) 2000-2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -55,7 +55,7 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -jack_nframes_t Diskstream::disk_io_chunk_frames; +jack_nframes_t Diskstream::disk_io_chunk_frames = 0; sigc::signal Diskstream::DiskstreamCreated; //sigc::signal*> Diskstream::DeleteSources; @@ -65,13 +65,14 @@ sigc::signal Diskstream::DiskUnderrun; Diskstream::Diskstream (Session &sess, const string &name, Flag flag) : _name (name) , _session (sess) + , _playlist(NULL) { init (flag); } Diskstream::Diskstream (Session& sess, const XMLNode& node) : _session (sess) - + , _playlist(NULL) { init (Recordable); } @@ -113,37 +114,28 @@ Diskstream::init (Flag f) _read_data_count = 0; _write_data_count = 0; - /* there are no channels at this point, so these - two calls just get speed_buffer_size and wrap_buffer - size setup without duplicating their code. - */ - - //set_block_size (_session.get_block_size()); - //allocate_temporary_buffers (); - pending_overwrite = false; overwrite_frame = 0; overwrite_queued = false; input_change_pending = NoChange; - //add_channel (); - _n_channels = 0;//1; + _n_channels = 0; } Diskstream::~Diskstream () { - // Taken by child.. assure lock? + // Taken by derived class destrctors.. assure lock? //Glib::Mutex::Lock lm (state_lock); - //if (_playlist) { - // _playlist->unref (); - //} + if (_playlist) + _playlist->unref (); +} - //for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { - // destroy_channel((*chan)); - //} - - //channels.clear(); +void +Diskstream::set_io (IO& io) +{ + _io = &io; + set_align_style_from_io (); } void @@ -157,6 +149,29 @@ Diskstream::handle_input_change (IOChange change, void *src) } } +void +Diskstream::non_realtime_set_speed () +{ + if (_buffer_reallocation_required) + { + Glib::Mutex::Lock lm (state_lock); + allocate_temporary_buffers (); + + _buffer_reallocation_required = false; + } + + if (_seek_required) { + if (speed() != 1.0f || speed() != -1.0f) { + seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()), true); + } + else { + seek (_session.transport_frame(), true); + } + + _seek_required = false; + } +} + bool Diskstream::realtime_set_speed (double sp, bool global) { @@ -223,7 +238,6 @@ Diskstream::set_align_style (AlignStyle a) return; } - if (a != _alignment_style) { _alignment_style = a; AlignmentStyleChanged (); @@ -287,6 +301,47 @@ Diskstream::set_speed (double sp) playlist_modified(); } +int +Diskstream::use_playlist (Playlist* playlist) +{ + { + Glib::Mutex::Lock lm (state_lock); + + if (playlist == _playlist) { + return 0; + } + + plstate_connection.disconnect(); + plmod_connection.disconnect (); + plgone_connection.disconnect (); + + if (_playlist) { + _playlist->unref(); + } + + _playlist = playlist; + _playlist->ref(); + + if (!in_set_state && recordable()) { + reset_write_sources (false); + } + + plstate_connection = _playlist->StateChanged.connect (mem_fun (*this, &Diskstream::playlist_changed)); + plmod_connection = _playlist->Modified.connect (mem_fun (*this, &Diskstream::playlist_modified)); + plgone_connection = _playlist->GoingAway.connect (mem_fun (*this, &Diskstream::playlist_deleted)); + } + + if (!overwrite_queued) { + _session.request_overwrite_buffer (this); + overwrite_queued = true; + } + + PlaylistChanged (); /* EMIT SIGNAL */ + _session.set_dirty (); + + return 0; +} + void Diskstream::playlist_changed (Change ignored) { @@ -302,6 +357,17 @@ Diskstream::playlist_modified () } } +void +Diskstream::playlist_deleted (Playlist* pl) +{ + /* this catches an ordering issue with session destruction. playlists + are destroyed before diskstreams. we have to invalidate any handles + we have to the playlist. + */ + + _playlist = 0; +} + int Diskstream::set_name (string str, void *src) { diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index a5853136ea..4602fc8f67 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -388,7 +388,7 @@ MidiDiskstream::read (RawMidi* buf, RawMidi* mixdown_buffer, char * workbuf, jac { return 0; } - +/* int MidiDiskstream::do_refill (RawMidi* mixdown_buffer, float* gain_buffer, char * workbuf) { @@ -400,7 +400,7 @@ MidiDiskstream::do_flush (char * workbuf, bool force_flush) { return 0; } - +*/ void MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index fec674b671..011d1d6237 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -403,6 +403,8 @@ Session::~Session () for (map::iterator i = _conversion_buffers.begin(); i != _conversion_buffers.end(); ++i) { delete [] (i->second); } + + AudioDiskstream::free_working_buffers(); #undef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION @@ -2105,7 +2107,7 @@ void Session::add_diskstream (Diskstream* dstream) { /* need to do this in case we're rolling at the time, to prevent false underruns */ - dstream->non_realtime_do_refill(); + dstream->do_refill_with_alloc(); { Glib::RWLock::WriterLock lm (diskstream_lock); diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index f0a2af0a83..6509a783bb 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -170,11 +170,6 @@ Session::butler_thread_work () bool disk_work_outstanding = false; DiskstreamList::iterator i; - butler_mixdown_buffer = new Sample[AudioDiskstream::disk_io_frames()]; - butler_gain_buffer = new gain_t[AudioDiskstream::disk_io_frames()]; - // this buffer is used for temp conversion purposes in filesources - char * conv_buffer = conversion_buffer(ButlerContext); - while (true) { pfd[0].fd = butler_request_pipe[0]; pfd[0].events = POLLIN|POLLERR|POLLHUP; @@ -256,16 +251,15 @@ Session::butler_thread_work () Glib::RWLock::ReaderLock dsm (diskstream_lock); for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) { - // cerr << "rah fondr " << (*i)->io()->name () << endl; - AudioDiskstream* ads = dynamic_cast(*i); - if (!ads) continue; // FIXME - switch (ads->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) { + Diskstream* const ds = *i; + + switch (ds->do_refill ()) { case 0: - bytes += ads->read_data_count(); + bytes += ds->read_data_count(); break; case 1: - bytes += ads->read_data_count(); + bytes += ds->read_data_count(); disk_work_outstanding = true; break; @@ -302,7 +296,7 @@ Session::butler_thread_work () for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) { // cerr << "write behind for " << (*i)->name () << endl; - switch ((*i)->do_flush (conv_buffer)) { + switch ((*i)->do_flush (Session::ButlerContext)) { case 0: bytes += (*i)->write_data_count(); break; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 73ba391873..0809aae6eb 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -196,7 +196,8 @@ Session::first_stage_init (string fullpath, string snapshot_name) /* allocate conversion buffers */ _conversion_buffers[ButlerContext] = new char[AudioDiskstream::disk_io_frames() * 4]; _conversion_buffers[TransportContext] = new char[AudioDiskstream::disk_io_frames() * 4]; - + AudioDiskstream::allocate_working_buffers(); + /* default short fade = 15ms */ Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0)); -- cgit v1.2.3