sndio.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2007 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 <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include "alMain.h"
  25. #include "alu.h"
  26. #include "threads.h"
  27. #include "ringbuffer.h"
  28. #include "backends/base.h"
  29. #include <sndio.h>
  30. static const ALCchar sndio_device[] = "SndIO Default";
  31. typedef struct SndioPlayback {
  32. DERIVE_FROM_TYPE(ALCbackend);
  33. struct sio_hdl *sndHandle;
  34. ALvoid *mix_data;
  35. ALsizei data_size;
  36. ATOMIC(int) killNow;
  37. althrd_t thread;
  38. } SndioPlayback;
  39. static int SndioPlayback_mixerProc(void *ptr);
  40. static void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device);
  41. static void SndioPlayback_Destruct(SndioPlayback *self);
  42. static ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name);
  43. static ALCboolean SndioPlayback_reset(SndioPlayback *self);
  44. static ALCboolean SndioPlayback_start(SndioPlayback *self);
  45. static void SndioPlayback_stop(SndioPlayback *self);
  46. static DECLARE_FORWARD2(SndioPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
  47. static DECLARE_FORWARD(SndioPlayback, ALCbackend, ALCuint, availableSamples)
  48. static DECLARE_FORWARD(SndioPlayback, ALCbackend, ClockLatency, getClockLatency)
  49. static DECLARE_FORWARD(SndioPlayback, ALCbackend, void, lock)
  50. static DECLARE_FORWARD(SndioPlayback, ALCbackend, void, unlock)
  51. DECLARE_DEFAULT_ALLOCATORS(SndioPlayback)
  52. DEFINE_ALCBACKEND_VTABLE(SndioPlayback);
  53. static void SndioPlayback_Construct(SndioPlayback *self, ALCdevice *device)
  54. {
  55. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  56. SET_VTABLE2(SndioPlayback, ALCbackend, self);
  57. self->sndHandle = NULL;
  58. self->mix_data = NULL;
  59. ATOMIC_INIT(&self->killNow, AL_TRUE);
  60. }
  61. static void SndioPlayback_Destruct(SndioPlayback *self)
  62. {
  63. if(self->sndHandle)
  64. sio_close(self->sndHandle);
  65. self->sndHandle = NULL;
  66. al_free(self->mix_data);
  67. self->mix_data = NULL;
  68. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  69. }
  70. static int SndioPlayback_mixerProc(void *ptr)
  71. {
  72. SndioPlayback *self = (SndioPlayback*)ptr;
  73. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  74. ALsizei frameSize;
  75. size_t wrote;
  76. SetRTPriority();
  77. althrd_setname(althrd_current(), MIXER_THREAD_NAME);
  78. frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  79. while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
  80. ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
  81. {
  82. ALsizei len = self->data_size;
  83. ALubyte *WritePtr = self->mix_data;
  84. SndioPlayback_lock(self);
  85. aluMixData(device, WritePtr, len/frameSize);
  86. SndioPlayback_unlock(self);
  87. while(len > 0 && !ATOMIC_LOAD(&self->killNow, almemory_order_acquire))
  88. {
  89. wrote = sio_write(self->sndHandle, WritePtr, len);
  90. if(wrote == 0)
  91. {
  92. ERR("sio_write failed\n");
  93. ALCdevice_Lock(device);
  94. aluHandleDisconnect(device, "Failed to write playback samples");
  95. ALCdevice_Unlock(device);
  96. break;
  97. }
  98. len -= wrote;
  99. WritePtr += wrote;
  100. }
  101. }
  102. return 0;
  103. }
  104. static ALCenum SndioPlayback_open(SndioPlayback *self, const ALCchar *name)
  105. {
  106. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  107. if(!name)
  108. name = sndio_device;
  109. else if(strcmp(name, sndio_device) != 0)
  110. return ALC_INVALID_VALUE;
  111. self->sndHandle = sio_open(NULL, SIO_PLAY, 0);
  112. if(self->sndHandle == NULL)
  113. {
  114. ERR("Could not open device\n");
  115. return ALC_INVALID_VALUE;
  116. }
  117. alstr_copy_cstr(&device->DeviceName, name);
  118. return ALC_NO_ERROR;
  119. }
  120. static ALCboolean SndioPlayback_reset(SndioPlayback *self)
  121. {
  122. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  123. struct sio_par par;
  124. sio_initpar(&par);
  125. par.rate = device->Frequency;
  126. par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
  127. switch(device->FmtType)
  128. {
  129. case DevFmtByte:
  130. par.bits = 8;
  131. par.sig = 1;
  132. break;
  133. case DevFmtUByte:
  134. par.bits = 8;
  135. par.sig = 0;
  136. break;
  137. case DevFmtFloat:
  138. case DevFmtShort:
  139. par.bits = 16;
  140. par.sig = 1;
  141. break;
  142. case DevFmtUShort:
  143. par.bits = 16;
  144. par.sig = 0;
  145. break;
  146. case DevFmtInt:
  147. par.bits = 32;
  148. par.sig = 1;
  149. break;
  150. case DevFmtUInt:
  151. par.bits = 32;
  152. par.sig = 0;
  153. break;
  154. }
  155. par.le = SIO_LE_NATIVE;
  156. par.round = device->UpdateSize;
  157. par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
  158. if(!par.appbufsz) par.appbufsz = device->UpdateSize;
  159. if(!sio_setpar(self->sndHandle, &par) || !sio_getpar(self->sndHandle, &par))
  160. {
  161. ERR("Failed to set device parameters\n");
  162. return ALC_FALSE;
  163. }
  164. if(par.bits != par.bps*8)
  165. {
  166. ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
  167. return ALC_FALSE;
  168. }
  169. device->Frequency = par.rate;
  170. device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
  171. if(par.bits == 8 && par.sig == 1)
  172. device->FmtType = DevFmtByte;
  173. else if(par.bits == 8 && par.sig == 0)
  174. device->FmtType = DevFmtUByte;
  175. else if(par.bits == 16 && par.sig == 1)
  176. device->FmtType = DevFmtShort;
  177. else if(par.bits == 16 && par.sig == 0)
  178. device->FmtType = DevFmtUShort;
  179. else if(par.bits == 32 && par.sig == 1)
  180. device->FmtType = DevFmtInt;
  181. else if(par.bits == 32 && par.sig == 0)
  182. device->FmtType = DevFmtUInt;
  183. else
  184. {
  185. ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
  186. return ALC_FALSE;
  187. }
  188. device->UpdateSize = par.round;
  189. device->NumUpdates = (par.bufsz/par.round) + 1;
  190. SetDefaultChannelOrder(device);
  191. return ALC_TRUE;
  192. }
  193. static ALCboolean SndioPlayback_start(SndioPlayback *self)
  194. {
  195. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  196. self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
  197. device->FmtChans, device->FmtType, device->AmbiOrder
  198. );
  199. al_free(self->mix_data);
  200. self->mix_data = al_calloc(16, self->data_size);
  201. if(!sio_start(self->sndHandle))
  202. {
  203. ERR("Error starting playback\n");
  204. return ALC_FALSE;
  205. }
  206. ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
  207. if(althrd_create(&self->thread, SndioPlayback_mixerProc, self) != althrd_success)
  208. {
  209. sio_stop(self->sndHandle);
  210. return ALC_FALSE;
  211. }
  212. return ALC_TRUE;
  213. }
  214. static void SndioPlayback_stop(SndioPlayback *self)
  215. {
  216. int res;
  217. if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
  218. return;
  219. althrd_join(self->thread, &res);
  220. if(!sio_stop(self->sndHandle))
  221. ERR("Error stopping device\n");
  222. al_free(self->mix_data);
  223. self->mix_data = NULL;
  224. }
  225. typedef struct SndioCapture {
  226. DERIVE_FROM_TYPE(ALCbackend);
  227. struct sio_hdl *sndHandle;
  228. ll_ringbuffer_t *ring;
  229. ATOMIC(int) killNow;
  230. althrd_t thread;
  231. } SndioCapture;
  232. static int SndioCapture_recordProc(void *ptr);
  233. static void SndioCapture_Construct(SndioCapture *self, ALCdevice *device);
  234. static void SndioCapture_Destruct(SndioCapture *self);
  235. static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name);
  236. static DECLARE_FORWARD(SndioCapture, ALCbackend, ALCboolean, reset)
  237. static ALCboolean SndioCapture_start(SndioCapture *self);
  238. static void SndioCapture_stop(SndioCapture *self);
  239. static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples);
  240. static ALCuint SndioCapture_availableSamples(SndioCapture *self);
  241. static DECLARE_FORWARD(SndioCapture, ALCbackend, ClockLatency, getClockLatency)
  242. static DECLARE_FORWARD(SndioCapture, ALCbackend, void, lock)
  243. static DECLARE_FORWARD(SndioCapture, ALCbackend, void, unlock)
  244. DECLARE_DEFAULT_ALLOCATORS(SndioCapture)
  245. DEFINE_ALCBACKEND_VTABLE(SndioCapture);
  246. static void SndioCapture_Construct(SndioCapture *self, ALCdevice *device)
  247. {
  248. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  249. SET_VTABLE2(SndioCapture, ALCbackend, self);
  250. self->sndHandle = NULL;
  251. self->ring = NULL;
  252. ATOMIC_INIT(&self->killNow, AL_TRUE);
  253. }
  254. static void SndioCapture_Destruct(SndioCapture *self)
  255. {
  256. if(self->sndHandle)
  257. sio_close(self->sndHandle);
  258. self->sndHandle = NULL;
  259. ll_ringbuffer_free(self->ring);
  260. self->ring = NULL;
  261. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  262. }
  263. static int SndioCapture_recordProc(void* ptr)
  264. {
  265. SndioCapture *self = (SndioCapture*)ptr;
  266. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  267. ALsizei frameSize;
  268. SetRTPriority();
  269. althrd_setname(althrd_current(), RECORD_THREAD_NAME);
  270. frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  271. while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
  272. ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
  273. {
  274. ll_ringbuffer_data_t data[2];
  275. size_t total, todo;
  276. ll_ringbuffer_get_write_vector(self->ring, data);
  277. todo = data[0].len + data[1].len;
  278. if(todo == 0)
  279. {
  280. static char junk[4096];
  281. sio_read(self->sndHandle, junk, minz(sizeof(junk)/frameSize, device->UpdateSize)*frameSize);
  282. continue;
  283. }
  284. total = 0;
  285. data[0].len *= frameSize;
  286. data[1].len *= frameSize;
  287. todo = minz(todo, device->UpdateSize) * frameSize;
  288. while(total < todo)
  289. {
  290. size_t got;
  291. if(!data[0].len)
  292. data[0] = data[1];
  293. got = sio_read(self->sndHandle, data[0].buf, minz(todo-total, data[0].len));
  294. if(!got)
  295. {
  296. SndioCapture_lock(self);
  297. aluHandleDisconnect(device, "Failed to read capture samples");
  298. SndioCapture_unlock(self);
  299. break;
  300. }
  301. data[0].buf += got;
  302. data[0].len -= got;
  303. total += got;
  304. }
  305. ll_ringbuffer_write_advance(self->ring, total / frameSize);
  306. }
  307. return 0;
  308. }
  309. static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name)
  310. {
  311. ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
  312. struct sio_par par;
  313. if(!name)
  314. name = sndio_device;
  315. else if(strcmp(name, sndio_device) != 0)
  316. return ALC_INVALID_VALUE;
  317. self->sndHandle = sio_open(NULL, SIO_REC, 0);
  318. if(self->sndHandle == NULL)
  319. {
  320. ERR("Could not open device\n");
  321. return ALC_INVALID_VALUE;
  322. }
  323. sio_initpar(&par);
  324. switch(device->FmtType)
  325. {
  326. case DevFmtByte:
  327. par.bps = 1;
  328. par.sig = 1;
  329. break;
  330. case DevFmtUByte:
  331. par.bps = 1;
  332. par.sig = 0;
  333. break;
  334. case DevFmtShort:
  335. par.bps = 2;
  336. par.sig = 1;
  337. break;
  338. case DevFmtUShort:
  339. par.bps = 2;
  340. par.sig = 0;
  341. break;
  342. case DevFmtInt:
  343. par.bps = 4;
  344. par.sig = 1;
  345. break;
  346. case DevFmtUInt:
  347. par.bps = 4;
  348. par.sig = 0;
  349. break;
  350. case DevFmtFloat:
  351. ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType));
  352. return ALC_INVALID_VALUE;
  353. }
  354. par.bits = par.bps * 8;
  355. par.le = SIO_LE_NATIVE;
  356. par.msb = SIO_LE_NATIVE ? 0 : 1;
  357. par.rchan = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  358. par.rate = device->Frequency;
  359. par.appbufsz = maxu(device->UpdateSize*device->NumUpdates, (device->Frequency+9)/10);
  360. par.round = clampu(par.appbufsz/device->NumUpdates, (device->Frequency+99)/100,
  361. (device->Frequency+19)/20);
  362. device->UpdateSize = par.round;
  363. device->NumUpdates = maxu(par.appbufsz/par.round, 1);
  364. if(!sio_setpar(self->sndHandle, &par) || !sio_getpar(self->sndHandle, &par))
  365. {
  366. ERR("Failed to set device parameters\n");
  367. return ALC_INVALID_VALUE;
  368. }
  369. if(par.bits != par.bps*8)
  370. {
  371. ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
  372. return ALC_INVALID_VALUE;
  373. }
  374. if(!((device->FmtType == DevFmtByte && par.bits == 8 && par.sig != 0) ||
  375. (device->FmtType == DevFmtUByte && par.bits == 8 && par.sig == 0) ||
  376. (device->FmtType == DevFmtShort && par.bits == 16 && par.sig != 0) ||
  377. (device->FmtType == DevFmtUShort && par.bits == 16 && par.sig == 0) ||
  378. (device->FmtType == DevFmtInt && par.bits == 32 && par.sig != 0) ||
  379. (device->FmtType == DevFmtUInt && par.bits == 32 && par.sig == 0)) ||
  380. ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)par.rchan ||
  381. device->Frequency != par.rate)
  382. {
  383. ERR("Failed to set format %s %s %uhz, got %c%u %u-channel %uhz instead\n",
  384. DevFmtTypeString(device->FmtType), DevFmtChannelsString(device->FmtChans),
  385. device->Frequency, par.sig?'s':'u', par.bits, par.rchan, par.rate);
  386. return ALC_INVALID_VALUE;
  387. }
  388. self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, par.bps*par.rchan, 0);
  389. if(!self->ring)
  390. {
  391. ERR("Failed to allocate %u-byte ringbuffer\n",
  392. device->UpdateSize*device->NumUpdates*par.bps*par.rchan);
  393. return ALC_OUT_OF_MEMORY;
  394. }
  395. SetDefaultChannelOrder(device);
  396. alstr_copy_cstr(&device->DeviceName, name);
  397. return ALC_NO_ERROR;
  398. }
  399. static ALCboolean SndioCapture_start(SndioCapture *self)
  400. {
  401. if(!sio_start(self->sndHandle))
  402. {
  403. ERR("Error starting playback\n");
  404. return ALC_FALSE;
  405. }
  406. ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
  407. if(althrd_create(&self->thread, SndioCapture_recordProc, self) != althrd_success)
  408. {
  409. sio_stop(self->sndHandle);
  410. return ALC_FALSE;
  411. }
  412. return ALC_TRUE;
  413. }
  414. static void SndioCapture_stop(SndioCapture *self)
  415. {
  416. int res;
  417. if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
  418. return;
  419. althrd_join(self->thread, &res);
  420. if(!sio_stop(self->sndHandle))
  421. ERR("Error stopping device\n");
  422. }
  423. static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples)
  424. {
  425. ll_ringbuffer_read(self->ring, buffer, samples);
  426. return ALC_NO_ERROR;
  427. }
  428. static ALCuint SndioCapture_availableSamples(SndioCapture *self)
  429. {
  430. return ll_ringbuffer_read_space(self->ring);
  431. }
  432. typedef struct SndioBackendFactory {
  433. DERIVE_FROM_TYPE(ALCbackendFactory);
  434. } SndioBackendFactory;
  435. #define SNDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(SndioBackendFactory, ALCbackendFactory) } }
  436. ALCbackendFactory *SndioBackendFactory_getFactory(void);
  437. static ALCboolean SndioBackendFactory_init(SndioBackendFactory *self);
  438. static DECLARE_FORWARD(SndioBackendFactory, ALCbackendFactory, void, deinit)
  439. static ALCboolean SndioBackendFactory_querySupport(SndioBackendFactory *self, ALCbackend_Type type);
  440. static void SndioBackendFactory_probe(SndioBackendFactory *self, enum DevProbe type, al_string *outnames);
  441. static ALCbackend* SndioBackendFactory_createBackend(SndioBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
  442. DEFINE_ALCBACKENDFACTORY_VTABLE(SndioBackendFactory);
  443. ALCbackendFactory *SndioBackendFactory_getFactory(void)
  444. {
  445. static SndioBackendFactory factory = SNDIOBACKENDFACTORY_INITIALIZER;
  446. return STATIC_CAST(ALCbackendFactory, &factory);
  447. }
  448. static ALCboolean SndioBackendFactory_init(SndioBackendFactory* UNUSED(self))
  449. {
  450. /* No dynamic loading */
  451. return ALC_TRUE;
  452. }
  453. static ALCboolean SndioBackendFactory_querySupport(SndioBackendFactory* UNUSED(self), ALCbackend_Type type)
  454. {
  455. if(type == ALCbackend_Playback || type == ALCbackend_Capture)
  456. return ALC_TRUE;
  457. return ALC_FALSE;
  458. }
  459. static void SndioBackendFactory_probe(SndioBackendFactory* UNUSED(self), enum DevProbe type, al_string *outnames)
  460. {
  461. switch(type)
  462. {
  463. case ALL_DEVICE_PROBE:
  464. case CAPTURE_DEVICE_PROBE:
  465. alstr_append_range(outnames, sndio_device, sndio_device+sizeof(sndio_device));
  466. break;
  467. }
  468. }
  469. static ALCbackend* SndioBackendFactory_createBackend(SndioBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
  470. {
  471. if(type == ALCbackend_Playback)
  472. {
  473. SndioPlayback *backend;
  474. NEW_OBJ(backend, SndioPlayback)(device);
  475. if(!backend) return NULL;
  476. return STATIC_CAST(ALCbackend, backend);
  477. }
  478. if(type == ALCbackend_Capture)
  479. {
  480. SndioCapture *backend;
  481. NEW_OBJ(backend, SndioCapture)(device);
  482. if(!backend) return NULL;
  483. return STATIC_CAST(ALCbackend, backend);
  484. }
  485. return NULL;
  486. }