source: roaraudio/plugins/alsa/pcm.c @ 3517:1a3218a3fc5b

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

updated license headers, FSF moved office

File size: 7.4 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(*) = ?");
86 return 0;
87}
88
89static snd_pcm_sframes_t roar_pcm_pointer(snd_pcm_ioplug_t *io) {
90 ROAR_DBG("roar_pcm_pointer(*) = ?");
91 return 0;
92}
93
94// TODO: FIXME: add support for reading data!
95static snd_pcm_sframes_t roar_pcm_transfer(snd_pcm_ioplug_t *io,
96                                        const snd_pcm_channel_area_t *areas,
97                                        snd_pcm_uframes_t offset,
98                                        snd_pcm_uframes_t size) {
99 struct roar_alsa_pcm * self = io->private_data;
100 char * buf;
101
102 ROAR_DBG("roar_pcm_transfer(*) = ?");
103
104 buf = (char *)areas->addr + (areas->first + areas->step * offset) / 8;
105
106 roar_vio_write(&(self->stream_vio), buf, size * self->info.channels * self->info.bits / 8);
107
108 return size;
109}
110
111static int roar_pcm_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp) {
112 ROAR_DBG("roar_pcm_delay(*) = ?");
113 return 0;
114}
115
116static int roar_pcm_prepare(snd_pcm_ioplug_t *io) {
117 struct roar_alsa_pcm * self = io->private_data;
118
119 ROAR_DBG("roar_pcm_prepare(*) = ?");
120
121 if ( self->stream_opened ) {
122  roar_vio_close(&(self->stream_vio));
123  self->stream_opened = 0;
124 }
125
126 if ( roar_stream_new(&(self->stream), self->info.rate, self->info.channels, self->info.bits, self->info.codec) == -1 ) {
127  return -EINVAL;
128 }
129
130 if ( roar_stream_connect(&(self->roar.con), &(self->stream), io->stream == SND_PCM_STREAM_PLAYBACK ? ROAR_DIR_PLAY : ROAR_DIR_MONITOR) == -1 ) {
131  return -EINVAL;
132 }
133
134 self->stream_opened = 1;
135
136 return -ENOSYS;
137}
138
139static int roar_pcm_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) {
140 struct roar_alsa_pcm * self = io->private_data;
141
142 ROAR_DBG("roar_pcm_hw_params(*) = ?");
143
144 self->info.channels = io->channels;
145 self->info.rate     = io->rate;
146
147 switch (io->format) {
148  case SND_PCM_FORMAT_U8:
149    self->info.codec = ROAR_CODEC_PCM_U_LE;
150    self->info.bits  = 8;
151   break;
152  case SND_PCM_FORMAT_A_LAW:
153    self->info.codec = ROAR_CODEC_ALAW;
154    self->info.bits  = 8;
155   break;
156  case SND_PCM_FORMAT_MU_LAW:
157    self->info.codec = ROAR_CODEC_MULAW;
158    self->info.bits  = 8;
159   break;
160  case SND_PCM_FORMAT_S16_LE:
161    self->info.codec = ROAR_CODEC_PCM_S_LE;
162    self->info.bits  = 16;
163   break;
164  case SND_PCM_FORMAT_S16_BE:
165    self->info.codec = ROAR_CODEC_PCM_S_BE;
166    self->info.bits  = 16;
167   break;
168  default:
169    return-EINVAL;
170 }
171
172 return 0;
173}
174
175static int roar_pcm_close (snd_pcm_ioplug_t * io) {
176 struct roar_alsa_pcm * self = io->private_data;
177
178 ROAR_DBG("roar_pcm_close(*) = ?");
179
180 roar_disconnect(&(self->roar.con));
181
182 free(self);
183
184 return 0;
185}
186
187static snd_pcm_ioplug_callback_t roar_pcm_callback = {
188    .start                  = roar_pcm_dummy,
189    .stop                   = roar_pcm_dummy,
190    .drain                  = roar_pcm_dummy,
191    .pointer                = roar_pcm_pointer,
192    .transfer               = roar_pcm_transfer,
193    .delay                  = roar_pcm_delay,
194    .poll_descriptors_count = NULL,
195    .poll_descriptors       = NULL,
196    .poll_revents           = NULL,
197    .prepare                = roar_pcm_prepare,
198    .hw_params              = roar_pcm_hw_params,
199    .close                  = roar_pcm_close,
200};
201
202SND_PCM_PLUGIN_DEFINE_FUNC(roar) {
203 struct roar_alsa_pcm * self;
204 snd_config_iterator_t i, next;
205 snd_config_t * n;
206 const char   * para;
207 const char   * server = NULL;
208 int            ret;
209
210 ROAR_DBG("SND_PCM_PLUGIN_DEFINE_FUNC(roar) = ?");
211
212 snd_config_for_each(i, next, conf) {
213  n = snd_config_iterator_entry(i);
214  if ( snd_config_get_id(n, &para) < 0 )
215   continue;
216
217  if ( !strcmp(para, "type") || !strcmp(para, "comment") )
218   continue;
219
220  if ( !strcmp(para, "server") ) {
221   if (snd_config_get_string(n, &server) < 0) {
222    return -EINVAL;
223   }
224  } else {
225   return -EINVAL;
226  }
227 }
228
229 errno = ENOSYS;
230
231 if ( (self = malloc(sizeof(struct roar_alsa_pcm))) == NULL )
232  return -errno;
233
234 memset(self, 0, sizeof(struct roar_alsa_pcm));
235
236 errno = ENOSYS;
237 if ( roar_simple_connect(&(self->roar.con), (char*)server, "ALSA Plugin") == -1 ) {
238  free(self);
239  return -errno;
240 }
241
242 self->io.version      = SND_PCM_IOPLUG_VERSION;
243 self->io.name         = "RoarAudio Plugin";
244 self->io.poll_fd      = -1;
245 self->io.poll_events  =  0;
246 self->io.mmap_rw      =  0;
247 self->io.callback     = &roar_pcm_callback;
248 self->io.private_data =  self;
249
250 if ( (ret = snd_pcm_ioplug_create(&(self->io), name, stream, mode)) < 0 ) {
251  roar_disconnect(&(self->roar.con));
252  free(self);
253  return ret;
254 }
255
256 if ( (ret = roar_hw_constraint(self)) < 0 ) {
257  snd_pcm_ioplug_delete(&(self->io));
258  roar_disconnect(&(self->roar.con));
259  free(self);
260  return ret;
261 }
262
263 ROAR_DBG("SND_PCM_PLUGIN_DEFINE_FUNC(roar) = 0");
264
265 return 0;
266}
267
268SND_PCM_PLUGIN_SYMBOL(roar);
269
270int __snd_pcm_roar_open_dlsym_pcm_001 (void) {
271 return 0;
272}
273
274//ll
Note: See TracBrowser for help on using the repository browser.