Directly apply MIDI automation state changes
[ardour.git] / libs / ardouralsautil / deviceparams.cc
1 /*
2  * Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
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 #include <alsa/asoundlib.h>
20 #include "pbd/convert.h"
21 #include "ardouralsautil/deviceinfo.h"
22
23 using namespace std;
24
25 int
26 ARDOUR::get_alsa_device_parameters (const char* device_name, const bool play, ALSADeviceInfo *nfo)
27 {
28         snd_pcm_t *pcm;
29         snd_pcm_hw_params_t *hw_params;
30         std::string errmsg;
31         int err;
32
33         nfo->valid = false;
34
35         unsigned long min_psiz, max_psiz;
36         unsigned long min_bufz, max_bufz;
37         unsigned int min_nper, max_nper;
38
39         err = snd_pcm_open (&pcm, device_name,
40                         play ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE,
41                         SND_PCM_NONBLOCK);
42
43         if (err < 0) {
44                 fprintf (stderr, "ALSA: Cannot open device '%s': %s\n", device_name, snd_strerror (err));
45                 return 1;
46         }
47
48         snd_pcm_hw_params_alloca (&hw_params);
49         err = snd_pcm_hw_params_any (pcm, hw_params);
50         if (err < 0) {
51                 errmsg = "Cannot get hardware parameters";
52                 goto error_out;
53         }
54
55         err = snd_pcm_hw_params_get_channels_max (hw_params, &nfo->max_channels);
56         if (err < 0) {
57                 errmsg = "Cannot get maximum channels count";
58                 goto error_out;
59         }
60
61         err = snd_pcm_hw_params_get_rate_min (hw_params, &nfo->min_rate, NULL);
62         if (err < 0) {
63                 errmsg = "Cannot get minimum rate";
64                 goto error_out;
65         }
66         err = snd_pcm_hw_params_get_rate_max (hw_params, &nfo->max_rate, NULL);
67         if (err < 0) {
68                 errmsg = "Cannot get maximum rate";
69                 goto error_out;
70         }
71
72         err = snd_pcm_hw_params_get_period_size_min (hw_params, &min_psiz, 0);
73         if (err < 0) {
74                 errmsg = "Cannot get minimum period size";
75                 goto error_out;
76         }
77         err = snd_pcm_hw_params_get_period_size_max (hw_params, &max_psiz, 0);
78         if (err < 0) {
79                 errmsg = "Cannot get maximum period size";
80                 goto error_out;
81         }
82
83         err = snd_pcm_hw_params_get_buffer_size_min (hw_params, &min_bufz);
84         if (err < 0) {
85                 errmsg = "Cannot get minimum buffer size";
86                 goto error_out;
87         }
88         err = snd_pcm_hw_params_get_buffer_size_max (hw_params, &max_bufz);
89         if (err < 0) {
90                 errmsg = "Cannot get maximum buffer size";
91                 goto error_out;
92         }
93
94         err = snd_pcm_hw_params_get_periods_min (hw_params, &min_nper, 0);
95         if (err < 0) {
96                 errmsg = "Cannot get minimum period count";
97                 goto error_out;
98         }
99         err = snd_pcm_hw_params_get_periods_max (hw_params, &max_nper, 0);
100         if (err < 0) {
101                 errmsg = "Cannot get maximum period count";
102                 goto error_out;
103         }
104
105         snd_pcm_close (pcm);
106
107         /* see also libs/backends/alsa/zita-alsa-pcmi.cc
108          * If any debug parameter is set, print device info.
109          */
110         if (getenv ("ZITA_ALSA_PCMI_DEBUG")) {
111                 fprintf (stdout, "ALSA: *%s* device-info\n", play ? "playback" : "capture");
112                 fprintf (stdout, "  dev_name : %s\n", device_name);
113                 fprintf (stdout, "  channels : %u\n", nfo->max_channels);
114                 fprintf (stdout, "  min_rate : %u\n", nfo->min_rate);
115                 fprintf (stdout, "  max_rate : %u\n", nfo->max_rate);
116                 fprintf (stdout, "  min_psiz : %lu\n", nfo->min_size);
117                 fprintf (stdout, "  max_psiz : %lu\n", nfo->max_size);
118                 fprintf (stdout, "  min_bufz : %lu\n", min_bufz);
119                 fprintf (stdout, "  max_bufz : %lu\n", max_bufz);
120                 fprintf (stdout, "  min_nper : %d\n", min_nper);
121                 fprintf (stdout, "  max_nper : %d\n", max_nper);
122                 fprintf (stdout, "  possible : %lu .. %lu\n", nfo->min_size, nfo->max_size);
123         }
124
125         /* AlsaAudioBackend supports n-periods 2, 3 */
126         if (min_nper > 2 || max_nper < 3) {
127                 errmsg = "Unsupported period count";
128                 return 1;
129         }
130
131         nfo->min_size = std::max (min_psiz, min_bufz / 3);
132         nfo->max_size = std::min (max_psiz, max_bufz / 2);
133         nfo->valid = true;
134         return 0;
135
136 error_out:
137         fprintf (stderr, "ALSA: %s: %s\n", errmsg.c_str(), snd_strerror (err));
138         snd_pcm_close (pcm);
139         return 1;
140
141 }