Beispiel #1
0
void
pr_enc(struct sio_enc *enc)
{
	fprintf(stderr, "%s%d", enc->sig ? "s" : "u", enc->bits);
	if (enc->bps > 1)
		fprintf(stderr, "%s", enc->le ? "le" : "be");
	if (enc->bps != SIO_BPS(enc->bits))
		fprintf(stderr, "%d%s", enc->bps, enc->msb ? "msb" : "lsb");
}
Beispiel #2
0
static struct sio_par *sndio_initpar(uint32_t srate, uint8_t ch)
{
	struct sio_par *par = NULL;

	if ((par = mem_zalloc(sizeof(*par), NULL)) == NULL)
		return NULL;

	sio_initpar(par);

	/* sndio doesn't support a-low and u-low */
	par->bits = 16;
	par->bps  = SIO_BPS(par->bits);
	par->sig  = 1;
	par->le   = SIO_LE_NATIVE;

	par->rchan = ch;
	par->pchan = ch;
	par->rate = srate;

	return par;
}
Beispiel #3
0
static struct sio_par *sndio_initpar(void *arg)
{
	struct sio_par *par;
	struct auplay_prm *prm = arg;

	if ((par = malloc(sizeof(struct sio_par))) == NULL)
		return NULL;

	sio_initpar(par);

	/* sndio doesn't support a-low and u-low */
	par->bits = 16;
	par->bps  = SIO_BPS(par->bits);
	par->sig  = 1;
	par->le   = 1;

	par->rchan = prm->ch;
	par->pchan = prm->ch;
	par->rate = prm->srate;

	return par;
}
Beispiel #4
0
static int
SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
    struct sio_par par;
    int status;

    this->hidden = (struct SDL_PrivateAudioData *)
        SDL_malloc(sizeof(*this->hidden));
    if (this->hidden == NULL) {
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden, 0, sizeof(*this->hidden));

    this->hidden->mixlen = this->spec.size;

    /* !!! FIXME: SIO_DEVANY can be a specific device... */
    if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) {
        SNDIO_CloseDevice(this);
        return SDL_SetError("sio_open() failed");
    }

    SNDIO_sio_initpar(&par);

    par.rate = this->spec.freq;
    par.pchan = this->spec.channels;
    par.round = this->spec.samples;
    par.appbufsz = par.round * 2;

    /* Try for a closest match on audio format */
    status = -1;
    while (test_format && (status < 0)) {
        if (!SDL_AUDIO_ISFLOAT(test_format)) {
            par.le = SDL_AUDIO_ISLITTLEENDIAN(test_format) ? 1 : 0;
            par.sig = SDL_AUDIO_ISSIGNED(test_format) ? 1 : 0;
            par.bits = SDL_AUDIO_BITSIZE(test_format);

            if (SNDIO_sio_setpar(this->hidden->dev, &par) == 0) {
                continue;
            }
            if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
                SNDIO_CloseDevice(this);
                return SDL_SetError("sio_getpar() failed");
            }
            if (par.bps != SIO_BPS(par.bits)) {
                continue;
            }
            if ((par.bits == 8 * par.bps) || (par.msb)) {
                status = 0;
                break;
            }
        }
        test_format = SDL_NextAudioFormat();
    }

    if (status < 0) {
        SNDIO_CloseDevice(this);
        return SDL_SetError("sndio: Couldn't find any hardware audio formats");
    }

    if ((par.bps == 4) && (par.sig) && (par.le))
        this->spec.format = AUDIO_S32LSB;
    else if ((par.bps == 4) && (par.sig) && (!par.le))
        this->spec.format = AUDIO_S32MSB;
    else if ((par.bps == 2) && (par.sig) && (par.le))
        this->spec.format = AUDIO_S16LSB;
    else if ((par.bps == 2) && (par.sig) && (!par.le))
        this->spec.format = AUDIO_S16MSB;
    else if ((par.bps == 2) && (!par.sig) && (par.le))
        this->spec.format = AUDIO_U16LSB;
    else if ((par.bps == 2) && (!par.sig) && (!par.le))
        this->spec.format = AUDIO_U16MSB;
    else if ((par.bps == 1) && (par.sig))
        this->spec.format = AUDIO_S8;
    else if ((par.bps == 1) && (!par.sig))
        this->spec.format = AUDIO_U8;
    else {
        SNDIO_CloseDevice(this);
        return SDL_SetError("sndio: Got unsupported hardware audio format.");
    }

    this->spec.freq = par.rate;
    this->spec.channels = par.pchan;
    this->spec.samples = par.round;

    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(&this->spec);

    /* Allocate mixing buffer */
    this->hidden->mixlen = this->spec.size;
    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
    if (this->hidden->mixbuf == NULL) {
        SNDIO_CloseDevice(this);
        return SDL_OutOfMemory();
    }
    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);

    if (!SNDIO_sio_start(this->hidden->dev)) {
        return SDL_SetError("sio_start() failed");
    }

    /* We're ready to rock and roll. :-) */
    return 0;
}
Beispiel #5
0
/*
 * open device and setup parameters
 * return: 0=success -1=fail
 */
