3
* Network Audio System? (NAS)
11
#include <audio/audiolib.h>
12
#include <audio/soundlib.h>
20
AuDeviceAttributes *da;
29
#define NAS_SOUND_PORT_DURATION 5 /* seconds */
30
#define NAS_SOUND_LOW_WATER_MARK 25 /* percent */
31
#define NAS_MAX_FORMAT 10 /* currently, there are 7 supported formats */
35
/* NAS specific routines */
38
nas_sendData(AuServer *aud, InfoPtr i, AuUint32 numBytes)
40
if (numBytes < i->buf_cnt) {
41
AuWriteElement(aud, i->flow, 0, numBytes, i->buf, AuFalse, NULL);
42
memmove(i->buf, i->buf + numBytes, i->buf_cnt - numBytes);
43
i->buf_cnt = i->buf_cnt - numBytes;
46
AuWriteElement(aud, i->flow, 0, i->buf_cnt, i->buf,
47
(numBytes > i->buf_cnt), NULL);
50
i->data_sent = AuTrue;
54
nas_eventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler)
56
InfoPtr i = (InfoPtr) handler->data;
60
case AuEventTypeMonitorNotify:
63
case AuEventTypeElementNotify:
65
AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
69
case AuElementNotifyKindLowWater:
70
nas_sendData(aud, i, event->num_bytes);
72
case AuElementNotifyKindState:
73
switch (event->cur_state)
76
if (event->reason != AuReasonUser)
77
nas_sendData(aud, i, event->num_bytes);
89
void nas_createFlow(struct audio_info_struct *ai)
91
AuDeviceID device = AuNone;
92
AuElement elements[2];
99
case AUDIO_FORMAT_SIGNED_16:
101
if (((char) *(short *)"x")=='x') /* ugly, but painless */
102
format = AuFormatLinearSigned16LSB; /* little endian */
104
format = AuFormatLinearSigned16MSB; /* big endian */
106
case AUDIO_FORMAT_UNSIGNED_8:
107
format = AuFormatLinearUnsigned8;
109
case AUDIO_FORMAT_SIGNED_8:
110
format = AuFormatLinearSigned8;
112
case AUDIO_FORMAT_ULAW_8:
113
format = AuFormatULAW8;
116
/* look for an output device */
117
for (i = 0; i < AuServerNumDevices(info.aud); i++)
118
if (((AuDeviceKind(AuServerDevice(info.aud, i)) ==
119
AuComponentKindPhysicalOutput) &&
120
AuDeviceNumTracks(AuServerDevice(info.aud, i))
122
device = AuDeviceIdentifier(AuServerDevice(info.aud, i));
125
if (device == AuNone) {
127
"Couldn't find an output device providing %d channels\n",
134
info.da = AuGetDeviceAttributes(info.aud, device, NULL);
135
if ((info.da)!=NULL) {
136
AuDeviceGain(info.da) = AuFixedPointFromSum(ai->gain, 0);
137
AuSetDeviceAttributes(info.aud, AuDeviceIdentifier(info.da),
138
AuCompDeviceGainMask, info.da, NULL);
141
fprintf(stderr,"audio/gain: setable Volume/PCM-Level not supported");
144
if (!(info.flow = AuCreateFlow(info.aud, NULL))) {
145
fprintf(stderr, "Couldn't create flow\n");
149
buf_samples = ai->rate * NAS_SOUND_PORT_DURATION;
151
AuMakeElementImportClient(&elements[0], /* element */
152
(unsigned short) ai->rate,
155
ai->channels, /* channels */
157
buf_samples, /* max samples */
158
(AuUint32) (buf_samples / 100
159
* NAS_SOUND_LOW_WATER_MARK),
163
AuMakeElementExportDevice(&elements[1], /* element */
166
(unsigned short) ai->rate,
168
AuUnlimitedSamples, /* num samples */
171
AuSetElements(info.aud, /* Au server */
172
info.flow, /* flow ID */
173
AuTrue, /* clocked */
174
2, /* num elements */
175
elements, /* elements */
176
NULL); /* return status */
178
AuRegisterEventHandler(info.aud, /* Au server */
179
AuEventHandlerIDMask, /* value mask */
182
nas_eventHandler, /* callback */
183
(AuPointer) &info); /* data */
185
info.buf_size = buf_samples * ai->channels * AuSizeofFormat(format);
186
info.buf = (char *) malloc(info.buf_size);
187
if (info.buf == NULL) {
188
fprintf(stderr, "Unable to allocate input/output buffer of size %ld\n",
193
info.data_sent = AuFalse;
194
info.finished = AuFalse;
196
AuStartFlow(info.aud, /* Au server */
206
while ((!info.data_sent) && (!info.finished)) {
207
AuNextEvent(info.aud, AuTrue, &ev);
208
AuDispatchEvent(info.aud, &ev);
210
info.data_sent = AuFalse;
213
/* required functions */
215
int audio_open(struct audio_info_struct *ai)
220
if (!(info.aud = AuOpenServer(ai->device, 0, NULL, 0, NULL, NULL))) {
221
if (ai->device==NULL)
222
fprintf(stderr,"could not open default NAS server\n");
224
fprintf(stderr,"could not open NAS server %s\n",
233
int audio_reset_parameters(struct audio_info_struct *ai)
237
ret = audio_close(ai);
239
ret = audio_open(ai);
243
extern int audio_rate_best_match(struct audio_info_struct *ai)
245
int maxRate, minRate;
247
if(!ai || ai->rate < 0)
249
maxRate = AuServerMaxSampleRate(info.aud);
250
minRate = AuServerMinSampleRate(info.aud);
251
if (ai->rate > maxRate) ai->rate = maxRate;
252
if (ai->rate < minRate) ai->rate = minRate;
256
int audio_set_rate(struct audio_info_struct *ai)
261
int audio_set_channels(struct audio_info_struct *ai)
266
int audio_set_format(struct audio_info_struct *ai)
271
int audio_get_formats(struct audio_info_struct *ai)
276
j = AuServerNumFormats(info.aud);
277
for (i=0; i<j; i++) {
278
k=AuServerFormat(info.aud,i);
282
ret |= AUDIO_FORMAT_ULAW_8;
284
case AuFormatLinearUnsigned8:
285
ret |= AUDIO_FORMAT_UNSIGNED_8;
287
case AuFormatLinearSigned8:
288
ret |= AUDIO_FORMAT_SIGNED_8;
290
case AuFormatLinearSigned16LSB:
291
ret |= AUDIO_FORMAT_SIGNED_16;
298
int audio_play_samples(struct audio_info_struct *ai,unsigned char *buf,int len)
302
if (info.buf_size == 0) nas_createFlow(ai);
304
while ((info.buf_cnt + (len - buf_cnt)) > info.buf_size) {
305
memcpy(info.buf + info.buf_cnt,
307
(info.buf_size - info.buf_cnt));
308
buf_cnt += (info.buf_size - info.buf_cnt);
309
info.buf_cnt += (info.buf_size - info.buf_cnt);
312
memcpy(info.buf + info.buf_cnt,
315
info.buf_cnt += (len - buf_cnt);
320
int audio_close(struct audio_info_struct *ai)
322
if (info.aud == NULL) {
326
if (info.buf_size == 0) {
327
/* Au server opened, but not yet initialized */
328
AuCloseServer(info.aud);
332
while (!info.finished) {
335
AuCloseServer(info.aud);