1 /*
2  * Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifndef __libbackend_portaudio_pcmio_h__
20 #define __libbackend_portaudio_pcmio_h__
21 
22 #include <map>
23 #include <vector>
24 #include <string>
25 #include <boost/shared_ptr.hpp>
26 
27 #include <stdint.h>
28 
29 #include <portaudio.h>
30 
31 namespace ARDOUR {
32 
33 class PortAudioIO {
34 public:
35 	PortAudioIO (void);
36 	~PortAudioIO (void);
37 
38 	enum StandardDevices {
39 		DeviceNone = -2,
40 		DeviceDefault = -1
41 	};
42 
43 	void host_api_list (std::vector<std::string>&);
44 	bool set_host_api (const std::string& host_api_name);
get_host_api()45 	std::string get_host_api () const { return _host_api_name; }
46 	PaHostApiTypeId get_current_host_api_type () const;
47 	PaHostApiIndex get_host_api_index_from_name (const std::string& name);
48 
49 	PaDeviceIndex get_default_input_device () const;
50 	PaDeviceIndex get_default_output_device () const;
51 
52 	bool     update_devices();
53 	void     input_device_list (std::map<int, std::string> &devices) const;
54 	void     output_device_list (std::map<int, std::string> &devices) const;
55 
56 	int available_sample_rates (int device_id, std::vector<float>& sample_rates);
57 	int available_buffer_sizes (int device_id, std::vector<uint32_t>& buffer_sizes);
58 
59 #ifdef WITH_ASIO
60 	bool get_asio_buffer_properties (int device_id,
61 	                                 long& min_size_samples,
62 	                                 long& max_size_samples,
63 	                                 long& preferred_size_samples,
64 	                                 long& granularity);
65 
66 	bool get_asio_buffer_sizes(int device_id,
67 	                           std::vector<uint32_t>& buffer_size,
68 	                           bool preferred_only);
69 #endif
70 
71 	std::string control_app_name (int device_id) const;
72 	void launch_control_app (int device_id);
73 
74 	PaErrorCode open_blocking_stream(int device_input,
75 	                                 int device_output,
76 	                                 double sample_rate,
77 	                                 uint32_t samples_per_period);
78 
79 	PaErrorCode open_callback_stream(int device_input,
80 	                                 int device_output,
81 	                                 double sample_rate,
82 	                                 uint32_t samples_per_period,
83 	                                 PaStreamCallback* callback,
84 	                                 void* data);
85 
86 	PaErrorCode start_stream(void);
87 
88 	PaErrorCode close_stream(void);
89 
n_playback_channels(void)90 	uint32_t n_playback_channels (void) const { return _playback_channels; }
n_capture_channels(void)91 	uint32_t n_capture_channels (void) const { return _capture_channels; }
92 
93 	std::string get_input_channel_name (int device_id, uint32_t channel) const;
94 	std::string get_output_channel_name (int device_id, uint32_t channel) const;
95 
sample_rate(void)96 	double   sample_rate (void) const { return _cur_sample_rate; }
capture_latency(void)97 	uint32_t capture_latency (void) const { return _cur_input_latency; }
playback_latency(void)98 	uint32_t playback_latency (void) const { return _cur_output_latency; }
stream_time(void)99 	double   stream_time(void) const { if (_stream) return Pa_GetStreamTime (_stream); return 0; }
100 
101 	int      next_cycle(uint32_t n_samples);
102 	int      get_capture_channel (uint32_t chn, float *input, uint32_t n_samples);
103 	int      set_playback_channel (uint32_t chn, const float *input, uint32_t n_samples);
104 
get_capture_buffer()105 	float* get_capture_buffer () { return _input_buffer; }
get_playback_buffer()106 	float* get_playback_buffer () { return _output_buffer; }
107 
108 private: // Methods
109 
110 	static bool pa_initialize();
111 	static bool pa_deinitialize();
112 	static bool& pa_initialized();
113 
114 	void clear_device_lists ();
115 	void add_none_devices ();
116 	void add_default_devices ();
117 	void add_devices ();
118 	std::string get_host_api_name_from_index (PaHostApiIndex index);
119 
120 	bool get_output_stream_params(int device_output,
121 	                              PaStreamParameters& outputParam) const;
122 	bool get_input_stream_params(int device_input,
123 	                             PaStreamParameters& inputParam) const;
124 
125 	bool set_sample_rate_and_latency_from_stream();
126 	bool allocate_buffers_for_blocking_api (uint32_t samples_per_period);
127 
128 	PaErrorCode pre_stream_open(int device_input,
129 	                          PaStreamParameters& inputParam,
130 	                          int device_output,
131 	                          PaStreamParameters& outputParam,
132 	                          uint32_t sample_rate,
133 	                          uint32_t samples_per_period);
134 
135 	void reset_stream_dependents ();
136 
137 	static void get_default_sample_rates(std::vector<float>&);
138 	static void get_default_buffer_sizes(std::vector<uint32_t>&);
139 
140 private: // Data
141 	uint32_t _capture_channels;
142 	uint32_t _playback_channels;
143 
144 	PaStream *_stream;
145 
146 	float *_input_buffer;
147 	float *_output_buffer;
148 
149 	double _cur_sample_rate;
150 	uint32_t _cur_input_latency;
151 	uint32_t _cur_output_latency;
152 
153 	struct paDevice {
154 		std::string name;
155 		uint32_t n_inputs;
156 		uint32_t n_outputs;
157 
paDevicepaDevice158 		paDevice (std::string n, uint32_t i, uint32_t o)
159 			: name (n)
160 			, n_inputs (i)
161 			, n_outputs (o)
162 		{}
163 	};
164 
165 	std::map<int, paDevice *> _input_devices;
166 	std::map<int, paDevice *> _output_devices;
167 
168 	PaHostApiIndex _host_api_index;
169 	std::string _host_api_name;
170 
171 };
172 
173 } // namespace
174 
175 #endif /* __libbackend_portaudio_pcmio_h__ */
176