qsa.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  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.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. #include "backends/base.h"
  33. typedef struct {
  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. ATOMIC(ALenum) killNow;
  41. althrd_t thread;
  42. } qsa_data;
  43. typedef struct {
  44. ALCchar* name;
  45. int card;
  46. int dev;
  47. } DevMap;
  48. TYPEDEF_VECTOR(DevMap, vector_DevMap)
  49. static vector_DevMap DeviceNameMap;
  50. static vector_DevMap CaptureNameMap;
  51. static const ALCchar qsaDevice[] = "QSA Default";
  52. static const struct {
  53. int32_t format;
  54. } formatlist[] = {
  55. {SND_PCM_SFMT_FLOAT_LE},
  56. {SND_PCM_SFMT_S32_LE},
  57. {SND_PCM_SFMT_U32_LE},
  58. {SND_PCM_SFMT_S16_LE},
  59. {SND_PCM_SFMT_U16_LE},
  60. {SND_PCM_SFMT_S8},
  61. {SND_PCM_SFMT_U8},
  62. {0},
  63. };
  64. static const struct {
  65. int32_t rate;
  66. } ratelist[] = {
  67. {192000},
  68. {176400},
  69. {96000},
  70. {88200},
  71. {48000},
  72. {44100},
  73. {32000},
  74. {24000},
  75. {22050},
  76. {16000},
  77. {12000},
  78. {11025},
  79. {8000},
  80. {0},
  81. };
  82. static const struct {
  83. int32_t channels;
  84. } channellist[] = {
  85. {8},
  86. {7},
  87. {6},
  88. {4},
  89. {2},
  90. {1},
  91. {0},
  92. };
  93. static void deviceList(int type, vector_DevMap *devmap)
  94. {
  95. snd_ctl_t* handle;
  96. snd_pcm_info_t pcminfo;
  97. int max_cards, card, err, dev;
  98. DevMap entry;
  99. char name[1024];
  100. struct snd_ctl_hw_info info;
  101. max_cards = snd_cards();
  102. if(max_cards < 0)
  103. return;
  104. #define FREE_NAME(iter) free((iter)->name)
  105. VECTOR_FOR_EACH(DevMap, *devmap, FREE_NAME);
  106. #undef FREE_NAME
  107. VECTOR_RESIZE(*devmap, 0, max_cards+1);
  108. entry.name = strdup(qsaDevice);
  109. entry.card = 0;
  110. entry.dev = 0;
  111. VECTOR_PUSH_BACK(*devmap, entry);
  112. for(card = 0;card < max_cards;card++)
  113. {
  114. if((err=snd_ctl_open(&handle, card)) < 0)
  115. continue;
  116. if((err=snd_ctl_hw_info(handle, &info)) < 0)
  117. {
  118. snd_ctl_close(handle);
  119. continue;
  120. }
  121. for(dev = 0;dev < (int)info.pcmdevs;dev++)
  122. {
  123. if((err=snd_ctl_pcm_info(handle, dev, &pcminfo)) < 0)
  124. continue;
  125. if((type==SND_PCM_CHANNEL_PLAYBACK && (pcminfo.flags&SND_PCM_INFO_PLAYBACK)) ||
  126. (type==SND_PCM_CHANNEL_CAPTURE && (pcminfo.flags&SND_PCM_INFO_CAPTURE)))
  127. {
  128. snprintf(name, sizeof(name), "%s [%s] (hw:%d,%d)", info.name, pcminfo.name, card, dev);
  129. entry.name = strdup(name);
  130. entry.card = card;
  131. entry.dev = dev;
  132. VECTOR_PUSH_BACK(*devmap, entry);
  133. TRACE("Got device \"%s\", card %d, dev %d\n", name, card, dev);
  134. }
  135. }
  136. snd_ctl_close(handle);
  137. }
  138. }
  139. /* Wrappers to use an old-style backend with the new interface. */
  140. typedef struct PlaybackWrapper {
  141. DERIVE_FROM_TYPE(ALCbackend);
  142. qsa_data *ExtraData;
  143. } PlaybackWrapper;
  144. static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device);
  145. static void PlaybackWrapper_Destruct(PlaybackWrapper *self);
  146. static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name);
  147. static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self);
  148. static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self);
  149. static void PlaybackWrapper_stop(PlaybackWrapper *self);
  150. static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
  151. static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples)
  152. static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ClockLatency, getClockLatency)
  153. static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock)
  154. static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock)
  155. DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper)
  156. DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper);
  157. FORCE_ALIGN static int qsa_proc_playback(void *ptr)
  158. {
  159. PlaybackWrapper *self = ptr;
  160. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  161. qsa_data *data = self->ExtraData;
  162. snd_pcm_channel_status_t status;
  163. struct sched_param param;
  164. struct timeval timeout;
  165. char* write_ptr;
  166. fd_set wfds;
  167. ALint len;
  168. int sret;
  169. SetRTPriority();
  170. althrd_setname(althrd_current(), MIXER_THREAD_NAME);
  171. /* Increase default 10 priority to 11 to avoid jerky sound */
  172. SchedGet(0, 0, &param);
  173. param.sched_priority=param.sched_curpriority+1;
  174. SchedSet(0, 0, SCHED_NOCHANGE, &param);
  175. const ALint frame_size = FrameSizeFromDevFmt(
  176. device->FmtChans, device->FmtType, device->AmbiOrder
  177. );
  178. V0(device->Backend,lock)();
  179. while(!ATOMIC_LOAD(&data->killNow, almemory_order_acquire))
  180. {
  181. FD_ZERO(&wfds);
  182. FD_SET(data->audio_fd, &wfds);
  183. timeout.tv_sec=2;
  184. timeout.tv_usec=0;
  185. /* Select also works like time slice to OS */
  186. V0(device->Backend,unlock)();
  187. sret = select(data->audio_fd+1, NULL, &wfds, NULL, &timeout);
  188. V0(device->Backend,lock)();
  189. if(sret == -1)
  190. {
  191. ERR("select error: %s\n", strerror(errno));
  192. aluHandleDisconnect(device, "Failed waiting for playback buffer: %s", strerror(errno));
  193. break;
  194. }
  195. if(sret == 0)
  196. {
  197. ERR("select timeout\n");
  198. continue;
  199. }
  200. len = data->size;
  201. write_ptr = data->buffer;
  202. aluMixData(device, write_ptr, len/frame_size);
  203. while(len>0 && !ATOMIC_LOAD(&data->killNow, almemory_order_acquire))
  204. {
  205. int wrote = snd_pcm_plugin_write(data->pcmHandle, write_ptr, len);
  206. if(wrote <= 0)
  207. {
  208. if(errno==EAGAIN || errno==EWOULDBLOCK)
  209. continue;
  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, "Playback recovery failed");
  220. break;
  221. }
  222. }
  223. }
  224. else
  225. {
  226. write_ptr += wrote;
  227. len -= wrote;
  228. }
  229. }
  230. }
  231. V0(device->Backend,unlock)();
  232. return 0;
  233. }
  234. /************/
  235. /* Playback */
  236. /************/
  237. static ALCenum qsa_open_playback(PlaybackWrapper *self, const ALCchar* deviceName)
  238. {
  239. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  240. qsa_data *data;
  241. int card, dev;
  242. int status;
  243. data = (qsa_data*)calloc(1, sizeof(qsa_data));
  244. if(data == NULL)
  245. return ALC_OUT_OF_MEMORY;
  246. ATOMIC_INIT(&data->killNow, AL_TRUE);
  247. if(!deviceName)
  248. deviceName = qsaDevice;
  249. if(strcmp(deviceName, qsaDevice) == 0)
  250. status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK);
  251. else
  252. {
  253. const DevMap *iter;
  254. if(VECTOR_SIZE(DeviceNameMap) == 0)
  255. deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap);
  256. #define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0)
  257. VECTOR_FIND_IF(iter, const DevMap, DeviceNameMap, MATCH_DEVNAME);
  258. #undef MATCH_DEVNAME
  259. if(iter == VECTOR_END(DeviceNameMap))
  260. {
  261. free(data);
  262. return ALC_INVALID_DEVICE;
  263. }
  264. status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_PLAYBACK);
  265. }
  266. if(status < 0)
  267. {
  268. free(data);
  269. return ALC_INVALID_DEVICE;
  270. }
  271. data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
  272. if(data->audio_fd < 0)
  273. {
  274. snd_pcm_close(data->pcmHandle);
  275. free(data);
  276. return ALC_INVALID_DEVICE;
  277. }
  278. alstr_copy_cstr(&device->DeviceName, deviceName);
  279. self->ExtraData = data;
  280. return ALC_NO_ERROR;
  281. }
  282. static void qsa_close_playback(PlaybackWrapper *self)
  283. {
  284. qsa_data *data = self->ExtraData;
  285. if (data->buffer!=NULL)
  286. {
  287. free(data->buffer);
  288. data->buffer=NULL;
  289. }
  290. snd_pcm_close(data->pcmHandle);
  291. free(data);
  292. self->ExtraData = NULL;
  293. }
  294. static ALCboolean qsa_reset_playback(PlaybackWrapper *self)
  295. {
  296. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  297. qsa_data *data = self->ExtraData;
  298. int32_t format=-1;
  299. switch(device->FmtType)
  300. {
  301. case DevFmtByte:
  302. format=SND_PCM_SFMT_S8;
  303. break;
  304. case DevFmtUByte:
  305. format=SND_PCM_SFMT_U8;
  306. break;
  307. case DevFmtShort:
  308. format=SND_PCM_SFMT_S16_LE;
  309. break;
  310. case DevFmtUShort:
  311. format=SND_PCM_SFMT_U16_LE;
  312. break;
  313. case DevFmtInt:
  314. format=SND_PCM_SFMT_S32_LE;
  315. break;
  316. case DevFmtUInt:
  317. format=SND_PCM_SFMT_U32_LE;
  318. break;
  319. case DevFmtFloat:
  320. format=SND_PCM_SFMT_FLOAT_LE;
  321. break;
  322. }
  323. /* we actually don't want to block on writes */
  324. snd_pcm_nonblock_mode(data->pcmHandle, 1);
  325. /* Disable mmap to control data transfer to the audio device */
  326. snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP);
  327. snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS);
  328. // configure a sound channel
  329. memset(&data->cparams, 0, sizeof(data->cparams));
  330. data->cparams.channel=SND_PCM_CHANNEL_PLAYBACK;
  331. data->cparams.mode=SND_PCM_MODE_BLOCK;
  332. data->cparams.start_mode=SND_PCM_START_FULL;
  333. data->cparams.stop_mode=SND_PCM_STOP_STOP;
  334. data->cparams.buf.block.frag_size=device->UpdateSize *
  335. FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  336. data->cparams.buf.block.frags_max=device->NumUpdates;
  337. data->cparams.buf.block.frags_min=device->NumUpdates;
  338. data->cparams.format.interleave=1;
  339. data->cparams.format.rate=device->Frequency;
  340. data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  341. data->cparams.format.format=format;
  342. if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
  343. {
  344. int original_rate=data->cparams.format.rate;
  345. int original_voices=data->cparams.format.voices;
  346. int original_format=data->cparams.format.format;
  347. int it;
  348. int jt;
  349. for (it=0; it<1; it++)
  350. {
  351. /* Check for second pass */
  352. if (it==1)
  353. {
  354. original_rate=ratelist[0].rate;
  355. original_voices=channellist[0].channels;
  356. original_format=formatlist[0].format;
  357. }
  358. do {
  359. /* At first downgrade sample format */
  360. jt=0;
  361. do {
  362. if (formatlist[jt].format==data->cparams.format.format)
  363. {
  364. data->cparams.format.format=formatlist[jt+1].format;
  365. break;
  366. }
  367. if (formatlist[jt].format==0)
  368. {
  369. data->cparams.format.format=0;
  370. break;
  371. }
  372. jt++;
  373. } while(1);
  374. if (data->cparams.format.format==0)
  375. {
  376. data->cparams.format.format=original_format;
  377. /* At secod downgrade sample rate */
  378. jt=0;
  379. do {
  380. if (ratelist[jt].rate==data->cparams.format.rate)
  381. {
  382. data->cparams.format.rate=ratelist[jt+1].rate;
  383. break;
  384. }
  385. if (ratelist[jt].rate==0)
  386. {
  387. data->cparams.format.rate=0;
  388. break;
  389. }
  390. jt++;
  391. } while(1);
  392. if (data->cparams.format.rate==0)
  393. {
  394. data->cparams.format.rate=original_rate;
  395. data->cparams.format.format=original_format;
  396. /* At third downgrade channels number */
  397. jt=0;
  398. do {
  399. if(channellist[jt].channels==data->cparams.format.voices)
  400. {
  401. data->cparams.format.voices=channellist[jt+1].channels;
  402. break;
  403. }
  404. if (channellist[jt].channels==0)
  405. {
  406. data->cparams.format.voices=0;
  407. break;
  408. }
  409. jt++;
  410. } while(1);
  411. }
  412. if (data->cparams.format.voices==0)
  413. {
  414. break;
  415. }
  416. }
  417. data->cparams.buf.block.frag_size=device->UpdateSize*
  418. data->cparams.format.voices*
  419. snd_pcm_format_width(data->cparams.format.format)/8;
  420. data->cparams.buf.block.frags_max=device->NumUpdates;
  421. data->cparams.buf.block.frags_min=device->NumUpdates;
  422. if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
  423. {
  424. continue;
  425. }
  426. else
  427. {
  428. break;
  429. }
  430. } while(1);
  431. if (data->cparams.format.voices!=0)
  432. {
  433. break;
  434. }
  435. }
  436. if (data->cparams.format.voices==0)
  437. {
  438. return ALC_FALSE;
  439. }
  440. }
  441. if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
  442. {
  443. return ALC_FALSE;
  444. }
  445. memset(&data->csetup, 0, sizeof(data->csetup));
  446. data->csetup.channel=SND_PCM_CHANNEL_PLAYBACK;
  447. if (snd_pcm_plugin_setup(data->pcmHandle, &data->csetup)<0)
  448. {
  449. return ALC_FALSE;
  450. }
  451. /* now fill back to the our AL device */
  452. device->Frequency=data->cparams.format.rate;
  453. switch (data->cparams.format.voices)
  454. {
  455. case 1:
  456. device->FmtChans=DevFmtMono;
  457. break;
  458. case 2:
  459. device->FmtChans=DevFmtStereo;
  460. break;
  461. case 4:
  462. device->FmtChans=DevFmtQuad;
  463. break;
  464. case 6:
  465. device->FmtChans=DevFmtX51;
  466. break;
  467. case 7:
  468. device->FmtChans=DevFmtX61;
  469. break;
  470. case 8:
  471. device->FmtChans=DevFmtX71;
  472. break;
  473. default:
  474. device->FmtChans=DevFmtMono;
  475. break;
  476. }
  477. switch (data->cparams.format.format)
  478. {
  479. case SND_PCM_SFMT_S8:
  480. device->FmtType=DevFmtByte;
  481. break;
  482. case SND_PCM_SFMT_U8:
  483. device->FmtType=DevFmtUByte;
  484. break;
  485. case SND_PCM_SFMT_S16_LE:
  486. device->FmtType=DevFmtShort;
  487. break;
  488. case SND_PCM_SFMT_U16_LE:
  489. device->FmtType=DevFmtUShort;
  490. break;
  491. case SND_PCM_SFMT_S32_LE:
  492. device->FmtType=DevFmtInt;
  493. break;
  494. case SND_PCM_SFMT_U32_LE:
  495. device->FmtType=DevFmtUInt;
  496. break;
  497. case SND_PCM_SFMT_FLOAT_LE:
  498. device->FmtType=DevFmtFloat;
  499. break;
  500. default:
  501. device->FmtType=DevFmtShort;
  502. break;
  503. }
  504. SetDefaultChannelOrder(device);
  505. device->UpdateSize=data->csetup.buf.block.frag_size/
  506. FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  507. device->NumUpdates=data->csetup.buf.block.frags;
  508. data->size=data->csetup.buf.block.frag_size;
  509. data->buffer=malloc(data->size);
  510. if (!data->buffer)
  511. {
  512. return ALC_FALSE;
  513. }
  514. return ALC_TRUE;
  515. }
  516. static ALCboolean qsa_start_playback(PlaybackWrapper *self)
  517. {
  518. qsa_data *data = self->ExtraData;
  519. ATOMIC_STORE(&data->killNow, AL_FALSE, almemory_order_release);
  520. if(althrd_create(&data->thread, qsa_proc_playback, self) != althrd_success)
  521. return ALC_FALSE;
  522. return ALC_TRUE;
  523. }
  524. static void qsa_stop_playback(PlaybackWrapper *self)
  525. {
  526. qsa_data *data = self->ExtraData;
  527. int res;
  528. if(ATOMIC_EXCHANGE(&data->killNow, AL_TRUE, almemory_order_acq_rel))
  529. return;
  530. althrd_join(data->thread, &res);
  531. }
  532. static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device)
  533. {
  534. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  535. SET_VTABLE2(PlaybackWrapper, ALCbackend, self);
  536. self->ExtraData = NULL;
  537. }
  538. static void PlaybackWrapper_Destruct(PlaybackWrapper *self)
  539. {
  540. if(self->ExtraData)
  541. qsa_close_playback(self);
  542. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  543. }
  544. static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name)
  545. {
  546. return qsa_open_playback(self, name);
  547. }
  548. static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self)
  549. {
  550. return qsa_reset_playback(self);
  551. }
  552. static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self)
  553. {
  554. return qsa_start_playback(self);
  555. }
  556. static void PlaybackWrapper_stop(PlaybackWrapper *self)
  557. {
  558. qsa_stop_playback(self);
  559. }
  560. /***********/
  561. /* Capture */
  562. /***********/
  563. typedef struct CaptureWrapper {
  564. DERIVE_FROM_TYPE(ALCbackend);
  565. qsa_data *ExtraData;
  566. } CaptureWrapper;
  567. static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device);
  568. static void CaptureWrapper_Destruct(CaptureWrapper *self);
  569. static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name);
  570. static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset)
  571. static ALCboolean CaptureWrapper_start(CaptureWrapper *self);
  572. static void CaptureWrapper_stop(CaptureWrapper *self);
  573. static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples);
  574. static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self);
  575. static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ClockLatency, getClockLatency)
  576. static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock)
  577. static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock)
  578. DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper)
  579. DEFINE_ALCBACKEND_VTABLE(CaptureWrapper);
  580. static ALCenum qsa_open_capture(CaptureWrapper *self, const ALCchar *deviceName)
  581. {
  582. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  583. qsa_data *data;
  584. int card, dev;
  585. int format=-1;
  586. int status;
  587. data=(qsa_data*)calloc(1, sizeof(qsa_data));
  588. if (data==NULL)
  589. {
  590. return ALC_OUT_OF_MEMORY;
  591. }
  592. if(!deviceName)
  593. deviceName = qsaDevice;
  594. if(strcmp(deviceName, qsaDevice) == 0)
  595. status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE);
  596. else
  597. {
  598. const DevMap *iter;
  599. if(VECTOR_SIZE(CaptureNameMap) == 0)
  600. deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap);
  601. #define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0)
  602. VECTOR_FIND_IF(iter, const DevMap, CaptureNameMap, MATCH_DEVNAME);
  603. #undef MATCH_DEVNAME
  604. if(iter == VECTOR_END(CaptureNameMap))
  605. {
  606. free(data);
  607. return ALC_INVALID_DEVICE;
  608. }
  609. status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_CAPTURE);
  610. }
  611. if(status < 0)
  612. {
  613. free(data);
  614. return ALC_INVALID_DEVICE;
  615. }
  616. data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE);
  617. if(data->audio_fd < 0)
  618. {
  619. snd_pcm_close(data->pcmHandle);
  620. free(data);
  621. return ALC_INVALID_DEVICE;
  622. }
  623. alstr_copy_cstr(&device->DeviceName, deviceName);
  624. self->ExtraData = data;
  625. switch (device->FmtType)
  626. {
  627. case DevFmtByte:
  628. format=SND_PCM_SFMT_S8;
  629. break;
  630. case DevFmtUByte:
  631. format=SND_PCM_SFMT_U8;
  632. break;
  633. case DevFmtShort:
  634. format=SND_PCM_SFMT_S16_LE;
  635. break;
  636. case DevFmtUShort:
  637. format=SND_PCM_SFMT_U16_LE;
  638. break;
  639. case DevFmtInt:
  640. format=SND_PCM_SFMT_S32_LE;
  641. break;
  642. case DevFmtUInt:
  643. format=SND_PCM_SFMT_U32_LE;
  644. break;
  645. case DevFmtFloat:
  646. format=SND_PCM_SFMT_FLOAT_LE;
  647. break;
  648. }
  649. /* we actually don't want to block on reads */
  650. snd_pcm_nonblock_mode(data->pcmHandle, 1);
  651. /* Disable mmap to control data transfer to the audio device */
  652. snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP);
  653. /* configure a sound channel */
  654. memset(&data->cparams, 0, sizeof(data->cparams));
  655. data->cparams.mode=SND_PCM_MODE_BLOCK;
  656. data->cparams.channel=SND_PCM_CHANNEL_CAPTURE;
  657. data->cparams.start_mode=SND_PCM_START_GO;
  658. data->cparams.stop_mode=SND_PCM_STOP_STOP;
  659. data->cparams.buf.block.frag_size=device->UpdateSize*
  660. FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  661. data->cparams.buf.block.frags_max=device->NumUpdates;
  662. data->cparams.buf.block.frags_min=device->NumUpdates;
  663. data->cparams.format.interleave=1;
  664. data->cparams.format.rate=device->Frequency;
  665. data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  666. data->cparams.format.format=format;
  667. if(snd_pcm_plugin_params(data->pcmHandle, &data->cparams) < 0)
  668. {
  669. snd_pcm_close(data->pcmHandle);
  670. free(data);
  671. return ALC_INVALID_VALUE;
  672. }
  673. return ALC_NO_ERROR;
  674. }
  675. static void qsa_close_capture(CaptureWrapper *self)
  676. {
  677. qsa_data *data = self->ExtraData;
  678. if (data->pcmHandle!=NULL)
  679. snd_pcm_close(data->pcmHandle);
  680. free(data);
  681. self->ExtraData = NULL;
  682. }
  683. static void qsa_start_capture(CaptureWrapper *self)
  684. {
  685. qsa_data *data = self->ExtraData;
  686. int rstatus;
  687. if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
  688. {
  689. ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
  690. return;
  691. }
  692. memset(&data->csetup, 0, sizeof(data->csetup));
  693. data->csetup.channel=SND_PCM_CHANNEL_CAPTURE;
  694. if ((rstatus=snd_pcm_plugin_setup(data->pcmHandle, &data->csetup))<0)
  695. {
  696. ERR("capture setup failed: %s\n", snd_strerror(rstatus));
  697. return;
  698. }
  699. snd_pcm_capture_go(data->pcmHandle);
  700. }
  701. static void qsa_stop_capture(CaptureWrapper *self)
  702. {
  703. qsa_data *data = self->ExtraData;
  704. snd_pcm_capture_flush(data->pcmHandle);
  705. }
  706. static ALCuint qsa_available_samples(CaptureWrapper *self)
  707. {
  708. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  709. qsa_data *data = self->ExtraData;
  710. snd_pcm_channel_status_t status;
  711. ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  712. ALint free_size;
  713. int rstatus;
  714. memset(&status, 0, sizeof (status));
  715. status.channel=SND_PCM_CHANNEL_CAPTURE;
  716. snd_pcm_plugin_status(data->pcmHandle, &status);
  717. if ((status.status==SND_PCM_STATUS_OVERRUN) ||
  718. (status.status==SND_PCM_STATUS_READY))
  719. {
  720. if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
  721. {
  722. ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
  723. aluHandleDisconnect(device, "Failed capture recovery: %s", snd_strerror(rstatus));
  724. return 0;
  725. }
  726. snd_pcm_capture_go(data->pcmHandle);
  727. return 0;
  728. }
  729. free_size=data->csetup.buf.block.frag_size*data->csetup.buf.block.frags;
  730. free_size-=status.free;
  731. return free_size/frame_size;
  732. }
  733. static ALCenum qsa_capture_samples(CaptureWrapper *self, ALCvoid *buffer, ALCuint samples)
  734. {
  735. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  736. qsa_data *data = self->ExtraData;
  737. char* read_ptr;
  738. snd_pcm_channel_status_t status;
  739. fd_set rfds;
  740. int selectret;
  741. struct timeval timeout;
  742. int bytes_read;
  743. ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  744. ALint len=samples*frame_size;
  745. int rstatus;
  746. read_ptr=buffer;
  747. while (len>0)
  748. {
  749. FD_ZERO(&rfds);
  750. FD_SET(data->audio_fd, &rfds);
  751. timeout.tv_sec=2;
  752. timeout.tv_usec=0;
  753. /* Select also works like time slice to OS */
  754. bytes_read=0;
  755. selectret=select(data->audio_fd+1, &rfds, NULL, NULL, &timeout);
  756. switch (selectret)
  757. {
  758. case -1:
  759. aluHandleDisconnect(device, "Failed to check capture samples");
  760. return ALC_INVALID_DEVICE;
  761. case 0:
  762. break;
  763. default:
  764. if (FD_ISSET(data->audio_fd, &rfds))
  765. {
  766. bytes_read=snd_pcm_plugin_read(data->pcmHandle, read_ptr, len);
  767. break;
  768. }
  769. break;
  770. }
  771. if (bytes_read<=0)
  772. {
  773. if ((errno==EAGAIN) || (errno==EWOULDBLOCK))
  774. {
  775. continue;
  776. }
  777. memset(&status, 0, sizeof (status));
  778. status.channel=SND_PCM_CHANNEL_CAPTURE;
  779. snd_pcm_plugin_status(data->pcmHandle, &status);
  780. /* we need to reinitialize the sound channel if we've overrun the buffer */
  781. if ((status.status==SND_PCM_STATUS_OVERRUN) ||
  782. (status.status==SND_PCM_STATUS_READY))
  783. {
  784. if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
  785. {
  786. ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
  787. aluHandleDisconnect(device, "Failed capture recovery: %s",
  788. snd_strerror(rstatus));
  789. return ALC_INVALID_DEVICE;
  790. }
  791. snd_pcm_capture_go(data->pcmHandle);
  792. }
  793. }
  794. else
  795. {
  796. read_ptr+=bytes_read;
  797. len-=bytes_read;
  798. }
  799. }
  800. return ALC_NO_ERROR;
  801. }
  802. static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device)
  803. {
  804. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  805. SET_VTABLE2(CaptureWrapper, ALCbackend, self);
  806. self->ExtraData = NULL;
  807. }
  808. static void CaptureWrapper_Destruct(CaptureWrapper *self)
  809. {
  810. if(self->ExtraData)
  811. qsa_close_capture(self);
  812. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  813. }
  814. static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name)
  815. {
  816. return qsa_open_capture(self, name);
  817. }
  818. static ALCboolean CaptureWrapper_start(CaptureWrapper *self)
  819. {
  820. qsa_start_capture(self);
  821. return ALC_TRUE;
  822. }
  823. static void CaptureWrapper_stop(CaptureWrapper *self)
  824. {
  825. qsa_stop_capture(self);
  826. }
  827. static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples)
  828. {
  829. return qsa_capture_samples(self, buffer, samples);
  830. }
  831. static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self)
  832. {
  833. return qsa_available_samples(self);
  834. }
  835. typedef struct ALCqsaBackendFactory {
  836. DERIVE_FROM_TYPE(ALCbackendFactory);
  837. } ALCqsaBackendFactory;
  838. #define ALCQSABACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCqsaBackendFactory, ALCbackendFactory) } }
  839. static ALCboolean ALCqsaBackendFactory_init(ALCqsaBackendFactory* UNUSED(self));
  840. static void ALCqsaBackendFactory_deinit(ALCqsaBackendFactory* UNUSED(self));
  841. static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED(self), ALCbackend_Type type);
  842. static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames);
  843. static ALCbackend* ALCqsaBackendFactory_createBackend(ALCqsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type);
  844. DEFINE_ALCBACKENDFACTORY_VTABLE(ALCqsaBackendFactory);
  845. static ALCboolean ALCqsaBackendFactory_init(ALCqsaBackendFactory* UNUSED(self))
  846. {
  847. return ALC_TRUE;
  848. }
  849. static void ALCqsaBackendFactory_deinit(ALCqsaBackendFactory* UNUSED(self))
  850. {
  851. #define FREE_NAME(iter) free((iter)->name)
  852. VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME);
  853. VECTOR_DEINIT(DeviceNameMap);
  854. VECTOR_FOR_EACH(DevMap, CaptureNameMap, FREE_NAME);
  855. VECTOR_DEINIT(CaptureNameMap);
  856. #undef FREE_NAME
  857. }
  858. static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED(self), ALCbackend_Type type)
  859. {
  860. if(type == ALCbackend_Playback || type == ALCbackend_Capture)
  861. return ALC_TRUE;
  862. return ALC_FALSE;
  863. }
  864. static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
  865. {
  866. switch (type)
  867. {
  868. #define APPEND_OUTNAME(e) do { \
  869. const char *n_ = (e)->name; \
  870. if(n_ && n_[0]) \
  871. alstr_append_range(outnames, n_, n_+strlen(n_)+1); \
  872. } while(0)
  873. case ALL_DEVICE_PROBE:
  874. deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap);
  875. VECTOR_FOR_EACH(const DevMap, DeviceNameMap, APPEND_OUTNAME);
  876. break;
  877. case CAPTURE_DEVICE_PROBE:
  878. deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap);
  879. VECTOR_FOR_EACH(const DevMap, CaptureNameMap, APPEND_OUTNAME);
  880. break;
  881. #undef APPEND_OUTNAME
  882. }
  883. }
  884. static ALCbackend* ALCqsaBackendFactory_createBackend(ALCqsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
  885. {
  886. if(type == ALCbackend_Playback)
  887. {
  888. PlaybackWrapper *backend;
  889. NEW_OBJ(backend, PlaybackWrapper)(device);
  890. if(!backend) return NULL;
  891. return STATIC_CAST(ALCbackend, backend);
  892. }
  893. if(type == ALCbackend_Capture)
  894. {
  895. CaptureWrapper *backend;
  896. NEW_OBJ(backend, CaptureWrapper)(device);
  897. if(!backend) return NULL;
  898. return STATIC_CAST(ALCbackend, backend);
  899. }
  900. return NULL;
  901. }
  902. ALCbackendFactory *ALCqsaBackendFactory_getFactory(void)
  903. {
  904. static ALCqsaBackendFactory factory = ALCQSABACKENDFACTORY_INITIALIZER;
  905. return STATIC_CAST(ALCbackendFactory, &factory);
  906. }