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 static const snd_pcm_format_t format_trans
[] = {
42 [PA_SAMPLE_U8
] = SND_PCM_FORMAT_U8
,
43 [PA_SAMPLE_ALAW
] = SND_PCM_FORMAT_A_LAW
,
44 [PA_SAMPLE_ULAW
] = SND_PCM_FORMAT_MU_LAW
,
45 [PA_SAMPLE_S16LE
] = SND_PCM_FORMAT_S16_LE
,
46 [PA_SAMPLE_S16BE
] = SND_PCM_FORMAT_S16_BE
,
47 [PA_SAMPLE_FLOAT32LE
] = SND_PCM_FORMAT_FLOAT_LE
,
48 [PA_SAMPLE_FLOAT32BE
] = SND_PCM_FORMAT_FLOAT_BE
,
50 assert(pcm_handle
&& ss
&& periods
&& period_size
);
52 if (snd_pcm_hw_params_malloc(&hwparams
) < 0 ||
53 snd_pcm_hw_params_any(pcm_handle
, hwparams
) < 0 ||
54 snd_pcm_hw_params_set_access(pcm_handle
, hwparams
, SND_PCM_ACCESS_RW_INTERLEAVED
) < 0 ||
55 snd_pcm_hw_params_set_format(pcm_handle
, hwparams
, format_trans
[ss
->format
]) < 0 ||
56 snd_pcm_hw_params_set_rate_near(pcm_handle
, hwparams
, &ss
->rate
, NULL
) < 0 ||
57 snd_pcm_hw_params_set_channels(pcm_handle
, hwparams
, ss
->channels
) < 0 ||
58 (*periods
> 0 && snd_pcm_hw_params_set_periods_near(pcm_handle
, hwparams
, periods
, NULL
) < 0) ||
59 (*period_size
> 0 && snd_pcm_hw_params_set_period_size_near(pcm_handle
, hwparams
, period_size
, NULL
) < 0) ||
60 snd_pcm_hw_params(pcm_handle
, hwparams
) < 0)
63 if (snd_pcm_prepare(pcm_handle
) < 0)
66 if (snd_pcm_hw_params_get_buffer_size(hwparams
, &buffer_size
) < 0 ||
67 snd_pcm_hw_params_get_period_size(hwparams
, period_size
, NULL
) < 0)
70 assert(buffer_size
> 0);
71 assert(*period_size
> 0);
72 *periods
= buffer_size
/ *period_size
;
79 snd_pcm_hw_params_free(hwparams
);
84 /* Allocate an IO event for every ALSA poll descriptor for the
85 * specified ALSA device. Return a pointer to such an array in
86 * *io_events. Store the length of that array in *n_io_events. Use the
87 * specified callback function and userdata. The array has to be freed
88 * with pa_free_io_events(). */
89 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
) {
91 struct pollfd
*pfds
, *ppfd
;
93 assert(pcm_handle
&& m
&& io_events
&& n_io_events
&& cb
);
95 *n_io_events
= snd_pcm_poll_descriptors_count(pcm_handle
);
97 pfds
= pa_xmalloc(sizeof(struct pollfd
) * *n_io_events
);
98 if (snd_pcm_poll_descriptors(pcm_handle
, pfds
, *n_io_events
) < 0) {
103 *io_events
= pa_xmalloc(sizeof(void*) * *n_io_events
);
105 for (i
= 0, ios
= *io_events
, ppfd
= pfds
; i
< *n_io_events
; i
++, ios
++, ppfd
++) {
106 *ios
= m
->io_new(m
, ppfd
->fd
,
107 ((ppfd
->events
& POLLIN
) ? PA_IO_EVENT_INPUT
: 0) |
108 ((ppfd
->events
& POLLOUT
) ? PA_IO_EVENT_OUTPUT
: 0), cb
, userdata
);
116 /* Free the memory allocated by pa_create_io_events() */
117 void pa_free_io_events(pa_mainloop_api
* m
, pa_io_event
**io_events
, unsigned n_io_events
) {
120 assert(m
&& io_events
);
122 for (ios
= io_events
, i
= 0; i
< n_io_events
; i
++, ios
++)