You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
3.8KB

  1. /*
  2. * Linux audio play and grab interface
  3. * Copyright (c) 2000, 2001 Gerard Lantau.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <linux/soundcard.h>
  23. #include <unistd.h>
  24. #include <fcntl.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/mman.h>
  27. #include <errno.h>
  28. #include <sys/time.h>
  29. #include "avformat.h"
  30. const char *audio_device = "/dev/dsp";
  31. typedef struct {
  32. int fd;
  33. int rate;
  34. int channels;
  35. } AudioData;
  36. #define AUDIO_BLOCK_SIZE 4096
  37. /* audio read support */
  38. static int audio_read(URLContext *h, UINT8 *buf, int size)
  39. {
  40. AudioData *s = h->priv_data;
  41. int ret;
  42. ret = read(s->fd, buf, size);
  43. if (ret < 0)
  44. return -errno;
  45. else
  46. return ret;
  47. }
  48. static int audio_write(URLContext *h, UINT8 *buf, int size)
  49. {
  50. AudioData *s = h->priv_data;
  51. int ret;
  52. ret = write(s->fd, buf, size);
  53. if (ret < 0)
  54. return -errno;
  55. else
  56. return ret;
  57. }
  58. static int audio_get_format(URLContext *h, URLFormat *f)
  59. {
  60. AudioData *s = h->priv_data;
  61. strcpy(f->format_name, "pcm");
  62. f->sample_rate = s->rate;
  63. f->channels = s->channels;
  64. return 0;
  65. }
  66. /* URI syntax: 'audio:[rate[,channels]]'
  67. default: rate=44100, channels=2
  68. */
  69. static int audio_open(URLContext *h, const char *uri, int flags)
  70. {
  71. AudioData *s;
  72. const char *p;
  73. int freq, channels, audio_fd;
  74. int tmp, err;
  75. h->is_streamed = 1;
  76. h->packet_size = AUDIO_BLOCK_SIZE;
  77. s = malloc(sizeof(AudioData));
  78. if (!s)
  79. return -ENOMEM;
  80. h->priv_data = s;
  81. /* extract parameters */
  82. p = uri;
  83. strstart(p, "audio:", &p);
  84. freq = strtol(p, (char **)&p, 0);
  85. if (freq <= 0)
  86. freq = 44100;
  87. if (*p == ',')
  88. p++;
  89. channels = strtol(p, (char **)&p, 0);
  90. if (channels <= 0)
  91. channels = 2;
  92. s->rate = freq;
  93. s->channels = channels;
  94. /* open linux audio device */
  95. if (flags & URL_WRONLY)
  96. audio_fd = open(audio_device,O_WRONLY);
  97. else
  98. audio_fd = open(audio_device,O_RDONLY);
  99. if (audio_fd < 0) {
  100. perror(audio_device);
  101. return -EIO;
  102. }
  103. /* non blocking mode */
  104. fcntl(audio_fd, F_SETFL, O_NONBLOCK);
  105. #if 0
  106. tmp=(NB_FRAGMENTS << 16) | FRAGMENT_BITS;
  107. err=ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
  108. if (err < 0) {
  109. perror("SNDCTL_DSP_SETFRAGMENT");
  110. }
  111. #endif
  112. tmp=AFMT_S16_LE;
  113. err=ioctl(audio_fd,SNDCTL_DSP_SETFMT,&tmp);
  114. if (err < 0) {
  115. perror("SNDCTL_DSP_SETFMT");
  116. goto fail;
  117. }
  118. tmp= (channels == 2);
  119. err=ioctl(audio_fd,SNDCTL_DSP_STEREO,&tmp);
  120. if (err < 0) {
  121. perror("SNDCTL_DSP_STEREO");
  122. goto fail;
  123. }
  124. tmp = freq;
  125. err=ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
  126. if (err < 0) {
  127. perror("SNDCTL_DSP_SPEED");
  128. goto fail;
  129. }
  130. s->rate = tmp;
  131. s->fd = audio_fd;
  132. return 0;
  133. fail:
  134. close(audio_fd);
  135. free(s);
  136. return -EIO;
  137. }
  138. static int audio_close(URLContext *h)
  139. {
  140. AudioData *s = h->priv_data;
  141. close(s->fd);
  142. free(s);
  143. return 0;
  144. }
  145. URLProtocol audio_protocol = {
  146. "audio",
  147. audio_open,
  148. audio_read,
  149. audio_write,
  150. NULL, /* seek */
  151. audio_close,
  152. audio_get_format,
  153. };