1 /* 2 * Copyright (C) 2016-2018 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2017-2019 Robin Gareus <robin@gareus.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #ifndef __ardour_disk_io_h__ 21 #define __ardour_disk_io_h__ 22 23 #include <vector> 24 #include <string> 25 #include <exception> 26 27 #include "pbd/ringbufferNPT.h" 28 #include "pbd/rcu.h" 29 30 #include "ardour/interpolation.h" 31 #include "ardour/midi_buffer.h" 32 #include "ardour/processor.h" 33 #include "ardour/rt_midibuffer.h" 34 35 namespace PBD { 36 template<class T> class PlaybackBuffer; 37 } 38 39 namespace ARDOUR { 40 41 class AudioFileSource; 42 class AudioPlaylist; 43 class Location; 44 class MidiPlaylist; 45 class Playlist; 46 class Track; 47 class Session; 48 49 template<typename T> class MidiRingBuffer; 50 51 class LIBARDOUR_API DiskIOProcessor : public Processor 52 { 53 public: 54 enum Flag { 55 Recordable = 0x1, 56 Hidden = 0x2, 57 NonLayered = 0x8 // deprecated (kept only for enum compat) 58 }; 59 60 static const std::string state_node_name; 61 62 DiskIOProcessor (Session&, Track&, const std::string& name, Flag f); 63 virtual ~DiskIOProcessor (); 64 65 static void set_buffering_parameters (BufferingPreset bp); 66 67 int set_block_size (pframes_t); 68 bool configure_io (ChanCount in, ChanCount out); 69 bool can_support_io_configuration (const ChanCount& in, ChanCount& out); 70 71 /** @return A number between 0 and 1, where 0 indicates that the playback/capture buffer 72 * is dry (ie the disk subsystem could not keep up) and 1 indicates that the 73 * buffer is full. 74 */ 75 virtual float buffer_load() const = 0; 76 set_flag(Flag f)77 void set_flag (Flag f) { _flags = Flag (_flags | f); } unset_flag(Flag f)78 void unset_flag (Flag f) { _flags = Flag (_flags & ~f); } 79 hidden()80 bool hidden() const { return _flags & Hidden; } recordable()81 bool recordable() const { return _flags & Recordable; } 82 83 virtual void non_realtime_locate (samplepos_t); 84 punch_in()85 virtual void punch_in() {} punch_out()86 virtual void punch_out() {} 87 slaved()88 bool slaved() const { return _slaved; } set_slaved(bool yn)89 void set_slaved(bool yn) { _slaved = yn; } 90 91 PBD::Signal0<void> SpeedChanged; 92 PBD::Signal0<void> ReverseChanged; 93 94 int set_state (const XMLNode&, int version); 95 96 int add_channel (uint32_t how_many); 97 int remove_channel (uint32_t how_many); 98 need_butler()99 bool need_butler() const { return _need_butler; } 100 get_playlist(DataType dt)101 boost::shared_ptr<Playlist> get_playlist (DataType dt) const { return _playlists[dt]; } 102 boost::shared_ptr<MidiPlaylist> midi_playlist() const; 103 boost::shared_ptr<AudioPlaylist> audio_playlist() const; 104 playlist_modified()105 virtual void playlist_modified () {} 106 virtual int use_playlist (DataType, boost::shared_ptr<Playlist>); 107 108 virtual void adjust_buffering() = 0; 109 110 protected: 111 friend class Auditioner; 112 virtual int seek (samplepos_t which_sample, bool complete_refill = false) = 0; 113 virtual void configuration_changed () = 0; 114 115 protected: 116 Flag _flags; 117 bool _slaved; 118 bool in_set_state; 119 samplepos_t playback_sample; 120 bool _need_butler; 121 Track& _track; 122 123 void init (); 124 125 Glib::Threads::Mutex state_lock; 126 127 static bool get_buffering_presets (BufferingPreset bp, 128 samplecnt_t& read_chunk_size, 129 samplecnt_t& read_buffer_size, 130 samplecnt_t& write_chunk_size, 131 samplecnt_t& write_buffer_size); 132 133 enum TransitionType { 134 CaptureStart = 0, 135 CaptureEnd 136 }; 137 138 struct CaptureTransition { 139 TransitionType type; 140 samplepos_t capture_val; ///< The start or end file sample position 141 }; 142 143 /** Information about one audio channel, playback or capture 144 * (depending on the derived class) 145 */ 146 struct ChannelInfo : public boost::noncopyable { 147 148 ChannelInfo (samplecnt_t buffer_size); 149 virtual ~ChannelInfo (); 150 151 /** A semi-random-access ringbuffers for data to be played back. 152 * written to in the butler thread, read from in the process 153 * thread. 154 */ 155 PBD::PlaybackBuffer<Sample>* rbuf; 156 157 /** A ringbuffer for data to be recorded back, written to in the 158 * process thread, read from in the butler thread. 159 */ 160 PBD::RingBufferNPT<Sample>* wbuf; 161 PBD::RingBufferNPT<Sample>::rw_vector rw_vector; 162 163 /* used only by capture */ 164 boost::shared_ptr<AudioFileSource> write_source; 165 PBD::RingBufferNPT<CaptureTransition>* capture_transition_buf; 166 167 /* used in the butler thread only */ 168 samplecnt_t curr_capture_cnt; 169 170 virtual void resize (samplecnt_t) = 0; 171 }; 172 173 typedef std::vector<ChannelInfo*> ChannelList; 174 SerializedRCUManager<ChannelList> channels; 175 176 virtual int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many) = 0; 177 int remove_channel_from (boost::shared_ptr<ChannelList>, uint32_t how_many); 178 179 boost::shared_ptr<Playlist> _playlists[DataType::num_types]; 180 PBD::ScopedConnectionList playlist_connections; 181 playlist_changed(const PBD::PropertyChange &)182 virtual void playlist_changed (const PBD::PropertyChange&) {} 183 virtual void playlist_deleted (boost::weak_ptr<Playlist>); playlist_ranges_moved(std::list<Evoral::RangeMove<samplepos_t>> const &,bool)184 virtual void playlist_ranges_moved (std::list< Evoral::RangeMove<samplepos_t> > const &, bool) {} 185 186 /* The MIDI stuff */ 187 188 MidiRingBuffer<samplepos_t>* _midi_buf; 189 gint _samples_written_to_ringbuffer; 190 gint _samples_read_from_ringbuffer; 191 192 static void get_location_times (const Location* location, samplepos_t* start, samplepos_t* end, samplepos_t* length); 193 }; 194 195 } // namespace ARDOUR 196 197 #endif /* __ardour_disk_io_h__ */ 198