static int init(struct xmp_context *ctx) { struct xmp_options *o = &ctx->o; int channels, rate, format, buf_samples; int duration, gain, watermark; char *server; AuDeviceID device = AuNone; AuElement element[2]; char *token, **parm; int i; duration = 2; gain = 100; server = NULL; watermark = 10; channels = 2; rate = o->freq; parm_init(); chkparm1("duration", duration = atoi(token)); chkparm1("gain", gain = atoi(token)); chkparm1("server", server = token); chkparm1("watermark", watermark = atoi(token)); parm_end(); if (o->resol == 8) { format = o->outfmt & XMP_FMT_UNS ? AuFormatLinearUnsigned8 : AuFormatLinearSigned8; } else { if (o->big_endian) { format = o->outfmt & XMP_FMT_UNS ? AuFormatLinearUnsigned16MSB : AuFormatLinearSigned16MSB; } else { format = o-> outfmt & XMP_FMT_UNS ? AuFormatLinearUnsigned16LSB : AuFormatLinearSigned16LSB; } } if (o->outfmt & XMP_FMT_MONO) channels = 1; info.aud = AuOpenServer(server, 0, NULL, 0, NULL, NULL); if (!info.aud) { fprintf(stderr, "xmp: drv_nas: can't connect to server %s\n", server ? server : ""); return XMP_ERR_DINIT; } for (i = 0; i < AuServerNumDevices(info.aud); i++) { if (((AuDeviceKind(AuServerDevice(info.aud, i)) == AuComponentKindPhysicalOutput) && AuDeviceNumTracks(AuServerDevice(info.aud, i)) == channels)) { device = AuDeviceIdentifier(AuServerDevice(info.aud, i)); break; } } info.da = AuGetDeviceAttributes(info.aud, device, NULL); if (!info.da) { fprintf(stderr, "xmp: drv_nas: can't get device attributes\n"); AuCloseServer(info.aud); return XMP_ERR_DINIT; } AuDeviceGain(info.da) = AuFixedPointFromSum(gain, 0); AuSetDeviceAttributes(info.aud, AuDeviceIdentifier(info.da), AuCompDeviceGainMask, info.da, NULL); info.flow = AuCreateFlow(info.aud, NULL); if (!info.flow) { fprintf(stderr, "xmp: drv_nas: can't create flow\n"); AuCloseServer(info.aud); return XMP_ERR_DINIT; } buf_samples = rate * duration; AuMakeElementImportClient(&element[0], rate, format, channels, AuTrue, buf_samples, (AuUint32) (buf_samples * watermark / 100), 0, NULL); AuMakeElementExportDevice(&element[1], 0, device, rate, AuUnlimitedSamples, 0, NULL); AuSetElements(info.aud, info.flow, AuTrue, 2, element, NULL); AuRegisterEventHandler(info.aud, AuEventHandlerIDMask, 0, info.flow, nas_event, (AuPointer) & info); info.buf_size = buf_samples * channels * AuSizeofFormat(format); info.buf = (char *)malloc(info.buf_size); info.buf_cnt = 0; info.data_sent = AuFalse; info.finished = AuFalse; AuStartFlow(info.aud, info.flow, NULL); return xmp_smix_on(ctx); }
/* 0 on error */ static int nas_createFlow(out123_handle *ao) { AuDeviceID device = AuNone; AuElement elements[2]; unsigned char format; AuUint32 buf_samples; int i; switch(ao->format) { case MPG123_ENC_SIGNED_16: default: if (((char) *(short *)"x")=='x') /* ugly, but painless */ format = AuFormatLinearSigned16LSB; /* little endian */ else format = AuFormatLinearSigned16MSB; /* big endian */ break; case MPG123_ENC_UNSIGNED_8: format = AuFormatLinearUnsigned8; break; case MPG123_ENC_SIGNED_8: format = AuFormatLinearSigned8; break; case MPG123_ENC_ULAW_8: format = AuFormatULAW8; break; } /* look for an output device */ for (i = 0; i < AuServerNumDevices(info.aud); i++) if (((AuDeviceKind(AuServerDevice(info.aud, i)) == AuComponentKindPhysicalOutput) && AuDeviceNumTracks(AuServerDevice(info.aud, i)) == ao->channels )) { device = AuDeviceIdentifier(AuServerDevice(info.aud, i)); break; } if (device == AuNone) { error1("Couldn't find an output device providing %d channels.", ao->channels); return 0; } /* set gain */ if(ao->gain >= 0) { info.da = AuGetDeviceAttributes(info.aud, device, NULL); if ((info.da)!=NULL) { AuDeviceGain(info.da) = AuFixedPointFromSum(ao->gain, 0); AuSetDeviceAttributes(info.aud, AuDeviceIdentifier(info.da), AuCompDeviceGainMask, info.da, NULL); } else error("audio/gain: setable Volume/PCM-Level not supported"); } if (!(info.flow = AuCreateFlow(info.aud, NULL))) { error("Couldn't create flow"); return 0; } buf_samples = ao->rate * NAS_SOUND_PORT_DURATION; AuMakeElementImportClient(&elements[0], /* element */ (unsigned short) ao->rate, /* rate */ format, /* format */ ao->channels, /* channels */ AuTrue, /* ??? */ buf_samples, /* max samples */ (AuUint32) (buf_samples / 100 * NAS_SOUND_LOW_WATER_MARK), /* low water mark */ 0, /* num actions */ NULL); /* actions */ AuMakeElementExportDevice(&elements[1], /* element */ 0, /* input */ device, /* device */ (unsigned short) ao->rate, /* rate */ AuUnlimitedSamples, /* num samples */ 0, /* num actions */ NULL); /* actions */ AuSetElements(info.aud, /* Au server */ info.flow, /* flow ID */ AuTrue, /* clocked */ 2, /* num elements */ elements, /* elements */ NULL); /* return status */ AuRegisterEventHandler(info.aud, /* Au server */ AuEventHandlerIDMask, /* value mask */ 0, /* type */ info.flow, /* id */ nas_eventHandler, /* callback */ (AuPointer) &info); /* data */ info.buf_size = buf_samples * ao->channels * AuSizeofFormat(format); info.buf = (char *) malloc(info.buf_size); if (info.buf == NULL) { error1("Unable to allocate input/output buffer of size %ld", (long)info.buf_size); return 0; } info.buf_cnt = 0; info.data_sent = AuFalse; info.finished = AuFalse; AuStartFlow(info.aud, /* Au server */ info.flow, /* id */ NULL); /* status */ return 1; /* success */ }