source: roaraudio/plugins/alsa/pcm.c @ 3659:1b7bb8e236a4

Last change on this file since 3659:1b7bb8e236a4 was 3659:1b7bb8e236a4, checked in by phi, 14 years ago

some cleanup

File size: 8.1 KB
Line 
1//pcm.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "roar.h"
37
38static int roar_hw_constraint(struct roar_alsa_pcm * self) {
39 snd_pcm_ioplug_t *io = &(self->io);
40 static const snd_pcm_access_t access_list[] = {
41  SND_PCM_ACCESS_RW_INTERLEAVED
42 };
43 static const unsigned int formats[] = {
44  // TODO: add list of additioal formats we support
45  SND_PCM_FORMAT_U8,
46  SND_PCM_FORMAT_A_LAW,
47  SND_PCM_FORMAT_MU_LAW,
48  SND_PCM_FORMAT_S16_LE,
49  SND_PCM_FORMAT_S16_BE,
50 };
51 int ret;
52
53 ROAR_DBG("roar_hw_constraint(*) = ?");
54
55 if ( (ret = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
56        _as(access_list), access_list)) < 0 )
57  return ret;
58
59 if ( (ret = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
60        _as(formats), formats)) < 0 )
61  return ret;
62
63 if ( (ret = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
64        1, ROAR_MAX_CHANNELS)) < 0 )
65  return ret;
66
67 if ( (ret = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 8000, 48000)) < 0 )
68  return ret;
69
70 if ( (ret = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1, 4294967295U)) < 0 )
71  return ret;
72
73 if ( (ret = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 1, 4294967295U)) < 0 )
74  return ret;
75
76 if ( (ret = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_BUFFER_BYTES, 1, 4294967295U)) < 0 )
77  return ret;
78
79 ROAR_DBG("roar_hw_constraint(*) = 0");
80
81 return 0;
82}
83
84static int roar_pcm_dummy (snd_pcm_ioplug_t * io) {
85 ROAR_DBG("roar_pcm_dummy(*) = 0");
86 return 0;
87}
88
89static snd_pcm_sframes_t roar_pcm_pointer(snd_pcm_ioplug_t *io) {
90 struct roar_alsa_pcm * self = io->private_data;
91
92 ROAR_DBG("roar_pcm_pointer(*) = ?");
93
94 return snd_pcm_bytes_to_frames(io->pcm, self->writec);
95}
96
97// TODO: FIXME: add support for reading data!
98static snd_pcm_sframes_t roar_pcm_transfer(snd_pcm_ioplug_t *io,
99                                        const snd_pcm_channel_area_t *areas,
100                                        snd_pcm_uframes_t offset,
101                                        snd_pcm_uframes_t size) {
102 struct roar_alsa_pcm * self = io->private_data;
103 char * buf;
104 size_t len = size * self->info.channels * self->info.bits / 8;
105 ssize_t ret;
106
107 ROAR_DBG("roar_pcm_transfer(*) = ?");
108 ROAR_DBG("roar_pcm_transfer(*): len=%lu", (long unsigned int) len);
109
110 buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
111
112 ret = roar_vio_write(&(self->stream_vio), buf, len);
113
114 if ( ret != -1 )
115  self->writec += ret;
116
117 ROAR_DBG("roar_pcm_transfer(*) = %lli", (long long int)size);
118 return size;
119}
120
121static int roar_pcm_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp) {
122 ROAR_DBG("roar_pcm_delay(*) = ?");
123 return 0;
124}
125
126static int roar_pcm_prepare(snd_pcm_ioplug_t *io) {
127 struct roar_alsa_pcm * self = io->private_data;
128
129 ROAR_DBG("roar_pcm_prepare(*) = ?");
130
131 if ( self->stream_opened ) {
132  roar_vio_close(&(self->stream_vio));
133  self->stream_opened = 0;
134 }
135
136 if ( roar_vio_simple_new_stream_obj(&(self->stream_vio), &(self->roar.con), &(self->stream),
137                                     self->info.rate, self->info.channels, self->info.bits, self->info.codec,
138                                     io->stream == SND_PCM_STREAM_PLAYBACK ? ROAR_DIR_PLAY : ROAR_DIR_MONITOR
139                                    ) == -1 ) {
140  return -EINVAL;
141 }
142
143 self->stream_opened = 1;
144
145 ROAR_DBG("roar_pcm_prepare(*) = 0");
146 return 0;
147}
148
149static int roar_pcm_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) {
150 struct roar_alsa_pcm * self = io->private_data;
151
152 ROAR_DBG("roar_pcm_hw_params(*) = ?");
153
154 self->info.channels = io->channels;
155 self->info.rate     = io->rate;
156
157 switch (io->format) {
158  case SND_PCM_FORMAT_U8:
159    self->info.codec = ROAR_CODEC_PCM_U_LE;
160    self->info.bits  = 8;
161   break;
162  case SND_PCM_FORMAT_A_LAW:
163    self->info.codec = ROAR_CODEC_ALAW;
164    self->info.bits  = 8;
165   break;
166  case SND_PCM_FORMAT_MU_LAW:
167    self->info.codec = ROAR_CODEC_MULAW;
168    self->info.bits  = 8;
169   break;
170  case SND_PCM_FORMAT_S16_LE:
171    self->info.codec = ROAR_CODEC_PCM_S_LE;
172    self->info.bits  = 16;
173   break;
174  case SND_PCM_FORMAT_S16_BE:
175    self->info.codec = ROAR_CODEC_PCM_S_BE;
176    self->info.bits  = 16;
177   break;
178  default:
179    return-EINVAL;
180 }
181
182 ROAR_DBG("roar_pcm_hw_params(*) = 0");
183 return 0;
184}
185
186static int roar_pcm_close (snd_pcm_ioplug_t * io) {
187 struct roar_alsa_pcm * self = io->private_data;
188
189 ROAR_DBG("roar_pcm_close(*) = ?");
190
191 roar_disconnect(&(self->roar.con));
192
193 free(self);
194
195 return 0;
196}
197
198static snd_pcm_ioplug_callback_t roar_pcm_callback = {
199    .start                  = roar_pcm_dummy,
200    .stop                   = roar_pcm_dummy,
201    .drain                  = roar_pcm_dummy,
202    .pointer                = roar_pcm_pointer,
203    .transfer               = roar_pcm_transfer,
204    .delay                  = roar_pcm_delay,
205    .poll_descriptors_count = NULL,
206    .poll_descriptors       = NULL,
207    .poll_revents           = NULL,
208    .prepare                = roar_pcm_prepare,
209    .hw_params              = roar_pcm_hw_params,
210    .hw_free                = NULL,
211    .sw_params              = NULL,
212    .pause                  = NULL,
213    .resume                 = NULL,
214    .dump                   = NULL,
215    .close                  = roar_pcm_close,
216};
217
218SND_PCM_PLUGIN_DEFINE_FUNC(roar) {
219 struct roar_alsa_pcm * self;
220 snd_config_iterator_t i, next;
221 snd_config_t * n;
222 const char   * para;
223 const char   * server = NULL;
224 int            ret;
225
226 ROAR_DBG("SND_PCM_PLUGIN_DEFINE_FUNC(roar) = ?");
227
228 snd_config_for_each(i, next, conf) {
229  n = snd_config_iterator_entry(i);
230  if ( snd_config_get_id(n, &para) < 0 )
231   continue;
232
233  if ( !strcmp(para, "type") || !strcmp(para, "comment") )
234   continue;
235
236  if ( !strcmp(para, "server") ) {
237   if (snd_config_get_string(n, &server) < 0) {
238    return -EINVAL;
239   }
240  } else {
241   return -EINVAL;
242  }
243 }
244
245 errno = ENOSYS;
246
247 if ( (self = malloc(sizeof(struct roar_alsa_pcm))) == NULL )
248  return -errno;
249
250 memset(self, 0, sizeof(struct roar_alsa_pcm));
251
252 errno = ENOSYS;
253 if ( roar_simple_connect(&(self->roar.con), (char*)server, "ALSA Plugin") == -1 ) {
254  free(self);
255  return -errno;
256 }
257
258 self->io.version      = SND_PCM_IOPLUG_VERSION;
259 self->io.name         = "RoarAudio Plugin";
260 self->io.poll_fd      = -1;
261 self->io.poll_events  =  0;
262 self->io.mmap_rw      =  0;
263 self->io.callback     = &roar_pcm_callback;
264 self->io.private_data =  self;
265
266 if ( (ret = snd_pcm_ioplug_create(&(self->io), name, stream, mode)) < 0 ) {
267  roar_disconnect(&(self->roar.con));
268  free(self);
269  return ret;
270 }
271
272 if ( (ret = roar_hw_constraint(self)) < 0 ) {
273  snd_pcm_ioplug_delete(&(self->io));
274  roar_disconnect(&(self->roar.con));
275  free(self);
276  return ret;
277 }
278
279 *pcmp = self->io.pcm;
280
281 ROAR_DBG("SND_PCM_PLUGIN_DEFINE_FUNC(roar) = 0");
282
283 return 0;
284}
285
286SND_PCM_PLUGIN_SYMBOL(roar);
287
288int __snd_pcm_roar_open_dlsym_pcm_001 (void) {
289 ROAR_DBG("__snd_pcm_roar_open_dlsym_pcm_001(void) = 0");
290 return 0;
291}
292
293//ll
Note: See TracBrowser for help on using the repository browser.