4 This file is part of polypaudio.
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include <sys/types.h>
27 #include <asoundlib.h>
29 #include <polyp/sample.h>
30 #include <polypcore/xmalloc.h>
31 #include <polypcore/log.h>
33 #include "alsa-util.h"
35 /* Set the hardware parameters of the given ALSA device. Returns the
36 * selected fragment settings in *period and *period_size */
37 int pa_alsa_set_hw_params(snd_pcm_t
*pcm_handle
, const pa_sample_spec
*ss
, uint32_t *periods
, snd_pcm_uframes_t
*period_size
) {
39 snd_pcm_uframes_t buffer_size
;
40 snd_pcm_hw_params_t
*hwparams
= NULL
;
41 unsigned int r
= ss
->rate
;
43 static const snd_pcm_format_t format_trans
[] = {
44 [PA_SAMPLE_U8
] = SND_PCM_FORMAT_U8
,
45 [PA_SAMPLE_ALAW
] = SND_PCM_FORMAT_A_LAW
,
46 [PA_SAMPLE_ULAW
] = SND_PCM_FORMAT_MU_LAW
,
47 [PA_SAMPLE_S16LE
] = SND_PCM_FORMAT_S16_LE
,
48 [PA_SAMPLE_S16BE
] = SND_PCM_FORMAT_S16_BE
,
49 [PA_SAMPLE_FLOAT32LE
] = SND_PCM_FORMAT_FLOAT_LE
,
50 [PA_SAMPLE_FLOAT32BE
] = SND_PCM_FORMAT_FLOAT_BE
,
52 assert(pcm_handle
&& ss
&& periods
&& period_size
);
54 if (snd_pcm_hw_params_malloc(&hwparams
) < 0 ||
55 snd_pcm_hw_params_any(pcm_handle
, hwparams
) < 0 ||
56 snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
) < 0 ||
57 snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[ss
->format
]) < 0 ||
58 snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &r
, NULL
) < 0 ||
59 snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, ss
->channels
) < 0 ||
60 (*periods
> 0 && snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, periods
, NULL
) < 0) ||
61 (*period_size
> 0 && snd_pcm_hw_params_set_period_size_near(pcm_handle
, hwparams
, period_size
, NULL
) < 0) ||
62 snd_pcm_hw_params(pcm_handle
, hwparams
) < 0)
66 pa_log_info(__FILE__
": device doesn't support %u Hz, changed to %u Hz.\n", ss
->rate
, r
);
68 if (snd_pcm_prepare(pcm_handle
) < 0)
71 if (snd_pcm_hw_params_get_buffer_size(hwparams
, &buffer_size
) < 0 ||
72 snd_pcm_hw_params_get_period_size(hwparams
, period_size
, NULL
) < 0)
75 assert(buffer_size
> 0);
76 assert(*period_size
> 0);
77 *periods
= buffer_size
/ *period_size
;
84 snd_pcm_hw_params_free(hwparams
);
89 /* Allocate an IO event for every ALSA poll descriptor for the
90 * specified ALSA device. Return a pointer to such an array in
91 * *io_events. Store the length of that array in *n_io_events. Use the
92 * specified callback function and userdata. The array has to be freed
93 * with pa_free_io_events(). */
94 int pa_create_io_events(snd_pcm_t
*pcm_handle
, pa_mainloop_api
* m
, pa_io_event
***io_events
, unsigned *n_io_events
, void (*cb
)(pa_mainloop_api
*a
, pa_io_event
*e
, int fd
, pa_io_event_flags_t events
, void *userdata
), void *userdata
) {
96 struct pollfd
*pfds
, *ppfd
;
98 assert(pcm_handle
&& m
&& io_events
&& n_io_events
&& cb
);
100 *n_io_events
= snd_pcm_poll_descriptors_count(pcm_handle
);
102 pfds
= pa_xmalloc(sizeof(struct pollfd
) * *n_io_events
);
103 if (snd_pcm_poll_descriptors(pcm_handle
, pfds
, *n_io_events
) < 0) {
108 *io_events
= pa_xmalloc(sizeof(void*) * *n_io_events
);
110 for (i
= 0, ios
= *io_events
, ppfd
= pfds
; i
< *n_io_events
; i
++, ios
++, ppfd
++) {
111 *ios
= m
->io_new(m
, ppfd
->fd
,
112 ((ppfd
->events
& POLLIN
) ? PA_IO_EVENT_INPUT
: 0) |
113 ((ppfd
->events
& POLLOUT
) ? PA_IO_EVENT_OUTPUT
: 0), cb
, userdata
);
121 /* Free the memory allocated by pa_create_io_events() */
122 void pa_free_io_events(pa_mainloop_api
* m
, pa_io_event
**io_events
, unsigned n_io_events
) {
125 assert(m
&& io_events
);
127 for (ios
= io_events
, i
= 0; i
< n_io_events
; i
++, ios
++)