static int init(struct ao *ao)
{
    struct priv *p = ao->priv;

    struct af_to_par {
        int format, bits, sig, le;
    } static const af_to_par[] = {
        {AF_FORMAT_U8,      8, 0, 0},
        {AF_FORMAT_S8,      8, 1, 0},
        {AF_FORMAT_U16_LE, 16, 0, 1},
        {AF_FORMAT_U16_BE, 16, 0, 0},
        {AF_FORMAT_S16_LE, 16, 1, 1},
        {AF_FORMAT_S16_BE, 16, 1, 0},
        {AF_FORMAT_U24_LE, 16, 0, 1},
        {AF_FORMAT_U24_BE, 24, 0, 0},
        {AF_FORMAT_S24_LE, 24, 1, 1},
        {AF_FORMAT_S24_BE, 24, 1, 0},
        {AF_FORMAT_U32_LE, 32, 0, 1},
        {AF_FORMAT_U32_BE, 32, 0, 0},
        {AF_FORMAT_S32_LE, 32, 1, 1},
        {AF_FORMAT_S32_BE, 32, 1, 0}
    }, *ap;
    int i;

    p->hdl = sio_open(p->dev, SIO_PLAY, 0);
    if (p->hdl == NULL) {
        MP_ERR(ao, "can't open sndio %s\n", p->dev);
        goto error;
    }

    ao->format = af_fmt_from_planar(ao->format);

    sio_initpar(&p->par);
    for (i = 0, ap = af_to_par;; i++, ap++) {
        if (i == sizeof(af_to_par) / sizeof(struct af_to_par)) {
            MP_VERBOSE(ao, "unsupported format\n");
            p->par.bits = 16;
            p->par.sig = 1;
            p->par.le = SIO_LE_NATIVE;
            break;
        }
        if (ap->format == ao->format) {
            p->par.bits = ap->bits;
            p->par.sig = ap->sig;
            if (ap->bits > 8)
                p->par.le = ap->le;
            if (ap->bits != SIO_BPS(ap->bits))
                p->par.bps = ap->bits / 8;
            break;
        }
    }
    p->par.rate = ao->samplerate;

    struct mp_chmap_sel sel = {0};
    for (int n = 0; n < MP_NUM_CHANNELS+1; n++)
        mp_chmap_sel_add_map(&sel, &sndio_layouts[n]);

    if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels))
        goto error;

    p->par.pchan = ao->channels.num;
    p->par.appbufsz = p->par.rate * 250 / 1000;    /* 250ms buffer */
    p->par.round = p->par.rate * 10 / 1000;    /*  10ms block size */
    if (!sio_setpar(p->hdl, &p->par)) {
        MP_ERR(ao, "couldn't set params\n");
        goto error;
    }
    if (!sio_getpar(p->hdl, &p->par)) {
        MP_ERR(ao, "couldn't get params\n");
        goto error;
    }
    if (p->par.bits == 8 && p->par.bps == 1) {
        ao->format = p->par.sig ? AF_FORMAT_S8 : AF_FORMAT_U8;
    } else if (p->par.bits == 16 && p->par.bps == 2) {
        ao->format = p->par.sig ?
            (p->par.le ? AF_FORMAT_S16_LE : AF_FORMAT_S16_BE) :
            (p->par.le ? AF_FORMAT_U16_LE : AF_FORMAT_U16_BE);
    } else if ((p->par.bits == 24 || p->par.msb) && p->par.bps == 3) {
        ao->format = p->par.sig ?
            (p->par.le ? AF_FORMAT_S24_LE : AF_FORMAT_S24_BE) :
            (p->par.le ? AF_FORMAT_U24_LE : AF_FORMAT_U24_BE);
    } else if ((p->par.bits == 32 || p->par.msb) && p->par.bps == 4) {
        ao->format = p->par.sig ?
            (p->par.le ? AF_FORMAT_S32_LE : AF_FORMAT_S32_BE) :
            (p->par.le ? AF_FORMAT_U32_LE : AF_FORMAT_U32_BE);
    } else {
        MP_ERR(ao, "couldn't set format\n");
        goto error;
    }

    ao->bps = p->par.bps * p->par.pchan * p->par.rate;
    p->havevol = sio_onvol(p->hdl, volcb, p);
    sio_onmove(p->hdl, movecb, p);
    p->delay = 0;
    if (!sio_start(p->hdl))
        MP_ERR(ao, "init: couldn't start\n");

    p->pfd = calloc (sio_nfds(p->hdl), sizeof (struct pollfd));
    if (!p->pfd)
        goto error;

    return 0;

