/* * convert sndio encoding to PA encoding, return true on success */ static int sndioGetFmt(struct sio_par *sio, PaSampleFormat *fmt) { if ((sio->bps * 8 != sio->bits && !sio->msb) || (sio->bps > 1 && sio->le != SIO_LE_NATIVE)) { DPR("sndioGetFmt: bits = %u, le = %u, msb = %u, bps = %u\n", sio->bits, sio->le, sio->msb, sio->bps); return 0; } switch (sio->bits) { case 32: if (!sio->sig) return 0; *fmt = paInt32; break; case 24: if (!sio->sig) return 0; *fmt = (sio->bps == 3) ? paInt24 : paInt32; break; case 16: if (!sio->sig) return 0; *fmt = paInt16; break; case 8: *fmt = sio->sig ? paInt8 : paUInt8; break; default: DPR("sndioGetFmt: %u: unsupported\n", sio->bits); return 0; } return 1; }
static PaError StopStream(PaStream *stream) { PaSndioStream *s = (PaSndioStream *)stream; void *ret; int err; DPR("StopStream: s=%d, a=%d\n", s->stopped, s->active); if (s->stopped) { DPR("StartStream: already started\n"); return paNoError; } s->stopped = 1; if (s->base.streamCallback) { err = pthread_join(s->thread, &ret); if (err) { DPR("SndioStop: couldn't join thread\n"); return paUnanticipatedHostError; } } if (!sio_stop(s->hdl)) return paUnanticipatedHostError; return paNoError; }
void ximsWaitDone() { int ret; UserSelection *sel = &userSel; DPR(("ximsWaitDone():\tOpState=%s OpErrCode=%s[%d]\n", StateName(), error_name(OpErrCode), OpErrCode)); set_sig_chld(False); ret = sel->renv->status; switch (ret) { case ErrImsWaiting: sel->status = ErrImsTimeout; put_xims_log("'%s' timed-out.", sel->name, 0, 0); break; case ErrImsWaitDone: sel->status = NoError; # ifdef old_hpux if ((OpFlag & FLAG_CONNECT) || (sel->ent->ims->flags & F_TRY_CONNECT)) { sel->status = try_connection(sel); } # endif /* old_hpux */ break; case ErrImsConnecting: case ErrImsConnectDone: sel->status = NoError; break; case ErrImsAborted: /* put_xims_log("'%s' aborted.", sel->name, 0, 0); */ case ErrImsExecution: default: sel->status = ret; break; } if (sel->status != NoError) { OpErrCode = sel->status; DPR(("ximsWaitDone(): OpErrCode=%s[%d]\n", error_name(OpErrCode), OpErrCode)); } restore_resources(); settle_ims(sel); /* clear WM_COMMAND property */ OpState = OpErrCode == NoError ? State_Wait_Done : State_Wait_Err; ximsMain(); }
void ximsWait() { OpStateVal oldOpState = OpState; UserSelection *sel = &userSel; struct timeval interval; time_t start_tm = 0; int lapse; DPR(("ximsWait(): OpState=%s OpErrCode=%s[%d]\n", StateName(), error_name(OpErrCode), OpErrCode)); OpState = State_Wait; if (oldOpState == State_Start_Err) { /* don't change OpErrCode */ OpState = State_Wait_Err; return; } if (!is_waiting() || (OpFlag & FLAG_NOWAIT)) { ximsWaitDone(); } if (im_mod_available(sel->renv) != 1) { if (useWINDOW()) { xt_start_waiting(); /* never returns unless failed */ } /* waiting */ lapse = 0; interval.tv_sec = Opt.Interval / 1000; interval.tv_usec = (Opt.Interval % 1000) * 1000; start_tm = time((time_t) 0); while (is_waiting()) { select(0, 0, 0, 0, &interval); /* usleep */ lapse = (int) time((time_t) 0) - start_tm; if (im_mod_available(sel->renv) != 0 || lapse >= Opt.Timeout) { DPR(("ximsWait(tmout=%d): wait done (%d sec.)\n", Opt.Timeout, lapse)); break; } } } ximsWaitDone(); }
static PaError AbortStream(PaStream *stream) { DPR("AbortStream:\n"); return StopStream(stream); }
/* * convert PA encoding to sndio encoding, return true on success */ static int sndioSetFmt(struct sio_par *sio, PaSampleFormat fmt) { switch (fmt & ~paNonInterleaved) { case paInt32: sio->sig = 1; sio->bits = 32; break; case paInt24: sio->sig = 1; sio->bits = 24; sio->bps = 3; /* paInt24 is packed format */ break; case paInt16: case paFloat32: sio->sig = 1; sio->bits = 16; break; case paInt8: sio->sig = 1; sio->bits = 8; break; case paUInt8: sio->sig = 0; sio->bits = 8; break; default: DPR("sndioSetFmt: %x: unsupported\n", fmt); return 0; } sio->le = SIO_LE_NATIVE; return 1; }
static int sunaudio_stream_get_position(cubeb_stream *s, uint64_t *p) { int rv = CUBEB_OK; pthread_mutex_lock(&s->mutex); if (s->active && s->fd > 0) { if (s->using_oss) { int delay; ioctl(s->fd, SNDCTL_DSP_GETODELAY, &delay); int64_t t = s->frm_played - delay / s->n_channles / 2; if (t < 0) { *p = 0; } else { *p = t; } } else { audio_info_t info; ioctl(s->fd, AUDIO_GETINFO, &info); *p = info.play.samples; } DPR("sunaudio_stream_get_position() %lld\n", *p); } else { rv = CUBEB_ERROR; } pthread_mutex_unlock(&s->mutex); return rv; }
static void sndio_stream_destroy(cubeb_stream *s) { DPR("sndio_stream_destroy()\n"); sio_close(s->hdl); free(s); }
static PaError BlockingWriteStream(PaStream* stream, const void *data, unsigned long numFrames) { PaSndioStream *s = (PaSndioStream *)stream; unsigned n, res; while (numFrames > 0) { n = s->par.round; if (n > numFrames) n = numFrames; PaUtil_SetOutputFrameCount(&s->bufproc, n); PaUtil_SetInterleavedOutputChannels(&s->bufproc, 0, s->wbuf, s->par.pchan); res = PaUtil_CopyOutput(&s->bufproc, &data, n); if (res != n) { DPR("BlockingWriteStream: copyOutput: %u != %u\n"); return paUnanticipatedHostError; } res = sio_write(s->hdl, s->wbuf, n * s->par.pchan * s->par.bps); if (res == 0) return paUnanticipatedHostError; s->wpos += n; numFrames -= n; } return paNoError; }
static PaError BlockingReadStream(PaStream *stream, void *data, unsigned long numFrames) { PaSndioStream *s = (PaSndioStream *)stream; unsigned n, res, todo; void *buf; while (numFrames > 0) { n = s->par.round; if (n > numFrames) n = numFrames; buf = s->rbuf; todo = n * s->par.rchan * s->par.bps; while (todo > 0) { res = sio_read(s->hdl, buf, todo); if (res == 0) return paUnanticipatedHostError; buf = (char *)buf + res; todo -= res; } s->rpos += n; PaUtil_SetInputFrameCount(&s->bufproc, n); PaUtil_SetInterleavedInputChannels(&s->bufproc, 0, s->rbuf, s->par.rchan); res = PaUtil_CopyInput(&s->bufproc, &data, n); if (res != n) { DPR("BlockingReadStream: copyInput: %u != %u\n"); return paUnanticipatedHostError; } numFrames -= n; } return paNoError; }
Transport::Transport(TransportType t, City* origin, City* destination, const QList<quint16> passengers, QObject *parent) : QObject(parent), m_origin(origin), m_destination(destination), m_position(origin->getPosition()), m_type(t), m_speed(TRANSPORT_SPEEDS[t]), m_travelTimeLeft((m_position.distanceTo(m_destination->getPosition()) / m_speed) * 60 * 60) // travel time in seconds { Q_ASSERT_X(passengers.size() == PT_MAX_TYPES, Q_FUNC_INFO, "Amount of passenger types must be exactly PT_MAX_TYPES"); this->setObjectName(TRANSPORT_NAMES[m_type] % "-" % QString::number(s_transportId++)); for(int i = 0; i < PT_MAX_TYPES; ++i) { m_passengers[i] = passengers.at(i); CDPR(tr("Passenger type %1, amount %2").arg(PASSENGER_TYPE_NAMES[i]). arg(m_passengers[i])); } DPR(tr("Transport %1 speed %2 from %3 to %4 (%5->%6). ETA %7 (%8s)"). arg(objectName()). arg(m_speed). arg(m_origin->getName()). arg(m_destination->getName()). arg(m_position.toString()). arg(m_destination->getPosition().toString()). arg(m_travelTimeLeft.toString()). arg(m_travelTimeLeft.toSeconds())); }
/* * Given a specific type of board, if found, detached link and * returns the first occurrence in the list. */ struct cnode *dgap_find_config(int type, int bus, int slot) { struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL; p = &dgap_head; while (p->next != NULL) { prev = p; p = p->next; if (p->type == BNODE) { if (p->u.board.type == type) { if (p->u.board.v_pcibus && p->u.board.pcibus != bus) { DPR(("Found matching board, but wrong bus position. System says bus %d, we want bus %ld\n", bus, p->u.board.pcibus)); continue; } if (p->u.board.v_pcislot && p->u.board.pcislot != slot) { DPR_INIT(("Found matching board, but wrong slot position. System says slot %d, we want slot %ld\n", slot, p->u.board.pcislot)); continue; } DPR_INIT(("Matched type in config file\n")); found = p; /* * Keep walking thru the list till we find the next board. */ while (p->next != NULL) { prev2 = p; p = p->next; if (p->type == BNODE) { /* * Mark the end of our 1 board chain of configs. */ prev2->next = NULL; /* * Link the "next" board to the previous board, * effectively "unlinking" our board from the main config. */ prev->next = p; return found; } } /* * It must be the last board in the list. */ prev->next = NULL; return found; } } } return NULL; }
static int sndio_stream_get_position(cubeb_stream *s, uint64_t *p) { pthread_mutex_lock(&s->mtx); DPR("sndio_stream_get_position() %" PRId64 "\n", s->hwpos); *p = s->hwpos; pthread_mutex_unlock(&s->mtx); return CUBEB_OK; }
/*static*/ int sndio_init(cubeb **context, char const *context_name) { DPR("sndio_init(%s)\n", context_name); *context = malloc(sizeof(*context)); (*context)->ops = &sndio_ops; (void)context_name; return CUBEB_OK; }
static int sndio_stream_set_volume(cubeb_stream *s, float volume) { DPR("sndio_stream_set_volume(%f)\n", volume); pthread_mutex_lock(&s->mtx); sio_setvol(s->hdl, SIO_MAXVOL * volume); pthread_mutex_unlock(&s->mtx); return CUBEB_OK; }
static int sndio_stream_get_position(cubeb_stream *s, uint64_t *p) { pthread_mutex_lock(&s->mtx); DPR("sndio_stream_get_position() %lld\n", s->rdpos); *p = s->rdpos / s->bpf; pthread_mutex_unlock(&s->mtx); return CUBEB_OK; }
static void sndio_stream_destroy(cubeb_stream *s) { DPR("sndio_stream_destroy()\n"); sio_close(s->hdl); if (s->mode & SIO_PLAY) free(s->pbuf); if (s->mode & SIO_REC) free(s->rbuf); free(s); }
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 int sndio_stream_stop(cubeb_stream *s) { void *dummy; DPR("sndio_stream_stop()\n"); if (s->active) { s->active = 0; pthread_join(s->th, &dummy); } return CUBEB_OK; }
static PaError BlockingWaitEmpty( PaStream *stream ) { PaSndioStream *s = (PaSndioStream *)stream; /* * drain playback buffers; sndio always does it in background * and there is no way to wait for completion */ DPR("BlockingWaitEmpty: s=%d, a=%d\n", s->stopped, s->active); return paNoError; }
static int sndio_stream_start(cubeb_stream *s) { int err; DPR("sndio_stream_start()\n"); s->active = 1; err = pthread_create(&s->th, NULL, sndio_mainloop, s); if (err) { s->active = 0; return CUBEB_ERROR; } return CUBEB_OK; }
int ddWrite(int descriptor, int len, int *ev) { BOSIOptr BIOstream; int *bufout; int ifree,error,lenh,lenb,ncop,nfopen,lrlen; int ip,jp,kp; /* Ukazatel` na record segment header i data header v DD bufere */ int dathead[70]; /* intermediate buffers */ char *fmt, *ch; int i; DPR("\nSTART OF ddWrite >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); BIOstream = (BOSIOptr)descriptor; /* set pointers */ bufout = BIOS_BUFP; error = nfopen = 0; lrlen = ev[irNWRD]+RECHEADLEN; if (len < lrlen) { printf("ddWrite: FIFO length (%i) < Event length (%i) -> Corrupted\nReturn EBIO_CORREVENT\n", len,ev[irNWRD]+RECHEADLEN); return EBIO_CORREVENT; } DPR(">>> Got following event ============================================================\n"); PRLR(ev); DPR(">>> ================================================================================\n"); DPR1(">>> At the beginning IP=%i\n",IP); if(IP == 0) /* allocate output buffer */ { DPR1(">>> First time writing -> allocate I/O buffer RECL=%i\n",BIOS_RECL); bufout = BIOS_BUFP = (int *)malloc(BIOS_RECL); BIOS_NPHYSREC = 0; BIOS_NLOGREC = 0; START_NEW_PHYSREC_ }
static void sunaudio_stream_destroy(cubeb_stream *s) { DPR("sunaudio_stream_destroy()\n"); if (s->fd > 0) { // Flush buffer if (s->using_oss) { ioctl(s->fd, SNDCTL_DSP_HALT_OUTPUT); } else { ioctl(s->fd, I_FLUSH); } close(s->fd); } free(s->buf); free(s); }
static PaError CloseStream(PaStream *stream) { PaSndioStream *s = (PaSndioStream *)stream; DPR("CloseStream:\n"); if (!s->stopped) StopStream(stream); if (s->mode & SIO_REC) free(s->rbuf); if (s->mode & SIO_PLAY) free(s->wbuf); sio_close(s->hdl); PaUtil_TerminateStreamRepresentation(&s->base); PaUtil_TerminateBufferProcessor(&s->bufproc); PaUtil_FreeMemory(s); return paNoError; }
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; }
PaError PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex) { PaSndioHostApiRepresentation *sndioHostApi; PaDeviceInfo *info; struct sio_hdl *hdl; DPR("PaSndio_Initialize: initializing...\n"); /* unusable APIs should return paNoError and a NULL hostApi */ *hostApi = NULL; sndioHostApi = PaUtil_AllocateMemory(sizeof(PaSndioHostApiRepresentation)); if (sndioHostApi == NULL) return paNoError; info = &sndioHostApi->default_info; info->structVersion = 2; info->name = "default"; info->hostApi = hostApiIndex; info->maxInputChannels = 128; info->maxOutputChannels = 128; info->defaultLowInputLatency = 0.01; info->defaultLowOutputLatency = 0.01; info->defaultHighInputLatency = 0.5; info->defaultHighOutputLatency = 0.5; info->defaultSampleRate = 48000; sndioHostApi->infos[0] = info; *hostApi = &sndioHostApi->base; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paSndio; (*hostApi)->info.name = "sndio"; (*hostApi)->info.deviceCount = 1; (*hostApi)->info.defaultInputDevice = 0; (*hostApi)->info.defaultOutputDevice = 0; (*hostApi)->deviceInfos = sndioHostApi->infos; (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface(&sndioHostApi->blocking, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, BlockingReadStream, BlockingWriteStream, BlockingGetStreamReadAvailable, BlockingGetStreamWriteAvailable); PaUtil_InitializeStreamInterface(&sndioHostApi->callback, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, PaUtil_DummyRead, PaUtil_DummyWrite, PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable); DPR("PaSndio_Initialize: done\n"); return paNoError; }
static int sndio_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, cubeb_devid input_device, cubeb_stream_params * input_stream_params, cubeb_devid output_device, cubeb_stream_params * output_stream_params, unsigned int latency_frames, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void *user_ptr) { cubeb_stream *s; struct sio_par wpar, rpar; DPR("sndio_stream_init(%s)\n", stream_name); size_t size; assert(!input_stream_params && "not supported."); if (input_device || output_device) { /* Device selection not yet implemented. */ return CUBEB_ERROR_DEVICE_UNAVAILABLE; } s = malloc(sizeof(cubeb_stream)); if (s == NULL) return CUBEB_ERROR; s->context = context; s->hdl = sio_open(NULL, SIO_PLAY, 1); if (s->hdl == NULL) { free(s); DPR("sndio_stream_init(), sio_open() failed\n"); return CUBEB_ERROR; } sio_initpar(&wpar); wpar.sig = 1; wpar.bits = 16; switch (output_stream_params->format) { case CUBEB_SAMPLE_S16LE: wpar.le = 1; break; case CUBEB_SAMPLE_S16BE: wpar.le = 0; break; case CUBEB_SAMPLE_FLOAT32NE: wpar.le = SIO_LE_NATIVE; break; default: DPR("sndio_stream_init() unsupported format\n"); return CUBEB_ERROR_INVALID_FORMAT; } wpar.rate = output_stream_params->rate; wpar.pchan = output_stream_params->channels; wpar.appbufsz = latency_frames; if (!sio_setpar(s->hdl, &wpar) || !sio_getpar(s->hdl, &rpar)) { sio_close(s->hdl); free(s); DPR("sndio_stream_init(), sio_setpar() failed\n"); return CUBEB_ERROR; } if (rpar.bits != wpar.bits || rpar.le != wpar.le || rpar.sig != wpar.sig || rpar.rate != wpar.rate || rpar.pchan != wpar.pchan) { sio_close(s->hdl); free(s); DPR("sndio_stream_init() unsupported params\n"); return CUBEB_ERROR_INVALID_FORMAT; } sio_onmove(s->hdl, sndio_onmove, s); s->active = 0; s->nfr = rpar.round; s->bpf = rpar.bps * rpar.pchan; s->pchan = rpar.pchan; s->data_cb = data_callback; s->state_cb = state_callback; s->arg = user_ptr; s->mtx = PTHREAD_MUTEX_INITIALIZER; s->rdpos = s->wrpos = 0; if (output_stream_params->format == CUBEB_SAMPLE_FLOAT32LE) { s->conv = 1; size = rpar.round * rpar.pchan * sizeof(float); } else { s->conv = 0; size = rpar.round * rpar.pchan * rpar.bps; } s->buf = malloc(size); if (s->buf == NULL) { sio_close(s->hdl); free(s); return CUBEB_ERROR; } *stream = s; DPR("sndio_stream_init() end, ok\n"); (void)context; (void)stream_name; return CUBEB_OK; }
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; }
static void sndio_destroy(cubeb *context) { DPR("sndio_destroy()\n"); free(context); }
static int sndio_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name, cubeb_devid input_device, cubeb_stream_params * input_stream_params, cubeb_devid output_device, cubeb_stream_params * output_stream_params, unsigned int latency_frames, cubeb_data_callback data_callback, cubeb_state_callback state_callback, void *user_ptr) { cubeb_stream *s; struct sio_par wpar, rpar; cubeb_sample_format format; int rate; size_t bps; DPR("sndio_stream_init(%s)\n", stream_name); s = malloc(sizeof(cubeb_stream)); if (s == NULL) return CUBEB_ERROR; memset(s, 0, sizeof(cubeb_stream)); s->mode = 0; if (input_stream_params) { if (input_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) { DPR("sndio_stream_init(), loopback not supported\n"); goto err; } s->mode |= SIO_REC; format = input_stream_params->format; rate = input_stream_params->rate; } if (output_stream_params) { if (output_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK) { DPR("sndio_stream_init(), loopback not supported\n"); goto err; } s->mode |= SIO_PLAY; format = output_stream_params->format; rate = output_stream_params->rate; } if (s->mode == 0) { DPR("sndio_stream_init(), neither playing nor recording\n"); goto err; } s->context = context; s->hdl = sio_open(NULL, s->mode, 1); if (s->hdl == NULL) { DPR("sndio_stream_init(), sio_open() failed\n"); goto err; } sio_initpar(&wpar); wpar.sig = 1; wpar.bits = 16; switch (format) { case CUBEB_SAMPLE_S16LE: wpar.le = 1; break; case CUBEB_SAMPLE_S16BE: wpar.le = 0; break; case CUBEB_SAMPLE_FLOAT32NE: wpar.le = SIO_LE_NATIVE; break; default: DPR("sndio_stream_init() unsupported format\n"); goto err; } wpar.rate = rate; if (s->mode & SIO_REC) wpar.rchan = input_stream_params->channels; if (s->mode & SIO_PLAY) wpar.pchan = output_stream_params->channels; wpar.appbufsz = latency_frames; if (!sio_setpar(s->hdl, &wpar) || !sio_getpar(s->hdl, &rpar)) { DPR("sndio_stream_init(), sio_setpar() failed\n"); goto err; } if (rpar.bits != wpar.bits || rpar.le != wpar.le || rpar.sig != wpar.sig || rpar.rate != wpar.rate || ((s->mode & SIO_REC) && rpar.rchan != wpar.rchan) || ((s->mode & SIO_PLAY) && rpar.pchan != wpar.pchan)) { DPR("sndio_stream_init() unsupported params\n"); goto err; } sio_onmove(s->hdl, sndio_onmove, s); s->active = 0; s->nfr = rpar.round; s->rbpf = rpar.bps * rpar.rchan; s->pbpf = rpar.bps * rpar.pchan; s->rchan = rpar.rchan; s->pchan = rpar.pchan; s->nblks = rpar.bufsz / rpar.round; s->data_cb = data_callback; s->state_cb = state_callback; s->arg = user_ptr; s->mtx = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; s->hwpos = s->swpos = 0; if (format == CUBEB_SAMPLE_FLOAT32LE) { s->conv = 1; bps = sizeof(float); } else { s->conv = 0; bps = rpar.bps; } if (s->mode & SIO_PLAY) { s->pbuf = malloc(bps * rpar.pchan * rpar.round); if (s->pbuf == NULL) goto err; } if (s->mode & SIO_REC) { s->rbuf = malloc(bps * rpar.rchan * rpar.round); if (s->rbuf == NULL) goto err; } *stream = s; DPR("sndio_stream_init() end, ok\n"); (void)context; (void)stream_name; return CUBEB_OK; err: if (s->hdl) sio_close(s->hdl); if (s->pbuf) free(s->pbuf); if (s->rbuf) free(s->pbuf); free(s); return CUBEB_ERROR; }