qsa.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 2011-2013 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  17. * Boston, MA 02111-1307, USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <sched.h>
  24. #include <errno.h>
  25. #include <memory.h>
  26. #include <sys/select.h>
  27. #include <sys/asoundlib.h>
  28. #include <sys/neutrino.h>
  29. #include "alMain.h"
  30. #include "alu.h"
  31. #include "threads.h"
  32. typedef struct
  33. {
  34. snd_pcm_t* pcmHandle;
  35. int audio_fd;
  36. snd_pcm_channel_setup_t csetup;
  37. snd_pcm_channel_params_t cparams;
  38. ALvoid* buffer;
  39. ALsizei size;
  40. volatile int killNow;
  41. althread_t thread;
  42. } qsa_data;
  43. typedef struct
  44. {
  45. ALCchar* name;
  46. int card;
  47. int dev;
  48. } DevMap;
  49. static const ALCchar qsaDevice[]="QSA Default";
  50. static DevMap* allDevNameMap;
  51. static ALuint numDevNames;
  52. static DevMap* allCaptureDevNameMap;
  53. static ALuint numCaptureDevNames;
  54. static const struct
  55. {
  56. int32_t format;
  57. } formatlist[]=
  58. {
  59. {SND_PCM_SFMT_FLOAT_LE},
  60. {SND_PCM_SFMT_S32_LE},
  61. {SND_PCM_SFMT_U32_LE},
  62. {SND_PCM_SFMT_S16_LE},
  63. {SND_PCM_SFMT_U16_LE},
  64. {SND_PCM_SFMT_S8},
  65. {SND_PCM_SFMT_U8},
  66. {0},
  67. };
  68. static const struct
  69. {
  70. int32_t rate;
  71. } ratelist[]=
  72. {
  73. {192000},
  74. {176400},
  75. {96000},
  76. {88200},
  77. {48000},
  78. {44100},
  79. {32000},
  80. {24000},
  81. {22050},
  82. {16000},
  83. {12000},
  84. {11025},
  85. {8000},
  86. {0},
  87. };
  88. static const struct
  89. {
  90. int32_t channels;
  91. } channellist[]=
  92. {
  93. {8},
  94. {7},
  95. {6},
  96. {4},
  97. {2},
  98. {1},
  99. {0},
  100. };
  101. static DevMap* deviceList(int type, ALuint* count)
  102. {
  103. snd_ctl_t* handle;
  104. snd_pcm_info_t pcminfo;
  105. int max_cards, card, err, dev, num_devices, idx;
  106. DevMap* dev_list;
  107. char name[1024];
  108. struct snd_ctl_hw_info info;
  109. void* temp;
  110. idx=0;
  111. num_devices=0;
  112. max_cards=snd_cards();
  113. if (max_cards<=0)
  114. {
  115. return 0;
  116. }
  117. dev_list=malloc(sizeof(DevMap)*1);
  118. dev_list[0].name=strdup(qsaDevice);
  119. num_devices=1;
  120. for (card=0; card<max_cards; card++)
  121. {
  122. if ((err=snd_ctl_open(&handle, card))<0)
  123. {
  124. continue;
  125. }
  126. if ((err=snd_ctl_hw_info(handle, &info))<0)
  127. {
  128. snd_ctl_close(handle);
  129. continue;
  130. }
  131. for (dev=0; dev<(int)info.pcmdevs; dev++)
  132. {
  133. if ((err=snd_ctl_pcm_info(handle, dev, &pcminfo)) < 0)
  134. {
  135. continue;
  136. }
  137. if ((type==SND_PCM_CHANNEL_PLAYBACK && (pcminfo.flags&SND_PCM_INFO_PLAYBACK)) ||
  138. (type==SND_PCM_CHANNEL_CAPTURE && (pcminfo.flags&SND_PCM_INFO_CAPTURE)))
  139. {
  140. temp=realloc(dev_list, sizeof(DevMap)*(num_devices+1));
  141. if (temp)
  142. {
  143. dev_list=temp;
  144. snprintf(name, sizeof(name), "%s [%s] (hw:%d,%d)", info.name, pcminfo.name, card, dev);
  145. dev_list[num_devices].name=strdup(name);
  146. dev_list[num_devices].card=card;
  147. dev_list[num_devices].dev=dev;
  148. num_devices++;
  149. }
  150. }
  151. }
  152. snd_ctl_close (handle);
  153. }
  154. *count=num_devices;
  155. return dev_list;
  156. }
  157. FORCE_ALIGN static ALuint qsa_proc_playback(ALvoid* ptr)
  158. {
  159. ALCdevice* device=(ALCdevice*)ptr;
  160. qsa_data* data=(qsa_data*)device->ExtraData;
  161. char* write_ptr;
  162. int avail;
  163. snd_pcm_channel_status_t status;
  164. struct sched_param param;
  165. fd_set wfds;
  166. int selectret;
  167. struct timeval timeout;
  168. SetRTPriority();
  169. SetThreadName(MIXER_THREAD_NAME);
  170. /* Increase default 10 priority to 11 to avoid jerky sound */
  171. SchedGet(0, 0, &param);
  172. param.sched_priority=param.sched_curpriority+1;
  173. SchedSet(0, 0, SCHED_NOCHANGE, &param);
  174. ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
  175. while (!data->killNow)
  176. {
  177. ALint len=data->size;
  178. write_ptr=data->buffer;
  179. avail=len/frame_size;
  180. aluMixData(device, write_ptr, avail);
  181. while (len>0 && !data->killNow)
  182. {
  183. FD_ZERO(&wfds);
  184. FD_SET(data->audio_fd, &wfds);
  185. timeout.tv_sec=2;
  186. timeout.tv_usec=0;
  187. /* Select also works like time slice to OS */
  188. selectret=select(data->audio_fd+1, NULL, &wfds, NULL, &timeout);
  189. switch (selectret)
  190. {
  191. case -1:
  192. aluHandleDisconnect(device);
  193. return 1;
  194. case 0:
  195. break;
  196. default:
  197. if (FD_ISSET(data->audio_fd, &wfds))
  198. {
  199. break;
  200. }
  201. break;
  202. }
  203. int wrote=snd_pcm_plugin_write(data->pcmHandle, write_ptr, len);
  204. if (wrote<=0)
  205. {
  206. if ((errno==EAGAIN) || (errno==EWOULDBLOCK))
  207. {
  208. continue;
  209. }
  210. memset(&status, 0, sizeof (status));
  211. status.channel=SND_PCM_CHANNEL_PLAYBACK;
  212. snd_pcm_plugin_status(data->pcmHandle, &status);
  213. /* we need to reinitialize the sound channel if we've underrun the buffer */
  214. if ((status.status==SND_PCM_STATUS_UNDERRUN) ||
  215. (status.status==SND_PCM_STATUS_READY))
  216. {
  217. if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
  218. {
  219. aluHandleDisconnect(device);
  220. break;
  221. }
  222. }
  223. }
  224. else
  225. {
  226. write_ptr+=wrote;
  227. len-=wrote;
  228. }
  229. }
  230. }
  231. return 0;
  232. }
  233. /************/
  234. /* Playback */
  235. /************/
  236. static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName)
  237. {
  238. qsa_data* data;
  239. char driver[64];
  240. int status;
  241. int card, dev;
  242. strncpy(driver, GetConfigValue("qsa", "device", qsaDevice), sizeof(driver)-1);
  243. driver[sizeof(driver)-1]=0;
  244. data=(qsa_data*)calloc(1, sizeof(qsa_data));
  245. if (data==NULL)
  246. {
  247. return ALC_OUT_OF_MEMORY;
  248. }
  249. if (!deviceName)
  250. {
  251. deviceName=driver;
  252. }
  253. if (strcmp(deviceName, qsaDevice)==0)
  254. {
  255. if (!deviceName)
  256. {
  257. deviceName=qsaDevice;
  258. }
  259. status=snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK);
  260. }
  261. else
  262. {
  263. size_t idx;
  264. if (!allDevNameMap)
  265. {
  266. allDevNameMap=deviceList(SND_PCM_CHANNEL_PLAYBACK, &numDevNames);
  267. }
  268. for (idx=0; idx<numDevNames; idx++)
  269. {
  270. if (allDevNameMap[idx].name && strcmp(deviceName, allDevNameMap[idx].name)==0)
  271. {
  272. if (idx>0)
  273. {
  274. break;
  275. }
  276. }
  277. }
  278. if (idx==numDevNames)
  279. {
  280. free(data);
  281. return ALC_INVALID_DEVICE;
  282. }
  283. status=snd_pcm_open(&data->pcmHandle, allDevNameMap[idx].card, allDevNameMap[idx].dev, SND_PCM_OPEN_PLAYBACK);
  284. }
  285. if (status<0)
  286. {
  287. free(data);
  288. return ALC_INVALID_DEVICE;
  289. }
  290. data->audio_fd=snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
  291. if (data->audio_fd<0)
  292. {
  293. free(data);
  294. return ALC_INVALID_DEVICE;
  295. }
  296. device->DeviceName=strdup(deviceName);
  297. device->ExtraData=data;
  298. return ALC_NO_ERROR;
  299. }
  300. static void qsa_close_playback(ALCdevice* device)
  301. {
  302. qsa_data* data=(qsa_data*)device->ExtraData;
  303. if (data->buffer!=NULL)
  304. {
  305. free(data->buffer);
  306. data->buffer=NULL;
  307. }
  308. snd_pcm_close(data->pcmHandle);
  309. free(data);
  310. device->ExtraData=NULL;
  311. }
  312. static ALCboolean qsa_reset_playback(ALCdevice* device)
  313. {
  314. qsa_data* data=(qsa_data*)device->ExtraData;
  315. int32_t format=-1;
  316. switch(device->FmtType)
  317. {
  318. case DevFmtByte:
  319. format=SND_PCM_SFMT_S8;
  320. break;
  321. case DevFmtUByte:
  322. format=SND_PCM_SFMT_U8;
  323. break;
  324. case DevFmtShort:
  325. format=SND_PCM_SFMT_S16_LE;
  326. break;
  327. case DevFmtUShort:
  328. format=SND_PCM_SFMT_U16_LE;
  329. break;
  330. case DevFmtInt:
  331. format=SND_PCM_SFMT_S32_LE;
  332. break;
  333. case DevFmtUInt:
  334. format=SND_PCM_SFMT_U32_LE;
  335. break;
  336. case DevFmtFloat:
  337. format=SND_PCM_SFMT_FLOAT_LE;
  338. break;
  339. }
  340. /* we actually don't want to block on writes */
  341. snd_pcm_nonblock_mode(data->pcmHandle, 1);
  342. /* Disable mmap to control data transfer to the audio device */
  343. snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP);
  344. snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS);
  345. // configure a sound channel
  346. memset(&data->cparams, 0, sizeof(data->cparams));
  347. data->cparams.channel=SND_PCM_CHANNEL_PLAYBACK;
  348. data->cparams.mode=SND_PCM_MODE_BLOCK;
  349. data->cparams.start_mode=SND_PCM_START_FULL;
  350. data->cparams.stop_mode=SND_PCM_STOP_STOP;
  351. data->cparams.buf.block.frag_size=device->UpdateSize*
  352. ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
  353. data->cparams.buf.block.frags_max=device->NumUpdates;
  354. data->cparams.buf.block.frags_min=device->NumUpdates;
  355. data->cparams.format.interleave=1;
  356. data->cparams.format.rate=device->Frequency;
  357. data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
  358. data->cparams.format.format=format;
  359. if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
  360. {
  361. int original_rate=data->cparams.format.rate;
  362. int original_voices=data->cparams.format.voices;
  363. int original_format=data->cparams.format.format;
  364. int it;
  365. int jt;
  366. for (it=0; it<1; it++)
  367. {
  368. /* Check for second pass */
  369. if (it==1)
  370. {
  371. original_rate=ratelist[0].rate;
  372. original_voices=channellist[0].channels;
  373. original_format=formatlist[0].format;
  374. }
  375. do {
  376. /* At first downgrade sample format */
  377. jt=0;
  378. do {
  379. if (formatlist[jt].format==data->cparams.format.format)
  380. {
  381. data->cparams.format.format=formatlist[jt+1].format;
  382. break;
  383. }
  384. if (formatlist[jt].format==0)
  385. {
  386. data->cparams.format.format=0;
  387. break;
  388. }
  389. jt++;
  390. } while(1);
  391. if (data->cparams.format.format==0)
  392. {
  393. data->cparams.format.format=original_format;
  394. /* At secod downgrade sample rate */
  395. jt=0;
  396. do {
  397. if (ratelist[jt].rate==data->cparams.format.rate)
  398. {
  399. data->cparams.format.rate=ratelist[jt+1].rate;
  400. break;
  401. }
  402. if (ratelist[jt].rate==0)
  403. {
  404. data->cparams.format.rate=0;
  405. break;
  406. }
  407. jt++;
  408. } while(1);
  409. if (data->cparams.format.rate==0)
  410. {
  411. data->cparams.format.rate=original_rate;
  412. data->cparams.format.format=original_format;
  413. /* At third downgrade channels number */
  414. jt=0;
  415. do {
  416. if(channellist[jt].channels==data->cparams.format.voices)
  417. {
  418. data->cparams.format.voices=channellist[jt+1].channels;
  419. break;
  420. }
  421. if (channellist[jt].channels==0)
  422. {
  423. data->cparams.format.voices=0;
  424. break;
  425. }
  426. jt++;
  427. } while(1);
  428. }
  429. if (data->cparams.format.voices==0)
  430. {
  431. break;
  432. }
  433. }
  434. data->cparams.buf.block.frag_size=device->UpdateSize*
  435. data->cparams.format.voices*
  436. snd_pcm_format_width(data->cparams.format.format)/8;
  437. data->cparams.buf.block.frags_max=device->NumUpdates;
  438. data->cparams.buf.block.frags_min=device->NumUpdates;
  439. if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
  440. {
  441. continue;
  442. }
  443. else
  444. {
  445. break;
  446. }
  447. } while(1);
  448. if (data->cparams.format.voices!=0)
  449. {
  450. break;
  451. }
  452. }
  453. if (data->cparams.format.voices==0)
  454. {
  455. return ALC_FALSE;
  456. }
  457. }
  458. if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
  459. {
  460. return ALC_FALSE;
  461. }
  462. memset(&data->csetup, 0, sizeof(data->csetup));
  463. data->csetup.channel=SND_PCM_CHANNEL_PLAYBACK;
  464. if (snd_pcm_plugin_setup(data->pcmHandle, &data->csetup)<0)
  465. {
  466. return ALC_FALSE;
  467. }
  468. /* now fill back to the our AL device */
  469. device->Frequency=data->cparams.format.rate;
  470. switch (data->cparams.format.voices)
  471. {
  472. case 1:
  473. device->FmtChans=DevFmtMono;
  474. break;
  475. case 2:
  476. device->FmtChans=DevFmtStereo;
  477. break;
  478. case 4:
  479. device->FmtChans=DevFmtQuad;
  480. break;
  481. case 6:
  482. device->FmtChans=DevFmtX51;
  483. break;
  484. case 7:
  485. device->FmtChans=DevFmtX61;
  486. break;
  487. case 8:
  488. device->FmtChans=DevFmtX71;
  489. break;
  490. default:
  491. device->FmtChans=DevFmtMono;
  492. break;
  493. }
  494. switch (data->cparams.format.format)
  495. {
  496. case SND_PCM_SFMT_S8:
  497. device->FmtType=DevFmtByte;
  498. break;
  499. case SND_PCM_SFMT_U8:
  500. device->FmtType=DevFmtUByte;
  501. break;
  502. case SND_PCM_SFMT_S16_LE:
  503. device->FmtType=DevFmtShort;
  504. break;
  505. case SND_PCM_SFMT_U16_LE:
  506. device->FmtType=DevFmtUShort;
  507. break;
  508. case SND_PCM_SFMT_S32_LE:
  509. device->FmtType=DevFmtInt;
  510. break;
  511. case SND_PCM_SFMT_U32_LE:
  512. device->FmtType=DevFmtUInt;
  513. break;
  514. case SND_PCM_SFMT_FLOAT_LE:
  515. device->FmtType=DevFmtFloat;
  516. break;
  517. default:
  518. device->FmtType=DevFmtShort;
  519. break;
  520. }
  521. SetDefaultChannelOrder(device);
  522. device->UpdateSize=data->csetup.buf.block.frag_size/
  523. (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
  524. device->NumUpdates=data->csetup.buf.block.frags;
  525. data->size=data->csetup.buf.block.frag_size;
  526. data->buffer=malloc(data->size);
  527. if (!data->buffer)
  528. {
  529. return ALC_FALSE;
  530. }
  531. return ALC_TRUE;
  532. }
  533. static ALCboolean qsa_start_playback(ALCdevice* device)
  534. {
  535. qsa_data *data = (qsa_data*)device->ExtraData;
  536. if(!StartThread(&data->thread, qsa_proc_playback, device))
  537. return ALC_FALSE;
  538. return ALC_TRUE;
  539. }
  540. static void qsa_stop_playback(ALCdevice* device)
  541. {
  542. qsa_data* data=(qsa_data*)device->ExtraData;
  543. if (data->thread)
  544. {
  545. data->killNow=1;
  546. StopThread(data->thread);
  547. data->thread=NULL;
  548. }
  549. data->killNow=0;
  550. }
  551. /***********/
  552. /* Capture */
  553. /***********/
  554. static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
  555. {
  556. qsa_data* data;
  557. int format=-1;
  558. char driver[64];
  559. int card, dev;
  560. int status;
  561. strncpy(driver, GetConfigValue("qsa", "capture", qsaDevice), sizeof(driver)-1);
  562. driver[sizeof(driver)-1]=0;
  563. data=(qsa_data*)calloc(1, sizeof(qsa_data));
  564. if (data==NULL)
  565. {
  566. return ALC_OUT_OF_MEMORY;
  567. }
  568. if (!deviceName)
  569. {
  570. deviceName=driver;
  571. }
  572. if (strcmp(deviceName, qsaDevice)==0)
  573. {
  574. if (!deviceName)
  575. {
  576. deviceName=qsaDevice;
  577. }
  578. status=snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE);
  579. }
  580. else
  581. {
  582. size_t idx;
  583. if (!allCaptureDevNameMap)
  584. {
  585. allCaptureDevNameMap=deviceList(SND_PCM_CHANNEL_CAPTURE, &numDevNames);
  586. }
  587. for (idx=0; idx<numDevNames; idx++)
  588. {
  589. if (allCaptureDevNameMap[idx].name && strcmp(deviceName, allCaptureDevNameMap[idx].name)==0)
  590. {
  591. if (idx>0)
  592. {
  593. break;
  594. }
  595. }
  596. }
  597. if (idx==numDevNames)
  598. {
  599. free(data);
  600. return ALC_INVALID_DEVICE;
  601. }
  602. status=snd_pcm_open(&data->pcmHandle, allCaptureDevNameMap[idx].card, allCaptureDevNameMap[idx].dev, SND_PCM_OPEN_CAPTURE);
  603. }
  604. if (status<0)
  605. {
  606. free(data);
  607. return ALC_INVALID_DEVICE;
  608. }
  609. data->audio_fd=snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE);
  610. if (data->audio_fd<0)
  611. {
  612. free(data);
  613. return ALC_INVALID_DEVICE;
  614. }
  615. device->DeviceName=strdup(deviceName);
  616. device->ExtraData=data;
  617. switch (device->FmtType)
  618. {
  619. case DevFmtByte:
  620. format=SND_PCM_SFMT_S8;
  621. break;
  622. case DevFmtUByte:
  623. format=SND_PCM_SFMT_U8;
  624. break;
  625. case DevFmtShort:
  626. format=SND_PCM_SFMT_S16_LE;
  627. break;
  628. case DevFmtUShort:
  629. format=SND_PCM_SFMT_U16_LE;
  630. break;
  631. case DevFmtInt:
  632. format=SND_PCM_SFMT_S32_LE;
  633. break;
  634. case DevFmtUInt:
  635. format=SND_PCM_SFMT_U32_LE;
  636. break;
  637. case DevFmtFloat:
  638. format=SND_PCM_SFMT_FLOAT_LE;
  639. break;
  640. }
  641. /* we actually don't want to block on reads */
  642. snd_pcm_nonblock_mode(data->pcmHandle, 1);
  643. /* Disable mmap to control data transfer to the audio device */
  644. snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP);
  645. /* configure a sound channel */
  646. memset(&data->cparams, 0, sizeof(data->cparams));
  647. data->cparams.mode=SND_PCM_MODE_BLOCK;
  648. data->cparams.channel=SND_PCM_CHANNEL_CAPTURE;
  649. data->cparams.start_mode=SND_PCM_START_GO;
  650. data->cparams.stop_mode=SND_PCM_STOP_STOP;
  651. data->cparams.buf.block.frag_size=device->UpdateSize*
  652. ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
  653. data->cparams.buf.block.frags_max=device->NumUpdates;
  654. data->cparams.buf.block.frags_min=device->NumUpdates;
  655. data->cparams.format.interleave=1;
  656. data->cparams.format.rate=device->Frequency;
  657. data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
  658. data->cparams.format.format=format;
  659. if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
  660. {
  661. int original_rate=data->cparams.format.rate;
  662. int original_voices=data->cparams.format.voices;
  663. int original_format=data->cparams.format.format;
  664. int it;
  665. int jt;
  666. for (it=0; it<1; it++)
  667. {
  668. /* Check for second pass */
  669. if (it==1)
  670. {
  671. original_rate=ratelist[0].rate;
  672. original_voices=channellist[0].channels;
  673. original_format=formatlist[0].format;
  674. }
  675. do {
  676. /* At first downgrade sample format */
  677. jt=0;
  678. do {
  679. if (formatlist[jt].format==data->cparams.format.format)
  680. {
  681. data->cparams.format.format=formatlist[jt+1].format;
  682. break;
  683. }
  684. if (formatlist[jt].format==0)
  685. {
  686. data->cparams.format.format=0;
  687. break;
  688. }
  689. jt++;
  690. } while(1);
  691. if (data->cparams.format.format==0)
  692. {
  693. data->cparams.format.format=original_format;
  694. /* At secod downgrade sample rate */
  695. jt=0;
  696. do {
  697. if (ratelist[jt].rate==data->cparams.format.rate)
  698. {
  699. data->cparams.format.rate=ratelist[jt+1].rate;
  700. break;
  701. }
  702. if (ratelist[jt].rate==0)
  703. {
  704. data->cparams.format.rate=0;
  705. break;
  706. }
  707. jt++;
  708. } while(1);
  709. if (data->cparams.format.rate==0)
  710. {
  711. data->cparams.format.rate=original_rate;
  712. data->cparams.format.format=original_format;
  713. /* At third downgrade channels number */
  714. jt=0;
  715. do {
  716. if(channellist[jt].channels==data->cparams.format.voices)
  717. {
  718. data->cparams.format.voices=channellist[jt+1].channels;
  719. break;
  720. }
  721. if (channellist[jt].channels==0)
  722. {
  723. data->cparams.format.voices=0;
  724. break;
  725. }
  726. jt++;
  727. } while(1);
  728. }
  729. if (data->cparams.format.voices==0)
  730. {
  731. break;
  732. }
  733. }
  734. data->cparams.buf.block.frag_size=device->UpdateSize*
  735. data->cparams.format.voices*
  736. snd_pcm_format_width(data->cparams.format.format)/8;
  737. data->cparams.buf.block.frags_max=device->NumUpdates;
  738. data->cparams.buf.block.frags_min=device->NumUpdates;
  739. if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
  740. {
  741. continue;
  742. }
  743. else
  744. {
  745. break;
  746. }
  747. } while(1);
  748. if (data->cparams.format.voices!=0)
  749. {
  750. break;
  751. }
  752. }
  753. if (data->cparams.format.voices==0)
  754. {
  755. return ALC_INVALID_VALUE;
  756. }
  757. }
  758. /* now fill back to the our AL device */
  759. device->Frequency=data->cparams.format.rate;
  760. switch (data->cparams.format.voices)
  761. {
  762. case 1:
  763. device->FmtChans=DevFmtMono;
  764. break;
  765. case 2:
  766. device->FmtChans=DevFmtStereo;
  767. break;
  768. case 4:
  769. device->FmtChans=DevFmtQuad;
  770. break;
  771. case 6:
  772. device->FmtChans=DevFmtX51;
  773. break;
  774. case 7:
  775. device->FmtChans=DevFmtX61;
  776. break;
  777. case 8:
  778. device->FmtChans=DevFmtX71;
  779. break;
  780. default:
  781. device->FmtChans=DevFmtMono;
  782. break;
  783. }
  784. switch (data->cparams.format.format)
  785. {
  786. case SND_PCM_SFMT_S8:
  787. device->FmtType=DevFmtByte;
  788. break;
  789. case SND_PCM_SFMT_U8:
  790. device->FmtType=DevFmtUByte;
  791. break;
  792. case SND_PCM_SFMT_S16_LE:
  793. device->FmtType=DevFmtShort;
  794. break;
  795. case SND_PCM_SFMT_U16_LE:
  796. device->FmtType=DevFmtUShort;
  797. break;
  798. case SND_PCM_SFMT_S32_LE:
  799. device->FmtType=DevFmtInt;
  800. break;
  801. case SND_PCM_SFMT_U32_LE:
  802. device->FmtType=DevFmtUInt;
  803. break;
  804. case SND_PCM_SFMT_FLOAT_LE:
  805. device->FmtType=DevFmtFloat;
  806. break;
  807. default:
  808. device->FmtType=DevFmtShort;
  809. break;
  810. }
  811. return ALC_NO_ERROR;
  812. }
  813. static void qsa_close_capture(ALCdevice* device)
  814. {
  815. qsa_data* data=(qsa_data*)device->ExtraData;
  816. if (data->pcmHandle!=NULL)
  817. {
  818. snd_pcm_close(data->pcmHandle);
  819. }
  820. free(data);
  821. device->ExtraData=NULL;
  822. }
  823. static void qsa_start_capture(ALCdevice* device)
  824. {
  825. qsa_data* data=(qsa_data*)device->ExtraData;
  826. int rstatus;
  827. if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
  828. {
  829. ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
  830. return;
  831. }
  832. memset(&data->csetup, 0, sizeof(data->csetup));
  833. data->csetup.channel=SND_PCM_CHANNEL_CAPTURE;
  834. if ((rstatus=snd_pcm_plugin_setup(data->pcmHandle, &data->csetup))<0)
  835. {
  836. ERR("capture setup failed: %s\n", snd_strerror(rstatus));
  837. return;
  838. }
  839. snd_pcm_capture_go(data->pcmHandle);
  840. device->UpdateSize=data->csetup.buf.block.frag_size/
  841. (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
  842. device->NumUpdates=data->csetup.buf.block.frags;
  843. }
  844. static void qsa_stop_capture(ALCdevice* device)
  845. {
  846. qsa_data* data=(qsa_data*)device->ExtraData;
  847. snd_pcm_capture_flush(data->pcmHandle);
  848. }
  849. static ALCuint qsa_available_samples(ALCdevice* device)
  850. {
  851. qsa_data* data=(qsa_data*)device->ExtraData;
  852. snd_pcm_channel_status_t status;
  853. ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
  854. ALint free_size;
  855. int rstatus;
  856. memset(&status, 0, sizeof (status));
  857. status.channel=SND_PCM_CHANNEL_CAPTURE;
  858. snd_pcm_plugin_status(data->pcmHandle, &status);
  859. if ((status.status==SND_PCM_STATUS_OVERRUN) ||
  860. (status.status==SND_PCM_STATUS_READY))
  861. {
  862. if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
  863. {
  864. ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
  865. aluHandleDisconnect(device);
  866. return 0;
  867. }
  868. snd_pcm_capture_go(data->pcmHandle);
  869. return 0;
  870. }
  871. free_size=data->csetup.buf.block.frag_size*data->csetup.buf.block.frags;
  872. free_size-=status.free;
  873. return free_size/frame_size;
  874. }
  875. static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
  876. {
  877. qsa_data* data=(qsa_data*)device->ExtraData;
  878. char* read_ptr;
  879. snd_pcm_channel_status_t status;
  880. fd_set rfds;
  881. int selectret;
  882. struct timeval timeout;
  883. int bytes_read;
  884. ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
  885. ALint len=samples*frame_size;
  886. int rstatus;
  887. read_ptr=buffer;
  888. while (len>0)
  889. {
  890. FD_ZERO(&rfds);
  891. FD_SET(data->audio_fd, &rfds);
  892. timeout.tv_sec=2;
  893. timeout.tv_usec=0;
  894. /* Select also works like time slice to OS */
  895. bytes_read=0;
  896. selectret=select(data->audio_fd+1, &rfds, NULL, NULL, &timeout);
  897. switch (selectret)
  898. {
  899. case -1:
  900. aluHandleDisconnect(device);
  901. return ALC_INVALID_DEVICE;
  902. case 0:
  903. break;
  904. default:
  905. if (FD_ISSET(data->audio_fd, &rfds))
  906. {
  907. bytes_read=snd_pcm_plugin_read(data->pcmHandle, read_ptr, len);
  908. break;
  909. }
  910. break;
  911. }
  912. if (bytes_read<=0)
  913. {
  914. if ((errno==EAGAIN) || (errno==EWOULDBLOCK))
  915. {
  916. continue;
  917. }
  918. memset(&status, 0, sizeof (status));
  919. status.channel=SND_PCM_CHANNEL_CAPTURE;
  920. snd_pcm_plugin_status(data->pcmHandle, &status);
  921. /* we need to reinitialize the sound channel if we've overrun the buffer */
  922. if ((status.status==SND_PCM_STATUS_OVERRUN) ||
  923. (status.status==SND_PCM_STATUS_READY))
  924. {
  925. if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
  926. {
  927. ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
  928. aluHandleDisconnect(device);
  929. return ALC_INVALID_DEVICE;
  930. }
  931. snd_pcm_capture_go(data->pcmHandle);
  932. }
  933. }
  934. else
  935. {
  936. read_ptr+=bytes_read;
  937. len-=bytes_read;
  938. }
  939. }
  940. return ALC_NO_ERROR;
  941. }
  942. static ALint64 qsa_get_latency(ALCdevice* device)
  943. {
  944. ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
  945. return (ALint64)(device->UpdateSize*device->NumUpdates/frame_size)*
  946. 1000000000/device->Frequency;
  947. }
  948. BackendFuncs qsa_funcs=
  949. {
  950. qsa_open_playback,
  951. qsa_close_playback,
  952. qsa_reset_playback,
  953. qsa_start_playback,
  954. qsa_stop_playback,
  955. qsa_open_capture,
  956. qsa_close_capture,
  957. qsa_start_capture,
  958. qsa_stop_capture,
  959. qsa_capture_samples,
  960. qsa_available_samples,
  961. qsa_get_latency,
  962. };
  963. ALCboolean alc_qsa_init(BackendFuncs* func_list)
  964. {
  965. *func_list=qsa_funcs;
  966. return ALC_TRUE;
  967. }
  968. void alc_qsa_deinit(void)
  969. {
  970. ALuint i;
  971. for (i=0; i<numDevNames; ++i)
  972. {
  973. free(allDevNameMap[i].name);
  974. }
  975. free(allDevNameMap);
  976. allDevNameMap=NULL;
  977. numDevNames=0;
  978. for (i=0; i<numCaptureDevNames; ++i)
  979. {
  980. free(allCaptureDevNameMap[i].name);
  981. }
  982. free(allCaptureDevNameMap);
  983. allCaptureDevNameMap=NULL;
  984. numCaptureDevNames=0;
  985. }
  986. void alc_qsa_probe(enum DevProbe type)
  987. {
  988. ALuint i;
  989. switch (type)
  990. {
  991. case ALL_DEVICE_PROBE:
  992. for (i=0; i<numDevNames; ++i)
  993. {
  994. free(allDevNameMap[i].name);
  995. }
  996. free(allDevNameMap);
  997. allDevNameMap=deviceList(SND_PCM_CHANNEL_PLAYBACK, &numDevNames);
  998. for (i=0; i<numDevNames; ++i)
  999. {
  1000. AppendAllDevicesList(allDevNameMap[i].name);
  1001. }
  1002. break;
  1003. case CAPTURE_DEVICE_PROBE:
  1004. for (i=0; i<numCaptureDevNames; ++i)
  1005. {
  1006. free(allCaptureDevNameMap[i].name);
  1007. }
  1008. free(allCaptureDevNameMap);
  1009. allCaptureDevNameMap=deviceList(SND_PCM_CHANNEL_CAPTURE, &numCaptureDevNames);
  1010. for (i=0; i<numCaptureDevNames; ++i)
  1011. {
  1012. AppendCaptureDeviceList(allCaptureDevNameMap[i].name);
  1013. }
  1014. break;
  1015. }
  1016. }