/* * Re-opens device with read-mode and starts recording (half-duplex). * Returns the DMA buffer size if successful. */ static int sndio_rec_start(int rate, int bits, int stereo) { sndio_save_bits = _sound_bits; sndio_save_stereo = _sound_stereo; sndio_save_freq = _sound_freq; _unix_bg_man->unregister_func(sndio_update); if (hdl != NULL) sio_close(hdl); hdl = NULL; _sound_bits = bits; _sound_stereo = stereo; _sound_freq = rate; if (open_sndio_device(1) != 0) return 0; sndio_volume = 127; sio_onvol(hdl, volcb, NULL); if (!sio_start(hdl)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not start sndio for recording")); sio_close(hdl); return 0; } return sndio_rec_bufsize; }
/* Stops recording and switches the device back to the original mode. */ static void sndio_rec_stop(void) { if (hdl != NULL) sio_close(hdl); hdl = NULL; _sound_bits = sndio_save_bits; _sound_stereo = sndio_save_stereo; _sound_freq = sndio_save_freq; if (open_sndio_device(0) != 0) return; sndio_realpos = sndio_playpos = 0; sio_onmove(hdl, movecb, NULL); sndio_volume = 127; sio_onvol(hdl, volcb, NULL); if (!sio_start(hdl)) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not start sndio")); sio_close(hdl); return; } _unix_bg_man->register_func(sndio_update); }
void siofile_start(struct file *file, void (*cb)(void *, int), void *arg) { struct siofile *f = (struct siofile *)file; if (!sio_start(f->hdl)) { #ifdef DEBUG dbg_puts(f->file.name); dbg_puts(": failed to start device\n"); #endif file_close(file); return; } f->started = 1; f->wtickets = f->bufsz * f->wbpf; f->rtickets = 0; #ifdef DEBUG f->wtime = file_wtime; f->utime = file_utime; if (debug_level >= 3) { file_dbg(&f->file); dbg_puts(": started\n"); } #endif f->onmove = cb; f->arg = arg; }
static void * read_thread(void *dp) { sndio_in_driver *d = dp; struct pollfd pfd; int size, ret, off, nfds; if (!sio_start(d->hdl)) { error_error("could not start sndio"); goto done; } while (d->read_trun) { nfds = sio_pollfd(d->hdl, &pfd, POLLIN); poll(&pfd, nfds, -1); if (sio_revents(d->hdl, &pfd) & POLLIN) { size = d->par.rchan * d->par.bps * d->bufsize; off = 0; while (size > 0) { ret = sio_read(d->hdl, d->sndbuf + off, size); off += ret; size -= ret; } sample_editor_sampled(d->sndbuf, d->bufsize, d->par.rate, d->mf); } } done: pthread_exit(NULL); return NULL; }
unsigned long open_audio(unsigned long f, int s) { struct sio_par par; int buf_max; hdl = sio_open(NULL, SIO_PLAY, 0); if (hdl == NULL) end_all("Error opening audio device"); realpos = 0; sio_onmove(hdl, movecb, NULL); sio_initpar(&par); if (f) par.rate = f; par.pchan = 2; if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par) || !sio_start(hdl) || (par.bits != 8 && par.bits != 16) || par.pchan > 2) end_all("Sorry, no audio format supported by this binary is available"); buf_max = par.appbufsz * par.bps * par.pchan; current_freq = par.rate; stereo = par.pchan == 2 ? 1 : 0; dsp_samplesize = par.bits; dsize = par.bps; buffer = malloc(buf_max); buffer16 = (short *)buffer; idx = 0; samples_max = buf_max / dsize / par.pchan; set_watched_scalar(FREQUENCY, current_freq); total = 0; return current_freq; }
void dev_sio_start(struct dev *d) { if (!sio_start(d->sio.hdl)) { if (log_level >= 1) { dev_log(d); log_puts(": failed to start device\n"); } return; } if (d->mode & MODE_PLAY) { d->sio.cstate = DEV_SIO_CYCLE; d->sio.todo = 0; } else { d->sio.cstate = DEV_SIO_READ; d->sio.todo = d->round * d->rchan * d->par.bps; } #ifdef DEBUG d->sio.pused = 0; d->sio.rused = 0; d->sio.sum_utime = 0; d->sio.sum_wtime = 0; d->sio.wtime = file_wtime; d->sio.utime = file_utime; if (log_level >= 3) { dev_log(d); log_puts(": started\n"); } #endif timo_add(&d->sio.watchdog, WATCHDOG_USEC); }
bool CAESinkSNDIO::Initialize(AEAudioFormat &format, std::string &device) { if ((m_hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0)) == nullptr) { CLog::Log(LOGERROR, "CAESinkSNDIO::Initialize - Failed to open device"); return false; } AudioFormatToPar(format); if (!sio_setpar(m_hdl, &m_par) || !sio_getpar(m_hdl, &m_par) || !ParToAudioFormat(format)) { CLog::Log(LOGERROR, "CAESinkSNDIO::Initialize - could not negotiate parameters"); return false; } m_played = m_written = 0; sio_onmove(m_hdl, CAESinkSNDIO::OnmoveCb, this); if (!sio_start(m_hdl)) { CLog::Log(LOGERROR, "CAESinkSNDIO::Initialize - sio_start failed"); return false; } return true; }
static int sndio_unpause(void) { if (sndio_paused) { if (!sio_start(hdl)) return -OP_ERROR_INTERNAL; sndio_paused = 0; } return OP_ERROR_SUCCESS; }
void CAESinkSNDIO::Drain() { if(!m_hdl) return; if (!sio_stop(m_hdl) || !sio_start(m_hdl)) CLog::Log(LOGERROR, "CAESinkSNDIO::Drain - failed"); m_written = m_played = 0; }
/* * stop playing and empty buffers (for seeking/pause) */ static void reset(struct ao *ao) { struct priv *p = ao->priv; if (!sio_stop(p->hdl)) MP_ERR(ao, "reset: couldn't stop\n"); p->delay = 0; if (!sio_start(p->hdl)) MP_ERR(ao, "reset: couldn't start\n"); }
static int sndio_set_sf(sample_format_t sf) { struct sio_par apar; sndio_sf = sf; sio_initpar(&par); par.pchan = sf_get_channels(sndio_sf); par.rate = sf_get_rate(sndio_sf); sndio_paused = 0; if (sf_get_signed(sndio_sf)) par.sig = 1; else par.sig = 0; if (sf_get_bigendian(sndio_sf)) par.le = 0; else par.le = 1; switch (sf_get_bits(sndio_sf)) { case 16: par.bits = 16; break; case 8: par.bits = 8; break; default: return -OP_ERROR_SAMPLE_FORMAT; } par.appbufsz = par.rate * 300 / 1000; apar = par; if (!sio_setpar(hdl, &par)) return -OP_ERROR_INTERNAL; if (!sio_getpar(hdl, &par)) return -OP_ERROR_INTERNAL; if (apar.rate != par.rate || apar.pchan != par.pchan || apar.bits != par.bits || (par.bits > 8 && apar.le != par.le) || apar.sig != par.sig) return -OP_ERROR_INTERNAL; sndio_mixer_set_volume(sndio_volume, sndio_volume); if (!sio_start(hdl)) return -OP_ERROR_INTERNAL; return OP_ERROR_SUCCESS; }
static int open_output(void) { static struct sio_par par, newpar; sndio_ctx = sio_open(NULL, SIO_PLAY, 0); if (sndio_ctx == NULL) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_open() failed"); return -1; } sio_initpar(&par); par.sig = 1; par.pchan = (dpm.encoding & PE_MONO) ? 1 : 2; par.le = SIO_LE_NATIVE; par.rate = dpm.rate; if (dpm.encoding & PE_24BIT) { par.bits = 24; par.bps = 3; } else if (dpm.encoding & PE_16BIT) { par.bits = 16; par.bps = 2; } else { par.bits = 8; par.bps = 1; } if (!sio_setpar(sndio_ctx, &par)) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_setpar() failed"); return -1; } if (sio_getpar(sndio_ctx, &newpar) == 0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_getpar() failed"); return -1; } if (newpar.sig != par.sig || newpar.le != par.le || newpar.pchan != par.pchan || newpar.bits != par.bits || newpar.bps != par.bps || newpar.rate * 1000 > par.rate * 1005 || newpar.rate * 1000 < par.rate * 995) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "couldn't set output play parameters"); return -1; } if (!sio_start(sndio_ctx)) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sio_start() failed"); return -1; } return 0; }
int audio_init(int argc, char *argv[]) { int rate_set = 0; int use_audio = 1; prog = argv[0]; argc = getargs("OpenBSD Audio",argc, argv, "r", "%d", &rate_set, "Sample rate", "a", NULL, &use_audio, "Audio enable", NULL); if (help_only) return argc; if (rate_set) samp_rate = rate_set; if (!use_audio) return argc; audio_open(); sio_initpar(&par); par.bits = 16; par.sig = 1; par.rate = samp_rate; par.pchan = 1; if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) { fprintf(stderr, "error setting sndio parameters\n"); hdl = NULL; } else { if (par.bits != 16 || par.sig != 1 || par.pchan != 1 || par.rate != samp_rate) { fprintf(stderr, "returned incorrect sndio parameters\n"); hdl = NULL; } } if (hdl && !sio_start(hdl)) { fprintf(stderr, "error starting sndio\n"); hdl = NULL; } return argc; }
static void sndio_play (int argc, char *argv []) { struct sio_hdl *hdl ; struct sio_par par ; short buffer [BUFFER_LEN] ; SNDFILE *sndfile ; SF_INFO sfinfo ; int k, readcount ; for (k = 1 ; k < argc ; k++) { printf ("Playing %s\n", argv [k]) ; if (! (sndfile = sf_open (argv [k], SFM_READ, &sfinfo))) { puts (sf_strerror (NULL)) ; continue ; } ; if (sfinfo.channels < 1 || sfinfo.channels > 2) { printf ("Error : channels = %d.\n", sfinfo.channels) ; continue ; } ; if ((hdl = sio_open (NULL, SIO_PLAY, 0)) == NULL) { fprintf (stderr, "open sndio device failed") ; return ; } ; sio_initpar (&par) ; par.rate = sfinfo.samplerate ; par.pchan = sfinfo.channels ; par.bits = 16 ; par.sig = 1 ; par.le = SIO_LE_NATIVE ; if (! sio_setpar (hdl, &par) || ! sio_getpar (hdl, &par)) { fprintf (stderr, "set sndio params failed") ; return ; } ; if (! sio_start (hdl)) { fprintf (stderr, "sndio start failed") ; return ; } ; while ((readcount = sf_read_short (sndfile, buffer, BUFFER_LEN))) sio_write (hdl, buffer, readcount * sizeof (short)) ; sio_close (hdl) ; } ; return ; } /* sndio_play */
int SndioSink::setAudioConfiguration(const AudioConfiguration* config) { d->config = *config; if (d->valid) sio_stop(d->hdl); sio_initpar(&d->par); if (config->sample_width < 0) { d->par.bits = 16; d->par.sig = 1; } else { d->par.bits = config->sample_width; if (d->par.bits == 8) d->par.sig = 0; else d->par.sig = 1; } d->par.pchan = config->channels; d->par.rate = config->sample_rate; if (!sio_setpar(d->hdl, &d->par)) { d->valid = false; return -1; } if (!sio_getpar(d->hdl, &d->par)) { d->valid = false; return -1; } d->config.sample_width = d->par.bits; d->config.sample_rate = d->par.rate; d->config.channels = d->par.pchan; if (d->config.channels <= 2) d->config.channel_config = MonoStereo; if (!sio_start(d->hdl)) { std::cerr << "akode: could not restart sndio device\n"; d->valid = false; return -1; } if (d->config == *config) return 0; else return 1; }
static int init (struct xmp_context *ctx) { struct sio_par par, askpar; struct xmp_options *opt = &ctx->o; hdl = sio_open (NULL, SIO_PLAY, 0); if (hdl == NULL) { fprintf (stderr, "%s: failed to open audio device\n", __func__); return XMP_ERR_DINIT; } sio_initpar (&par); par.pchan = opt->outfmt & XMP_FMT_MONO ? 1 : 2; par.rate = opt->freq; par.bits = opt->resol; par.sig = opt->resol > 8 ? 1 : 0; par.le = SIO_LE_NATIVE; par.appbufsz = par.rate / 4; askpar = par; if (!sio_setpar (hdl, &par) || !sio_getpar (hdl, &par)) { fprintf (stderr, "%s: failed to set parameters\n", __func__); goto error; } if ((par.bits == 16 && par.le != askpar.le) || par.bits != askpar.bits || par.sig != askpar.sig || par.pchan != askpar.pchan || ((par.rate * 1000 < askpar.rate * 995) || (par.rate * 1000 > askpar.rate * 1005))) { fprintf (stderr, "%s: parameters not supported\n", __func__); goto error; } if (!sio_start (hdl)) { fprintf (stderr, "%s: failed to start audio device\n", __func__); goto error; } return xmp_smix_on (ctx); error: sio_close (hdl); return XMP_ERR_DINIT; }
/* * stop playing and empty buffers (for seeking/pause) */ static void reset(struct ao *ao) { struct priv *p = ao->priv; if (p->playing) { MP_WARN(ao, "Blocking until remaining audio is played... (sndio design bug).\n"); p->playing = false; if (!sio_stop(p->hdl)) MP_ERR(ao, "reset: couldn't stop\n"); p->delay = 0; if (!sio_start(p->hdl)) MP_ERR(ao, "reset: couldn't start\n"); } }
int sa_stream_open(sa_stream_t *s) { struct sio_hdl *handle; struct sio_par par; if (s == NULL) return SA_ERROR_NO_INIT; if (s->handle != NULL) return SA_ERROR_INVALID; handle = sio_open(NULL, SIO_PLAY, 0); if (handle == NULL) return SA_ERROR_NO_DEVICE; sio_initpar(&par); par.bits = s->format; par.le = SIO_LE_NATIVE; par.pchan = s->channels; par.rate = s->rate; par.sig = 1; if (!sio_setpar(handle, &par) || !sio_getpar(handle, &par)) { sio_close(handle); return SA_ERROR_NOT_SUPPORTED; } if (par.bits != s->format || par.le != SIO_LE_NATIVE || par.pchan != s->channels || par.rate != s->rate || par.sig != 1) { sio_close(handle); return SA_ERROR_NOT_SUPPORTED; } sio_onmove(handle, onmove_callback, s); if (!sio_start(handle)) { sio_close(handle); return SA_ERROR_NOT_SUPPORTED; } s->bpf = par.pchan * par.bps; s->buffer = par.bufsz * s->bpf; s->handle = handle; return SA_SUCCESS; }
static void *write_thread(void *arg) { struct auplay_st *st = arg; if (!sio_start(st->hdl)) { warning("sndio: could not start playback\n"); goto out; } while (st->run) { st->wh(st->sampv, st->sampc, st->arg); sio_write(st->hdl, st->sampv, st->sampc*2); } out: return NULL; }
static void *read_thread(void *arg) { struct ausrc_st *st = arg; if (!sio_start(st->hdl)) { warning("sndio: could not start record\n"); goto out; } while (st->run) { size_t n = sio_read(st->hdl, st->sampv, st->sampc*2); st->rh(st->sampv, n/2, st->arg); } out: return NULL; }
static void swfdec_playback_stream_start (Stream *stream) { if (!stream->started) { stream->offset = 0; if (!sio_start (stream->hdl)) { g_printerr("Could not start sndio\n"); return; } stream->started = 1; swfdec_playback_stream_install_handlers (stream); } else { g_printerr("Called _stream_start but already started\n"); } }
bool SndioSink::open() { d->hdl = ::sio_open(NULL, SIO_PLAY, 0); if (d->hdl == NULL) { std::cerr << "akode: could not open sndio device\n"; goto failed; } if (!sio_start(d->hdl)) { std::cerr << "akode: could not start sndio device\n"; goto failed; } d->valid = true; return true; failed: d->valid = false; return false; }
static PaError StartStream(PaStream *stream) { PaSndioStream *s = (PaSndioStream *)stream; unsigned primes, wblksz; int err; DPR("StartStream: s=%d, a=%d\n", s->stopped, s->active); if (!s->stopped) { DPR("StartStream: already started\n"); return paNoError; } s->stopped = 0; s->active = 1; s->realpos = 0; s->wpos = 0; s->rpos = 0; PaUtil_ResetBufferProcessor(&s->bufproc); if (!sio_start(s->hdl)) return paUnanticipatedHostError; /* * send a complete buffer of silence */ if (s->mode & SIO_PLAY) { wblksz = s->par.round * s->par.pchan * s->par.bps; memset(s->wbuf, 0, wblksz); for (primes = s->par.bufsz / s->par.round; primes > 0; primes--) s->wpos += sio_write(s->hdl, s->wbuf, wblksz); } if (s->base.streamCallback) { err = pthread_create(&s->thread, NULL, sndioThread, s); if (err) { DPR("SndioStartStream: couldn't create thread\n"); return paUnanticipatedHostError; } DPR("StartStream: started...\n"); } return paNoError; }
static ALCboolean sndio_start_playback(ALCdevice *device) { sndio_data *data = device->ExtraData; if(!sio_start(data->sndHandle)) { ERR("Error starting playback\n"); return ALC_FALSE; } data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); data->mix_data = calloc(1, data->data_size); if(!StartThread(&data->thread, sndio_proc, device)) { sio_stop(data->sndHandle); free(data->mix_data); data->mix_data = NULL; return ALC_FALSE; } return ALC_TRUE; }
void audioInit(int sampleSize, int frequency, int stereo, int sign, int big) { sio_initpar(&par); par.bits = sampleSize; par.sig = sign ? 1 : 0; par.le = big ? 0 : 1; par.rate = frequency; par.pchan = stereo ? 2 : 1; if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) fprintf(stderr, "error setting sndio parameters\n"); if (par.bits != sampleSize || par.sig != sign ? 1 : 0 || par.le != big ? 0 : 1 || par.rate != frequency || par.pchan != stereo ? 2 : 1) fprintf(stderr, "could not set requested audio parameters"); if (!sio_start(hdl)) fprintf(stderr, "could not start audio"); }
static void * sndio_mainloop(void *arg) { #define MAXFDS 8 struct pollfd pfds[MAXFDS]; cubeb_stream *s = arg; int n, eof = 0, prime, nfds, events, revents, state = CUBEB_STATE_STARTED; size_t pstart = 0, pend = 0, rstart = 0, rend = 0; long nfr; DPR("sndio_mainloop()\n"); s->state_cb(s, s->arg, CUBEB_STATE_STARTED); pthread_mutex_lock(&s->mtx); if (!sio_start(s->hdl)) { pthread_mutex_unlock(&s->mtx); return NULL; } DPR("sndio_mainloop(), started\n"); if (s->mode & SIO_PLAY) { pstart = pend = s->nfr * s->pbpf; prime = s->nblks; if (s->mode & SIO_REC) { memset(s->rbuf, 0, s->nfr * s->rbpf); rstart = rend = s->nfr * s->rbpf; } } else { prime = 0; rstart = 0; rend = s->nfr * s->rbpf; } for (;;) { if (!s->active) { DPR("sndio_mainloop() stopped\n"); state = CUBEB_STATE_STOPPED; break; } /* do we have a complete block? */ if ((!(s->mode & SIO_PLAY) || pstart == pend) && (!(s->mode & SIO_REC) || rstart == rend)) { if (eof) { DPR("sndio_mainloop() drained\n"); state = CUBEB_STATE_DRAINED; break; } if ((s->mode & SIO_REC) && s->conv) s16_to_float(s->rbuf, s->nfr * s->rchan); /* invoke call-back, it returns less that s->nfr if done */ pthread_mutex_unlock(&s->mtx); nfr = s->data_cb(s, s->arg, s->rbuf, s->pbuf, s->nfr); pthread_mutex_lock(&s->mtx); if (nfr < 0) { DPR("sndio_mainloop() cb err\n"); state = CUBEB_STATE_ERROR; break; } s->swpos += nfr; /* was this last call-back invocation (aka end-of-stream) ? */ if (nfr < s->nfr) { if (!(s->mode & SIO_PLAY) || nfr == 0) { state = CUBEB_STATE_DRAINED; break; } /* need to write (aka drain) the partial play block we got */ pend = nfr * s->pbpf; eof = 1; } if (prime > 0) prime--; if ((s->mode & SIO_PLAY) && s->conv) float_to_s16(s->pbuf, nfr * s->pchan); if (s->mode & SIO_REC) rstart = 0; if (s->mode & SIO_PLAY) pstart = 0; } events = 0; if ((s->mode & SIO_REC) && rstart < rend && prime == 0) events |= POLLIN; if ((s->mode & SIO_PLAY) && pstart < pend) events |= POLLOUT; nfds = sio_pollfd(s->hdl, pfds, events); if (nfds > 0) { pthread_mutex_unlock(&s->mtx); n = poll(pfds, nfds, -1); pthread_mutex_lock(&s->mtx); if (n < 0) continue; } revents = sio_revents(s->hdl, pfds); if (revents & POLLHUP) { state = CUBEB_STATE_ERROR; break; } if (revents & POLLOUT) { n = sio_write(s->hdl, s->pbuf + pstart, pend - pstart); if (n == 0 && sio_eof(s->hdl)) { DPR("sndio_mainloop() werr\n"); state = CUBEB_STATE_ERROR; break; } pstart += n; } if (revents & POLLIN) { n = sio_read(s->hdl, s->rbuf + rstart, rend - rstart); if (n == 0 && sio_eof(s->hdl)) { DPR("sndio_mainloop() rerr\n"); state = CUBEB_STATE_ERROR; break; } rstart += n; } /* skip rec block, if not recording (yet) */ if (prime > 0 && (s->mode & SIO_REC)) rstart = rend; } sio_stop(s->hdl); s->hwpos = s->swpos; pthread_mutex_unlock(&s->mtx); s->state_cb(s, s->arg, state); return NULL; }
int main(int argc, char **argv) { int ch; int tty; struct sio_hdl *hdl; struct termios tio; struct pollfd pfd[2]; char cmd; ssize_t n, len; /* * defaults parameters */ sio_initpar(&par); par.sig = 1; par.bits = 16; par.pchan = 2; par.rate = 44100; if (isatty(STDIN_FILENO)) { fprintf(stderr, "stdin can't be a tty\n"); exit(1); } tty = open("/dev/tty", O_RDWR); if (tty < 0) { perror("/dev/tty"); exit(1); } if (tcgetattr(tty, &tio) < 0) { perror("tcsetattr"); exit(1); } tio.c_lflag &= ~ICANON; tio.c_lflag &= ~ECHO; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; if (tcsetattr(tty, TCSAFLUSH, &tio) < 0) { perror("tcsetattr"); exit(1); } while ((ch = getopt(argc, argv, "r:c:e:b:x:")) != -1) { switch(ch) { case 'r': if (sscanf(optarg, "%u", &par.rate) != 1) { fprintf(stderr, "%s: bad rate\n", optarg); exit(1); } break; case 'c': if (sscanf(optarg, "%u", &par.pchan) != 1) { fprintf(stderr, "%s: bad channels\n", optarg); exit(1); } break; case 'e': if (!sio_strtoenc(&par, optarg)) { fprintf(stderr, "%s: bad encoding\n", optarg); exit(1); } break; default: usage(); exit(1); break; } } hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0); if (hdl == NULL) { fprintf(stderr, "sio_open() failed\n"); exit(1); } if (!sio_setpar(hdl, &par)) { fprintf(stderr, "sio_setpar() failed\n"); exit(1); } if (!sio_onvol(hdl, onvol, NULL)) fprintf(stderr, "warning: no volume knob on this device\n"); fprintf(stderr, "use ``+'' and ``-'' to adjust the volume\n"); if (!sio_start(hdl)) { fprintf(stderr, "sio_start() failed\n"); exit(1); } for (;;) { pfd[0].fd = tty; pfd[0].events = POLLIN; sio_pollfd(hdl, &pfd[1], POLLOUT); if (poll(pfd, 2, -1) < 0) { perror("poll"); exit(1); } if (pfd[0].revents & POLLIN) { if (read(tty, &cmd, 1) < 0) { perror("read(tty)"); exit(1); } switch (cmd) { case '+': if (vol < SIO_MAXVOL) { vol++; sio_setvol(hdl, vol); } break; case '-': if (vol > 0) { vol--; sio_setvol(hdl, vol); } break; } } if (sio_revents(hdl, &pfd[1]) & POLLOUT) { len = read(STDIN_FILENO, buf, BUFSZ); if (len < 0) { perror("stdin"); exit(1); } if (len == 0) break; n = sio_write(hdl, buf, len); if (n == 0) { fprintf(stderr, "sio_write: failed\n"); exit(1); } } } sio_close(hdl); return 0; }
static void * sndio_mainloop(void *arg) { #define MAXFDS 8 struct pollfd pfds[MAXFDS]; cubeb_stream *s = arg; int n, nfds, revents, state = CUBEB_STATE_STARTED; size_t start = 0, end = 0; long nfr; DPR("sndio_mainloop()\n"); s->state_cb(s, s->arg, CUBEB_STATE_STARTED); pthread_mutex_lock(&s->mtx); if (!sio_start(s->hdl)) { pthread_mutex_unlock(&s->mtx); return NULL; } DPR("sndio_mainloop(), started\n"); start = end = s->nfr; for (;;) { if (!s->active) { DPR("sndio_mainloop() stopped\n"); state = CUBEB_STATE_STOPPED; break; } if (start == end) { if (end < s->nfr) { DPR("sndio_mainloop() drained\n"); state = CUBEB_STATE_DRAINED; break; } pthread_mutex_unlock(&s->mtx); nfr = s->data_cb(s, s->arg, NULL, s->buf, s->nfr); pthread_mutex_lock(&s->mtx); if (nfr < 0) { DPR("sndio_mainloop() cb err\n"); state = CUBEB_STATE_ERROR; break; } if (s->conv) float_to_s16(s->buf, nfr * s->pchan); start = 0; end = nfr * s->bpf; } if (end == 0) continue; nfds = sio_pollfd(s->hdl, pfds, POLLOUT); if (nfds > 0) { pthread_mutex_unlock(&s->mtx); n = poll(pfds, nfds, -1); pthread_mutex_lock(&s->mtx); if (n < 0) continue; } revents = sio_revents(s->hdl, pfds); if (revents & POLLHUP) break; if (revents & POLLOUT) { n = sio_write(s->hdl, s->buf + start, end - start); if (n == 0) { DPR("sndio_mainloop() werr\n"); state = CUBEB_STATE_ERROR; break; } s->wrpos += n; start += n; } } sio_stop(s->hdl); s->rdpos = s->wrpos; pthread_mutex_unlock(&s->mtx); s->state_cb(s, s->arg, state); return NULL; }
/* * 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; }
/* * Open the audio device for writing to. */ static int ao_sndio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int mode) { sndio_driver_t *this = (sndio_driver_t *) this_gen; struct sio_par par; xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_sndio_out: ao_sndio_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); if (this->hdl != NULL) { sio_close (this->hdl); this->hdl = NULL; } this->hdl = sio_open(NULL, SIO_PLAY, 0); if (this->hdl == NULL) goto bad; sio_initpar(&par); switch (mode) { case AO_CAP_MODE_MONO: par.pchan = 1; break; case AO_CAP_MODE_STEREO: par.pchan = 2; break; #if 0 case AO_CAP_MODE_4CHANNEL: par.pchan = 4; break; case AO_CAP_MODE_4_1CHANNEL: case AO_CAP_MODE_5CHANNEL: case AO_CAP_MODE_5_1CHANNEL: par.pchan = 6; break; #endif default: xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_sndio_out: ao_sndio_open does not support the requested mode: 0x%X\n", mode); goto bad; } switch (bits) { case 8: par.bits = 8; par.sig = 0; break; case 16: par.bits = 16; par.sig = 1; break; default: xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_sndio_out: ao_sndio_open bits per sample not supported: %d\n", bits); goto bad; } par.rate = rate; par.appbufsz = par.rate * 250 / 1000; /* 250ms buffer */ if (!sio_setpar(this->hdl, &par)) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_sndio_out: ao_sndio_open could not set params\n"); goto bad; } if (!sio_getpar(this->hdl, &par)) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_sndio_out: ao_sndio_open could not get params\n"); goto bad; } xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_sndio_out: ao_sndio_open %d channels output\n", par.pchan); this->num_channels = par.pchan; this->bytes_per_frame = par.bps * par.pchan; this->playpos = 0; this->realpos = 0; sio_onmove(this->hdl, ao_sndio_onmove_cb, this); if (!sio_start(this->hdl)) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_sndio_out: ao_sndio_open could not start\n"); goto bad; } return par.rate; bad: if (this->hdl != NULL) sio_close(this->hdl); return 0; }