summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour/disk_io.h
blob: 0f79930654d25ac7c552b10a65d5fa16b1e58235 (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
/*
    Copyright (C) 2009-2016 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_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/processor.h"

namespace ARDOUR {

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

template<typename T> class MidiRingBuffer;

class LIBARDOUR_API DiskIOProcessor : public Processor
{
public:
	enum Flag {
		Recordable  = 0x1,
		Hidden      = 0x2,
		Destructive = 0x4,
		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_route (boost::shared_ptr<Route>);
	void drop_route ();

	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;

protected:
	Flag         _flags;
	uint32_t      i_am_the_modifier;
	double       _actual_speed;
	double       _target_speed;
	bool         _slaved;
	bool          in_set_state;
	samplepos_t   playback_sample;
	bool         _need_butler;
	boost::shared_ptr<Route> _route;

	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 ();

		/** Ringbuffer for data to be played back.
		 * written to in the butler thread, read from in the process thread.
		 */
		PBD::RingBufferNPT<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__ */