error:
    if (p->hdl)
      sio_close(p->hdl);

    return -1;
}
Beispiel #6
0
/*
 * open the device.
 */
int
dev_sio_open(struct dev *d)
{
	struct sio_par par;
	unsigned int mode = d->mode & (MODE_PLAY | MODE_REC);

	d->sio.hdl = sio_open(d->path, mode, 1);
	if (d->sio.hdl == NULL) {
		if (mode != (SIO_PLAY | SIO_REC))
			return 0;
		d->sio.hdl = sio_open(d->path, SIO_PLAY, 1);
		if (d->sio.hdl != NULL)
			mode = SIO_PLAY;
		else {
			d->sio.hdl = sio_open(d->path, SIO_REC, 1);
			if (d->sio.hdl != NULL)
				mode = SIO_REC;
			else
				return 0;
		}
		if (log_level >= 1) {
			log_puts("warning, device opened in ");
			log_puts(mode == SIO_PLAY ? "play-only" : "rec-only");
			log_puts(" mode\n");
		}
	}
	sio_initpar(&par);
	par.bits = d->par.bits;
	par.bps = d->par.bps;
	par.sig = d->par.sig;
	par.le = d->par.le;
	par.msb = d->par.msb;
	if (mode & SIO_PLAY)
		par.pchan = d->pchan;
	if (mode & SIO_REC)
		par.rchan = d->rchan;
	if (d->bufsz)
		par.appbufsz = d->bufsz;
	if (d->round)
		par.round = d->round;
	if (d->rate)
		par.rate = d->rate;
	if (!sio_setpar(d->sio.hdl, &par))
		goto bad_close;
	if (!sio_getpar(d->sio.hdl, &par))
		goto bad_close;

#ifdef DEBUG
	/*
	 * We support any parameter combination exposed by the kernel,
	 * and we have no other choice than trusting the kernel for
	 * returning correct parameters. But let's check parameters
	 * early and nicely report kernel bugs rather than crashing
	 * later in memset(), malloc() or alike.
	 */

	if (par.bits > BITS_MAX) {
		log_puts(d->path);
		log_puts(": ");
		log_putu(par.bits);
		log_puts(": unsupported number of bits\n");
		goto bad_close;
	}
	if (par.bps > SIO_BPS(BITS_MAX)) {
		log_puts(d->path);
		log_puts(": ");
		log_putu(par.bps);
		log_puts(": unsupported sample size\n");
		goto bad_close;
	}
	if ((mode & SIO_PLAY) && par.pchan > NCHAN_MAX) {
		log_puts(d->path);
		log_puts(": ");
		log_putu(par.pchan);
		log_puts(": unsupported number of play channels\n");
		goto bad_close;
	}
	if ((mode & SIO_REC) && par.rchan > NCHAN_MAX) {
		log_puts(d->path);
		log_puts(": ");
		log_putu(par.rchan);
		log_puts(": unsupported number of rec channels\n");
		goto bad_close;
	}
	if (par.bufsz == 0 || par.bufsz > RATE_MAX) {
		log_puts(d->path);
		log_puts(": ");
		log_putu(par.bufsz);
		log_puts(": unsupported buffer size\n");
		goto bad_close;
	}
	if (par.round == 0 || par.round > par.bufsz ||
	    par.bufsz % par.round != 0) {
		log_puts(d->path);
		log_puts(": ");
		log_putu(par.round);
		log_puts(": unsupported block size\n");
		goto bad_close;
	}
	if (par.rate == 0 || par.rate > RATE_MAX) {
		log_puts(d->path);
		log_puts(": ");
		log_putu(par.rate);
		log_puts(": unsupported rate\n");
		goto bad_close;
	}
#endif

	d->par.bits = par.bits;
	d->par.bps = par.bps;
	d->par.sig = par.sig;
	d->par.le = par.le;
	d->par.msb = par.msb;
	if (mode & SIO_PLAY)
		d->pchan = par.pchan;
	if (mode & SIO_REC)
		d->rchan = par.rchan;
	d->bufsz = par.bufsz;
	d->round = par.round;
	d->rate = par.rate;
	if (!(mode & MODE_PLAY))
		d->mode &= ~(MODE_PLAY | MODE_MON);
	if (!(mode & MODE_REC))
		d->mode &= ~MODE_REC;
	sio_onmove(d->sio.hdl, dev_sio_onmove, d);
	d->sio.file = file_new(&dev_sio_ops, d, d->path, sio_nfds(d->sio.hdl));
	timo_set(&d->sio.watchdog, dev_sio_timeout, d);
	return 1;
 bad_close:
	sio_close(d->sio.hdl);
	return 0;
}