devaudio-unix.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Linux and BSD
  3. */
  4. #include <sys/ioctl.h>
  5. #ifdef __linux__
  6. #include <linux/soundcard.h>
  7. #else
  8. #include <sys/soundcard.h>
  9. #endif
  10. #include "u.h"
  11. #include "lib.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "error.h"
  15. #include "devaudio.h"
  16. enum
  17. {
  18. Channels = 2,
  19. Rate = 44100,
  20. Bits = 16,
  21. Bigendian = 1,
  22. };
  23. static int afd = -1;
  24. static int cfd= -1;
  25. static int speed;
  26. /* maybe this should return -1 instead of sysfatal */
  27. void
  28. audiodevopen(void)
  29. {
  30. int t;
  31. ulong ul;
  32. afd = -1;
  33. cfd = -1;
  34. if((afd = open("/dev/dsp", OWRITE)) < 0)
  35. goto err;
  36. if((cfd = open("/dev/mixer", ORDWR)) < 0)
  37. goto err;
  38. t = Bits;
  39. if(ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &t) < 0)
  40. goto err;
  41. t = Channels-1;
  42. if(ioctl(afd, SNDCTL_DSP_STEREO, &t) < 0)
  43. goto err;
  44. speed = Rate;
  45. ul = Rate;
  46. if(ioctl(afd, SNDCTL_DSP_SPEED, &ul) < 0)
  47. goto err;
  48. return;
  49. err:
  50. if(afd >= 0)
  51. close(afd);
  52. afd = -1;
  53. oserror();
  54. }
  55. void
  56. audiodevclose(void)
  57. {
  58. close(afd);
  59. close(cfd);
  60. afd = -1;
  61. cfd = -1;
  62. }
  63. static struct {
  64. int id9;
  65. int id;
  66. } names[] = {
  67. Vaudio, SOUND_MIXER_VOLUME,
  68. Vbass, SOUND_MIXER_BASS,
  69. Vtreb, SOUND_MIXER_TREBLE,
  70. Vline, SOUND_MIXER_LINE,
  71. Vpcm, SOUND_MIXER_PCM,
  72. Vsynth, SOUND_MIXER_SYNTH,
  73. Vcd, SOUND_MIXER_CD,
  74. Vmic, SOUND_MIXER_MIC,
  75. // "record", SOUND_MIXER_RECLEV,
  76. // "mix", SOUND_MIXER_IMIX,
  77. // "pcm2", SOUND_MIXER_ALTPCM,
  78. Vspeaker, SOUND_MIXER_SPEAKER
  79. // "line1", SOUND_MIXER_LINE1,
  80. // "line2", SOUND_MIXER_LINE2,
  81. // "line3", SOUND_MIXER_LINE3,
  82. // "digital1", SOUND_MIXER_DIGITAL1,
  83. // "digital2", SOUND_MIXER_DIGITAL2,
  84. // "digital3", SOUND_MIXER_DIGITAL3,
  85. // "phonein", SOUND_MIXER_PHONEIN,
  86. // "phoneout", SOUND_MIXER_PHONEOUT,
  87. // "radio", SOUND_MIXER_RADIO,
  88. // "video", SOUND_MIXER_VIDEO,
  89. // "monitor", SOUND_MIXER_MONITOR,
  90. // "igain", SOUND_MIXER_IGAIN,
  91. // "ogain", SOUND_MIXER_OGAIN,
  92. };
  93. static int
  94. lookname(int id9)
  95. {
  96. int i;
  97. for(i=0; i<nelem(names); i++)
  98. if(names[i].id9 == id9)
  99. return names[i].id;
  100. return -1;
  101. }
  102. void
  103. audiodevsetvol(int what, int left, int right)
  104. {
  105. int id;
  106. ulong x;
  107. int can, v;
  108. if(cfd < 0)
  109. error("audio device not open");
  110. if(what == Vspeed){
  111. x = left;
  112. if(ioctl(afd, SNDCTL_DSP_SPEED, &x) < 0)
  113. oserror();
  114. speed = x;
  115. return;
  116. }
  117. if((id = lookname(what)) < 0)
  118. return;
  119. if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0)
  120. can = ~0;
  121. if(!(can & (1<<id)))
  122. return;
  123. v = left | (right<<8);
  124. if(ioctl(cfd, MIXER_WRITE(id), &v) < 0)
  125. oserror();
  126. }
  127. void
  128. audiodevgetvol(int what, int *left, int *right)
  129. {
  130. int id;
  131. int can, v;
  132. if(cfd < 0)
  133. error("audio device not open");
  134. if(what == Vspeed){
  135. *left = *right = speed;
  136. return;
  137. }
  138. if((id = lookname(what)) < 0)
  139. return;
  140. if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0)
  141. can = ~0;
  142. if(!(can & (1<<id)))
  143. return;
  144. if(ioctl(cfd, MIXER_READ(id), &v) < 0)
  145. oserror();
  146. *left = v&0xFF;
  147. *right = (v>>8)&0xFF;
  148. }
  149. int
  150. audiodevwrite(void *v, int n)
  151. {
  152. int m, tot;
  153. for(tot=0; tot<n; tot+=m)
  154. if((m = write(afd, (uchar*)v+tot, n-tot)) <= 0)
  155. oserror();
  156. return tot;
  157. }
  158. int
  159. audiodevread(void *v, int n)
  160. {
  161. error("no reading");
  162. return -1;
  163. }