PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/sf/tags/RELEASE_0_1_1/src/sndlib/audio.c

#
C | 1738 lines | 1482 code | 116 blank | 140 comment | 587 complexity | e3db111fd51e3b5d760ffad55a9c5efd MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. /* Audio hardware handlers (SGI, OSS, Sun, NeXT, Mac, W95, Be, HPUX) */
  2. /*
  3. * layout of this file:
  4. * error handlers
  5. * SGI new and old audio library (find "- SG")
  6. * OSS ("- O")
  7. * NeXT ("- NE")
  8. * Sun ("- SU") (has switches for OPENBSD, but they're untested)
  9. * Mac ("- M")
  10. * Be ("- B")
  11. * HPUX ("- H")
  12. * W95 ("- WI")
  13. * audio describers
  14. */
  15. /* TODO: w95 input, read/write state
  16. * sgi/w95/mac? also may have multiple systems/cards
  17. * more machines!
  18. */
  19. /* when reading device_field, put default input device first, or mark somehow */
  20. /*
  21. * void describe_audio_state(void) describes the audio hardware state.
  22. * char *report_audio_state(void) returns the same information as a string.
  23. *
  24. * int open_audio_output(int dev, int srate, int chans, int format, int size)
  25. * int open_audio_input(int dev, int srate, int chans, int format, int size)
  26. * int write_audio(int line, char *buf, int bytes)
  27. * int close_audio(int line)
  28. * int read_audio(int line, char *buf, int bytes)
  29. *
  30. * int read_audio_state(int dev, int field, int chan, float *val)
  31. * int write_audio_state(int dev, int field, int chan, float *val)
  32. * void save_audio_state(void)
  33. * void restore_audio_state(void)
  34. *
  35. * int audio_error(void) returns the error code indicated by the immediately preceding audio call
  36. * int initialize_audio(void) does whatever is needed to get set up
  37. * char *audio_error_name(int err) gives string decription of error code
  38. *
  39. * int audio_systems(void) returns number of separate complete audio systems (soundcards essentially)
  40. * AUDIO_SYSTEM(n) selects the nth card (counting from 0), AUDIO_SYSTEM(0) is always the default
  41. * char *audio_system_name(int system) returns some user-recognizable (?) name for the given card
  42. */
  43. #if defined(HAVE_CONFIG_H)
  44. #include "config.h"
  45. #endif
  46. #include <math.h>
  47. #include <stdio.h>
  48. #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_FCNTL_H))
  49. #include <fcntl.h>
  50. #endif
  51. #include <signal.h>
  52. #if (!defined(HAVE_CONFIG_H)) || (defined(HAVE_LIMITS_H))
  53. #include <limits.h>
  54. #endif
  55. #include <errno.h>
  56. #include <stdlib.h>
  57. #if (defined(NEXT) || (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H))))
  58. #include <libc.h>
  59. #else
  60. #include <unistd.h>
  61. #endif
  62. #include "sndlib.h"
  63. #define STRBUF_SIZE 4096
  64. #if (defined(HAVE_CONFIG_H)) && (!defined(HAVE_STRERROR))
  65. char *strerror(int errnum)
  66. {
  67. char *strerrbuf;
  68. strerrbuf = (char *)CALLOC(16,sizeof(char));
  69. sprintf(strerrbuf,"io err %d",errnum);
  70. return(strerrbuf);
  71. }
  72. #else
  73. #include <string.h>
  74. #endif
  75. static int AUDIO_ERROR = NO_ERROR;
  76. int audio_error(void) {return(AUDIO_ERROR);}
  77. void set_audio_error(int err) {AUDIO_ERROR = err;}
  78. static int audio_initialized = 0;
  79. static char *audio_error_name_1(int err)
  80. {
  81. switch (err)
  82. {
  83. case NO_ERROR: return(""); break;
  84. case CHANNELS_NOT_AVAILABLE: return("channel(s) not available"); break;
  85. case SRATE_NOT_AVAILABLE: return("srate not available"); break;
  86. case FORMAT_NOT_AVAILABLE: return("format not available"); break;
  87. case NO_INPUT_AVAILABLE: return("no input available"); break;
  88. case NO_OUTPUT_AVAILABLE: return("no output available"); break;
  89. case INPUT_BUSY: return("input busy"); break;
  90. case OUTPUT_BUSY: return("output busy"); break;
  91. case CONFIGURATION_NOT_AVAILABLE: return("configuration not available"); break;
  92. case INPUT_CLOSED: return("input closed"); break;
  93. case OUTPUT_CLOSED: return("output closed"); break;
  94. case IO_INTERRUPTED: return("io interrupted"); break;
  95. case NO_LINES_AVAILABLE: return("no lines available"); break;
  96. case WRITE_ERROR: return("write error"); break;
  97. case SIZE_NOT_AVAILABLE: return("size not available"); break;
  98. case DEVICE_NOT_AVAILABLE: return("device not available"); break;
  99. case CANT_CLOSE: return("close failed"); break;
  100. case CANT_OPEN: return("open failed"); break;
  101. case READ_ERROR: return("read error"); break;
  102. case AMP_NOT_AVAILABLE: return("amp control not available"); break;
  103. case AUDIO_NO_OP: return("unimplemented operation"); break;
  104. case CANT_WRITE: return("write failed"); break;
  105. case CANT_READ: return("read failed"); break;
  106. case NO_READ_PERMISSION: return("need read permission on /dev/dsp"); break;
  107. default: return("unknown error"); break;
  108. }
  109. }
  110. static char *strbuf = NULL;
  111. static void pprint(char *str);
  112. int device_channels(int dev);
  113. int device_gains(int dev);
  114. int device_channels(int dev)
  115. {
  116. float val[1];
  117. read_audio_state(dev,CHANNEL_FIELD,0,val);
  118. return((int)val[0]);
  119. }
  120. int device_gains(int ur_dev)
  121. {
  122. float val[1];
  123. int err;
  124. int dev;
  125. dev = SNDLIB_DEVICE(ur_dev);
  126. /* to get hardware gains, read device amp_field and error = none */
  127. if ((dev == DAC_FILTER_DEVICE) || (dev == MIXER_DEVICE))
  128. {
  129. err = read_audio_state(ur_dev,CHANNEL_FIELD,0,val);
  130. return((int)val[0]);
  131. }
  132. err = read_audio_state(ur_dev,AMP_FIELD,0,val);
  133. if (err != NO_ERROR) return(0);
  134. return(device_channels(ur_dev));
  135. }
  136. /* ------------------------------- SGI ----------------------------------------- */
  137. #ifdef SGI
  138. #define AUDIO_OK
  139. #include <audio.h>
  140. static char errstr[256];
  141. static int al_err = 0;
  142. int audio_systems(void) {return(1);} /* I think more than 1 is possible, but don't have a case to test with */
  143. char *audio_system_name(int system) {return("SGI");}
  144. #ifdef AL_RESOURCE
  145. char *audio_error_name(int err)
  146. {
  147. if (!al_err) return(audio_error_name_1(err));
  148. sprintf(errstr,"%s: %s",audio_error_name_1(err),alGetErrorString(al_err));
  149. return(errstr);
  150. }
  151. static int check_queue_size (int size, int chans) {return(size);}
  152. #else
  153. #define STEREO_QUEUE_MIN_SIZE 1024
  154. #define STEREO_QUEUE_MIN_CHOICE 1024
  155. /* docs say 510 or 512, but they die with "File size limit exceeded" %$@#!(& */
  156. #define MONO_QUEUE_MIN_SIZE 1019
  157. #define MONO_QUEUE_MIN_CHOICE 1024
  158. #define STEREO_QUEUE_MAX_SIZE 131069
  159. #define STEREO_QUEUE_MAX_CHOICE 65536
  160. #define MONO_QUEUE_MAX_SIZE 262139
  161. #define MONO_QUEUE_MAX_CHOICE 131072
  162. /* if these limits are not followed, the damned thing dumps core and dies */
  163. static int check_queue_size (int size, int chans)
  164. {
  165. if ((chans == 1) && (size > MONO_QUEUE_MAX_SIZE)) return(MONO_QUEUE_MAX_CHOICE);
  166. if ((chans == 1) && (size < MONO_QUEUE_MIN_SIZE)) return(MONO_QUEUE_MIN_CHOICE);
  167. if ((chans > 1) && (size > STEREO_QUEUE_MAX_SIZE)) return(STEREO_QUEUE_MAX_CHOICE);
  168. if ((chans > 1) && (size < STEREO_QUEUE_MIN_SIZE)) return(STEREO_QUEUE_MIN_CHOICE);
  169. return(size);
  170. }
  171. static void check_quad (int device, int channels)
  172. {
  173. long sr[2];
  174. /* if quad, make sure we are set up for it, else make sure we aren't (perhaps the latter is unnecessary) */
  175. /* in 4 channel mode, stereo mic and line-in are 4 inputs, headphones/speakers and stereo line-out are the 4 outputs */
  176. sr[0] = AL_CHANNEL_MODE;
  177. ALgetparams(device,sr,2);
  178. if ((channels == 4) && (sr[1] != AL_4CHANNEL))
  179. {
  180. sr[1] = AL_4CHANNEL;
  181. ALsetparams(device,sr,2);
  182. }
  183. else
  184. {
  185. if ((channels != 4) && (sr[1] != AL_STEREO))
  186. {
  187. sr[1] = AL_STEREO;
  188. ALsetparams(device,sr,2);
  189. }
  190. }
  191. }
  192. static char *AL_GetErrorString(int err)
  193. {
  194. switch (err)
  195. {
  196. case AL_BAD_NOT_IMPLEMENTED: return("not implemented yet"); break;
  197. case AL_BAD_PORT: return("tried to use an invalid port"); break;
  198. case AL_BAD_CONFIG: return("tried to use an invalid configuration"); break;
  199. case AL_BAD_DEVICE: return("tried to use an invalid device"); break;
  200. case AL_BAD_DEVICE_ACCESS: return("unable to access the device"); break;
  201. case AL_BAD_DIRECTION: return("illegal direction given for port"); break;
  202. case AL_BAD_OUT_OF_MEM: return("operation has run out of memory"); break;
  203. case AL_BAD_NO_PORTS: return("not able to allocate a port"); break;
  204. case AL_BAD_WIDTH: return("invalid sample width given"); break;
  205. case AL_BAD_ILLEGAL_STATE: return("an illegal state has occurred"); break;
  206. case AL_BAD_QSIZE: return("attempt to set an invalid queue size"); break;
  207. case AL_BAD_FILLPOINT: return("attempt to set an invalid fillpoint"); break;
  208. case AL_BAD_BUFFER_NULL: return("null buffer pointer"); break;
  209. case AL_BAD_COUNT_NEG: return("negative count"); break;
  210. case AL_BAD_PVBUFFER: return("param/val buffer doesn't make sense"); break;
  211. case AL_BAD_BUFFERLENGTH_NEG: return("negative buffer length"); break;
  212. case AL_BAD_BUFFERLENGTH_ODD: return("odd length parameter/value buffer"); break;
  213. case AL_BAD_CHANNELS: return("invalid channel specifier"); break;
  214. case AL_BAD_PARAM: return("invalid parameter"); break;
  215. case AL_BAD_SAMPFMT: return("attempt to set invalid sample format"); break;
  216. case AL_BAD_RATE: return("invalid sample rate token"); break;
  217. case AL_BAD_TRANSFER_SIZE: return("invalid size for sample read/write"); break;
  218. case AL_BAD_FLOATMAX: return("invalid size for floatmax"); break;
  219. case AL_BAD_PORTSTYLE: return("invalid port style"); break;
  220. default: return("");
  221. }
  222. }
  223. char *audio_error_name(int err)
  224. {
  225. if (!al_err) return(audio_error_name_1(err));
  226. sprintf(errstr,"%s: %s",audio_error_name_1(err),AL_GetErrorString(al_err));
  227. return(errstr);
  228. }
  229. #endif
  230. #define IO_LINES 8
  231. static ALconfig config[IO_LINES];
  232. static ALport port[IO_LINES];
  233. static int line_in_use[IO_LINES];
  234. static int channels[IO_LINES];
  235. static long device[IO_LINES];
  236. static int datum_size[IO_LINES];
  237. static int line_out[IO_LINES];
  238. int initialize_audio(void)
  239. {
  240. int i;
  241. if (!audio_initialized)
  242. {
  243. audio_initialized = 1;
  244. AUDIO_ERROR = NO_ERROR; al_err = 0;
  245. for (i=0;i<IO_LINES;i++) line_in_use[i]=0;
  246. }
  247. return(0);
  248. }
  249. static int error_exit(int error, int line)
  250. {
  251. AUDIO_ERROR = error;
  252. #ifdef AL_RESOURCE
  253. if (line != -1) alFreeConfig(config[line]);
  254. #else
  255. if (line != -1) ALfreeconfig(config[line]);
  256. #endif
  257. return(-1);
  258. }
  259. #ifdef AL_RESOURCE
  260. static int to_al_interface_or_device(int dev,int which)
  261. {
  262. switch (dev)
  263. {
  264. case MICROPHONE_DEVICE: return(alGetResourceByName(AL_SYSTEM,"Microphone",which)); break;
  265. case DEFAULT_DEVICE:
  266. case READ_WRITE_DEVICE:
  267. case DAC_OUT_DEVICE:
  268. case SPEAKERS_DEVICE: return(alGetResourceByName(AL_SYSTEM,"Analog Out",which)); break;
  269. case ADAT_IN_DEVICE: return(alGetResourceByName(AL_SYSTEM,"ADAT In",which)); break;
  270. case AES_IN_DEVICE: return(alGetResourceByName(AL_SYSTEM,"AES In",which)); break;
  271. case ADAT_OUT_DEVICE: return(alGetResourceByName(AL_SYSTEM,"ADAT Out",which)); break;
  272. case DIGITAL_OUT_DEVICE:
  273. case AES_OUT_DEVICE: return(alGetResourceByName(AL_SYSTEM,"AES Out",which)); break;
  274. case LINE_IN_DEVICE: return(alGetResourceByName(AL_SYSTEM,"Line In",which)); break;
  275. case LINE_OUT_DEVICE: return(alGetResourceByName(AL_SYSTEM,"Line Out2",which)); break; /* ?? */
  276. /* case DIGITAL_IN_DEVICE: return(alGetResourceByName(AL_SYSTEM,"DAC2 In",which)); break; */ /* this is analog in ?? */
  277. }
  278. return(0);
  279. }
  280. static int to_al_device(int dev) {return(to_al_interface_or_device(dev,AL_DEVICE_TYPE));}
  281. static int to_al_interface(int dev) {return(to_al_interface_or_device(dev,AL_INTERFACE_TYPE));}
  282. #endif
  283. #include <stdio.h>
  284. /* just a placeholder for now */
  285. int find_audio_output(int chans)
  286. {
  287. #ifdef AL_RESOURCE
  288. ALvalue x[32];
  289. ALpv y;
  290. int n,i;
  291. y.param = AL_INTERFACE;
  292. y.value.i = AL_DIGITAL_IF_TYPE;
  293. n = alQueryValues(AL_SYSTEM,AL_DEFAULT_OUTPUT,x,32,&y,1);
  294. for (i=0;i<n;i++)
  295. {
  296. y.param = AL_CHANNELS;
  297. alGetParams(x[i].i,&y,1);
  298. if (chans <= y.value.i) return(x[i].i);
  299. }
  300. #endif
  301. return(-1);
  302. }
  303. static int to_sgi_format(int frm)
  304. {
  305. switch (frm)
  306. {
  307. case snd_8_linear:
  308. case snd_16_linear:
  309. case snd_24_linear: return(AL_SAMPFMT_TWOSCOMP); break;
  310. case snd_32_float: return(AL_SAMPFMT_FLOAT); break;
  311. case snd_64_double: return(AL_SAMPFMT_DOUBLE); break;
  312. }
  313. return(-1);
  314. }
  315. int open_audio_output(int ur_dev, int srate, int chans, int format, int requested_size)
  316. {
  317. #ifdef AL_RESOURCE
  318. ALpv pv;
  319. ALpv z[2];
  320. #else
  321. long sr[2];
  322. #endif
  323. int i,line,size,width,sgi_format,dev;
  324. AUDIO_ERROR = NO_ERROR; al_err = 0;
  325. dev = SNDLIB_DEVICE(ur_dev);
  326. line = -1;
  327. for (i=0;i<IO_LINES;i++) if (line_in_use[i] == 0) {line=i; break;}
  328. if (line == -1) {AUDIO_ERROR = NO_LINES_AVAILABLE; return(-1);}
  329. channels[line] = chans;
  330. line_out[line] = 1;
  331. datum_size[line] = c_snd_datum_size(format);
  332. if (requested_size == 0)
  333. size = 4096;
  334. else size = check_queue_size(requested_size,chans);
  335. if (datum_size[line] == 3)
  336. width = AL_SAMPLE_24;
  337. else
  338. {
  339. if (datum_size[line] == 1)
  340. width = AL_SAMPLE_8;
  341. else width = AL_SAMPLE_16;
  342. }
  343. sgi_format = to_sgi_format(format);
  344. #ifdef AL_RESOURCE
  345. if (dev == DEFAULT_DEVICE) dev = DAC_OUT_DEVICE;
  346. device[line] = to_al_device(dev); if (!(device[line])) return(error_exit(DEVICE_NOT_AVAILABLE,-1));
  347. if (chans>2) size = 65536; /* for temp adat code */
  348. if (device_channels(dev) < chans) /* look for some device that can play this file */
  349. device[line] = find_audio_output(chans); if (device[line] == -1) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  350. z[0].param = AL_RATE;
  351. z[0].value.ll = alDoubleToFixed((double)srate);
  352. z[1].param = AL_MASTER_CLOCK;
  353. z[1].value.i = AL_CRYSTAL_MCLK_TYPE;
  354. alSetParams(device[line],z, 2);
  355. config[line] = alNewConfig(); if (!(config[line])) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  356. if ((sgi_format == -1) ||
  357. (alSetSampFmt(config[line],sgi_format) == -1) ||
  358. (alSetWidth(config[line],width) == -1)) /* this is a no-op in the float and double cases */
  359. return(error_exit(FORMAT_NOT_AVAILABLE,line));
  360. al_err = alSetChannels(config[line],chans); if (al_err == -1) return(error_exit(CHANNELS_NOT_AVAILABLE,line));
  361. al_err = alSetQueueSize(config[line],size); if (al_err == -1) return(error_exit(SIZE_NOT_AVAILABLE,line));
  362. al_err = alSetDevice(config[line],device[line]); if (al_err == -1) return(error_exit(DEVICE_NOT_AVAILABLE,line));
  363. port[line] = alOpenPort("dac","w",config[line]); if (!(port[line])) return(error_exit(CONFIGURATION_NOT_AVAILABLE,line));
  364. #else
  365. device[line] = AL_DEFAULT_DEVICE;
  366. check_quad(device[line],chans);
  367. sr[0]=AL_OUTPUT_RATE;
  368. sr[1]=srate;
  369. al_err = ALsetparams(device[line],sr,2); if (al_err == -1) return(error_exit(SRATE_NOT_AVAILABLE,-1));
  370. config[line] = ALnewconfig(); if (!(config[line])) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  371. if ((sgi_format == -1) ||
  372. (ALsetsampfmt(config[line],sgi_format) == -1) ||
  373. (ALsetwidth(config[line],width) == -1)) /* this is a no-op in the float and double cases */
  374. return(error_exit(FORMAT_NOT_AVAILABLE,line));
  375. al_err = ALsetchannels(config[line],chans); if (al_err == -1) return(error_exit(CHANNELS_NOT_AVAILABLE,line));
  376. al_err = ALsetqueuesize(config[line],size); if (al_err == -1) return(error_exit(SIZE_NOT_AVAILABLE,line));
  377. port[line] = ALopenport("dac","w",config[line]); if (!(port[line])) return(error_exit(CONFIGURATION_NOT_AVAILABLE,line));
  378. #endif
  379. line_in_use[line] = 1;
  380. return(line);
  381. }
  382. int write_audio(int line, char *buf, int bytes)
  383. {
  384. AUDIO_ERROR = NO_ERROR; al_err = 0;
  385. #ifdef AL_RESOURCE
  386. al_err = alWriteFrames(port[line],(short *)buf,bytes/(channels[line]*datum_size[line]));
  387. #else
  388. al_err = ALwritesamps(port[line],(short *)buf,bytes/datum_size[line]);
  389. #endif
  390. if (al_err) {AUDIO_ERROR = WRITE_ERROR; return(-1);}
  391. return(0);
  392. }
  393. int close_audio(int line)
  394. {
  395. AUDIO_ERROR = NO_ERROR; al_err = 0;
  396. if (line_in_use[line])
  397. {
  398. if (line_out[line])
  399. {
  400. #ifdef AL_RESOURCE
  401. while (alGetFilled(port[line]) > 0) sginap(1);
  402. #else
  403. while (ALgetfilled(port[line]) > 0) sginap(1);
  404. #endif
  405. }
  406. #ifdef AL_RESOURCE
  407. al_err = alClosePort(port[line]);
  408. if (al_err == 0) al_err = alFreeConfig(config[line]);
  409. #else
  410. al_err = ALcloseport(port[line]);
  411. if (al_err == 0) al_err = ALfreeconfig(config[line]);
  412. #endif
  413. line_in_use[line] = 0;
  414. if (al_err) {AUDIO_ERROR = CANT_CLOSE; return(-1);}
  415. }
  416. return(0);
  417. }
  418. int open_audio_input(int ur_dev, int srate, int chans, int format, int requested_size)
  419. {
  420. int dev;
  421. #ifdef AL_RESOURCE
  422. ALpv pv;
  423. ALpv x[2];
  424. int itf;
  425. #else
  426. long sr[2];
  427. int resind;
  428. #endif
  429. int i,line,size;
  430. AUDIO_ERROR = NO_ERROR; al_err = 0;
  431. dev = SNDLIB_DEVICE(ur_dev);
  432. line = -1;
  433. for (i=0;i<IO_LINES;i++) if (line_in_use[i] == 0) {line=i; break;}
  434. if (line == -1) {AUDIO_ERROR = NO_LINES_AVAILABLE; return(-1);}
  435. channels[line] = chans;
  436. line_out[line] = 0;
  437. datum_size[line] = c_snd_datum_size(format);
  438. if (requested_size == 0)
  439. size = 4096;
  440. else size = check_queue_size(requested_size,chans);
  441. /* there are lots of ways this may be called in terms of the desired "device" */
  442. /* in CLM, the caller specifies which device, in Snd we try to open everything available */
  443. #ifdef AL_RESOURCE
  444. device[line] = to_al_device((dev == DEFAULT_DEVICE) ? MICROPHONE_DEVICE : dev);
  445. if (!(device[line])) return(error_exit(DEVICE_NOT_AVAILABLE,-1));
  446. itf = to_al_interface((dev == DEFAULT_DEVICE) ? MICROPHONE_DEVICE : dev);
  447. if (itf)
  448. {
  449. pv.param = AL_INTERFACE;
  450. pv.value.i = itf;
  451. al_err = alSetParams(device[line],&pv,1); if (al_err == -1) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  452. }
  453. x[0].param = AL_RATE;
  454. x[0].value.ll = alDoubleToFixed((double)srate);
  455. x[1].param = AL_MASTER_CLOCK;
  456. x[1].value.i = AL_CRYSTAL_MCLK_TYPE;
  457. al_err = alSetParams(device[line],x,2); if (al_err == -1) return(error_exit(SRATE_NOT_AVAILABLE,-1));
  458. config[line] = alNewConfig(); if (!config[line]) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  459. if ((to_sgi_format(format) == -1) ||
  460. (alSetSampFmt(config[line],to_sgi_format(format)) == -1) ||
  461. (alSetWidth(config[line],(datum_size[line] == 2) ? AL_SAMPLE_16 : AL_SAMPLE_8) == -1))
  462. return(error_exit(FORMAT_NOT_AVAILABLE,line));
  463. al_err = alSetChannels(config[line],chans); if (al_err == -1) return(error_exit(CHANNELS_NOT_AVAILABLE,line));
  464. al_err = alSetQueueSize(config[line],size); if (al_err == -1) return(error_exit(SIZE_NOT_AVAILABLE,line));
  465. al_err = alSetDevice(config[line],device[line]); if (al_err == -1) return(error_exit(DEVICE_NOT_AVAILABLE,line));
  466. port[line] = alOpenPort("adc","r",config[line]); if (!(port[line])) return(error_exit(CONFIGURATION_NOT_AVAILABLE,line));
  467. #else
  468. switch (dev)
  469. {
  470. case DEFAULT_DEVICE:
  471. case READ_WRITE_DEVICE:
  472. case MICROPHONE_DEVICE: resind = AL_INPUT_MIC; break;
  473. case LINE_IN_DEVICE: resind = AL_INPUT_LINE; break;
  474. case DIGITAL_IN_DEVICE: resind = AL_INPUT_DIGITAL; break;
  475. default: return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1)); break;
  476. }
  477. device[line] = AL_DEFAULT_DEVICE;
  478. sr[0] = AL_INPUT_SOURCE;
  479. sr[1] = resind;
  480. al_err = ALsetparams(device[line],sr,2); if (al_err == -1) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  481. check_quad(device[line],chans);
  482. sr[0] = AL_INPUT_RATE;
  483. sr[1] = srate;
  484. al_err = ALsetparams(device[line],sr,2); if (al_err == -1) return(error_exit(SRATE_NOT_AVAILABLE,-1));
  485. config[line] = ALnewconfig(); if (!config[line]) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  486. if ((to_sgi_format(format) == -1) ||
  487. (ALsetsampfmt(config[line],to_sgi_format(format)) == -1) ||
  488. (ALsetwidth(config[line],(datum_size[line] == 2) ? AL_SAMPLE_16 : AL_SAMPLE_8) == -1))
  489. return(error_exit(FORMAT_NOT_AVAILABLE,line));
  490. al_err = ALsetchannels(config[line],chans); if (al_err == -1) return(error_exit(CHANNELS_NOT_AVAILABLE,line));
  491. al_err = ALsetqueuesize(config[line],size); if (al_err == -1) return(error_exit(SIZE_NOT_AVAILABLE,line));
  492. port[line] = ALopenport("adc","r",config[line]); if (!(port[line])) return(error_exit(CONFIGURATION_NOT_AVAILABLE,line));
  493. #endif
  494. line_in_use[line] = 1;
  495. return(line);
  496. }
  497. int read_audio(int line, char *buf, int bytes)
  498. {
  499. AUDIO_ERROR = NO_ERROR; al_err = 0;
  500. #ifdef AL_RESOURCE
  501. al_err = alReadFrames(port[line],(short *)buf,bytes/(channels[line]*datum_size[line]));
  502. #else
  503. al_err = ALreadsamps(port[line],(short *)buf,bytes/datum_size[line]);
  504. #endif
  505. if (al_err) {AUDIO_ERROR = WRITE_ERROR; return(-1);}
  506. return(0);
  507. }
  508. #ifdef AL_RESOURCE
  509. /* borrowed from /usr/share/src/dmedia/audio/printdevs.c with modifications */
  510. #define MAX_CHANNELS 8
  511. static float dB_to_linear(float val)
  512. {
  513. if (val == 0.0) return(1.0);
  514. return(pow(10.0,val/20.0));
  515. }
  516. static float linear_to_dB(float val)
  517. {
  518. return(20.0 * log10(val));
  519. }
  520. static float dB_to_normalized(float val, float lo, float hi)
  521. {
  522. float linlo;
  523. if (hi <= lo) return(1.0);
  524. linlo = dB_to_linear(lo);
  525. return((dB_to_linear(val) - linlo) / (dB_to_linear(hi) - linlo));
  526. }
  527. static float normalized_to_dB(float val_norm, float lo_dB, float hi_dB)
  528. {
  529. if (hi_dB <= lo_dB) return(0.0);
  530. return(lo_dB + (hi_dB - lo_dB)*val_norm);
  531. }
  532. int read_audio_state(int ur_dev, int field, int chan, float *val)
  533. {
  534. ALpv x[4];
  535. ALparamInfo pinf;
  536. ALfixed g[MAX_CHANNELS];
  537. int rv,chans,i,dev;
  538. long fld;
  539. float amp;
  540. AUDIO_ERROR = NO_ERROR; al_err = 0;
  541. dev = SNDLIB_DEVICE(ur_dev);
  542. if (field != DEVICE_FIELD)
  543. {
  544. rv = to_al_device(dev); if (!rv) return(error_exit(DEVICE_NOT_AVAILABLE,-1));
  545. }
  546. switch (field)
  547. {
  548. case DEVICE_FIELD:
  549. /* in this case, chan == length of incoming val array. Number of devices is returned as val[0],
  550. * and the rest of the available area (if needed) is filled with the device ids.
  551. */
  552. /* TODO: get current AL_INPUT_SOURCE and output device and put these at the head of the list */
  553. i = 0;
  554. if (alGetResourceByName(AL_SYSTEM,"Microphone",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = MICROPHONE_DEVICE; i++;}
  555. if (alGetResourceByName(AL_SYSTEM,"Analog Out",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = DAC_OUT_DEVICE; i++;}
  556. if (alGetResourceByName(AL_SYSTEM,"ADAT In",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = ADAT_IN_DEVICE; i++;}
  557. if (alGetResourceByName(AL_SYSTEM,"AES In",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = AES_IN_DEVICE; i++;}
  558. if (alGetResourceByName(AL_SYSTEM,"ADAT Out",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = ADAT_OUT_DEVICE; i++;}
  559. if (alGetResourceByName(AL_SYSTEM,"AES Out",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = AES_OUT_DEVICE; i++;}
  560. if (alGetResourceByName(AL_SYSTEM,"Line In",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = LINE_IN_DEVICE; i++;}
  561. /* if (alGetResourceByName(AL_SYSTEM,"DAC2 In",AL_DEVICE_TYPE) != 0) {if ((i+1)<chan) val[i+1] = DIGITAL_IN_DEVICE; i++;} */
  562. val[0] = i;
  563. break;
  564. case FORMAT_FIELD: val[0] = 1; if (chan>1) val[1] = snd_16_linear; break;
  565. case CHANNEL_FIELD:
  566. x[0].param = AL_CHANNELS;
  567. al_err = alGetParams(rv,x,1); if (al_err == -1) return(error_exit(READ_ERROR,-1));
  568. val[0] = (float)(x[0].value.i);
  569. break;
  570. case SRATE_FIELD:
  571. x[0].param = AL_RATE;
  572. al_err = alGetParams(rv,x,1); if (al_err == -1) return(error_exit(READ_ERROR,-1));
  573. val[0] = (float)(x[0].value.i);
  574. break;
  575. case AMP_FIELD:
  576. al_err = alGetParamInfo(rv,AL_GAIN,&pinf); if (al_err == -1) return(error_exit(READ_ERROR,-1));
  577. if (pinf.min.ll == pinf.max.ll) return(error_exit(AMP_NOT_AVAILABLE,-1));
  578. /* this ridiculous thing is in dB with completely arbitrary min and max values */
  579. x[0].param = AL_GAIN;
  580. x[0].value.ptr = g;
  581. x[0].sizeIn = MAX_CHANNELS;
  582. al_err = alGetParams(rv,x,1); if (x[0].sizeOut <= chan) return(error_exit(CHANNELS_NOT_AVAILABLE,-1));
  583. val[0] = dB_to_normalized(alFixedToDouble(g[chan]),alFixedToDouble(pinf.min.ll),alFixedToDouble(pinf.max.ll));
  584. break;
  585. default: AUDIO_ERROR = CANT_READ; break;
  586. }
  587. if (AUDIO_ERROR != NO_ERROR) return(-1);
  588. return(0);
  589. }
  590. int write_audio_state(int ur_dev, int field, int chan, float *val)
  591. {
  592. /* each field coming in assumes 0.0 to 1.0 as the range */
  593. ALpv x[4];
  594. ALparamInfo pinf;
  595. ALfixed g[MAX_CHANNELS];
  596. int rv,dev;
  597. long fld;
  598. double amp;
  599. AUDIO_ERROR = NO_ERROR; al_err = 0;
  600. dev = SNDLIB_DEVICE(ur_dev);
  601. rv = to_al_device(dev); if (!rv) return(error_exit(DEVICE_NOT_AVAILABLE,-1));
  602. switch (field)
  603. {
  604. case SRATE_FIELD:
  605. x[0].param = AL_RATE;
  606. x[0].value.i = (int)val[0];
  607. x[1].param = AL_MASTER_CLOCK;
  608. x[1].value.i = AL_CRYSTAL_MCLK_TYPE;
  609. alSetParams(rv,x,2);
  610. break;
  611. case AMP_FIELD:
  612. /* need to change normalized linear value into dB between (dB) lo and hi */
  613. al_err = alGetParamInfo(rv,AL_GAIN,&pinf); if (al_err == -1) return(error_exit(READ_ERROR,-1));
  614. /* I think we need to read all channels here, change the one we care about, then write all channels */
  615. x[0].param = AL_GAIN;
  616. x[0].value.ptr = g;
  617. x[0].sizeIn = MAX_CHANNELS;
  618. al_err = alGetParams(rv,x,1); if (x[0].sizeOut <= chan) return(error_exit(CHANNELS_NOT_AVAILABLE,-1));
  619. g[chan] = alDoubleToFixed(normalized_to_dB(val[0],alFixedToDouble(pinf.min.ll),alFixedToDouble(pinf.max.ll)));
  620. al_err = alSetParams(rv,x,1); if (al_err == -1) return(error_exit(WRITE_ERROR,-1));
  621. break;
  622. case DEVICE_FIELD:
  623. /* TODO: */
  624. /* how to set digital in??? */
  625. AUDIO_ERROR = CANT_WRITE;
  626. break;
  627. default: AUDIO_ERROR = CANT_WRITE; break;
  628. }
  629. if (AUDIO_ERROR != NO_ERROR) return(-1);
  630. return(0);
  631. }
  632. #define STRING_SIZE 32
  633. static void dump_resources(ALvalue *x,int rv)
  634. {
  635. ALpv y[4];
  636. ALpv yy;
  637. ALparamInfo pinf;
  638. ALfixed g[MAX_CHANNELS];
  639. char dn[STRING_SIZE];
  640. char dl[STRING_SIZE];
  641. int i,k;
  642. ALvalue z[16];
  643. int nres;
  644. for (i=0;i<rv;i++)
  645. {
  646. y[0].param = AL_LABEL;
  647. y[0].value.ptr = dl;
  648. y[0].sizeIn = STRING_SIZE;
  649. y[1].param = AL_NAME;
  650. y[1].value.ptr = dn;
  651. y[1].sizeIn = STRING_SIZE;
  652. y[2].param = AL_CHANNELS;
  653. y[3].param = AL_RATE;
  654. alGetParams(x[i].i,y,5);
  655. if (alIsSubtype(AL_DEVICE_TYPE, x[i].i))
  656. {
  657. al_err = alGetParamInfo(x[i].i,AL_GAIN,&pinf);
  658. sprintf(strbuf,"\nDevice name: '%s', label: '%s', srate: %d, chans: %d",
  659. dn,dl,
  660. y[3].value.i,y[2].value.i);
  661. pprint(strbuf);
  662. if (pinf.min.ll != pinf.max.ll)
  663. {
  664. yy.param = AL_GAIN;
  665. yy.value.ptr = g;
  666. yy.sizeIn = MAX_CHANNELS;
  667. alGetParams(x[i].i,&yy,1);
  668. pprint(" amps:[");
  669. for (k=0;k<yy.sizeOut;k++)
  670. {
  671. sprintf(strbuf,"%.2f",dB_to_normalized(alFixedToDouble(g[k]),alFixedToDouble(pinf.min.ll),alFixedToDouble(pinf.max.ll)));
  672. pprint(strbuf);
  673. if (k<(yy.sizeOut-1)) pprint(" ");
  674. }
  675. pprint("]");
  676. }
  677. pprint("\n");
  678. if ((nres= alQueryValues(x[i].i,AL_INTERFACE,z,16,0,0))>=0)
  679. dump_resources(z,nres);
  680. else sprintf(strbuf,"query failed: %s\n",alGetErrorString(oserror()));
  681. pprint(strbuf);
  682. }
  683. else
  684. {
  685. sprintf(strbuf," Interface name: '%s', label: '%s', chans: %d\n",dn,dl,y[2].value.i);
  686. pprint(strbuf);
  687. }
  688. }
  689. }
  690. static void describe_audio_state_1(void)
  691. {
  692. int rv;
  693. ALvalue x[16];
  694. if (!strbuf) strbuf = (char *)CALLOC(STRBUF_SIZE,sizeof(char));
  695. pprint("Devices and Interfaces on this system:\n");
  696. rv= alQueryValues(AL_SYSTEM,AL_DEVICES,x,16,0,0);
  697. if (rv>0) dump_resources(x,rv);
  698. }
  699. typedef struct {
  700. int dev,has_gains;
  701. ALfixed gains[MAX_CHANNELS];
  702. int srate;
  703. } saved_info;
  704. #define MAX_SAVED_DEVICES 16
  705. static saved_info *si[MAX_SAVED_DEVICES];
  706. static int saved_devices = 0;
  707. static void save_devices(ALvalue *x,int rv)
  708. {
  709. ALpv y;
  710. saved_info *sv;
  711. ALparamInfo pinf;
  712. ALfixed g[MAX_CHANNELS];
  713. int i,k;
  714. ALvalue z[16];
  715. int nres;
  716. if (saved_devices >= MAX_SAVED_DEVICES) return;
  717. for (i=0;i<rv;i++)
  718. {
  719. si[saved_devices] = (saved_info *)CALLOC(1,sizeof(saved_info));
  720. sv = si[saved_devices];
  721. sv->dev = x[i].i;
  722. y.param = AL_RATE;
  723. alGetParams(x[i].i,&y,1);
  724. sv->srate = y.value.i;
  725. saved_devices++;
  726. if (alIsSubtype(AL_DEVICE_TYPE, x[i].i))
  727. {
  728. alGetParamInfo(x[i].i,AL_GAIN,&pinf);
  729. if (pinf.min.ll != pinf.max.ll)
  730. {
  731. y.param = AL_GAIN;
  732. y.value.ptr = sv->gains;
  733. y.sizeIn = MAX_CHANNELS;
  734. alGetParams(x[i].i,&y,1);
  735. sv->has_gains = 1;
  736. }
  737. else sv->has_gains = 0;
  738. if ((nres = alQueryValues(x[i].i,AL_INTERFACE,z,16,0,0))>=0) save_devices(z,nres);
  739. }
  740. }
  741. }
  742. void save_audio_state (void)
  743. {
  744. int rv,i;
  745. ALvalue x[16];
  746. if (saved_devices>0)
  747. {
  748. for (i=0;i<saved_devices;i++)
  749. {
  750. if (si[i])
  751. {
  752. FREE(si[i]);
  753. si[i] = NULL;
  754. }
  755. }
  756. }
  757. saved_devices = 0;
  758. rv= alQueryValues(AL_SYSTEM,AL_DEVICES,x,16,0,0);
  759. if (rv>0) save_devices(x,rv);
  760. }
  761. void restore_audio_state (void)
  762. {
  763. int i;
  764. ALpv x;
  765. if (saved_devices > 0)
  766. {
  767. for (i=0;i<saved_devices;i++)
  768. {
  769. if (si[i])
  770. {
  771. if (si[i]->has_gains)
  772. {
  773. x.param = AL_GAIN;
  774. x.value.ptr = si[i]->gains;
  775. x.sizeIn = MAX_CHANNELS;
  776. alSetParams(si[i]->dev,&x,1);
  777. }
  778. x.param = AL_RATE;
  779. x.value.i = si[i]->srate;
  780. alSetParams(si[i]->dev,&x,1);
  781. }
  782. }
  783. }
  784. }
  785. #else
  786. /* old audio library */
  787. #define MAX_VOLUME 255
  788. static int decode_field(int dev, int field, int chan)
  789. {
  790. int fld = -1;
  791. switch (dev)
  792. {
  793. case DEFAULT_DEVICE:
  794. case DAC_OUT_DEVICE:
  795. case READ_WRITE_DEVICE:
  796. case SPEAKERS_DEVICE:
  797. switch (field)
  798. {
  799. case AMP_FIELD:
  800. fld = ((chan == 0) ? AL_LEFT_SPEAKER_GAIN : AL_RIGHT_SPEAKER_GAIN);
  801. break;
  802. case SRATE_FIELD:
  803. fld = AL_OUTPUT_RATE;
  804. break;
  805. }
  806. break;
  807. case ADAT_IN_DEVICE: case ADAT_OUT_DEVICE:
  808. case AES_IN_DEVICE: case AES_OUT_DEVICE:
  809. AUDIO_ERROR = CONFIGURATION_NOT_AVAILABLE;
  810. break;
  811. case LINE_OUT_DEVICE:
  812. switch (field)
  813. {
  814. case SRATE_FIELD:
  815. fld = AL_OUTPUT_RATE; /* ? */
  816. break;
  817. }
  818. break;
  819. case DIGITAL_OUT_DEVICE:
  820. if (field == SRATE_FIELD)
  821. fld = AL_OUTPUT_RATE;
  822. else AUDIO_ERROR = CONFIGURATION_NOT_AVAILABLE;
  823. break;
  824. case DIGITAL_IN_DEVICE:
  825. if (field == SRATE_FIELD)
  826. fld = AL_INPUT_RATE;
  827. else AUDIO_ERROR = CONFIGURATION_NOT_AVAILABLE;
  828. break;
  829. case LINE_IN_DEVICE:
  830. if (field == AMP_FIELD)
  831. fld = ((chan == 0) ? AL_LEFT_INPUT_ATTEN : AL_RIGHT_INPUT_ATTEN);
  832. else
  833. {
  834. if (field == SRATE_FIELD)
  835. fld = AL_INPUT_RATE;
  836. else AUDIO_ERROR = CONFIGURATION_NOT_AVAILABLE;
  837. }
  838. break;
  839. case MICROPHONE_DEVICE:
  840. if (field == AMP_FIELD)
  841. fld = ((chan == 0) ? AL_LEFT2_INPUT_ATTEN : AL_RIGHT2_INPUT_ATTEN);
  842. else
  843. {
  844. if (field == SRATE_FIELD)
  845. fld = AL_INPUT_RATE;
  846. else AUDIO_ERROR = CONFIGURATION_NOT_AVAILABLE;
  847. }
  848. break;
  849. }
  850. return(fld);
  851. }
  852. int read_audio_state(int ur_dev, int field, int chan, float *val)
  853. {
  854. long pb[4];
  855. long fld;
  856. int dev;
  857. AUDIO_ERROR = NO_ERROR; al_err = 0;
  858. dev = SNDLIB_DEVICE(ur_dev);
  859. switch (field)
  860. {
  861. case CHANNEL_FIELD:
  862. val[0] = 2;
  863. break;
  864. case FORMAT_FIELD: val[0] = 1; if (chan>1) val[1] = snd_16_linear; break;
  865. case DEVICE_FIELD:
  866. /* how to tell which machine we're on? */
  867. /* TODO: put default in/out devices first */
  868. val[0] = 4;
  869. if (chan>1) val[1]=LINE_IN_DEVICE;
  870. if (chan>2) val[2]=MICROPHONE_DEVICE;
  871. if (chan>3) val[3]=DIGITAL_IN_DEVICE;
  872. if (chan>4) val[4]=DAC_OUT_DEVICE;
  873. /* does this order work for digital input as well? (i.e. does it replace the microphone)? */
  874. break;
  875. case AMP_FIELD:
  876. fld = decode_field(dev,field,chan);
  877. if (fld != -1)
  878. {
  879. pb[0] = fld;
  880. al_err = ALgetparams(AL_DEFAULT_DEVICE,pb,2);
  881. if ((fld == AL_LEFT_SPEAKER_GAIN) || (fld == AL_RIGHT_SPEAKER_GAIN))
  882. val[0] = ((float)pb[1])/((float)MAX_VOLUME);
  883. else val[0] = 1.0 - ((float)pb[1])/((float)MAX_VOLUME);
  884. if (al_err) AUDIO_ERROR = READ_ERROR;
  885. }
  886. break;
  887. case SRATE_FIELD:
  888. fld = decode_field(dev,field,chan);
  889. if (fld != -1)
  890. {
  891. pb[0] = fld;
  892. al_err = ALgetparams(AL_DEFAULT_DEVICE,pb,2);
  893. val[0] = pb[1];
  894. if (al_err) AUDIO_ERROR = READ_ERROR;
  895. }
  896. break;
  897. default: AUDIO_ERROR = CANT_READ; break;
  898. }
  899. if (AUDIO_ERROR != NO_ERROR) return(-1);
  900. return(0);
  901. }
  902. int write_audio_state(int ur_dev, int field, int chan, float *val)
  903. {
  904. long pb[4];
  905. long fld;
  906. int dev;
  907. AUDIO_ERROR = NO_ERROR; al_err = 0;
  908. dev = SNDLIB_DEVICE(ur_dev);
  909. switch (field)
  910. {
  911. case DEVICE_FIELD:
  912. if (dev == DEFAULT_DEVICE)
  913. {
  914. pb[0] = AL_CHANNEL_MODE;
  915. pb[1] = ((chan == DIGITAL_IN_DEVICE) ? AL_STEREO : AL_4CHANNEL);
  916. pb[2] = AL_INPUT_SOURCE;
  917. pb[3] = ((chan == DIGITAL_IN_DEVICE) ? AL_INPUT_DIGITAL : AL_INPUT_MIC);
  918. al_err = ALsetparams(AL_DEFAULT_DEVICE,pb,4);
  919. if (al_err) AUDIO_ERROR = WRITE_ERROR;
  920. }
  921. else AUDIO_ERROR = CANT_WRITE;
  922. break;
  923. case CHANNEL_FIELD:
  924. if (dev == MICROPHONE_DEVICE)
  925. {
  926. pb[0] = AL_MIC_MODE;
  927. pb[1] = ((chan == 2) ? AL_STEREO : AL_MONO);
  928. al_err = ALsetparams(AL_DEFAULT_DEVICE,pb,2);
  929. if (al_err) AUDIO_ERROR = WRITE_ERROR;
  930. }
  931. else
  932. {
  933. if (dev == DEFAULT_DEVICE)
  934. {
  935. pb[0] = AL_CHANNEL_MODE;
  936. pb[1] = ((chan == 4) ? AL_4CHANNEL : AL_STEREO);
  937. al_err = ALsetparams(AL_DEFAULT_DEVICE,pb,2);
  938. if (al_err) AUDIO_ERROR = WRITE_ERROR;
  939. }
  940. else AUDIO_ERROR = CANT_WRITE;
  941. }
  942. break;
  943. case AMP_FIELD:
  944. fld = decode_field(dev,field,chan);
  945. if (fld != -1)
  946. {
  947. pb[0] = fld;
  948. if ((fld == AL_LEFT_SPEAKER_GAIN) || (fld == AL_RIGHT_SPEAKER_GAIN))
  949. pb[1] = val[0] * MAX_VOLUME;
  950. else pb[1] = (1.0 - val[0])*MAX_VOLUME;
  951. al_err = ALsetparams(AL_DEFAULT_DEVICE,pb,2);
  952. if (al_err) AUDIO_ERROR = WRITE_ERROR;
  953. }
  954. else AUDIO_ERROR = CANT_WRITE;
  955. break;
  956. case SRATE_FIELD:
  957. fld = decode_field(dev,field,chan);
  958. if (fld != -1)
  959. {
  960. pb[0] = fld;
  961. pb[1] = val[0];
  962. al_err = ALsetparams(AL_DEFAULT_DEVICE,pb,2);
  963. if (al_err)
  964. AUDIO_ERROR = WRITE_ERROR;
  965. else
  966. {
  967. if (fld == AL_INPUT_RATE)
  968. {
  969. pb[0] = AL_OUTPUT_RATE;
  970. pb[1] = val[0];
  971. al_err = ALsetparams(AL_DEFAULT_DEVICE,pb,2);
  972. if (al_err) AUDIO_ERROR = WRITE_ERROR;
  973. }
  974. }
  975. }
  976. else AUDIO_ERROR = CANT_WRITE;
  977. break;
  978. default: AUDIO_ERROR = CANT_WRITE; break;
  979. }
  980. if (AUDIO_ERROR != NO_ERROR) return(-1);
  981. return(0);
  982. }
  983. static void describe_audio_state_1(void)
  984. {
  985. float amps[1];
  986. int err;
  987. if (!strbuf) strbuf = (char *)CALLOC(STRBUF_SIZE,sizeof(char));
  988. err = read_audio_state(SPEAKERS_DEVICE,SRATE_FIELD,0,amps);
  989. if (err == NO_ERROR) {sprintf(strbuf,"srate: %.2f\n",amps[0]); pprint(strbuf);} else {fprintf(stdout,"err: %d!\n",err); fflush(stdout);}
  990. err = read_audio_state(SPEAKERS_DEVICE,AMP_FIELD,0,amps);
  991. if (err == NO_ERROR) {sprintf(strbuf,"speakers: %.2f",amps[0]); pprint(strbuf);}
  992. err = read_audio_state(SPEAKERS_DEVICE,AMP_FIELD,1,amps);
  993. if (err == NO_ERROR) {sprintf(strbuf," %.2f\n",amps[0]); pprint(strbuf);}
  994. err = read_audio_state(LINE_IN_DEVICE,AMP_FIELD,0,amps);
  995. if (err == NO_ERROR) {sprintf(strbuf,"line in: %.2f",amps[0]); pprint(strbuf);}
  996. err = read_audio_state(LINE_IN_DEVICE,AMP_FIELD,1,amps);
  997. if (err == NO_ERROR) {sprintf(strbuf," %.2f\n",amps[0]); pprint(strbuf);}
  998. err = read_audio_state(MICROPHONE_DEVICE,AMP_FIELD,0,amps);
  999. if (err == NO_ERROR) {sprintf(strbuf,"microphone: %.2f",amps[0]); pprint(strbuf);}
  1000. err = read_audio_state(MICROPHONE_DEVICE,AMP_FIELD,1,amps);
  1001. if (err == NO_ERROR) {sprintf(strbuf," %.2f\n",amps[0]); pprint(strbuf);}
  1002. err = read_audio_state(LINE_OUT_DEVICE,AMP_FIELD,0,amps);
  1003. if (err == NO_ERROR) {sprintf(strbuf,"line out: %.2f",amps[0]); pprint(strbuf);}
  1004. err = read_audio_state(LINE_OUT_DEVICE,AMP_FIELD,1,amps);
  1005. if (err == NO_ERROR) {sprintf(strbuf," %.2f\n",amps[0]); pprint(strbuf);}
  1006. err = read_audio_state(DIGITAL_OUT_DEVICE,AMP_FIELD,0,amps);
  1007. if (err == NO_ERROR) {sprintf(strbuf,"digital out: %.2f",amps[0]); pprint(strbuf);}
  1008. err = read_audio_state(DIGITAL_OUT_DEVICE,AMP_FIELD,1,amps);
  1009. if (err == NO_ERROR) {sprintf(strbuf," %.2f\n",amps[0]); pprint(strbuf);}
  1010. }
  1011. static long init_state[22];
  1012. void save_audio_state (void)
  1013. {
  1014. /* save channel mode, input source, left/right atten (2), speaker gain, input/output rate, mic_mode */
  1015. AUDIO_ERROR = NO_ERROR; al_err = 0;
  1016. init_state[0] = AL_CHANNEL_MODE;
  1017. init_state[2] = AL_INPUT_SOURCE;
  1018. init_state[4] = AL_LEFT_INPUT_ATTEN;
  1019. init_state[6] = AL_RIGHT_INPUT_ATTEN;
  1020. init_state[8] = AL_LEFT2_INPUT_ATTEN;
  1021. init_state[10] = AL_RIGHT2_INPUT_ATTEN;
  1022. init_state[12] = AL_MIC_MODE;
  1023. init_state[14] = AL_LEFT_SPEAKER_GAIN;
  1024. init_state[16] = AL_RIGHT_SPEAKER_GAIN;
  1025. init_state[18] = AL_INPUT_RATE;
  1026. init_state[20] = AL_OUTPUT_RATE;
  1027. al_err = ALgetparams(AL_DEFAULT_DEVICE,init_state,22);
  1028. if (al_err) AUDIO_ERROR = READ_ERROR;
  1029. }
  1030. void restore_audio_state (void)
  1031. {
  1032. AUDIO_ERROR = NO_ERROR; al_err = 0;
  1033. al_err = ALsetparams(AL_DEFAULT_DEVICE,init_state,22);
  1034. if (al_err) AUDIO_ERROR = WRITE_ERROR;
  1035. }
  1036. #endif
  1037. /* new or old AL */
  1038. #endif
  1039. /* SGI */
  1040. /* ------------------------------- OSS ----------------------------------------- */
  1041. #if HAVE_OSS
  1042. #define AUDIO_OK
  1043. #include <sys/ioctl.h>
  1044. /* the system version of the soundcard header file may have no relation to the current OSS actually loaded */
  1045. /* sys/soundcard.h is usually just a pointer to linux/soundcard.h */
  1046. #if (USR_LIB_OSS)
  1047. #include "/usr/lib/oss/include/sys/soundcard.h"
  1048. #else
  1049. #if (USR_LOCAL_LIB_OSS)
  1050. #include "/usr/local/lib/oss/include/sys/soundcard.h"
  1051. #else
  1052. #if defined(HAVE_SYS_SOUNDCARD_H) || defined(LINUX) || defined(UW2)
  1053. #include <sys/soundcard.h>
  1054. #else
  1055. #if defined(HAVE_MACHINE_SOUNDCARD_H)
  1056. #include <machine/soundcard.h>
  1057. #else
  1058. #include <soundcard.h>
  1059. #endif
  1060. #endif
  1061. #endif
  1062. #endif
  1063. #if ((SOUND_VERSION > 360) && (defined(OSS_SYSINFO)))
  1064. /* apparently OSS is trying to hide its new structs from non-paying customers!
  1065. * the OSS/Free version of soundcard.h has the current version number, but not the
  1066. * associated struct definitions. This is not a good turn of events...
  1067. */
  1068. #define NEW_OSS
  1069. #endif
  1070. #define MAX_VOLUME 100
  1071. #define DAC_NAME "/dev/dsp"
  1072. #define MIXER_NAME "/dev/mixer"
  1073. #define SYNTH_NAME "/dev/music"
  1074. /* some programs use /dev/audio */
  1075. /* there can be more than one sound card installed, and a card can be handled through
  1076. * more than one /dev/dsp device, so we can't use a global dac device here.
  1077. * The caller has to keep track of the various cards (via AUDIO_SYSTEM) --
  1078. * I toyed with embedding all that in open_audio_output and write_audio, but
  1079. * decided it's better to keep them explicit -- the caller may want entirely
  1080. * different (non-synchronous) streams going to the various cards. This same
  1081. * code (AUDIO_SYSTEM(n)->devn) should work in Windoze (see below), and
  1082. * might work on the Mac and SGI -- something for a rainy day...
  1083. */
  1084. static int FRAGMENTS = 4;
  1085. static int FRAGMENT_SIZE = 12;
  1086. static int fragments_locked = 0;
  1087. /* defaults here are FRAGMENTS 16 and FRAGMENT_SIZE 12; these values however
  1088. * cause about a .5 second delay, which is not acceptable in "real-time" situations.
  1089. */
  1090. void set_oss_buffers(int num,int size) {FRAGMENTS = num; FRAGMENT_SIZE = size; fragments_locked = 1;}
  1091. char *audio_error_name(int err) {return(audio_error_name_1(err));}
  1092. #define MAX_SOUNDCARDS 8
  1093. #define MAX_DSPS 8
  1094. #define MAX_MIXERS 8
  1095. /* there can be (apparently) any number of mixers and dsps per soundcard, but 8 is enough! */
  1096. static int audio_fd[MAX_SOUNDCARDS];
  1097. static int audio_open_ctr[MAX_SOUNDCARDS];
  1098. static int audio_dsp[MAX_SOUNDCARDS];
  1099. static int audio_mixer[MAX_SOUNDCARDS];
  1100. static int sound_cards = 0;
  1101. static int new_oss_running = 0;
  1102. static char dev_name[32];
  1103. int audio_systems(void)
  1104. {
  1105. return(sound_cards);
  1106. }
  1107. static char *mixer_name(int sys)
  1108. {
  1109. if (sys < sound_cards)
  1110. {
  1111. sprintf(dev_name,"%s%d",MIXER_NAME,(audio_mixer[sys] == -2) ? 0 : audio_mixer[sys]);
  1112. return(dev_name);
  1113. }
  1114. return(DAC_NAME);
  1115. }
  1116. char *audio_system_name(int system)
  1117. {
  1118. #ifdef NEW_OSS
  1119. static mixer_info mixinfo;
  1120. int status,ignored,fd;
  1121. fd = open(mixer_name(system),O_RDONLY,0);
  1122. if (fd != -1)
  1123. {
  1124. status = ioctl(fd,OSS_GETVERSION,&ignored);
  1125. if (status == 0)
  1126. {
  1127. status = ioctl(fd,SOUND_MIXER_INFO,&mixinfo);
  1128. if (status == 0)
  1129. {
  1130. close(fd);
  1131. return(mixinfo.name);
  1132. }
  1133. }
  1134. close(fd);
  1135. }
  1136. #endif
  1137. return("OSS");
  1138. }
  1139. static char *dac_name(int sys, int offset)
  1140. {
  1141. if ((sys < sound_cards) && (audio_mixer[sys] != -2))
  1142. {
  1143. sprintf(dev_name,"%s%d",DAC_NAME,audio_dsp[sys]+offset);
  1144. return(dev_name);
  1145. }
  1146. return(DAC_NAME);
  1147. }
  1148. void setup_dsps(int cards, int *dsps, int *mixers)
  1149. {
  1150. /* see note below -- there are still bugs in OSS multi-cards support, so sometimes the map has to be made by hand */
  1151. int i;
  1152. if (cards > MAX_SOUNDCARDS) cards = MAX_SOUNDCARDS;
  1153. sound_cards = cards;
  1154. for (i=0;i<cards;i++)
  1155. {
  1156. audio_dsp[i] = dsps[i];
  1157. audio_mixer[i] = mixers[i];
  1158. }
  1159. }
  1160. int initialize_audio(void)
  1161. {
  1162. /* here we need to set up the map of /dev/dsp and /dev/mixer to a given system */
  1163. /* since this info is not passed to us by OSS, we have to work at it... */
  1164. /* for the time being, I'll ignore auxiliary dsp and mixer ports (each is a special case) */
  1165. int i,fd,md,err;
  1166. char dname[16];
  1167. int amp,old_mixer_amp,old_dsp_amp,new_mixer_amp,responsive_field;
  1168. int devmask;
  1169. #ifdef NEW_OSS
  1170. int status,ignored;
  1171. oss_sysinfo sysinfo;
  1172. int sysinfo_ok = 0;
  1173. #endif
  1174. int num_mixers,num_dsps,nmix,ndsp;
  1175. if (!audio_initialized)
  1176. {
  1177. audio_initialized = 1;
  1178. AUDIO_ERROR = NO_ERROR;
  1179. for (i=0;i<MAX_SOUNDCARDS;i++)
  1180. {
  1181. audio_fd[i] = -1;
  1182. audio_open_ctr[i] = 0;
  1183. audio_dsp[i] = -1;
  1184. audio_mixer[i] = -1;
  1185. }
  1186. num_mixers = MAX_MIXERS;
  1187. num_dsps = MAX_DSPS;
  1188. #ifdef NEW_OSS
  1189. fd = open(DAC_NAME,O_WRONLY,0);
  1190. if (fd == -1) fd = open(SYNTH_NAME,O_RDONLY,0);
  1191. if (fd == -1) fd = open(MIXER_NAME,O_RDONLY,0);
  1192. if (fd != -1)
  1193. {
  1194. status = ioctl(fd,OSS_GETVERSION,&ignored);
  1195. new_oss_running = (status == 0);
  1196. if (new_oss_running)
  1197. {
  1198. status = ioctl(fd,OSS_SYSINFO,&sysinfo);
  1199. sysinfo_ok = (status == 0);
  1200. }
  1201. if ((new_oss_running) && (sysinfo_ok))
  1202. {
  1203. num_mixers = sysinfo.nummixers;
  1204. num_dsps = sysinfo.numaudios;
  1205. }
  1206. }
  1207. close(fd);
  1208. #endif
  1209. /* need to get which /dev/dsp lines match which /dev/mixer lines,
  1210. * find out how many separate systems (soundcards) are available,
  1211. * fill the audio_dsp and audio_mixer arrays with the system-related numbers,
  1212. * since we have no way to tell from OSS info which mixers/dsps are the
  1213. * main ones, we'll do some messing aound to try to deduce this info.
  1214. * for example, SB uses two dsp ports and two mixers pre card, whereas
  1215. * Ensoniq uses 2 dsps and 1 mixer.
  1216. *
  1217. * the data we are gathering here:
  1218. * int audio_dsp[MAX_SOUNDCARDS] -> main_dsp_port[AUDIO_SYSTEM(n)] (-1 => no such system dsp)
  1219. * int audio_mixer[MAX_SOUNDCARDS] -> main_mixer_port[AUDIO_SYSTEM(n)]
  1220. * int sound_cards = 0 -> usable systems
  1221. * all auxiliary ports are currently ignored (SB equalizer, etc)
  1222. */
  1223. sound_cards = 0;
  1224. ndsp = 0;
  1225. nmix = 0;
  1226. while ((nmix<num_mixers) && (ndsp < num_dsps))
  1227. {
  1228. /* for each mixer, find associated main dsp (assumed to be first in /dev/dsp ordering) */
  1229. /* if mixer's dsp overlaps or we run out of dsps first, ignore it (aux mixer) */
  1230. /* our by-guess-or-by-gosh method here is to try to open the mixer.
  1231. * if that fails, quit (if very first, try at least to get the dsp setup)
  1232. * find volume field, if none, go on, else read current volume
  1233. * open next unchecked dsp, try to set volume, read current, if different we found a match -- set and go on.
  1234. * if no change, move to next dsp and try again, if no more dsps, quit (checking for null case as before)
  1235. */
  1236. sprintf(dname,"%s%d",MIXER_NAME,nmix);
  1237. md = open(dname,O_RDWR,0);
  1238. if (md == -1) {if (errno == EBUSY) {sprintf(strbuf,"%s is busy: can't access it",dname); pprint(strbuf); break;}}
  1239. sprintf(dname,"%s%d",DAC_NAME,ndsp);
  1240. fd = open(dname,O_RDWR,0);
  1241. if (fd == -1) {close(md); if (errno == EBUSY) fprintf(stderr,"%s is busy: can't access it\n",dname); break;}
  1242. err = ioctl(md,SOUND_MIXER_READ_DEVMASK,&devmask);
  1243. responsive_field = SOUND_MIXER_VOLUME;
  1244. for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
  1245. if ((1<<i) & devmask)
  1246. {
  1247. responsive_field = i;
  1248. break;
  1249. }
  1250. if (!err)
  1251. {
  1252. err = ioctl(md,MIXER_READ(responsive_field),&old_mixer_amp);
  1253. if (!err)
  1254. {
  1255. err = ioctl(fd,MIXER_READ(responsive_field),&old_dsp_amp);
  1256. if ((!err) && (old_dsp_amp == old_mixer_amp))
  1257. {
  1258. if (old_mixer_amp == 0) amp = 50; else amp = 0; /* 0..100 */
  1259. err = ioctl(fd,MIXER_WRITE(responsive_field),&amp);
  1260. if (!err)
  1261. {
  1262. err = ioctl(md,MIXER_READ(responsive_field),&new_mixer_amp);
  1263. if (!err)
  1264. {
  1265. if (new_mixer_amp == amp)
  1266. {
  1267. /* found one! */
  1268. audio_dsp[sound_cards] = ndsp; ndsp++;
  1269. audio_mixer[sound_cards] = nmix; nmix++;
  1270. sound_cards++;
  1271. }
  1272. else ndsp++;
  1273. err = ioctl(fd,MIXER_WRITE(responsive_field),&old_dsp_amp);
  1274. }
  1275. else nmix++;
  1276. }
  1277. else ndsp++;
  1278. }
  1279. else ndsp++;
  1280. }
  1281. else nmix++;
  1282. }
  1283. else nmix++;
  1284. close(fd);
  1285. close(md);
  1286. }
  1287. if (sound_cards == 0)
  1288. {
  1289. fd = open(DAC_NAME,O_WRONLY,0);
  1290. if (fd != -1)
  1291. {
  1292. sound_cards = 1;
  1293. audio_dsp[0] = 0;
  1294. audio_mixer[0] = -2; /* hmmm -- need a way to see /dev/dsp as lonely outpost */
  1295. close(fd);
  1296. }
  1297. }
  1298. }
  1299. return(0);
  1300. }
  1301. /* TODO: fix this to handle aux devices correctly */
  1302. static int linux_audio_open(const char *pathname, int flags, mode_t mode, int system)
  1303. {
  1304. if (audio_fd[system] == -1)
  1305. {
  1306. audio_fd[system] = open(pathname,flags,mode);
  1307. audio_open_ctr[system] = 0;
  1308. }
  1309. else audio_open_ctr[system]++;
  1310. return(audio_fd[system]);
  1311. }
  1312. static int find_system(int line)
  1313. {
  1314. int i;
  1315. for (i=0;i<MAX_SOUNDCARDS;i++)
  1316. {
  1317. if (line == audio_fd[i])
  1318. return(i);
  1319. }
  1320. return(-1);
  1321. }
  1322. static int linux_audio_close(int fd)
  1323. {
  1324. int err = 0,sys;
  1325. if (fd != -1)
  1326. {
  1327. sys = find_system(fd);
  1328. if (sys != -1)
  1329. {
  1330. if (audio_open_ctr[sys] > 0)
  1331. audio_open_ctr[sys]--;
  1332. else
  1333. {
  1334. err = close(fd);
  1335. audio_open_ctr[sys] = 0;
  1336. audio_fd[sys] = -1;
  1337. }
  1338. }
  1339. else err = close(fd);
  1340. }
  1341. return(err);
  1342. }
  1343. static int error_exit(int error, int line)
  1344. {
  1345. AUDIO_ERROR = error;
  1346. if (line != -1) linux_audio_close(line);
  1347. return(-1);
  1348. }
  1349. static int to_oss_format(int snd_format)
  1350. {
  1351. switch (snd_format)
  1352. {
  1353. case snd_8_linear: return(AFMT_S8); break;
  1354. case snd_16_linear: return(AFMT_S16_BE); break;
  1355. case snd_8_unsigned: return(AFMT_U8); break;
  1356. case snd_8_mulaw: return(AFMT_MU_LAW); break;
  1357. case snd_8_alaw: return(AFMT_A_LAW); break;
  1358. case snd_16_linear_little_endian: return(AFMT_S16_LE); break;
  1359. case snd_16_unsigned: return(AFMT_U16_BE); break;
  1360. case snd_16_unsigned_little_endian: return(AFMT_U16_LE); break;
  1361. }
  1362. return(-1);
  1363. }
  1364. int open_audio_output(int ur_dev, int srate, int chans, int format, int size)
  1365. {
  1366. /* ur_dev is in general AUDIO_SYSTEM(n) | sndlib_DEVICE */
  1367. int oss_format,stereo,buffer_info,audio_out,sys,dev;
  1368. AUDIO_ERROR = NO_ERROR;
  1369. sys = SNDLIB_SYSTEM(ur_dev);
  1370. dev = SNDLIB_DEVICE(ur_dev);
  1371. oss_format = to_oss_format(format);
  1372. if (oss_format == -1) return(error_exit(FORMAT_NOT_AVAILABLE,-1));
  1373. if (chans == 2) stereo = 1; else stereo = 0;
  1374. if (dev == DEFAULT_DEVICE)
  1375. audio_out = linux_audio_open(dac_name(sys,0),O_WRONLY,0,sys);
  1376. else audio_out = linux_audio_open(dac_name(sys,(dev == AUX_OUTPUT_DEVICE) ? 1 : 0),O_RDWR,0,sys);
  1377. if (audio_out == -1) return(error_exit(CANT_OPEN,audio_out));
  1378. /* ioctl(audio_out,SNDCTL_DSP_RESET,0); */ /* causes clicks */
  1379. if ((dev == READ_WRITE_DEVICE) || (size != 0))
  1380. {
  1381. if (!fragments_locked) {if (srate > 30000) FRAGMENTS = 4; else FRAGMENTS = 2;}
  1382. buffer_info = (FRAGMENTS<<16) | (FRAGMENT_SIZE);
  1383. if (ioctl(audio_out,SNDCTL_DSP_SETFRAGMENT,&buffer_info) == -1)
  1384. {
  1385. /* older Linuces (or OSS's?) refuse to handle the fragment reset if O_RDWR used --
  1386. * someone at OSS forgot to update the version number when this was fixed, so
  1387. * I have no way to get around this except to try and retry...
  1388. *
  1389. * But, if we hope to get input as well, we can't open this WRONLY. This means
  1390. * that in Linux, the real-time controls in CLM will be very sluggish if input is active.
  1391. * We do what we can.
  1392. */
  1393. linux_audio_close(audio_out);
  1394. audio_out = linux_audio_open(dac_name(sys,(dev == AUX_OUTPUT_DEVICE) ? 1 : 0),O_WRONLY,0,sys);
  1395. if (audio_out == -1) return(error_exit(CANT_OPEN,audio_out));
  1396. buffer_info = (FRAGMENTS<<16) | (FRAGMENT_SIZE);
  1397. if (ioctl(audio_out,SNDCTL_DSP_SETFRAGMENT,&buffer_info) == -1) return(error_exit(CONFIGURATION_NOT_AVAILABLE,audio_out));
  1398. }
  1399. }
  1400. if ((ioctl(audio_out,SNDCTL_DSP_SETFMT,&oss_format) == -1) || (oss_format != to_oss_format(format)))
  1401. return(error_exit(FORMAT_NOT_AVAILABLE,audio_out));
  1402. if ((ioctl(audio_out,SNDCTL_DSP_STEREO,&stereo) == -1) || ((chans == 2) && (stereo == 0))) return(error_exit(CHANNELS_NOT_AVAILABLE,audio_out));
  1403. if (ioctl(audio_out,SNDCTL_DSP_SPEED,&srate) == -1) return(error_exit(SRATE_NOT_AVAILABLE,audio_out));
  1404. /* http://www.4front-tech.com/pguide/audio.html says this order has to be followed */
  1405. return(audio_out);
  1406. }
  1407. int write_audio(int line, char *buf, int bytes)
  1408. {
  1409. AUDIO_ERROR = NO_ERROR;
  1410. write(line,buf,bytes);
  1411. return(0);
  1412. }
  1413. int close_audio(int line)
  1414. {
  1415. AUDIO_ERROR = NO_ERROR;
  1416. return(linux_audio_close(line));
  1417. }
  1418. int read_audio(int line, char *buf, int bytes)
  1419. {
  1420. AUDIO_ERROR = NO_ERROR;
  1421. read(line,buf,bytes);
  1422. return(0);
  1423. }
  1424. int open_audio_input(int ur_dev, int srate, int chans, int format, int requested_size)
  1425. {
  1426. /* dev can be DEFAULT_DEVICE or READ_WRITE_DEVICE as well as the obvious others */
  1427. int audio_fd,oss_format,stereo,buffer_info,sys,dev,srcbit,cursrc;
  1428. AUDIO_ERROR = NO_ERROR;
  1429. sys = SNDLIB_SYSTEM(ur_dev);
  1430. dev = SNDLIB_DEVICE(ur_dev);
  1431. oss_format = to_oss_format(format);
  1432. if (oss_format == -1) return(error_exit(FORMAT_NOT_AVAILABLE,-1));
  1433. audio_fd = linux_audio_open(dac_name(sys,(dev == AUX_INPUT_DEVICE) ? 1 : 0),O_RDWR,0,sys);
  1434. if (audio_fd == -1)
  1435. {
  1436. if (dev == READ_WRITE_DEVICE) return(error_exit(CONFIGURATION_NOT_AVAILABLE,-1));
  1437. if ((audio_fd = linux_audio_open(dac_name(sys,(dev == AUX_INPUT_DEVICE) ? 1 : 0),O_RDONLY,0,sys)) == -1)
  1438. {
  1439. if ((errno == EACCES) || (errno == ENOENT))
  1440. {
  1441. fprintf(stdout,"(to get input in Linux, we need read permission on /dev/dsp)");
  1442. fflush(stdout);
  1443. return(error_exit(NO_READ_PERMISSION,-1));
  1444. }
  1445. return(error_exit(NO_INPUT_AVAILABLE,-1));
  1446. }
  1447. }
  1448. else ioctl(audio_fd,SNDCTL_DSP_SETDUPLEX,0); /* not always a no-op! */
  1449. /* need to make sure the desired recording source is active -- does this actually have any effect? */
  1450. switch (dev)
  1451. {
  1452. case MICROPHONE_DEVICE: srcbit = SOUND_MASK_MIC; break;
  1453. case LINE_IN_DEVICE: srcbit = SOUND_MASK_LINE; break;
  1454. case LINE1_DEVICE: srcbit = SOUND_MASK_LINE1; break;
  1455. case LINE2_DEVICE: srcbit = SOUND_MASK_LINE2; break;
  1456. case LINE3_DEVICE: srcbit = SOUND_MASK_LINE3; break; /* also digital1..3 */
  1457. case READ_WRITE_DEVICE:
  1458. case DEFAULT_DEVICE: srcbit = SOUND_MASK_LINE | SOUND_MASK_MIC; break;
  1459. case CD_IN_DEVICE: srcbit = SOUND_MASK_CD; break;
  1460. default: srcbit = 0; break;
  1461. /* other possibilities: synth, radio, phonein */
  1462. }
  1463. ioctl(audio_fd,MIXER_READ(SOUND_MIXER_RECSRC),&cursrc);
  1464. srcbit = (srcbit | cursrc);
  1465. ioctl(audio_fd,MIXER_WRITE(SOUND_MIXER_RECSRC),&srcbit);
  1466. if (chans == 2) stereo = 1; else stereo = 0;
  1467. ioctl(audio_fd,SNDCTL_DSP_RESET,0);
  1468. if (requested_size != 0)
  1469. {
  1470. buffer_info = (FRAGMENTS<<16) | (FRAGMENT_SIZE);
  1471. ioctl(audio_fd,SNDCTL_DSP_SETFRAGMENT,&buffer_info);
  1472. }
  1473. if ((ioctl(audio_fd,SNDCTL_DSP_SETFMT,&oss_format) == -1) || (oss_format != to_oss_format(format)))
  1474. return(error_exit(FORMAT_NOT_AVAILABLE,audio_fd));
  1475. if ((ioctl(audio_fd,SNDCTL_DSP_STEREO,&stereo) == -1) || ((chans == 2) && (stereo == 0))) return(error_exit(CHANNELS_NOT_AVAILABLE,audio_fd));
  1476. if (ioctl(audio_fd,SNDCTL_DSP_SPEED,&srate) == -1) return(error_exit(SRATE_NOT_AVAILABLE,audio_fd));
  1477. return(audio_fd);
  1478. }
  1479. int read_audio_state(int ur_dev, int field, int chan, float *val)
  1480. {
  1481. int fd,amp,channels,err,devmask,stereodevs,ind,formats,sys,dev;
  1482. AUDIO_ERROR = NO_ERROR;
  1483. sys = SNDLIB_SYSTEM(ur_dev);
  1484. dev = SNDLIB_DEVICE(ur_dev);
  1485. fd = linux_audio_open(mixer_name(sys),O_RDONLY | O_NONBLOCK,0,sys);
  1486. if (fd == -1)
  1487. {
  1488. fd = linux_audio_open(DAC_NAME,O_RDONLY,0,sys);
  1489. if (fd == -1)
  1490. {
  1491. fd = linux_audio_open(DAC_NAME,O_WRONLY,0,sys);
  1492. if (fd == -1) return(error_exit(CANT_OPEN,-1));
  1493. }
  1494. }
  1495. err = ioctl(fd,SOUND_MIXER_READ_DEVMASK,&devmask);
  1496. if (err) return(error_exit(CONFIGURATION_NOT_AVAILABLE,fd));
  1497. if ((dev == MIXER_DEVICE) || (dev == DAC_FILTER_DEVICE)) /* these give access to all the on-board analog input gain controls */
  1498. {
  1499. amp = 0;
  1500. err = ioctl(fd,SOUND_MIXER_READ_DEVMASK,&devmask);
  1501. switch (field)
  1502. {
  1503. /* also DIGITAL1..3 PHONEIN PHONEOUT VIDEO RADIO MONITOR */
  1504. /* the digital lines should get their own panes in the recorder */
  1505. /* not clear whether the phone et al lines are routed to the ADC */
  1506. /* also, I've never seen a card with any of these devices */
  1507. case IMIX_FIELD: if (SOUND_MASK_IMIX & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_IMIX),&amp); break;
  1508. case IGAIN_FIELD: if (SOUND_MASK_IGAIN & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_IGAIN),&amp); break;
  1509. case RECLEV_FIELD: if (SOUND_MASK_RECLEV & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_RECLEV),&amp); break;
  1510. case PCM_FIELD: if (SOUND_MASK_PCM & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_PCM),&amp); break;
  1511. case PCM2_FIELD: if (SOUND_MASK_ALTPCM & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_ALTPCM),&amp); break;
  1512. case OGAIN_FIELD: if (SOUND_MASK_OGAIN & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_OGAIN),&amp); break;
  1513. case LINE_FIELD: if (SOUND_MASK_LINE & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_LINE),&amp); break;
  1514. case MIC_FIELD: if (SOUND_MASK_MIC & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_MIC),&amp); break;
  1515. case LINE1_FIELD: if (SOUND_MASK_LINE1 & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_LINE1),&amp); break;
  1516. case LINE2_FIELD: if (SOUND_MASK_LINE2 & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_LINE2),&amp); break;
  1517. case LINE3_FIELD: if (SOUND_MASK_LINE3 & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_LINE3),&amp); break;
  1518. case SYNTH_FIELD: if (SOUND_MASK_SYNTH & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_SYNTH),&amp); break;
  1519. case BASS_FIELD: if (SOUND_MASK_BASS & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_BASS),&amp); break;
  1520. case TREBLE_FIELD: if (SOUND_MASK_TREBLE & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_TREBLE),&amp); break;
  1521. case CD_FIELD: if (SOUND_MASK_CD & devmask) err = ioctl(fd,MIXER_READ(SOUND_MIXER_CD),&amp); break;
  1522. case CHANNEL_FIELD:
  1523. if (dev == MIXER_DEVICE)
  1524. {
  1525. channels = 0;
  1526. err = ioctl(fd,SOUND_MIXER_READ_STEREODEVS,&stereodevs);
  1527. if (SOUND_MASK_IMIX & devmask) {if (SOUND_MASK_IMIX & stereodevs) channels += 2; else channels += 1;}
  1528. if (SOUND_MASK_IGAIN & devmask) {if (SOUND_MASK_IGAIN & stereodevs) channels += 2; else channels += 1;}
  1529. if (SOUND_MASK_RECLEV & devmask) {if (SOUND_MASK_RECLEV & stereodevs) channels += 2; else channels += 1;}
  1530. if (SOUND_MASK_PCM & devmask) {if (SOUND_MASK_PCM & stereodevs) channels += 2; else channels += 1;}
  1531. if (SOUND_MASK_ALTPCM & devmask) {if (SOUND_MASK_ALTPCM & stereodevs) channels += 2; else channels += 1;}
  1532. if (SOUND_MASK_OGAIN & devmask) {if (SOUND_MASK_OGAIN & stereodevs) channels += 2; else channels += 1;}
  1533. if (SOUND_MASK_LINE & devmask) {if (SOUND_MASK_LINE & stereodevs) channels += 2; else channels += 1;}
  1534. if (SOUND_MASK_MIC & devmask) {if (SOUND_MASK_MIC & stereodevs) channels += 2; else channels += 1;}
  1535. if (SOUND_MASK_LINE1 & devmask) {if (SOUND_MASK_LINE1 & stereodevs) channels += 2; else channels += 1;}
  1536. if (SOUND_MASK_LINE2 & devmask) {if (SOUND_MASK_LINE2 & stereodevs) channels += 2; else channels += 1;}
  1537. if (SOUND_MASK_LINE3 & devmask) {if (SOUND_MASK_LINE3 & stereodevs) channels += 2; else channels += 1;}
  1538. if (SOUND_MASK_SYNTH & devmask) {if (SOUND_MASK_SYNTH & stereodevs) channels += 2; else channels += 1;}
  1539. if (SOUND_MASK_CD & devmask) {if (SOUND_MASK_CD & stereodevs) channels += 2; else channels += 1;}
  1540. }
  1541. else
  1542. if (SOUND_MASK_TREBLE & devmask) channels = 2; else channels = 0;
  1543. val[0] = channels;
  1544. linux_audio_close(fd);
  1545. return(0);
  1546. break;
  1547. case FORMAT_FIELD: /* this is asking for configuration info -- we return an array with per-"device" channels */
  1548. err = ioctl(fd,SOUND_MIXER_READ_STEREODEVS,&stereodevs);
  1549. for (ind=0;ind<=SYNTH_FIELD;ind++) {if (chan>ind) val[ind]=0;}
  1550. if (SOUND_MASK_IMIX & devmask) {if (chan>IMIX_FIELD) val[IMIX_FIELD] = ((SOUND_MASK_IMIX & stereodevs) ? 2 : 1);}
  1551. if (SOUND_MASK_IGAIN & devmask) {if (chan>IGAIN_FIELD) val[IGAIN_FIELD] = ((SOUND_MASK_IGAIN & stereodevs) ? 2 : 1);}
  1552. if (SOUND_MASK_RECLEV & devmask) {if (chan>RECLEV_FIELD) val[RECLEV_FIELD] = ((SOUND_MASK_RECLEV & stereodevs) ? 2 : 1);}
  1553. if (SOUND_MASK_PCM & devmask) {if (chan>PCM_FIELD) val[PCM_FIELD] = ((SOUND_MASK_PCM & stereodevs) ? 2 : 1);}
  1554. if (SOUND_MASK_ALTPCM & devmask) {if (chan>PCM2_FIELD) val[PCM2_FIELD] = ((SOUND_MASK_ALTPCM & stereodevs) ? 2 : 1);}
  1555. if (SOUND_MASK_OGAIN & devmask) {if (chan>OGAIN_FIELD) val[OGAIN_FIELD] = ((SOUND_MASK_OGAIN & stereodevs) ? 2 : 1);}
  1556. if (SOUND_MASK_LINE & devmask) {if (chan>LINE_FIELD) val[LINE_FIELD] = ((SOUND_MASK_LINE & stereodevs) ? 2 : 1);}
  1557. if (SOUND_MASK_MIC & devmask) {if (chan>MIC_FIELD) val[MIC_FIELD] = ((SOUND_MASK_MIC & stereodevs) ? 2 : 1);}
  1558. if (SOUND_MASK_LINE1 & devmask) {if (chan>LINE1_FIELD) val[LINE1_FIELD] = ((SOUND_MASK_LINE1 & stereodevs) ? 2 : 1);}
  1559. if (SOUND_MASK_LINE2 & devmask) {if (chan>LINE2_FIELD) val[LINE2_FIELD] = ((SOUND_MASK_LINE2 & stereodevs) ? 2 : 1);}
  1560. if (SOUND_MASK_LINE3 & devmask) {if (chan>LINE3_FIELD) val[LINE3_FIELD] = ((SOUND_MASK_LINE3 & stereodevs) ? 2 : 1);}
  1561. if (SOUND_MASK_SYNTH & devmask) {if (chan>SYNTH_FIELD) val[SYNTH_FIELD] = ((SOUND_MASK_SYNTH & stereodevs) ? 2 : 1);}
  1562. if (SOUND_MASK_CD & devmask) {if (chan>CD_FIELD) val[CD_FIELD] = ((SOUND_MASK_CD & stereodevs) ? 2 : 1);}
  1563. linux_audio_close(fd);
  1564. return(0);
  1565. break;
  1566. default: AUDIO_ERROR = CANT_READ; break;
  1567. }
  1568. if (chan == 0)
  1569. val[0] = ((float)(amp & 0xff))*0.01;
  1570. else val[0] = (((float)((amp & 0xff00) >> 8))*0.01);
  1571. }
  1572. else
  1573. {
  1574. switch (field)
  1575. {
  1576. case DEVICE_FIELD:
  1577. ind = 1;
  1578. val[1] = MIXER_DEVICE;
  1579. if ((SOUND_MASK_MIC | SOUND_MASK_LINE | SOUND_MASK_CD) & devmask) {ind++; if (chan>ind) val[ind] = LINE_IN_DEVICE;}
  1580. /* problem here is that microphone and line_in are mixed before the ADC */
  1581. if (SOUND_MASK_SPEAKER & devmask) {ind++; if (chan>ind) val[ind] = SPEAKERS_DEVICE;}
  1582. if (SOUND_MASK_VOLUME & devmask) {ind++; if (chan>ind) val[ind] = DAC_OUT_DEVICE;}
  1583. if (SOUND_MASK_TREBLE & devmask) {ind++; if (chan>ind) val[ind] = DAC_FILTER_DEVICE;}
  1584. /* DIGITAL1..3 as RECSRC(?) => DIGITAL_IN_DEVICE */
  1585. val[0] = ind;
  1586. break;
  1587. case FORMAT_FIELD:
  1588. err = ioctl(fd,SOUND_PCM_GETFMTS,&formats);
  1589. ind = 0;
  1590. if (formats & (to_oss_format(snd_8_linear))) {ind++; if (chan>ind) val[ind] = snd_8_linear;}
  1591. if (formats & (to_oss_format(snd_16_linear))) {ind++; if (chan>ind) val[ind] = snd_16_linear;}
  1592. if (formats & (to_oss_format(snd_8_unsigned))) {ind++; if (chan>ind) val[ind] = snd_8_unsigned;}
  1593. if (formats & (to_oss_format(snd_8_mulaw))) {ind++; if (chan>ind) val[ind] = snd_8_mulaw;}
  1594. if (formats & (to_oss_format(snd_8_alaw))) {ind++; if (chan>ind) val[ind] = snd_8_alaw;}
  1595. if (formats & (to_oss_format(snd_16_linear_little_endian))) {ind++; if (chan>ind) val[ind] = snd_16_linear_little_endian;}
  1596. if (formats & (to_oss_format(snd_16_unsigned))) {ind++; if (chan>ind) val[ind] = snd_16_unsigned;}
  1597. if (formats & (to_oss_format(snd_16_unsigned_little_endian))) {ind++; if (chan>ind) val[ind] = snd_16_unsigned_little_endian;}
  1598. val[0] = ind;
  1599. break;
  1600. case CHANNEL_FIELD:
  1601. err = ioctl(fd,SOUND_MIXER_READ_STEREODEVS,&stereodevs);
  1602. channels = 0;
  1603. switch (dev)
  1604. {
  1605. case MICROPHONE_DEVICE: if (SOUND_MASK_MIC & devmask) {if (SOUND_MASK_MIC & stereodevs) channels = 2; else channels = 1;} break;
  1606. case SPEAKERS_DEVICE: if (SOUND_MASK_SPEAKER & devmask) {if (SOUND_MASK_SPEAKER & stereodevs) channels = 2; else channels = 1;} break;
  1607. case LINE_IN_DEVICE: if (SOUND_MASK_LINE & devmask) {if (SOUND_MASK_LINE & stereodevs) channels = 2; else channels = 1;} break;
  1608. case LINE1_DEVICE: if (SOUND_MASK_LINE1 & devmask) {if (SOUND_MASK_LINE1 & stereodevs) channels = 2; else channels = 1;} break;
  1609. case LINE2_DEVICE: if (SOUND_MASK_LINE2 & devmask) {if (SOUND_MASK_LINE2 & stereodevs) channels = 2; else channels = 1;} break;
  1610. case LINE3_DEVICE: if (SOUND_MASK_LINE3 & devmask) {if (SOUND_MASK_LINE3 & stereodevs) channels = 2; else channels = 1;} break;
  1611. case DAC_OUT_DEVICE: if (SOUND_MASK_VOLUME & devmask) {if (SOUND_MASK_VOLUME & stereodevs) channels = 2; else channels = 1;} break;
  1612. case DEFAULT_DEVICE: if (SOUND_MASK_VOLUME & devmask) {if (SOUND_MASK_VOLUME & stereodevs) channels = 2; else channels = 1;} break;
  1613. case CD_IN_DEVICE: if (SOUND_MASK_CD & devmask) {if (SOUND_MASK_CD & stereodevs) channels = 2; else channels = 1;} break;
  1614. case READ_WRITE_DEVICE:
  1615. err = ioctl(fd,SNDCTL_DSP_GETCAPS,&ind);
  1616. if (err != -1)
  1617. channels = (ind & DSP_CAP_DUPLEX);
  1618. else channels = 0;
  1619. break;
  1620. default: AUDIO_ERROR = DEVICE_NOT_AVAILABLE; break;
  1621. }
  1622. val