Example #1
0
static int
sio_psleep(struct sio_hdl *hdl, int event)
{
    struct pollfd pfd[SIO_MAXNFDS];
    int revents;
    int nfds;

    nfds = sio_nfds(hdl);
    if (nfds > SIO_MAXNFDS) {
        DPRINTF("sio_psleep: %d: too many descriptors\n", nfds);
        hdl->eof = 1;
        return 0;
    }
    for (;;) {
        nfds = sio_pollfd(hdl, pfd, event);
        while (poll(pfd, nfds, -1) < 0) {
            if (errno == EINTR)
                continue;
            DPERROR("sio_psleep: poll");
            hdl->eof = 1;
            return 0;
        }
        revents = sio_revents(hdl, pfd);
        if (revents & POLLHUP) {
            DPRINTF("sio_psleep: hang-up\n");
            return 0;
        }
        if (revents & event)
            break;
    }
    return 1;
}
Example #2
0
int
siofile_nfds(struct file *file)
{
	return sio_nfds(((struct siofile *)file)->hdl);
}
Example #3
0
/*
 * Open the device.
 */
struct siofile *
siofile_new(struct fileops *ops, char *path, unsigned int *rmode,
    struct aparams *ipar, struct aparams *opar,
    unsigned int *bufsz, unsigned int *round)
{
	struct sio_par par;
	struct sio_hdl *hdl;
	struct siofile *f;
	unsigned int mode = *rmode;

	hdl = sio_open(path, mode, 1);
	if (hdl == NULL) {
		if (mode != (SIO_PLAY | SIO_REC))
			return NULL;
		hdl = sio_open(path, SIO_PLAY, 1);
		if (hdl != NULL)
			mode = SIO_PLAY;
		else {
			hdl = sio_open(path, SIO_REC, 1);
			if (hdl != NULL)
				mode = SIO_REC;
			else
				return NULL;
		}
#ifdef DEBUG
		if (debug_level >= 1) {
			dbg_puts("warning, device opened in ");
			dbg_puts(mode == SIO_PLAY ? "play-only" : "rec-only");
			dbg_puts(" mode\n");
		}
#endif
	}

	sio_initpar(&par);
	if (mode & SIO_REC) {
		par.bits = ipar->bits;
		par.bps = ipar->bps;
		par.sig = ipar->sig;
		par.le = ipar->le;
		par.msb = ipar->msb;
		par.rate = ipar->rate;
		par.rchan = ipar->cmax + 1;
	} else {
		par.bits = opar->bits;
		par.bps = opar->bps;
		par.sig = opar->sig;
		par.le = opar->le;
		par.msb = opar->msb;
		par.rate = opar->rate;
	}
	if (mode & SIO_PLAY)
		par.pchan = opar->cmax + 1;
	if (*bufsz)
		par.appbufsz = *bufsz;
	if (*round)
		par.round = *round;
	if (!sio_setpar(hdl, &par))
		goto bad_close;
	if (!sio_getpar(hdl, &par))
		goto bad_close;
	if (mode & SIO_REC) {
		ipar->bits = par.bits;
		ipar->bps = par.bps;
		ipar->sig = par.sig;
		ipar->le = par.le;
		ipar->msb = par.msb;
		ipar->rate = par.rate;
		ipar->cmin = 0;
		ipar->cmax = par.rchan - 1;
	}
	if (mode & SIO_PLAY) {
		opar->bits = par.bits;
		opar->bps = par.bps;
		opar->sig = par.sig;
		opar->le = par.le;
		opar->msb = par.msb;
		opar->rate = par.rate;
		opar->cmin = 0;
		opar->cmax = par.pchan - 1;
	}
	*rmode = mode;
	*bufsz = par.bufsz;
	*round = par.round;
	f = (struct siofile *)file_new(ops, path, sio_nfds(hdl));
	if (f == NULL)
		goto bad_close;
	f->hdl = hdl;
	f->started = 0;
	f->wtickets = 0;
	f->rtickets = 0;
	f->wbpf = par.pchan * par.bps;
	f->rbpf = par.rchan * par.bps;
	f->bufsz = par.bufsz;
	sio_onmove(f->hdl, siofile_cb, f);
	return f;
 bad_close:
	sio_close(hdl);
	return NULL;
}
Example #4
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;
}
Example #5
0
File: siofile.c Project: t6/sndio
/*
 * 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;
}
Example #6
0
static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi,
    PaStream **stream,
    const PaStreamParameters *inputPar,
    const PaStreamParameters *outputPar,
    double sampleRate,
    unsigned long framesPerBuffer,
    PaStreamFlags streamFlags,
    PaStreamCallback *streamCallback,
    void *userData)
{
    PaSndioHostApiRepresentation *sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
    PaSndioStream *s;
    PaError err;
    struct sio_hdl *hdl;
    struct sio_par par;
    unsigned mode;
    int readChannels, writeChannels;
    PaSampleFormat readFormat, writeFormat, deviceFormat;

    PA_DEBUG(("OpenStream:\n"));

    mode = 0;
    readChannels = writeChannels = 0;
    readFormat = writeFormat = 0;
    sio_initpar(&par);

    if (outputPar && outputPar->channelCount > 0) {
        if (outputPar->device != 0) {
            PA_DEBUG(("OpenStream: %d: bad output device\n", outputPar->device));
            return paInvalidDevice;
        }
        if (outputPar->hostApiSpecificStreamInfo) {
            PA_DEBUG(("OpenStream: output specific info\n"));
            return paIncompatibleHostApiSpecificStreamInfo;
        }
        if (!SampleFormatToSndioParameters(&par, outputPar->sampleFormat)) {
            return paSampleFormatNotSupported;
        }
        writeFormat = outputPar->sampleFormat;
        writeChannels = par.pchan = outputPar->channelCount;
        mode |= SIO_PLAY;
    }
    if (inputPar && inputPar->channelCount > 0) {
        if (inputPar->device != 0) {
            PA_DEBUG(("OpenStream: %d: bad input device\n", inputPar->device));
            return paInvalidDevice;
        }
        if (inputPar->hostApiSpecificStreamInfo) {
            PA_DEBUG(("OpenStream: input specific info\n"));
            return paIncompatibleHostApiSpecificStreamInfo;
        }
        if (!SampleFormatToSndioParameters(&par, inputPar->sampleFormat)) {
            return paSampleFormatNotSupported;
        }
        readFormat = inputPar->sampleFormat;
        readChannels = par.rchan = inputPar->channelCount;
        mode |= SIO_REC;
    }
    par.rate = sampleRate;
    if (framesPerBuffer != paFramesPerBufferUnspecified)
        par.round = framesPerBuffer;

    PA_DEBUG(("OpenStream: mode = %x, trying rate = %u\n", mode, par.rate));

    hdl = sio_open(SIO_DEVANY, mode, 0);
    if (hdl == NULL)
        return paUnanticipatedHostError;
    if (!sio_setpar(hdl, &par)) {
        sio_close(hdl);
        return paUnanticipatedHostError;
    }
    if (!sio_getpar(hdl, &par)) {
        sio_close(hdl);
        return paUnanticipatedHostError;
    }
    if (!SndioParametersToSampleFormat(&par, &deviceFormat)) {
        sio_close(hdl);
        return paSampleFormatNotSupported;
    }
    if ((mode & SIO_REC) && par.rchan != inputPar->channelCount) {
        PA_DEBUG(("OpenStream: rchan(%u) != %d\n", par.rchan, inputPar->channelCount));
        sio_close(hdl);
        return paInvalidChannelCount;
    }
    if ((mode & SIO_PLAY) && par.pchan != outputPar->channelCount) {
        PA_DEBUG(("OpenStream: pchan(%u) != %d\n", par.pchan, outputPar->channelCount));
        sio_close(hdl);
        return paInvalidChannelCount;
    }
    if ((double)par.rate < sampleRate * 0.995 ||
        (double)par.rate > sampleRate * 1.005) {
        PA_DEBUG(("OpenStream: rate(%u) != %g\n", par.rate, sampleRate));
        sio_close(hdl);
        return paInvalidSampleRate;
    }
    
    s = (PaSndioStream *)PaUtil_AllocateMemory(sizeof(PaSndioStream));
    if (s == NULL) {
        sio_close(hdl);
        return paInsufficientMemory;
    }
    PaUtil_InitializeStreamRepresentation(&s->base, 
        streamCallback ? &sndioHostApi->callback : &sndioHostApi->blocking,
        streamCallback, userData);
    PA_DEBUG(("readChannels = %d, writeChannels = %d, readFormat = %x, writeFormat = %x\n", 
        readChannels, writeChannels, readFormat, writeFormat));
    err = PaUtil_InitializeBufferProcessor(&s->bufferProcessor,
        readChannels, readFormat, deviceFormat,
        writeChannels, writeFormat, deviceFormat,
        sampleRate,
        streamFlags,
        framesPerBuffer,
        par.round,
        paUtilFixedHostBufferSize, 
        streamCallback, userData);
    if (err) {
        PA_DEBUG(("OpenStream: PaUtil_InitializeBufferProcessor failed\n"));
        PaUtil_FreeMemory(s);
        sio_close(hdl);
        return err;
    }
    if (mode & SIO_REC) {
        s->readBuffer = malloc(par.round * par.rchan * par.bps);
        if (s->readBuffer == NULL) {
            PA_DEBUG(("OpenStream: failed to allocate readBuffer\n"));
            PaUtil_FreeMemory(s);
            sio_close(hdl);
            return paInsufficientMemory;
        }
    }
    if (mode & SIO_PLAY) {
        s->writeBuffer = malloc(par.round * par.pchan * par.bps);
        if (s->writeBuffer == NULL) {
            PA_DEBUG(("OpenStream: failed to allocate writeBuffer\n"));
            free(s->readBuffer);
            PaUtil_FreeMemory(s);
            sio_close(hdl);
            return paInsufficientMemory;
        }
    }
    s->nfds = sio_nfds(hdl);
    s->pfds = malloc(sizeof(struct pollfd) * s->nfds);
    s->base.streamInfo.inputLatency = 0;
    s->base.streamInfo.outputLatency = (mode & SIO_PLAY) ?
        (double)(par.bufsz + PaUtil_GetBufferProcessorOutputLatencyFrames(&s->bufferProcessor)) / (double)par.rate : 0;
    s->base.streamInfo.sampleRate = par.rate;
    s->active = 0;
    s->stopped = 1;
    s->mode = mode;
    s->hdl = hdl;
    s->par = par;
    *stream = s;    
    PA_DEBUG(("OpenStream: done\n"));
    return paNoError;
}