oss.c 24 KB

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