summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/disk_io.h
blob: 39c8b16ec46b5ba99aa2c8a0969392a8a3a82bc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 * Copyright (C) 2016-2018 Paul Davis <paul@linuxaudiosystems.com>
 * Copyright (C) 2017-2019 Robin Gareus <robin@gareus.org>
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef __ardour_disk_io_h__
#define __ardour_disk_io_h__

#include <vector>
#include <string>
#include <exception>

#include "pbd/ringbufferNPT.h"
#include "pbd/rcu.h"

#include "ardour/interpolation.h"
#include "ardour/midi_buffer.h"
#include "ardour/processor.h"
#include "ardour/rt_midibuffer.h"

namespace PBD {
	template<class T> class PlaybackBuffer;
}

namespace ARDOUR {

class AudioFileSource;
class AudioPlaylist;
class Location;
class MidiPlaylist;
class Playlist;
class Track;
class Session;

template<typename T> class MidiRingBuffer;

class LIBARDOUR_API DiskIOProcessor : public Processor
{
public:
	enum Flag {
		Recordable  = 0x1,
		Hidden      = 0x2,
		NonLayered  = 0x8 // deprecated (kept only for enum compat)
	};

	static const std::string state_node_name;

	DiskIOProcessor (Session&, const std::string& name, Flag f);
	virtual ~DiskIOProcessor ();

	void set_track (boost::shared_ptr<Track>);
	void drop_track ();

	static void set_buffering_parameters (BufferingPreset bp);

	int set_block_size (pframes_t);
	bool configure_io (ChanCount in, ChanCount out);
	bool can_support_io_configuration (const ChanCount& in, ChanCount& out);

	/** @return A number between 0 and 1, where 0 indicates that the playback/capture buffer
	 *  is dry (ie the disk subsystem could not keep up) and 1 indicates that the
	 *  buffer is full.
	 */
	virtual float buffer_load() const = 0;

	void set_flag (Flag f)   { _flags = Flag (_flags | f); }
	void unset_flag (Flag f) { _flags = Flag (_flags & ~f); }

	bool           hidden()      const { return _flags & Hidden; }
	bool           recordable()  const { return _flags & Recordable; }

	virtual void non_realtime_locate (samplepos_t);

	virtual void punch_in()  {}
	virtual void punch_out() {}

	bool slaved() const      { return _slaved; }
	void set_slaved(bool yn) { _slaved = yn; }

	PBD::Signal0<void>            SpeedChanged;
	PBD::Signal0<void>            ReverseChanged;

	int set_state (const XMLNode&, int version);

	int add_channel (uint32_t how_many);
	int remove_channel (uint32_t how_many);

	bool need_butler() const { return _need_butler; }

	boost::shared_ptr<Playlist>      get_playlist (DataType dt) const { return _playlists[dt]; }
	boost::shared_ptr<MidiPlaylist>  midi_playlist() const;
	boost::shared_ptr<AudioPlaylist> audio_playlist() const;

	virtual void playlist_modified () {}
	virtual int use_playlist (DataType, boost::shared_ptr<Playlist>);

	virtual void adjust_buffering() = 0;

protected:
	friend class Auditioner;
	virtual int  seek (samplepos_t which_sample, bool complete_refill = false) = 0;
	virtual void configuration_changed () = 0;

protected:
	Flag         _flags;
	bool         _slaved;
	bool          in_set_state;
	samplepos_t   playback_sample;
	bool         _need_butler;
	boost::shared_ptr<Track> _track;

	void init ();

	Glib::Threads::Mutex state_lock;

	static bool get_buffering_presets (BufferingPreset bp,
	                                   samplecnt_t& read_chunk_size,
	                                   samplecnt_t& read_buffer_size,
	                                   samplecnt_t& write_chunk_size,
	                                   samplecnt_t& write_buffer_size);

	enum TransitionType {
		CaptureStart = 0,
		CaptureEnd
	};

	struct CaptureTransition {
		TransitionType   type;
		samplepos_t       capture_val; ///< The start or end file sample position
	};

	/** Information about one audio channel, playback or capture
	 * (depending on the derived class)
	 */
	struct ChannelInfo : public boost::noncopyable {

		ChannelInfo (samplecnt_t buffer_size);
		virtual ~ChannelInfo ();

		/** A semi-random-access ringbuffers for data to be played back.
		 * written to in the butler thread, read from in the process
		 * thread.
		 */
		PBD::PlaybackBuffer<Sample>* rbuf;

		/** A ringbuffer for data to be recorded back, written to in the
		 * process thread, read from in the butler thread.
		 */
		PBD::RingBufferNPT<Sample>* wbuf;
		PBD::RingBufferNPT<Sample>::rw_vector rw_vector;

		/* used only by capture */
		boost::shared_ptr<AudioFileSource> write_source;
		PBD::RingBufferNPT<CaptureTransition>* capture_transition_buf;

		/* used in the butler thread only */
		samplecnt_t curr_capture_cnt;

		virtual void resize (samplecnt_t) = 0;
	};

	typedef std::vector<ChannelInfo*> ChannelList;
	SerializedRCUManager<ChannelList> channels;

	virtual int add_channel_to (boost::shared_ptr<ChannelList>, uint32_t how_many) = 0;
	int remove_channel_from (boost::shared_ptr<ChannelList>, uint32_t how_many);

	boost::shared_ptr<Playlist> _playlists[DataType::num_types];
	PBD::ScopedConnectionList playlist_connections;

	virtual void playlist_changed (const PBD::PropertyChange&) {}
	virtual void playlist_deleted (boost::weak_ptr<Playlist>);
	virtual void playlist_ranges_moved (std::list< Evoral::RangeMove<samplepos_t> > const &, bool) {}

	/* The MIDI stuff */

	MidiRingBuffer<samplepos_t>*  _midi_buf;
	gint                         _samples_written_to_ringbuffer;
	gint                         _samples_read_from_ringbuffer;

	static void get_location_times (const Location* location, samplepos_t* start, samplepos_t* end, samplepos_t* length);
};

} // namespace ARDOUR

#endif /* __ardour_disk_io_h__ */