From 6f4a92f740b2fd75794489ce58f9348f8adf6bf4 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 1 Aug 2006 03:23:35 +0000 Subject: Heavy-duty abstraction work to split type-specific classes into specializations of (new, for the most part) generic bases. (eg. most everything from the MIDI branch except for actual MIDI things, so merges have a chance of succeeding). Also the new edit toolbar, and various other cleanup things I did along the way. Should be functionally equivalent (except the toolbar), this is just design work. She's a big'un.... git-svn-id: svn://localhost/ardour2/trunk@727 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/SConscript | 2 + libs/ardour/ardour/audio_diskstream.h | 276 +++------------ libs/ardour/ardour/audio_track.h | 113 +----- libs/ardour/ardour/audioengine.h | 5 +- libs/ardour/ardour/audioplaylist.h | 3 - libs/ardour/ardour/audioregion.h | 85 ++--- libs/ardour/ardour/buffer.h | 144 ++++++++ libs/ardour/ardour/diskstream.h | 319 +++++++++++++++++ libs/ardour/ardour/io.h | 26 +- libs/ardour/ardour/playlist.h | 20 +- libs/ardour/ardour/port.h | 73 ++-- libs/ardour/ardour/region.h | 104 +++--- libs/ardour/ardour/route.h | 5 +- libs/ardour/ardour/route_group.h | 3 +- libs/ardour/ardour/route_group_specialized.h | 6 +- libs/ardour/ardour/session.h | 69 ++-- libs/ardour/ardour/session_diskstream.h | 42 --- libs/ardour/ardour/track.h | 158 +++++++++ libs/ardour/ardour/types.h | 6 + libs/ardour/audio_diskstream.cc | 510 +++++---------------------- libs/ardour/audio_playlist.cc | 40 +-- libs/ardour/audio_track.cc | 263 +++----------- libs/ardour/audioengine.cc | 37 +- libs/ardour/audioregion.cc | 51 +-- libs/ardour/auditioner.cc | 40 ++- libs/ardour/diskstream.cc | 401 +++++++++++++++++++++ libs/ardour/io.cc | 65 ++-- libs/ardour/playlist.cc | 25 ++ libs/ardour/port.cc | 18 +- libs/ardour/region.cc | 39 +- libs/ardour/route.cc | 14 +- libs/ardour/session.cc | 117 +++--- libs/ardour/session_butler.cc | 51 ++- libs/ardour/session_export.cc | 2 +- libs/ardour/session_process.cc | 12 +- libs/ardour/session_state.cc | 5 +- libs/ardour/session_transport.cc | 40 +-- libs/ardour/track.cc | 219 ++++++++++++ 38 files changed, 1937 insertions(+), 1471 deletions(-) create mode 100644 libs/ardour/ardour/buffer.h create mode 100644 libs/ardour/ardour/diskstream.h delete mode 100644 libs/ardour/ardour/session_diskstream.h create mode 100644 libs/ardour/ardour/track.h create mode 100644 libs/ardour/diskstream.cc create mode 100644 libs/ardour/track.cc (limited to 'libs') diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 1c30921353..303f021f42 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -27,9 +27,11 @@ ardour.Append(POTFILE = domain + '.pot') ardour.Append(CPPPATH = '#libs/surfaces/control_protocol') ardour_files=Split(""" +diskstream.cc audio_diskstream.cc audio_library.cc audio_playlist.cc +track.cc audio_track.cc audioengine.cc audiofilesource.cc diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 0a0c908d31..e2dfc5fd0c 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,12 +14,10 @@ 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_diskstream_h__ -#define __ardour_diskstream_h__ +#ifndef __ardour_audio_diskstream_h__ +#define __ardour_audio_diskstream_h__ #include @@ -42,6 +40,8 @@ #include #include #include +#include +#include struct tm; @@ -54,53 +54,20 @@ class AudioPlaylist; class AudioFileSource; class IO; -class AudioDiskstream : public Stateful, public sigc::trackable +class AudioDiskstream : public Diskstream { public: - enum Flag { - Recordable = 0x1, - Hidden = 0x2, - Destructive = 0x4 - }; - - AudioDiskstream (Session &, const string& name, Flag f = Recordable); + AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable); AudioDiskstream (Session &, const XMLNode&); - string name() const { return _name; } - - ARDOUR::IO* io() const { return _io; } - void set_io (ARDOUR::IO& io); + const PBD::ID& id() const { return _id; } + // 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_flag (Flag f) { - _flags |= f; - } - - void unset_flag (Flag f) { - _flags &= ~f; - } - - AlignStyle alignment_style() const { return _alignment_style; } - void set_align_style (AlignStyle); - void set_persistent_align_style (AlignStyle); - - bool hidden() const { return _flags & Hidden; } - bool recordable() const { return _flags & Recordable; } - bool destructive() const { return _flags & Destructive; } - - void set_destructive (bool yn); - - jack_nframes_t roll_delay() const { return _roll_delay; } - void set_roll_delay (jack_nframes_t); - - int set_name (string str, void* src); - string input_source (uint32_t n=0) const { if (n < channels.size()) { return channels[n].source ? channels[n].source->name() : ""; @@ -113,14 +80,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable if (n < channels.size()) return channels[n].source; return 0; } - void set_record_enabled (bool yn, void *src); - bool record_enabled() const { return g_atomic_int_get (&_record_enabled); } - void punch_in (); - void punch_out (); - - bool reversed() const { return _actual_speed < 0.0f; } - double speed() const { return _visible_speed; } - void set_speed (double); + void set_record_enabled (bool yn); float peak_power(uint32_t n=0) { float x = channels[n].peak_power; @@ -131,14 +91,13 @@ class AudioDiskstream : public Stateful, public sigc::trackable return minus_infinity(); } } + + AudioPlaylist* audio_playlist () { return dynamic_cast(_playlist); } - int use_playlist (AudioPlaylist *); + int use_playlist (Playlist *); int use_new_playlist (); int use_copy_playlist (); - void start_scrub (jack_nframes_t where); - void end_scrub (); - Sample *playback_buffer (uint32_t n=0) { if (n < channels.size()) return channels[n].current_playback_buffer; @@ -151,51 +110,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable return 0; } - AudioPlaylist *playlist () { return _playlist; } - AudioFileSource *write_source (uint32_t n=0) { if (n < channels.size()) return channels[n].write_source; return 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); - jack_nframes_t get_captured_frames (uint32_t n=0); - - uint32_t n_channels() { return _n_channels; } - int add_channel (); int remove_channel (); - static void set_disk_io_chunk_frames (uint32_t n) { - disk_io_chunk_frames = n; - } - - static jack_nframes_t disk_io_frames() { return disk_io_chunk_frames; } - sigc::signal record_enable_changed; - sigc::signal speed_changed; - sigc::signal reverse_changed; - sigc::signal PlaylistChanged; - sigc::signal AlignmentStyleChanged; - - static sigc::signal DiskOverrun; - static sigc::signal DiskUnderrun; - static sigc::signal AudioDiskstreamCreated; // XXX use a ref with sigc2 - static sigc::signal*> DeleteSources; - /* stateful */ XMLNode& get_state(void); - int set_state(const XMLNode& node); + int set_state(const XMLNode& node); void monitor_input (bool); - jack_nframes_t capture_offset() const { return _capture_offset; } - void set_capture_offset (); - static void swap_by_ptr (Sample *first, Sample *last) { while (first < last) { Sample tmp = *first; @@ -212,19 +143,7 @@ class AudioDiskstream : public Stateful, public sigc::trackable } } - bool slaved() const { return _slaved; } - void set_slaved(bool yn) { _slaved = yn; } - - int set_loop (Location *loc); - sigc::signal LoopSet; - - std::list& last_capture_regions () { - return _last_capture_regions; - } - - void handle_input_change (IOChange, void *src); - - const PBD::ID& id() const { return _id; } + std::list& last_capture_regions () { return _last_capture_regions; } XMLNode* deprecated_io_node; @@ -236,9 +155,8 @@ class AudioDiskstream : public Stateful, public sigc::trackable while they are called. */ - void set_pending_overwrite (bool); + void set_pending_overwrite(bool); int overwrite_existing_buffers (); - void reverse_scrub_buffer (bool to_forward); void set_block_size (jack_nframes_t); int internal_playback_seek (jack_nframes_t distance); int can_internal_playback_seek (jack_nframes_t distance); @@ -246,9 +164,6 @@ class AudioDiskstream : public Stateful, public sigc::trackable void reset_write_sources (bool, bool force = false); void non_realtime_input_change (); - uint32_t read_data_count() const { return _read_data_count; } - uint32_t write_data_count() const { return _write_data_count; } - protected: friend class Auditioner; int seek (jack_nframes_t which_sample, bool complete_refill = false); @@ -256,38 +171,23 @@ class AudioDiskstream : public Stateful, public sigc::trackable protected: friend class AudioTrack; - void prepare (); int process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input); bool commit (jack_nframes_t nframes); - void recover (); /* called if commit will not be called, but process was */ private: /* use unref() to destroy a diskstream */ - ~AudioDiskstream(); - enum TransitionType { - CaptureStart = 0, - CaptureEnd - }; - - struct CaptureTransition { - - TransitionType type; - // the start or end file frame pos - jack_nframes_t capture_val; - }; - struct ChannelInfo { Sample *playback_wrap_buffer; Sample *capture_wrap_buffer; Sample *speed_buffer; - float peak_power; + float peak_power; - AudioFileSource *fades_source; + AudioFileSource *fades_source; AudioFileSource *write_source; Port *source; @@ -309,129 +209,30 @@ class AudioDiskstream : public Stateful, public sigc::trackable jack_nframes_t curr_capture_cnt; }; - typedef vector ChannelList; - - - string _name; - ARDOUR::Session& _session; - ARDOUR::IO* _io; - ChannelList channels; - uint32_t _n_channels; - PBD::ID _id; - - mutable gint _record_enabled; - AudioPlaylist* _playlist; - double _visible_speed; - double _actual_speed; - /* items needed for speed change logic */ - bool _buffer_reallocation_required; - bool _seek_required; - - bool force_refill; - jack_nframes_t capture_start_frame; - jack_nframes_t capture_captured; - bool was_recording; - jack_nframes_t adjust_capture_position; - jack_nframes_t _capture_offset; - jack_nframes_t _roll_delay; - jack_nframes_t first_recordable_frame; - jack_nframes_t last_recordable_frame; - int last_possibly_recording; - AlignStyle _alignment_style; - bool _scrubbing; - bool _slaved; - bool _processed; - Location* loop_location; - jack_nframes_t overwrite_frame; - off_t overwrite_offset; - bool pending_overwrite; - bool overwrite_queued; - IOChange input_change_pending; - jack_nframes_t wrap_buffer_size; - jack_nframes_t speed_buffer_size; - - uint64_t last_phase; - uint64_t phi; - - jack_nframes_t file_frame; - jack_nframes_t playback_sample; - jack_nframes_t playback_distance; - - uint32_t _read_data_count; - uint32_t _write_data_count; - - bool in_set_state; - AlignStyle _persistent_alignment_style; - bool first_input_change; - - Glib::Mutex state_lock; - - jack_nframes_t scrub_start; - jack_nframes_t scrub_buffer_size; - jack_nframes_t scrub_offset; - uint32_t _refcnt; - - sigc::connection ports_created_c; - sigc::connection plmod_connection; - sigc::connection plstate_connection; - sigc::connection plgone_connection; - - /* the two central butler operations */ - - int do_flush (char * workbuf, bool force = false); - int do_refill (Sample *mixdown_buffer, float *gain_buffer, char *workbuf); - - 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); - - uint32_t i_am_the_modifier; + /* 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); } - /* XXX fix this redundancy ... */ + int do_refill_with_alloc(); - void playlist_changed (Change); - void playlist_modified (); - void playlist_deleted (Playlist*); - void session_controls_changed (Session::ControlType); + 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); 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 (Flag); + void init (Diskstream::Flag); void init_channel (ChannelInfo &chan); void destroy_channel (ChannelInfo &chan); - static jack_nframes_t disk_io_chunk_frames; - int use_new_write_source (uint32_t n=0); - int use_new_fade_source (uint32_t n=0); int find_and_use_playlist (const string&); void allocate_temporary_buffers (); - unsigned char _flags; - - int create_input_port (); - int connect_input_port (); - int seek_unlocked (jack_nframes_t which_sample); - - int ports_created (); - - 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 (); @@ -439,10 +240,29 @@ class AudioDiskstream : public Stateful, public sigc::trackable void set_align_style_from_io(); void setup_destructive_playlist (); void use_destructive_playlist (); - void engage_record_enable (void* src); - void disengage_record_enable (void* src); + + void engage_record_enable (); + void disengage_record_enable (); + + // 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 -#endif /* __ardour_diskstream_h__ */ +#endif /* __ardour_audio_diskstream_h__ */ diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 5f65e2591d..15b99297c8 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -21,7 +21,7 @@ #ifndef __ardour_audio_track_h__ #define __ardour_audio_track_h__ -#include +#include namespace ARDOUR { @@ -30,76 +30,38 @@ class AudioDiskstream; class AudioPlaylist; class RouteGroup; -class AudioTrack : public Route +class AudioTrack : public Track { public: AudioTrack (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal); AudioTrack (Session&, const XMLNode&); ~AudioTrack (); - - int set_name (string str, void *src); - - int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input); - int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input); - int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t offset, bool can_record, bool rec_monitors_input); - - void toggle_monitor_input (); + int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input); + + int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input); + + int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, bool can_record, bool rec_monitors_input); - bool can_record() const { return true; } - void set_record_enable (bool yn, void *src); + AudioDiskstream& audio_diskstream() const; - AudioDiskstream& disk_stream() const { return *diskstream; } - int set_diskstream (AudioDiskstream&, void *); int use_diskstream (string name); int use_diskstream (const PBD::ID& id); - - TrackMode mode() const { return _mode; } - void set_mode (TrackMode m); - sigc::signal ModeChanged; - - jack_nframes_t update_total_latency(); - void set_latency_delay (jack_nframes_t); int export_stuff (vector& buffers, char * workbuf, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t end_frame); - sigc::signal diskstream_changed; - - enum FreezeState { - NoFreeze, - Frozen, - UnFrozen - }; - - FreezeState freeze_state() const; - - sigc::signal FreezeChange; - void freeze (InterThreadInfo&); void unfreeze (); void bounce (InterThreadInfo&); void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&); - XMLNode& get_state(); - XMLNode& get_template(); int set_state(const XMLNode& node); - PBD::Controllable& rec_enable_control() { - return _rec_enable_control; - } - - bool record_enabled() const; - void set_meter_point (MeterPoint, void* src); - protected: - AudioDiskstream *diskstream; - MeterPoint _saved_meter_point; - TrackMode _mode; - XMLNode& state (bool full); void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, @@ -107,59 +69,12 @@ class AudioTrack : public Route bool meter); uint32_t n_process_buffers (); - + private: - struct FreezeRecordInsertInfo { - FreezeRecordInsertInfo(XMLNode& st, boost::shared_ptr ins) - : state (st), insert (ins) {} - - XMLNode state; - boost::shared_ptr insert; - PBD::ID id; - UndoAction memento; - }; - - struct FreezeRecord { - FreezeRecord() { - playlist = 0; - have_mementos = false; - } - - ~FreezeRecord(); - - AudioPlaylist* playlist; - vector insert_info; - bool have_mementos; - FreezeState state; - }; - - FreezeRecord _freeze_record; - XMLNode* pending_state; - - void diskstream_record_enable_changed (void *src); - void diskstream_input_channel_changed (void *src); - - void input_change_handler (void *src); - - sigc::connection recenable_connection; - sigc::connection ic_connection; - - int deprecated_use_diskstream_connections (); + int set_diskstream (AudioDiskstream&, void *); + int deprecated_use_diskstream_connections (); void set_state_part_two (); void set_state_part_three (); - - struct RecEnableControllable : public PBD::Controllable { - RecEnableControllable (AudioTrack&); - - void set_value (float); - float get_value (void) const; - - AudioTrack& track; - }; - - RecEnableControllable _rec_enable_control; - - bool _destructive; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 8db795ae90..81370e379c 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -34,6 +34,7 @@ #include #include #include +#include namespace ARDOUR { @@ -104,8 +105,8 @@ class AudioEngine : public sigc::trackable virtual const char *what() const throw() { return "could not connect to engine backend"; } }; - Port *register_audio_input_port (const std::string& portname); - Port *register_audio_output_port (const std::string& portname); + Port *register_input_port (DataType type, const std::string& portname); + Port *register_output_port (DataType type, const std::string& portname); int unregister_port (Port *); int connect (const std::string& source, const std::string& destination); diff --git a/libs/ardour/ardour/audioplaylist.h b/libs/ardour/ardour/audioplaylist.h index 1b60cf185d..5a77067f8f 100644 --- a/libs/ardour/ardour/audioplaylist.h +++ b/libs/ardour/ardour/audioplaylist.h @@ -77,9 +77,6 @@ class AudioPlaylist : public ARDOUR::Playlist bool destroy_region (Region*); - void get_equivalent_regions (const AudioRegion&, std::vector&); - void get_region_list_equivalent_regions (const AudioRegion&, std::vector&); - void drop_all_states (); protected: diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index d7bb0c916b..683e946713 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -27,8 +27,9 @@ #include #include -#include #include +#include +#include #include class XMLNode; @@ -43,14 +44,14 @@ class AudioSource; struct AudioRegionState : public RegionState { - AudioRegionState (std::string why); - - Curve _fade_in; - Curve _fade_out; - Curve _envelope; - gain_t _scale_amplitude; - uint32_t _fade_in_disabled; - uint32_t _fade_out_disabled; + AudioRegionState (std::string why); + + Curve _fade_in; + Curve _fade_out; + Curve _envelope; + gain_t _scale_amplitude; + uint32_t _fade_in_disabled; + uint32_t _fade_out_disabled; }; class AudioRegion : public Region @@ -75,11 +76,7 @@ class AudioRegion : public Region AudioRegion (SourceList &, const XMLNode&); ~AudioRegion(); - bool region_list_equivalent (const AudioRegion&) const ; - bool source_equivalent (const AudioRegion&) const; - bool equivalent (const AudioRegion&) const; - bool size_equivalent (const AudioRegion&) const; - bool overlap_equivalent (const AudioRegion&) const; + bool source_equivalent (const Region&) const; bool speed_mismatch (float) const; @@ -96,7 +93,7 @@ class AudioRegion : public Region vector master_source_names(); bool envelope_active () const { return _flags & Region::EnvelopeActive; } - bool fade_in_active () const { return _flags & Region::FadeIn; } + bool fade_in_active () const { return _flags & Region::FadeIn; } bool fade_out_active () const { return _flags & Region::FadeOut; } bool captured() const { return !(_flags & (Region::Flag (Region::Import|Region::External))); } @@ -104,20 +101,21 @@ class AudioRegion : public Region Curve& fade_out() { return _fade_out; } Curve& envelope() { return _envelope; } - jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks, jack_nframes_t offset, jack_nframes_t cnt, uint32_t chan_n=0, double samples_per_unit= 1.0) const; - - virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, - uint32_t chan_n = 0, - jack_nframes_t read_frames = 0, - jack_nframes_t skip_frames = 0) const; + jack_nframes_t read_peaks (PeakData *buf, jack_nframes_t npeaks, + jack_nframes_t offset, jack_nframes_t cnt, + uint32_t chan_n=0, double samples_per_unit= 1.0) const; - jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const; + virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buf, + float *gain_buf, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, + uint32_t chan_n = 0, + jack_nframes_t read_frames = 0, + jack_nframes_t skip_frames = 0) const; + jack_nframes_t master_read_at (Sample *buf, Sample *mixdown_buf, + float *gain_buf, char * workbuf, + jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n=0) const; XMLNode& state (bool); - XMLNode& get_state (); int set_state (const XMLNode&); static void set_default_fade (float steepness, jack_nframes_t len); @@ -144,10 +142,6 @@ class AudioRegion : public Region int separate_by_channel (ARDOUR::Session&, vector&) const; - uint32_t read_data_count() const { return _read_data_count; } - - ARDOUR::Playlist* playlist() const { return _playlist; } - UndoAction get_memento() const; /* filter */ @@ -171,20 +165,6 @@ class AudioRegion : public Region friend class Playlist; private: - SourceList sources; - SourceList master_sources; /* used when timefx are applied, so - we can always use the original - source. - */ - mutable Curve _fade_in; - FadeShape _fade_in_shape; - mutable Curve _fade_out; - FadeShape _fade_out_shape; - mutable Curve _envelope; - gain_t _scale_amplitude; - uint32_t _fade_in_disabled; - uint32_t _fade_out_disabled; - void set_default_fades (); void set_default_fade_in (); void set_default_fade_out (); @@ -196,10 +176,6 @@ class AudioRegion : public Region void recompute_gain_at_end (); void recompute_gain_at_start (); - bool copied() const { return _flags & Copied; } - void maybe_uncopy (); - void rename_after_first_edit (); - jack_nframes_t _read_at (const SourceList&, Sample *buf, Sample *mixdown_buffer, float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, uint32_t chan_n = 0, @@ -216,6 +192,21 @@ class AudioRegion : public Region void envelope_changed (Change); void source_deleted (Source*); + + + SourceList sources; + + /** Used when timefx are applied, so we can always use the original source. */ + SourceList master_sources; + + mutable Curve _fade_in; + FadeShape _fade_in_shape; + mutable Curve _fade_out; + FadeShape _fade_out_shape; + mutable Curve _envelope; + gain_t _scale_amplitude; + uint32_t _fade_in_disabled; + uint32_t _fade_out_disabled; }; } /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h new file mode 100644 index 0000000000..6604e5533b --- /dev/null +++ b/libs/ardour/ardour/buffer.h @@ -0,0 +1,144 @@ +/* + Copyright (C) 2006 Paul Davis + Written by Dave Robillard, 2006 + + 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 the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + 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. +*/ + +#ifndef __ardour_buffer_h__ +#define __ardour_buffer_h__ + +#define _XOPEN_SOURCE 600 +#include // for posix_memalign +#include +#include +#include + +namespace ARDOUR { + + +/* Yes, this is a bit of a mess right now. I'll clean it up when everything + * using it works out.. */ + + +/** A buffer of recordable/playable data. + * + * This is a datatype-agnostic base class for all buffers (there are no + * methods to actually access the data). This provides a way for code that + * doesn't care about the data type to still deal with buffers (which is + * why the base class can't be a template). + * + * To actually read/write buffer contents, use the appropriate derived class. + */ +class Buffer +{ +public: + Buffer(DataType type, size_t capacity) + : _type(type), _capacity(capacity), _size(0) + {} + + virtual ~Buffer() {} + + /** Maximum capacity of buffer. + * Note in some cases the entire buffer may not contain valid data, use size. */ + size_t capacity() const { return _capacity; } + + /** Amount of valid data in buffer. Use this over capacity almost always. */ + size_t size() const { return _size; } + + /** Type of this buffer. + * Based on this you can static cast a Buffer* to the desired type. */ + virtual DataType type() const { return _type; } + + /** Jack type (eg JACK_DEFAULT_AUDIO_TYPE) */ + const char* jack_type() const { return type_to_jack_type(type()); } + + /** String type as saved in session XML files (eg "audio" or "midi") */ + const char* type_string() const { return type_to_string(type()); } + + /* The below static methods need to be separate from the above methods + * because the conversion is needed in places where there's no Buffer. + * These should probably live somewhere else... + */ + + static const char* type_to_jack_type(DataType t) { + switch (t) { + case AUDIO: return JACK_DEFAULT_AUDIO_TYPE; + case MIDI: return JACK_DEFAULT_MIDI_TYPE; + default: return ""; + } + } + + static const char* type_to_string(DataType t) { + switch (t) { + case AUDIO: return "audio"; + case MIDI: return "midi"; + default: return "unknown"; // reeeally shouldn't ever happen + } + } + + /** Used for loading from XML (route default types etc) */ + static DataType type_from_string(const string& str) { + if (str == "audio") + return AUDIO; + else if (str == "midi") + return MIDI; + else + return NIL; + } + +protected: + DataType _type; + size_t _capacity; + size_t _size; +}; + + +/* Inside every class with a type in it's name is a template waiting to get out... */ + + +/** Buffer containing 32-bit floating point (audio) data. */ +class AudioBuffer : public Buffer +{ +public: + AudioBuffer(size_t capacity) + : Buffer(AUDIO, capacity) + , _data(NULL) + { + _size = capacity; // For audio buffers, size = capacity (always) +#ifdef NO_POSIX_MEMALIGN + b = (Sample *) malloc(sizeof(Sample) * capacity); +#else + posix_memalign((void**)_data, 16, sizeof(Sample) * capacity); +#endif + assert(_data); + memset(_data, 0, sizeof(Sample) * capacity); + } + + const Sample* data() const { return _data; } + Sample* data() { return _data; } + +private: + // These are undefined (prevent copies) + AudioBuffer(const AudioBuffer& copy); + AudioBuffer& operator=(const AudioBuffer& copy); + + Sample* const _data; ///< Actual buffer contents +}; + + +} // namespace ARDOUR + +#endif // __ardour_buffer_h__ diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h new file mode 100644 index 0000000000..ebce516d8b --- /dev/null +++ b/libs/ardour/ardour/diskstream.h @@ -0,0 +1,319 @@ +/* + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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_diskstream_h__ +#define __ardour_diskstream_h__ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +struct tm; + +namespace ARDOUR { + +class AudioEngine; +class Send; +class Session; +class Playlist; +class IO; + +class Diskstream : public Stateful, public sigc::trackable +{ + public: + enum Flag { + Recordable = 0x1, + Hidden = 0x2, + Destructive = 0x4 + }; + + string name () const { return _name; } + virtual int set_name (string str); + + ARDOUR::IO* io() const { return _io; } + void set_io (ARDOUR::IO& io); + + virtual Diskstream& ref() { _refcnt++; return *this; } + void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; } + uint32_t refcnt() const { return _refcnt; } + + virtual float playback_buffer_load() const = 0; + virtual float capture_buffer_load() const = 0; + + void set_flag (Flag f) { _flags |= f; } + void unset_flag (Flag f) { _flags &= ~f; } + + AlignStyle alignment_style() const { return _alignment_style; } + void set_align_style (AlignStyle); + void set_persistent_align_style (AlignStyle a) { _persistent_alignment_style = a; } + + jack_nframes_t roll_delay() const { return _roll_delay; } + void set_roll_delay (jack_nframes_t); + + bool record_enabled() const { return g_atomic_int_get (&_record_enabled); } + virtual void set_record_enabled (bool yn) = 0; + + bool destructive() const { return _flags & Destructive; } + virtual void set_destructive (bool yn); + + const PBD::ID& id() const { return _id; } + bool hidden() const { return _flags & Hidden; } + bool recordable() const { return _flags & Recordable; } + bool reversed() const { return _actual_speed < 0.0f; } + double speed() const { return _visible_speed; } + + virtual void punch_in() {} + virtual void punch_out() {} + + void set_speed (double); + void non_realtime_set_speed (); + + Playlist* playlist () { return _playlist; } + + virtual int use_playlist (Playlist *); + virtual int use_new_playlist () = 0; + virtual int use_copy_playlist () = 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); + jack_nframes_t get_captured_frames (uint32_t n=0); + + uint32_t n_channels() { return _n_channels; } + + 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 */ + virtual XMLNode& get_state(void) = 0; + virtual int set_state(const XMLNode& node) = 0; + + // FIXME: makes sense for all diskstream types? + virtual void monitor_input (bool) {} + + jack_nframes_t capture_offset() const { return _capture_offset; } + virtual void set_capture_offset (); + + bool slaved() const { return _slaved; } + void set_slaved(bool yn) { _slaved = yn; } + + int set_loop (Location *loc); + + std::list& last_capture_regions () { return _last_capture_regions; } + + void handle_input_change (IOChange, void *src); + + sigc::signal RecordEnableChanged; + sigc::signal SpeedChanged; + sigc::signal ReverseChanged; + sigc::signal PlaylistChanged; + sigc::signal AlignmentStyleChanged; + sigc::signal LoopSet; + + static sigc::signal DiskOverrun; + static sigc::signal DiskUnderrun; + static sigc::signal DiskstreamCreated; // XXX use a ref with sigc2 + static sigc::signal*> DeleteSources; + + protected: + friend class Session; + + Diskstream (Session &, const string& name, Flag f = Recordable); + Diskstream (Session &, const XMLNode&); + + /* the Session is the only point of access for these because they require + * that the Session is "inactive" while they are called. + */ + + virtual void set_pending_overwrite (bool) = 0; + virtual int overwrite_existing_buffers () = 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; + virtual int rename_write_sources () = 0; + virtual void reset_write_sources (bool, bool force = false) = 0; + virtual void non_realtime_input_change () = 0; + + uint32_t read_data_count() const { return _read_data_count; } + uint32_t write_data_count() const { return _write_data_count; } + + protected: + friend class Auditioner; + virtual int seek (jack_nframes_t which_sample, bool complete_refill = false) = 0; + + protected: + friend class Track; + + virtual void prepare (); + virtual int process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input) = 0; + virtual bool commit (jack_nframes_t nframes) = 0; + virtual void recover (); /* called if commit will not be called, but process was */ + + //private: + + /** Use unref() to destroy a diskstream */ + virtual ~Diskstream(); + + enum TransitionType { + CaptureStart = 0, + CaptureEnd + }; + + struct CaptureTransition { + TransitionType type; + jack_nframes_t capture_val; ///< The start or end file frame position + }; + + /* The two central butler operations */ + virtual int do_flush (Session::RunContext context, bool force = false) = 0; + virtual int do_refill () = 0; + + /** For non-butler contexts (allocates temporary working buffers) */ + virtual int do_refill_with_alloc() = 0; + + + /* XXX fix this redundancy ... */ + + virtual void playlist_changed (Change); + virtual void playlist_modified (); + virtual void playlist_deleted (Playlist*); + + virtual void finish_capture (bool rec_monitors_input) = 0; + virtual void transport_stopped (struct tm&, time_t, bool abort) = 0; + + struct CaptureInfo { + uint32_t start; + uint32_t frames; + }; + + virtual void init (Flag); + + virtual int use_new_write_source (uint32_t n=0) = 0; + + virtual int find_and_use_playlist (const string&) = 0; + + virtual void allocate_temporary_buffers () = 0; + + virtual bool realtime_set_speed (double, bool global_change); + + std::list _last_capture_regions; + 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; + virtual void set_align_style_from_io() {} + virtual void setup_destructive_playlist () = 0; + virtual void use_destructive_playlist () = 0; + + static jack_nframes_t disk_io_chunk_frames; + vector capture_info; + Glib::Mutex capture_info_lock; + + uint32_t i_am_the_modifier; + + string _name; + ARDOUR::Session& _session; + ARDOUR::IO* _io; + uint32_t _n_channels; + PBD::ID _id; + Playlist* _playlist; + + mutable gint _record_enabled; + double _visible_speed; + double _actual_speed; + /* items needed for speed change logic */ + bool _buffer_reallocation_required; + bool _seek_required; + + bool force_refill; + jack_nframes_t capture_start_frame; + jack_nframes_t capture_captured; + bool was_recording; + jack_nframes_t adjust_capture_position; + jack_nframes_t _capture_offset; + jack_nframes_t _roll_delay; + jack_nframes_t first_recordable_frame; + jack_nframes_t last_recordable_frame; + int last_possibly_recording; + AlignStyle _alignment_style; + bool _scrubbing; + bool _slaved; + bool _processed; + Location* loop_location; + jack_nframes_t overwrite_frame; + off_t overwrite_offset; + bool pending_overwrite; + bool overwrite_queued; + IOChange input_change_pending; + jack_nframes_t wrap_buffer_size; + jack_nframes_t speed_buffer_size; + + uint64_t last_phase; + uint64_t phi; + + jack_nframes_t file_frame; + jack_nframes_t playback_sample; + jack_nframes_t playback_distance; + + uint32_t _read_data_count; + uint32_t _write_data_count; + + bool in_set_state; + AlignStyle _persistent_alignment_style; + bool first_input_change; + + Glib::Mutex state_lock; + + jack_nframes_t scrub_start; + jack_nframes_t scrub_buffer_size; + jack_nframes_t scrub_offset; + + uint32_t _refcnt; + + sigc::connection ports_created_c; + sigc::connection plmod_connection; + sigc::connection plstate_connection; + sigc::connection plgone_connection; + + unsigned char _flags; +}; + +}; /* namespace ARDOUR */ + +#endif /* __ardour_diskstream_h__ */ diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 0356da8dc8..35b20f655e 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -38,6 +38,7 @@ #include #include #include +#include using std::string; using std::vector; @@ -52,6 +53,11 @@ class Port; class Connection; class Panner; +/** A collection of input and output ports with connections. + * + * An IO can contain ports of varying types, making routes/inserts/etc with + * varied combinations of types (eg MIDI and audio) possible. + */ class IO : public Stateful, public ARDOUR::StateManager { @@ -60,7 +66,8 @@ class IO : public Stateful, public ARDOUR::StateManager IO (Session&, string name, int input_min = -1, int input_max = -1, - int output_min = -1, int output_max = -1); + int output_min = -1, int output_max = -1, + DataType default_type = AUDIO); virtual ~IO(); @@ -74,25 +81,29 @@ class IO : public Stateful, public ARDOUR::StateManager void set_output_minimum (int n); void set_output_maximum (int n); + DataType default_type() const { return _default_type; } + const string& name() const { return _name; } virtual int set_name (string str, void *src); virtual void silence (jack_nframes_t, jack_nframes_t offset); + // These should be moved in to a separate object that manipulates an IO + void pan (vector& bufs, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset, gain_t gain_coeff); void pan_automated (vector& bufs, uint32_t nbufs, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset); void collect_input (vector&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); - void deliver_output (vector&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); - void deliver_output_no_pan (vector&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void deliver_output (vector&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); + void deliver_output_no_pan (vector&, uint32_t nbufs, jack_nframes_t nframes, jack_nframes_t offset); void just_meter_input (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset); virtual uint32_t n_process_buffers () { return 0; } virtual void set_gain (gain_t g, void *src); - void inc_gain (gain_t delta, void *src); - gain_t gain () const { return _desired_gain; } + void inc_gain (gain_t delta, void *src); + gain_t gain () const { return _desired_gain; } virtual gain_t effective_gain () const; Panner& panner() { return *_panner; } @@ -105,8 +116,8 @@ class IO : public Stateful, public ARDOUR::StateManager Connection *input_connection() const { return _input_connection; } Connection *output_connection() const { return _output_connection; } - int add_input_port (string source, void *src); - int add_output_port (string destination, void *src); + int add_input_port (string source, void *src, DataType type = NIL); + int add_output_port (string destination, void *src, DataType type = NIL); int remove_input_port (Port *, void *src); int remove_output_port (Port *, void *src); @@ -273,6 +284,7 @@ public: PBD::ID _id; bool no_panner_reset; XMLNode* deferred_state; + DataType _default_type; virtual void set_deferred_state() {} diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 9fb1950bfa..9fb5b0eb2b 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -54,7 +54,6 @@ class Playlist : public Stateful, public StateManager { Playlist (const Playlist&, string name, bool hidden = false); Playlist (const Playlist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false); - virtual jack_nframes_t read (Sample *dst, Sample *mixdown, float *gain_buffer, char * workbuf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0) = 0; virtual void clear (bool with_delete = false, bool with_save = true); virtual void dump () const; virtual UndoAction get_memento() const = 0; @@ -81,6 +80,8 @@ class Playlist : public Stateful, public StateManager { void add_region (const Region&, jack_nframes_t position, float times = 1, bool with_save = true); void remove_region (Region *); + void get_equivalent_regions (const Region&, std::vector&); + void get_region_list_equivalent_regions (const Region&, std::vector&); void replace_region (Region& old, Region& newr, jack_nframes_t pos); void split_region (Region&, jack_nframes_t position); void partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level); @@ -108,16 +109,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/port.h b/libs/ardour/ardour/port.h index 93ed2777e4..86c99cb7e3 100644 --- a/libs/ardour/ardour/port.h +++ b/libs/ardour/ardour/port.h @@ -33,24 +33,24 @@ class AudioEngine; class Port : public sigc::trackable { public: virtual ~Port() { - free (port); + free (_port); } Sample *get_buffer (jack_nframes_t nframes) { if (_flags & JackPortIsOutput) { return _buffer; } else { - return (Sample *) jack_port_get_buffer (port, nframes); + return (Sample *) jack_port_get_buffer (_port, nframes); } } void reset_buffer () { if (_flags & JackPortIsOutput) { - _buffer = (Sample *) jack_port_get_buffer (port, 0); + _buffer = (Sample *) jack_port_get_buffer (_port, 0); } else { _buffer = 0; /* catch illegal attempts to use it */ } - silent = false; + _silent = false; } std::string name() { @@ -58,7 +58,7 @@ class Port : public sigc::trackable { } std::string short_name() { - return jack_port_short_name (port); + return jack_port_short_name (_port); } int set_name (std::string str); @@ -68,7 +68,7 @@ class Port : public sigc::trackable { } bool is_mine (jack_client_t *client) { - return jack_port_is_mine (client, port); + return jack_port_is_mine (client, _port); } const char* type() const { @@ -76,21 +76,21 @@ class Port : public sigc::trackable { } int connected () const { - return jack_port_connected (port); + return jack_port_connected (_port); } bool connected_to (const std::string& portname) const { - return jack_port_connected_to (port, portname.c_str()); + return jack_port_connected_to (_port, portname.c_str()); } const char ** get_connections () const { - return jack_port_get_connections (port); + return jack_port_get_connections (_port); } void reset_overs () { _short_overs = 0; _long_overs = 0; - overlen = 0; + _overlen = 0; } void reset_peak_meter () { @@ -103,18 +103,18 @@ class Port : public sigc::trackable { } void enable_metering() { - metering++; + _metering++; } void disable_metering () { - if (metering) { metering--; } + if (_metering) { _metering--; } } - float peak_db() const { return _peak_db; } + float peak_db() const { return _peak_db; } jack_default_audio_sample_t peak() const { return _peak; } uint32_t short_overs () const { return _short_overs; } - uint32_t long_overs () const { return _long_overs; } + uint32_t long_overs () const { return _long_overs; } static void set_short_over_length (jack_nframes_t); static void set_long_over_length (jack_nframes_t); @@ -128,7 +128,7 @@ class Port : public sigc::trackable { } bool monitoring_input () const { - return jack_port_monitoring_input (port); + return jack_port_monitoring_input (_port); } bool can_monitor () const { @@ -136,30 +136,29 @@ class Port : public sigc::trackable { } void ensure_monitor_input (bool yn) { - jack_port_request_monitor (port, yn); + jack_port_request_monitor (_port, yn); } void request_monitor_input (bool yn) { - jack_port_request_monitor (port, yn); + jack_port_request_monitor (_port, yn); } jack_nframes_t latency () const { - return jack_port_get_latency (port); + return jack_port_get_latency (_port); } void set_latency (jack_nframes_t nframes) { - jack_port_set_latency (port, nframes); + jack_port_set_latency (_port, nframes); } sigc::signal MonitorInputChanged; sigc::signal ClockSyncChanged; - bool is_silent() const { return silent; } + bool is_silent() const { return _silent; } + /** Assumes that the port is an audio output port */ void silence (jack_nframes_t nframes, jack_nframes_t offset) { - /* assumes that the port is an output port */ - - if (!silent) { + if (!_silent) { memset (_buffer + offset, 0, sizeof (Sample) * nframes); if (offset == 0) { /* XXX this isn't really true, but i am not sure @@ -167,13 +166,13 @@ class Port : public sigc::trackable { want to set it true when the entire port buffer has been overrwritten. */ - silent = true; + _silent = true; } } } void mark_silence (bool yn) { - silent = yn; + _silent = yn; } private: @@ -184,7 +183,7 @@ class Port : public sigc::trackable { /* engine isn't supposed to below here */ - Sample *_buffer; + Sample *_buffer; /* cache these 3 from JACK so that we can access them for reconnecting. @@ -194,18 +193,18 @@ class Port : public sigc::trackable { std::string _type; std::string _name; - bool last_monitor : 1; - bool silent : 1; - jack_port_t *port; - jack_nframes_t overlen; - jack_default_audio_sample_t _peak; - float _peak_db; - uint32_t _short_overs; - uint32_t _long_overs; - unsigned short metering; + bool _last_monitor : 1; + bool _silent : 1; + jack_port_t *_port; + jack_nframes_t _overlen; + jack_default_audio_sample_t _peak; + float _peak_db; + uint32_t _short_overs; + uint32_t _long_overs; + unsigned short _metering; - static jack_nframes_t long_over_length; - static jack_nframes_t short_over_length; + static jack_nframes_t _long_over_length; + static jack_nframes_t _short_over_length; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index baf93a8f77..3773a3b893 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -24,7 +24,6 @@ #include #include -#include #include class XMLNode; @@ -36,22 +35,22 @@ class Source; enum RegionEditState { EditChangesNothing = 0, - EditChangesName = 1, - EditChangesID = 2 + EditChangesName = 1, + EditChangesID = 2 }; -struct RegionState : public StateManager::State { - - RegionState (std::string why) : StateManager::State (why) {} - - jack_nframes_t _start; - jack_nframes_t _length; - jack_nframes_t _position; - uint32_t _flags; - jack_nframes_t _sync_position; - layer_t _layer; - string _name; - mutable RegionEditState _first_edit; +struct RegionState : public StateManager::State +{ + RegionState (std::string why) : StateManager::State (why) {} + + jack_nframes_t _start; + jack_nframes_t _length; + jack_nframes_t _position; + uint32_t _flags; + jack_nframes_t _sync_position; + layer_t _layer; + string _name; + mutable RegionEditState _first_edit; }; class Region : public Stateful, public StateManager @@ -95,7 +94,7 @@ class Region : public Stateful, public StateManager Region (const Region&, jack_nframes_t start, jack_nframes_t length, const string& name, layer_t = 0, Flag flags = DefaultFlags); Region (const Region&); Region (const XMLNode&); - ~Region(); + virtual ~Region(); const PBD::ID& id() const { return _id; } @@ -105,9 +104,10 @@ class Region : public Stateful, public StateManager void set_name (string str); jack_nframes_t position () const { return _position; } - jack_nframes_t start () const { return _start; } - jack_nframes_t length() const { return _length; } - layer_t layer () const { return _layer; } + jack_nframes_t start () const { return _start; } + jack_nframes_t length() const { return _length; } + layer_t layer () const { return _layer; } + jack_nframes_t sync_offset(int& dir) const; jack_nframes_t sync_position() const; @@ -118,14 +118,13 @@ class Region : public Stateful, public StateManager jack_nframes_t first_frame() const { return _position; } jack_nframes_t last_frame() const { return _position + _length - 1; } - bool hidden() const { return _flags & Hidden; } - bool muted() const { return _flags & Muted; } - bool opaque () const { return _flags & Opaque; } - bool envelope_active () const { return _flags & EnvelopeActive; } - bool locked() const { return _flags & Locked; } - bool automatic() const { return _flags & Automatic; } + bool hidden() const { return _flags & Hidden; } + bool muted() const { return _flags & Muted; } + bool opaque () const { return _flags & Opaque; } + bool locked() const { return _flags & Locked; } + bool automatic() const { return _flags & Automatic; } bool whole_file() const { return _flags & WholeFile ; } - Flag flags() const { return _flags; } + Flag flags() const { return _flags; } virtual bool should_save_state () const { return !(_flags & DoNotSaveState); }; @@ -139,12 +138,14 @@ class Region : public Stateful, public StateManager OverlapType coverage (jack_nframes_t start, jack_nframes_t end) const { return ARDOUR::coverage (_position, _position + _length - 1, start, end); } - - virtual jack_nframes_t read_at (Sample *buf, Sample *mixdown_buffer, - float *gain_buffer, char * workbuf, jack_nframes_t position, jack_nframes_t cnt, - uint32_t chan_n = 0, - jack_nframes_t read_frames = 0, - jack_nframes_t skip_frames = 0) const = 0; + + bool equivalent (const Region&) const; + bool size_equivalent (const Region&) const; + 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; /* EDITING OPERATIONS */ @@ -173,7 +174,6 @@ class Region : public Stateful, public StateManager void set_hidden (bool yn); void set_muted (bool yn); void set_opaque (bool yn); - void set_envelope_active (bool yn); void set_locked (bool yn); virtual uint32_t read_data_count() const { return _read_data_count; } @@ -189,9 +189,9 @@ class Region : public Stateful, public StateManager /* serialization */ + XMLNode& get_state (); virtual XMLNode& state (bool); - XMLNode& get_state (); - int set_state (const XMLNode&); + virtual int set_state (const XMLNode&); sigc::signal GoingAway; @@ -211,23 +211,6 @@ class Region : public Stateful, public StateManager void set_last_layer_op (uint64_t when); protected: - - jack_nframes_t _start; - jack_nframes_t _length; - jack_nframes_t _position; - Flag _flags; - jack_nframes_t _sync_position; - layer_t _layer; - string _name; - mutable RegionEditState _first_edit; - int _frozen; - Glib::Mutex lock; - PBD::ID _id; - ARDOUR::Playlist* _playlist; - mutable uint32_t _read_data_count; // modified in read() - Change pending_changed; - uint64_t _last_layer_op; // timestamp - XMLNode& get_short_state (); /* used only by Session */ /* state management */ @@ -251,6 +234,23 @@ class Region : public Stateful, public StateManager virtual bool verify_length (jack_nframes_t) = 0; virtual void recompute_at_start () = 0; virtual void recompute_at_end () = 0; + + + jack_nframes_t _start; + jack_nframes_t _length; + jack_nframes_t _position; + Flag _flags; + jack_nframes_t _sync_position; + layer_t _layer; + string _name; + mutable RegionEditState _first_edit; + int _frozen; + Glib::Mutex lock; + PBD::ID _id; + ARDOUR::Playlist* _playlist; + mutable uint32_t _read_data_count; // modified in read() + Change pending_changed; + uint64_t _last_layer_op; // timestamp }; } /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index b8a11301ca..ea4a2374d4 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -40,6 +40,7 @@ #include #include #include +#include namespace ARDOUR { @@ -68,7 +69,9 @@ class Route : public IO }; - Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, Flag flags = Flag(0)); + Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max, + Flag flags = Flag(0), DataType default_type = AUDIO); + Route (Session&, const XMLNode&); virtual ~Route(); diff --git a/libs/ardour/ardour/route_group.h b/libs/ardour/ardour/route_group.h index 11253eda5b..e9fad1aa2b 100644 --- a/libs/ardour/ardour/route_group.h +++ b/libs/ardour/ardour/route_group.h @@ -35,6 +35,7 @@ using std::list; namespace ARDOUR { class Route; +class Track; class AudioTrack; class Session; @@ -90,7 +91,7 @@ class RouteGroup : public Stateful, public sigc::trackable { /* to use these, #include */ - template void apply (void (AudioTrack::*func)(T, void *), T val, void *src); + template void apply (void (Track::*func)(T, void *), T val, void *src); /* fills at_set with all members of the group that are AudioTracks */ diff --git a/libs/ardour/ardour/route_group_specialized.h b/libs/ardour/ardour/route_group_specialized.h index 0424002dcd..250d3744df 100644 --- a/libs/ardour/ardour/route_group_specialized.h +++ b/libs/ardour/ardour/route_group_specialized.h @@ -7,11 +7,11 @@ namespace ARDOUR { template void -RouteGroup::apply (void (AudioTrack::*func)(T, void *), T val, void *src) +RouteGroup::apply (void (Track::*func)(T, void *), T val, void *src) { for (list::iterator i = routes.begin(); i != routes.end(); i++) { - AudioTrack *at; - if ((at = dynamic_cast(*i)) != 0) { + Track *at; + if ((at = dynamic_cast(*i)) != 0) { (at->*func)(val, this); } } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index dbcd830a04..8d10d9f598 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -66,6 +66,7 @@ namespace ARDOUR { class Port; class AudioEngine; class Slave; +class Diskstream; class AudioDiskstream; class Route; class AuxInput; @@ -157,17 +158,17 @@ class Session : public sigc::trackable, public Stateful Clear }; - Type type; - Action action; - jack_nframes_t action_frame; - jack_nframes_t target_frame; - float speed; + Type type; + Action action; + jack_nframes_t action_frame; + jack_nframes_t target_frame; + float speed; union { - void* ptr; - bool yes_or_no; - Session::SlaveSource slave; - Route* route; + void* ptr; + bool yes_or_no; + Session::SlaveSource slave; + Route* route; }; list audio_range; @@ -269,30 +270,18 @@ class Session : public sigc::trackable, public Stateful vector& get_silent_buffers (uint32_t howmany); vector& get_send_buffers () { return _send_buffers; } - AudioDiskstream *diskstream_by_id (const PBD::ID& id); - AudioDiskstream *diskstream_by_name (string name); + Diskstream* diskstream_by_id (const PBD::ID& id); + Diskstream* diskstream_by_name (string name); bool have_captured() const { return _have_captured; } void refill_all_diskstream_buffers (); uint32_t diskstream_buffer_size() const { return dstream_buffer_size; } - /* XXX fix required here when we get new diskstream types *, but - not sure of the direction to take this in until then. - */ - - uint32_t get_next_diskstream_id() const { return n_audio_diskstreams(); } - uint32_t n_audio_diskstreams() const; + uint32_t get_next_diskstream_id() const { return n_diskstreams(); } + uint32_t n_diskstreams() const; - typedef list AudioDiskstreamList; - - Session::AudioDiskstreamList audio_disk_streams() const { - Glib::RWLock::ReaderLock lm (diskstream_lock); - return audio_diskstreams; /* XXX yes, force a copy */ - } - - void foreach_audio_diskstream (void (AudioDiskstream::*func)(void)); - template void foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&)); + typedef list DiskstreamList; typedef std::list > RouteList; @@ -356,7 +345,7 @@ class Session : public sigc::trackable, public Stateful sigc::signal HaltOnXrun; sigc::signal > RouteAdded; - sigc::signal AudioDiskstreamAdded; + sigc::signal DiskstreamAdded; // FIXME: make a shared_ptr void request_roll (); void request_bounded_roll (jack_nframes_t start, jack_nframes_t end); @@ -368,15 +357,14 @@ class Session : public sigc::trackable, public Stateful void goto_start () { request_locate (start_location->start(), false); } void use_rf_shuttle_speed (); void request_transport_speed (float speed); - void request_overwrite_buffer (AudioDiskstream*); - void request_diskstream_speed (AudioDiskstream&, float speed); + void request_overwrite_buffer (Diskstream*); + void request_diskstream_speed (Diskstream&, float speed); void request_input_change_handling (); bool locate_pending() const { return static_cast(post_transport_work&PostTransportLocate); } bool transport_locked () const; int wipe (); - int wipe_diskstream (AudioDiskstream *); int remove_region_from_region_list (Region&); @@ -553,9 +541,6 @@ class Session : public sigc::trackable, public Stateful void resort_routes (); void resort_routes_using (boost::shared_ptr); - void resort_routes_proxy (void* src) { - resort_routes (); - } AudioEngine &engine() { return _engine; }; @@ -636,7 +621,7 @@ class Session : public sigc::trackable, public Stateful string path_from_region_name (string name, string identifier); AudioRegion* find_whole_file_parent (AudioRegion&); - void find_equivalent_playlist_regions (AudioRegion&, std::vector& result); + void find_equivalent_playlist_regions (Region&, std::vector& result); AudioRegion *XMLRegionFactory (const XMLNode&, bool full); @@ -713,8 +698,6 @@ class Session : public sigc::trackable, public Stateful sigc::signal PlaylistAdded; sigc::signal PlaylistRemoved; - Playlist *get_playlist (string name); - uint32_t n_playlists() const; template void foreach_playlist (T *obj, void (T::*func)(Playlist *)); @@ -739,7 +722,7 @@ class Session : public sigc::trackable, public Stateful boost::shared_ptr the_auditioner() { return auditioner; } void audition_playlist (); - void audition_region (AudioRegion&); + void audition_region (Region&); void cancel_audition (); bool is_auditioning () const; @@ -980,7 +963,7 @@ class Session : public sigc::trackable, public Stateful void set_frame_rate (jack_nframes_t nframes); protected: - friend class AudioDiskstream; + friend class Diskstream; void stop_butler (); void wait_till_butler_finished(); @@ -1442,12 +1425,12 @@ class Session : public sigc::trackable, public Stateful bool waiting_to_start; void set_auto_loop (bool yn); - void overwrite_some_buffers (AudioDiskstream*); + void overwrite_some_buffers (Diskstream*); void flush_all_redirects (); void locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void start_locate (jack_nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void force_locate (jack_nframes_t frame, bool with_roll = false); - void set_diskstream_speed (AudioDiskstream*, float speed); + void set_diskstream_speed (Diskstream*, float speed); void set_transport_speed (float speed, bool abort = false); void stop_transport (bool abort = false); void start_transport (); @@ -1478,10 +1461,10 @@ class Session : public sigc::trackable, public Stateful /* disk-streams */ - AudioDiskstreamList audio_diskstreams; + DiskstreamList diskstreams; mutable Glib::RWLock diskstream_lock; uint32_t dstream_buffer_size; - void add_diskstream (AudioDiskstream*); + void add_diskstream (Diskstream*); int load_diskstreams (const XMLNode&); /* routes stuff */ @@ -1549,7 +1532,7 @@ class Session : public sigc::trackable, public Stateful Playlist *XMLPlaylistFactory (const XMLNode&); void playlist_length_changed (Playlist *); - void diskstream_playlist_changed (AudioDiskstream *); + void diskstream_playlist_changed (Diskstream *); /* NAMED SELECTIONS */ diff --git a/libs/ardour/ardour/session_diskstream.h b/libs/ardour/ardour/session_diskstream.h deleted file mode 100644 index 33fc5419ba..0000000000 --- a/libs/ardour/ardour/session_diskstream.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Copyright (C) 2002 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - 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$ -*/ - -#ifndef __ardour_session_diskstream_h__ -#define __ardour_session_diskstream_h__ - -#include -#include - -namespace ARDOUR { - -template void -Session::foreach_audio_diskstream (T *obj, void (T::*func)(AudioDiskstream&)) -{ - Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); i++) { - if (!(*i)->hidden()) { - (obj->*func) (**i); - } - } -} - -} /* namespace */ - -#endif /* __ardour_session_diskstream_h__ */ diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h new file mode 100644 index 0000000000..707ead1573 --- /dev/null +++ b/libs/ardour/ardour/track.h @@ -0,0 +1,158 @@ +/* + Copyright (C) 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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. +*/ + +#ifndef __ardour_track_h__ +#define __ardour_track_h__ + +#include + +namespace ARDOUR { + +class Session; +class Diskstream; +class Playlist; +class RouteGroup; + +class Track : public Route +{ + public: + Track (Session&, string name, Route::Flag f = Route::Flag (0), TrackMode m = Normal, DataType default_type = AUDIO); + + virtual ~Track (); + + int set_name (string str, void *src); + + virtual int roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input) = 0; + + virtual int no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, bool state_changing, bool can_record, bool rec_monitors_input) = 0; + + virtual int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t offset, bool can_record, bool rec_monitors_input) = 0; + + void toggle_monitor_input (); + + bool can_record() const { return true; } + + Diskstream& diskstream() const { return *_diskstream; } + + virtual int use_diskstream (string name) = 0; + virtual int use_diskstream (const PBD::ID& id) = 0; + + TrackMode mode() const { return _mode; } + void set_mode (TrackMode m); + + jack_nframes_t update_total_latency(); + void set_latency_delay (jack_nframes_t); + + enum FreezeState { + NoFreeze, + Frozen, + UnFrozen + }; + + FreezeState freeze_state() const; + + virtual void freeze (InterThreadInfo&) = 0; + virtual void unfreeze () = 0; + + virtual void bounce (InterThreadInfo&) = 0; + virtual void bounce_range (jack_nframes_t start, jack_nframes_t end, InterThreadInfo&) = 0; + + XMLNode& get_state(); + XMLNode& get_template(); + virtual int set_state(const XMLNode& node) = 0; + + PBD::Controllable& rec_enable_control() { return _rec_enable_control; } + + bool record_enabled() const; + void set_record_enable (bool yn, void *src); + + void set_meter_point (MeterPoint, void* src); + + sigc::signal ModeChanged; + sigc::signal DiskstreamChanged; + sigc::signal FreezeChange; + + protected: + Track (Session& sess, const XMLNode& node, DataType default_type = AUDIO); + + virtual XMLNode& state (bool full) = 0; + + virtual void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) = 0; + + virtual uint32_t n_process_buffers () = 0; + + Diskstream *_diskstream; + MeterPoint _saved_meter_point; + TrackMode _mode; + + //private: (FIXME) + struct FreezeRecordInsertInfo { + FreezeRecordInsertInfo(XMLNode& st, boost::shared_ptr ins) + : state (st), insert (ins) {} + + XMLNode state; + boost::shared_ptr insert; + PBD::ID id; + UndoAction memento; + }; + + struct FreezeRecord { + FreezeRecord() + : playlist(0) + , have_mementos(false) + {} + + ~FreezeRecord(); + + Playlist* playlist; + vector insert_info; + bool have_mementos; + FreezeState state; + }; + + struct RecEnableControllable : public PBD::Controllable { + RecEnableControllable (Track&); + + void set_value (float); + float get_value (void) const; + + Track& track; + }; + + //virtual void diskstream_record_enable_changed (void *src) = 0; + //virtual void diskstream_input_channel_changed (void *src) = 0; + + //virtual void input_change_handler (void *src) = 0; + + virtual void set_state_part_two () = 0; + + FreezeRecord _freeze_record; + XMLNode* pending_state; + sigc::connection recenable_connection; + sigc::connection ic_connection; + RecEnableControllable _rec_enable_control; + bool _destructive; +}; + +}; /* namespace ARDOUR*/ + +#endif /* __ardour_track_h__ */ diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index fa1d121d02..e073b413bb 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -243,6 +243,12 @@ namespace ARDOUR { PeakDatum min; PeakDatum max; }; + + enum DataType { + NIL = 0, + AUDIO, + MIDI + }; } std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index e7cb48452b..7f0cb55821 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 @@ -55,32 +54,30 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -jack_nframes_t AudioDiskstream::disk_io_chunk_frames; - -sigc::signal AudioDiskstream::AudioDiskstreamCreated; -sigc::signal*> AudioDiskstream::DeleteSources; -sigc::signal AudioDiskstream::DiskOverrun; -sigc::signal AudioDiskstream::DiskUnderrun; +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, Flag flag) - : _name (name), - _session (sess) +AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag) + : Diskstream(sess, name, flag) + , deprecated_io_node(NULL) { /* prevent any write sources from being created */ in_set_state = true; - init (flag); + init(flag); use_new_playlist (); in_set_state = false; - AudioDiskstreamCreated (this); /* EMIT SIGNAL */ + DiskstreamCreated (this); /* EMIT SIGNAL */ } AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) - : _session (sess) - + : Diskstream(sess, node) + , deprecated_io_node(NULL) { in_set_state = true; init (Recordable); @@ -96,7 +93,7 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) use_destructive_playlist (); } - AudioDiskstreamCreated (this); /* EMIT SIGNAL */ + DiskstreamCreated (this); /* EMIT SIGNAL */ } void @@ -129,43 +126,9 @@ AudioDiskstream::init_channel (ChannelInfo &chan) void -AudioDiskstream::init (Flag f) +AudioDiskstream::init (Diskstream::Flag f) { - _refcnt = 0; - _flags = f; - _io = 0; - _alignment_style = ExistingMaterial; - _persistent_alignment_style = ExistingMaterial; - first_input_change = true; - _playlist = 0; - i_am_the_modifier = 0; - g_atomic_int_set (&_record_enabled, 0); - was_recording = false; - capture_start_frame = 0; - capture_captured = 0; - _visible_speed = 1.0f; - _actual_speed = 1.0f; - _buffer_reallocation_required = false; - _seek_required = false; - first_recordable_frame = max_frames; - last_recordable_frame = max_frames; - _roll_delay = 0; - _capture_offset = 0; - _processed = false; - _slaved = false; - adjust_capture_position = 0; - last_possibly_recording = 0; - loop_location = 0; - wrap_buffer_size = 0; - speed_buffer_size = 0; - last_phase = 0; - phi = (uint64_t) (0x1000000); - file_frame = 0; - playback_sample = 0; - playback_distance = 0; - _read_data_count = 0; - _write_data_count = 0; - deprecated_io_node = 0; + Diskstream::init(f); /* there are no channels at this point, so these two calls just get speed_buffer_size and wrap_buffer @@ -175,13 +138,8 @@ AudioDiskstream::init (Flag f) 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 = 1; + assert(_n_channels == 1); } void @@ -215,26 +173,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 @@ -332,9 +297,9 @@ AudioDiskstream::find_and_use_playlist (const string& name) Playlist* pl; AudioPlaylist* playlist; - if ((pl = _session.get_playlist (name)) == 0) { - error << string_compose(_("AudioDiskstream: Session doesn't know about a Playlist called \"%1\""), name) << endmsg; - return -1; + if ((pl = _session.playlist_by_name (name)) == 0) { + playlist = new AudioPlaylist(_session, name); + pl = playlist; } if ((playlist = dynamic_cast (pl)) == 0) { @@ -346,57 +311,15 @@ AudioDiskstream::find_and_use_playlist (const string& name) } int -AudioDiskstream::use_playlist (AudioPlaylist* playlist) +AudioDiskstream::use_playlist (Playlist* playlist) { - { - Glib::Mutex::Lock lm (state_lock); + assert(dynamic_cast(playlist)); - 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, &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; } -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; -} - int AudioDiskstream::use_new_playlist () { @@ -424,6 +347,8 @@ AudioDiskstream::use_new_playlist () int AudioDiskstream::use_copy_playlist () { + assert(audio_playlist()); + if (destructive()) { return 0; } @@ -438,7 +363,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 { @@ -488,110 +413,13 @@ AudioDiskstream::use_destructive_playlist () for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) { (*chan).write_source = dynamic_cast(®ion->source (n)); + assert((*chan).write_source); (*chan).write_source->set_allow_remove_if_empty (false); } /* the source list will never be reset for a destructive track */ } -void -AudioDiskstream::set_io (IO& io) -{ - _io = &io; - set_align_style_from_io (); -} - -int -AudioDiskstream::set_name (string str, void *src) -{ - if (str != _name) { - _playlist->set_name (str); - _name = str; - - if (!in_set_state && recordable()) { - /* rename existing capture files so that they have the correct name */ - return rename_write_sources (); - } else { - return -1; - } - } - - return 0; -} - -void -AudioDiskstream::set_speed (double sp) -{ - _session.request_diskstream_speed (*this, sp); - - /* to force a rebuffering at the right place */ - playlist_modified(); -} - -bool -AudioDiskstream::realtime_set_speed (double sp, bool global) -{ - bool changed = false; - double new_speed = sp * _session.transport_speed(); - - if (_visible_speed != sp) { - _visible_speed = sp; - changed = true; - } - - if (new_speed != _actual_speed) { - - jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() * - fabs (new_speed)) + 1; - - if (required_wrap_size > wrap_buffer_size) { - _buffer_reallocation_required = true; - } - - _actual_speed = new_speed; - phi = (uint64_t) (0x1000000 * fabs(_actual_speed)); - } - - if (changed) { - if (!global) { - _seek_required = true; - } - speed_changed (); /* EMIT SIGNAL */ - } - - return _buffer_reallocation_required || _seek_required; -} - -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::prepare () -{ - _processed = false; - playback_distance = 0; -} - void AudioDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record) { @@ -755,7 +583,7 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes returns a non-zero value, in which case, ::commit should not be called. */ - // If we can't take the state lock return. + // If we can't take the state lock return. if (!state_lock.trylock()) { return 1; } @@ -1011,13 +839,6 @@ AudioDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes return ret; } -void -AudioDiskstream::recover () -{ - state_lock.unlock(); - _processed = false; -} - bool AudioDiskstream::commit (jack_nframes_t nframes) { @@ -1156,16 +977,16 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill) /* can't rec-enable in destructive mode if transport is before start */ if (destructive() && record_enabled() && frame < _session.current_start_frame()) { - disengage_record_enable (this); + disengage_record_enable (); } playback_sample = frame; file_frame = frame; if (complete_refill) { - while ((ret = do_refill (0, 0, 0)) > 0); + while ((ret = do_refill_with_alloc ()) > 0) ; } else { - ret = do_refill (0, 0, 0); + ret = do_refill_with_alloc (); } return ret; @@ -1257,7 +1078,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; @@ -1291,14 +1112,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; @@ -1306,6 +1140,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) { @@ -1412,33 +1250,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; @@ -1507,37 +1318,30 @@ 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; } +/** Flush pending data to disk. + * + * Important note: this function will write *AT MOST* disk_io_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 + * written at all unless @a force_flush is true. + */ 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; RingBufferNPT::rw_vector transvec; jack_nframes_t total; - - /* important note: this function will write *AT MOST* - disk_io_chunk_frames of data to disk. it will never - write more than that. if its 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 written at all unless `force_flush' is true. - */ _write_data_count = 0; @@ -1552,7 +1356,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush) goto out; } - /* if there are 2+ chunks of disk i/o possible for this track, let the caller know so that it can arrange for us to be called again, ASAP. @@ -1656,21 +1459,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush) return ret; } -void -AudioDiskstream::playlist_changed (Change ignored) -{ - playlist_modified (); -} - -void -AudioDiskstream::playlist_modified () -{ - if (!i_am_the_modifier && !overwrite_queued) { - _session.request_overwrite_buffer (this); - overwrite_queued = true; - } -} - void AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture) { @@ -1684,7 +1472,6 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca ChannelList::iterator chan; vector::iterator ci; uint32_t n = 0; - list* deletion_list; bool mark_write_completed = false; finish_capture (true); @@ -1694,7 +1481,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; @@ -1717,7 +1504,7 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca ChannelList::iterator chan; - deletion_list = new list; + list* deletion_list = new list; for ( chan = channels.begin(); chan != channels.end(); ++chan) { @@ -1904,7 +1691,7 @@ AudioDiskstream::finish_capture (bool rec_monitors_input) } void -AudioDiskstream::set_record_enabled (bool yn, void* src) +AudioDiskstream::set_record_enabled (bool yn) { if (!recordable() || !_session.record_enabling_legal()) { return; @@ -1931,17 +1718,17 @@ AudioDiskstream::set_record_enabled (bool yn, void* src) if (record_enabled() != yn) { if (yn) { - engage_record_enable (src); + engage_record_enable (); } else { - disengage_record_enable (src); + disengage_record_enable (); } } } void -AudioDiskstream::engage_record_enable (void* src) +AudioDiskstream::engage_record_enable () { - bool rolling = _session.transport_speed() != 0.0f; + bool rolling = _session.transport_speed() != 0.0f; g_atomic_int_set (&_record_enabled, 1); capturing_sources.clear (); @@ -1958,11 +1745,11 @@ AudioDiskstream::engage_record_enable (void* src) } } - record_enable_changed (src); /* EMIT SIGNAL */ + RecordEnableChanged (); /* EMIT SIGNAL */ } void -AudioDiskstream::disengage_record_enable (void* src) +AudioDiskstream::disengage_record_enable () { g_atomic_int_set (&_record_enabled, 0); if (Config->get_use_hardware_monitoring()) { @@ -1973,7 +1760,7 @@ AudioDiskstream::disengage_record_enable (void* src) } } capturing_sources.clear (); - record_enable_changed (src); /* EMIT SIGNAL */ + RecordEnableChanged (); /* EMIT SIGNAL */ } @@ -1981,7 +1768,7 @@ XMLNode& AudioDiskstream::get_state () { XMLNode* node = new XMLNode ("AudioDiskstream"); - char buf[64]; + char buf[64] = ""; LocaleGuard lg (X_("POSIX")); snprintf (buf, sizeof(buf), "0x%x", _flags); @@ -2080,8 +1867,7 @@ AudioDiskstream::set_state (const XMLNode& node) } // create necessary extra channels - // we are always constructed with one - // and we always need one + // we are always constructed with one and we always need one if (nchans > _n_channels) { @@ -2311,23 +2097,6 @@ AudioDiskstream::monitor_input (bool yn) } } -void -AudioDiskstream::set_capture_offset () -{ - if (_io == 0) { - /* can't capture, so forget it */ - return; - } - - _capture_offset = _io->input_latency(); -} - -void -AudioDiskstream::set_persistent_align_style (AlignStyle a) -{ - _persistent_alignment_style = a; -} - void AudioDiskstream::set_align_style_from_io () { @@ -2353,20 +2122,6 @@ AudioDiskstream::set_align_style_from_io () } } -void -AudioDiskstream::set_align_style (AlignStyle a) -{ - if (record_enabled() && _session.actively_recording()) { - return; - } - - - if (a != _alignment_style) { - _alignment_style = a; - AlignmentStyleChanged (); - } -} - int AudioDiskstream::add_channel () { @@ -2417,58 +2172,6 @@ AudioDiskstream::capture_buffer_load () const (double) channels.front().capture_buf->bufsize()); } -int -AudioDiskstream::set_loop (Location *location) -{ - if (location) { - if (location->start() >= location->end()) { - error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl; - return -1; - } - } - - loop_location = location; - - LoopSet (location); /* EMIT SIGNAL */ - return 0; -} - -jack_nframes_t -AudioDiskstream::get_capture_start_frame (uint32_t n) -{ - Glib::Mutex::Lock lm (capture_info_lock); - - if (capture_info.size() > n) { - return capture_info[n]->start; - } - else { - return capture_start_frame; - } -} - -jack_nframes_t -AudioDiskstream::get_captured_frames (uint32_t n) -{ - Glib::Mutex::Lock lm (capture_info_lock); - - if (capture_info.size() > n) { - return capture_info[n]->frames; - } - else { - return capture_captured; - } -} - -void -AudioDiskstream::punch_in () -{ -} - -void -AudioDiskstream::punch_out () -{ -} - int AudioDiskstream::use_pending_capture_data (XMLNode& node) { @@ -2564,22 +2267,3 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) return 0; } - -void -AudioDiskstream::set_roll_delay (jack_nframes_t nframes) -{ - _roll_delay = nframes; -} - -void -AudioDiskstream::set_destructive (bool yn) -{ - if (yn != destructive()) { - reset_write_sources (true, true); - if (yn) { - _flags |= Destructive; - } else { - _flags &= ~Destructive; - } - } -} diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index 85c11647f4..93d380679d 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -243,16 +243,18 @@ AudioPlaylist::read (Sample *buf, Sample *mixdown_buffer, float *gain_buffer, ch for (vector::iterator l = relevant_layers.begin(); l != relevant_layers.end(); ++l) { + // FIXME: Should be vector vector& r (relevant_regions[*l]); vector& x (relevant_xfades[*l]); for (vector::iterator i = r.begin(); i != r.end(); ++i) { - (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames); - _read_data_count += (*i)->read_data_count(); + AudioRegion* const ar = dynamic_cast(*i); + assert(ar); + ar->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n, read_frames, skip_frames); + _read_data_count += ar->read_data_count(); } for (vector::iterator i = x.begin(); i != x.end(); ++i) { - (*i)->read_at (buf, mixdown_buffer, gain_buffer, workbuf, start, cnt, chan_n); /* don't JACK up _read_data_count, since its the same data as we just @@ -880,38 +882,6 @@ AudioPlaylist::crossfade_changed (Change ignored) notify_modified (); } -void -AudioPlaylist::get_equivalent_regions (const AudioRegion& other, vector& results) -{ - for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { - - AudioRegion* ar = dynamic_cast (*i); - - if (ar) { - if (Config->get_use_overlap_equivalency()) { - if (ar->overlap_equivalent (other)) { - results.push_back (ar); - } else if (ar->equivalent (other)) { - results.push_back (ar); - } - } - } - } -} - -void -AudioPlaylist::get_region_list_equivalent_regions (const AudioRegion& other, vector& results) -{ - for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { - - AudioRegion* ar = dynamic_cast (*i); - - if (ar && ar->region_list_equivalent (other)) { - results.push_back (ar); - } - } -} - bool AudioPlaylist::region_changed (Change what_changed, Region* region) { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index f425f0172e..78af23e3df 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -41,9 +41,7 @@ using namespace ARDOUR; using namespace PBD; AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode mode) - : Route (sess, name, 1, -1, -1, -1, flag), - diskstream (0), - _rec_enable_control (*this) + : Track (sess, name, flag, mode) { AudioDiskstream::Flag dflags = AudioDiskstream::Flag (0); @@ -59,45 +57,34 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags); - _declickable = true; - _freeze_record.state = NoFreeze; - _saved_meter_point = _meter_point; - _mode = mode; - set_diskstream (*ds, this); } AudioTrack::AudioTrack (Session& sess, const XMLNode& node) - : Route (sess, "to be renamed", 0, 0, -1, -1), - diskstream (0), - _rec_enable_control (*this) + : Track (sess, node) { - _freeze_record.state = NoFreeze; set_state (node); - _declickable = true; - _saved_meter_point = _meter_point; } AudioTrack::~AudioTrack () { - if (diskstream) { - diskstream->unref(); - } } int AudioTrack::deprecated_use_diskstream_connections () { - if (diskstream->deprecated_io_node == 0) { + AudioDiskstream& diskstream = audio_diskstream(); + + if (diskstream.deprecated_io_node == 0) { return 0; } const XMLProperty* prop; - XMLNode& node (*diskstream->deprecated_io_node); + XMLNode& node (*diskstream.deprecated_io_node); /* don't do this more than once. */ - diskstream->deprecated_io_node = 0; + diskstream.deprecated_io_node = 0; set_input_minimum (-1); set_input_maximum (-1); @@ -140,15 +127,15 @@ AudioTrack::deprecated_use_diskstream_connections () int AudioTrack::set_diskstream (AudioDiskstream& ds, void *src) { - if (diskstream) { - diskstream->unref(); + if (_diskstream) { + _diskstream->unref(); } - diskstream = &ds.ref(); - diskstream->set_io (*this); - diskstream->set_destructive (_mode == Destructive); + _diskstream = &ds.ref(); + _diskstream->set_io (*this); + _diskstream->set_destructive (_mode == Destructive); - if (diskstream->deprecated_io_node) { + if (audio_diskstream().deprecated_io_node) { if (!connecting_legal) { ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections)); @@ -157,13 +144,13 @@ AudioTrack::set_diskstream (AudioDiskstream& ds, void *src) } } - diskstream->set_record_enabled (false, this); - diskstream->monitor_input (false); + _diskstream->set_record_enabled (false); + _diskstream->monitor_input (false); ic_connection.disconnect(); - ic_connection = input_changed.connect (mem_fun (*diskstream, &AudioDiskstream::handle_input_change)); + ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change)); - diskstream_changed (src); /* EMIT SIGNAL */ + DiskstreamChanged (); /* EMIT SIGNAL */ return 0; } @@ -173,8 +160,8 @@ AudioTrack::use_diskstream (string name) { AudioDiskstream *dstream; - if ((dstream = _session.diskstream_by_name (name)) == 0) { - error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), name) << endmsg; + if ((dstream = dynamic_cast(_session.diskstream_by_name (name))) == 0) { + error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg; return -1; } @@ -186,53 +173,18 @@ AudioTrack::use_diskstream (const PBD::ID& id) { AudioDiskstream *dstream; - if ((dstream = _session.diskstream_by_id (id)) == 0) { - error << string_compose(_("AudioTrack: diskstream \"%1\" not known by session"), id) << endmsg; + if ((dstream = dynamic_cast(_session.diskstream_by_id (id))) == 0) { + error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg; return -1; } return set_diskstream (*dstream, this); } -bool -AudioTrack::record_enabled () const -{ - return diskstream->record_enabled (); -} - -void -AudioTrack::set_record_enable (bool yn, void *src) -{ - if (_freeze_record.state == Frozen) { - return; - } - - if (_mix_group && src != _mix_group && _mix_group->is_active()) { - _mix_group->apply (&AudioTrack::set_record_enable, yn, _mix_group); - return; - } - - /* keep track of the meter point as it was before we rec-enabled */ - - if (!diskstream->record_enabled()) { - _saved_meter_point = _meter_point; - } - - diskstream->set_record_enabled (yn, src); - - if (diskstream->record_enabled()) { - set_meter_point (MeterInput, this); - } else { - set_meter_point (_saved_meter_point, this); - } - - _rec_enable_control.Changed (); -} - -void -AudioTrack::set_meter_point (MeterPoint p, void *src) +AudioDiskstream& +AudioTrack::audio_diskstream() const { - Route::set_meter_point (p, src); + return *dynamic_cast(_diskstream); } int @@ -306,18 +258,6 @@ AudioTrack::set_state (const XMLNode& node) return 0; } -XMLNode& -AudioTrack::get_template () -{ - return state (false); -} - -XMLNode& -AudioTrack::get_state () -{ - return state (true); -} - XMLNode& AudioTrack::state(bool full_state) { @@ -348,7 +288,7 @@ AudioTrack::state(bool full_state) /* Alignment: act as a proxy for the diskstream */ XMLNode* align_node = new XMLNode (X_("alignment")); - switch (diskstream->alignment_style()) { + switch (_diskstream->alignment_style()) { case ExistingMaterial: snprintf (buf, sizeof (buf), X_("existing")); break; @@ -379,7 +319,7 @@ AudioTrack::state(bool full_state) diskstream. */ - diskstream->id().print (buf); + _diskstream->id().print (buf); root.add_property ("diskstream-id", buf); return root; @@ -451,9 +391,9 @@ AudioTrack::set_state_part_two () if ((prop = fnode->property (X_("style"))) != 0) { if (prop->value() == "existing") { - diskstream->set_persistent_align_style (ExistingMaterial); + _diskstream->set_persistent_align_style (ExistingMaterial); } else if (prop->value() == "capture") { - diskstream->set_persistent_align_style (CaptureTime); + _diskstream->set_persistent_align_style (CaptureTime); } } } @@ -463,7 +403,7 @@ AudioTrack::set_state_part_two () uint32_t AudioTrack::n_process_buffers () { - return max ((uint32_t) diskstream->n_channels(), redirect_max_outs); + return max ((uint32_t) _diskstream->n_channels(), redirect_max_outs); } void @@ -494,7 +434,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf return 0; } - diskstream->check_record_status (start_frame, nframes, can_record); + audio_diskstream().check_record_status (start_frame, nframes, can_record); bool send_silence; @@ -513,7 +453,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf send_silence = true; } } else { - if (diskstream->record_enabled()) { + if (_diskstream->record_enabled()) { if (Config->get_use_sw_monitoring()) { send_silence = false; } else { @@ -561,7 +501,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram Sample* b; Sample* tmpb; jack_nframes_t transport_frame; - + AudioDiskstream& diskstream = audio_diskstream(); + { Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK); if (lm.locked()) { @@ -587,13 +528,13 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram playback distance to zero, thus causing diskstream::commit to do nothing. */ - return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input); + return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input); } _silent = false; apply_gain_automation = false; - if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) { + if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) { silence (nframes, offset); @@ -606,7 +547,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 && !_session.get_auto_input()) { /* not actually recording, but we want to hear the input material anyway, at least potentially (depending on monitoring options) @@ -614,7 +555,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram passthru (start_frame, end_frame, nframes, offset, 0, true); - } else if ((b = diskstream->playback_buffer(0)) != 0) { + } else if ((b = diskstream.playback_buffer(0)) != 0) { /* XXX is it true that the earlier test on n_outputs() @@ -636,8 +577,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram for (i = 0, n = 1; i < limit; ++i, ++n) { memcpy (bufs[i], b, sizeof (Sample) * nframes); - if (n < diskstream->n_channels()) { - tmpb = diskstream->playback_buffer(n); + if (n < diskstream.n_channels()) { + tmpb = diskstream.playback_buffer(n); if (tmpb!=0) { b = tmpb; } @@ -646,7 +587,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */ - if (!diskstream->record_enabled() && _session.transport_rolling()) { + if (!diskstream.record_enabled() && _session.transport_rolling()) { Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK); if (am.locked() && gain_automation_playback()) { @@ -682,37 +623,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac silence (nframes, offset); - return diskstream->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input); -} - -void -AudioTrack::toggle_monitor_input () -{ - for (vector::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { - (*i)->request_monitor_input(!(*i)->monitoring_input()); - } -} - -int -AudioTrack::set_name (string str, void *src) -{ - int ret; - - if (record_enabled() && _session.actively_recording()) { - /* this messes things up if done while recording */ - return -1; - } - - if (diskstream->set_name (str, src)) { - return -1; - } - - /* save state so that the statefile fully reflects any filename changes */ - - if ((ret = IO::set_name (str, src)) == 0) { - _session.save_state (""); - } - return ret; + return audio_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input); } int @@ -726,10 +637,15 @@ AudioTrack::export_stuff (vector& buffers, char * workbuf, uint32_t nbu gain_t this_gain = _gain; vector::iterator bi; Sample * b; + AudioDiskstream& diskstream = audio_diskstream(); Glib::RWLock::ReaderLock rlock (redirect_lock); - - if (diskstream->playlist()->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) { + + // FIXME + AudioPlaylist* const apl = dynamic_cast(diskstream.playlist()); + assert(apl); + + if (apl->read (buffers[0], mix_buffer, gain_buffer, workbuf, start, nframes) != nframes) { return -1; } @@ -738,8 +654,8 @@ AudioTrack::export_stuff (vector& buffers, char * workbuf, uint32_t nbu b = buffers[0]; ++bi; for (; bi != buffers.end(); ++bi, ++n) { - if (n < diskstream->n_channels()) { - if (diskstream->playlist()->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) { + if (n < diskstream.n_channels()) { + if (apl->read ((*bi), mix_buffer, gain_buffer, workbuf, start, nframes, n) != nframes) { return -1; } b = (*bi); @@ -811,29 +727,6 @@ AudioTrack::export_stuff (vector& buffers, char * workbuf, uint32_t nbu return 0; } -void -AudioTrack::set_latency_delay (jack_nframes_t longest_session_latency) -{ - Route::set_latency_delay (longest_session_latency); - diskstream->set_roll_delay (_roll_delay); -} - -jack_nframes_t -AudioTrack::update_total_latency () -{ - _own_latency = 0; - - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - if ((*i)->active ()) { - _own_latency += (*i)->latency (); - } - } - - set_port_latency (_own_latency); - - return _own_latency; -} - void AudioTrack::bounce (InterThreadInfo& itt) { @@ -858,8 +751,9 @@ AudioTrack::freeze (InterThreadInfo& itt) string dir; AudioRegion* region; string region_name; + AudioDiskstream& diskstream = audio_diskstream(); - if ((_freeze_record.playlist = diskstream->playlist()) == 0) { + if ((_freeze_record.playlist = dynamic_cast(diskstream.playlist())) == 0) { return; } @@ -881,7 +775,7 @@ AudioTrack::freeze (InterThreadInfo& itt) } if (n == (UINT_MAX-1)) { - error << string_compose (X_("There Are too many frozen versions of playlist \"%1\"" + error << string_compose (X_("There are too many frozen versions of playlist \"%1\"" " to create another one"), _freeze_record.playlist->name()) << endmsg; return; @@ -927,13 +821,13 @@ AudioTrack::freeze (InterThreadInfo& itt) (AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags), false); - new_playlist->set_orig_diskstream_id (diskstream->id()); + new_playlist->set_orig_diskstream_id (diskstream.id()); new_playlist->add_region (*region, 0); new_playlist->set_frozen (true); region->set_locked (true); - diskstream->use_playlist (dynamic_cast(new_playlist)); - diskstream->set_record_enabled (false, this); + diskstream.use_playlist (dynamic_cast(new_playlist)); + diskstream.set_record_enabled (false); _freeze_record.state = Frozen; FreezeChange(); /* EMIT SIGNAL */ @@ -943,7 +837,7 @@ void AudioTrack::unfreeze () { if (_freeze_record.playlist) { - diskstream->use_playlist (_freeze_record.playlist); + audio_diskstream().use_playlist (_freeze_record.playlist); if (_freeze_record.have_mementos) { @@ -971,46 +865,3 @@ AudioTrack::unfreeze () FreezeChange (); /* EMIT SIGNAL */ } -AudioTrack::FreezeRecord::~FreezeRecord () -{ - for (vector::iterator i = insert_info.begin(); i != insert_info.end(); ++i) { - delete *i; - } -} - -AudioTrack::FreezeState -AudioTrack::freeze_state() const -{ - return _freeze_record.state; -} - -AudioTrack::RecEnableControllable::RecEnableControllable (AudioTrack& s) - : track (s) -{ -} - -void -AudioTrack::RecEnableControllable::set_value (float val) -{ - bool bval = ((val >= 0.5f) ? true: false); - track.set_record_enable (bval, this); -} - -float -AudioTrack::RecEnableControllable::get_value (void) const -{ - if (track.record_enabled()) { return 1.0f; } - return 0.0f; -} - -void -AudioTrack::set_mode (TrackMode m) -{ - if (diskstream) { - if (_mode != m) { - _mode = m; - diskstream->set_destructive (m == Destructive); - ModeChanged(); - } - } -} diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 5a5e200531..5618c7ef5f 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -42,8 +43,8 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -jack_nframes_t Port::short_over_length = 2; -jack_nframes_t Port::long_over_length = 10; +jack_nframes_t Port::_short_over_length = 2; +jack_nframes_t Port::_long_over_length = 10; AudioEngine::AudioEngine (string client_name) { @@ -274,8 +275,8 @@ AudioEngine::process_callback (jack_nframes_t nframes) Port *port = (*i); bool x; - if (port->last_monitor != (x = port->monitoring_input ())) { - port->last_monitor = x; + if (port->_last_monitor != (x = port->monitoring_input ())) { + port->_last_monitor = x; /* XXX I think this is dangerous, due to a likely mutex in the signal handlers ... */ @@ -388,18 +389,19 @@ AudioEngine::remove_session () } Port * -AudioEngine::register_audio_input_port (const string& portname) +AudioEngine::register_input_port (DataType type, const string& portname) { if (!_running) { if (!_has_run) { - fatal << _("register audio input port called before engine was started") << endmsg; + fatal << _("register input port called before engine was started") << endmsg; /*NOTREACHED*/ } else { return 0; } } - jack_port_t *p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + jack_port_t *p = jack_port_register (_jack, portname.c_str(), + Buffer::type_to_jack_type(type), JackPortIsInput, 0); if (p) { @@ -419,11 +421,11 @@ AudioEngine::register_audio_input_port (const string& portname) } Port * -AudioEngine::register_audio_output_port (const string& portname) +AudioEngine::register_output_port (DataType type, const string& portname) { if (!_running) { if (!_has_run) { - fatal << _("register audio output port called before engine was started") << endmsg; + fatal << _("register output port called before engine was started") << endmsg; /*NOTREACHED*/ } else { return 0; @@ -432,7 +434,8 @@ AudioEngine::register_audio_output_port (const string& portname) jack_port_t *p; - if ((p = jack_port_register (_jack, portname.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) != 0) { + if ((p = jack_port_register (_jack, portname.c_str(), + Buffer::type_to_jack_type(type), JackPortIsOutput, 0)) != 0) { Port *newport = new Port (p); ports.insert (ports.begin(), newport); return newport; @@ -446,6 +449,7 @@ AudioEngine::register_audio_output_port (const string& portname) return 0; } + int AudioEngine::unregister_port (Port *port) { @@ -458,7 +462,7 @@ AudioEngine::unregister_port (Port *port) if (port) { - int ret = jack_port_unregister (_jack, port->port); + int ret = jack_port_unregister (_jack, port->_port); if (ret == 0) { @@ -549,7 +553,7 @@ AudioEngine::disconnect (Port *port) } } - int ret = jack_port_disconnect (_jack, port->port); + int ret = jack_port_disconnect (_jack, port->_port); if (ret == 0) { remove_connections_for (port); @@ -699,7 +703,6 @@ AudioEngine::n_physical_inputs () const } string - AudioEngine::get_nth_physical (uint32_t n, int flag) { const char ** ports; @@ -747,7 +750,7 @@ AudioEngine::get_port_total_latency (const Port& port) } } - return jack_port_get_total_latency (_jack, port.port); + return jack_port_get_total_latency (_jack, port._port); } void @@ -825,7 +828,7 @@ AudioEngine::remove_all_ports () if (_jack) { for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { - jack_port_unregister (_jack, (*i)->port); + jack_port_unregister (_jack, (*i)->_port); } } @@ -948,7 +951,7 @@ AudioEngine::reconnect_to_jack () short_name = long_name.substr (long_name.find_last_of (':') + 1); - if (((*i)->port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) { + if (((*i)->_port = jack_port_register (_jack, short_name.c_str(), (*i)->type(), (*i)->flags(), 0)) == 0) { error << string_compose (_("could not reregister %1"), (*i)->name()) << endmsg; break; } else { @@ -963,7 +966,7 @@ AudioEngine::reconnect_to_jack () if (i != ports.end()) { for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) { - jack_port_unregister (_jack, (*i)->port); + jack_port_unregister (_jack, (*i)->_port); } return -1; } diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 4a8593cd63..fff1c99598 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -48,13 +48,13 @@ using namespace ARDOUR; /* a Session will reset these to its chosen defaults by calling AudioRegion::set_default_fade() */ -Change AudioRegion::FadeInChanged = ARDOUR::new_change(); -Change AudioRegion::FadeOutChanged = ARDOUR::new_change(); -Change AudioRegion::FadeInActiveChanged = ARDOUR::new_change(); -Change AudioRegion::FadeOutActiveChanged = ARDOUR::new_change(); +Change AudioRegion::FadeInChanged = ARDOUR::new_change(); +Change AudioRegion::FadeOutChanged = ARDOUR::new_change(); +Change AudioRegion::FadeInActiveChanged = ARDOUR::new_change(); +Change AudioRegion::FadeOutActiveChanged = ARDOUR::new_change(); Change AudioRegion::EnvelopeActiveChanged = ARDOUR::new_change(); Change AudioRegion::ScaleAmplitudeChanged = ARDOUR::new_change(); -Change AudioRegion::EnvelopeChanged = ARDOUR::new_change(); +Change AudioRegion::EnvelopeChanged = ARDOUR::new_change(); AudioRegionState::AudioRegionState (string why) : RegionState (why), @@ -633,12 +633,6 @@ AudioRegion::_read_at (const SourceList& srcs, Sample *buf, Sample *mixdown_buff return to_read; } -XMLNode& -AudioRegion::get_state () -{ - return state (true); -} - XMLNode& AudioRegion::state (bool full) { @@ -1139,24 +1133,22 @@ AudioRegion::master_source_names () } bool -AudioRegion::region_list_equivalent (const AudioRegion& other) const +AudioRegion::source_equivalent (const Region& o) const { - return size_equivalent (other) && source_equivalent (other) && _name == other._name; -} + const AudioRegion* other = dynamic_cast(&o); + if (!other) + return false; -bool -AudioRegion::source_equivalent (const AudioRegion& other) const -{ SourceList::const_iterator i; SourceList::const_iterator io; - for (i = sources.begin(), io = other.sources.begin(); i != sources.end() && io != other.sources.end(); ++i, ++io) { + for (i = sources.begin(), io = other->sources.begin(); i != sources.end() && io != other->sources.end(); ++i, ++io) { if ((*i)->id() != (*io)->id()) { return false; } } - for (i = master_sources.begin(), io = other.master_sources.begin(); i != master_sources.end() && io != other.master_sources.end(); ++i, ++io) { + for (i = master_sources.begin(), io = other->master_sources.begin(); i != master_sources.end() && io != other->master_sources.end(); ++i, ++io) { if ((*i)->id() != (*io)->id()) { return false; } @@ -1165,27 +1157,6 @@ AudioRegion::source_equivalent (const AudioRegion& other) const return true; } -bool -AudioRegion::overlap_equivalent (const AudioRegion& other) const -{ - return coverage (other.first_frame(), other.last_frame()) != OverlapNone; -} - -bool -AudioRegion::equivalent (const AudioRegion& other) const -{ - return _start == other._start && - _position == other._position && - _length == other._length; -} - -bool -AudioRegion::size_equivalent (const AudioRegion& other) const -{ - return _start == other._start && - _length == other._length; -} - int AudioRegion::apply (AudioFilter& filter) { diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc index 2f0b943c0e..81f64d2671 100644 --- a/libs/ardour/auditioner.cc +++ b/libs/ardour/auditioner.cc @@ -44,12 +44,12 @@ Auditioner::Auditioner (Session& s) defer_pan_reset (); if (left.length()) { - add_output_port (left, this); + add_output_port (left, this, AUDIO); } if (right.length()) { - disk_stream().add_channel(); - add_output_port (right, this); + audio_diskstream().add_channel(); + add_output_port (right, this, AUDIO); } allow_pan_reset (); @@ -67,8 +67,12 @@ Auditioner::~Auditioner () AudioPlaylist& Auditioner::prepare_playlist () { - diskstream->playlist()->clear (false, false); - return *diskstream->playlist(); + // FIXME auditioner is still audio-only + AudioPlaylist* const apl = dynamic_cast(_diskstream->playlist()); + assert(apl); + + apl->clear (false, false); + return *apl; } void @@ -82,13 +86,13 @@ Auditioner::audition_current_playlist () } Glib::Mutex::Lock lm (lock); - diskstream->seek (0); - length = diskstream->playlist()->get_maximum_extent(); + _diskstream->seek (0); + length = _diskstream->playlist()->get_maximum_extent(); current_frame = 0; /* force a panner reset now that we have all channels */ - _panner->reset (n_outputs(), diskstream->n_channels()); + _panner->reset (n_outputs(), _diskstream->n_channels()); g_atomic_int_set (&_active, 1); } @@ -108,23 +112,23 @@ Auditioner::audition_region (AudioRegion& region) the_region = new AudioRegion (region); the_region->set_position (0, this); - diskstream->playlist()->clear (true, false); - diskstream->playlist()->add_region (*the_region, 0, 1, false); + _diskstream->playlist()->clear (true, false); + _diskstream->playlist()->add_region (*the_region, 0, 1, false); - while (diskstream->n_channels() < the_region->n_channels()) { - diskstream->add_channel (); + while (_diskstream->n_channels() < the_region->n_channels()) { + audio_diskstream().add_channel (); } - while (diskstream->n_channels() > the_region->n_channels()) { - diskstream->remove_channel (); + while (_diskstream->n_channels() > the_region->n_channels()) { + audio_diskstream().remove_channel (); } /* force a panner reset now that we have all channels */ - _panner->reset (n_outputs(), diskstream->n_channels()); + _panner->reset (n_outputs(), _diskstream->n_channels()); length = the_region->length(); - diskstream->seek (0); + _diskstream->seek (0); current_frame = 0; g_atomic_int_set (&_active, 1); } @@ -143,14 +147,14 @@ Auditioner::play_audition (jack_nframes_t nframes) this_nframes = min (nframes, length - current_frame); - diskstream->prepare (); + _diskstream->prepare (); if ((ret = roll (this_nframes, current_frame, current_frame + nframes, 0, false, false, false)) != 0) { silence (nframes, 0); return ret; } - need_butler = diskstream->commit (this_nframes); + need_butler = _diskstream->commit (this_nframes); current_frame += this_nframes; if (current_frame >= length) { diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc new file mode 100644 index 0000000000..9312de5bf1 --- /dev/null +++ b/libs/ardour/diskstream.cc @@ -0,0 +1,401 @@ +/* + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i18n.h" +#include + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + +jack_nframes_t Diskstream::disk_io_chunk_frames = 0; + +sigc::signal Diskstream::DiskstreamCreated; +sigc::signal*> Diskstream::DeleteSources; +sigc::signal Diskstream::DiskOverrun; +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); +} + +void +Diskstream::init (Flag f) +{ + _refcnt = 0; + _flags = f; + _io = 0; + _alignment_style = ExistingMaterial; + _persistent_alignment_style = ExistingMaterial; + first_input_change = true; + i_am_the_modifier = 0; + g_atomic_int_set (&_record_enabled, 0); + was_recording = false; + capture_start_frame = 0; + capture_captured = 0; + _visible_speed = 1.0f; + _actual_speed = 1.0f; + _buffer_reallocation_required = false; + _seek_required = false; + first_recordable_frame = max_frames; + last_recordable_frame = max_frames; + _roll_delay = 0; + _capture_offset = 0; + _processed = false; + _slaved = false; + adjust_capture_position = 0; + last_possibly_recording = 0; + loop_location = 0; + wrap_buffer_size = 0; + speed_buffer_size = 0; + last_phase = 0; + phi = (uint64_t) (0x1000000); + file_frame = 0; + playback_sample = 0; + playback_distance = 0; + _read_data_count = 0; + _write_data_count = 0; + + pending_overwrite = false; + overwrite_frame = 0; + overwrite_queued = false; + input_change_pending = NoChange; + + _n_channels = 0; +} + +Diskstream::~Diskstream () +{ + // Taken by derived class destrctors.. should assure locked here somehow? + //Glib::Mutex::Lock lm (state_lock); + + if (_playlist) + _playlist->unref (); +} + +void +Diskstream::set_io (IO& io) +{ + _io = &io; + set_align_style_from_io (); +} + +void +Diskstream::handle_input_change (IOChange change, void *src) +{ + Glib::Mutex::Lock lm (state_lock); + + if (!(input_change_pending & change)) { + input_change_pending = IOChange (input_change_pending|change); + _session.request_input_change_handling (); + } +} + +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) +{ + bool changed = false; + double new_speed = sp * _session.transport_speed(); + + if (_visible_speed != sp) { + _visible_speed = sp; + changed = true; + } + + if (new_speed != _actual_speed) { + + jack_nframes_t required_wrap_size = (jack_nframes_t) floor (_session.get_block_size() * + fabs (new_speed)) + 1; + + if (required_wrap_size > wrap_buffer_size) { + _buffer_reallocation_required = true; + } + + _actual_speed = new_speed; + phi = (uint64_t) (0x1000000 * fabs(_actual_speed)); + } + + if (changed) { + if (!global) { + _seek_required = true; + } + SpeedChanged (); /* EMIT SIGNAL */ + } + + return _buffer_reallocation_required || _seek_required; +} + +void +Diskstream::prepare () +{ + _processed = false; + playback_distance = 0; +} + +void +Diskstream::recover () +{ + state_lock.unlock(); + _processed = false; +} + +void +Diskstream::set_capture_offset () +{ + if (_io == 0) { + /* can't capture, so forget it */ + return; + } + + _capture_offset = _io->input_latency(); +} + +void +Diskstream::set_align_style (AlignStyle a) +{ + if (record_enabled() && _session.actively_recording()) { + return; + } + + if (a != _alignment_style) { + _alignment_style = a; + AlignmentStyleChanged (); + } +} + +int +Diskstream::set_loop (Location *location) +{ + if (location) { + if (location->start() >= location->end()) { + error << string_compose(_("Location \"%1\" not valid for track loop (start >= end)"), location->name()) << endl; + return -1; + } + } + + loop_location = location; + + LoopSet (location); /* EMIT SIGNAL */ + return 0; +} + +jack_nframes_t +Diskstream::get_capture_start_frame (uint32_t n) +{ + Glib::Mutex::Lock lm (capture_info_lock); + + if (capture_info.size() > n) { + return capture_info[n]->start; + } + else { + return capture_start_frame; + } +} + +jack_nframes_t +Diskstream::get_captured_frames (uint32_t n) +{ + Glib::Mutex::Lock lm (capture_info_lock); + + if (capture_info.size() > n) { + return capture_info[n]->frames; + } + else { + return capture_captured; + } +} + +void +Diskstream::set_roll_delay (jack_nframes_t nframes) +{ + _roll_delay = nframes; +} + +void +Diskstream::set_speed (double sp) +{ + _session.request_diskstream_speed (*this, sp); + + /* to force a rebuffering at the right place */ + 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) +{ + playlist_modified (); +} + +void +Diskstream::playlist_modified () +{ + if (!i_am_the_modifier && !overwrite_queued) { + _session.request_overwrite_buffer (this); + overwrite_queued = true; + } +} + +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) +{ + if (str != _name) { + assert(playlist()); + playlist()->set_name (str); + _name = str; + + if (!in_set_state && recordable()) { + /* rename existing capture files so that they have the correct name */ + return rename_write_sources (); + } else { + return -1; + } + } + + return 0; +} + +void +Diskstream::set_destructive (bool yn) +{ + if (yn != destructive()) { + reset_write_sources (true, true); + if (yn) { + _flags |= Destructive; + } else { + _flags &= ~Destructive; + } + } +} diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index bb2bb52e9e..a70bf8abd3 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -97,11 +97,15 @@ static bool sort_ports_by_name (Port* a, Port* b) } +/** @param default_type The type of port that will be created by ensure_io + * and friends if no type is explicitly requested (to avoid breakage). + */ IO::IO (Session& s, string name, - - int input_min, int input_max, int output_min, int output_max) + int input_min, int input_max, int output_min, int output_max, + DataType default_type) : _session (s), _name (name), + _default_type(default_type), _gain_control (*this), _gain_automation_curve (0.0, 2.0, 1.0), _input_minimum (input_min), @@ -781,11 +785,20 @@ IO::remove_output_port (Port* port, void* src) return -1; } +/** Add an output port. + * + * @param destination Name of input port to connect new port to. + * @param src Source for emitted ConfigurationChanged signal. + * @param type Data type of port. Default value (NIL) will use this IO's default type. + */ int -IO::add_output_port (string destination, void* src) +IO::add_output_port (string destination, void* src, DataType type) { Port* our_port; - char buf[64]; + char name[64]; + + if (type == NIL) + type = _default_type; { Glib::Mutex::Lock em(_session.engine().process_lock()); @@ -799,14 +812,15 @@ IO::add_output_port (string destination, void* src) /* Create a new output port */ + // FIXME: naming scheme for differently typed ports? if (_output_maximum == 1) { - snprintf (buf, sizeof (buf), _("%s/out"), _name.c_str()); + snprintf (name, sizeof (name), _("%s/out"), _name.c_str()); } else { - snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole()); + snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole()); } - if ((our_port = _session.engine().register_audio_output_port (buf)) == 0) { - error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg; + if ((our_port = _session.engine().register_output_port (type, name)) == 0) { + error << string_compose(_("IO: cannot register output port %1"), name) << endmsg; return -1; } @@ -882,11 +896,21 @@ IO::remove_input_port (Port* port, void* src) return -1; } + +/** Add an input port. + * + * @param type Data type of port. The appropriate Jack port type, and @ref Port will be created. + * @param destination Name of input port to connect new port to. + * @param src Source for emitted ConfigurationChanged signal. + */ int -IO::add_input_port (string source, void* src) +IO::add_input_port (string source, void* src, DataType type) { Port* our_port; - char buf[64]; + char name[64]; + + if (type == NIL) + type = _default_type; { Glib::Mutex::Lock em (_session.engine().process_lock()); @@ -900,14 +924,15 @@ IO::add_input_port (string source, void* src) /* Create a new input port */ + // FIXME: naming scheme for differently typed ports? if (_input_maximum == 1) { - snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); + snprintf (name, sizeof (name), _("%s/in"), _name.c_str()); } else { - snprintf (buf, sizeof (buf), _("%s/in %u"), _name.c_str(), find_input_port_hole()); + snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole()); } - if ((our_port = _session.engine().register_audio_input_port (buf)) == 0) { - error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg; + if ((our_port = _session.engine().register_input_port (type, name)) == 0) { + error << string_compose(_("IO: cannot register input port %1"), name) << endmsg; return -1; } @@ -1001,7 +1026,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src) char buf[64]; - /* Create a new input port */ + /* Create a new input port (of the default type) */ if (_input_maximum == 1) { snprintf (buf, sizeof (buf), _("%s/in"), _name.c_str()); @@ -1012,7 +1037,7 @@ IO::ensure_inputs_locked (uint32_t n, bool clear, void* src) try { - if ((input_port = _session.engine().register_audio_input_port (buf)) == 0) { + if ((input_port = _session.engine().register_input_port (_default_type, buf)) == 0) { error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg; return -1; } @@ -1101,7 +1126,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) out_changed = true; } - /* create any necessary new ports */ + /* create any necessary new ports (of the default type) */ while (_ninputs < nin) { @@ -1117,7 +1142,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) } try { - if ((port = _session.engine().register_audio_input_port (buf)) == 0) { + if ((port = _session.engine().register_input_port (_default_type, buf)) == 0) { error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg; return -1; } @@ -1150,7 +1175,7 @@ IO::ensure_io (uint32_t nin, uint32_t nout, bool clear, void* src) } try { - if ((port = _session.engine().register_audio_output_port (buf)) == 0) { + if ((port = _session.engine().register_output_port (_default_type, buf)) == 0) { error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg; return -1; } @@ -1275,7 +1300,7 @@ IO::ensure_outputs_locked (uint32_t n, bool clear, void* src) snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole()); } - if ((output_port = _session.engine().register_audio_output_port (buf)) == 0) { + if ((output_port = _session.engine().register_output_port (_default_type, buf)) == 0) { error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg; return -1; } diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index fc1dd84066..6d5e8f7847 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -598,6 +598,31 @@ Playlist::remove_region_internal (Region *region, bool delay_sort) return -1; } +void +Playlist::get_equivalent_regions (const Region& other, vector& results) +{ + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + if (Config->get_use_overlap_equivalency()) { + if ((*i)->overlap_equivalent (other)) { + results.push_back ((*i)); + } else if ((*i)->equivalent (other)) { + results.push_back ((*i)); + } + } + } +} + +void +Playlist::get_region_list_equivalent_regions (const Region& other, vector& results) +{ + for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) { + + if ((*i) && (*i)->region_list_equivalent (other)) { + results.push_back (*i); + } + } +} + void Playlist::partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level) { diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index c5c03d0a05..7ec0d5a05a 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -24,15 +24,15 @@ using namespace ARDOUR; using namespace std; Port::Port (jack_port_t *p) - : port (p) + : _port (p) { - if (port == 0) { + if (_port == 0) { throw failed_constructor(); } - _flags = JackPortFlags (jack_port_flags (port)); - _type = jack_port_type (port); - _name = jack_port_name (port); + _flags = JackPortFlags (jack_port_flags (_port)); + _type = jack_port_type (_port); + _name = jack_port_name (_port); reset (); } @@ -42,9 +42,9 @@ Port::reset () { reset_buffer (); - last_monitor = false; - silent = false; - metering = 0; + _last_monitor = false; + _silent = false; + _metering = 0; reset_meters (); } @@ -54,7 +54,7 @@ Port::set_name (string str) { int ret; - if ((ret = jack_port_set_name (port, str.c_str())) == 0) { + if ((ret = jack_port_set_name (_port, str.c_str())) == 0) { _name = str; } diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index f195e42148..037c844324 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -39,13 +39,13 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -Change Region::FadeChanged = ARDOUR::new_change (); +Change Region::FadeChanged = ARDOUR::new_change (); Change Region::SyncOffsetChanged = ARDOUR::new_change (); -Change Region::MuteChanged = ARDOUR::new_change (); -Change Region::OpacityChanged = ARDOUR::new_change (); -Change Region::LockChanged = ARDOUR::new_change (); -Change Region::LayerChanged = ARDOUR::new_change (); -Change Region::HiddenChanged = ARDOUR::new_change (); +Change Region::MuteChanged = ARDOUR::new_change (); +Change Region::OpacityChanged = ARDOUR::new_change (); +Change Region::LockChanged = ARDOUR::new_change (); +Change Region::LayerChanged = ARDOUR::new_change (); +Change Region::HiddenChanged = ARDOUR::new_change (); sigc::signal Region::CheckNewRegion; @@ -990,3 +990,30 @@ Region::set_last_layer_op (uint64_t when) { _last_layer_op = when; } + +bool +Region::overlap_equivalent (const Region& other) const +{ + return coverage (other.first_frame(), other.last_frame()) != OverlapNone; +} + +bool +Region::equivalent (const Region& other) const +{ + return _start == other._start && + _position == other._position && + _length == other._length; +} + +bool +Region::size_equivalent (const Region& other) const +{ + return _start == other._start && + _length == other._length; +} + +bool +Region::region_list_equivalent (const Region& other) const +{ + return size_equivalent (other) && source_equivalent (other) && _name == other._name; +} diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index f3162f9131..effb8432d1 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -20,11 +20,13 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -50,8 +52,8 @@ using namespace PBD; uint32_t Route::order_key_cnt = 0; -Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg) - : IO (sess, name, input_min, input_max, output_min, output_max), +Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type) + : IO (sess, name, input_min, input_max, output_min, output_max, default_type), _flags (flg), _solo_control (*this, ToggleControllable::SoloControl), _mute_control (*this, ToggleControllable::MuteControl) @@ -1330,6 +1332,9 @@ Route::state(bool full_state) snprintf (buf, sizeof (buf), "0x%x", _flags); node->add_property("flags", buf); } + + node->add_property("default-type", Buffer::type_to_string(_default_type)); + node->add_property("active", _active?"yes":"no"); node->add_property("muted", _muted?"yes":"no"); node->add_property("soloed", _soloed?"yes":"no"); @@ -1503,6 +1508,11 @@ Route::set_state (const XMLNode& node) } else { _flags = Flag (0); } + + if ((prop = node.property ("default-type")) != 0) { + _default_type = Buffer::type_from_string(prop->value()); + assert(_default_type != NIL); + } if ((prop = node.property ("phase-invert")) != 0) { set_phase_invert(prop->value()=="yes"?true:false, this); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index ae879ed083..45afdf479f 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -397,6 +397,8 @@ Session::~Session () delete [] (i->second); } + AudioDiskstream::free_working_buffers(); + #undef TRACK_DESTRUCTION #ifdef TRACK_DESTRUCTION cerr << "delete named selections\n"; @@ -440,10 +442,10 @@ Session::~Session () } #ifdef TRACK_DESTRUCTION - cerr << "delete audio_diskstreams\n"; + cerr << "delete diskstreams\n"; #endif /* TRACK_DESTRUCTION */ - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ) { - AudioDiskstreamList::iterator tmp; + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) { + DiskstreamList::iterator tmp; tmp = i; ++tmp; @@ -860,7 +862,7 @@ Session::playlist_length_changed (Playlist* pl) } void -Session::diskstream_playlist_changed (AudioDiskstream* dstream) +Session::diskstream_playlist_changed (Diskstream* dstream) { Playlist *playlist; @@ -940,7 +942,7 @@ Session::set_auto_input (bool yn) The rarity and short potential lock duration makes this "OK" */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (!auto_input); @@ -958,7 +960,7 @@ Session::reset_input_monitor_state () { if (transport_rolling()) { Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input); @@ -966,7 +968,7 @@ Session::reset_input_monitor_state () } } else { Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (Config->get_use_hardware_monitoring()); @@ -1047,7 +1049,7 @@ Session::auto_loop_changed (Location* location) } else if (seamless_loop && !loop_changing) { - // schedule a locate-roll to refill the audio_diskstreams at the + // schedule a locate-roll to refill the diskstreams at the // previous loop end loop_changing = true; @@ -1244,7 +1246,7 @@ Session::enable_record () */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { (*i)->monitor_input (true); } @@ -1279,7 +1281,7 @@ Session::disable_record (bool rt_context, bool force) */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { (*i)->monitor_input (false); } @@ -1306,7 +1308,7 @@ Session::step_back_from_record () */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (auto_input && (*i)->record_enabled ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (false); @@ -1476,7 +1478,7 @@ Session::set_block_size (jack_nframes_t nframes) (*i)->set_block_size (nframes); } - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->set_block_size (nframes); } @@ -1760,7 +1762,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod track->set_control_outs (cports); } - track->diskstream_changed.connect (mem_fun (this, &Session::resort_routes_proxy)); + track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes)); add_route (track); @@ -1805,7 +1807,7 @@ Session::new_audio_route (int input_channels, int output_channels) } while (n < (UINT_MAX-1)); try { - shared_ptr bus (new Route (*this, bus_name, -1, -1, -1, -1)); + shared_ptr bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), AUDIO)); if (bus->ensure_io (input_channels, output_channels, false, this)) { error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"), @@ -1858,7 +1860,7 @@ Session::new_audio_route (int input_channels, int output_channels) } catch (failed_constructor &err) { - error << _("Session: could not create new route.") << endmsg; + error << _("Session: could not create new audio route.") << endmsg; return shared_ptr ((Route*) 0); } } @@ -1893,14 +1895,14 @@ Session::add_route (shared_ptr route) } void -Session::add_diskstream (AudioDiskstream* dstream) +Session::add_diskstream (Diskstream* dstream) { /* need to do this in case we're rolling at the time, to prevent false underruns */ - dstream->do_refill(0, 0, 0); + dstream->do_refill_with_alloc(); { Glib::RWLock::WriterLock lm (diskstream_lock); - audio_diskstreams.push_back (dstream); + diskstreams.push_back (dstream); } /* take a reference to the diskstream, preventing it from @@ -1920,7 +1922,7 @@ Session::add_diskstream (AudioDiskstream* dstream) set_dirty(); save_state (_current_snapshot_name); - AudioDiskstreamAdded (dstream); /* EMIT SIGNAL */ + DiskstreamAdded (dstream); /* EMIT SIGNAL */ } void @@ -1957,18 +1959,19 @@ Session::remove_route (shared_ptr route) /* writer goes out of scope, forces route list update */ } + // FIXME: audio specific AudioTrack* at; AudioDiskstream* ds = 0; if ((at = dynamic_cast(route.get())) != 0) { - ds = &at->disk_stream(); + ds = &at->audio_diskstream(); } if (ds) { { Glib::RWLock::WriterLock lm (diskstream_lock); - audio_diskstreams.remove (ds); + diskstreams.remove (ds); } ds->unref (); @@ -2261,7 +2264,7 @@ Session::get_maximum_extent () const ensure atomicity. */ - for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { Playlist* pl = (*i)->playlist(); if ((me = pl->get_maximum_extent()) > max) { max = me; @@ -2271,12 +2274,12 @@ Session::get_maximum_extent () const return max; } -AudioDiskstream * +Diskstream * Session::diskstream_by_name (string name) { Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->name() == name) { return* i; } @@ -2285,12 +2288,12 @@ Session::diskstream_by_name (string name) return 0; } -AudioDiskstream * +Diskstream * Session::diskstream_by_id (const PBD::ID& id) { Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->id() == id) { return *i; } @@ -2555,18 +2558,10 @@ Session::find_whole_file_parent (AudioRegion& child) } void -Session::find_equivalent_playlist_regions (AudioRegion& region, vector& result) +Session::find_equivalent_playlist_regions (Region& region, vector& result) { - for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { - - AudioPlaylist* pl; - - if ((pl = dynamic_cast(*i)) == 0) { - continue; - } - - pl->get_region_list_equivalent_regions (region, result); - } + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) + (*i)->get_region_list_equivalent_regions (region, result); } int @@ -2618,7 +2613,7 @@ Session::remove_last_capture () Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { list& l = (*i)->last_capture_regions(); if (!l.empty()) { @@ -2925,18 +2920,6 @@ Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bo /* Playlist management */ -Playlist * -Session::get_playlist (string name) -{ - Playlist* ret = 0; - - if ((ret = playlist_by_name (name)) == 0) { - ret = new AudioPlaylist (*this, name); - } - - return ret; -} - Playlist * Session::playlist_by_name (string name) { @@ -3066,11 +3049,14 @@ Session::audition_playlist () } void -Session::audition_region (AudioRegion& r) +Session::audition_region (Region& r) { - Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0); - ev->set_ptr (&r); - queue_event (ev); + AudioRegion* ar = dynamic_cast(&r); + if (ar) { + Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0); + ev->set_ptr (ar); + queue_event (ev); + } } void @@ -3155,12 +3141,12 @@ Session::set_all_mute (bool yn) } uint32_t -Session::n_audio_diskstreams () const +Session::n_diskstreams () const { Glib::RWLock::ReaderLock lm (diskstream_lock); uint32_t n = 0; - for (AudioDiskstreamList::const_iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { n++; } @@ -3168,17 +3154,6 @@ Session::n_audio_diskstreams () const return n; } -void -Session::foreach_audio_diskstream (void (AudioDiskstream::*func)(void)) -{ - Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { - if (!(*i)->hidden()) { - ((*i)->*func)(); - } - } -} - void Session::graph_reordered () { @@ -3198,7 +3173,7 @@ Session::graph_reordered () reflect any changes in latencies within the graph. */ - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->set_capture_offset (); } } @@ -3481,7 +3456,7 @@ Session::reset_native_file_format () //RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__); Glib::RWLock::ReaderLock lm2 (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->reset_write_sources (false); } } @@ -3592,7 +3567,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf /* call tree *MUST* hold route_lock */ - if ((playlist = track.disk_stream().playlist()) == 0) { + if ((playlist = track.diskstream().playlist()) == 0) { goto out; } @@ -3602,7 +3577,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf goto out; } - nchans = track.disk_stream().n_channels(); + nchans = track.audio_diskstream().n_channels(); dir = discover_best_sound_dir (); diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index 4613bfccf9..6509a783bb 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -168,15 +168,9 @@ Session::butler_thread_work () struct timeval begin, end; struct pollfd pfd[1]; bool disk_work_outstanding = false; - AudioDiskstreamList::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); + DiskstreamList::iterator i; while (true) { - pfd[0].fd = butler_request_pipe[0]; pfd[0].events = POLLIN|POLLERR|POLLHUP; @@ -198,14 +192,13 @@ Session::butler_thread_work () } if (pfd[0].revents & POLLIN) { - + char req; /* empty the pipe of all current requests */ while (1) { size_t nread = ::read (butler_request_pipe[0], &req, sizeof (req)); - if (nread == 1) { switch ((ButlerRequest::Type) req) { @@ -240,10 +233,10 @@ Session::butler_thread_work () } } } - - for (i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + + //for (i = diskstreams.begin(); i != diskstreams.end(); ++i) { // cerr << "BEFORE " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl; - } + //} if (transport_work_requested()) { butler_transport_work (); @@ -257,16 +250,16 @@ Session::butler_thread_work () Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) { - - // cerr << "rah fondr " << (*i)->io()->name () << endl; + for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) { + + Diskstream* const ds = *i; - switch ((*i)->do_refill (butler_mixdown_buffer, butler_gain_buffer, conv_buffer)) { + switch (ds->do_refill ()) { case 0: - bytes += (*i)->read_data_count(); + bytes += ds->read_data_count(); break; case 1: - bytes += (*i)->read_data_count(); + bytes += ds->read_data_count(); disk_work_outstanding = true; break; @@ -278,7 +271,7 @@ Session::butler_thread_work () } - if (i != audio_diskstreams.end()) { + if (i != diskstreams.end()) { /* we didn't get to all the streams */ disk_work_outstanding = true; } @@ -299,12 +292,11 @@ Session::butler_thread_work () bytes = 0; compute_io = true; gettimeofday (&begin, 0); - - for (i = audio_diskstreams.begin(); !transport_work_requested() && butler_should_run && i != audio_diskstreams.end(); ++i) { - + + 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; @@ -330,7 +322,7 @@ Session::butler_thread_work () request_stop (); } - if (i != audio_diskstreams.end()) { + if (i != diskstreams.end()) { /* we didn't get to all the streams */ disk_work_outstanding = true; } @@ -357,7 +349,7 @@ Session::butler_thread_work () Glib::Mutex::Lock lm (butler_request_lock); if (butler_should_run && (disk_work_outstanding || transport_work_requested())) { -// for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { +// for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { // cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl; // } @@ -375,18 +367,17 @@ Session::butler_thread_work () void -Session::request_overwrite_buffer (AudioDiskstream* stream) +Session::request_overwrite_buffer (Diskstream* stream) { Event *ev = new Event (Event::Overwrite, Event::Add, Event::Immediate, 0, 0, 0.0); ev->set_ptr (stream); queue_event (ev); } +/** Process thread. */ void -Session::overwrite_some_buffers (AudioDiskstream* ds) +Session::overwrite_some_buffers (Diskstream* ds) { - /* executed by the audio thread */ - if (actively_recording()) { return; } @@ -398,7 +389,7 @@ Session::overwrite_some_buffers (AudioDiskstream* ds) } else { Glib::RWLock::ReaderLock dm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->set_pending_overwrite (true); } } diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc index ad8ce7c407..b39c4f2218 100644 --- a/libs/ardour/session_export.cc +++ b/libs/ardour/session_export.cc @@ -496,7 +496,7 @@ Session::prepare_to_export (AudioExportSpecification& spec) { Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)-> seek (spec.start_frame, true)) { error << string_compose (_("%1: cannot seek to %2 for export"), (*i)->name(), spec.start_frame) diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 2024730292..88b111a1fb 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -66,7 +66,7 @@ Session::process (jack_nframes_t nframes) void Session::prepare_diskstreams () { - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->prepare (); } } @@ -141,7 +141,7 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset) call path, so make sure we release any outstanding locks here before we return failure. */ - for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) { + for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) { (*ids)->recover (); } @@ -181,7 +181,7 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset) call path, so make sure we release any outstanding locks here before we return failure. */ - for (AudioDiskstreamList::iterator ids = audio_diskstreams.begin(); ids != audio_diskstreams.end(); ++ids) { + for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) { (*ids)->recover (); } @@ -200,7 +200,7 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler) float pworst = 1.0f; float cworst = 1.0f; - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->hidden()) { continue; @@ -570,7 +570,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset) bool ok = true; jack_nframes_t frame_delta = slave_transport_frame - _transport_frame; - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->can_internal_playback_seek (frame_delta)) { ok = false; break; @@ -578,7 +578,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset) } if (ok) { - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->internal_playback_seek (frame_delta); } _transport_frame += frame_delta; diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 2f6f57e2d8..c90fd91d73 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -194,6 +194,7 @@ 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 */ @@ -266,7 +267,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source)); Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist)); Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect)); - AudioDiskstream::AudioDiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream)); + AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream)); NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection)); Controllable::Created.connect (mem_fun (*this, &Session::add_controllable)); @@ -1386,7 +1387,7 @@ Session::state(bool full_state) { Glib::RWLock::ReaderLock dl (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { child->add_child_nocopy ((*i)->get_state()); } diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 03e078ecde..d850fb94c8 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -79,7 +79,7 @@ Session::request_transport_speed (float speed) } void -Session::request_diskstream_speed (AudioDiskstream& ds, float speed) +Session::request_diskstream_speed (Diskstream& ds, float speed) { Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed); ev->set_ptr (&ds); @@ -201,7 +201,7 @@ Session::butler_transport_work () } if (post_transport_work & PostTransportInputChange) { - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->non_realtime_input_change (); } } @@ -217,7 +217,7 @@ Session::butler_transport_work () cumulative_rf_motion = 0; reset_rf_scale (0); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed())); @@ -249,7 +249,7 @@ Session::non_realtime_set_speed () { Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->non_realtime_set_speed (); } } @@ -259,7 +259,7 @@ Session::non_realtime_overwrite () { Glib::RWLock::ReaderLock lm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->pending_overwrite) { (*i)->overwrite_existing_buffers (); } @@ -275,7 +275,7 @@ Session::non_realtime_stop (bool abort) did_record = false; - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->get_captured_frames () != 0) { did_record = true; break; @@ -328,7 +328,7 @@ Session::non_realtime_stop (bool abort) _have_captured = true; } - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->transport_stopped (*now, xnow, abort); } @@ -367,7 +367,7 @@ Session::non_realtime_stop (bool abort) } #endif - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) { (*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed())); @@ -494,7 +494,7 @@ Session::set_auto_loop (bool yn) if (seamless_loop) { // set all diskstreams to use internal looping - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { (*i)->set_loop (loc); } @@ -502,7 +502,7 @@ Session::set_auto_loop (bool yn) } else { // set all diskstreams to NOT use internal looping - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { (*i)->set_loop (0); } @@ -532,7 +532,7 @@ Session::set_auto_loop (bool yn) clear_events (Event::AutoLoop); // set all diskstreams to NOT use internal looping - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { (*i)->set_loop (0); } @@ -650,7 +650,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b The rarity and short potential lock duration makes this "OK" */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (!auto_input); @@ -665,7 +665,7 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b The rarity and short potential lock duration makes this "OK" */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (true); @@ -709,7 +709,7 @@ Session::set_transport_speed (float speed, bool abort) The rarity and short potential lock duration makes this "OK" */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->record_enabled ()) { //cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (true); @@ -735,7 +735,7 @@ Session::set_transport_speed (float speed, bool abort) The rarity and short potential lock duration makes this "OK" */ Glib::RWLock::ReaderLock dsm (diskstream_lock); - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (auto_input && (*i)->record_enabled ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (false); @@ -786,7 +786,7 @@ Session::set_transport_speed (float speed, bool abort) _last_transport_speed = _transport_speed; _transport_speed = speed; - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if ((*i)->realtime_set_speed ((*i)->speed(), true)) { post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed); } @@ -876,7 +876,7 @@ Session::actually_start_transport () transport_sub_state |= PendingDeclickIn; _transport_speed = 1.0; - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->realtime_set_speed ((*i)->speed(), true); } @@ -1006,7 +1006,7 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame) _slave_type = src; - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { if (!(*i)->hidden()) { if ((*i)->realtime_set_speed ((*i)->speed(), true)) { non_rt_required = true; @@ -1038,7 +1038,7 @@ Session::reverse_diskstream_buffers () } void -Session::set_diskstream_speed (AudioDiskstream* stream, float speed) +Session::set_diskstream_speed (Diskstream* stream, float speed) { if (stream->realtime_set_speed (speed, false)) { post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed); @@ -1235,7 +1235,7 @@ Session::update_latency_compensation (bool with_stop, bool abort) /* reflect any changes in latencies into capture offsets */ - for (AudioDiskstreamList::iterator i = audio_diskstreams.begin(); i != audio_diskstreams.end(); ++i) { + for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) { (*i)->set_capture_offset (); } } diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc new file mode 100644 index 0000000000..3b3b705a87 --- /dev/null +++ b/libs/ardour/track.cc @@ -0,0 +1,219 @@ +/* + Copyright (C) 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + 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. +*/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace PBD; + +Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type) + : Route (sess, name, 1, -1, -1, -1, flag, default_type) + , _diskstream (0) + , _rec_enable_control (*this) +{ + _declickable = true; + _freeze_record.state = NoFreeze; + _saved_meter_point = _meter_point; + _mode = mode; +} + +Track::Track (Session& sess, const XMLNode& node, DataType default_type) + : Route (sess, "to be renamed", 0, 0, -1, -1, Route::Flag(0), default_type) + , _diskstream (0) + , _rec_enable_control (*this) +{ + _freeze_record.state = NoFreeze; + _declickable = true; + _saved_meter_point = _meter_point; +} + +Track::~Track () +{ + if (_diskstream) { + _diskstream->unref(); + } +} + +void +Track::set_meter_point (MeterPoint p, void *src) +{ + Route::set_meter_point (p, src); +} + +XMLNode& +Track::get_state () +{ + return state (true); +} + +XMLNode& +Track::get_template () +{ + return state (false); +} + +void +Track::toggle_monitor_input () +{ + for (vector::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { + (*i)->request_monitor_input(!(*i)->monitoring_input()); + } +} + +jack_nframes_t +Track::update_total_latency () +{ + _own_latency = 0; + + for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { + if ((*i)->active ()) { + _own_latency += (*i)->latency (); + } + } + + set_port_latency (_own_latency); + + return _own_latency; +} + + +Track::FreezeRecord::~FreezeRecord () +{ + for (vector::iterator i = insert_info.begin(); i != insert_info.end(); ++i) { + delete *i; + } +} + +Track::FreezeState +Track::freeze_state() const +{ + return _freeze_record.state; +} + +Track::RecEnableControllable::RecEnableControllable (Track& s) + : track (s) +{ +} + +void +Track::RecEnableControllable::set_value (float val) +{ + bool bval = ((val >= 0.5f) ? true: false); + track.set_record_enable (bval, this); +} + +float +Track::RecEnableControllable::get_value (void) const +{ + if (track.record_enabled()) { return 1.0f; } + return 0.0f; +} + +bool +Track::record_enabled () const +{ + return _diskstream->record_enabled (); +} + +void +Track::set_record_enable (bool yn, void *src) +{ + if (_freeze_record.state == Frozen) { + return; + } + + if (_mix_group && src != _mix_group && _mix_group->is_active()) { + _mix_group->apply (&Track::set_record_enable, yn, _mix_group); + return; + } + + /* keep track of the meter point as it was before we rec-enabled */ + + if (!_diskstream->record_enabled()) { + _saved_meter_point = _meter_point; + } + + _diskstream->set_record_enabled (yn); + + if (_diskstream->record_enabled()) { + set_meter_point (MeterInput, this); + } else { + set_meter_point (_saved_meter_point, this); + } + + _rec_enable_control.Changed (); +} + +void +Track::set_mode (TrackMode m) +{ + if (_diskstream) { + if (_mode != m) { + _mode = m; + _diskstream->set_destructive (m == Destructive); + ModeChanged(); + } + } +} + +int +Track::set_name (string str, void *src) +{ + int ret; + + if (record_enabled() && _session.actively_recording()) { + /* this messes things up if done while recording */ + return -1; + } + + if (_diskstream->set_name (str)) { + return -1; + } + + /* save state so that the statefile fully reflects any filename changes */ + + if ((ret = IO::set_name (str, src)) == 0) { + _session.save_state (""); + } + return ret; +} + +void +Track::set_latency_delay (jack_nframes_t longest_session_latency) +{ + Route::set_latency_delay (longest_session_latency); + _diskstream->set_roll_delay (_roll_delay); +} + -- cgit v1.2.3