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);
}
示例#2
0
文件: nas.c 项目: dirker/mpg123
/* 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 */
}