oss.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  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 <sys/ioctl.h>
  22. #include <sys/types.h>
  23. #include <sys/time.h>
  24. #include <sys/stat.h>
  25. #include <fcntl.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <memory.h>
  30. #include <unistd.h>
  31. #include <errno.h>
  32. #include <math.h>
  33. #include "alMain.h"
  34. #include "alu.h"
  35. #include "alconfig.h"
  36. #include "ringbuffer.h"
  37. #include "threads.h"
  38. #include "compat.h"
  39. #include "backends/base.h"
  40. #include <sys/soundcard.h>
  41. /*
  42. * The OSS documentation talks about SOUND_MIXER_READ, but the header
  43. * only contains MIXER_READ. Play safe. Same for WRITE.
  44. */
  45. #ifndef SOUND_MIXER_READ
  46. #define SOUND_MIXER_READ MIXER_READ
  47. #endif
  48. #ifndef SOUND_MIXER_WRITE
  49. #define SOUND_MIXER_WRITE MIXER_WRITE
  50. #endif
  51. #if defined(SOUND_VERSION) && (SOUND_VERSION < 0x040000)
  52. #define ALC_OSS_COMPAT
  53. #endif
  54. #ifndef SNDCTL_AUDIOINFO
  55. #define ALC_OSS_COMPAT
  56. #endif
  57. /*
  58. * FreeBSD strongly discourages the use of specific devices,
  59. * such as those returned in oss_audioinfo.devnode
  60. */
  61. #ifdef __FreeBSD__
  62. #define ALC_OSS_DEVNODE_TRUC
  63. #endif
  64. struct oss_device {
  65. const ALCchar *handle;
  66. const char *path;
  67. struct oss_device *next;
  68. };
  69. static struct oss_device oss_playback = {
  70. "OSS Default",
  71. "/dev/dsp",
  72. NULL
  73. };
  74. static struct oss_device oss_capture = {
  75. "OSS Default",
  76. "/dev/dsp",
  77. NULL
  78. };
  79. #ifdef ALC_OSS_COMPAT
  80. #define DSP_CAP_OUTPUT 0x00020000
  81. #define DSP_CAP_INPUT 0x00010000
  82. static void ALCossListPopulate(struct oss_device *UNUSED(devlist), int UNUSED(type_flag))
  83. {
  84. }
  85. #else
  86. #ifndef HAVE_STRNLEN
  87. static size_t strnlen(const char *str, size_t maxlen)
  88. {
  89. const char *end = memchr(str, 0, maxlen);
  90. if(!end) return maxlen;
  91. return end - str;
  92. }
  93. #endif
  94. static void ALCossListAppend(struct oss_device *list, const char *handle, size_t hlen, const char *path, size_t plen)
  95. {
  96. struct oss_device *next;
  97. struct oss_device *last;
  98. size_t i;
  99. /* skip the first item "OSS Default" */
  100. last = list;
  101. next = list->next;
  102. #ifdef ALC_OSS_DEVNODE_TRUC
  103. for(i = 0;i < plen;i++)
  104. {
  105. if(path[i] == '.')
  106. {
  107. if(strncmp(path + i, handle + hlen + i - plen, plen - i) == 0)
  108. hlen = hlen + i - plen;
  109. plen = i;
  110. }
  111. }
  112. #else
  113. (void)i;
  114. #endif
  115. if(handle[0] == '\0')
  116. {
  117. handle = path;
  118. hlen = plen;
  119. }
  120. while(next != NULL)
  121. {
  122. if(strncmp(next->path, path, plen) == 0)
  123. return;
  124. last = next;
  125. next = next->next;
  126. }
  127. next = (struct oss_device*)malloc(sizeof(struct oss_device) + hlen + plen + 2);
  128. next->handle = (char*)(next + 1);
  129. next->path = next->handle + hlen + 1;
  130. next->next = NULL;
  131. last->next = next;
  132. strncpy((char*)next->handle, handle, hlen);
  133. ((char*)next->handle)[hlen] = '\0';
  134. strncpy((char*)next->path, path, plen);
  135. ((char*)next->path)[plen] = '\0';
  136. TRACE("Got device \"%s\", \"%s\"\n", next->handle, next->path);
  137. }
  138. static void ALCossListPopulate(struct oss_device *devlist, int type_flag)
  139. {
  140. struct oss_sysinfo si;
  141. struct oss_audioinfo ai;
  142. int fd, i;
  143. if((fd=open("/dev/mixer", O_RDONLY)) < 0)
  144. {
  145. TRACE("Could not open /dev/mixer: %s\n", strerror(errno));
  146. return;
  147. }
  148. if(ioctl(fd, SNDCTL_SYSINFO, &si) == -1)
  149. {
  150. TRACE("SNDCTL_SYSINFO failed: %s\n", strerror(errno));
  151. goto done;
  152. }
  153. for(i = 0;i < si.numaudios;i++)
  154. {
  155. const char *handle;
  156. size_t len;
  157. ai.dev = i;
  158. if(ioctl(fd, SNDCTL_AUDIOINFO, &ai) == -1)
  159. {
  160. ERR("SNDCTL_AUDIOINFO (%d) failed: %s\n", i, strerror(errno));
  161. continue;
  162. }
  163. if(ai.devnode[0] == '\0')
  164. continue;
  165. if(ai.handle[0] != '\0')
  166. {
  167. len = strnlen(ai.handle, sizeof(ai.handle));
  168. handle = ai.handle;
  169. }
  170. else
  171. {
  172. len = strnlen(ai.name, sizeof(ai.name));
  173. handle = ai.name;
  174. }
  175. if((ai.caps&type_flag))
  176. ALCossListAppend(devlist, handle, len, ai.devnode,
  177. strnlen(ai.devnode, sizeof(ai.devnode)));
  178. }
  179. done:
  180. close(fd);
  181. }
  182. #endif
  183. static void ALCossListFree(struct oss_device *list)
  184. {
  185. struct oss_device *cur;
  186. if(list == NULL)
  187. return;
  188. /* skip the first item "OSS Default" */
  189. cur = list->next;
  190. list->next = NULL;
  191. while(cur != NULL)
  192. {
  193. struct oss_device *next = cur->next;
  194. free(cur);
  195. cur = next;
  196. }
  197. }
  198. static int log2i(ALCuint x)
  199. {
  200. int y = 0;
  201. while (x > 1)
  202. {
  203. x >>= 1;
  204. y++;
  205. }
  206. return y;
  207. }
  208. typedef struct ALCplaybackOSS {
  209. DERIVE_FROM_TYPE(ALCbackend);
  210. int fd;
  211. ALubyte *mix_data;
  212. int data_size;
  213. ATOMIC(ALenum) killNow;
  214. althrd_t thread;
  215. } ALCplaybackOSS;
  216. static int ALCplaybackOSS_mixerProc(void *ptr);
  217. static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device);
  218. static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self);
  219. static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name);
  220. static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self);
  221. static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self);
  222. static void ALCplaybackOSS_stop(ALCplaybackOSS *self);
  223. static DECLARE_FORWARD2(ALCplaybackOSS, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
  224. static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALCuint, availableSamples)
  225. static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ClockLatency, getClockLatency)
  226. static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, lock)
  227. static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, unlock)
  228. DECLARE_DEFAULT_ALLOCATORS(ALCplaybackOSS)
  229. DEFINE_ALCBACKEND_VTABLE(ALCplaybackOSS);
  230. static int ALCplaybackOSS_mixerProc(void *ptr)
  231. {
  232. ALCplaybackOSS *self = (ALCplaybackOSS*)ptr;
  233. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  234. struct timeval timeout;
  235. ALubyte *write_ptr;
  236. ALint frame_size;
  237. ALint to_write;
  238. ssize_t wrote;
  239. fd_set wfds;
  240. int sret;
  241. SetRTPriority();
  242. althrd_setname(althrd_current(), MIXER_THREAD_NAME);
  243. frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  244. ALCplaybackOSS_lock(self);
  245. while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
  246. ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
  247. {
  248. FD_ZERO(&wfds);
  249. FD_SET(self->fd, &wfds);
  250. timeout.tv_sec = 1;
  251. timeout.tv_usec = 0;
  252. ALCplaybackOSS_unlock(self);
  253. sret = select(self->fd+1, NULL, &wfds, NULL, &timeout);
  254. ALCplaybackOSS_lock(self);
  255. if(sret < 0)
  256. {
  257. if(errno == EINTR)
  258. continue;
  259. ERR("select failed: %s\n", strerror(errno));
  260. aluHandleDisconnect(device, "Failed waiting for playback buffer: %s", strerror(errno));
  261. break;
  262. }
  263. else if(sret == 0)
  264. {
  265. WARN("select timeout\n");
  266. continue;
  267. }
  268. write_ptr = self->mix_data;
  269. to_write = self->data_size;
  270. aluMixData(device, write_ptr, to_write/frame_size);
  271. while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow))
  272. {
  273. wrote = write(self->fd, write_ptr, to_write);
  274. if(wrote < 0)
  275. {
  276. if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
  277. continue;
  278. ERR("write failed: %s\n", strerror(errno));
  279. aluHandleDisconnect(device, "Failed writing playback samples: %s",
  280. strerror(errno));
  281. break;
  282. }
  283. to_write -= wrote;
  284. write_ptr += wrote;
  285. }
  286. }
  287. ALCplaybackOSS_unlock(self);
  288. return 0;
  289. }
  290. static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device)
  291. {
  292. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  293. SET_VTABLE2(ALCplaybackOSS, ALCbackend, self);
  294. self->fd = -1;
  295. ATOMIC_INIT(&self->killNow, AL_FALSE);
  296. }
  297. static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self)
  298. {
  299. if(self->fd != -1)
  300. close(self->fd);
  301. self->fd = -1;
  302. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  303. }
  304. static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name)
  305. {
  306. struct oss_device *dev = &oss_playback;
  307. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  308. if(!name || strcmp(name, dev->handle) == 0)
  309. name = dev->handle;
  310. else
  311. {
  312. if(!dev->next)
  313. {
  314. ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT);
  315. dev = &oss_playback;
  316. }
  317. while(dev != NULL)
  318. {
  319. if (strcmp(dev->handle, name) == 0)
  320. break;
  321. dev = dev->next;
  322. }
  323. if(dev == NULL)
  324. {
  325. WARN("Could not find \"%s\" in device list\n", name);
  326. return ALC_INVALID_VALUE;
  327. }
  328. }
  329. self->fd = open(dev->path, O_WRONLY);
  330. if(self->fd == -1)
  331. {
  332. ERR("Could not open %s: %s\n", dev->path, strerror(errno));
  333. return ALC_INVALID_VALUE;
  334. }
  335. alstr_copy_cstr(&device->DeviceName, name);
  336. return ALC_NO_ERROR;
  337. }
  338. static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self)
  339. {
  340. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  341. int numFragmentsLogSize;
  342. int log2FragmentSize;
  343. unsigned int periods;
  344. audio_buf_info info;
  345. ALuint frameSize;
  346. int numChannels;
  347. int ossFormat;
  348. int ossSpeed;
  349. char *err;
  350. switch(device->FmtType)
  351. {
  352. case DevFmtByte:
  353. ossFormat = AFMT_S8;
  354. break;
  355. case DevFmtUByte:
  356. ossFormat = AFMT_U8;
  357. break;
  358. case DevFmtUShort:
  359. case DevFmtInt:
  360. case DevFmtUInt:
  361. case DevFmtFloat:
  362. device->FmtType = DevFmtShort;
  363. /* fall-through */
  364. case DevFmtShort:
  365. ossFormat = AFMT_S16_NE;
  366. break;
  367. }
  368. periods = device->NumUpdates;
  369. numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  370. ossSpeed = device->Frequency;
  371. frameSize = numChannels * BytesFromDevFmt(device->FmtType);
  372. /* According to the OSS spec, 16 bytes (log2(16)) is the minimum. */
  373. log2FragmentSize = maxi(log2i(device->UpdateSize*frameSize), 4);
  374. numFragmentsLogSize = (periods << 16) | log2FragmentSize;
  375. #define CHECKERR(func) if((func) < 0) { \
  376. err = #func; \
  377. goto err; \
  378. }
  379. /* Don't fail if SETFRAGMENT fails. We can handle just about anything
  380. * that's reported back via GETOSPACE */
  381. ioctl(self->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize);
  382. CHECKERR(ioctl(self->fd, SNDCTL_DSP_SETFMT, &ossFormat));
  383. CHECKERR(ioctl(self->fd, SNDCTL_DSP_CHANNELS, &numChannels));
  384. CHECKERR(ioctl(self->fd, SNDCTL_DSP_SPEED, &ossSpeed));
  385. CHECKERR(ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &info));
  386. if(0)
  387. {
  388. err:
  389. ERR("%s failed: %s\n", err, strerror(errno));
  390. return ALC_FALSE;
  391. }
  392. #undef CHECKERR
  393. if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels)
  394. {
  395. ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
  396. return ALC_FALSE;
  397. }
  398. if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) ||
  399. (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) ||
  400. (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort)))
  401. {
  402. ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat);
  403. return ALC_FALSE;
  404. }
  405. device->Frequency = ossSpeed;
  406. device->UpdateSize = info.fragsize / frameSize;
  407. device->NumUpdates = info.fragments;
  408. SetDefaultChannelOrder(device);
  409. return ALC_TRUE;
  410. }
  411. static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self)
  412. {
  413. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  414. self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
  415. device->FmtChans, device->FmtType, device->AmbiOrder
  416. );
  417. self->mix_data = calloc(1, self->data_size);
  418. ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
  419. if(althrd_create(&self->thread, ALCplaybackOSS_mixerProc, self) != althrd_success)
  420. {
  421. free(self->mix_data);
  422. self->mix_data = NULL;
  423. return ALC_FALSE;
  424. }
  425. return ALC_TRUE;
  426. }
  427. static void ALCplaybackOSS_stop(ALCplaybackOSS *self)
  428. {
  429. int res;
  430. if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE))
  431. return;
  432. althrd_join(self->thread, &res);
  433. if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0)
  434. ERR("Error resetting device: %s\n", strerror(errno));
  435. free(self->mix_data);
  436. self->mix_data = NULL;
  437. }
  438. typedef struct ALCcaptureOSS {
  439. DERIVE_FROM_TYPE(ALCbackend);
  440. int fd;
  441. ll_ringbuffer_t *ring;
  442. ATOMIC(ALenum) killNow;
  443. althrd_t thread;
  444. } ALCcaptureOSS;
  445. static int ALCcaptureOSS_recordProc(void *ptr);
  446. static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device);
  447. static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self);
  448. static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name);
  449. static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALCboolean, reset)
  450. static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self);
  451. static void ALCcaptureOSS_stop(ALCcaptureOSS *self);
  452. static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples);
  453. static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self);
  454. static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ClockLatency, getClockLatency)
  455. static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, lock)
  456. static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, unlock)
  457. DECLARE_DEFAULT_ALLOCATORS(ALCcaptureOSS)
  458. DEFINE_ALCBACKEND_VTABLE(ALCcaptureOSS);
  459. static int ALCcaptureOSS_recordProc(void *ptr)
  460. {
  461. ALCcaptureOSS *self = (ALCcaptureOSS*)ptr;
  462. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  463. struct timeval timeout;
  464. int frame_size;
  465. fd_set rfds;
  466. ssize_t amt;
  467. int sret;
  468. SetRTPriority();
  469. althrd_setname(althrd_current(), RECORD_THREAD_NAME);
  470. frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
  471. while(!ATOMIC_LOAD_SEQ(&self->killNow))
  472. {
  473. ll_ringbuffer_data_t vec[2];
  474. FD_ZERO(&rfds);
  475. FD_SET(self->fd, &rfds);
  476. timeout.tv_sec = 1;
  477. timeout.tv_usec = 0;
  478. sret = select(self->fd+1, &rfds, NULL, NULL, &timeout);
  479. if(sret < 0)
  480. {
  481. if(errno == EINTR)
  482. continue;
  483. ERR("select failed: %s\n", strerror(errno));
  484. aluHandleDisconnect(device, "Failed to check capture samples: %s", strerror(errno));
  485. break;
  486. }
  487. else if(sret == 0)
  488. {
  489. WARN("select timeout\n");
  490. continue;
  491. }
  492. ll_ringbuffer_get_write_vector(self->ring, vec);
  493. if(vec[0].len > 0)
  494. {
  495. amt = read(self->fd, vec[0].buf, vec[0].len*frame_size);
  496. if(amt < 0)
  497. {
  498. ERR("read failed: %s\n", strerror(errno));
  499. ALCcaptureOSS_lock(self);
  500. aluHandleDisconnect(device, "Failed reading capture samples: %s", strerror(errno));
  501. ALCcaptureOSS_unlock(self);
  502. break;
  503. }
  504. ll_ringbuffer_write_advance(self->ring, amt/frame_size);
  505. }
  506. }
  507. return 0;
  508. }
  509. static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device)
  510. {
  511. ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
  512. SET_VTABLE2(ALCcaptureOSS, ALCbackend, self);
  513. self->fd = -1;
  514. self->ring = NULL;
  515. ATOMIC_INIT(&self->killNow, AL_FALSE);
  516. }
  517. static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self)
  518. {
  519. if(self->fd != -1)
  520. close(self->fd);
  521. self->fd = -1;
  522. ll_ringbuffer_free(self->ring);
  523. self->ring = NULL;
  524. ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
  525. }
  526. static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
  527. {
  528. ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
  529. struct oss_device *dev = &oss_capture;
  530. int numFragmentsLogSize;
  531. int log2FragmentSize;
  532. unsigned int periods;
  533. audio_buf_info info;
  534. ALuint frameSize;
  535. int numChannels;
  536. int ossFormat;
  537. int ossSpeed;
  538. char *err;
  539. if(!name || strcmp(name, dev->handle) == 0)
  540. name = dev->handle;
  541. else
  542. {
  543. if(!dev->next)
  544. {
  545. ALCossListPopulate(&oss_capture, DSP_CAP_INPUT);
  546. dev = &oss_capture;
  547. }
  548. while(dev != NULL)
  549. {
  550. if (strcmp(dev->handle, name) == 0)
  551. break;
  552. dev = dev->next;
  553. }
  554. if(dev == NULL)
  555. {
  556. WARN("Could not find \"%s\" in device list\n", name);
  557. return ALC_INVALID_VALUE;
  558. }
  559. }
  560. self->fd = open(dev->path, O_RDONLY);
  561. if(self->fd == -1)
  562. {
  563. ERR("Could not open %s: %s\n", dev->path, strerror(errno));
  564. return ALC_INVALID_VALUE;
  565. }
  566. switch(device->FmtType)
  567. {
  568. case DevFmtByte:
  569. ossFormat = AFMT_S8;
  570. break;
  571. case DevFmtUByte:
  572. ossFormat = AFMT_U8;
  573. break;
  574. case DevFmtShort:
  575. ossFormat = AFMT_S16_NE;
  576. break;
  577. case DevFmtUShort:
  578. case DevFmtInt:
  579. case DevFmtUInt:
  580. case DevFmtFloat:
  581. ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType));
  582. return ALC_INVALID_VALUE;
  583. }
  584. periods = 4;
  585. numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
  586. frameSize = numChannels * BytesFromDevFmt(device->FmtType);
  587. ossSpeed = device->Frequency;
  588. log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates *
  589. frameSize / periods);
  590. /* according to the OSS spec, 16 bytes are the minimum */
  591. if (log2FragmentSize < 4)
  592. log2FragmentSize = 4;
  593. numFragmentsLogSize = (periods << 16) | log2FragmentSize;
  594. #define CHECKERR(func) if((func) < 0) { \
  595. err = #func; \
  596. goto err; \
  597. }
  598. CHECKERR(ioctl(self->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize));
  599. CHECKERR(ioctl(self->fd, SNDCTL_DSP_SETFMT, &ossFormat));
  600. CHECKERR(ioctl(self->fd, SNDCTL_DSP_CHANNELS, &numChannels));
  601. CHECKERR(ioctl(self->fd, SNDCTL_DSP_SPEED, &ossSpeed));
  602. CHECKERR(ioctl(self->fd, SNDCTL_DSP_GETISPACE, &info));
  603. if(0)
  604. {
  605. err:
  606. ERR("%s failed: %s\n", err, strerror(errno));
  607. close(self->fd);
  608. self->fd = -1;
  609. return ALC_INVALID_VALUE;
  610. }
  611. #undef CHECKERR
  612. if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels)
  613. {
  614. ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
  615. close(self->fd);
  616. self->fd = -1;
  617. return ALC_INVALID_VALUE;
  618. }
  619. if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) ||
  620. (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) ||
  621. (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort)))
  622. {
  623. ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat);
  624. close(self->fd);
  625. self->fd = -1;
  626. return ALC_INVALID_VALUE;
  627. }
  628. self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, frameSize, false);
  629. if(!self->ring)
  630. {
  631. ERR("Ring buffer create failed\n");
  632. close(self->fd);
  633. self->fd = -1;
  634. return ALC_OUT_OF_MEMORY;
  635. }
  636. alstr_copy_cstr(&device->DeviceName, name);
  637. return ALC_NO_ERROR;
  638. }
  639. static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self)
  640. {
  641. ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
  642. if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success)
  643. return ALC_FALSE;
  644. return ALC_TRUE;
  645. }
  646. static void ALCcaptureOSS_stop(ALCcaptureOSS *self)
  647. {
  648. int res;
  649. if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE))
  650. return;
  651. althrd_join(self->thread, &res);
  652. if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0)
  653. ERR("Error resetting device: %s\n", strerror(errno));
  654. }
  655. static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples)
  656. {
  657. ll_ringbuffer_read(self->ring, buffer, samples);
  658. return ALC_NO_ERROR;
  659. }
  660. static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self)
  661. {
  662. return ll_ringbuffer_read_space(self->ring);
  663. }
  664. typedef struct ALCossBackendFactory {
  665. DERIVE_FROM_TYPE(ALCbackendFactory);
  666. } ALCossBackendFactory;
  667. #define ALCOSSBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCossBackendFactory, ALCbackendFactory) } }
  668. ALCbackendFactory *ALCossBackendFactory_getFactory(void);
  669. static ALCboolean ALCossBackendFactory_init(ALCossBackendFactory *self);
  670. static void ALCossBackendFactory_deinit(ALCossBackendFactory *self);
  671. static ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory *self, ALCbackend_Type type);
  672. static void ALCossBackendFactory_probe(ALCossBackendFactory *self, enum DevProbe type);
  673. static ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
  674. DEFINE_ALCBACKENDFACTORY_VTABLE(ALCossBackendFactory);
  675. ALCbackendFactory *ALCossBackendFactory_getFactory(void)
  676. {
  677. static ALCossBackendFactory factory = ALCOSSBACKENDFACTORY_INITIALIZER;
  678. return STATIC_CAST(ALCbackendFactory, &factory);
  679. }
  680. ALCboolean ALCossBackendFactory_init(ALCossBackendFactory* UNUSED(self))
  681. {
  682. ConfigValueStr(NULL, "oss", "device", &oss_playback.path);
  683. ConfigValueStr(NULL, "oss", "capture", &oss_capture.path);
  684. return ALC_TRUE;
  685. }
  686. void ALCossBackendFactory_deinit(ALCossBackendFactory* UNUSED(self))
  687. {
  688. ALCossListFree(&oss_playback);
  689. ALCossListFree(&oss_capture);
  690. }
  691. ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory* UNUSED(self), ALCbackend_Type type)
  692. {
  693. if(type == ALCbackend_Playback || type == ALCbackend_Capture)
  694. return ALC_TRUE;
  695. return ALC_FALSE;
  696. }
  697. void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProbe type)
  698. {
  699. struct oss_device *cur;
  700. switch(type)
  701. {
  702. case ALL_DEVICE_PROBE:
  703. ALCossListFree(&oss_playback);
  704. ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT);
  705. cur = &oss_playback;
  706. while(cur != NULL)
  707. {
  708. #ifdef HAVE_STAT
  709. struct stat buf;
  710. if(stat(cur->path, &buf) == 0)
  711. #endif
  712. AppendAllDevicesList(cur->handle);
  713. cur = cur->next;
  714. }
  715. break;
  716. case CAPTURE_DEVICE_PROBE:
  717. ALCossListFree(&oss_capture);
  718. ALCossListPopulate(&oss_capture, DSP_CAP_INPUT);
  719. cur = &oss_capture;
  720. while(cur != NULL)
  721. {
  722. #ifdef HAVE_STAT
  723. struct stat buf;
  724. if(stat(cur->path, &buf) == 0)
  725. #endif
  726. AppendCaptureDeviceList(cur->handle);
  727. cur = cur->next;
  728. }
  729. break;
  730. }
  731. }
  732. ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
  733. {
  734. if(type == ALCbackend_Playback)
  735. {
  736. ALCplaybackOSS *backend;
  737. NEW_OBJ(backend, ALCplaybackOSS)(device);
  738. if(!backend) return NULL;
  739. return STATIC_CAST(ALCbackend, backend);
  740. }
  741. if(type == ALCbackend_Capture)
  742. {
  743. ALCcaptureOSS *backend;
  744. NEW_OBJ(backend, ALCcaptureOSS)(device);
  745. if(!backend) return NULL;
  746. return STATIC_CAST(ALCbackend, backend);
  747. }
  748. return NULL;
  749. }