Lines Matching defs:*
2 * \file pcm/pcm_simple.c
3 * \ingroup PCM_Simple
4 * \brief PCM Simple Interface
5 * \author Jaroslav Kysela <perex@perex.cz>
6 * \date 2004
10 * This library is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as
12 * published by the Free Software Foundation; either version 2.1 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "pcm_local.h"
28 static int set_buffer_time(snd_spcm_latency_t latency,
29 unsigned int *buffer_time)
31 switch (latency) {
32 case SND_SPCM_LATENCY_STANDARD:
33 *buffer_time = 350000;
34 break;
35 case SND_SPCM_LATENCY_MEDIUM:
36 *buffer_time = 25000;
37 break;
38 case SND_SPCM_LATENCY_REALTIME:
39 *buffer_time = 2500;
40 break;
41 default:
42 return -EINVAL;
44 return 0;
47 static int set_hw_params(snd_pcm_t *pcm,
48 snd_pcm_hw_params_t *hw_params,
49 unsigned int *rate,
50 unsigned int channels,
51 snd_pcm_format_t format,
52 snd_pcm_subformat_t subformat,
53 unsigned int *buffer_time,
54 unsigned int *period_time,
55 snd_pcm_access_t access)
57 int err;
60 * hardware parameters
62 err = snd_pcm_hw_params_any(pcm, hw_params);
63 if (err < 0)
64 return err;
65 err = snd_pcm_hw_params_set_access(pcm, hw_params, access);
66 if (err < 0)
67 return err;
68 err = snd_pcm_hw_params_set_format(pcm, hw_params, format);
69 if (err < 0)
70 return err;
71 if (subformat != SND_PCM_SUBFORMAT_STD) {
72 err = snd_pcm_hw_params_set_subformat(pcm, hw_params, subformat);
73 if (err < 0)
74 return err;
76 err = snd_pcm_hw_params_set_channels(pcm, hw_params, channels);
77 if (err < 0)
78 return err;
79 err = INTERNAL(snd_pcm_hw_params_set_rate_near)(pcm, hw_params, rate, 0);
80 if (err < 0)
81 return err;
82 err = INTERNAL(snd_pcm_hw_params_set_buffer_time_near)(pcm, hw_params, buffer_time, NULL);
83 if (err < 0)
84 return err;
85 if (period_time == NULL || *period_time == 0) {
86 unsigned int periods = 3;
87 err = INTERNAL(snd_pcm_hw_params_set_periods_near)(pcm, hw_params, &periods, NULL);
88 if (err < 0)
89 return err;
90 if (periods == 1)
91 return -EINVAL;
92 if (period_time) {
93 err = INTERNAL(snd_pcm_hw_params_get_period_time)(hw_params, period_time, NULL);
94 if (err < 0)
95 return err;
97 } else {
98 err = snd_pcm_hw_params_set_period_time(pcm, hw_params, *period_time, 0);
99 if (err < 0)
100 return err;
101 if (*buffer_time == *period_time)
102 return -EINVAL;
104 err = snd_pcm_hw_params(pcm, hw_params);
105 if (err < 0)
106 return err;
107 return 0;
110 static int set_sw_params(snd_pcm_t *pcm,
111 snd_pcm_sw_params_t *sw_params,
112 snd_spcm_xrun_type_t xrun_type)
114 int err;
116 err = snd_pcm_sw_params_current(pcm, sw_params);
117 if (err < 0)
118 return err;
119 err = snd_pcm_sw_params_set_start_threshold(pcm, sw_params, (pcm->buffer_size / pcm->period_size) * pcm->period_size);
120 if (err < 0)
121 return err;
122 err = snd_pcm_sw_params_set_avail_min(pcm, sw_params, pcm->period_size);
123 if (err < 0)
124 return err;
125 switch (xrun_type) {
126 case SND_SPCM_XRUN_STOP:
127 err = snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, pcm->buffer_size);
128 break;
129 case SND_SPCM_XRUN_IGNORE:
130 err = snd_pcm_sw_params_set_stop_threshold(pcm, sw_params, pcm->boundary);
131 break;
132 default:
133 return -EINVAL;
135 if (err < 0)
136 return err;
137 err = snd_pcm_sw_params(pcm, sw_params);
138 if (err < 0)
139 return err;
140 return 0;
144 * \brief Set up a simple PCM
145 * \param pcm PCM handle
146 * \param rate Sample rate
147 * \param channels Number of channels
148 * \param format PCM format
149 * \param subformat PCM subformat
150 * \param latency Latency type
151 * \param access PCM acceess type
152 * \param xrun_type XRUN type
153 * \return 0 if successful, or a negative error code
155 * \warning The simple PCM API may be broken in the current release.
157 int snd_spcm_init(snd_pcm_t *pcm,
158 unsigned int rate,
159 unsigned int channels,
160 snd_pcm_format_t format,
161 snd_pcm_subformat_t subformat,
162 snd_spcm_latency_t latency,
163 snd_pcm_access_t access,
164 snd_spcm_xrun_type_t xrun_type)
166 int err;
167 snd_pcm_hw_params_t *hw_params;
168 snd_pcm_sw_params_t *sw_params;
169 unsigned int rrate;
170 unsigned int buffer_time;
172 snd_pcm_hw_params_alloca(&hw_params);
173 snd_pcm_sw_params_alloca(&sw_params);
175 assert(pcm);
176 assert(rate > 5000 && rate < 192000);
177 assert(channels > 1 && channels < 512);
179 rrate = rate;
180 err = set_buffer_time(latency, &buffer_time);
181 if (err < 0)
182 return err;
183 err = set_hw_params(pcm, hw_params,
184 &rrate, channels, format, subformat,
185 &buffer_time, NULL, access);
186 if (err < 0)
187 return err;
189 err = set_sw_params(pcm, sw_params, xrun_type);
190 if (err < 0)
191 return err;
193 return 0;
197 * \brief Initialize simple PCMs in the duplex mode
198 * \param playback_pcm PCM handle for playback
199 * \param capture_pcm PCM handle for capture
200 * \param rate Sample rate
201 * \param channels Number of channels
202 * \param format PCM format
203 * \param subformat PCM subformat
204 * \param latency Latency type
205 * \param access PCM acceess type
206 * \param xrun_type XRUN type
207 * \param duplex_type Duplex mode
208 * \return 0 if successful, or a negative error code
210 * \warning The simple PCM API may be broken in the current release.
212 int snd_spcm_init_duplex(snd_pcm_t *playback_pcm,
213 snd_pcm_t *capture_pcm,
214 unsigned int rate,
215 unsigned int channels,
216 snd_pcm_format_t format,
217 snd_pcm_subformat_t subformat,
218 snd_spcm_latency_t latency,
219 snd_pcm_access_t access,
220 snd_spcm_xrun_type_t xrun_type,
221 snd_spcm_duplex_type_t duplex_type)
223 int err, i;
224 snd_pcm_hw_params_t *hw_params;
225 snd_pcm_sw_params_t *sw_params;
226 unsigned int rrate;
227 unsigned int xbuffer_time, buffer_time[2];
228 unsigned int period_time[2];
229 snd_pcm_t *pcms[2];
231 snd_pcm_hw_params_alloca(&hw_params);
232 snd_pcm_sw_params_alloca(&sw_params);
234 assert(playback_pcm);
235 assert(capture_pcm);
236 assert(rate > 5000 && rate < 192000);
237 assert(channels > 1 && channels < 512);
239 pcms[0] = playback_pcm;
240 pcms[1] = capture_pcm;
243 * hardware parameters
245 err = set_buffer_time(latency, &xbuffer_time);
246 if (err < 0)
247 return err;
249 for (i = 0; i < 2; i++) {
250 buffer_time[i] = xbuffer_time;
251 period_time[i] = i > 0 ? period_time[0] : 0;
252 rrate = rate;
253 err = set_hw_params(pcms[i], hw_params,
254 &rrate, channels, format, subformat,
255 &buffer_time[i], &period_time[i], access);
256 if (err < 0)
257 return err;
259 if (buffer_time[0] == buffer_time[1] &&
260 period_time[0] == period_time[1])
261 goto __sw_params;
262 if (duplex_type == SND_SPCM_DUPLEX_LIBERAL)
263 goto __sw_params;
264 /* FIXME: */
265 return -EINVAL;
268 * software parameters
270 __sw_params:
271 for (i = 0; i < 2; i++) {
272 err = set_sw_params(pcms[i], sw_params, xrun_type);
273 if (err < 0)
274 return err;
277 return 0;
281 * \brief Get the set up of simple PCM
282 * \param pcm PCM handle
283 * \param rate Pointer to store the current sample rate
284 * \param buffer_size Pointer to store the current buffer size
285 * \param period_size Pointer to store the current period size
286 * \return 0 if successful, or a negative error code
288 * \warning The simple PCM API may be broken in the current release.
290 int snd_spcm_init_get_params(snd_pcm_t *pcm,
291 unsigned int *rate,
292 snd_pcm_uframes_t *buffer_size,
293 snd_pcm_uframes_t *period_size)
295 assert(pcm);
296 if (!pcm->setup)
297 return -EBADFD;
298 if (rate)
299 *rate = pcm->rate;
300 if (buffer_size)
301 *buffer_size = pcm->buffer_size;
302 if (period_size)
303 *period_size = pcm->period_size;
304 return 0;