X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/1f3d2413174c3187de3fd8701d3ba26a0d1e4489..7a2c706849ecf6cee19d9e502f8491ffac3322e0:/clients/playrtp-oss.c diff --git a/clients/playrtp-oss.c b/clients/playrtp-oss.c deleted file mode 100644 index 4b0ab83..0000000 --- a/clients/playrtp-oss.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * This file is part of DisOrder. - * Copyright (C) 2007 Richard Kettlewell - * Portions copyright (C) 2007 Ross Younger - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -/** @file clients/playrtp-oss.c - * @brief RTP player - OSS and empeg support - */ - -#include "common.h" - -#if HAVE_SYS_SOUNDCARD_H || EMPEG_HOST - -#include -#include -#if !EMPEG_HOST -#include -#endif -#include -#include -#include -#include -#include - -#include "mem.h" -#include "log.h" -#include "vector.h" -#include "heap.h" -#include "syscalls.h" -#include "playrtp.h" - -/** @brief /dev/dsp (or whatever) */ -static int playrtp_oss_fd = -1; - -/** @brief Audio buffer */ -static char *playrtp_oss_buffer; - -/** @brief Size of @ref playrtp_oss_buffer in bytes */ -static int playrtp_oss_bufsize; - -/** @brief Number of bytes used in @ref playrtp_oss_buffer */ -static int playrtp_oss_bufused; - -/** @brief Open and configure the OSS audio device */ -static void playrtp_oss_enable(void) { - if(playrtp_oss_fd == -1) { -#if EMPEG_HOST - /* empeg audio driver only knows /dev/audio, only supports the equivalent - * of AFMT_S16_NE, has a fixed buffer size, and does not support the - * SNDCTL_ ioctls. */ - if(!device) - device = "/dev/audio"; - if((playrtp_oss_fd = open(device, O_WRONLY)) < 0) - fatal(errno, "error opening %s", device); - playrtp_oss_bufsize = 4608; -#else - int rate = 44100, stereo = 1, format = AFMT_S16_BE; - if(!device) { - if(access("/dev/dsp", W_OK) == 0) - device = "/dev/dsp"; - else if(access("/dev/audio", W_OK) == 0) - device = "/dev/audio"; - else - fatal(0, "cannot determine default audio device"); - } - if((playrtp_oss_fd = open(device, O_WRONLY)) < 0) - fatal(errno, "error opening %s", device); - if(ioctl(playrtp_oss_fd, SNDCTL_DSP_SETFMT, &format) < 0) - fatal(errno, "ioctl SNDCTL_DSP_SETFMT"); - if(ioctl(playrtp_oss_fd, SNDCTL_DSP_STEREO, &stereo) < 0) - fatal(errno, "ioctl SNDCTL_DSP_STEREO"); - if(ioctl(playrtp_oss_fd, SNDCTL_DSP_SPEED, &rate) < 0) - fatal(errno, "ioctl SNDCTL_DSP_SPEED"); - if(rate != 44100) - error(0, "asking for 44100Hz, got %dHz", rate); - if(ioctl(playrtp_oss_fd, SNDCTL_DSP_GETBLKSIZE, &playrtp_oss_bufsize) < 0) - fatal(errno, "ioctl SNDCTL_DSP_GETBLKSIZE"); - info("OSS buffer size %d", playrtp_oss_bufsize); -#endif - playrtp_oss_buffer = xmalloc(playrtp_oss_bufsize); - playrtp_oss_bufused = 0; - nonblock(playrtp_oss_fd); - } -} - -/** @brief Flush the OSS output buffer - * @return 0 on success, non-0 on error - */ -static int playrtp_oss_flush(void) { - int nbyteswritten; - - if(!playrtp_oss_bufused) - return 0; /* nothing to do */ - /* 0 out the unused portion of the buffer */ - memset(playrtp_oss_buffer + playrtp_oss_bufused, 0, - playrtp_oss_bufsize - playrtp_oss_bufused); -#if EMPEG_HOST - /* empeg audio driver insists on native-endian samples */ - { - uint16_t *ptr, - *const limit = (uint16_t *)(playrtp_oss_buffer + playrtp_oss_bufused); - - for(ptr = (uint16_t *)playrtp_oss_buffer; ptr < limit; ++ptr) - *ptr = ntohs(*ptr); - } -#endif - for(;;) { - nbyteswritten = write(playrtp_oss_fd, - playrtp_oss_buffer, playrtp_oss_bufsize); - if(nbyteswritten < 0) { - switch(errno) { - case EINTR: - break; /* try again */ - case EAGAIN: - return 0; /* try later */ - default: - error(errno, "error writing to %s", device); - return -1; - } - } else { - if(nbyteswritten < playrtp_oss_bufsize) - error(0, "%s: short write (%d/%d)", - device, nbyteswritten, playrtp_oss_bufsize); - if(dump_buffer) { - int count; - const int16_t *sp = (const int16_t *)playrtp_oss_buffer; - - for(count = 0; count < playrtp_oss_bufsize; count += sizeof(int16_t)) { - dump_buffer[dump_index++] = (int16_t)ntohs(*sp++); - dump_index %= dump_size; - } - } - playrtp_oss_bufused = 0; - return 0; - } - } -} - -/** @brief Wait until the audio device can accept more data */ -static void playrtp_oss_wait(void) { - struct pollfd fds[1]; - int n; - - do { - fds[0].fd = playrtp_oss_fd; - fds[0].events = POLLOUT; - while((n = poll(fds, 1, -1)) < 0 && errno == EINTR) - ; - if(n < 0) - fatal(errno, "calling poll"); - } while(!(fds[0].revents & (POLLOUT|POLLERR))); -} - -/** @brief Close the OSS output device - * @param hard If nonzero, drop pending data - */ -static void playrtp_oss_disable(int hard) { - if(hard) { -#if !EMPEG_HOST - /* No SNDCTL_DSP_ ioctls on empeg */ - if(ioctl(playrtp_oss_fd, SNDCTL_DSP_RESET, 0) < 0) - error(errno, "ioctl SNDCTL_DSP_RESET"); -#endif - } else - playrtp_oss_flush(); - xclose(playrtp_oss_fd); - playrtp_oss_fd = -1; - free(playrtp_oss_buffer); - playrtp_oss_buffer = 0; -} - -/** @brief Write samples to OSS output device - * @param data Pointer to sample data - * @param samples Number of samples - * @return 0 on success, non-0 on error - */ -static int playrtp_oss_write(const char *data, size_t samples) { - long bytes = samples * sizeof(int16_t); - while(bytes > 0) { - int n = playrtp_oss_bufsize - playrtp_oss_bufused; - - if(n > bytes) - n = bytes; - memcpy(playrtp_oss_buffer + playrtp_oss_bufused, data, n); - bytes -= n; - data += n; - playrtp_oss_bufused += n; - if(playrtp_oss_bufused == playrtp_oss_bufsize) - if(playrtp_oss_flush()) - return -1; - } - next_timestamp += samples; - return 0; -} - -/** @brief Play some data from packet @p p - * - * @p p is assumed to contain @ref next_timestamp. - */ -static int playrtp_oss_play(const struct packet *p) { - return playrtp_oss_write - ((const char *)(p->samples_raw + next_timestamp - p->timestamp), - (p->timestamp + p->nsamples) - next_timestamp); -} - -/** @brief Play some silence before packet @p p - * - * @p p is assumed to be entirely before @ref next_timestamp. - */ -static int playrtp_oss_infill(const struct packet *p) { - static const char zeros[INFILL_SAMPLES * sizeof(int16_t)]; - size_t samples_available = INFILL_SAMPLES; - - if(p && samples_available > p->timestamp - next_timestamp) - samples_available = p->timestamp - next_timestamp; - return playrtp_oss_write(zeros, samples_available); -} - -/** @brief OSS backend for playrtp */ -void playrtp_oss(void) { - int escape; - const struct packet *p; - - pthread_mutex_lock(&lock); - for(;;) { - /* Wait for the buffer to fill up a bit */ - playrtp_fill_buffer(); - playrtp_oss_enable(); - escape = 0; - info("Playing..."); - /* Keep playing until the buffer empties out, we get an error */ - while((nsamples >= minbuffer - || (nsamples > 0 - && contains(pheap_first(&packets), next_timestamp))) - && !escape) { - /* Wait until we can play more */ - pthread_mutex_unlock(&lock); - playrtp_oss_wait(); - pthread_mutex_lock(&lock); - /* Device is ready for more data, find something to play */ - p = playrtp_next_packet(); - /* Play it or play some silence */ - if(contains(p, next_timestamp)) - escape = playrtp_oss_play(p); - else - escape = playrtp_oss_infill(p); - } - active = 0; - /* We stop playing for a bit until the buffer re-fills */ - pthread_mutex_unlock(&lock); - playrtp_oss_disable(escape); - pthread_mutex_lock(&lock); - } -} - -#endif - -/* -Local Variables: -c-basic-offset:2 -comment-column:40 -fill-column:79 -indent-tabs-mode:nil -End: -*/