-static void *oss_thread(void *userdata) {
- int16_t *buffer;
- pthread_mutex_lock(&oss_lock);
- buffer = xmalloc(XXX);
- while(oss_started) {
- while(oss_started && !oss_activated)
- pthread_cond_wait(&oss_cond, &oss_lock);
- if(!oss_started)
- break;
- /* We are definitely active now */
- oss_going = 1;
- pthread_cond_signal(&oss_cond);
- while(oss_activated) {
- const int nsamples = oss_callback(buffer, oss_bufsizeXXX, userdata);;
- if(write(oss_fd, buffer, XXX) < 0)
- fatal(errno, "error playing audio");
- // TODO short writes!
- }
- oss_going = 0;
- pthread_cond_signal(&oss_cond);
+/** @brief Open the OSS sound device */
+static void oss_open(void) {
+ const char *device = uaudio_get("device", NULL);
+
+#if EMPEG_HOST
+ if(!device || !*device || !strcmp(device, "default"))
+ device = "/dev/audio";
+#else
+ if(!device || !*device || !strcmp(device, "default")) {
+ if(access("/dev/dsp", W_OK) == 0)
+ device = "/dev/dsp";
+ else
+ device = "/dev/audio";
+ }
+#endif
+ if((oss_fd = open(device, O_WRONLY, 0)) < 0)
+ disorder_fatal(errno, "error opening %s", device);
+#if !EMPEG_HOST
+ int stereo = (uaudio_channels == 2), format;
+ if(ioctl(oss_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
+ disorder_fatal(errno, "error calling ioctl SNDCTL_DSP_STEREO %d", stereo);
+ if(uaudio_bits == 16)
+ format = uaudio_signed ? AFMT_S16_NE : AFMT_U16_NE;
+ else
+ format = uaudio_signed ? AFMT_S8 : AFMT_U8;
+ if(ioctl(oss_fd, SNDCTL_DSP_SETFMT, &format) < 0)
+ disorder_fatal(errno, "error calling ioctl SNDCTL_DSP_SETFMT %#x", format);
+ int rate = uaudio_rate;
+ if(ioctl(oss_fd, SNDCTL_DSP_SPEED, &rate) < 0)
+ disorder_fatal(errno, "error calling ioctl SNDCTL_DSP_SPEED %d", rate);
+ if(rate != uaudio_rate)
+ disorder_error(0, "asked for %dHz, got %dHz", uaudio_rate, rate);
+#endif
+}
+
+/** @brief Close the OSS sound device */
+static void oss_close(void) {
+ if(oss_fd != -1) {
+ close(oss_fd);
+ oss_fd = -1;
+ }
+}
+
+/** @brief Actually play sound via OSS */
+static size_t oss_play(void *buffer, size_t samples, unsigned flags) {
+ /* cf uaudio-alsa.c:alsa-play() */
+ if(flags & UAUDIO_PAUSED) {
+ if(flags & UAUDIO_PAUSE)
+ oss_close();
+ if(samples > 64)
+ samples /= 2;
+ const uint64_t ns = ((uint64_t)samples * 1000000000
+ / (uaudio_rate * uaudio_channels));
+ struct timespec ts[1];
+ ts->tv_sec = ns / 1000000000;
+ ts->tv_nsec = ns % 1000000000;
+ while(nanosleep(ts, ts) < 0 && errno == EINTR)
+ ;
+ return samples;