static int start_rsd(int fd, rsound_t *rd) { int flags = fcntl(fd, F_GETFD); if ( flags < 0 ) return -1; if ( rd->conn.socket == -1 ) { char *ident = "OSS emulation"; rsd_set_param(rd, RSD_IDENTITY, ident); if ( rsd_start(rd) < 0 ) return -1; } // Now we should reroute our socket to fd if ( dup2(rd->conn.socket, fd) < 0 ) return -1; if ( flags & O_NONBLOCK ) { int i = fd2index(fd); if ( i >= 0 ) _rd[i].nonblock = 1; else return -1; } return 0; }
static void *rs_init(const char *device, unsigned rate, unsigned latency) { int channels, format; rsd_t *rsd = (rsd_t*)calloc(1, sizeof(rsd_t)); if (!rsd) return NULL; rsound_t *rd; if (rsd_init(&rd) < 0) { free(rsd); return NULL; } rsd->cond_lock = slock_new(); rsd->cond = scond_new(); rsd->buffer = fifo_new(1024 * 4); channels = 2; format = RSD_S16_NE; rsd_set_param(rd, RSD_CHANNELS, &channels); rsd_set_param(rd, RSD_SAMPLERATE, &rate); rsd_set_param(rd, RSD_LATENCY, &latency); if (device) rsd_set_param(rd, RSD_HOST, (void*)device); rsd_set_param(rd, RSD_FORMAT, &format); rsd_set_callback(rd, rsound_audio_cb, err_cb, 256, rsd); if (rsd_start(rd) < 0) { free(rsd); rsd_free(rd); return NULL; } rsd->rd = rd; return rsd; }
static int init(struct ao *ao) { struct priv *priv = ao->priv; if (rsd_init(&priv->rd) < 0) return -1; if (priv->host && priv->host[0]) rsd_set_param(priv->rd, RSD_HOST, priv->host); if (priv->port && priv->port[0]) rsd_set_param(priv->rd, RSD_PORT, priv->port); // Actual channel layout unknown. struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext_def(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) { rsd_free(priv->rd); return -1; } rsd_set_param(priv->rd, RSD_SAMPLERATE, (int[]) { ao->samplerate });
static int init(struct ao *ao) { struct priv *priv = ao->priv; if (rsd_init(&priv->rd) < 0) return -1; if (priv->host && priv->host[0]) rsd_set_param(priv->rd, RSD_HOST, priv->host); if (priv->port && priv->port[0]) rsd_set_param(priv->rd, RSD_PORT, priv->port); // Actual channel layout unknown. struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext_def(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) { rsd_free(priv->rd); return -1; } rsd_set_param(priv->rd, RSD_SAMPLERATE, &ao->samplerate); rsd_set_param(priv->rd, RSD_CHANNELS, &ao->channels.num); ao->format = af_fmt_from_planar(ao->format); int rsd_format = set_format(ao); rsd_set_param(priv->rd, RSD_FORMAT, &rsd_format); if (rsd_start(priv->rd) < 0) { rsd_free(priv->rd); return -1; } return 0; }
static int open_generic(const char* path, int largefile, int flags, mode_t mode) { if ( path == NULL ) { errno = EFAULT; return -1; } // We should use the OS calls directly. if ( !is_oss_path(path) ) { if ( largefile ) return _os.open64(path, flags, mode); else return _os.open(path, flags, mode); } // Let's fake this call! :D // Search for a vacant fd int i = get_vacant_fd(); if ( i == -1 ) // We couldn't find a vacant fd. return -1; if ( rsd_init(&_rd[i].rd) < 0 ) return -1; // Sets some sane defaults int rate = 44100; int channels = 2; rsd_set_param(_rd[i].rd, RSD_SAMPLERATE, &rate); rsd_set_param(_rd[i].rd, RSD_CHANNELS, &channels); int bufsiz = BUFSIZE; rsd_set_param(_rd[i].rd, RSD_BUFSIZE, &bufsiz); int fds[2]; if ( pipe(fds) < 0 ) { goto error; } _os.close(fds[0]); _rd[i].fd = fds[1]; // Let's check the flags if ( flags & O_NONBLOCK ) { _rd[i].nonblock = 1; if ( fcntl(fds[1], F_SETFL, O_NONBLOCK) < 0 ) { goto error; } } if ( flags & O_RDONLY ) // We do not support this. { errno = EINVAL; goto error; } return fds[1]; error: rsd_free(_rd[i].rd); _rd[i].rd = NULL; _rd[i].fd = -1; _rd[i].nonblock = 0; _rd[i].bytes = 0; return -1; }
int driver_rsound_open (struct roar_vio_calls * inst, char * device, struct roar_audio_info * info, int fh, struct roar_stream_server * sstream) { rsound_t * self; int tmp, tmp2; if ( fh != -1 ) return -1; if ( rsd_init(&self) == -1 ) { ROAR_DBG("driver_rsound_open(*): rsd_init(&self) failed."); return -1; } if ( device != NULL ) { if ( rsd_set_param(self, RSD_HOST, device) == -1 ) { ROAR_DBG("driver_rsound_open(*): rsd_set_param(self, RSD_HOST, device) failed."); rsd_free(self); return -1; } } tmp = info->channels; if ( rsd_set_param(self, RSD_CHANNELS, &tmp) == -1 ) { ROAR_DBG("driver_rsound_open(*): rsd_set_param(self, RSD_CHANNELS, &tmp) failed."); rsd_free(self); return -1; } if ( tmp != info->channels ) { rsd_free(self); return -1; } tmp = info->rate; if ( rsd_set_param(self, RSD_SAMPLERATE, &tmp) == -1 ) { ROAR_DBG("driver_rsound_open(*): rsd_set_param(self, RSD_SAMPLERATE, &tmp) failed."); rsd_free(self); return -1; } if ( tmp != info->rate ) { rsd_free(self); return -1; } tmp = -1; // unknown by RSound switch (info->codec) { case ROAR_CODEC_PCM_S_LE: switch (info->bits) { case 8: tmp = RSD_S8; break; case 16: tmp = RSD_S16_LE; break; } break; case ROAR_CODEC_PCM_S_BE: switch (info->bits) { case 8: tmp = RSD_S8; break; case 16: tmp = RSD_S16_BE; break; } break; case ROAR_CODEC_PCM_S_PDP: switch (info->bits) { case 8: tmp = RSD_S8; break; } break; case ROAR_CODEC_PCM_U_LE: switch (info->bits) { case 8: tmp = RSD_U8; break; case 16: tmp = RSD_U16_LE; break; } break; case ROAR_CODEC_PCM_U_BE: switch (info->bits) { case 8: tmp = RSD_U8; break; case 16: tmp = RSD_U16_BE; break; } break; case ROAR_CODEC_PCM_U_PDP: switch (info->bits) { case 8: tmp = RSD_U8; break; } break; } if ( tmp == -1 ) { ROAR_DBG("driver_rsound_open(*): Codec/Bits not supported by RSound"); rsd_free(self); return -1; } tmp2 = tmp; if ( rsd_set_param(self, RSD_FORMAT, &tmp) == -1 ) { ROAR_DBG("driver_rsound_open(*): rsd_set_param(self, RSD_FORMAT, &tmp={0x%x->0x%x}) failed.", tmp2, tmp); rsd_free(self); return -1; } if ( tmp != tmp2 ) { rsd_free(self); return -1; } if ( rsd_start(self) == -1 ) { ROAR_DBG("driver_rsound_open(*): rsd_start(self) failed."); rsd_free(self); return -1; } memset(inst, 0, sizeof(struct roar_vio_calls)); inst->inst = self; inst->close = driver_rsound_close; inst->write = driver_rsound_write; return 0; }